升级插件 修复安装判断

This commit is contained in:
toogee 2020-05-20 11:33:27 +08:00
parent 6ee23c779e
commit 5a6363d3ec
74 changed files with 621 additions and 744 deletions

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
/.idea
/.vscode
/vendor
*.log
.env

View File

@ -1,68 +1,52 @@
# TaoLer
ThinkPHP 6.0
===============
版本TaoLer 1.2.3
日期2020.5.1
官网http://www.aieok.com
测试http://adm.aieok.com 账号test 密码test123
> 运行环境要求PHP7.1+。
#### 项目地址
## 主要新特性
1. gitee https://www.gitee.com/toogee/Taoler
2. github https://www.github.com/taoser/TaoLer
* 采用`PHP7`强类型(严格模式)
* 支持更多的`PSR`规范
* 原生多应用支持
* 更强大和易用的查询
* 全新的事件系统
* 模型事件和数据库事件统一纳入事件系统
* 模板引擎分离出核心
* 内部功能中间件化
* SESSION/Cookie机制改进
* 对Swoole以及协程支持改进
* 对IDE更加友好
* 统一和精简大量用法
#### 介绍
## 安装
1. 采用动态密码加密,相同密码在入库时具有唯一性,即使管理员也无法破解,用户信息安全牢固。
2. 系统采用最新版TinkPHP6框架开发底层安全可靠数据查询更快运行效率更高网站速度更快。
3. 自适应前端,桌面和移动端访问界面友好简洁,模块清晰。
4. 完善的后台系统管理便捷动态菜单和权限角色分配系统。支持3级菜单和无限极分类。
5. 双升级系统,可支持自动和手动升级。可在线检测并升级系统,保持网站的更新和安全。
6. 代码开源,不设暗门操作,更安全。
7. 项目会长期维护,优化更新。
~~~
composer create-project topthink/think tp 6.0.*
~~~
如果需要更新框架使用
~~~
composer update topthink/framework
~~~
#### 软件架构
## 文档
thinkphp6+layui+fly
ThinkPHP6核心框架
快速、简单的面向对象的轻量级PHP开发框架出色的性能和至简代码的更注重易用性。代码维护方便。
layui前端
极简、丰盈简单高效模块化UI框架体积轻盈组件丰盈。
Fly模板:
一款至简的社区模板,适合政府机构、教育机构、事业单位、商业企业、个人站长等众多行业领域。
[完全开发手册](https://www.kancloud.cn/manual/thinkphp6_0/content)
#### 安装教程
## 参与开发
1. git下载https://gitee.com/toogee/TaoLer
2. 官网下载https://www.aieok.com
3. 解压后项目绑定域名为public目录对外访问首次安装访问域名http://www.youdomain.com可自动跳转到/install/index进行引导安装重新安装需删除根目录下install.lock。
4. 安装前需要先创建mysql数据库(准备:数据库连接地址,数据库用户名,数据库密码,数据库端口,建好在数据库名)
5. 请牢记安装设置的管理员用户名和密码默认admin/123456。前后台的管理员密码一致。前后端管理员账户是独立的前端主要对文章内容的审查管理等操作。
请参阅 [ThinkPHP 核心框架包](https://github.com/top-think/framework)。
#### 使用说明
## 版权信息
1. 安装后本系统已配置默认演示数据,可以删除原数据或者进行数据的修改
2. 后台可设置分类cate,一定要设置英文别名
3. 首页有置顶模块,列表文章模块,右侧包含广告模块,回复展示模块
#### 文档
参考官网分享文章
#### 参与贡献
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
#### 版权信息
非商业可免费使用,没有功能限制,但不能更改版本信息,如需更改可购买授权。
ThinkPHP遵循Apache2开源协议发布并提供免费使用。
本项目包含的第三方源码和二进制文件之版权信息另行标注。
版权所有Copyright © 2020 by aieok.com (https://www.aieok.com)
版权所有Copyright © 2006-2020 by ThinkPHP (http://thinkphp.cn)
All rights reserved。
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
更多细节参阅 [LICENSE.txt](LICENSE.txt)

View File

@ -1,274 +0,0 @@
# think-addons
The ThinkPHP 6 Addons Package
## 安装
> composer require zzstudio/think-addons
## 配置
### 生成配置
系统安装后会自动在 config 目录中生成 addons.php 的配置文件,
如果系统未生成可在命令行执行
```php
php think addons:config
```
快速生成配置文件
### 公共配置
```php
'addons' => [
// 是否自动读取取插件钩子配置信息(默认是开启)
'autoload' => true,
// 当关闭自动获取配置时需要手动配置hooks信息
'hooks' => [
// 可以定义多个钩子
'testhook'=>'test' // 键为钩子名称,用于在业务中自定义钩子处理,值为实现该钩子的插件,
// 多个插件可以用数组也可以用逗号分割
],
'route' => [],
'service' => [],
];
```
或者在\config目录中新建`addons.php`,内容为:
```php
<?php
return [
// 是否自动读取取插件钩子配置信息
'autoload' => false,
// 当关闭自动获取配置时需要手动配置hooks信息
'hooks' => [
// 可以定义多个钩子
'testhook'=>'test' // 键为钩子名称,用于在业务中自定义钩子处理,值为实现该钩子的插件,
// 多个插件可以用数组也可以用逗号分割
],
'route' => [],
'service' => [],
];
```
## 创建插件
> 创建的插件可以在view视图中使用也可以在php业务中使用
安装完成后访问系统时会在项目根目录生成名为`addons`的目录,在该目录中创建需要的插件。
下面写一个例子:
### 创建test插件
> 在addons目录中创建test目录
### 创建钩子实现类
> 在test目录中创建 Plugin.php 类文件。注意:类文件首字母需大写
```php
<?php
namespace addons\test; // 注意命名空间规范
use think\Addons;
/**
* 插件测试
* @author byron sampson
*/
class Plugin extends Addons // 需继承think\Addons类
{
// 该插件的基础信息
public $info = [
'name' => 'test', // 插件标识
'title' => '插件测试', // 插件名称
'description' => 'thinkph6插件测试', // 插件简介
'status' => 0, // 状态
'author' => 'byron sampson',
'version' => '0.1'
];
/**
* 插件安装方法
* @return bool
*/
public function install()
{
return true;
}
/**
* 插件卸载方法
* @return bool
*/
public function uninstall()
{
return true;
}
/**
* 实现的testhook钩子方法
* @return mixed
*/
public function testhook($param)
{
// 调用钩子时候的参数信息
print_r($param);
// 当前插件的配置信息配置信息存在当前目录的config.php文件中见下方
print_r($this->getConfig());
// 可以返回模板,模板文件默认读取的为插件目录中的文件。模板名不能为空!
return $this->fetch('info');
}
}
```
### 创建插件配置文件
> 在test目录中创建config.php类文件插件配置文件可以省略。
```php
<?php
return [
'display' => [
'title' => '是否显示:',
'type' => 'radio',
'options' => [
'1' => '显示',
'0' => '不显示'
],
'value' => '1'
]
];
```
### 创建钩子模板文件
> 在test->view目录中创建info.html模板文件钩子在使用fetch方法时对应的模板文件。
```html
<h1>hello tpl</h1>
如果插件中需要有链接或提交数据的业务可以在插件中创建controller业务文件
要访问插件中的controller时使用addon_url生成url链接。
如下:
<a href="{:addons_url('Action/link')}">link test</a>
<a href="{:addons_url('test://Action/link')}">link test</a>
格式为:
test为插件名Action为controller中的类名[多级控制器可以用.分割]link为controller中的方法
```
### 创建插件的controller文件
> 在test目录中创建controller目录在controller目录中创建Index.php文件
> controller类的用法与tp6中的controller一致
```php
<?php
namespace addons\test\controller;
class Index
{
public function link()
{
echo 'hello link';
}
}
```
## 使用钩子
> 创建好插件后就可以在正常业务中使用该插件中的钩子了
> 使用钩子的时候第二个参数可以省略
### 模板中使用钩子
```html
<div>{:hook('testhook', ['id'=>1])}</div>
```
### php业务中使用
> 只要是thinkphp6正常流程中的任意位置均可以使用
```php
hook('testhook', ['id'=>1])
```
### 插件公共方法
```php
/**
* 处理插件钩子
* @param string $event 钩子名称
* @param array|null $params 传入参数
* @param bool $once 是否只返回一个结果
* @return mixed
*/
function hook($event, $params = null, bool $once = false);
/**
* 读取插件的基础信息
* @param string $name 插件名
* @return array
*/
function get_addons_info($name);
/**
* 获取插件Plugin的单例
* @param string $name 插件名
* @return mixed|null
*/
function get_addons_instance($name);
/**
* 插件显示内容里生成访问插件的url
* @param $url 在插件控制器中可忽略插件名,在非插件中生成时需指定插件名。例:插件名://控制器/方法
* @param array $param
* @param bool|string $suffix 生成的URL后缀
* @param bool|string $domain 域名
* @return bool|string
*/
function addons_url($url = '', $param = [], $suffix = true, $domain = false);
```
## 插件目录结构
### 最终生成的目录结构为
```html
www WEB部署目录或者子目录
├─addons 插件目录
├─app 应用目录
│ ├─controller 控制器目录
│ ├─model 模型目录
│ ├─ ... 更多类库目录
│ │
│ ├─common.php 公共函数文件
│ └─event.php 事件定义文件
├─config 配置目录
│ ├─app.php 应用配置
│ ├─cache.php 缓存配置
│ ├─console.php 控制台配置
│ ├─cookie.php Cookie配置
│ ├─database.php 数据库配置
│ ├─filesystem.php 文件磁盘配置
│ ├─lang.php 多语言配置
│ ├─log.php 日志配置
│ ├─middleware.php 中间件配置
│ ├─route.php URL和路由配置
│ ├─session.php Session配置
│ ├─trace.php Trace配置
│ └─view.php 视图配置
├─view 视图目录
├─route 路由定义目录
│ ├─route.php 路由定义文件
│ └─ ...
├─public WEB目录对外访问目录
│ ├─index.php 入口文件
│ ├─router.php 快速测试文件
│ └─.htaccess 用于apache的重写
├─extend 扩展类库目录
├─runtime 应用的运行时目录(可写,可定制)
├─vendor Composer类库目录
├─.example.env 环境变量示例文件
├─composer.json composer 定义文件
├─LICENSE.txt 授权说明文件
├─README.md README 文件
├─think 命令行入口文件
```

View File

@ -1,2 +1,3 @@
KeyAuth.php
Version.php
TimeLine.php

View File

@ -143,6 +143,8 @@ class Index extends BaseController
$db_str = <<<php
<?php
return [
// 默认使用的数据库连接配置
'default' => 'mysql',
// 自定义时间查询规则
'time_query_rule' => [],
// 自动写入时间戳字段

View File

@ -23,11 +23,11 @@
"php": ">=7.1.0",
"topthink/framework": "^6.0.0",
"topthink/think-orm": "^2.0",
"phpmailer/phpmailer": "^6.1",
"taoser/think-auth": "^1.0",
"topthink/think-multi-app": "^1.0",
"topthink/think-captcha": "^3.0",
"taoser/think-auth": "^1.0",
"topthink/think-view": "^1.0",
"topthink/think-captcha": "^3.0",
"phpmailer/phpmailer": "^6.1",
"zzstudio/think-addons": "^2.0"
},
"require-dev": {

116
composer.lock generated
View File

@ -4,20 +4,20 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "6228bf65a800388ad9f6b06b8ac6ba72",
"content-hash": "670826f4ed6fc63b8b224456dd1826d9",
"packages": [
{
"name": "league/flysystem",
"version": "1.0.64",
"version": "1.0.69",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem.git",
"reference": "d13c43dbd4b791f815215959105a008515d1a2e0"
"reference": "7106f78428a344bc4f643c233a94e48795f10967"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/d13c43dbd4b791f815215959105a008515d1a2e0",
"reference": "d13c43dbd4b791f815215959105a008515d1a2e0",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/7106f78428a344bc4f643c233a94e48795f10967",
"reference": "7106f78428a344bc4f643c233a94e48795f10967",
"shasum": "",
"mirrors": [
{
@ -94,7 +94,7 @@
"sftp",
"storage"
],
"time": "2020-02-05T18:14:17+00:00"
"time": "2020-05-18T15:13:39+00:00"
},
{
"name": "league/flysystem-cached-adapter",
@ -218,16 +218,16 @@
},
{
"name": "phpmailer/phpmailer",
"version": "v6.1.4",
"version": "v6.1.5",
"source": {
"type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git",
"reference": "c5e61d0729507049cec9673aa1a679f9adefd683"
"reference": "a8bf068f64a580302026e484ee29511f661b2ad3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/c5e61d0729507049cec9673aa1a679f9adefd683",
"reference": "c5e61d0729507049cec9673aa1a679f9adefd683",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/a8bf068f64a580302026e484ee29511f661b2ad3",
"reference": "a8bf068f64a580302026e484ee29511f661b2ad3",
"shasum": "",
"mirrors": [
{
@ -282,7 +282,7 @@
}
],
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
"time": "2019-12-10T11:17:38+00:00"
"time": "2020-03-14T14:23:48+00:00"
},
{
"name": "psr/cache",
@ -393,16 +393,16 @@
},
{
"name": "psr/log",
"version": "1.1.2",
"version": "1.1.3",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801"
"reference": "0f73288fd15629204f9d42b7055f72dacbe811fc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801",
"reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801",
"url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc",
"reference": "0f73288fd15629204f9d42b7055f72dacbe811fc",
"shasum": "",
"mirrors": [
{
@ -442,7 +442,7 @@
"psr",
"psr-3"
],
"time": "2019-11-01T11:05:21+00:00"
"time": "2020-03-23T09:12:05+00:00"
},
{
"name": "psr/simple-cache",
@ -623,16 +623,16 @@
},
{
"name": "topthink/think-captcha",
"version": "v3.0.2",
"version": "v3.0.3",
"source": {
"type": "git",
"url": "https://github.com/top-think/think-captcha.git",
"reference": "0b4305da19e118cefd934007875a8112f9352f01"
"reference": "1eef3717c1bcf4f5bbe2d1a1c704011d330a8b55"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/think-captcha/zipball/0b4305da19e118cefd934007875a8112f9352f01",
"reference": "0b4305da19e118cefd934007875a8112f9352f01",
"url": "https://api.github.com/repos/top-think/think-captcha/zipball/1eef3717c1bcf4f5bbe2d1a1c704011d330a8b55",
"reference": "1eef3717c1bcf4f5bbe2d1a1c704011d330a8b55",
"shasum": "",
"mirrors": [
{
@ -674,20 +674,20 @@
}
],
"description": "captcha package for thinkphp",
"time": "2019-10-03T07:45:11+00:00"
"time": "2020-05-19T10:55:45+00:00"
},
{
"name": "topthink/think-helper",
"version": "v3.1.3",
"version": "v3.1.4",
"source": {
"type": "git",
"url": "https://github.com/top-think/think-helper.git",
"reference": "4d85dfd3778623bbb1de3648f1dcd0c82f4439f4"
"reference": "c28d37743bda4a0455286ca85b17b5791d626e10"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/think-helper/zipball/4d85dfd3778623bbb1de3648f1dcd0c82f4439f4",
"reference": "4d85dfd3778623bbb1de3648f1dcd0c82f4439f4",
"url": "https://api.github.com/repos/top-think/think-helper/zipball/c28d37743bda4a0455286ca85b17b5791d626e10",
"reference": "c28d37743bda4a0455286ca85b17b5791d626e10",
"shasum": "",
"mirrors": [
{
@ -719,20 +719,20 @@
}
],
"description": "The ThinkPHP6 Helper Package",
"time": "2019-09-30T02:36:48+00:00"
"time": "2019-11-08T08:01:10+00:00"
},
{
"name": "topthink/think-multi-app",
"version": "v1.0.11",
"version": "v1.0.12",
"source": {
"type": "git",
"url": "https://github.com/top-think/think-multi-app.git",
"reference": "215f4a6bb88e53ad41b448c61957336eb55ce6f9"
"reference": "3c1914d2adc08c8753c7f67228885ca47fb9b3bf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/think-multi-app/zipball/215f4a6bb88e53ad41b448c61957336eb55ce6f9",
"reference": "215f4a6bb88e53ad41b448c61957336eb55ce6f9",
"url": "https://api.github.com/repos/top-think/think-multi-app/zipball/3c1914d2adc08c8753c7f67228885ca47fb9b3bf",
"reference": "3c1914d2adc08c8753c7f67228885ca47fb9b3bf",
"shasum": "",
"mirrors": [
{
@ -769,20 +769,20 @@
}
],
"description": "thinkphp6 multi app support",
"time": "2019-10-29T06:34:59+00:00"
"time": "2020-03-01T13:29:35+00:00"
},
{
"name": "topthink/think-orm",
"version": "v2.0.31",
"version": "v2.0.32",
"source": {
"type": "git",
"url": "https://github.com/top-think/think-orm.git",
"reference": "d6965dfae21f150e29cc899ab6f9b1bd2c0f2ee4"
"reference": "03aaaa4d8c4475115b3acaa5aa2498bf5792e017"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/think-orm/zipball/d6965dfae21f150e29cc899ab6f9b1bd2c0f2ee4",
"reference": "d6965dfae21f150e29cc899ab6f9b1bd2c0f2ee4",
"url": "https://api.github.com/repos/top-think/think-orm/zipball/03aaaa4d8c4475115b3acaa5aa2498bf5792e017",
"reference": "03aaaa4d8c4475115b3acaa5aa2498bf5792e017",
"shasum": "",
"mirrors": [
{
@ -820,7 +820,7 @@
"database",
"orm"
],
"time": "2020-01-07T10:05:10+00:00"
"time": "2020-04-26T13:54:48+00:00"
},
{
"name": "topthink/think-template",
@ -970,16 +970,16 @@
"packages-dev": [
{
"name": "symfony/polyfill-mbstring",
"version": "v1.13.1",
"version": "v1.17.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "7b4aab9743c30be783b73de055d24a39cf4b954f"
"reference": "fa79b11539418b02fc5e1897267673ba2c19419c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7b4aab9743c30be783b73de055d24a39cf4b954f",
"reference": "7b4aab9743c30be783b73de055d24a39cf4b954f",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fa79b11539418b02fc5e1897267673ba2c19419c",
"reference": "fa79b11539418b02fc5e1897267673ba2c19419c",
"shasum": "",
"mirrors": [
{
@ -997,7 +997,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.13-dev"
"dev-master": "1.17-dev"
}
},
"autoload": {
@ -1031,20 +1031,20 @@
"portable",
"shim"
],
"time": "2019-11-27T14:18:11+00:00"
"time": "2020-05-12T16:47:27+00:00"
},
{
"name": "symfony/polyfill-php72",
"version": "v1.13.1",
"version": "v1.17.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "66fea50f6cb37a35eea048d75a7d99a45b586038"
"reference": "f048e612a3905f34931127360bdd2def19a5e582"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/66fea50f6cb37a35eea048d75a7d99a45b586038",
"reference": "66fea50f6cb37a35eea048d75a7d99a45b586038",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/f048e612a3905f34931127360bdd2def19a5e582",
"reference": "f048e612a3905f34931127360bdd2def19a5e582",
"shasum": "",
"mirrors": [
{
@ -1059,7 +1059,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.13-dev"
"dev-master": "1.17-dev"
}
},
"autoload": {
@ -1092,20 +1092,20 @@
"portable",
"shim"
],
"time": "2019-11-27T13:56:44+00:00"
"time": "2020-05-12T16:47:27+00:00"
},
{
"name": "symfony/var-dumper",
"version": "v4.4.4",
"version": "v4.4.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
"reference": "46b53fd714568af343953c039ff47b67ce8af8d6"
"reference": "c587e04ce5d1aa62d534a038f574d9a709e814cf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/46b53fd714568af343953c039ff47b67ce8af8d6",
"reference": "46b53fd714568af343953c039ff47b67ce8af8d6",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/c587e04ce5d1aa62d534a038f574d9a709e814cf",
"reference": "c587e04ce5d1aa62d534a038f574d9a709e814cf",
"shasum": "",
"mirrors": [
{
@ -1174,20 +1174,20 @@
"debug",
"dump"
],
"time": "2020-01-25T12:44:29+00:00"
"time": "2020-04-12T16:14:02+00:00"
},
{
"name": "topthink/think-trace",
"version": "v1.2",
"version": "v1.3",
"source": {
"type": "git",
"url": "https://github.com/top-think/think-trace.git",
"reference": "4589d06a07945d57478cc2236f4b23d51ff919cc"
"reference": "d8da2e39df268ab8775013de699f0c3012e51318"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/think-trace/zipball/4589d06a07945d57478cc2236f4b23d51ff919cc",
"reference": "4589d06a07945d57478cc2236f4b23d51ff919cc",
"url": "https://api.github.com/repos/top-think/think-trace/zipball/d8da2e39df268ab8775013de699f0c3012e51318",
"reference": "d8da2e39df268ab8775013de699f0c3012e51318",
"shasum": "",
"mirrors": [
{
@ -1227,7 +1227,7 @@
}
],
"description": "thinkphp debug trace",
"time": "2019-10-17T02:14:09+00:00"
"time": "2020-03-18T07:59:53+00:00"
}
],
"aliases": [],

2
config/.gitignore vendored
View File

@ -1,2 +0,0 @@
database.php
app.php

View File

@ -20,9 +20,7 @@ return [
// 应用映射(自动多应用模式有效)
'app_map' => [],
// 域名绑定(自动多应用模式有效)
'domain_bind' => [
//'www' => 'index'
],
'domain_bind' => [],
// 禁止URL访问的应用列表自动多应用模式有效
'deny_app_list' => [],
@ -33,8 +31,4 @@ return [
'error_message' => '页面错误!请稍后再试~',
// 显示错误信息
'show_error_msg' => false,
//404
'http_exception_template' => [
404 => \think\facade\App::getAppPath() .'view/404.html'
]
];

View File

@ -17,7 +17,7 @@ return [
// 是否使用背景图
'useImgBg' => false,
//验证码字符大小
'fontSize' => 14,
'fontSize' => 25,
// 是否使用混淆曲线
'useCurve' => true,
//是否添加杂点

View File

@ -1,5 +1,7 @@
<?php
return [
// 默认使用的数据库连接配置
'default' => 'mysql',
// 自定义时间查询规则
'time_query_rule' => [],
// 自动写入时间戳字段

View File

@ -40,38 +40,6 @@ return [
'realtime_write' => false,
],
// 其它日志通道配置
'login' => [
// 日志记录方式
'type' => 'File',
// 日志保存目录
'path' => '../runtime/log/login/',
// 单文件日志写入
'single' => false,
// 最大日志文件数量
'max_files' => 0,
// 日志处理
'processor' => null,
// 日志输出格式化
'format' => '[%s][%s] %s',
// 是否实时写入
'realtime_write' => true,
],
'browse' => [
// 日志记录方式
'type' => 'File',
// 日志保存目录
'path' => '../runtime/log/browse/',
// 单文件日志写入
'single' => false,
// 最大日志文件数量
'max_files' => 0,
// 日志处理
'processor' => null,
// 日志输出格式化
'format' => '[%s][%s] %s',
// 是否实时写入
'realtime_write' => true,
],
],
];

View File

@ -3,8 +3,12 @@
// | 模板设置
// +----------------------------------------------------------------------
use think\facade\Db;
$template = Db::name('system')->where('id',1)->value('template');
//如果网站安装从数据库查询选择的模板
if(file_exists('../install.lock')){
$template = Db::name('system')->where('id',1)->value('template');
} else {
$template = '';
}
return [
// 模板引擎类型使用Think

View File

@ -12,8 +12,6 @@
// [ 应用入口文件 ]
namespace think;
use think\facade\Request;
require __DIR__ . '/../vendor/autoload.php';
// 执行HTTP应用并响应

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

View File

@ -1,14 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
use think\facade\Route;
Route::get('captcha/[:config]','\\think\\captcha\\CaptchaController@index');

2
vendor/autoload.php vendored
View File

@ -4,4 +4,4 @@
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit9b80d9a7bd440d07cac42880e0942921::getLoader();
return ComposerAutoloaderInit1b32198725235c8d6500c87262ef30c2::getLoader();

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit9b80d9a7bd440d07cac42880e0942921
class ComposerAutoloaderInit1b32198725235c8d6500c87262ef30c2
{
private static $loader;
@ -19,15 +19,15 @@ class ComposerAutoloaderInit9b80d9a7bd440d07cac42880e0942921
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit9b80d9a7bd440d07cac42880e0942921', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInit1b32198725235c8d6500c87262ef30c2', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit9b80d9a7bd440d07cac42880e0942921', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInit1b32198725235c8d6500c87262ef30c2', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit9b80d9a7bd440d07cac42880e0942921::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInit1b32198725235c8d6500c87262ef30c2::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
@ -48,19 +48,19 @@ class ComposerAutoloaderInit9b80d9a7bd440d07cac42880e0942921
$loader->register(true);
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInit9b80d9a7bd440d07cac42880e0942921::$files;
$includeFiles = Composer\Autoload\ComposerStaticInit1b32198725235c8d6500c87262ef30c2::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire9b80d9a7bd440d07cac42880e0942921($fileIdentifier, $file);
composerRequire1b32198725235c8d6500c87262ef30c2($fileIdentifier, $file);
}
return $loader;
}
}
function composerRequire9b80d9a7bd440d07cac42880e0942921($fileIdentifier, $file)
function composerRequire1b32198725235c8d6500c87262ef30c2($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
require $file;

View File

@ -4,7 +4,7 @@
namespace Composer\Autoload;
class ComposerStaticInit9b80d9a7bd440d07cac42880e0942921
class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
{
public static $files = array (
'9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php',
@ -141,9 +141,9 @@ class ComposerStaticInit9b80d9a7bd440d07cac42880e0942921
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit9b80d9a7bd440d07cac42880e0942921::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit9b80d9a7bd440d07cac42880e0942921::$prefixDirsPsr4;
$loader->fallbackDirsPsr0 = ComposerStaticInit9b80d9a7bd440d07cac42880e0942921::$fallbackDirsPsr0;
$loader->prefixLengthsPsr4 = ComposerStaticInit1b32198725235c8d6500c87262ef30c2::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit1b32198725235c8d6500c87262ef30c2::$prefixDirsPsr4;
$loader->fallbackDirsPsr0 = ComposerStaticInit1b32198725235c8d6500c87262ef30c2::$fallbackDirsPsr0;
}, null, ClassLoader::class);
}

View File

@ -1,17 +1,17 @@
[
{
"name": "league/flysystem",
"version": "1.0.64",
"version_normalized": "1.0.64.0",
"version": "1.0.69",
"version_normalized": "1.0.69.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem.git",
"reference": "d13c43dbd4b791f815215959105a008515d1a2e0"
"reference": "7106f78428a344bc4f643c233a94e48795f10967"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/d13c43dbd4b791f815215959105a008515d1a2e0",
"reference": "d13c43dbd4b791f815215959105a008515d1a2e0",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/7106f78428a344bc4f643c233a94e48795f10967",
"reference": "7106f78428a344bc4f643c233a94e48795f10967",
"shasum": "",
"mirrors": [
{
@ -47,7 +47,7 @@
"spatie/flysystem-dropbox": "Allows you to use Dropbox storage",
"srmklive/flysystem-dropbox-v2": "Allows you to use Dropbox storage for PHP 5 applications"
},
"time": "2020-02-05T18:14:17+00:00",
"time": "2020-05-18T15:13:39+00:00",
"type": "library",
"extra": {
"branch-alias": {
@ -217,17 +217,17 @@
},
{
"name": "phpmailer/phpmailer",
"version": "v6.1.4",
"version_normalized": "6.1.4.0",
"version": "v6.1.5",
"version_normalized": "6.1.5.0",
"source": {
"type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git",
"reference": "c5e61d0729507049cec9673aa1a679f9adefd683"
"reference": "a8bf068f64a580302026e484ee29511f661b2ad3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/c5e61d0729507049cec9673aa1a679f9adefd683",
"reference": "c5e61d0729507049cec9673aa1a679f9adefd683",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/a8bf068f64a580302026e484ee29511f661b2ad3",
"reference": "a8bf068f64a580302026e484ee29511f661b2ad3",
"shasum": "",
"mirrors": [
{
@ -254,7 +254,7 @@
"stevenmaguire/oauth2-microsoft": "Needed for Microsoft XOAUTH2 authentication",
"symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)"
},
"time": "2019-12-10T11:17:38+00:00",
"time": "2020-03-14T14:23:48+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -398,17 +398,17 @@
},
{
"name": "psr/log",
"version": "1.1.2",
"version_normalized": "1.1.2.0",
"version": "1.1.3",
"version_normalized": "1.1.3.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801"
"reference": "0f73288fd15629204f9d42b7055f72dacbe811fc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801",
"reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801",
"url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc",
"reference": "0f73288fd15629204f9d42b7055f72dacbe811fc",
"shasum": "",
"mirrors": [
{
@ -420,7 +420,7 @@
"require": {
"php": ">=5.3.0"
},
"time": "2019-11-01T11:05:21+00:00",
"time": "2020-03-23T09:12:05+00:00",
"type": "library",
"extra": {
"branch-alias": {
@ -509,17 +509,17 @@
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.13.1",
"version_normalized": "1.13.1.0",
"version": "v1.17.0",
"version_normalized": "1.17.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "7b4aab9743c30be783b73de055d24a39cf4b954f"
"reference": "fa79b11539418b02fc5e1897267673ba2c19419c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7b4aab9743c30be783b73de055d24a39cf4b954f",
"reference": "7b4aab9743c30be783b73de055d24a39cf4b954f",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fa79b11539418b02fc5e1897267673ba2c19419c",
"reference": "fa79b11539418b02fc5e1897267673ba2c19419c",
"shasum": "",
"mirrors": [
{
@ -534,11 +534,11 @@
"suggest": {
"ext-mbstring": "For best performance"
},
"time": "2019-11-27T14:18:11+00:00",
"time": "2020-05-12T16:47:27+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.13-dev"
"dev-master": "1.17-dev"
}
},
"installation-source": "dist",
@ -576,17 +576,17 @@
},
{
"name": "symfony/polyfill-php72",
"version": "v1.13.1",
"version_normalized": "1.13.1.0",
"version": "v1.17.0",
"version_normalized": "1.17.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "66fea50f6cb37a35eea048d75a7d99a45b586038"
"reference": "f048e612a3905f34931127360bdd2def19a5e582"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/66fea50f6cb37a35eea048d75a7d99a45b586038",
"reference": "66fea50f6cb37a35eea048d75a7d99a45b586038",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/f048e612a3905f34931127360bdd2def19a5e582",
"reference": "f048e612a3905f34931127360bdd2def19a5e582",
"shasum": "",
"mirrors": [
{
@ -598,11 +598,11 @@
"require": {
"php": ">=5.3.3"
},
"time": "2019-11-27T13:56:44+00:00",
"time": "2020-05-12T16:47:27+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.13-dev"
"dev-master": "1.17-dev"
}
},
"installation-source": "dist",
@ -639,17 +639,17 @@
},
{
"name": "symfony/var-dumper",
"version": "v4.4.4",
"version_normalized": "4.4.4.0",
"version": "v4.4.8",
"version_normalized": "4.4.8.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
"reference": "46b53fd714568af343953c039ff47b67ce8af8d6"
"reference": "c587e04ce5d1aa62d534a038f574d9a709e814cf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/46b53fd714568af343953c039ff47b67ce8af8d6",
"reference": "46b53fd714568af343953c039ff47b67ce8af8d6",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/c587e04ce5d1aa62d534a038f574d9a709e814cf",
"reference": "c587e04ce5d1aa62d534a038f574d9a709e814cf",
"shasum": "",
"mirrors": [
{
@ -678,7 +678,7 @@
"ext-intl": "To show region name in time zone dump",
"symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script"
},
"time": "2020-01-25T12:44:29+00:00",
"time": "2020-04-12T16:14:02+00:00",
"bin": [
"Resources/bin/var-dump-server"
],
@ -850,17 +850,17 @@
},
{
"name": "topthink/think-captcha",
"version": "v3.0.2",
"version_normalized": "3.0.2.0",
"version": "v3.0.3",
"version_normalized": "3.0.3.0",
"source": {
"type": "git",
"url": "https://github.com/top-think/think-captcha.git",
"reference": "0b4305da19e118cefd934007875a8112f9352f01"
"reference": "1eef3717c1bcf4f5bbe2d1a1c704011d330a8b55"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/think-captcha/zipball/0b4305da19e118cefd934007875a8112f9352f01",
"reference": "0b4305da19e118cefd934007875a8112f9352f01",
"url": "https://api.github.com/repos/top-think/think-captcha/zipball/1eef3717c1bcf4f5bbe2d1a1c704011d330a8b55",
"reference": "1eef3717c1bcf4f5bbe2d1a1c704011d330a8b55",
"shasum": "",
"mirrors": [
{
@ -872,7 +872,7 @@
"require": {
"topthink/framework": "^6.0.0"
},
"time": "2019-10-03T07:45:11+00:00",
"time": "2020-05-19T10:55:45+00:00",
"type": "library",
"extra": {
"think": {
@ -907,17 +907,17 @@
},
{
"name": "topthink/think-helper",
"version": "v3.1.3",
"version_normalized": "3.1.3.0",
"version": "v3.1.4",
"version_normalized": "3.1.4.0",
"source": {
"type": "git",
"url": "https://github.com/top-think/think-helper.git",
"reference": "4d85dfd3778623bbb1de3648f1dcd0c82f4439f4"
"reference": "c28d37743bda4a0455286ca85b17b5791d626e10"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/think-helper/zipball/4d85dfd3778623bbb1de3648f1dcd0c82f4439f4",
"reference": "4d85dfd3778623bbb1de3648f1dcd0c82f4439f4",
"url": "https://api.github.com/repos/top-think/think-helper/zipball/c28d37743bda4a0455286ca85b17b5791d626e10",
"reference": "c28d37743bda4a0455286ca85b17b5791d626e10",
"shasum": "",
"mirrors": [
{
@ -929,7 +929,7 @@
"require": {
"php": ">=7.1.0"
},
"time": "2019-09-30T02:36:48+00:00",
"time": "2019-11-08T08:01:10+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -954,17 +954,17 @@
},
{
"name": "topthink/think-multi-app",
"version": "v1.0.11",
"version_normalized": "1.0.11.0",
"version": "v1.0.12",
"version_normalized": "1.0.12.0",
"source": {
"type": "git",
"url": "https://github.com/top-think/think-multi-app.git",
"reference": "215f4a6bb88e53ad41b448c61957336eb55ce6f9"
"reference": "3c1914d2adc08c8753c7f67228885ca47fb9b3bf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/think-multi-app/zipball/215f4a6bb88e53ad41b448c61957336eb55ce6f9",
"reference": "215f4a6bb88e53ad41b448c61957336eb55ce6f9",
"url": "https://api.github.com/repos/top-think/think-multi-app/zipball/3c1914d2adc08c8753c7f67228885ca47fb9b3bf",
"reference": "3c1914d2adc08c8753c7f67228885ca47fb9b3bf",
"shasum": "",
"mirrors": [
{
@ -977,7 +977,7 @@
"php": ">=7.1.0",
"topthink/framework": "^6.0.0"
},
"time": "2019-10-29T06:34:59+00:00",
"time": "2020-03-01T13:29:35+00:00",
"type": "library",
"extra": {
"think": {
@ -1006,17 +1006,17 @@
},
{
"name": "topthink/think-orm",
"version": "v2.0.31",
"version_normalized": "2.0.31.0",
"version": "v2.0.32",
"version_normalized": "2.0.32.0",
"source": {
"type": "git",
"url": "https://github.com/top-think/think-orm.git",
"reference": "d6965dfae21f150e29cc899ab6f9b1bd2c0f2ee4"
"reference": "03aaaa4d8c4475115b3acaa5aa2498bf5792e017"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/think-orm/zipball/d6965dfae21f150e29cc899ab6f9b1bd2c0f2ee4",
"reference": "d6965dfae21f150e29cc899ab6f9b1bd2c0f2ee4",
"url": "https://api.github.com/repos/top-think/think-orm/zipball/03aaaa4d8c4475115b3acaa5aa2498bf5792e017",
"reference": "03aaaa4d8c4475115b3acaa5aa2498bf5792e017",
"shasum": "",
"mirrors": [
{
@ -1032,7 +1032,7 @@
"psr/simple-cache": "^1.0",
"topthink/think-helper": "^3.1"
},
"time": "2020-01-07T10:05:10+00:00",
"time": "2020-04-26T13:54:48+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -1104,17 +1104,17 @@
},
{
"name": "topthink/think-trace",
"version": "v1.2",
"version_normalized": "1.2.0.0",
"version": "v1.3",
"version_normalized": "1.3.0.0",
"source": {
"type": "git",
"url": "https://github.com/top-think/think-trace.git",
"reference": "4589d06a07945d57478cc2236f4b23d51ff919cc"
"reference": "d8da2e39df268ab8775013de699f0c3012e51318"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/think-trace/zipball/4589d06a07945d57478cc2236f4b23d51ff919cc",
"reference": "4589d06a07945d57478cc2236f4b23d51ff919cc",
"url": "https://api.github.com/repos/top-think/think-trace/zipball/d8da2e39df268ab8775013de699f0c3012e51318",
"reference": "d8da2e39df268ab8775013de699f0c3012e51318",
"shasum": "",
"mirrors": [
{
@ -1127,7 +1127,7 @@
"php": ">=7.1.0",
"topthink/framework": "^6.0.0"
},
"time": "2019-10-17T02:14:09+00:00",
"time": "2020-03-18T07:59:53+00:00",
"type": "library",
"extra": {
"think": {

View File

@ -7,6 +7,12 @@
"abstraction", "s3", "ftp", "sftp", "remote", "webdav",
"file systems", "cloud", "cloud files", "rackspace", "copy.com"
],
"funding": [
{
"type": "other",
"url": "https://offset.earth/frankdejonge"
}
],
"license": "MIT",
"authors": [
{

View File

@ -131,9 +131,9 @@ class Ftp extends AbstractFtpAdapter
public function connect()
{
if ($this->ssl) {
$this->connection = ftp_ssl_connect($this->getHost(), $this->getPort(), $this->getTimeout());
$this->connection = @ftp_ssl_connect($this->getHost(), $this->getPort(), $this->getTimeout());
} else {
$this->connection = ftp_connect($this->getHost(), $this->getPort(), $this->getTimeout());
$this->connection = @ftp_connect($this->getHost(), $this->getPort(), $this->getTimeout());
}
if ( ! $this->connection) {
@ -230,7 +230,7 @@ class Ftp extends AbstractFtpAdapter
public function disconnect()
{
if (is_resource($this->connection)) {
ftp_close($this->connection);
@ftp_close($this->connection);
}
$this->connection = null;

View File

@ -301,7 +301,7 @@ class Filesystem implements FilesystemInterface
return false;
}
return $object['timestamp'];
return (int) $object['timestamp'];
}
/**

View File

@ -87,7 +87,7 @@ interface FilesystemInterface
*
* @throws FileNotFoundException
*
* @return string|false The timestamp or false on failure.
* @return int|false The timestamp or false on failure.
*/
public function getTimestamp($path);

View File

@ -20,6 +20,8 @@ use League\Flysystem\Plugin\PluginNotFoundException;
* @method void assertPresent($path)
* @method void assertAbsent($path)
* @method Filesystem addPlugin(PluginInterface $plugin)
*
* @deprecated This functionality will be removed in 2.0
*/
class MountManager implements FilesystemInterface
{

View File

@ -102,6 +102,8 @@ class MimeType
'txt' => 'text/plain',
'text' => 'text/plain',
'log' => 'text/plain',
'markdown' => 'text/markdown',
'md' => 'text/markdown',
'rtx' => 'text/richtext',
'rtf' => 'text/rtf',
'xml' => 'application/xml',
@ -185,6 +187,8 @@ class MimeType
'odm' => 'application/vnd.oasis.opendocument.text-master',
'odb' => 'application/vnd.oasis.opendocument.database',
'ott' => 'application/vnd.oasis.opendocument.text-template',
'webp' => 'image/webp',
'ico' => 'image/x-icon',
];
/**

View File

@ -102,8 +102,8 @@ try {
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = 'user@example.com'; // SMTP username
$mail->Password = 'secret'; // SMTP password
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` also accepted
$mail->Port = 587; // TCP port to connect to
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` encouraged
$mail->Port = 587; // TCP port to connect to, use 465 for `PHPMailer::ENCRYPTION_SMTPS` above
//Recipients
$mail->setFrom('from@example.com', 'Mailer');
@ -155,7 +155,7 @@ Note that in order to reduce PHPMailer's deployed code footprint, the examples a
Complete generated API documentation is [available online](http://phpmailer.github.io/PHPMailer/).
You can generate complete API-level documentation by running `phpdoc` in the top-level folder, and documentation will appear in the `docs` folder, though you'll need to have [PHPDocumentor](http://www.phpdoc.org) installed. You may find [the unit tests](https://github.com/PHPMailer/PHPMailer/tree/master/test/phpmailerTest.php) a good source of how to do various operations such as encryption.
You can generate complete API-level documentation by running `phpdoc` in the top-level folder, and documentation will appear in the `docs` folder, though you'll need to have [PHPDocumentor](http://www.phpdoc.org) installed. You may find [the unit tests](https://github.com/PHPMailer/PHPMailer/blob/master/test/PHPMailerTest.php) a good source of how to do various operations such as encryption.
If the documentation doesn't cover what you need, search the [many questions on Stack Overflow](http://stackoverflow.com/questions/tagged/phpmailer), and before you ask a question about "SMTP Error: Could not connect to SMTP host.", [read the troubleshooting guide](https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting).

View File

@ -1 +1 @@
6.1.4
6.1.5

View File

@ -2,25 +2,27 @@
/**
* Danish PHPMailer language file: refer to English translation for definitive list
* @package PHPMailer
* @author Mikael Stokkebro <info@stokkebro.dk>
* @author John Sebastian <jms@iwb.dk>
* Rewrite and extension of the work by Mikael Stokkebro <info@stokkebro.dk>
*
*/
$PHPMAILER_LANG['authenticate'] = 'SMTP fejl: Kunne ikke logge på.';
$PHPMAILER_LANG['connect_host'] = 'SMTP fejl: Kunne ikke tilslutte SMTP serveren.';
$PHPMAILER_LANG['data_not_accepted'] = 'SMTP fejl: Data kunne ikke accepteres.';
//$PHPMAILER_LANG['empty_message'] = 'Message body empty';
$PHPMAILER_LANG['authenticate'] = 'SMTP fejl: Login mislykkedes.';
$PHPMAILER_LANG['connect_host'] = 'SMTP fejl: Forbindelse til SMTP serveren kunne ikke oprettes.';
$PHPMAILER_LANG['data_not_accepted'] = 'SMTP fejl: Data blev ikke accepteret.';
$PHPMAILER_LANG['empty_message'] = 'Meddelelsen er uden indhold';
$PHPMAILER_LANG['encoding'] = 'Ukendt encode-format: ';
$PHPMAILER_LANG['execute'] = 'Kunne ikke køre: ';
$PHPMAILER_LANG['file_access'] = 'Ingen adgang til fil: ';
$PHPMAILER_LANG['execute'] = 'Kunne ikke afvikle: ';
$PHPMAILER_LANG['file_access'] = 'Kunne ikke tilgå filen: ';
$PHPMAILER_LANG['file_open'] = 'Fil fejl: Kunne ikke åbne filen: ';
$PHPMAILER_LANG['from_failed'] = 'Følgende afsenderadresse er forkert: ';
$PHPMAILER_LANG['instantiate'] = 'Kunne ikke initialisere email funktionen.';
//$PHPMAILER_LANG['invalid_address'] = 'Invalid address: ';
$PHPMAILER_LANG['instantiate'] = 'Email funktionen kunne ikke initialiseres.';
$PHPMAILER_LANG['invalid_address'] = 'Udgyldig adresse: ';
$PHPMAILER_LANG['mailer_not_supported'] = ' mailer understøttes ikke.';
$PHPMAILER_LANG['provide_address'] = 'Du skal indtaste mindst en modtagers emailadresse.';
$PHPMAILER_LANG['provide_address'] = 'Indtast mindst en modtagers email adresse.';
$PHPMAILER_LANG['recipients_failed'] = 'SMTP fejl: Følgende modtagere er forkerte: ';
//$PHPMAILER_LANG['signing'] = 'Signing Error: ';
//$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
//$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
//$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
//$PHPMAILER_LANG['extension_missing'] = 'Extension missing: ';
$PHPMAILER_LANG['signing'] = 'Signeringsfejl: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() fejlede.';
$PHPMAILER_LANG['smtp_error'] = 'SMTP server fejl: ';
$PHPMAILER_LANG['variable_set'] = 'Kunne ikke definere eller nulstille variablen: ';
$PHPMAILER_LANG['extension_missing'] = 'Udvidelse mangler: ';

View File

@ -64,7 +64,7 @@ class PHPMailer
* Options: null (default), 1 = High, 3 = Normal, 5 = low.
* When null, the header is not set at all.
*
* @var int
* @var int|null
*/
public $Priority;
@ -745,7 +745,7 @@ class PHPMailer
*
* @var string
*/
const VERSION = '6.1.4';
const VERSION = '6.1.5';
/**
* Error severity: message only, continue processing.
@ -769,11 +769,22 @@ class PHPMailer
const STOP_CRITICAL = 2;
/**
* SMTP RFC standard line ending.
* The SMTP standard CRLF line break.
* If you want to change line break format, change static::$LE, not this.
*/
const CRLF = "\r\n";
/**
* "Folding White Space" a white space string used for line folding.
*/
const FWS = ' ';
/**
* SMTP RFC standard line ending; Carriage Return, Line Feed.
*
* @var string
*/
protected static $LE = "\r\n";
protected static $LE = self::CRLF;
/**
* The maximum line length supported by mail().
@ -1446,7 +1457,7 @@ class PHPMailer
) {
//SMTP mandates RFC-compliant line endings
//and it's also used with mail() on Windows
static::setLE("\r\n");
static::setLE(self::CRLF);
} else {
//Maintain backward compatibility with legacy Linux command line mailers
static::setLE(PHP_EOL);
@ -1553,7 +1564,7 @@ class PHPMailer
$this->encodeHeader($this->secureHeader($this->Subject)),
$this->MIMEBody
);
$this->MIMEHeader = rtrim($this->MIMEHeader, "\r\n ") . static::$LE .
$this->MIMEHeader = static::stripTrailingWSP($this->MIMEHeader) . static::$LE .
static::normalizeBreaks($header_dkim) . static::$LE;
}
@ -1620,7 +1631,7 @@ class PHPMailer
*/
protected function sendmailSend($header, $body)
{
$header = rtrim($header, "\r\n ") . static::$LE . static::$LE;
$header = static::stripTrailingWSP($header) . static::$LE . static::$LE;
// CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
if (!empty($this->Sender) && self::isShellSafe($this->Sender)) {
@ -1750,7 +1761,7 @@ class PHPMailer
*/
protected function mailSend($header, $body)
{
$header = rtrim($header, "\r\n ") . static::$LE . static::$LE;
$header = static::stripTrailingWSP($header) . static::$LE . static::$LE;
$toArr = [];
foreach ($this->to as $toaddr) {
@ -1839,7 +1850,7 @@ class PHPMailer
*/
protected function smtpSend($header, $body)
{
$header = rtrim($header, "\r\n ") . static::$LE . static::$LE;
$header = static::stripTrailingWSP($header) . static::$LE . static::$LE;
$bad_rcpt = [];
if (!$this->smtpConnect($this->SMTPOptions)) {
throw new Exception($this->lang('smtp_connect_failed'), self::STOP_CRITICAL);
@ -2511,7 +2522,8 @@ class PHPMailer
*/
public function getSentMIMEMessage()
{
return rtrim($this->MIMEHeader . $this->mailHeader, "\n\r") . static::$LE . static::$LE . $this->MIMEBody;
return static::stripTrailingWSP($this->MIMEHeader . $this->mailHeader) .
static::$LE . static::$LE . $this->MIMEBody;
}
/**
@ -2594,7 +2606,7 @@ class PHPMailer
$altBodyEncoding = static::ENCODING_QUOTED_PRINTABLE;
}
//Use this as a preamble in all multipart message types
$mimepre = 'This is a multi-part message in MIME format.' . static::$LE;
$mimepre = 'This is a multi-part message in MIME format.' . static::$LE . static::$LE;
switch ($this->message_type) {
case 'inline':
$body .= $mimepre;
@ -2949,7 +2961,7 @@ class PHPMailer
$disposition = 'attachment'
) {
try {
if (!static::isPermittedPath($path) || !@is_file($path)) {
if (!static::isPermittedPath($path) || !@is_file($path) || !is_readable($path)) {
throw new Exception($this->lang('file_access') . $path, self::STOP_CONTINUE);
}
@ -3134,7 +3146,7 @@ class PHPMailer
protected function encodeFile($path, $encoding = self::ENCODING_BASE64)
{
try {
if (!static::isPermittedPath($path) || !file_exists($path)) {
if (!static::isPermittedPath($path) || !file_exists($path) || !is_readable($path)) {
throw new Exception($this->lang('file_open') . $path, self::STOP_CONTINUE);
}
$file_buffer = file_get_contents($path);
@ -3146,7 +3158,10 @@ class PHPMailer
return $file_buffer;
} catch (Exception $exc) {
$this->setError($exc->getMessage());
$this->edebug($exc->getMessage());
if ($this->exceptions) {
throw $exc;
}
return '';
}
}
@ -3516,7 +3531,7 @@ class PHPMailer
$disposition = 'inline'
) {
try {
if (!static::isPermittedPath($path) || !@is_file($path)) {
if (!static::isPermittedPath($path) || !@is_file($path) || !is_readable($path)) {
throw new Exception($this->lang('file_access') . $path, self::STOP_CONTINUE);
}
@ -3935,15 +3950,28 @@ class PHPMailer
*
* @param string $name Custom header name
* @param string|null $value Header value
*
* @throws Exception
*/
public function addCustomHeader($name, $value = null)
{
if (null === $value) {
if (null === $value && strpos($name, ':') !== false) {
// Value passed in as name:value
$this->CustomHeader[] = explode(':', $name, 2);
} else {
$this->CustomHeader[] = [$name, $value];
list($name, $value) = explode(':', $name, 2);
}
$name = trim($name);
$value = trim($value);
//Ensure name is not empty, and that neither name nor value contain line breaks
if (empty($name) || strpbrk($name . $value, "\r\n") !== false) {
if ($this->exceptions) {
throw new Exception('Invalid header name or value');
}
return false;
}
$this->CustomHeader[] = [$name, $value];
return true;
}
/**
@ -3987,6 +4015,7 @@ class PHPMailer
foreach ($images[2] as $imgindex => $url) {
// Convert data URIs into embedded images
//e.g. "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
$match = [];
if (preg_match('#^data:(image/(?:jpe?g|gif|png));?(base64)?,(.+)#', $url, $match)) {
if (count($match) === 4 && static::ENCODING_BASE64 === $match[2]) {
$data = base64_decode($match[3]);
@ -4355,7 +4384,7 @@ class PHPMailer
$breaktype = static::$LE;
}
// Normalise to \n
$text = str_replace(["\r\n", "\r"], "\n", $text);
$text = str_replace([self::CRLF, "\r"], "\n", $text);
// Now convert LE as needed
if ("\n" !== $breaktype) {
$text = str_replace("\n", $breaktype, $text);
@ -4364,6 +4393,18 @@ class PHPMailer
return $text;
}
/**
* Remove trailing breaks from a string.
*
* @param string $text
*
* @return string The text to remove breaks from
*/
public static function stripTrailingWSP($text)
{
return rtrim($text, " \r\n\t");
}
/**
* Return the current line break format string.
*
@ -4472,13 +4513,15 @@ class PHPMailer
*/
public function DKIM_HeaderC($signHeader)
{
//Normalize breaks to CRLF (regardless of the mailer)
$signHeader = static::normalizeBreaks($signHeader, self::CRLF);
//Unfold header lines
//Note PCRE \s is too broad a definition of whitespace; RFC5322 defines it as `[ \t]`
//@see https://tools.ietf.org/html/rfc5322#section-2.2
//That means this may break if you do something daft like put vertical tabs in your headers.
//Unfold header lines
$signHeader = preg_replace('/\r\n[ \t]+/', ' ', $signHeader);
//Break headers out into an array
$lines = explode("\r\n", $signHeader);
$lines = explode(self::CRLF, $signHeader);
foreach ($lines as $key => $line) {
//If the header is missing a :, skip it as it's invalid
//This is likely to happen because the explode() above will also split
@ -4498,7 +4541,7 @@ class PHPMailer
$lines[$key] = trim($heading, " \t") . ':' . trim($value, " \t");
}
return implode("\r\n", $lines);
return implode(self::CRLF, $lines);
}
/**
@ -4515,13 +4558,13 @@ class PHPMailer
public function DKIM_BodyC($body)
{
if (empty($body)) {
return "\r\n";
return self::CRLF;
}
// Normalize line endings to CRLF
$body = static::normalizeBreaks($body, "\r\n");
$body = static::normalizeBreaks($body, self::CRLF);
//Reduce multiple trailing line breaks to a single one
return rtrim($body, "\r\n") . "\r\n";
return static::stripTrailingWSP($body) . self::CRLF;
}
/**
@ -4542,17 +4585,18 @@ class PHPMailer
$DKIMquery = 'dns/txt'; // Query method
$DKIMtime = time();
//Always sign these headers without being asked
//Recommended list from https://tools.ietf.org/html/rfc6376#section-5.4.1
$autoSignHeaders = [
'From',
'To',
'CC',
'Date',
'Subject',
'Reply-To',
'Message-ID',
'Content-Type',
'Mime-Version',
'X-Mailer',
'from',
'to',
'cc',
'date',
'subject',
'reply-to',
'message-id',
'content-type',
'mime-version',
'x-mailer',
];
if (stripos($headers_line, 'Subject') === false) {
$headers_line .= 'Subject: ' . $subject . static::$LE;
@ -4587,7 +4631,7 @@ class PHPMailer
$headersToSign = [];
foreach ($parsedHeaders as $header) {
//Is this header one that must be included in the DKIM signature?
if (in_array($header['label'], $autoSignHeaders, true)) {
if (in_array(strtolower($header['label']), $autoSignHeaders, true)) {
$headersToSignKeys[] = $header['label'];
$headersToSign[] = $header['label'] . ': ' . $header['value'];
if ($this->DKIM_copyHeaderFields) {
@ -4625,9 +4669,9 @@ class PHPMailer
//Fold long values
if (strlen($copiedHeader) > self::STD_LINE_LENGTH - 3) {
$copiedHeaderFields .= substr(
chunk_split($copiedHeader, self::STD_LINE_LENGTH - 3, static::$LE . ' '),
chunk_split($copiedHeader, self::STD_LINE_LENGTH - 3, static::$LE . self::FWS),
0,
-strlen(static::$LE . ' ')
-strlen(static::$LE . self::FWS)
);
} else {
$copiedHeaderFields .= $copiedHeader;
@ -4639,7 +4683,6 @@ class PHPMailer
$headerKeys = ' h=' . implode(':', $headersToSignKeys) . ';' . static::$LE;
$headerValues = implode(static::$LE, $headersToSign);
$body = $this->DKIM_BodyC($body);
$DKIMlen = strlen($body); // Length of body
$DKIMb64 = base64_encode(pack('H*', hash('sha256', $body))); // Base64 of packed binary SHA-256 hash of body
$ident = '';
if ('' !== $this->DKIM_identity) {
@ -4653,7 +4696,6 @@ class PHPMailer
' s=' . $this->DKIM_selector . ';' . static::$LE .
' a=' . $DKIMsignatureType . ';' .
' q=' . $DKIMquery . ';' .
' l=' . $DKIMlen . ';' .
' t=' . $DKIMtime . ';' .
' c=' . $DKIMcanonicalization . ';' . static::$LE .
$headerKeys .
@ -4666,9 +4708,9 @@ class PHPMailer
$headerValues . static::$LE . $dkimSignatureHeader
);
$signature = $this->DKIM_Sign($canonicalizedHeaders);
$signature = trim(chunk_split($signature, self::STD_LINE_LENGTH - 3, static::$LE . ' '));
$signature = trim(chunk_split($signature, self::STD_LINE_LENGTH - 3, static::$LE . self::FWS));
return static::normalizeBreaks($dkimSignatureHeader . $signature) . static::$LE;
return static::normalizeBreaks($dkimSignatureHeader . $signature);
}
/**

View File

@ -45,7 +45,7 @@ class POP3
*
* @var string
*/
const VERSION = '6.1.4';
const VERSION = '6.1.5';
/**
* Default POP3 port number.
@ -230,6 +230,8 @@ class POP3
}
// connect to the POP3 server
$errno = 0;
$errstr = '';
$this->pop_conn = fsockopen(
$host, // POP3 Host
$port, // Port #

View File

@ -34,7 +34,7 @@ class SMTP
*
* @var string
*/
const VERSION = '6.1.4';
const VERSION = '6.1.5';
/**
* SMTP line break constant.
@ -1344,6 +1344,7 @@ class SMTP
} else {
$this->last_smtp_transaction_id = false;
foreach ($this->smtp_transaction_id_patterns as $smtp_transaction_id_pattern) {
$matches = [];
if (preg_match($smtp_transaction_id_pattern, $reply, $matches)) {
$this->last_smtp_transaction_id = trim($matches[1]);
break;

View File

@ -1 +0,0 @@
vendor

View File

@ -23,7 +23,7 @@ interface LoggerInterface
* System is unusable.
*
* @param string $message
* @param array $context
* @param mixed[] $context
*
* @return void
*/
@ -36,7 +36,7 @@ interface LoggerInterface
* trigger the SMS alerts and wake you up.
*
* @param string $message
* @param array $context
* @param mixed[] $context
*
* @return void
*/
@ -48,7 +48,7 @@ interface LoggerInterface
* Example: Application component unavailable, unexpected exception.
*
* @param string $message
* @param array $context
* @param mixed[] $context
*
* @return void
*/
@ -59,7 +59,7 @@ interface LoggerInterface
* be logged and monitored.
*
* @param string $message
* @param array $context
* @param mixed[] $context
*
* @return void
*/
@ -72,7 +72,7 @@ interface LoggerInterface
* that are not necessarily wrong.
*
* @param string $message
* @param array $context
* @param mixed[] $context
*
* @return void
*/
@ -82,7 +82,7 @@ interface LoggerInterface
* Normal but significant events.
*
* @param string $message
* @param array $context
* @param mixed[] $context
*
* @return void
*/
@ -94,7 +94,7 @@ interface LoggerInterface
* Example: User logs in, SQL logs.
*
* @param string $message
* @param array $context
* @param mixed[] $context
*
* @return void
*/
@ -104,7 +104,7 @@ interface LoggerInterface
* Detailed debug information.
*
* @param string $message
* @param array $context
* @param mixed[] $context
*
* @return void
*/
@ -115,7 +115,7 @@ interface LoggerInterface
*
* @param mixed $level
* @param string $message
* @param array $context
* @param mixed[] $context
*
* @return void
*

View File

@ -136,11 +136,3 @@ abstract class LoggerInterfaceTest extends TestCase
$this->assertEquals($expected, $this->getLogs());
}
}
class DummyTest
{
public function __toString()
{
return 'DummyTest';
}
}

2
vendor/services.php vendored
View File

@ -1,5 +1,5 @@
<?php
// This file is automatically generated at:2020-02-18 19:24:39
// This file is automatically generated at:2020-05-20 10:51:37
declare (strict_types = 1);
return array (
0 => 'think\\captcha\\CaptchaService',

View File

@ -545,7 +545,14 @@ final class Mbstring
}
if ('UTF-8' === $encoding = self::getEncoding($encoding)) {
return preg_split("/(.{{$split_length}})/u", $string, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
$rx = '/(';
while (65535 < $split_length) {
$rx .= '.{65535}';
$split_length -= 65535;
}
$rx .= '.{'.$split_length.'})/us';
return preg_split($rx, $string, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
}
$result = array();

View File

@ -2,7 +2,7 @@ Symfony Polyfill / Mbstring
===========================
This component provides a partial, native PHP implementation for the
[Mbstring](http://php.net/mbstring) extension.
[Mbstring](https://php.net/mbstring) extension.
More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).

View File

@ -11,52 +11,131 @@
use Symfony\Polyfill\Mbstring as p;
if (!function_exists('mb_strlen')) {
define('MB_CASE_UPPER', 0);
define('MB_CASE_LOWER', 1);
define('MB_CASE_TITLE', 2);
if (!function_exists('mb_convert_encoding')) {
function mb_convert_encoding($s, $to, $from = null) { return p\Mbstring::mb_convert_encoding($s, $to, $from); }
}
if (!function_exists('mb_decode_mimeheader')) {
function mb_decode_mimeheader($s) { return p\Mbstring::mb_decode_mimeheader($s); }
}
if (!function_exists('mb_encode_mimeheader')) {
function mb_encode_mimeheader($s, $charset = null, $transferEnc = null, $lf = null, $indent = null) { return p\Mbstring::mb_encode_mimeheader($s, $charset, $transferEnc, $lf, $indent); }
}
if (!function_exists('mb_decode_numericentity')) {
function mb_decode_numericentity($s, $convmap, $enc = null) { return p\Mbstring::mb_decode_numericentity($s, $convmap, $enc); }
}
if (!function_exists('mb_encode_numericentity')) {
function mb_encode_numericentity($s, $convmap, $enc = null, $is_hex = false) { return p\Mbstring::mb_encode_numericentity($s, $convmap, $enc, $is_hex); }
}
if (!function_exists('mb_convert_case')) {
function mb_convert_case($s, $mode, $enc = null) { return p\Mbstring::mb_convert_case($s, $mode, $enc); }
}
if (!function_exists('mb_internal_encoding')) {
function mb_internal_encoding($enc = null) { return p\Mbstring::mb_internal_encoding($enc); }
}
if (!function_exists('mb_language')) {
function mb_language($lang = null) { return p\Mbstring::mb_language($lang); }
}
if (!function_exists('mb_list_encodings')) {
function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); }
}
if (!function_exists('mb_encoding_aliases')) {
function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); }
}
if (!function_exists('mb_check_encoding')) {
function mb_check_encoding($var = null, $encoding = null) { return p\Mbstring::mb_check_encoding($var, $encoding); }
}
if (!function_exists('mb_detect_encoding')) {
function mb_detect_encoding($str, $encodingList = null, $strict = false) { return p\Mbstring::mb_detect_encoding($str, $encodingList, $strict); }
}
if (!function_exists('mb_detect_order')) {
function mb_detect_order($encodingList = null) { return p\Mbstring::mb_detect_order($encodingList); }
}
if (!function_exists('mb_parse_str')) {
function mb_parse_str($s, &$result = array()) { parse_str($s, $result); }
}
if (!function_exists('mb_strlen')) {
function mb_strlen($s, $enc = null) { return p\Mbstring::mb_strlen($s, $enc); }
}
if (!function_exists('mb_strpos')) {
function mb_strpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strpos($s, $needle, $offset, $enc); }
}
if (!function_exists('mb_strtolower')) {
function mb_strtolower($s, $enc = null) { return p\Mbstring::mb_strtolower($s, $enc); }
}
if (!function_exists('mb_strtoupper')) {
function mb_strtoupper($s, $enc = null) { return p\Mbstring::mb_strtoupper($s, $enc); }
}
if (!function_exists('mb_substitute_character')) {
function mb_substitute_character($char = null) { return p\Mbstring::mb_substitute_character($char); }
}
if (!function_exists('mb_substr')) {
function mb_substr($s, $start, $length = 2147483647, $enc = null) { return p\Mbstring::mb_substr($s, $start, $length, $enc); }
}
if (!function_exists('mb_stripos')) {
function mb_stripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_stripos($s, $needle, $offset, $enc); }
}
if (!function_exists('mb_stristr')) {
function mb_stristr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_stristr($s, $needle, $part, $enc); }
}
if (!function_exists('mb_strrchr')) {
function mb_strrchr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrchr($s, $needle, $part, $enc); }
}
if (!function_exists('mb_strrichr')) {
function mb_strrichr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrichr($s, $needle, $part, $enc); }
}
if (!function_exists('mb_strripos')) {
function mb_strripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strripos($s, $needle, $offset, $enc); }
}
if (!function_exists('mb_strrpos')) {
function mb_strrpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strrpos($s, $needle, $offset, $enc); }
}
if (!function_exists('mb_strstr')) {
function mb_strstr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strstr($s, $needle, $part, $enc); }
}
if (!function_exists('mb_get_info')) {
function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); }
}
if (!function_exists('mb_http_output')) {
function mb_http_output($enc = null) { return p\Mbstring::mb_http_output($enc); }
}
if (!function_exists('mb_strwidth')) {
function mb_strwidth($s, $enc = null) { return p\Mbstring::mb_strwidth($s, $enc); }
}
if (!function_exists('mb_substr_count')) {
function mb_substr_count($haystack, $needle, $enc = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $enc); }
}
if (!function_exists('mb_output_handler')) {
function mb_output_handler($contents, $status) { return p\Mbstring::mb_output_handler($contents, $status); }
}
if (!function_exists('mb_http_input')) {
function mb_http_input($type = '') { return p\Mbstring::mb_http_input($type); }
}
if (!function_exists('mb_convert_variables')) {
function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null) { return p\Mbstring::mb_convert_variables($toEncoding, $fromEncoding, $a, $b, $c, $d, $e, $f); }
}
if (!function_exists('mb_chr')) {
if (!function_exists('mb_ord')) {
function mb_ord($s, $enc = null) { return p\Mbstring::mb_ord($s, $enc); }
}
if (!function_exists('mb_chr')) {
function mb_chr($code, $enc = null) { return p\Mbstring::mb_chr($code, $enc); }
}
if (!function_exists('mb_scrub')) {
function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); }
}
if (!function_exists('mb_str_split')) {
function mb_str_split($string, $split_length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $split_length, $encoding); }
}
if (extension_loaded('mbstring')) {
return;
}
if (!defined('MB_CASE_UPPER')) {
define('MB_CASE_UPPER', 0);
}
if (!defined('MB_CASE_LOWER')) {
define('MB_CASE_LOWER', 1);
}
if (!defined('MB_CASE_TITLE')) {
define('MB_CASE_TITLE', 2);
}

View File

@ -28,7 +28,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "1.13-dev"
"dev-master": "1.17-dev"
}
}
}

View File

@ -95,7 +95,8 @@ final class Php72
return;
}
return self::$hashMask ^ hexdec(substr($hash, 16 - \PHP_INT_SIZE, \PHP_INT_SIZE));
// On 32-bit systems, PHP_INT_SIZE is 4,
return self::$hashMask ^ hexdec(substr($hash, 16 - (\PHP_INT_SIZE * 2 - 1), (\PHP_INT_SIZE * 2 - 1)));
}
public static function sapi_windows_vt100_support($stream, $enable = null)
@ -166,7 +167,7 @@ final class Php72
self::$hashMask = (int) substr(ob_get_clean(), 17);
}
self::$hashMask ^= hexdec(substr(spl_object_hash($obj), 16 - \PHP_INT_SIZE, \PHP_INT_SIZE));
self::$hashMask ^= hexdec(substr(spl_object_hash($obj), 16 - (\PHP_INT_SIZE * 2 - 1), (\PHP_INT_SIZE * 2 - 1)));
}
public static function mb_chr($code, $encoding = null)

View File

@ -15,8 +15,9 @@ Moved to core since 7.2 (was in the optional XML extension earlier):
- [`utf8_encode`](https://php.net/utf8_encode)
- [`utf8_decode`](https://php.net/utf8_decode)
Also, it provides a constant added to PHP 7.2:
- [`PHP_OS_FAMILY`](http://php.net/manual/en/reserved.constants.php#constant.php-os-family)
Also, it provides constants added to PHP 7.2:
- [`PHP_FLOAT_*`](https://php.net/reserved.constants#constant.php-float-dig)
- [`PHP_OS_FAMILY`](https://php.net/reserved.constants#constant.php-os-family)
More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).

View File

@ -11,26 +11,47 @@
use Symfony\Polyfill\Php72 as p;
if (PHP_VERSION_ID < 70200) {
if ('\\' === DIRECTORY_SEPARATOR && !function_exists('sapi_windows_vt100_support')) {
function sapi_windows_vt100_support($stream, $enable = null) { return p\Php72::sapi_windows_vt100_support($stream, $enable); }
}
if (!function_exists('stream_isatty')) {
function stream_isatty($stream) { return p\Php72::stream_isatty($stream); }
}
if (!function_exists('utf8_encode')) {
function utf8_encode($s) { return p\Php72::utf8_encode($s); }
function utf8_decode($s) { return p\Php72::utf8_decode($s); }
}
if (!function_exists('spl_object_id')) {
function spl_object_id($s) { return p\Php72::spl_object_id($s); }
}
if (!defined('PHP_OS_FAMILY')) {
define('PHP_OS_FAMILY', p\Php72::php_os_family());
}
if (!function_exists('mb_chr')) {
function mb_ord($s, $enc = null) { return p\Php72::mb_ord($s, $enc); }
function mb_chr($code, $enc = null) { return p\Php72::mb_chr($code, $enc); }
function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); }
}
if (PHP_VERSION_ID >= 70200) {
return;
}
if (!defined('PHP_FLOAT_DIG')) {
define('PHP_FLOAT_DIG', 15);
}
if (!defined('PHP_FLOAT_EPSILON')) {
define('PHP_FLOAT_EPSILON', 2.2204460492503E-16);
}
if (!defined('PHP_FLOAT_MIN')) {
define('PHP_FLOAT_MIN', 2.2250738585072E-308);
}
if (!defined('PHP_FLOAT_MAX')) {
define('PHP_FLOAT_MAX', 1.7976931348623157E+308);
}
if (!defined('PHP_OS_FAMILY')) {
define('PHP_OS_FAMILY', p\Php72::php_os_family());
}
if ('\\' === DIRECTORY_SEPARATOR && !function_exists('sapi_windows_vt100_support')) {
function sapi_windows_vt100_support($stream, $enable = null) { return p\Php72::sapi_windows_vt100_support($stream, $enable); }
}
if (!function_exists('stream_isatty')) {
function stream_isatty($stream) { return p\Php72::stream_isatty($stream); }
}
if (!function_exists('utf8_encode')) {
function utf8_encode($s) { return p\Php72::utf8_encode($s); }
}
if (!function_exists('utf8_decode')) {
function utf8_decode($s) { return p\Php72::utf8_decode($s); }
}
if (!function_exists('spl_object_id')) {
function spl_object_id($s) { return p\Php72::spl_object_id($s); }
}
if (!function_exists('mb_ord')) {
function mb_ord($s, $enc = null) { return p\Php72::mb_ord($s, $enc); }
}
if (!function_exists('mb_chr')) {
function mb_chr($code, $enc = null) { return p\Php72::mb_chr($code, $enc); }
}
if (!function_exists('mb_scrub')) {
function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); }
}

View File

@ -25,7 +25,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "1.13-dev"
"dev-master": "1.17-dev"
}
}
}

View File

@ -1,3 +0,0 @@
/Tests export-ignore
/phpunit.xml.dist export-ignore
/.gitignore export-ignore

View File

@ -35,7 +35,11 @@ class DateCaster
.($location ? ($d->format('I') ? "\nDST On" : "\nDST Off") : '')
;
$a = [];
unset(
$a[Caster::PREFIX_DYNAMIC.'date'],
$a[Caster::PREFIX_DYNAMIC.'timezone'],
$a[Caster::PREFIX_DYNAMIC.'timezone_type']
);
$a[$prefix.'date'] = new ConstStub(self::formatDateTime($d, $location ? ' e (P)' : ' P'), $title);
$stub->class .= $d->format(' @U');

View File

@ -122,7 +122,7 @@ class Data implements \ArrayAccess, \Countable, \IteratorAggregate
public function getIterator()
{
if (!\is_array($value = $this->getValue())) {
throw new \LogicException(sprintf('%s object holds non-iterable type "%s".', self::class, \gettype($value)));
throw new \LogicException(sprintf('"%s" object holds non-iterable type "%s".', self::class, \gettype($value)));
}
yield from $value;
@ -396,7 +396,7 @@ class Data implements \ArrayAccess, \Countable, \IteratorAggregate
break;
default:
throw new \RuntimeException(sprintf('Unexpected Stub type: %s', $item->type));
throw new \RuntimeException(sprintf('Unexpected Stub type: "%s".', $item->type));
}
} elseif ('array' === $type) {
$dumper->enterHash($cursor, Cursor::HASH_INDEXED, 0, false);

View File

@ -48,7 +48,7 @@ class Stub
{
$properties = [];
if (!isset(self::$defaultProperties[$c = \get_class($this)])) {
if (!isset(self::$defaultProperties[$c = static::class])) {
self::$defaultProperties[$c] = get_class_vars($c);
foreach ((new \ReflectionClass($c))->getStaticProperties() as $k => $v) {

View File

@ -46,7 +46,7 @@ class VarCloner extends AbstractCloner
// or null if the original value is used directly
if (!$gid = self::$gid) {
$gid = self::$gid = uniqid(mt_rand(), true); // Unique string used to detect the special $GLOBALS variable
$gid = self::$gid = md5(random_bytes(6)); // Unique string used to detect the special $GLOBALS variable
}
$arrayStub = new Stub();
$arrayStub->type = Stub::TYPE_ARRAY;

View File

@ -38,6 +38,6 @@ if (!function_exists('dd')) {
VarDumper::dump($v);
}
die(1);
exit(1);
}
}

View File

@ -41,7 +41,7 @@ class DumpServer
public function start(): void
{
if (!$this->socket = stream_socket_server($this->host, $errno, $errstr)) {
throw new \RuntimeException(sprintf('Server start failed on "%s": %s %s.', $this->host, $errstr, $errno));
throw new \RuntimeException(sprintf('Server start failed on "%s": '.$errstr.' '.$errno, $this->host));
}
}

View File

@ -28,6 +28,5 @@
"captcha": "src/config.php"
}
}
},
"minimum-stability": "dev"
}
}

View File

@ -8,14 +8,16 @@ use think\Validate;
class CaptchaService extends Service
{
public function boot(Route $route)
public function boot()
{
$route->get('captcha/[:config]', "\\think\\captcha\\CaptchaController@index");
Validate::maker(function ($validate) {
$validate->extend('captcha', function ($value) {
return captcha_check($value);
}, ':attribute错误!');
});
$this->registerRoutes(function (Route $route) {
$route->get('captcha/[:config]', "\\think\\captcha\\CaptchaController@index");
});
}
}

View File

@ -35,11 +35,13 @@ function captcha_src($config = null): string
* @param $id
* @return string
*/
function captcha_img($id = ''): string
function captcha_img($id = '', $domid = ''): string
{
$src = captcha_src($id);
return "<img src='{$src}' alt='captcha' onclick='this.src=\"{$src}?\"+Math.random();' />";
$domid = empty($domid) ? $domid : "id='" . $domid . "'";
return "<img src='{$src}' alt='captcha' " . $domid . " onclick='this.src=\"{$src}?\"+Math.random();' />";
}
/**

View File

@ -353,7 +353,7 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
return $this->filter(function ($data) use ($field, $operator, $value) {
if (strpos($field, '.')) {
list($field, $relation) = explode('.', $field);
[$field, $relation] = explode('.', $field);
$result = $data[$field][$relation] ?? null;
} else {
@ -385,10 +385,10 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
case 'not in':
return is_scalar($result) && !in_array($result, $value, true);
case 'between':
list($min, $max) = is_string($value) ? explode(',', $value) : $value;
[$min, $max] = is_string($value) ? explode(',', $value) : $value;
return is_scalar($result) && $result >= $min && $result <= $max;
case 'not between':
list($min, $max) = is_string($value) ? explode(',', $value) : $value;
[$min, $max] = is_string($value) ? explode(',', $value) : $value;
return is_scalar($result) && $result > $max || $result < $min;
case '==':
case '=':
@ -473,11 +473,11 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
/**
* 返回数据中指定的一列
* @access public
* @param string $columnKey 键名
* @param string $indexKey 作为索引值的列
* @param string|null $columnKey 键名
* @param string|null $indexKey 作为索引值的列
* @return array
*/
public function column(string $columnKey, string $indexKey = null)
public function column(?string $columnKey, string $indexKey = null)
{
return array_column($this->items, $columnKey, $indexKey);
}
@ -509,13 +509,13 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
* @param string $order 排序
* @return $this
*/
public function order(string $field, string $order = null)
public function order(string $field, string $order = 'asc')
{
return $this->sort(function ($a, $b) use ($field, $order) {
$fieldA = $a[$field] ?? null;
$fieldB = $b[$field] ?? null;
return 'desc' == strtolower($order) ? strcmp($fieldB, $fieldA) : strcmp($fieldA, $fieldB);
return 'desc' == strtolower($order) ? $fieldB > $fieldA : $fieldA > $fieldB;
});
}
@ -535,7 +535,7 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
}
/**
* 获取最一个单元数据
* 获取最一个单元数据
*
* @access public
* @param callable|null $callback
@ -548,7 +548,7 @@ class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSeria
}
/**
* 获取一个单元数据
* 获取最后一个单元数据
*
* @access public
* @param callable|null $callback

View File

@ -79,13 +79,9 @@ class MultiApp
*/
protected function getRoutePath(): string
{
if (is_dir($this->app->getAppPath() . 'route')) {
return $this->app->getAppPath() . 'route' . DIRECTORY_SEPARATOR;
}
return $this->app->getRootPath() . 'route' . DIRECTORY_SEPARATOR . $this->appName . DIRECTORY_SEPARATOR;
}
/**
* 解析多应用
* @return bool
@ -203,7 +199,7 @@ class MultiApp
$this->app->setNamespace($this->app->config->get('app.app_namespace') ?: 'app\\' . $appName);
if (is_dir($appPath)) {
$this->app->setRuntimePath($this->app->getRootPath() . 'runtime' . DIRECTORY_SEPARATOR . $appName . DIRECTORY_SEPARATOR);
$this->app->setRuntimePath($this->app->getRuntimePath() . $appName . DIRECTORY_SEPARATOR);
$this->app->http->setRoutePath($this->getRoutePath());
//加载应用
@ -222,15 +218,9 @@ class MultiApp
include_once $appPath . 'common.php';
}
$configPath = $this->app->getConfigPath();
$files = [];
if (is_dir($appPath . 'config')) {
$files = array_merge($files, glob($appPath . 'config' . DIRECTORY_SEPARATOR . '*' . $this->app->getConfigExt()));
} elseif (is_dir($configPath . $appName)) {
$files = array_merge($files, glob($configPath . $appName . DIRECTORY_SEPARATOR . '*' . $this->app->getConfigExt()));
}
foreach ($files as $file) {
$this->app->config->load($file, pathinfo($file, PATHINFO_FILENAME));

View File

@ -14,12 +14,15 @@ use think\Service as BaseService;
class Service extends BaseService
{
public function register()
public function boot()
{
$this->app->middleware->unshift(MultiApp::class);
$this->app->event->listen('HttpRun', function () {
$this->app->middleware->add(MultiApp::class);
});
$this->commands([
'build' => command\Build::class,
'clear' => command\Clear::class,
]);
$this->app->bind([

View File

@ -158,7 +158,7 @@ class Build extends Command
file_put_contents($appPath . 'common.php', "<?php" . PHP_EOL . "// 这是系统自动生成的公共文件" . PHP_EOL);
}
foreach (['event', 'middleware', 'provider'] as $name) {
foreach (['event', 'middleware', 'common'] as $name) {
if (!is_file($appPath . $name . '.php')) {
file_put_contents($appPath . $name . '.php', "<?php" . PHP_EOL . "// 这是系统自动生成的{$name}定义文件" . PHP_EOL . "return [" . PHP_EOL . PHP_EOL . "];" . PHP_EOL);
}

View File

@ -139,6 +139,12 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
*/
protected static $maker = [];
/**
* 方法注入
* @var Closure[][]
*/
protected static $macro = [];
/**
* 设置服务注入
* @access public
@ -150,6 +156,21 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
static::$maker[] = $maker;
}
/**
* 设置方法注入
* @access public
* @param string $method
* @param Closure $closure
* @return void
*/
public static function macro(string $method, Closure $closure)
{
if (!isset(static::$macro[static::class])) {
static::$macro[static::class] = [];
}
static::$macro[static::class][$method] = $closure;
}
/**
* 设置Db对象
* @access public
@ -759,11 +780,13 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
$result = [];
$suffix = $this->getSuffix();
foreach ($dataSet as $key => $data) {
if ($this->exists || (!empty($auto) && isset($data[$pk]))) {
$result[$key] = self::update($data);
$result[$key] = static::update($data, [], [], $suffix);
} else {
$result[$key] = self::create($data, $this->field, $this->replace);
$result[$key] = static::create($data, $this->field, $this->replace, $suffix);
}
}
@ -822,9 +845,10 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
* @param array $data 数据数组
* @param array $allowField 允许字段
* @param bool $replace 使用Replace
* @param string $suffix 数据表后缀
* @return static
*/
public static function create(array $data, array $allowField = [], bool $replace = false): Model
public static function create(array $data, array $allowField = [], bool $replace = false, string $suffix = ''): Model
{
$model = new static();
@ -832,6 +856,10 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
$model->allowField($allowField);
}
if (!empty($suffix)) {
$model->setSuffix($suffix);
}
$model->replace($replace)->save($data);
return $model;
@ -843,9 +871,10 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
* @param array $data 数据数组
* @param mixed $where 更新条件
* @param array $allowField 允许字段
* @param string $suffix 数据表后缀
* @return static
*/
public static function update(array $data, $where = [], array $allowField = [])
public static function update(array $data, $where = [], array $allowField = [], string $suffix = '')
{
$model = new static();
@ -857,6 +886,10 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
$model->setUpdateWhere($where);
}
if (!empty($suffix)) {
$model->setSuffix($suffix);
}
$model->exists(true)->save($data);
return $model;
@ -1013,6 +1046,10 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
public function __call($method, $args)
{
if (isset(static::$macro[static::class][$method])) {
return call_user_func_array(static::$macro[static::class][$method]->bindTo($this, static::class), $args);
}
if ('withattr' == strtolower($method)) {
return call_user_func_array([$this, 'withAttribute'], $args);
}
@ -1022,6 +1059,10 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
public static function __callStatic($method, $args)
{
if (isset(static::$macro[static::class][$method])) {
return call_user_func_array(static::$macro[static::class][$method]->bindTo(null, static::class), $args);
}
$model = new static();
return call_user_func_array([$model->db(), $method], $args);

View File

@ -368,7 +368,10 @@ abstract class Builder
if ($value instanceof Closure) {
// 使用闭包查询
$where[] = $this->parseClosureWhere($query, $value, $logic);
$whereClosureStr = $this->parseClosureWhere($query, $value, $logic);
if ($whereClosureStr) {
$where[] = $whereClosureStr;
}
} elseif (is_array($field)) {
$where[] = $this->parseMultiWhereField($query, $value, $field, $logic, $binds);
} elseif ($field instanceof Raw) {

View File

@ -214,11 +214,12 @@ abstract class Connection
* 分析缓存Key
* @access protected
* @param BaseQuery $query 查询对象
* @param string $method查询方法
* @return string
*/
protected function getCacheKey(BaseQuery $query): string
protected function getCacheKey(BaseQuery $query, string $method = ''): string
{
if (!empty($query->getOptions('key'))) {
if (!empty($query->getOptions('key')) && empty($method)) {
$key = 'think:' . $this->getConfig('database') . '.' . $query->getTable() . '|' . $query->getOptions('key');
} else {
$key = $query->getQueryGuid();
@ -232,9 +233,10 @@ abstract class Connection
* @access protected
* @param BaseQuery $query 查询对象
* @param array $cache 缓存信息
* @param string $method查询方法
* @return CacheItem
*/
protected function parseCache(BaseQuery $query, array $cache): CacheItem
protected function parseCache(BaseQuery $query, array $cache, string $method = ''): CacheItem
{
[$key, $expire, $tag] = $cache;
@ -242,7 +244,7 @@ abstract class Connection
$cacheItem = $key;
} else {
if (true === $key) {
$key = $this->getCacheKey($query);
$key = $this->getCacheKey($query, $method);
}
$cacheItem = new CacheItem($key);

View File

@ -1033,7 +1033,7 @@ abstract class PDOConnection extends Connection implements ConnectionInterface
$query->setOption('field', (array) $field);
if (!empty($options['cache'])) {
$cacheItem = $this->parseCache($query, $options['cache']);
$cacheItem = $this->parseCache($query, $options['cache'], 'value');
$key = $cacheItem->getKey();
if ($this->cache->has($key)) {
@ -1118,7 +1118,7 @@ abstract class PDOConnection extends Connection implements ConnectionInterface
if (!empty($options['cache'])) {
// 判断查询缓存
$cacheItem = $this->parseCache($query, $options['cache']);
$cacheItem = $this->parseCache($query, $options['cache'], 'column');
$name = $cacheItem->getKey();
if ($this->cache->has($name)) {
@ -1151,6 +1151,8 @@ abstract class PDOConnection extends Connection implements ConnectionInterface
if (strpos($column, ',')) {
$column = null;
} elseif (strpos($column, ' ')) {
$column = substr(strrchr(trim($column), ' '), 1);
} elseif (strpos($column, '.')) {
[$alias, $column] = explode('.', $column);
}

View File

@ -140,13 +140,19 @@ trait ModelRelationQuery
/**
* 使用搜索器条件搜索字段
* @access public
* @param array $fields 搜索字段
* @param array $data 搜索数据
* @param string|array $fields 搜索字段
* @param mixed $data 搜索数据
* @param string $prefix 字段前缀标识
* @return $this
*/
public function withSearch(array $fields, array $data = [], string $prefix = '')
public function withSearch($fields, $data = [], string $prefix = '')
{
if (is_string($fields)) {
$fields = explode(',', $fields);
}
$likeFields = $this->getConfig('match_like_fields') ?: [];
foreach ($fields as $key => $field) {
if ($field instanceof Closure) {
$field($this, $data[$key] ?? null, $data, $prefix);
@ -157,6 +163,8 @@ trait ModelRelationQuery
if (method_exists($this->model, $method)) {
$this->model->$method($this, $data[$field] ?? null, $data, $prefix);
} elseif (isset($data[$field])) {
$this->where($fieldName, in_array($fieldName, $likeFields) ? 'like' : '=', in_array($fieldName, $likeFields) ? '%' . $data[$field] . '%' : $data[$field]);
}
}
}

View File

@ -12,10 +12,14 @@ declare (strict_types = 1);
namespace think\db\concern;
use Closure;
use think\Collection;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\db\Query;
use think\helper\Str;
use think\Model;
/**
* 查询数据处理
@ -103,6 +107,7 @@ trait ResultOperation
*/
protected function filterResult(&$result): void
{
$array = [];
if (!empty($this->options['visible'])) {
foreach ($this->options['visible'] as $key) {
$array[] = $key;
@ -222,9 +227,6 @@ trait ResultOperation
* @access public
* @param array|string|Query|Closure $data 数据
* @return array|Model
* @throws DbException
* @throws ModelNotFoundException
* @throws DataNotFoundException
*/
public function selectOrFail($data = null)
{
@ -236,9 +238,6 @@ trait ResultOperation
* @access public
* @param array|string|Query|Closure $data 数据
* @return array|Model
* @throws DbException
* @throws ModelNotFoundException
* @throws DataNotFoundException
*/
public function findOrFail($data = null)
{

View File

@ -228,7 +228,7 @@ abstract class Relation
if (!empty($params)) {
$type = $params[0]->getType();
return Relation::class == $type || is_null($type) ? $this : $this->query;
return is_null($type) || Relation::class == $type->getName() ? $this : $this->query;
}
return $this;

View File

@ -720,7 +720,7 @@ trait RelationShip
{
$relation = Str::camel($attr);
if (method_exists($this, $relation) && !method_exists('think\Model', $relation)) {
if ((method_exists($this, $relation) && !method_exists('think\Model', $relation)) || isset(static::$macro[static::class][$relation])) {
return $relation;
}

View File

@ -13,9 +13,11 @@ declare (strict_types = 1);
namespace think\model\concern;
use think\db\BaseQuery as Query;
use think\Model;
/**
* 数据软删除
* @mixin Model
*/
trait SoftDelete
{
@ -149,7 +151,7 @@ trait SoftDelete
public static function destroy($data, bool $force = false): bool
{
// 包含软删除数据
$query = (new static())->db(false);
$query = (new static())->withTrashedData(true)->db(false);
if (is_array($data) && key($data) !== 0) {
$query->where($data);

View File

@ -222,7 +222,7 @@ class BelongsToMany extends Relation
*/
public function find($data = null)
{
$result = $this->buildQuery()->find($data);
$result = $this->buildQuery()->findOrEmpty($data);
if (!$result->isEmpty()) {
$this->hydratePivot([$result]);

View File

@ -340,7 +340,7 @@ class HasMany extends Relation
return $query->group($model . '.' . $this->localKey)
->field($fields)
->join([$table => $relation], $model . '.' . $this->localKey . '=' . $relation . '.' . $this->foreignKey)
->join([$table => $relation], $model . '.' . $this->localKey . '=' . $relation . '.' . $this->foreignKey, $joinType)
->when($softDelete, function ($query) use ($softDelete, $relation) {
$query->where($relation . strstr($softDelete[0], '.'), '=' == $softDelete[1][0] ? $softDelete[1][1] : null);
})

View File

@ -154,7 +154,7 @@ class HasManyThrough extends Relation
$query = $query ?: $this->parent->db()->alias($model);
return $query->join($throughTable, $throughTable . '.' . $this->foreignKey . '=' . $model . '.' . $this->localKey)
->join($modelTable, $modelTable . '.' . $throughKey . '=' . $throughTable . '.' . $this->throughPk)
->join($modelTable, $modelTable . '.' . $throughKey . '=' . $throughTable . '.' . $this->throughPk, $joinType)
->when($softDelete, function ($query) use ($softDelete, $modelTable) {
$query->where($modelTable . strstr($softDelete[0], '.'), '=' == $softDelete[1][0] ? $softDelete[1][1] : null);
})

View File

@ -223,7 +223,6 @@ class MorphTo extends Relation
// 关联模型
if (!isset($data[$result->$morphKey])) {
$relationModel = null;
throw new Exception('relation data not exists :' . $this->model);
} else {
$relationModel = $data[$result->$morphKey];
$relationModel->setParent(clone $result);

View File

@ -47,7 +47,7 @@ class Console
return false;
}
// 获取基本信息
$runtime = number_format(microtime(true) - $app->getBeginTime(), 10);
$runtime = number_format(microtime(true) - $app->getBeginTime(), 10, '.', '');
$reqs = $runtime > 0 ? number_format(1 / $runtime, 2) : '∞';
$mem = number_format((memory_get_usage() - $app->getBeginMem()) / 1024, 2);
@ -59,7 +59,7 @@ class Console
// 页面Trace信息
$base = [
'请求信息' => date('Y-m-d H:i:s', $request->time()) . ' ' . $uri,
'请求信息' => date('Y-m-d H:i:s', $request->time() ?: time()) . ' ' . $uri,
'运行时间' => number_format((float) $runtime, 6) . 's [ 吞吐率:' . $reqs . 'req/s ] 内存消耗:' . $mem . 'kb 文件加载:' . count(get_included_files()),
'查询信息' => $app->db->getQueryTimes() . ' queries',
'缓存信息' => $app->cache->getReadTimes() . ' reads,' . $app->cache->getWriteTimes() . ' writes',

View File

@ -63,7 +63,7 @@ class Html
}
$base = [
'请求信息' => date('Y-m-d H:i:s', $request->time()) . ' ' . $uri,
'请求信息' => date('Y-m-d H:i:s', $request->time() ?: time()) . ' ' . $uri,
'运行时间' => number_format((float) $runtime, 6) . 's [ 吞吐率:' . $reqs . 'req/s ] 内存消耗:' . $mem . 'kb 文件加载:' . count(get_included_files()),
'查询信息' => $app->db->getQueryTimes() . ' queries',
'缓存信息' => $app->cache->getReadTimes() . ' reads,' . $app->cache->getWriteTimes() . ' writes',

1
view/README.md Normal file
View File

@ -0,0 +1 @@
如果不使用模板,可以删除该目录