mirror of
https://gitee.com/zoujingli/ThinkAdmin.git
synced 2025-04-05 19:41:44 +08:00
[更新]合并原有版本任务管理,去除tp官方任务
This commit is contained in:
parent
a4fb320545
commit
8aec17e5ed
56
admin_v5.sql
56
admin_v5.sql
@ -11,7 +11,7 @@
|
||||
Target Server Version : 50562
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 13/08/2019 18:20:43
|
||||
Date: 14/08/2019 10:33:20
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
@ -549,48 +549,6 @@ CREATE TABLE `system_data` (
|
||||
-- ----------------------------
|
||||
INSERT INTO `system_data` VALUES (1, 'menudata', '[{\"name\":\"请输入名称\",\"type\":\"scancode_push\",\"key\":\"scancode_push\"}]');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for system_jobs
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `system_jobs`;
|
||||
CREATE TABLE `system_jobs` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`queue` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`payload` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`attempts` bigint(20) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`reserved` bigint(20) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`reserved_at` int(10) UNSIGNED NULL DEFAULT NULL,
|
||||
`available_at` int(10) UNSIGNED NOT NULL,
|
||||
`created_at` int(10) UNSIGNED NOT NULL,
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `index_system_jobs_reserved`(`reserved`) USING BTREE,
|
||||
INDEX `index_system_jobs_attempts`(`attempts`) USING BTREE,
|
||||
INDEX `index_system_jobs_reserved_at`(`reserved_at`) USING BTREE,
|
||||
INDEX `index_system_jobs_available_at`(`available_at`) USING BTREE,
|
||||
INDEX `index_system_jobs_create_at`(`created_at`) USING BTREE,
|
||||
INDEX `index_system_jobs_queue`(`queue`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统-任务';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for system_jobs_log
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `system_jobs_log`;
|
||||
CREATE TABLE `system_jobs_log` (
|
||||
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '任务名称',
|
||||
`uri` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '任务对象',
|
||||
`later` bigint(20) UNSIGNED NULL DEFAULT 0 COMMENT '任务延时',
|
||||
`data` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '任务数据',
|
||||
`desc` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '任务描述',
|
||||
`double` tinyint(1) UNSIGNED NULL DEFAULT 1 COMMENT '任务多开',
|
||||
`status` tinyint(1) UNSIGNED NULL DEFAULT 1 COMMENT '任务状态(1新任务,2任务进行中,3任务成功,4任务失败)',
|
||||
`status_at` datetime NULL DEFAULT NULL COMMENT '任务状态时间',
|
||||
`status_desc` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '任务状态描述',
|
||||
`create_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `index_system_jobs_log_status`(`status`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统-任务-日志';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for system_log
|
||||
-- ----------------------------
|
||||
@ -680,19 +638,21 @@ INSERT INTO `system_menu` VALUES (61, 58, '网络打卡管理', '', 'layui-icon
|
||||
DROP TABLE IF EXISTS `system_queue`;
|
||||
CREATE TABLE `system_queue` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '任务名称',
|
||||
`title` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '任务名称',
|
||||
`data` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '执行参数',
|
||||
`status` tinyint(1) UNSIGNED NULL DEFAULT 1 COMMENT '任务状态(1新任务,2处理中,3成功,4失败)',
|
||||
`preload` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '执行内容',
|
||||
`time` bigint(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT '执行时间',
|
||||
`double` tinyint(1) NULL DEFAULT 1 COMMENT '单例模式',
|
||||
`desc` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '状态描述',
|
||||
`start_at` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '开始时间',
|
||||
`end_at` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '结束时间',
|
||||
`create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `index_system_jobs_attempts`(`time`) USING BTREE,
|
||||
INDEX `index_system_jobs_create_at`(`create_at`) USING BTREE,
|
||||
INDEX `index_system_jobs_queue`(`title`(191)) USING BTREE
|
||||
INDEX `index_system_queue_double`(`double`) USING BTREE,
|
||||
INDEX `index_system_queue_time`(`time`) USING BTREE,
|
||||
INDEX `index_system_queue_title`(`title`) USING BTREE,
|
||||
INDEX `index_system_queue_create_at`(`create_at`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统-任务';
|
||||
|
||||
-- ----------------------------
|
||||
@ -724,7 +684,7 @@ CREATE TABLE `system_user` (
|
||||
-- ----------------------------
|
||||
-- Records of system_user
|
||||
-- ----------------------------
|
||||
INSERT INTO `system_user` VALUES (10000, 'admin', '21232f297a57a5a743894a0e4a801fc3', '22222222', '', '', '2019-08-13 16:01:30', '127.0.0.1', 657, '', '', '', 1, 0, '2015-11-13 15:14:22');
|
||||
INSERT INTO `system_user` VALUES (10000, 'admin', '21232f297a57a5a743894a0e4a801fc3', '22222222', '', '', '2019-08-14 10:07:34', '127.0.0.1', 659, '', '', '', 1, 0, '2015-11-13 15:14:22');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for wechat_fans
|
||||
|
@ -15,11 +15,8 @@
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\admin\service\QueueService;
|
||||
use library\Controller;
|
||||
use think\Console;
|
||||
use think\Db;
|
||||
use think\exception\HttpResponseException;
|
||||
|
||||
/**
|
||||
* 系统系统任务
|
||||
@ -32,7 +29,7 @@ class Queue extends Controller
|
||||
* 绑定数据表
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'SystemJobsLog';
|
||||
protected $table = 'SystemQueue';
|
||||
|
||||
/**
|
||||
* 系统系统任务
|
||||
@ -46,57 +43,26 @@ class Queue extends Controller
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
if (session('admin_user.username') === 'admin') {
|
||||
try {
|
||||
$this->cmd = 'php ' . env('root_path') . 'think xtask:start';
|
||||
$this->message = Console::call('xtask:state')->fetch();
|
||||
} catch (\Exception $exception) {
|
||||
$this->message = $exception->getMessage();
|
||||
}
|
||||
if (session('admin_user.username') === 'admin') try {
|
||||
$this->cmd = 'php ' . env('root_path') . 'think xtask:start';
|
||||
$this->message = Console::call('xtask:state')->fetch();
|
||||
} catch (\Exception $exception) {
|
||||
$this->message = $exception->getMessage();
|
||||
}
|
||||
$this->title = '系统任务管理';
|
||||
$this->uris = Db::name($this->table)->distinct(true)->column('uri');
|
||||
// 查询任务列表
|
||||
$query = $this->_query($this->table)->dateBetween('create_at,status_at');
|
||||
$query->equal('status,title,uri')->order('id desc')->page();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置失败任务
|
||||
* @auth true
|
||||
*/
|
||||
public function redo()
|
||||
{
|
||||
try {
|
||||
$info = Db::name($this->table)->where(['id' => input('id', '0')])->find();
|
||||
if (empty($info)) $this->error('任务读取异常!');
|
||||
$data = isset($info['data']) ? json_decode($info['data'], true) : '[]';
|
||||
QueueService::add($info['title'], $info['uri'], $info['later'], $data, $info['double'], $info['desc']);
|
||||
$this->success('任务重置成功!', url('@admin') . '#' . url('@admin/queue/index'));
|
||||
} catch (HttpResponseException $exception) {
|
||||
throw $exception;
|
||||
} catch (\Exception $e) {
|
||||
$this->error("任务重置失败,请稍候再试!<br> {$e->getMessage()}");
|
||||
}
|
||||
$query = $this->_query($this->table)->dateBetween('create_at,end_at');
|
||||
$query->like('title,preload')->equal('status')->order('id desc')->page();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除系统任务
|
||||
* @auth true
|
||||
* @throws \think\Exception
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
public function remove()
|
||||
{
|
||||
try {
|
||||
$isNot = false;
|
||||
$this->ids = explode(',', input('id', '0'));
|
||||
foreach ($this->ids as $id) if (!QueueService::del($id)) $isNot = true;
|
||||
if (empty($isNot)) $this->_delete($this->table);
|
||||
$this->success($isNot ? '部分任务删除成功!' : '任务删除成功!');
|
||||
} catch (HttpResponseException $exception) {
|
||||
throw $exception;
|
||||
} catch (\Exception $e) {
|
||||
$this->error("任务删除失败,请稍候再试!<br> {$e->getMessage()}");
|
||||
}
|
||||
$this->_delete($this->table);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,125 +0,0 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | 官方网站: http://demo.thinkadmin.top
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 ( https://mit-license.org )
|
||||
// +----------------------------------------------------------------------
|
||||
// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
|
||||
// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\admin\queue;
|
||||
|
||||
use app\admin\service\QueueService;
|
||||
use think\console\Output;
|
||||
use think\queue\Job;
|
||||
|
||||
/**
|
||||
* 基础指令公共类
|
||||
* Class JobsQueue
|
||||
* @package app\admin
|
||||
*/
|
||||
class JobsQueue
|
||||
{
|
||||
/**
|
||||
* 待处理
|
||||
*/
|
||||
const STATUS_PEND = 1;
|
||||
|
||||
/**
|
||||
* 处理中
|
||||
*/
|
||||
const STATUS_PROC = 2;
|
||||
|
||||
/**
|
||||
* 处理完成
|
||||
*/
|
||||
const STATUS_COMP = 3;
|
||||
|
||||
/**
|
||||
* 处理失败
|
||||
*/
|
||||
const STATUS_FAIL = 4;
|
||||
|
||||
/**
|
||||
* 任务ID
|
||||
* @var integer
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* 任务数据
|
||||
* @var array
|
||||
*/
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* 任务名称
|
||||
* @var string
|
||||
*/
|
||||
protected $title;
|
||||
|
||||
/**
|
||||
* 任务状态
|
||||
* @var integer
|
||||
*/
|
||||
protected $status;
|
||||
|
||||
/**
|
||||
* @var Output
|
||||
*/
|
||||
protected $output;
|
||||
|
||||
/**
|
||||
* 任务状态描述
|
||||
* @var string
|
||||
*/
|
||||
protected $statusDesc = '';
|
||||
|
||||
/**
|
||||
* 启动任务处理
|
||||
* @param Job $job 当前任务对象
|
||||
* @param array $data 任务执行对象
|
||||
* @throws \think\Exception
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
public function fire(Job $job, $data = [])
|
||||
{
|
||||
$this->data = $data;
|
||||
$this->output = new Output();
|
||||
$this->id = isset($data['_job_id_']) ? $data['_job_id_'] : '';
|
||||
$this->title = isset($data['_job_title_']) ? $data['_job_title_'] : '';
|
||||
$this->output->newLine();
|
||||
$this->output->writeln(" system task {$this->id} execution start");
|
||||
$this->output->writeln('---------------------------------------------');
|
||||
QueueService::status($this->id, self::STATUS_PROC, $this->statusDesc);
|
||||
if ($this->execute()) {
|
||||
$this->output->writeln('---------------------------------------------');
|
||||
$this->output->info(" successful");
|
||||
$this->status = self::STATUS_COMP;
|
||||
} else {
|
||||
$this->output->writeln('---------------------------------------------');
|
||||
$this->output->error(" failure");
|
||||
$this->status = self::STATUS_FAIL;
|
||||
}
|
||||
$job->delete();
|
||||
QueueService::status($this->id, $this->status, $this->statusDesc);
|
||||
$this->output->writeln('---------------------------------------------');
|
||||
$this->output->newLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行任务
|
||||
* @return boolean
|
||||
*/
|
||||
protected function execute()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -33,7 +33,7 @@ class Listen extends Task
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('xqueue:listen')->setDescription('启动异步任务监听守护主进程');
|
||||
$this->setName('xtask:listen')->setDescription('启动异步任务监听守护主进程');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -53,20 +53,19 @@ class Listen extends Task
|
||||
cli_set_process_title("ThinkAdmin {$this->version} 异步任务监听主进程");
|
||||
}
|
||||
while (true) {
|
||||
$map = [['status', 'eq', '1'], ['time', '<=', time()]];
|
||||
foreach (Db::name('SystemQueue')->where($map)->order('time asc')->select() as $item) {
|
||||
foreach (Db::name('SystemQueue')->where([['status', 'eq', '1'], ['time', '<=', time()]])->order('time asc')->select() as $item) {
|
||||
try {
|
||||
Db::name('SystemQueue')->where(['id' => $item['id']])->update(['status' => '2', 'start_at' => date('Y-m-d H:i:s')]);
|
||||
$this->cmd = "{$this->bin} xqueue:_work {$item['id']}";
|
||||
$this->cmd = "{$this->bin} xtask:_work {$item['id']}";
|
||||
if ($this->checkProcess()) {
|
||||
throw new Exception("该任务{$item['id']}的处理子进程已经存在");
|
||||
throw new Exception("处理任务的子进程已经存在 --> [{$item['id']}] {$item['title']}");
|
||||
} else {
|
||||
$this->createProcess();
|
||||
$output->info("创建任务{$item['id']}的处理子进程成功");
|
||||
$output->info("创建处理任务的子进程成功 --> [{$item['id']}] {$item['title']}");
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
Db::name('SystemQueue')->where(['id' => $item['id']])->update(['status' => '4', 'desc' => $e->getMessage()]);
|
||||
$output->error("创建任务{$item['id']}的处理进程失败,{$e->getMessage()}");
|
||||
$output->error("创建处理任务的子进程失败 --> [{$item['id']}] {$item['title']},{$e->getMessage()}");
|
||||
}
|
||||
}
|
||||
sleep(3);
|
||||
|
@ -31,7 +31,7 @@ class Query extends Task
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('xqueue:query')->setDescription('查询正在执行的所有任务进程');
|
||||
$this->setName('xtask:query')->setDescription('查询正在执行的所有任务进程');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -42,7 +42,7 @@ class Query extends Task
|
||||
*/
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
$this->cmd = "{$this->bin} xqueue:";
|
||||
$this->cmd = "{$this->bin} xtask:";
|
||||
foreach ($this->queryProcess() as $item) {
|
||||
$output->writeln("{$item['pid']}\t'{$item['cmd']}'");
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ class Start extends Task
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('xqueue:start')->setDescription('创建异步任务监听守护主进程');
|
||||
$this->setName('xtask:start')->setDescription('创建异步任务监听守护主进程');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -42,7 +42,7 @@ class Start extends Task
|
||||
*/
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
$this->cmd = "{$this->bin} xqueue:listen";
|
||||
$this->cmd = "{$this->bin} xtask:listen";
|
||||
if (($pid = $this->checkProcess()) > 0) {
|
||||
$output->info("异步任务监听主进程{$pid}已经启动!");
|
||||
} else {
|
||||
|
@ -31,7 +31,7 @@ class State extends Task
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('xqueue:state')->setDescription('查看异步任务监听主进程状态');
|
||||
$this->setName('xtask:state')->setDescription('查看异步任务监听主进程状态');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -41,7 +41,7 @@ class State extends Task
|
||||
*/
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
$this->cmd = "{$this->bin} xqueue:listen";
|
||||
$this->cmd = "{$this->bin} xtask:listen";
|
||||
if (($pid = $this->checkProcess()) > 0) {
|
||||
$output->info("异步任务监听主进程{$pid}正在运行...");
|
||||
} else {
|
||||
|
@ -32,7 +32,7 @@ class Stop extends Task
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('xqueue:stop')->setDescription('平滑停止异步任务所有的进程');
|
||||
$this->setName('xtask:stop')->setDescription('平滑停止异步任务所有的进程');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -42,7 +42,7 @@ class Stop extends Task
|
||||
*/
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
$this->cmd = "{$this->bin} xqueue:";
|
||||
$this->cmd = "{$this->bin} xtask:";
|
||||
if (count($processList = $this->queryProcess()) < 1) {
|
||||
$output->writeln("没有需要结束的任务进程哦!");
|
||||
} else foreach ($processList as $item) {
|
||||
|
@ -49,7 +49,7 @@ class Work extends Task
|
||||
protected function configure()
|
||||
{
|
||||
// 执行任务配置
|
||||
$this->setName('xqueue:_work')->setDescription('启动执行单个指定任务子进程');
|
||||
$this->setName('xtask:_work')->setDescription('启动执行单个指定任务子进程');
|
||||
$this->addArgument('id', Argument::OPTIONAL, '指定任务ID');
|
||||
}
|
||||
|
||||
|
@ -1,130 +0,0 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
// | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | 官方网站: http://demo.thinkadmin.top
|
||||
// +----------------------------------------------------------------------
|
||||
// | 开源协议 ( https://mit-license.org )
|
||||
// +----------------------------------------------------------------------
|
||||
// | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
|
||||
// | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\admin\service;
|
||||
|
||||
use think\Db;
|
||||
|
||||
/**
|
||||
* 任务管理器
|
||||
* Class QueueService
|
||||
* @package app\admin\service
|
||||
*/
|
||||
class QueueService
|
||||
{
|
||||
/**
|
||||
* 待处理
|
||||
*/
|
||||
const STATUS_PEND = 1;
|
||||
|
||||
/**
|
||||
* 处理中
|
||||
*/
|
||||
const STATUS_PROC = 2;
|
||||
|
||||
/**
|
||||
* 处理完成
|
||||
*/
|
||||
const STATUS_COMP = 3;
|
||||
|
||||
/**
|
||||
* 处理失败
|
||||
*/
|
||||
const STATUS_FAIL = 4;
|
||||
|
||||
/**
|
||||
* 创建任务并记录日志
|
||||
* @param string $title 任务名称
|
||||
* @param string $uri 任务命令
|
||||
* @param integer $later 延时时间
|
||||
* @param array $data 任务附加数据
|
||||
* @param integer $double 任务多开
|
||||
* @param string $desc 任务描述
|
||||
* @throws \think\Exception
|
||||
*/
|
||||
public static function add($title, $uri, $later, array $data, $double = 1, $desc = '')
|
||||
{
|
||||
if (empty($double) && self::exists($title)) {
|
||||
throw new \think\Exception('该任务已经创建,请耐心等待处理完成!');
|
||||
}
|
||||
$jobId = Db::name('SystemJobsLog')->insertGetId([
|
||||
'title' => $title, 'later' => $later, 'uri' => $uri, 'double' => intval($double),
|
||||
'data' => json_encode($data, 256), 'desc' => $desc, 'status_at' => date('Y-m-d H:i:s'),
|
||||
]);
|
||||
$data['_job_id_'] = $jobId;
|
||||
$data['_job_title_'] = $title;
|
||||
\think\Queue::later($later, $uri, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新任务状态
|
||||
* @param integer $jobId
|
||||
* @param integer $status
|
||||
* @param string $statusDesc
|
||||
* @return boolean
|
||||
* @throws \think\Exception
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
public static function status($jobId, $status = self::STATUS_PEND, $statusDesc = '')
|
||||
{
|
||||
$result = Db::name('SystemJobsLog')->where(['id' => $jobId])->update([
|
||||
'status' => $status, 'status_desc' => $statusDesc, 'status_at' => date('Y-m-d H:i:s'),
|
||||
]);
|
||||
return $result !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查任务是否存在
|
||||
* @param string $title
|
||||
* @return boolean
|
||||
*/
|
||||
public static function exists($title)
|
||||
{
|
||||
$where = [['title', 'eq', $title], ['status', 'in', [1, 2]]];
|
||||
return Db::name('SystemJobsLog')->where($where)->count() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务数据
|
||||
* @param integer $jobId
|
||||
* @return array|null
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
public static function get($jobId)
|
||||
{
|
||||
return Db::name('SystemJobsLog')->where(['id' => $jobId])->find();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除任务数据
|
||||
* @param integer $jobId
|
||||
* @return boolean
|
||||
* @throws \think\Exception
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
public static function del($jobId)
|
||||
{
|
||||
$where = [['id', 'eq', $jobId], ['status', 'in', [1, 3, 4]]];
|
||||
if (Db::name('SystemJobsLog')->where($where)->delete() > 0) {
|
||||
Db::name('SystemJobs')->whereLike('payload', '%"_job_id_":"' . $jobId . '"%')->delete();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -67,26 +67,33 @@ if (!function_exists('sysoplog')) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('addQueue')) {
|
||||
if (!function_exists('sysqueue')) {
|
||||
/**
|
||||
* 创建异步处理任务
|
||||
* @param string $title 任务名称
|
||||
* @param string $uri 任务执行内容
|
||||
* @param array $data 任务绑定数据
|
||||
* @param integer $time 延时执行时间
|
||||
* @param string $loade 执行内容
|
||||
* @param integer $later 延时执行时间
|
||||
* @param array $data 任务附加数据
|
||||
* @param integer $double 任务多开
|
||||
* @return boolean
|
||||
* @throws \think\Exception
|
||||
*/
|
||||
function addQueue($title, $uri, $data = [], $time = 0)
|
||||
function sysqueue($title, $loade, $later = 0, $data = [], $double = 1)
|
||||
{
|
||||
$map = [['title', 'eq', $title], ['status', 'in', [1, 2]]];
|
||||
if (empty($double) && Db::name('SystemQueue')->where($map)->count() > 0) {
|
||||
throw new \think\Exception('该任务已经创建,请耐心等待处理完成!');
|
||||
}
|
||||
$result = Db::name('SystemQueue')->insert([
|
||||
'title' => $title, 'preload' => $uri,
|
||||
'title' => $title, 'preload' => $loade,
|
||||
'data' => json_encode($data, JSON_UNESCAPED_UNICODE),
|
||||
'time' => $time > 0 ? time() + $time : time(),
|
||||
'time' => $later > 0 ? time() + $later : time(), 'double' => intval($double),
|
||||
]);
|
||||
return $result !== false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!function_exists('local_image')) {
|
||||
/**
|
||||
* 下载远程文件到本地
|
||||
|
@ -32,14 +32,12 @@
|
||||
<input class="list-check-box" value='{$vo.id}' type='checkbox'>
|
||||
</td>
|
||||
<td class='text-left nowrap'>
|
||||
任务名称:{$vo.title}
|
||||
<br>
|
||||
任务指令:{$vo.uri}
|
||||
任务名称:{$vo.title}<br>
|
||||
<span class="color-desc">任务指令:{$vo.preload}</span>
|
||||
</td>
|
||||
<td class='text-left nowrap'>
|
||||
创建时间:{$vo.create_at|format_datetime|raw}
|
||||
<br>
|
||||
跟进时间:{$vo.status_at|format_datetime|raw}
|
||||
创建时间:{$vo.create_at|format_datetime|raw}<br>
|
||||
跟进时间:{$vo.end_at|format_datetime|raw}
|
||||
</td>
|
||||
<td class='text-left nowrap'>
|
||||
任务状态:{eq name='vo.double' value='1'}
|
||||
|
@ -21,16 +21,7 @@
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">任务指令</label>
|
||||
<div class="layui-input-inline">
|
||||
<select class="layui-select" name="uri" lay-search>
|
||||
<option value="">-- 全部指令 --</option>
|
||||
{foreach $uris as $uri}
|
||||
<!--{eq name='Think.get.uri' value='$uri'}-->
|
||||
<option selected value="{$uri}">{$uri}</option>
|
||||
<!--{else}-->
|
||||
<option value="{$uri}">{$uri}</option>
|
||||
<!--{/eq}-->
|
||||
{/foreach}
|
||||
</select>
|
||||
<input name="preload" value="{$Think.get.preload|default=''}" placeholder="请输入任务指令" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item layui-inline">
|
||||
@ -56,7 +47,7 @@
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">跟进时间</label>
|
||||
<div class="layui-input-inline">
|
||||
<input data-date-range name="status_at" value="{$Think.get.status_at|default=''}" placeholder="请选择跟进时间" class="layui-input">
|
||||
<input data-date-range name="end_at" value="{$Think.get.end_at|default=''}" placeholder="请选择跟进时间" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item layui-inline">
|
||||
|
@ -34,6 +34,6 @@ class Index extends Controller
|
||||
|
||||
public function test()
|
||||
{
|
||||
addQueue('同步粉丝记录', 'xfans:list');
|
||||
sysqueue('同步粉丝记录', 'xfans:list');
|
||||
}
|
||||
}
|
||||
|
@ -16,8 +16,8 @@
|
||||
namespace app\service\controller;
|
||||
|
||||
use app\admin\service\QueueService;
|
||||
use app\service\service\WechatService;
|
||||
use app\service\queue\WechatQueue;
|
||||
use app\service\service\WechatService;
|
||||
use library\Controller;
|
||||
use think\Db;
|
||||
use think\exception\HttpResponseException;
|
||||
@ -141,7 +141,7 @@ class Fans extends Controller
|
||||
{
|
||||
try {
|
||||
sysoplog('微信管理', "创建微信[{$this->appid}]粉丝同步任务");
|
||||
QueueService::add("同步[{$this->appid}]粉丝列表", WechatQueue::URI, 0, ['appid' => $this->appid], 0);
|
||||
sysqueue("同步[{$this->appid}]粉丝列表", WechatQueue::URI, 0, ['appid' => $this->appid], 0);
|
||||
$this->success('创建同步粉丝任务成功,需要时间来完成。<br>请到 系统管理 > 任务管理 查看执行进度!');
|
||||
} catch (HttpResponseException $exception) {
|
||||
throw $exception;
|
||||
|
@ -15,16 +15,18 @@
|
||||
|
||||
namespace app\service\queue;
|
||||
|
||||
use app\admin\queue\JobsQueue;
|
||||
use app\admin\queue\Queue;
|
||||
use app\service\service\WechatService;
|
||||
use app\wechat\service\FansService;
|
||||
use think\console\Input;
|
||||
use think\console\Output;
|
||||
use think\Db;
|
||||
|
||||
/**
|
||||
* Class Jobs
|
||||
* @package app\wechat
|
||||
*/
|
||||
class WechatQueue extends JobsQueue
|
||||
class WechatQueue extends Queue
|
||||
{
|
||||
/**
|
||||
* 当前任务URI
|
||||
@ -39,43 +41,44 @@ class WechatQueue extends JobsQueue
|
||||
|
||||
/**
|
||||
* 执行任务
|
||||
* @return boolean
|
||||
* @param Input $input
|
||||
* @param Output $output
|
||||
* @param array $data
|
||||
* @throws \WeChat\Exceptions\InvalidResponseException
|
||||
* @throws \WeChat\Exceptions\LocalCacheException
|
||||
* @throws \think\Exception
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
public function execute()
|
||||
public function execute(Input $input, Output $output, array $data)
|
||||
{
|
||||
try {
|
||||
$this->appid = $this->data['appid'];
|
||||
$wechat = WechatService::WeChatUser($this->appid);
|
||||
$next = ''; // 获取远程粉丝
|
||||
$this->output->writeln('Start synchronizing fans from the Wechat server');
|
||||
while (is_array($result = $wechat->getUserList($next)) && !empty($result['data']['openid'])) {
|
||||
foreach (array_chunk($result['data']['openid'], 100) as $chunk)
|
||||
if (is_array($list = $wechat->getBatchUserInfo($chunk)) && !empty($list['user_info_list']))
|
||||
foreach ($list['user_info_list'] as $user) FansService::set($user, $this->appid);
|
||||
if (in_array($result['next_openid'], $result['data']['openid'])) break;
|
||||
$next = $result['next_openid'];
|
||||
|
||||
$this->appid = $data['appid'];
|
||||
$wechat = WechatService::WeChatUser($this->appid);
|
||||
$next = ''; // 获取远程粉丝
|
||||
$output->writeln('Start synchronizing fans from the Wechat server');
|
||||
while (is_array($result = $wechat->getUserList($next)) && !empty($result['data']['openid'])) {
|
||||
foreach (array_chunk($result['data']['openid'], 100) as $chunk)
|
||||
if (is_array($list = $wechat->getBatchUserInfo($chunk)) && !empty($list['user_info_list']))
|
||||
foreach ($list['user_info_list'] as $user) FansService::set($user, $this->appid);
|
||||
if (in_array($result['next_openid'], $result['data']['openid'])) break;
|
||||
$next = $result['next_openid'];
|
||||
}
|
||||
$next = ''; // 同步粉丝黑名单
|
||||
$output->writeln('Start synchronizing black from the Wechat server');
|
||||
while (is_array($result = $wechat->getBlackList($next)) && !empty($result['data']['openid'])) {
|
||||
foreach (array_chunk($result['data']['openid'], 100) as $chunk) {
|
||||
$where = [['is_black', 'eq', '0'], ['openid', 'in', $chunk]];
|
||||
Db::name('WechatFans')->where($where)->update(['is_black' => '1']);
|
||||
}
|
||||
$next = ''; // 同步粉丝黑名单
|
||||
$this->output->writeln('Start synchronizing black from the Wechat server');
|
||||
while (is_array($result = $wechat->getBlackList($next)) && !empty($result['data']['openid'])) {
|
||||
foreach (array_chunk($result['data']['openid'], 100) as $chunk) {
|
||||
$where = [['is_black', 'eq', '0'], ['openid', 'in', $chunk]];
|
||||
Db::name('WechatFans')->where($where)->update(['is_black' => '1']);
|
||||
}
|
||||
if (in_array($result['next_openid'], $result['data']['openid'])) break;
|
||||
$next = $result['next_openid'];
|
||||
}
|
||||
// 同步粉丝标签列表
|
||||
$this->output->writeln('Start synchronizing tags from the Wechat server');
|
||||
if (is_array($list = WechatService::WeChatTags($this->appid)->getTags()) && !empty($list['tags'])) {
|
||||
foreach ($list['tags'] as &$tag) $tag['appid'] = $this->appid;
|
||||
Db::name('WechatFansTags')->where('1=1')->delete();
|
||||
Db::name('WechatFansTags')->insertAll($list['tags']);
|
||||
}
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
$this->statusDesc = $e->getMessage();
|
||||
return false;
|
||||
if (in_array($result['next_openid'], $result['data']['openid'])) break;
|
||||
$next = $result['next_openid'];
|
||||
}
|
||||
// 同步粉丝标签列表
|
||||
$output->writeln('Start synchronizing tags from the Wechat server');
|
||||
if (is_array($list = WechatService::WeChatTags($this->appid)->getTags()) && !empty($list['tags'])) {
|
||||
foreach ($list['tags'] as &$tag) $tag['appid'] = $this->appid;
|
||||
Db::name('WechatFansTags')->where('1=1')->delete();
|
||||
Db::name('WechatFansTags')->insertAll($list['tags']);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,7 +117,7 @@ class Fans extends Controller
|
||||
try {
|
||||
$this->appid = WechatService::getAppid();
|
||||
sysoplog('微信管理', "创建微信[{$this->appid}]粉丝同步任务");
|
||||
QueueService::add("同步[{$this->appid}]粉丝列表", WechatQueue::URI, 0, ['appid' => $this->appid], 0);
|
||||
sysqueue("同步[{$this->appid}]粉丝列表", WechatQueue::URI, 0, ['appid' => $this->appid], 0);
|
||||
$this->success('创建同步粉丝任务成功,需要时间来完成。<br>请到 系统管理 > 任务管理 查看执行进度!');
|
||||
} catch (HttpResponseException $exception) {
|
||||
throw $exception;
|
||||
|
@ -15,16 +15,18 @@
|
||||
|
||||
namespace app\wechat\queue;
|
||||
|
||||
use app\admin\queue\JobsQueue;
|
||||
use app\admin\queue\Queue;
|
||||
use app\wechat\service\FansService;
|
||||
use app\wechat\service\WechatService;
|
||||
use think\console\Input;
|
||||
use think\console\Output;
|
||||
use think\Db;
|
||||
|
||||
/**
|
||||
* Class Jobs
|
||||
* @package app\wechat
|
||||
*/
|
||||
class WechatQueue extends JobsQueue
|
||||
class WechatQueue extends Queue
|
||||
{
|
||||
/**
|
||||
* 当前任务URI
|
||||
@ -33,43 +35,44 @@ class WechatQueue extends JobsQueue
|
||||
|
||||
/**
|
||||
* 执行任务
|
||||
* @param Input $input
|
||||
* @param Output $output
|
||||
* @param array $data
|
||||
* @return boolean
|
||||
* @throws \WeChat\Exceptions\InvalidResponseException
|
||||
* @throws \WeChat\Exceptions\LocalCacheException
|
||||
* @throws \think\Exception
|
||||
* @throws \think\exception\PDOException
|
||||
*/
|
||||
public function execute()
|
||||
public function execute(Input $input, Output $output, array $data)
|
||||
{
|
||||
try {
|
||||
$appid = WechatService::getAppid();
|
||||
$wechat = WechatService::WeChatUser();
|
||||
$next = ''; // 获取远程粉丝
|
||||
$this->output->writeln('Start synchronizing fans from the Wechat server');
|
||||
while (is_array($result = $wechat->getUserList($next)) && !empty($result['data']['openid'])) {
|
||||
foreach (array_chunk($result['data']['openid'], 100) as $chunk)
|
||||
if (is_array($list = $wechat->getBatchUserInfo($chunk)) && !empty($list['user_info_list']))
|
||||
foreach ($list['user_info_list'] as $user) FansService::set($user, $appid);
|
||||
if (in_array($result['next_openid'], $result['data']['openid'])) break;
|
||||
$next = $result['next_openid'];
|
||||
$appid = WechatService::getAppid();
|
||||
$wechat = WechatService::WeChatUser();
|
||||
$next = ''; // 获取远程粉丝
|
||||
$output->writeln('Start synchronizing fans from the Wechat server');
|
||||
while (is_array($result = $wechat->getUserList($next)) && !empty($result['data']['openid'])) {
|
||||
foreach (array_chunk($result['data']['openid'], 100) as $chunk)
|
||||
if (is_array($list = $wechat->getBatchUserInfo($chunk)) && !empty($list['user_info_list']))
|
||||
foreach ($list['user_info_list'] as $user) FansService::set($user, $appid);
|
||||
if (in_array($result['next_openid'], $result['data']['openid'])) break;
|
||||
$next = $result['next_openid'];
|
||||
}
|
||||
$next = ''; // 同步粉丝黑名单
|
||||
$output->writeln('Start synchronizing black from the Wechat server');
|
||||
while (is_array($result = $wechat->getBlackList($next)) && !empty($result['data']['openid'])) {
|
||||
foreach (array_chunk($result['data']['openid'], 100) as $chunk) {
|
||||
$where = [['is_black', 'eq', '0'], ['openid', 'in', $chunk]];
|
||||
Db::name('WechatFans')->where($where)->update(['is_black' => '1']);
|
||||
}
|
||||
$next = ''; // 同步粉丝黑名单
|
||||
$this->output->writeln('Start synchronizing black from the Wechat server');
|
||||
while (is_array($result = $wechat->getBlackList($next)) && !empty($result['data']['openid'])) {
|
||||
foreach (array_chunk($result['data']['openid'], 100) as $chunk) {
|
||||
$where = [['is_black', 'eq', '0'], ['openid', 'in', $chunk]];
|
||||
Db::name('WechatFans')->where($where)->update(['is_black' => '1']);
|
||||
}
|
||||
if (in_array($result['next_openid'], $result['data']['openid'])) break;
|
||||
$next = $result['next_openid'];
|
||||
}
|
||||
// 同步粉丝标签列表
|
||||
$this->output->writeln('Start synchronizing tags from the Wechat server');
|
||||
if (is_array($list = WechatService::WeChatTags()->getTags()) && !empty($list['tags'])) {
|
||||
foreach ($list['tags'] as &$tag) $tag['appid'] = $appid;
|
||||
Db::name('WechatFansTags')->where('1=1')->delete();
|
||||
Db::name('WechatFansTags')->insertAll($list['tags']);
|
||||
}
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
$this->statusDesc = $e->getMessage();
|
||||
return false;
|
||||
if (in_array($result['next_openid'], $result['data']['openid'])) break;
|
||||
$next = $result['next_openid'];
|
||||
}
|
||||
// 同步粉丝标签列表
|
||||
$output->writeln('Start synchronizing tags from the Wechat server');
|
||||
if (is_array($list = WechatService::WeChatTags()->getTags()) && !empty($list['tags'])) {
|
||||
foreach ($list['tags'] as &$tag) $tag['appid'] = $appid;
|
||||
Db::name('WechatFansTags')->where('1=1')->delete();
|
||||
Db::name('WechatFansTags')->insertAll($list['tags']);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,6 @@
|
||||
"endroid/qr-code": "^1.9",
|
||||
"topthink/framework": "5.1.*",
|
||||
"zoujingli/ip2region": "^1.0",
|
||||
"topthink/think-queue": "^2.0",
|
||||
"zoujingli/think-library": "5.1.*-dev",
|
||||
"zoujingli/weopen-developer": "dev-master"
|
||||
},
|
||||
|
2
vendor/autoload.php
vendored
2
vendor/autoload.php
vendored
@ -4,4 +4,4 @@
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit8d685cd2c09b7504d228a429250f6ce9::getLoader();
|
||||
return ComposerAutoloaderInitfd27f3866754b364531a2883ef29b843::getLoader();
|
||||
|
25
vendor/composer/autoload_classmap.php
vendored
25
vendor/composer/autoload_classmap.php
vendored
@ -212,33 +212,8 @@ return array(
|
||||
'library\\tools\\Http' => $vendorDir . '/zoujingli/think-library/src/tools/Http.php',
|
||||
'library\\tools\\Node' => $vendorDir . '/zoujingli/think-library/src/tools/Node.php',
|
||||
'library\\tools\\Options' => $vendorDir . '/zoujingli/think-library/src/tools/Options.php',
|
||||
'think\\Collection' => $vendorDir . '/topthink/think-helper/src/Collection.php',
|
||||
'think\\Queue' => $vendorDir . '/topthink/think-queue/src/Queue.php',
|
||||
'think\\composer\\Plugin' => $vendorDir . '/topthink/think-installer/src/Plugin.php',
|
||||
'think\\composer\\ThinkExtend' => $vendorDir . '/topthink/think-installer/src/ThinkExtend.php',
|
||||
'think\\composer\\ThinkFramework' => $vendorDir . '/topthink/think-installer/src/ThinkFramework.php',
|
||||
'think\\composer\\ThinkTesting' => $vendorDir . '/topthink/think-installer/src/ThinkTesting.php',
|
||||
'think\\contract\\Arrayable' => $vendorDir . '/topthink/think-helper/src/contract/Arrayable.php',
|
||||
'think\\contract\\Jsonable' => $vendorDir . '/topthink/think-helper/src/contract/Jsonable.php',
|
||||
'think\\helper\\Arr' => $vendorDir . '/topthink/think-helper/src/helper/Arr.php',
|
||||
'think\\helper\\Str' => $vendorDir . '/topthink/think-helper/src/helper/Str.php',
|
||||
'think\\queue\\CallQueuedHandler' => $vendorDir . '/topthink/think-queue/src/queue/CallQueuedHandler.php',
|
||||
'think\\queue\\Connector' => $vendorDir . '/topthink/think-queue/src/queue/Connector.php',
|
||||
'think\\queue\\Job' => $vendorDir . '/topthink/think-queue/src/queue/Job.php',
|
||||
'think\\queue\\Listener' => $vendorDir . '/topthink/think-queue/src/queue/Listener.php',
|
||||
'think\\queue\\Queueable' => $vendorDir . '/topthink/think-queue/src/queue/Queueable.php',
|
||||
'think\\queue\\ShouldQueue' => $vendorDir . '/topthink/think-queue/src/queue/ShouldQueue.php',
|
||||
'think\\queue\\Worker' => $vendorDir . '/topthink/think-queue/src/queue/Worker.php',
|
||||
'think\\queue\\command\\Listen' => $vendorDir . '/topthink/think-queue/src/queue/command/Listen.php',
|
||||
'think\\queue\\command\\Restart' => $vendorDir . '/topthink/think-queue/src/queue/command/Restart.php',
|
||||
'think\\queue\\command\\Subscribe' => $vendorDir . '/topthink/think-queue/src/queue/command/Subscribe.php',
|
||||
'think\\queue\\command\\Work' => $vendorDir . '/topthink/think-queue/src/queue/command/Work.php',
|
||||
'think\\queue\\connector\\Database' => $vendorDir . '/topthink/think-queue/src/queue/connector/Database.php',
|
||||
'think\\queue\\connector\\Redis' => $vendorDir . '/topthink/think-queue/src/queue/connector/Redis.php',
|
||||
'think\\queue\\connector\\Sync' => $vendorDir . '/topthink/think-queue/src/queue/connector/Sync.php',
|
||||
'think\\queue\\connector\\Topthink' => $vendorDir . '/topthink/think-queue/src/queue/connector/Topthink.php',
|
||||
'think\\queue\\job\\Database' => $vendorDir . '/topthink/think-queue/src/queue/job/Database.php',
|
||||
'think\\queue\\job\\Redis' => $vendorDir . '/topthink/think-queue/src/queue/job/Redis.php',
|
||||
'think\\queue\\job\\Sync' => $vendorDir . '/topthink/think-queue/src/queue/job/Sync.php',
|
||||
'think\\queue\\job\\Topthink' => $vendorDir . '/topthink/think-queue/src/queue/job/Topthink.php',
|
||||
);
|
||||
|
2
vendor/composer/autoload_files.php
vendored
2
vendor/composer/autoload_files.php
vendored
@ -7,7 +7,5 @@ $baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'841780ea2e1d6545ea3a253239d59c05' => $vendorDir . '/qiniu/php-sdk/src/Qiniu/functions.php',
|
||||
'9b552a3cc426e3287cc811caefa3cf53' => $vendorDir . '/topthink/think-helper/src/helper.php',
|
||||
'cc56288302d9df745d97c934d6a6e5f0' => $vendorDir . '/topthink/think-queue/src/common.php',
|
||||
'8dafcc6956460bc297e00381fed53e11' => $vendorDir . '/zoujingli/think-library/src/common.php',
|
||||
);
|
||||
|
1
vendor/composer/autoload_psr4.php
vendored
1
vendor/composer/autoload_psr4.php
vendored
@ -7,7 +7,6 @@ $baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'think\\composer\\' => array($vendorDir . '/topthink/think-installer/src'),
|
||||
'think\\' => array($vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-queue/src'),
|
||||
'library\\' => array($vendorDir . '/zoujingli/think-library/src'),
|
||||
'WePay\\' => array($vendorDir . '/zoujingli/wechat-developer/WePay'),
|
||||
'WeOpen\\' => array($vendorDir . '/zoujingli/weopen-developer/WeOpen'),
|
||||
|
14
vendor/composer/autoload_real.php
vendored
14
vendor/composer/autoload_real.php
vendored
@ -2,7 +2,7 @@
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInit8d685cd2c09b7504d228a429250f6ce9
|
||||
class ComposerAutoloaderInitfd27f3866754b364531a2883ef29b843
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
@ -19,15 +19,15 @@ class ComposerAutoloaderInit8d685cd2c09b7504d228a429250f6ce9
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit8d685cd2c09b7504d228a429250f6ce9', 'loadClassLoader'), true, true);
|
||||
spl_autoload_register(array('ComposerAutoloaderInitfd27f3866754b364531a2883ef29b843', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit8d685cd2c09b7504d228a429250f6ce9', 'loadClassLoader'));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInitfd27f3866754b364531a2883ef29b843', '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\ComposerStaticInit8d685cd2c09b7504d228a429250f6ce9::getInitializer($loader));
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInitfd27f3866754b364531a2883ef29b843::getInitializer($loader));
|
||||
} else {
|
||||
$map = require __DIR__ . '/autoload_namespaces.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
@ -48,19 +48,19 @@ class ComposerAutoloaderInit8d685cd2c09b7504d228a429250f6ce9
|
||||
$loader->register(true);
|
||||
|
||||
if ($useStaticLoader) {
|
||||
$includeFiles = Composer\Autoload\ComposerStaticInit8d685cd2c09b7504d228a429250f6ce9::$files;
|
||||
$includeFiles = Composer\Autoload\ComposerStaticInitfd27f3866754b364531a2883ef29b843::$files;
|
||||
} else {
|
||||
$includeFiles = require __DIR__ . '/autoload_files.php';
|
||||
}
|
||||
foreach ($includeFiles as $fileIdentifier => $file) {
|
||||
composerRequire8d685cd2c09b7504d228a429250f6ce9($fileIdentifier, $file);
|
||||
composerRequirefd27f3866754b364531a2883ef29b843($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
|
||||
function composerRequire8d685cd2c09b7504d228a429250f6ce9($fileIdentifier, $file)
|
||||
function composerRequirefd27f3866754b364531a2883ef29b843($fileIdentifier, $file)
|
||||
{
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
require $file;
|
||||
|
41
vendor/composer/autoload_static.php
vendored
41
vendor/composer/autoload_static.php
vendored
@ -4,12 +4,10 @@
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInit8d685cd2c09b7504d228a429250f6ce9
|
||||
class ComposerStaticInitfd27f3866754b364531a2883ef29b843
|
||||
{
|
||||
public static $files = array (
|
||||
'841780ea2e1d6545ea3a253239d59c05' => __DIR__ . '/..' . '/qiniu/php-sdk/src/Qiniu/functions.php',
|
||||
'9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php',
|
||||
'cc56288302d9df745d97c934d6a6e5f0' => __DIR__ . '/..' . '/topthink/think-queue/src/common.php',
|
||||
'8dafcc6956460bc297e00381fed53e11' => __DIR__ . '/..' . '/zoujingli/think-library/src/common.php',
|
||||
);
|
||||
|
||||
@ -17,7 +15,6 @@ class ComposerStaticInit8d685cd2c09b7504d228a429250f6ce9
|
||||
't' =>
|
||||
array (
|
||||
'think\\composer\\' => 15,
|
||||
'think\\' => 6,
|
||||
),
|
||||
'l' =>
|
||||
array (
|
||||
@ -57,11 +54,6 @@ class ComposerStaticInit8d685cd2c09b7504d228a429250f6ce9
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/topthink/think-installer/src',
|
||||
),
|
||||
'think\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/topthink/think-helper/src',
|
||||
1 => __DIR__ . '/..' . '/topthink/think-queue/src',
|
||||
),
|
||||
'library\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/zoujingli/think-library/src',
|
||||
@ -313,43 +305,18 @@ class ComposerStaticInit8d685cd2c09b7504d228a429250f6ce9
|
||||
'library\\tools\\Http' => __DIR__ . '/..' . '/zoujingli/think-library/src/tools/Http.php',
|
||||
'library\\tools\\Node' => __DIR__ . '/..' . '/zoujingli/think-library/src/tools/Node.php',
|
||||
'library\\tools\\Options' => __DIR__ . '/..' . '/zoujingli/think-library/src/tools/Options.php',
|
||||
'think\\Collection' => __DIR__ . '/..' . '/topthink/think-helper/src/Collection.php',
|
||||
'think\\Queue' => __DIR__ . '/..' . '/topthink/think-queue/src/Queue.php',
|
||||
'think\\composer\\Plugin' => __DIR__ . '/..' . '/topthink/think-installer/src/Plugin.php',
|
||||
'think\\composer\\ThinkExtend' => __DIR__ . '/..' . '/topthink/think-installer/src/ThinkExtend.php',
|
||||
'think\\composer\\ThinkFramework' => __DIR__ . '/..' . '/topthink/think-installer/src/ThinkFramework.php',
|
||||
'think\\composer\\ThinkTesting' => __DIR__ . '/..' . '/topthink/think-installer/src/ThinkTesting.php',
|
||||
'think\\contract\\Arrayable' => __DIR__ . '/..' . '/topthink/think-helper/src/contract/Arrayable.php',
|
||||
'think\\contract\\Jsonable' => __DIR__ . '/..' . '/topthink/think-helper/src/contract/Jsonable.php',
|
||||
'think\\helper\\Arr' => __DIR__ . '/..' . '/topthink/think-helper/src/helper/Arr.php',
|
||||
'think\\helper\\Str' => __DIR__ . '/..' . '/topthink/think-helper/src/helper/Str.php',
|
||||
'think\\queue\\CallQueuedHandler' => __DIR__ . '/..' . '/topthink/think-queue/src/queue/CallQueuedHandler.php',
|
||||
'think\\queue\\Connector' => __DIR__ . '/..' . '/topthink/think-queue/src/queue/Connector.php',
|
||||
'think\\queue\\Job' => __DIR__ . '/..' . '/topthink/think-queue/src/queue/Job.php',
|
||||
'think\\queue\\Listener' => __DIR__ . '/..' . '/topthink/think-queue/src/queue/Listener.php',
|
||||
'think\\queue\\Queueable' => __DIR__ . '/..' . '/topthink/think-queue/src/queue/Queueable.php',
|
||||
'think\\queue\\ShouldQueue' => __DIR__ . '/..' . '/topthink/think-queue/src/queue/ShouldQueue.php',
|
||||
'think\\queue\\Worker' => __DIR__ . '/..' . '/topthink/think-queue/src/queue/Worker.php',
|
||||
'think\\queue\\command\\Listen' => __DIR__ . '/..' . '/topthink/think-queue/src/queue/command/Listen.php',
|
||||
'think\\queue\\command\\Restart' => __DIR__ . '/..' . '/topthink/think-queue/src/queue/command/Restart.php',
|
||||
'think\\queue\\command\\Subscribe' => __DIR__ . '/..' . '/topthink/think-queue/src/queue/command/Subscribe.php',
|
||||
'think\\queue\\command\\Work' => __DIR__ . '/..' . '/topthink/think-queue/src/queue/command/Work.php',
|
||||
'think\\queue\\connector\\Database' => __DIR__ . '/..' . '/topthink/think-queue/src/queue/connector/Database.php',
|
||||
'think\\queue\\connector\\Redis' => __DIR__ . '/..' . '/topthink/think-queue/src/queue/connector/Redis.php',
|
||||
'think\\queue\\connector\\Sync' => __DIR__ . '/..' . '/topthink/think-queue/src/queue/connector/Sync.php',
|
||||
'think\\queue\\connector\\Topthink' => __DIR__ . '/..' . '/topthink/think-queue/src/queue/connector/Topthink.php',
|
||||
'think\\queue\\job\\Database' => __DIR__ . '/..' . '/topthink/think-queue/src/queue/job/Database.php',
|
||||
'think\\queue\\job\\Redis' => __DIR__ . '/..' . '/topthink/think-queue/src/queue/job/Redis.php',
|
||||
'think\\queue\\job\\Sync' => __DIR__ . '/..' . '/topthink/think-queue/src/queue/job/Sync.php',
|
||||
'think\\queue\\job\\Topthink' => __DIR__ . '/..' . '/topthink/think-queue/src/queue/job/Topthink.php',
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit8d685cd2c09b7504d228a429250f6ce9::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit8d685cd2c09b7504d228a429250f6ce9::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInit8d685cd2c09b7504d228a429250f6ce9::$classMap;
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInitfd27f3866754b364531a2883ef29b843::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInitfd27f3866754b364531a2883ef29b843::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInitfd27f3866754b364531a2883ef29b843::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
|
109
vendor/composer/installed.json
vendored
109
vendor/composer/installed.json
vendored
@ -296,53 +296,6 @@
|
||||
"thinkphp"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "topthink/think-helper",
|
||||
"version": "v3.1.2",
|
||||
"version_normalized": "3.1.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/top-think/think-helper.git",
|
||||
"reference": "a629c4271fdf3d7e7c6d89089791417cb4796a2c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/top-think/think-helper/zipball/a629c4271fdf3d7e7c6d89089791417cb4796a2c",
|
||||
"reference": "a629c4271fdf3d7e7c6d89089791417cb4796a2c",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1.0"
|
||||
},
|
||||
"time": "2019-07-11T04:35:03+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"think\\": "src"
|
||||
},
|
||||
"files": [
|
||||
"src/helper.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "yunwuxin",
|
||||
"email": "448901948@qq.com"
|
||||
}
|
||||
],
|
||||
"description": "The ThinkPHP6 Helper Package"
|
||||
},
|
||||
{
|
||||
"name": "topthink/think-installer",
|
||||
"version": "v2.0.0",
|
||||
@ -392,60 +345,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "topthink/think-queue",
|
||||
"version": "v2.0.4",
|
||||
"version_normalized": "2.0.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/top-think/think-queue.git",
|
||||
"reference": "d9b8f38c7af8ad770257b0d7db711ce8b12a6969"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/top-think/think-queue/zipball/d9b8f38c7af8ad770257b0d7db711ce8b12a6969",
|
||||
"reference": "d9b8f38c7af8ad770257b0d7db711ce8b12a6969",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"topthink/framework": "5.1.*",
|
||||
"topthink/think-helper": ">=1.0.4",
|
||||
"topthink/think-installer": "^2.0"
|
||||
},
|
||||
"time": "2018-05-11T06:55:55+00:00",
|
||||
"type": "think-extend",
|
||||
"extra": {
|
||||
"think-config": {
|
||||
"queue": "src/config.php"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"think\\": "src"
|
||||
},
|
||||
"files": [
|
||||
"src/common.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "yunwuxin",
|
||||
"email": "448901948@qq.com"
|
||||
}
|
||||
],
|
||||
"description": "The ThinkPHP5 Queue Package"
|
||||
},
|
||||
{
|
||||
"name": "zoujingli/ip2region",
|
||||
"version": "v1.0.6",
|
||||
@ -502,12 +401,12 @@
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/zoujingli/ThinkLibrary.git",
|
||||
"reference": "68e0145bebbe0c0982a5c91d6811d2e49e04d012"
|
||||
"reference": "b848dda3a548f8d976c200e2a8e1f6872f68fc4f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/zoujingli/ThinkLibrary/zipball/68e0145bebbe0c0982a5c91d6811d2e49e04d012",
|
||||
"reference": "68e0145bebbe0c0982a5c91d6811d2e49e04d012",
|
||||
"url": "https://api.github.com/repos/zoujingli/ThinkLibrary/zipball/b848dda3a548f8d976c200e2a8e1f6872f68fc4f",
|
||||
"reference": "b848dda3a548f8d976c200e2a8e1f6872f68fc4f",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
@ -526,7 +425,7 @@
|
||||
"qiniu/php-sdk": "^7.2",
|
||||
"topthink/framework": "5.1.*"
|
||||
},
|
||||
"time": "2019-08-13T10:38:27+00:00",
|
||||
"time": "2019-08-14T02:05:30+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
|
3
vendor/topthink/think-helper/.gitignore
vendored
3
vendor/topthink/think-helper/.gitignore
vendored
@ -1,3 +0,0 @@
|
||||
/vendor/
|
||||
/.idea/
|
||||
composer.lock
|
201
vendor/topthink/think-helper/LICENSE
vendored
201
vendor/topthink/think-helper/LICENSE
vendored
@ -1,201 +0,0 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
33
vendor/topthink/think-helper/README.md
vendored
33
vendor/topthink/think-helper/README.md
vendored
@ -1,33 +0,0 @@
|
||||
# thinkphp6 常用的一些扩展类库
|
||||
|
||||
基于PHP7.1+
|
||||
|
||||
> 以下类库都在`\\think\\helper`命名空间下
|
||||
|
||||
## Str
|
||||
|
||||
> 字符串操作
|
||||
|
||||
```
|
||||
// 检查字符串中是否包含某些字符串
|
||||
Str::contains($haystack, $needles)
|
||||
|
||||
// 检查字符串是否以某些字符串结尾
|
||||
Str::endsWith($haystack, $needles)
|
||||
|
||||
// 获取指定长度的随机字母数字组合的字符串
|
||||
Str::random($length = 16)
|
||||
|
||||
// 字符串转小写
|
||||
Str::lower($value)
|
||||
|
||||
// 字符串转大写
|
||||
Str::upper($value)
|
||||
|
||||
// 获取字符串的长度
|
||||
Str::length($value)
|
||||
|
||||
// 截取字符串
|
||||
Str::substr($string, $start, $length = null)
|
||||
|
||||
```
|
22
vendor/topthink/think-helper/composer.json
vendored
22
vendor/topthink/think-helper/composer.json
vendored
@ -1,22 +0,0 @@
|
||||
{
|
||||
"name": "topthink/think-helper",
|
||||
"description": "The ThinkPHP6 Helper Package",
|
||||
"license": "Apache-2.0",
|
||||
"authors": [
|
||||
{
|
||||
"name": "yunwuxin",
|
||||
"email": "448901948@qq.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"think\\": "src"
|
||||
},
|
||||
"files": [
|
||||
"src/helper.php"
|
||||
]
|
||||
}
|
||||
}
|
651
vendor/topthink/think-helper/src/Collection.php
vendored
651
vendor/topthink/think-helper/src/Collection.php
vendored
@ -1,651 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: zhangyajun <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace think;
|
||||
|
||||
use ArrayAccess;
|
||||
use ArrayIterator;
|
||||
use Countable;
|
||||
use IteratorAggregate;
|
||||
use JsonSerializable;
|
||||
use think\contract\Arrayable;
|
||||
use think\contract\Jsonable;
|
||||
use think\helper\Arr;
|
||||
|
||||
/**
|
||||
* 数据集管理类
|
||||
*/
|
||||
class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable, Arrayable, Jsonable
|
||||
{
|
||||
/**
|
||||
* 数据集数据
|
||||
* @var array
|
||||
*/
|
||||
protected $items = [];
|
||||
|
||||
public function __construct($items = [])
|
||||
{
|
||||
$this->items = $this->convertToArray($items);
|
||||
}
|
||||
|
||||
public static function make($items = [])
|
||||
{
|
||||
return new static($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为空
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmpty(): bool
|
||||
{
|
||||
return empty($this->items);
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
return array_map(function ($value) {
|
||||
return $value instanceof Arrayable ? $value->toArray() : $value;
|
||||
}, $this->items);
|
||||
}
|
||||
|
||||
public function all(): array
|
||||
{
|
||||
return $this->items;
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并数组
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $items 数据
|
||||
* @return static
|
||||
*/
|
||||
public function merge($items)
|
||||
{
|
||||
return new static(array_merge($this->items, $this->convertToArray($items)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 按指定键整理数据
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $items 数据
|
||||
* @param string $indexKey 键名
|
||||
* @return array
|
||||
*/
|
||||
public function dictionary($items = null, string &$indexKey = null)
|
||||
{
|
||||
if ($items instanceof self) {
|
||||
$items = $items->all();
|
||||
}
|
||||
|
||||
$items = is_null($items) ? $this->items : $items;
|
||||
|
||||
if ($items && empty($indexKey)) {
|
||||
$indexKey = is_array($items[0]) ? 'id' : $items[0]->getPk();
|
||||
}
|
||||
|
||||
if (isset($indexKey) && is_string($indexKey)) {
|
||||
return array_column($items, null, $indexKey);
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较数组,返回差集
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $items 数据
|
||||
* @param string $indexKey 指定比较的键名
|
||||
* @return static
|
||||
*/
|
||||
public function diff($items, string $indexKey = null)
|
||||
{
|
||||
if ($this->isEmpty() || is_scalar($this->items[0])) {
|
||||
return new static(array_diff($this->items, $this->convertToArray($items)));
|
||||
}
|
||||
|
||||
$diff = [];
|
||||
$dictionary = $this->dictionary($items, $indexKey);
|
||||
|
||||
if (is_string($indexKey)) {
|
||||
foreach ($this->items as $item) {
|
||||
if (!isset($dictionary[$item[$indexKey]])) {
|
||||
$diff[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new static($diff);
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较数组,返回交集
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $items 数据
|
||||
* @param string $indexKey 指定比较的键名
|
||||
* @return static
|
||||
*/
|
||||
public function intersect($items, string $indexKey = null)
|
||||
{
|
||||
if ($this->isEmpty() || is_scalar($this->items[0])) {
|
||||
return new static(array_diff($this->items, $this->convertToArray($items)));
|
||||
}
|
||||
|
||||
$intersect = [];
|
||||
$dictionary = $this->dictionary($items, $indexKey);
|
||||
|
||||
if (is_string($indexKey)) {
|
||||
foreach ($this->items as $item) {
|
||||
if (isset($dictionary[$item[$indexKey]])) {
|
||||
$intersect[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new static($intersect);
|
||||
}
|
||||
|
||||
/**
|
||||
* 交换数组中的键和值
|
||||
*
|
||||
* @access public
|
||||
* @return static
|
||||
*/
|
||||
public function flip()
|
||||
{
|
||||
return new static(array_flip($this->items));
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回数组中所有的键名
|
||||
*
|
||||
* @access public
|
||||
* @return static
|
||||
*/
|
||||
public function keys()
|
||||
{
|
||||
return new static(array_keys($this->items));
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回数组中所有的值组成的新 Collection 实例
|
||||
* @access public
|
||||
* @return static
|
||||
*/
|
||||
public function values()
|
||||
{
|
||||
return new static(array_values($this->items));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数组的最后一个元素(出栈)
|
||||
*
|
||||
* @access public
|
||||
* @return mixed
|
||||
*/
|
||||
public function pop()
|
||||
{
|
||||
return array_pop($this->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过使用用户自定义函数,以字符串返回数组
|
||||
*
|
||||
* @access public
|
||||
* @param callable $callback 调用方法
|
||||
* @param mixed $initial
|
||||
* @return mixed
|
||||
*/
|
||||
public function reduce(callable $callback, $initial = null)
|
||||
{
|
||||
return array_reduce($this->items, $callback, $initial);
|
||||
}
|
||||
|
||||
/**
|
||||
* 以相反的顺序返回数组。
|
||||
*
|
||||
* @access public
|
||||
* @return static
|
||||
*/
|
||||
public function reverse()
|
||||
{
|
||||
return new static(array_reverse($this->items));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数组中首个元素,并返回被删除元素的值
|
||||
*
|
||||
* @access public
|
||||
* @return mixed
|
||||
*/
|
||||
public function shift()
|
||||
{
|
||||
return array_shift($this->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在数组结尾插入一个元素
|
||||
* @access public
|
||||
* @param mixed $value 元素
|
||||
* @param string $key KEY
|
||||
* @return void
|
||||
*/
|
||||
public function push($value, string $key = null): void
|
||||
{
|
||||
if (is_null($key)) {
|
||||
$this->items[] = $value;
|
||||
} else {
|
||||
$this->items[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 把一个数组分割为新的数组块.
|
||||
*
|
||||
* @access public
|
||||
* @param int $size 块大小
|
||||
* @param bool $preserveKeys
|
||||
* @return static
|
||||
*/
|
||||
public function chunk(int $size, bool $preserveKeys = false)
|
||||
{
|
||||
$chunks = [];
|
||||
|
||||
foreach (array_chunk($this->items, $size, $preserveKeys) as $chunk) {
|
||||
$chunks[] = new static($chunk);
|
||||
}
|
||||
|
||||
return new static($chunks);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在数组开头插入一个元素
|
||||
* @access public
|
||||
* @param mixed $value 元素
|
||||
* @param string $key KEY
|
||||
* @return void
|
||||
*/
|
||||
public function unshift($value, string $key = null): void
|
||||
{
|
||||
if (is_null($key)) {
|
||||
array_unshift($this->items, $value);
|
||||
} else {
|
||||
$this->items = [$key => $value] + $this->items;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 给每个元素执行个回调
|
||||
*
|
||||
* @access public
|
||||
* @param callable $callback 回调
|
||||
* @return $this
|
||||
*/
|
||||
public function each(callable $callback)
|
||||
{
|
||||
foreach ($this->items as $key => $item) {
|
||||
$result = $callback($item, $key);
|
||||
|
||||
if (false === $result) {
|
||||
break;
|
||||
} elseif (!is_object($item)) {
|
||||
$this->items[$key] = $result;
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用回调函数处理数组中的元素
|
||||
* @access public
|
||||
* @param callable|null $callback 回调
|
||||
* @return static
|
||||
*/
|
||||
public function map(callable $callback)
|
||||
{
|
||||
return new static(array_map($callback, $this->items));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用回调函数过滤数组中的元素
|
||||
* @access public
|
||||
* @param callable|null $callback 回调
|
||||
* @return static
|
||||
*/
|
||||
public function filter(callable $callback = null)
|
||||
{
|
||||
if ($callback) {
|
||||
return new static(array_filter($this->items, $callback));
|
||||
}
|
||||
|
||||
return new static(array_filter($this->items));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字段条件过滤数组中的元素
|
||||
* @access public
|
||||
* @param string $field 字段名
|
||||
* @param mixed $operator 操作符
|
||||
* @param mixed $value 数据
|
||||
* @return static
|
||||
*/
|
||||
public function where(string $field, $operator, $value = null)
|
||||
{
|
||||
if (is_null($value)) {
|
||||
$value = $operator;
|
||||
$operator = '=';
|
||||
}
|
||||
|
||||
return $this->filter(function ($data) use ($field, $operator, $value) {
|
||||
if (strpos($field, '.')) {
|
||||
list($field, $relation) = explode('.', $field);
|
||||
|
||||
$result = $data[$field][$relation] ?? null;
|
||||
} else {
|
||||
$result = $data[$field] ?? null;
|
||||
}
|
||||
|
||||
switch ($operator) {
|
||||
case '===':
|
||||
return $result === $value;
|
||||
case '!==':
|
||||
return $result !== $value;
|
||||
case '!=':
|
||||
case '<>':
|
||||
return $result != $value;
|
||||
case '>':
|
||||
return $result > $value;
|
||||
case '>=':
|
||||
return $result >= $value;
|
||||
case '<':
|
||||
return $result < $value;
|
||||
case '<=':
|
||||
return $result <= $value;
|
||||
case 'like':
|
||||
return is_string($result) && false !== strpos($result, $value);
|
||||
case 'not like':
|
||||
return is_string($result) && false === strpos($result, $value);
|
||||
case 'in':
|
||||
return is_scalar($result) && in_array($result, $value, true);
|
||||
case 'not in':
|
||||
return is_scalar($result) && !in_array($result, $value, true);
|
||||
case 'between':
|
||||
list($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;
|
||||
return is_scalar($result) && $result > $max || $result < $min;
|
||||
case '==':
|
||||
case '=':
|
||||
default:
|
||||
return $result == $value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* LIKE过滤
|
||||
* @access public
|
||||
* @param string $field 字段名
|
||||
* @param string $value 数据
|
||||
* @return static
|
||||
*/
|
||||
public function whereLike(string $field, string $value)
|
||||
{
|
||||
return $this->where($field, 'like', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* NOT LIKE过滤
|
||||
* @access public
|
||||
* @param string $field 字段名
|
||||
* @param string $value 数据
|
||||
* @return static
|
||||
*/
|
||||
public function whereNotLike(string $field, string $value)
|
||||
{
|
||||
return $this->where($field, 'not like', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* IN过滤
|
||||
* @access public
|
||||
* @param string $field 字段名
|
||||
* @param array $value 数据
|
||||
* @return static
|
||||
*/
|
||||
public function whereIn(string $field, array $value)
|
||||
{
|
||||
return $this->where($field, 'in', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* NOT IN过滤
|
||||
* @access public
|
||||
* @param string $field 字段名
|
||||
* @param array $value 数据
|
||||
* @return static
|
||||
*/
|
||||
public function whereNotIn(string $field, array $value)
|
||||
{
|
||||
return $this->where($field, 'not in', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* BETWEEN 过滤
|
||||
* @access public
|
||||
* @param string $field 字段名
|
||||
* @param mixed $value 数据
|
||||
* @return static
|
||||
*/
|
||||
public function whereBetween(string $field, $value)
|
||||
{
|
||||
return $this->where($field, 'between', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* NOT BETWEEN 过滤
|
||||
* @access public
|
||||
* @param string $field 字段名
|
||||
* @param mixed $value 数据
|
||||
* @return static
|
||||
*/
|
||||
public function whereNotBetween(string $field, $value)
|
||||
{
|
||||
return $this->where($field, 'not between', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回数据中指定的一列
|
||||
* @access public
|
||||
* @param string $columnKey 键名
|
||||
* @param string $indexKey 作为索引值的列
|
||||
* @return array
|
||||
*/
|
||||
public function column(string $columnKey, string $indexKey = null)
|
||||
{
|
||||
return array_column($this->items, $columnKey, $indexKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对数组排序
|
||||
*
|
||||
* @access public
|
||||
* @param callable|null $callback 回调
|
||||
* @return static
|
||||
*/
|
||||
public function sort(callable $callback = null)
|
||||
{
|
||||
$items = $this->items;
|
||||
|
||||
$callback = $callback ?: function ($a, $b) {
|
||||
return $a == $b ? 0 : (($a < $b) ? -1 : 1);
|
||||
};
|
||||
|
||||
uasort($items, $callback);
|
||||
|
||||
return new static($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定字段排序
|
||||
* @access public
|
||||
* @param string $field 排序字段
|
||||
* @param string $order 排序
|
||||
* @return $this
|
||||
*/
|
||||
public function order(string $field, string $order = null)
|
||||
{
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 将数组打乱
|
||||
*
|
||||
* @access public
|
||||
* @return static
|
||||
*/
|
||||
public function shuffle()
|
||||
{
|
||||
$items = $this->items;
|
||||
|
||||
shuffle($items);
|
||||
|
||||
return new static($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最后一个单元数据
|
||||
*
|
||||
* @access public
|
||||
* @param callable|null $callback
|
||||
* @param null $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function first(callable $callback = null, $default = null)
|
||||
{
|
||||
return Arr::first($this->items, $callback, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取第一个单元数据
|
||||
*
|
||||
* @access public
|
||||
* @param callable|null $callback
|
||||
* @param null $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function last(callable $callback = null, $default = null)
|
||||
{
|
||||
return Arr::last($this->items, $callback, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* 截取数组
|
||||
*
|
||||
* @access public
|
||||
* @param int $offset 起始位置
|
||||
* @param int $length 截取长度
|
||||
* @param bool $preserveKeys preserveKeys
|
||||
* @return static
|
||||
*/
|
||||
public function slice(int $offset, int $length = null, bool $preserveKeys = false)
|
||||
{
|
||||
return new static(array_slice($this->items, $offset, $length, $preserveKeys));
|
||||
}
|
||||
|
||||
// ArrayAccess
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return array_key_exists($offset, $this->items);
|
||||
}
|
||||
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->items[$offset];
|
||||
}
|
||||
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
if (is_null($offset)) {
|
||||
$this->items[] = $value;
|
||||
} else {
|
||||
$this->items[$offset] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->items[$offset]);
|
||||
}
|
||||
|
||||
//Countable
|
||||
public function count()
|
||||
{
|
||||
return count($this->items);
|
||||
}
|
||||
|
||||
//IteratorAggregate
|
||||
public function getIterator()
|
||||
{
|
||||
return new ArrayIterator($this->items);
|
||||
}
|
||||
|
||||
//JsonSerializable
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换当前数据集为JSON字符串
|
||||
* @access public
|
||||
* @param integer $options json参数
|
||||
* @return string
|
||||
*/
|
||||
public function toJson(int $options = JSON_UNESCAPED_UNICODE): string
|
||||
{
|
||||
return json_encode($this->toArray(), $options);
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->toJson();
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换成数组
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $items 数据
|
||||
* @return array
|
||||
*/
|
||||
protected function convertToArray($items): array
|
||||
{
|
||||
if ($items instanceof self) {
|
||||
return $items->all();
|
||||
}
|
||||
|
||||
return (array) $items;
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace think\contract;
|
||||
|
||||
interface Arrayable
|
||||
{
|
||||
public function toArray(): array;
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace think\contract;
|
||||
|
||||
interface Jsonable
|
||||
{
|
||||
public function toJson(int $options = JSON_UNESCAPED_UNICODE): string;
|
||||
}
|
279
vendor/topthink/think-helper/src/helper.php
vendored
279
vendor/topthink/think-helper/src/helper.php
vendored
@ -1,279 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
use think\Collection;
|
||||
use think\helper\Arr;
|
||||
|
||||
if (!function_exists('throw_if')) {
|
||||
/**
|
||||
* 按条件抛异常
|
||||
*
|
||||
* @param mixed $condition
|
||||
* @param Throwable|string $exception
|
||||
* @param array ...$parameters
|
||||
* @return mixed
|
||||
*
|
||||
* @throws Throwable
|
||||
*/
|
||||
function throw_if($condition, $exception, ...$parameters)
|
||||
{
|
||||
if ($condition) {
|
||||
throw (is_string($exception) ? new $exception(...$parameters) : $exception);
|
||||
}
|
||||
|
||||
return $condition;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('throw_unless')) {
|
||||
/**
|
||||
* 按条件抛异常
|
||||
*
|
||||
* @param mixed $condition
|
||||
* @param Throwable|string $exception
|
||||
* @param array ...$parameters
|
||||
* @return mixed
|
||||
* @throws Throwable
|
||||
*/
|
||||
function throw_unless($condition, $exception, ...$parameters)
|
||||
{
|
||||
if (!$condition) {
|
||||
throw (is_string($exception) ? new $exception(...$parameters) : $exception);
|
||||
}
|
||||
|
||||
return $condition;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('tap')) {
|
||||
/**
|
||||
* 对一个值调用给定的闭包,然后返回该值
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param callable|null $callback
|
||||
* @return mixed
|
||||
*/
|
||||
function tap($value, $callback = null)
|
||||
{
|
||||
if (is_null($callback)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
$callback($value);
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('value')) {
|
||||
/**
|
||||
* Return the default value of the given value.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
function value($value)
|
||||
{
|
||||
return $value instanceof Closure ? $value() : $value;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('collect')) {
|
||||
/**
|
||||
* Create a collection from the given value.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return Collection
|
||||
*/
|
||||
function collect($value = null)
|
||||
{
|
||||
return new Collection($value);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('data_fill')) {
|
||||
/**
|
||||
* Fill in data where it's missing.
|
||||
*
|
||||
* @param mixed $target
|
||||
* @param string|array $key
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
function data_fill(&$target, $key, $value)
|
||||
{
|
||||
return data_set($target, $key, $value, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('data_get')) {
|
||||
/**
|
||||
* Get an item from an array or object using "dot" notation.
|
||||
*
|
||||
* @param mixed $target
|
||||
* @param string|array|int $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
function data_get($target, $key, $default = null)
|
||||
{
|
||||
if (is_null($key)) {
|
||||
return $target;
|
||||
}
|
||||
|
||||
$key = is_array($key) ? $key : explode('.', $key);
|
||||
|
||||
while (!is_null($segment = array_shift($key))) {
|
||||
if ('*' === $segment) {
|
||||
if ($target instanceof Collection) {
|
||||
$target = $target->all();
|
||||
} elseif (!is_array($target)) {
|
||||
return value($default);
|
||||
}
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($target as $item) {
|
||||
$result[] = data_get($item, $key);
|
||||
}
|
||||
|
||||
return in_array('*', $key) ? Arr::collapse($result) : $result;
|
||||
}
|
||||
|
||||
if (Arr::accessible($target) && Arr::exists($target, $segment)) {
|
||||
$target = $target[$segment];
|
||||
} elseif (is_object($target) && isset($target->{$segment})) {
|
||||
$target = $target->{$segment};
|
||||
} else {
|
||||
return value($default);
|
||||
}
|
||||
}
|
||||
|
||||
return $target;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('data_set')) {
|
||||
/**
|
||||
* Set an item on an array or object using dot notation.
|
||||
*
|
||||
* @param mixed $target
|
||||
* @param string|array $key
|
||||
* @param mixed $value
|
||||
* @param bool $overwrite
|
||||
* @return mixed
|
||||
*/
|
||||
function data_set(&$target, $key, $value, $overwrite = true)
|
||||
{
|
||||
$segments = is_array($key) ? $key : explode('.', $key);
|
||||
|
||||
if (($segment = array_shift($segments)) === '*') {
|
||||
if (!Arr::accessible($target)) {
|
||||
$target = [];
|
||||
}
|
||||
|
||||
if ($segments) {
|
||||
foreach ($target as &$inner) {
|
||||
data_set($inner, $segments, $value, $overwrite);
|
||||
}
|
||||
} elseif ($overwrite) {
|
||||
foreach ($target as &$inner) {
|
||||
$inner = $value;
|
||||
}
|
||||
}
|
||||
} elseif (Arr::accessible($target)) {
|
||||
if ($segments) {
|
||||
if (!Arr::exists($target, $segment)) {
|
||||
$target[$segment] = [];
|
||||
}
|
||||
|
||||
data_set($target[$segment], $segments, $value, $overwrite);
|
||||
} elseif ($overwrite || !Arr::exists($target, $segment)) {
|
||||
$target[$segment] = $value;
|
||||
}
|
||||
} elseif (is_object($target)) {
|
||||
if ($segments) {
|
||||
if (!isset($target->{$segment})) {
|
||||
$target->{$segment} = [];
|
||||
}
|
||||
|
||||
data_set($target->{$segment}, $segments, $value, $overwrite);
|
||||
} elseif ($overwrite || !isset($target->{$segment})) {
|
||||
$target->{$segment} = $value;
|
||||
}
|
||||
} else {
|
||||
$target = [];
|
||||
|
||||
if ($segments) {
|
||||
data_set($target[$segment], $segments, $value, $overwrite);
|
||||
} elseif ($overwrite) {
|
||||
$target[$segment] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $target;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('trait_uses_recursive')) {
|
||||
/**
|
||||
* 获取一个trait里所有引用到的trait
|
||||
*
|
||||
* @param string $trait Trait
|
||||
* @return array
|
||||
*/
|
||||
function trait_uses_recursive(string $trait): array
|
||||
{
|
||||
$traits = class_uses($trait);
|
||||
foreach ($traits as $trait) {
|
||||
$traits += trait_uses_recursive($trait);
|
||||
}
|
||||
|
||||
return $traits;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('class_basename')) {
|
||||
/**
|
||||
* 获取类名(不包含命名空间)
|
||||
*
|
||||
* @param mixed $class 类名
|
||||
* @return string
|
||||
*/
|
||||
function class_basename($class): string
|
||||
{
|
||||
$class = is_object($class) ? get_class($class) : $class;
|
||||
return basename(str_replace('\\', '/', $class));
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('class_uses_recursive')) {
|
||||
/**
|
||||
*获取一个类里所有用到的trait,包括父类的
|
||||
*
|
||||
* @param mixed $class 类名
|
||||
* @return array
|
||||
*/
|
||||
function class_uses_recursive($class): array
|
||||
{
|
||||
if (is_object($class)) {
|
||||
$class = get_class($class);
|
||||
}
|
||||
|
||||
$results = [];
|
||||
$classes = array_merge([$class => $class], class_parents($class));
|
||||
foreach ($classes as $class) {
|
||||
$results += trait_uses_recursive($class);
|
||||
}
|
||||
|
||||
return array_unique($results);
|
||||
}
|
||||
}
|
634
vendor/topthink/think-helper/src/helper/Arr.php
vendored
634
vendor/topthink/think-helper/src/helper/Arr.php
vendored
@ -1,634 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\helper;
|
||||
|
||||
use ArrayAccess;
|
||||
use InvalidArgumentException;
|
||||
use think\Collection;
|
||||
|
||||
class Arr
|
||||
{
|
||||
|
||||
/**
|
||||
* Determine whether the given value is array accessible.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public static function accessible($value)
|
||||
{
|
||||
return is_array($value) || $value instanceof ArrayAccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an element to an array using "dot" notation if it doesn't exist.
|
||||
*
|
||||
* @param array $array
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return array
|
||||
*/
|
||||
public static function add($array, $key, $value)
|
||||
{
|
||||
if (is_null(static::get($array, $key))) {
|
||||
static::set($array, $key, $value);
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collapse an array of arrays into a single array.
|
||||
*
|
||||
* @param array $array
|
||||
* @return array
|
||||
*/
|
||||
public static function collapse($array)
|
||||
{
|
||||
$results = [];
|
||||
|
||||
foreach ($array as $values) {
|
||||
if ($values instanceof Collection) {
|
||||
$values = $values->all();
|
||||
} elseif (!is_array($values)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$results = array_merge($results, $values);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cross join the given arrays, returning all possible permutations.
|
||||
*
|
||||
* @param array ...$arrays
|
||||
* @return array
|
||||
*/
|
||||
public static function crossJoin(...$arrays)
|
||||
{
|
||||
$results = [[]];
|
||||
|
||||
foreach ($arrays as $index => $array) {
|
||||
$append = [];
|
||||
|
||||
foreach ($results as $product) {
|
||||
foreach ($array as $item) {
|
||||
$product[$index] = $item;
|
||||
|
||||
$append[] = $product;
|
||||
}
|
||||
}
|
||||
|
||||
$results = $append;
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Divide an array into two arrays. One with keys and the other with values.
|
||||
*
|
||||
* @param array $array
|
||||
* @return array
|
||||
*/
|
||||
public static function divide($array)
|
||||
{
|
||||
return [array_keys($array), array_values($array)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten a multi-dimensional associative array with dots.
|
||||
*
|
||||
* @param array $array
|
||||
* @param string $prepend
|
||||
* @return array
|
||||
*/
|
||||
public static function dot($array, $prepend = '')
|
||||
{
|
||||
$results = [];
|
||||
|
||||
foreach ($array as $key => $value) {
|
||||
if (is_array($value) && !empty($value)) {
|
||||
$results = array_merge($results, static::dot($value, $prepend . $key . '.'));
|
||||
} else {
|
||||
$results[$prepend . $key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the given array except for a specified array of keys.
|
||||
*
|
||||
* @param array $array
|
||||
* @param array|string $keys
|
||||
* @return array
|
||||
*/
|
||||
public static function except($array, $keys)
|
||||
{
|
||||
static::forget($array, $keys);
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given key exists in the provided array.
|
||||
*
|
||||
* @param \ArrayAccess|array $array
|
||||
* @param string|int $key
|
||||
* @return bool
|
||||
*/
|
||||
public static function exists($array, $key)
|
||||
{
|
||||
if ($array instanceof ArrayAccess) {
|
||||
return $array->offsetExists($key);
|
||||
}
|
||||
|
||||
return array_key_exists($key, $array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first element in an array passing a given truth test.
|
||||
*
|
||||
* @param array $array
|
||||
* @param callable|null $callback
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public static function first($array, callable $callback = null, $default = null)
|
||||
{
|
||||
if (is_null($callback)) {
|
||||
if (empty($array)) {
|
||||
return value($default);
|
||||
}
|
||||
|
||||
foreach ($array as $item) {
|
||||
return $item;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($array as $key => $value) {
|
||||
if (call_user_func($callback, $value, $key)) {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
return value($default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the last element in an array passing a given truth test.
|
||||
*
|
||||
* @param array $array
|
||||
* @param callable|null $callback
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public static function last($array, callable $callback = null, $default = null)
|
||||
{
|
||||
if (is_null($callback)) {
|
||||
return empty($array) ? value($default) : end($array);
|
||||
}
|
||||
|
||||
return static::first(array_reverse($array, true), $callback, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten a multi-dimensional array into a single level.
|
||||
*
|
||||
* @param array $array
|
||||
* @param int $depth
|
||||
* @return array
|
||||
*/
|
||||
public static function flatten($array, $depth = INF)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
foreach ($array as $item) {
|
||||
$item = $item instanceof Collection ? $item->all() : $item;
|
||||
|
||||
if (!is_array($item)) {
|
||||
$result[] = $item;
|
||||
} elseif ($depth === 1) {
|
||||
$result = array_merge($result, array_values($item));
|
||||
} else {
|
||||
$result = array_merge($result, static::flatten($item, $depth - 1));
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove one or many array items from a given array using "dot" notation.
|
||||
*
|
||||
* @param array $array
|
||||
* @param array|string $keys
|
||||
* @return void
|
||||
*/
|
||||
public static function forget(&$array, $keys)
|
||||
{
|
||||
$original = &$array;
|
||||
|
||||
$keys = (array) $keys;
|
||||
|
||||
if (count($keys) === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($keys as $key) {
|
||||
// if the exact key exists in the top-level, remove it
|
||||
if (static::exists($array, $key)) {
|
||||
unset($array[$key]);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$parts = explode('.', $key);
|
||||
|
||||
// clean up before each pass
|
||||
$array = &$original;
|
||||
|
||||
while (count($parts) > 1) {
|
||||
$part = array_shift($parts);
|
||||
|
||||
if (isset($array[$part]) && is_array($array[$part])) {
|
||||
$array = &$array[$part];
|
||||
} else {
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
|
||||
unset($array[array_shift($parts)]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an item from an array using "dot" notation.
|
||||
*
|
||||
* @param \ArrayAccess|array $array
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public static function get($array, $key, $default = null)
|
||||
{
|
||||
if (!static::accessible($array)) {
|
||||
return value($default);
|
||||
}
|
||||
|
||||
if (is_null($key)) {
|
||||
return $array;
|
||||
}
|
||||
|
||||
if (static::exists($array, $key)) {
|
||||
return $array[$key];
|
||||
}
|
||||
|
||||
if (strpos($key, '.') === false) {
|
||||
return $array[$key] ?? value($default);
|
||||
}
|
||||
|
||||
foreach (explode('.', $key) as $segment) {
|
||||
if (static::accessible($array) && static::exists($array, $segment)) {
|
||||
$array = $array[$segment];
|
||||
} else {
|
||||
return value($default);
|
||||
}
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an item or items exist in an array using "dot" notation.
|
||||
*
|
||||
* @param \ArrayAccess|array $array
|
||||
* @param string|array $keys
|
||||
* @return bool
|
||||
*/
|
||||
public static function has($array, $keys)
|
||||
{
|
||||
$keys = (array) $keys;
|
||||
|
||||
if (!$array || $keys === []) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$subKeyArray = $array;
|
||||
|
||||
if (static::exists($array, $key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (explode('.', $key) as $segment) {
|
||||
if (static::accessible($subKeyArray) && static::exists($subKeyArray, $segment)) {
|
||||
$subKeyArray = $subKeyArray[$segment];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if an array is associative.
|
||||
*
|
||||
* An array is "associative" if it doesn't have sequential numerical keys beginning with zero.
|
||||
*
|
||||
* @param array $array
|
||||
* @return bool
|
||||
*/
|
||||
public static function isAssoc(array $array)
|
||||
{
|
||||
$keys = array_keys($array);
|
||||
|
||||
return array_keys($keys) !== $keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a subset of the items from the given array.
|
||||
*
|
||||
* @param array $array
|
||||
* @param array|string $keys
|
||||
* @return array
|
||||
*/
|
||||
public static function only($array, $keys)
|
||||
{
|
||||
return array_intersect_key($array, array_flip((array) $keys));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pluck an array of values from an array.
|
||||
*
|
||||
* @param array $array
|
||||
* @param string|array $value
|
||||
* @param string|array|null $key
|
||||
* @return array
|
||||
*/
|
||||
public static function pluck($array, $value, $key = null)
|
||||
{
|
||||
$results = [];
|
||||
|
||||
[$value, $key] = static::explodePluckParameters($value, $key);
|
||||
|
||||
foreach ($array as $item) {
|
||||
$itemValue = data_get($item, $value);
|
||||
|
||||
// If the key is "null", we will just append the value to the array and keep
|
||||
// looping. Otherwise we will key the array using the value of the key we
|
||||
// received from the developer. Then we'll return the final array form.
|
||||
if (is_null($key)) {
|
||||
$results[] = $itemValue;
|
||||
} else {
|
||||
$itemKey = data_get($item, $key);
|
||||
|
||||
if (is_object($itemKey) && method_exists($itemKey, '__toString')) {
|
||||
$itemKey = (string) $itemKey;
|
||||
}
|
||||
|
||||
$results[$itemKey] = $itemValue;
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Explode the "value" and "key" arguments passed to "pluck".
|
||||
*
|
||||
* @param string|array $value
|
||||
* @param string|array|null $key
|
||||
* @return array
|
||||
*/
|
||||
protected static function explodePluckParameters($value, $key)
|
||||
{
|
||||
$value = is_string($value) ? explode('.', $value) : $value;
|
||||
|
||||
$key = is_null($key) || is_array($key) ? $key : explode('.', $key);
|
||||
|
||||
return [$value, $key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Push an item onto the beginning of an array.
|
||||
*
|
||||
* @param array $array
|
||||
* @param mixed $value
|
||||
* @param mixed $key
|
||||
* @return array
|
||||
*/
|
||||
public static function prepend($array, $value, $key = null)
|
||||
{
|
||||
if (is_null($key)) {
|
||||
array_unshift($array, $value);
|
||||
} else {
|
||||
$array = [$key => $value] + $array;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value from the array, and remove it.
|
||||
*
|
||||
* @param array $array
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public static function pull(&$array, $key, $default = null)
|
||||
{
|
||||
$value = static::get($array, $key, $default);
|
||||
|
||||
static::forget($array, $key);
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get one or a specified number of random values from an array.
|
||||
*
|
||||
* @param array $array
|
||||
* @param int|null $number
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public static function random($array, $number = null)
|
||||
{
|
||||
$requested = is_null($number) ? 1 : $number;
|
||||
|
||||
$count = count($array);
|
||||
|
||||
if ($requested > $count) {
|
||||
throw new InvalidArgumentException(
|
||||
"You requested {$requested} items, but there are only {$count} items available."
|
||||
);
|
||||
}
|
||||
|
||||
if (is_null($number)) {
|
||||
return $array[array_rand($array)];
|
||||
}
|
||||
|
||||
if ((int) $number === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$keys = array_rand($array, $number);
|
||||
|
||||
$results = [];
|
||||
|
||||
foreach ((array) $keys as $key) {
|
||||
$results[] = $array[$key];
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an array item to a given value using "dot" notation.
|
||||
*
|
||||
* If no key is given to the method, the entire array will be replaced.
|
||||
*
|
||||
* @param array $array
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return array
|
||||
*/
|
||||
public static function set(&$array, $key, $value)
|
||||
{
|
||||
if (is_null($key)) {
|
||||
return $array = $value;
|
||||
}
|
||||
|
||||
$keys = explode('.', $key);
|
||||
|
||||
while (count($keys) > 1) {
|
||||
$key = array_shift($keys);
|
||||
|
||||
// If the key doesn't exist at this depth, we will just create an empty array
|
||||
// to hold the next value, allowing us to create the arrays to hold final
|
||||
// values at the correct depth. Then we'll keep digging into the array.
|
||||
if (!isset($array[$key]) || !is_array($array[$key])) {
|
||||
$array[$key] = [];
|
||||
}
|
||||
|
||||
$array = &$array[$key];
|
||||
}
|
||||
|
||||
$array[array_shift($keys)] = $value;
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuffle the given array and return the result.
|
||||
*
|
||||
* @param array $array
|
||||
* @param int|null $seed
|
||||
* @return array
|
||||
*/
|
||||
public static function shuffle($array, $seed = null)
|
||||
{
|
||||
if (is_null($seed)) {
|
||||
shuffle($array);
|
||||
} else {
|
||||
srand($seed);
|
||||
|
||||
usort($array, function () {
|
||||
return rand(-1, 1);
|
||||
});
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the array using the given callback or "dot" notation.
|
||||
*
|
||||
* @param array $array
|
||||
* @param callable|string|null $callback
|
||||
* @return array
|
||||
*/
|
||||
public static function sort($array, $callback = null)
|
||||
{
|
||||
return Collection::make($array)->sort($callback)->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively sort an array by keys and values.
|
||||
*
|
||||
* @param array $array
|
||||
* @return array
|
||||
*/
|
||||
public static function sortRecursive($array)
|
||||
{
|
||||
foreach ($array as &$value) {
|
||||
if (is_array($value)) {
|
||||
$value = static::sortRecursive($value);
|
||||
}
|
||||
}
|
||||
|
||||
if (static::isAssoc($array)) {
|
||||
ksort($array);
|
||||
} else {
|
||||
sort($array);
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the array into a query string.
|
||||
*
|
||||
* @param array $array
|
||||
* @return string
|
||||
*/
|
||||
public static function query($array)
|
||||
{
|
||||
return http_build_query($array, null, '&', PHP_QUERY_RFC3986);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the array using the given callback.
|
||||
*
|
||||
* @param array $array
|
||||
* @param callable $callback
|
||||
* @return array
|
||||
*/
|
||||
public static function where($array, callable $callback)
|
||||
{
|
||||
return array_filter($array, $callback, ARRAY_FILTER_USE_BOTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the given value is not an array and not null, wrap it in one.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return array
|
||||
*/
|
||||
public static function wrap($value)
|
||||
{
|
||||
if (is_null($value)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return is_array($value) ? $value : [$value];
|
||||
}
|
||||
}
|
202
vendor/topthink/think-helper/src/helper/Str.php
vendored
202
vendor/topthink/think-helper/src/helper/Str.php
vendored
@ -1,202 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace think\helper;
|
||||
|
||||
class Str
|
||||
{
|
||||
|
||||
protected static $snakeCache = [];
|
||||
|
||||
protected static $camelCache = [];
|
||||
|
||||
protected static $studlyCache = [];
|
||||
|
||||
/**
|
||||
* 检查字符串中是否包含某些字符串
|
||||
* @param string $haystack
|
||||
* @param string|array $needles
|
||||
* @return bool
|
||||
*/
|
||||
public static function contains(string $haystack, $needles): bool
|
||||
{
|
||||
foreach ((array) $needles as $needle) {
|
||||
if ('' != $needle && mb_strpos($haystack, $needle) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查字符串是否以某些字符串结尾
|
||||
*
|
||||
* @param string $haystack
|
||||
* @param string|array $needles
|
||||
* @return bool
|
||||
*/
|
||||
public static function endsWith(string $haystack, $needles): bool
|
||||
{
|
||||
foreach ((array) $needles as $needle) {
|
||||
if ((string) $needle === static::substr($haystack, -static::length($needle))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查字符串是否以某些字符串开头
|
||||
*
|
||||
* @param string $haystack
|
||||
* @param string|array $needles
|
||||
* @return bool
|
||||
*/
|
||||
public static function startsWith(string $haystack, $needles): bool
|
||||
{
|
||||
foreach ((array) $needles as $needle) {
|
||||
if ('' != $needle && mb_strpos($haystack, $needle) === 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定长度的随机字母数字组合的字符串
|
||||
*
|
||||
* @param int $length
|
||||
* @return string
|
||||
*/
|
||||
public static function random(int $length = 16): string
|
||||
{
|
||||
$pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
|
||||
return static::substr(str_shuffle(str_repeat($pool, $length)), 0, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转小写
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public static function lower(string $value): string
|
||||
{
|
||||
return mb_strtolower($value, 'UTF-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转大写
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public static function upper(string $value): string
|
||||
{
|
||||
return mb_strtoupper($value, 'UTF-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字符串的长度
|
||||
*
|
||||
* @param string $value
|
||||
* @return int
|
||||
*/
|
||||
public static function length(string $value): string
|
||||
{
|
||||
return mb_strlen($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 截取字符串
|
||||
*
|
||||
* @param string $string
|
||||
* @param int $start
|
||||
* @param int|null $length
|
||||
* @return string
|
||||
*/
|
||||
public static function substr(string $string, int $start, int $length = null): string
|
||||
{
|
||||
return mb_substr($string, $start, $length, 'UTF-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* 驼峰转下划线
|
||||
*
|
||||
* @param string $value
|
||||
* @param string $delimiter
|
||||
* @return string
|
||||
*/
|
||||
public static function snake(string $value, string $delimiter = '_'): string
|
||||
{
|
||||
$key = $value;
|
||||
|
||||
if (isset(static::$snakeCache[$key][$delimiter])) {
|
||||
return static::$snakeCache[$key][$delimiter];
|
||||
}
|
||||
|
||||
if (!ctype_lower($value)) {
|
||||
$value = preg_replace('/\s+/u', '', $value);
|
||||
|
||||
$value = static::lower(preg_replace('/(.)(?=[A-Z])/u', '$1' . $delimiter, $value));
|
||||
}
|
||||
|
||||
return static::$snakeCache[$key][$delimiter] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下划线转驼峰(首字母小写)
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public static function camel(string $value): string
|
||||
{
|
||||
if (isset(static::$camelCache[$value])) {
|
||||
return static::$camelCache[$value];
|
||||
}
|
||||
|
||||
return static::$camelCache[$value] = lcfirst(static::studly($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* 下划线转驼峰(首字母大写)
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public static function studly(string $value): string
|
||||
{
|
||||
$key = $value;
|
||||
|
||||
if (isset(static::$studlyCache[$key])) {
|
||||
return static::$studlyCache[$key];
|
||||
}
|
||||
|
||||
$value = ucwords(str_replace(['-', '_'], ' ', $value));
|
||||
|
||||
return static::$studlyCache[$key] = str_replace(' ', '', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转为首字母大写的标题格式
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public static function title(string $value): string
|
||||
{
|
||||
return mb_convert_case($value, MB_CASE_TITLE, 'UTF-8');
|
||||
}
|
||||
}
|
4
vendor/topthink/think-queue/.gitignore
vendored
4
vendor/topthink/think-queue/.gitignore
vendored
@ -1,4 +0,0 @@
|
||||
/vendor/
|
||||
/.idea/
|
||||
/composer.lock
|
||||
/thinkphp/
|
201
vendor/topthink/think-queue/LICENSE
vendored
201
vendor/topthink/think-queue/LICENSE
vendored
@ -1,201 +0,0 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
135
vendor/topthink/think-queue/README.md
vendored
135
vendor/topthink/think-queue/README.md
vendored
@ -1,135 +0,0 @@
|
||||
# think-queue for ThinkPHP5.1
|
||||
|
||||
## 安装
|
||||
|
||||
> composer require topthink/think-queue
|
||||
|
||||
## 配置
|
||||
|
||||
> 配置文件位于 `config/queue.php`
|
||||
|
||||
### 公共配置
|
||||
|
||||
```
|
||||
[
|
||||
'connector'=>'sync' //驱动类型,可选择 sync(默认):同步执行,database:数据库驱动,redis:Redis驱动,topthink:Topthink驱动
|
||||
//或其他自定义的完整的类名
|
||||
]
|
||||
```
|
||||
|
||||
### 驱动配置
|
||||
> 各个驱动的具体可用配置项在`think\queue\connector`目录下各个驱动类里的`options`属性中,写在上面的`queue`配置里即可覆盖
|
||||
|
||||
|
||||
## 使用 Database
|
||||
> 创建如下数据表
|
||||
|
||||
```
|
||||
CREATE TABLE `prefix_jobs` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`queue` varchar(255) NOT NULL,
|
||||
`payload` longtext NOT NULL,
|
||||
`attempts` tinyint(3) unsigned NOT NULL,
|
||||
`reserved` tinyint(3) unsigned NOT NULL,
|
||||
`reserved_at` int(10) unsigned DEFAULT NULL,
|
||||
`available_at` int(10) unsigned NOT NULL,
|
||||
`created_at` int(10) unsigned NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
```
|
||||
|
||||
## 创建任务类
|
||||
> 单模块项目推荐使用 `app\job` 作为任务类的命名空间
|
||||
> 多模块项目可用使用 `app\module\job` 作为任务类的命名空间
|
||||
> 也可以放在任意可以自动加载到的地方
|
||||
|
||||
任务类不需继承任何类,如果这个类只有一个任务,那么就只需要提供一个`fire`方法就可以了,如果有多个小任务,就写多个方法,下面发布任务的时候会有区别
|
||||
每个方法会传入两个参数 `think\queue\Job $job`(当前的任务对象) 和 `$data`(发布任务时自定义的数据)
|
||||
|
||||
还有个可选的任务失败执行的方法 `failed` 传入的参数为`$data`(发布任务时自定义的数据)
|
||||
|
||||
### 下面写两个例子
|
||||
|
||||
```
|
||||
namespace app\job;
|
||||
|
||||
use think\queue\Job;
|
||||
|
||||
class Job1{
|
||||
|
||||
public function fire(Job $job, $data){
|
||||
|
||||
//....这里执行具体的任务
|
||||
|
||||
if ($job->attempts() > 3) {
|
||||
//通过这个方法可以检查这个任务已经重试了几次了
|
||||
}
|
||||
|
||||
|
||||
//如果任务执行成功后 记得删除任务,不然这个任务会重复执行,直到达到最大重试次数后失败后,执行failed方法
|
||||
$job->delete();
|
||||
|
||||
// 也可以重新发布这个任务
|
||||
$job->release($delay); //$delay为延迟时间
|
||||
|
||||
}
|
||||
|
||||
public function failed($data){
|
||||
|
||||
// ...任务达到最大重试次数后,失败了
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
namespace app\lib\job;
|
||||
|
||||
use think\queue\Job;
|
||||
|
||||
class Job2{
|
||||
|
||||
public function task1(Job $job, $data){
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function task2(Job $job, $data){
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function failed($data){
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## 发布任务
|
||||
> `think\Queue::push($job, $data = '', $queue = null)` 和 `think\Queue::later($delay, $job, $data = '', $queue = null)` 两个方法,前者是立即执行,后者是在`$delay`秒后执行
|
||||
|
||||
`$job` 是任务名
|
||||
单模块的,且命名空间是`app\job`的,比如上面的例子一,写`Job1`类名即可
|
||||
多模块的,且命名空间是`app\module\job`的,写`model/Job1`即可
|
||||
其他的需要些完整的类名,比如上面的例子二,需要写完整的类名`app\lib\job\Job2`
|
||||
如果一个任务类里有多个小任务的话,如上面的例子二,需要用@+方法名`app\lib\job\Job2@task1`、`app\lib\job\Job2@task2`
|
||||
|
||||
`$data` 是你要传到任务里的参数
|
||||
|
||||
`$queue` 队列名,指定这个任务是在哪个队列上执行,同下面监控队列的时候指定的队列名,可不填
|
||||
|
||||
## 监听任务并执行
|
||||
|
||||
> php think queue:listen
|
||||
|
||||
> php think queue:work --daemon(不加--daemon为执行单个任务)
|
||||
|
||||
两种,具体的可选参数可以输入命令加 --help 查看
|
||||
|
||||
>可配合supervisor使用,保证进程常驻
|
30
vendor/topthink/think-queue/composer.json
vendored
30
vendor/topthink/think-queue/composer.json
vendored
@ -1,30 +0,0 @@
|
||||
{
|
||||
"name": "topthink/think-queue",
|
||||
"description": "The ThinkPHP5 Queue Package",
|
||||
"type": "think-extend",
|
||||
"authors": [
|
||||
{
|
||||
"name": "yunwuxin",
|
||||
"email": "448901948@qq.com"
|
||||
}
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"think\\": "src"
|
||||
},
|
||||
"files": [
|
||||
"src/common.php"
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"topthink/think-helper": ">=1.0.4",
|
||||
"topthink/think-installer": "^2.0",
|
||||
"topthink/framework": "5.1.*"
|
||||
},
|
||||
"extra": {
|
||||
"think-config": {
|
||||
"queue": "src/config.php"
|
||||
}
|
||||
}
|
||||
}
|
49
vendor/topthink/think-queue/src/Queue.php
vendored
49
vendor/topthink/think-queue/src/Queue.php
vendored
@ -1,49 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think;
|
||||
|
||||
use think\helper\Str;
|
||||
use think\queue\Connector;
|
||||
|
||||
/**
|
||||
* Class Queue
|
||||
* @package think\queue
|
||||
*
|
||||
* @method static push($job, $data = '', $queue = null)
|
||||
* @method static later($delay, $job, $data = '', $queue = null)
|
||||
* @method static pop($queue = null)
|
||||
* @method static marshal()
|
||||
*/
|
||||
class Queue
|
||||
{
|
||||
/** @var Connector */
|
||||
protected static $connector;
|
||||
|
||||
private static function buildConnector()
|
||||
{
|
||||
$options = \think\facade\Config::pull('queue');
|
||||
$type = !empty($options['connector']) ? $options['connector'] : 'Sync';
|
||||
|
||||
if (!isset(self::$connector)) {
|
||||
|
||||
$class = false !== strpos($type, '\\') ? $type : '\\think\\queue\\connector\\' . Str::studly($type);
|
||||
|
||||
self::$connector = new $class($options);
|
||||
}
|
||||
return self::$connector;
|
||||
}
|
||||
|
||||
public static function __callStatic($name, $arguments)
|
||||
{
|
||||
return call_user_func_array([self::buildConnector(), $name], $arguments);
|
||||
}
|
||||
}
|
36
vendor/topthink/think-queue/src/common.php
vendored
36
vendor/topthink/think-queue/src/common.php
vendored
@ -1,36 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
\think\Console::addDefaultCommands([
|
||||
"think\\queue\\command\\Work",
|
||||
"think\\queue\\command\\Restart",
|
||||
"think\\queue\\command\\Listen",
|
||||
"think\\queue\\command\\Subscribe"
|
||||
]);
|
||||
|
||||
if (!function_exists('queue')) {
|
||||
|
||||
/**
|
||||
* 添加到队列
|
||||
* @param $job
|
||||
* @param string $data
|
||||
* @param int $delay
|
||||
* @param null $queue
|
||||
*/
|
||||
function queue($job, $data = '', $delay = 0, $queue = null)
|
||||
{
|
||||
if ($delay > 0) {
|
||||
\think\Queue::later($delay, $job, $data, $queue);
|
||||
} else {
|
||||
\think\Queue::push($job, $data, $queue);
|
||||
}
|
||||
}
|
||||
}
|
14
vendor/topthink/think-queue/src/config.php
vendored
14
vendor/topthink/think-queue/src/config.php
vendored
@ -1,14 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
return [
|
||||
'connector' => 'Sync'
|
||||
];
|
@ -1,36 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\queue;
|
||||
|
||||
class CallQueuedHandler
|
||||
{
|
||||
|
||||
public function call(Job $job, array $data)
|
||||
{
|
||||
$command = unserialize($data['command']);
|
||||
|
||||
call_user_func([$command, 'handle']);
|
||||
|
||||
if (!$job->isDeletedOrReleased()) {
|
||||
$job->delete();
|
||||
}
|
||||
}
|
||||
|
||||
public function failed(array $data)
|
||||
{
|
||||
$command = unserialize($data['command']);
|
||||
|
||||
if (method_exists($command, 'failed')) {
|
||||
$command->failed();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\queue;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
abstract class Connector
|
||||
{
|
||||
protected $options = [];
|
||||
|
||||
abstract public function push($job, $data = '', $queue = null);
|
||||
|
||||
abstract public function later($delay, $job, $data = '', $queue = null);
|
||||
|
||||
abstract public function pop($queue = null);
|
||||
|
||||
public function marshal()
|
||||
{
|
||||
throw new \RuntimeException('pop queues not support for this type');
|
||||
}
|
||||
|
||||
protected function createPayload($job, $data = '', $queue = null)
|
||||
{
|
||||
if (is_object($job)) {
|
||||
$payload = json_encode([
|
||||
'job' => 'think\queue\CallQueuedHandler@call',
|
||||
'data' => [
|
||||
'commandName' => get_class($job),
|
||||
'command' => serialize(clone $job),
|
||||
],
|
||||
]);
|
||||
} else {
|
||||
$payload = json_encode($this->createPlainPayload($job, $data));
|
||||
}
|
||||
|
||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new InvalidArgumentException('Unable to create payload: ' . json_last_error_msg());
|
||||
}
|
||||
|
||||
return $payload;
|
||||
}
|
||||
|
||||
protected function createPlainPayload($job, $data)
|
||||
{
|
||||
return ['job' => $job, 'data' => $data];
|
||||
}
|
||||
|
||||
protected function setMeta($payload, $key, $value)
|
||||
{
|
||||
$payload = json_decode($payload, true);
|
||||
$payload[$key] = $value;
|
||||
$payload = json_encode($payload);
|
||||
|
||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new InvalidArgumentException('Unable to create payload: ' . json_last_error_msg());
|
||||
}
|
||||
|
||||
return $payload;
|
||||
}
|
||||
}
|
213
vendor/topthink/think-queue/src/queue/Job.php
vendored
213
vendor/topthink/think-queue/src/queue/Job.php
vendored
@ -1,213 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\queue;
|
||||
|
||||
use DateTime;
|
||||
use think\facade\Env;
|
||||
|
||||
abstract class Job
|
||||
{
|
||||
|
||||
/**
|
||||
* The job handler instance.
|
||||
* @var mixed
|
||||
*/
|
||||
protected $instance;
|
||||
|
||||
/**
|
||||
* The name of the queue the job belongs to.
|
||||
* @var string
|
||||
*/
|
||||
protected $queue;
|
||||
|
||||
/**
|
||||
* Indicates if the job has been deleted.
|
||||
* @var bool
|
||||
*/
|
||||
protected $deleted = false;
|
||||
|
||||
/**
|
||||
* Indicates if the job has been released.
|
||||
* @var bool
|
||||
*/
|
||||
protected $released = false;
|
||||
|
||||
/**
|
||||
* Fire the job.
|
||||
* @return void
|
||||
*/
|
||||
abstract public function fire();
|
||||
|
||||
/**
|
||||
* Delete the job from the queue.
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
$this->deleted = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the job has been deleted.
|
||||
* @return bool
|
||||
*/
|
||||
public function isDeleted()
|
||||
{
|
||||
return $this->deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the job back into the queue.
|
||||
* @param int $delay
|
||||
* @return void
|
||||
*/
|
||||
public function release($delay = 0)
|
||||
{
|
||||
$this->released = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the job was released back into the queue.
|
||||
* @return bool
|
||||
*/
|
||||
public function isReleased()
|
||||
{
|
||||
return $this->released;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the job has been deleted or released.
|
||||
* @return bool
|
||||
*/
|
||||
public function isDeletedOrReleased()
|
||||
{
|
||||
return $this->isDeleted() || $this->isReleased();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of times the job has been attempted.
|
||||
* @return int
|
||||
*/
|
||||
abstract public function attempts();
|
||||
|
||||
/**
|
||||
* Get the raw body string for the job.
|
||||
* @return string
|
||||
*/
|
||||
abstract public function getRawBody();
|
||||
|
||||
/**
|
||||
* Resolve and fire the job handler method.
|
||||
* @param array $payload
|
||||
* @return void
|
||||
*/
|
||||
protected function resolveAndFire(array $payload)
|
||||
{
|
||||
list($class, $method) = $this->parseJob($payload['job']);
|
||||
|
||||
$this->instance = $this->resolve($class);
|
||||
if ($this->instance) {
|
||||
$this->instance->{$method}($this, $payload['data']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the job declaration into class and method.
|
||||
* @param string $job
|
||||
* @return array
|
||||
*/
|
||||
protected function parseJob($job)
|
||||
{
|
||||
$segments = explode('@', $job);
|
||||
|
||||
return count($segments) > 1 ? $segments : [$segments[0], 'fire'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the given job handler.
|
||||
* @param string $name
|
||||
* @return mixed
|
||||
*/
|
||||
protected function resolve($name)
|
||||
{
|
||||
if (strpos($name, '\\') === false) {
|
||||
|
||||
if (strpos($name, '/') === false) {
|
||||
$module = '';
|
||||
} else {
|
||||
list($module, $name) = explode('/', $name, 2);
|
||||
}
|
||||
|
||||
$name = Env::get('app_namespace') . ($module ? '\\' . strtolower($module) : '') . '\\job\\' . $name;
|
||||
}
|
||||
if (class_exists($name)) {
|
||||
return new $name();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the failed method on the job instance.
|
||||
* @return void
|
||||
*/
|
||||
public function failed()
|
||||
{
|
||||
$payload = json_decode($this->getRawBody(), true);
|
||||
|
||||
list($class, $method) = $this->parseJob($payload['job']);
|
||||
|
||||
$this->instance = $this->resolve($class);
|
||||
if ($this->instance && method_exists($this->instance, 'failed')) {
|
||||
$this->instance->failed($payload['data']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the number of seconds with the given delay.
|
||||
* @param \DateTime|int $delay
|
||||
* @return int
|
||||
*/
|
||||
protected function getSeconds($delay)
|
||||
{
|
||||
if ($delay instanceof DateTime) {
|
||||
return max(0, $delay->getTimestamp() - $this->getTime());
|
||||
}
|
||||
|
||||
return (int) $delay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current system time.
|
||||
* @return int
|
||||
*/
|
||||
protected function getTime()
|
||||
{
|
||||
return time();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the queued job class.
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return json_decode($this->getRawBody(), true)['job'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the queue the job belongs to.
|
||||
* @return string
|
||||
*/
|
||||
public function getQueue()
|
||||
{
|
||||
return $this->queue;
|
||||
}
|
||||
}
|
164
vendor/topthink/think-queue/src/queue/Listener.php
vendored
164
vendor/topthink/think-queue/src/queue/Listener.php
vendored
@ -1,164 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\queue;
|
||||
|
||||
use Closure;
|
||||
use think\Process;
|
||||
|
||||
class Listener
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $commandPath;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $sleep = 3;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $maxTries = 0;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $workerCommand;
|
||||
|
||||
/**
|
||||
* @var \Closure|null
|
||||
*/
|
||||
protected $outputHandler;
|
||||
|
||||
/**
|
||||
* @param string $commandPath
|
||||
*/
|
||||
public function __construct($commandPath)
|
||||
{
|
||||
$this->commandPath = $commandPath;
|
||||
$this->workerCommand =
|
||||
'"' . PHP_BINARY . '" think queue:work --queue="%s" --delay=%s --memory=%s --sleep=%s --tries=%s';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $queue
|
||||
* @param string $delay
|
||||
* @param string $memory
|
||||
* @param int $timeout
|
||||
* @return void
|
||||
*/
|
||||
public function listen($queue, $delay, $memory, $timeout = 60)
|
||||
{
|
||||
$process = $this->makeProcess($queue, $delay, $memory, $timeout);
|
||||
|
||||
while (true) {
|
||||
$this->runProcess($process, $memory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Think\Process $process
|
||||
* @param int $memory
|
||||
*/
|
||||
public function runProcess(Process $process, $memory)
|
||||
{
|
||||
$process->run(function ($type, $line) {
|
||||
$this->handleWorkerOutput($type, $line);
|
||||
});
|
||||
|
||||
if ($this->memoryExceeded($memory)) {
|
||||
$this->stop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $queue
|
||||
* @param int $delay
|
||||
* @param int $memory
|
||||
* @param int $timeout
|
||||
* @return \think\Process
|
||||
*/
|
||||
public function makeProcess($queue, $delay, $memory, $timeout)
|
||||
{
|
||||
$string = $this->workerCommand;
|
||||
$command = sprintf($string, $queue, $delay, $memory, $this->sleep, $this->maxTries);
|
||||
|
||||
return new Process($command, $this->commandPath, null, null, $timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $type
|
||||
* @param string $line
|
||||
* @return void
|
||||
*/
|
||||
protected function handleWorkerOutput($type, $line)
|
||||
{
|
||||
if (isset($this->outputHandler)) {
|
||||
call_user_func($this->outputHandler, $type, $line);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $memoryLimit
|
||||
* @return bool
|
||||
*/
|
||||
public function memoryExceeded($memoryLimit)
|
||||
{
|
||||
return (memory_get_usage() / 1024 / 1024) >= $memoryLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function stop()
|
||||
{
|
||||
die;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Closure $outputHandler
|
||||
* @return void
|
||||
*/
|
||||
public function setOutputHandler(Closure $outputHandler)
|
||||
{
|
||||
$this->outputHandler = $outputHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getSleep()
|
||||
{
|
||||
return $this->sleep;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $sleep
|
||||
* @return void
|
||||
*/
|
||||
public function setSleep($sleep)
|
||||
{
|
||||
$this->sleep = $sleep;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $tries
|
||||
* @return void
|
||||
*/
|
||||
public function setMaxTries($tries)
|
||||
{
|
||||
$this->maxTries = $tries;
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\queue;
|
||||
|
||||
trait Queueable
|
||||
{
|
||||
|
||||
/** @var string 队列名称 */
|
||||
public $queue;
|
||||
|
||||
/** @var integer 延迟时间 */
|
||||
public $delay;
|
||||
|
||||
/**
|
||||
* 设置队列名
|
||||
* @param $queue
|
||||
* @return $this
|
||||
*/
|
||||
public function queue($queue)
|
||||
{
|
||||
$this->queue = $queue;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置延迟时间
|
||||
* @param $delay
|
||||
* @return $this
|
||||
*/
|
||||
public function delay($delay)
|
||||
{
|
||||
$this->delay = $delay;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\queue;
|
||||
|
||||
interface ShouldQueue
|
||||
{
|
||||
|
||||
}
|
119
vendor/topthink/think-queue/src/queue/Worker.php
vendored
119
vendor/topthink/think-queue/src/queue/Worker.php
vendored
@ -1,119 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\queue;
|
||||
|
||||
use Exception;
|
||||
use think\facade\Hook;
|
||||
use think\Queue;
|
||||
|
||||
class Worker
|
||||
{
|
||||
|
||||
/**
|
||||
* 执行下个任务
|
||||
* @param string $queue
|
||||
* @param int $delay
|
||||
* @param int $sleep
|
||||
* @param int $maxTries
|
||||
* @return array
|
||||
*/
|
||||
public function pop($queue = null, $delay = 0, $sleep = 3, $maxTries = 0)
|
||||
{
|
||||
|
||||
$job = $this->getNextJob($queue);
|
||||
|
||||
if (!is_null($job)) {
|
||||
Hook::listen('worker_before_process', $queue);
|
||||
return $this->process($job, $maxTries, $delay);
|
||||
}
|
||||
|
||||
Hook::listen('worker_before_sleep', $queue);
|
||||
$this->sleep($sleep);
|
||||
|
||||
return ['job' => null, 'failed' => false];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下个任务
|
||||
* @param string $queue
|
||||
* @return Job
|
||||
*/
|
||||
protected function getNextJob($queue)
|
||||
{
|
||||
if (is_null($queue)) {
|
||||
return Queue::pop();
|
||||
}
|
||||
|
||||
foreach (explode(',', $queue) as $queue) {
|
||||
if (!is_null($job = Queue::pop($queue))) {
|
||||
return $job;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a given job from the queue.
|
||||
* @param \think\queue\Job $job
|
||||
* @param int $maxTries
|
||||
* @param int $delay
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function process(Job $job, $maxTries = 0, $delay = 0)
|
||||
{
|
||||
if ($maxTries > 0 && $job->attempts() > $maxTries) {
|
||||
return $this->logFailedJob($job);
|
||||
}
|
||||
|
||||
try {
|
||||
$job->fire();
|
||||
|
||||
return ['job' => $job, 'failed' => false];
|
||||
} catch (Exception $e) {
|
||||
if (!$job->isDeleted()) {
|
||||
$job->release($delay);
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a failed job into storage.
|
||||
* @param \Think\Queue\Job $job
|
||||
* @return array
|
||||
*/
|
||||
protected function logFailedJob(Job $job)
|
||||
{
|
||||
if (!$job->isDeleted()) {
|
||||
try {
|
||||
$job->delete();
|
||||
$job->failed();
|
||||
} finally {
|
||||
Hook::listen('queue_failed', $job);
|
||||
}
|
||||
}
|
||||
|
||||
return ['job' => $job, 'failed' => true];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sleep the script for a given number of seconds.
|
||||
* @param int $seconds
|
||||
* @return void
|
||||
*/
|
||||
public function sleep($seconds)
|
||||
{
|
||||
sleep($seconds);
|
||||
}
|
||||
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\queue\command;
|
||||
|
||||
use think\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
use think\queue\Listener;
|
||||
|
||||
class Listen extends Command
|
||||
{
|
||||
/** @var Listener */
|
||||
protected $listener;
|
||||
|
||||
public function configure()
|
||||
{
|
||||
$this->setName('queue:listen')
|
||||
->addOption('queue', null, Option::VALUE_OPTIONAL, 'The queue to listen on', null)
|
||||
->addOption('delay', null, Option::VALUE_OPTIONAL, 'Amount of time to delay failed jobs', 0)
|
||||
->addOption('memory', null, Option::VALUE_OPTIONAL, 'The memory limit in megabytes', 128)
|
||||
->addOption('timeout', null, Option::VALUE_OPTIONAL, 'Seconds a job may run before timing out', 60)
|
||||
->addOption('sleep', null, Option::VALUE_OPTIONAL, 'Seconds to wait before checking queue for jobs', 3)
|
||||
->addOption('tries', null, Option::VALUE_OPTIONAL, 'Number of times to attempt a job before logging it failed', 0)
|
||||
->setDescription('Listen to a given queue');
|
||||
}
|
||||
|
||||
public function initialize(Input $input, Output $output)
|
||||
{
|
||||
$this->listener = new Listener(getcwd());
|
||||
$this->listener->setSleep($input->getOption('sleep'));
|
||||
$this->listener->setMaxTries($input->getOption('tries'));
|
||||
|
||||
$this->listener->setOutputHandler(function ($type, $line) use ($output) {
|
||||
$output->write($line);
|
||||
});
|
||||
}
|
||||
|
||||
public function execute(Input $input, Output $output)
|
||||
{
|
||||
$delay = $input->getOption('delay');
|
||||
|
||||
$memory = $input->getOption('memory');
|
||||
|
||||
$timeout = $input->getOption('timeout');
|
||||
|
||||
$queue = $input->getOption('queue') ?: 'default';
|
||||
|
||||
$this->listener->listen($queue, $delay, $memory, $timeout);
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\queue\command;
|
||||
|
||||
use think\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\Output;
|
||||
use think\facade\Cache;
|
||||
|
||||
class Restart extends Command
|
||||
{
|
||||
public function configure()
|
||||
{
|
||||
$this->setName('queue:restart')->setDescription('Restart queue worker daemons after their current job');
|
||||
}
|
||||
|
||||
public function execute(Input $input, Output $output)
|
||||
{
|
||||
Cache::set('think:queue:restart', time());
|
||||
$output->writeln("<info>Broadcasting queue restart signal.</info>");
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\queue\command;
|
||||
|
||||
use think\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Argument;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
use think\facade\Url;
|
||||
use think\Queue;
|
||||
|
||||
class Subscribe extends Command
|
||||
{
|
||||
public function configure()
|
||||
{
|
||||
$this->setName('queue:subscribe')
|
||||
->setDescription('Subscribe a URL to an push queue')
|
||||
->addArgument('name', Argument::REQUIRED, 'name')
|
||||
->addArgument('url', Argument::REQUIRED, 'The URL to be subscribed.')
|
||||
->addArgument('queue', Argument::OPTIONAL, 'The URL to be subscribed.')
|
||||
->addOption('option', null, Option::VALUE_IS_ARRAY | Option::VALUE_OPTIONAL, 'the options');
|
||||
}
|
||||
|
||||
public function execute(Input $input, Output $output)
|
||||
{
|
||||
|
||||
$url = $input->getArgument('url');
|
||||
if (!preg_match('/^https?:\/\//', $url)) {
|
||||
$url = Url::build($url);
|
||||
}
|
||||
|
||||
Queue::subscribe($input->getArgument('name'), $url, $input->getArgument('queue'), $input->getOption('option'));
|
||||
|
||||
$output->write('<info>Queue subscriber added:</info> <comment>' . $input->getArgument('url') . '</comment>');
|
||||
}
|
||||
}
|
@ -1,210 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace think\queue\command;
|
||||
|
||||
use Exception;
|
||||
use think\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
use think\exception\Handle;
|
||||
use think\exception\ThrowableError;
|
||||
use think\facade\Cache;
|
||||
use think\facade\Config;
|
||||
use think\facade\Hook;
|
||||
use think\queue\Job;
|
||||
use think\queue\Worker;
|
||||
use Throwable;
|
||||
|
||||
class Work extends Command
|
||||
{
|
||||
|
||||
/**
|
||||
* The queue worker instance.
|
||||
* @var \think\queue\Worker
|
||||
*/
|
||||
protected $worker;
|
||||
|
||||
protected function initialize(Input $input, Output $output)
|
||||
{
|
||||
$this->worker = new Worker();
|
||||
}
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('queue:work')
|
||||
->addOption('queue', null, Option::VALUE_OPTIONAL, 'The queue to listen on')
|
||||
->addOption('daemon', null, Option::VALUE_NONE, 'Run the worker in daemon mode')
|
||||
->addOption('delay', null, Option::VALUE_OPTIONAL, 'Amount of time to delay failed jobs', 0)
|
||||
->addOption('force', null, Option::VALUE_NONE, 'Force the worker to run even in maintenance mode')
|
||||
->addOption('memory', null, Option::VALUE_OPTIONAL, 'The memory limit in megabytes', 128)
|
||||
->addOption('sleep', null, Option::VALUE_OPTIONAL, 'Number of seconds to sleep when no job is available', 3)
|
||||
->addOption('tries', null, Option::VALUE_OPTIONAL, 'Number of times to attempt a job before logging it failed', 0)
|
||||
->setDescription('Process the next job on a queue');
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
* @param Input $input
|
||||
* @param Output $output
|
||||
* @return int|null|void
|
||||
*/
|
||||
public function execute(Input $input, Output $output)
|
||||
{
|
||||
$queue = $input->getOption('queue');
|
||||
|
||||
$delay = $input->getOption('delay');
|
||||
|
||||
$memory = $input->getOption('memory');
|
||||
|
||||
if ($input->getOption('daemon')) {
|
||||
Hook::listen('worker_daemon_start', $queue);
|
||||
$this->daemon(
|
||||
$queue, $delay, $memory,
|
||||
$input->getOption('sleep'), $input->getOption('tries')
|
||||
);
|
||||
} else {
|
||||
$response = $this->worker->pop($queue, $delay, $input->getOption('sleep'), $input->getOption('tries'));
|
||||
$this->output($response);
|
||||
}
|
||||
}
|
||||
|
||||
protected function output($response)
|
||||
{
|
||||
if (!is_null($response['job'])) {
|
||||
/** @var Job $job */
|
||||
$job = $response['job'];
|
||||
if ($response['failed']) {
|
||||
$this->output->writeln('<error>Failed:</error> ' . $job->getName());
|
||||
} else {
|
||||
$this->output->writeln('<info>Processed:</info> ' . $job->getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动一个守护进程执行任务.
|
||||
*
|
||||
* @param string $queue
|
||||
* @param int $delay
|
||||
* @param int $memory
|
||||
* @param int $sleep
|
||||
* @param int $maxTries
|
||||
* @return array
|
||||
*/
|
||||
protected function daemon($queue = null, $delay = 0, $memory = 128, $sleep = 3, $maxTries = 0)
|
||||
{
|
||||
$lastRestart = $this->getTimestampOfLastQueueRestart();
|
||||
|
||||
while (true) {
|
||||
$this->runNextJobForDaemon(
|
||||
$queue, $delay, $sleep, $maxTries
|
||||
);
|
||||
|
||||
if ($this->memoryExceeded($memory)) {
|
||||
Hook::listen('worker_memory_exceeded', $queue);
|
||||
$this->stop();
|
||||
}
|
||||
|
||||
if ($this->queueShouldRestart($lastRestart)) {
|
||||
Hook::listen('worker_queue_restart', $queue);
|
||||
$this->stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 以守护进程的方式执行下个任务.
|
||||
*
|
||||
* @param string $queue
|
||||
* @param int $delay
|
||||
* @param int $sleep
|
||||
* @param int $maxTries
|
||||
* @return void
|
||||
*/
|
||||
protected function runNextJobForDaemon($queue, $delay, $sleep, $maxTries)
|
||||
{
|
||||
try {
|
||||
$response = $this->worker->pop($queue, $delay, $sleep, $maxTries);
|
||||
|
||||
$this->output($response);
|
||||
} catch (Exception $e) {
|
||||
$this->getExceptionHandler()->report($e);
|
||||
} catch (Throwable $e) {
|
||||
$this->getExceptionHandler()->report(new ThrowableError($e));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上次重启守护进程的时间
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
protected function getTimestampOfLastQueueRestart()
|
||||
{
|
||||
return Cache::get('think:queue:restart');
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否要重启守护进程
|
||||
*
|
||||
* @param int|null $lastRestart
|
||||
* @return bool
|
||||
*/
|
||||
protected function queueShouldRestart($lastRestart)
|
||||
{
|
||||
return $this->getTimestampOfLastQueueRestart() != $lastRestart;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查内存是否超出
|
||||
* @param int $memoryLimit
|
||||
* @return bool
|
||||
*/
|
||||
protected function memoryExceeded($memoryLimit)
|
||||
{
|
||||
return (memory_get_usage() / 1024 / 1024) >= $memoryLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取异常处理实例
|
||||
*
|
||||
* @return \think\exception\Handle
|
||||
*/
|
||||
protected function getExceptionHandler()
|
||||
{
|
||||
static $handle;
|
||||
|
||||
if (!$handle) {
|
||||
|
||||
if ($class = Config::get('exception_handle')) {
|
||||
if (class_exists($class) && is_subclass_of($class, "\\think\\exception\\Handle")) {
|
||||
$handle = new $class;
|
||||
}
|
||||
}
|
||||
if (!$handle) {
|
||||
$handle = new Handle();
|
||||
}
|
||||
}
|
||||
|
||||
return $handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止执行任务的守护进程.
|
||||
* @return void
|
||||
*/
|
||||
public function stop()
|
||||
{
|
||||
die;
|
||||
}
|
||||
|
||||
}
|
@ -1,169 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\queue\connector;
|
||||
|
||||
use think\Db;
|
||||
use think\queue\Connector;
|
||||
use think\queue\job\Database as DatabaseJob;
|
||||
|
||||
class Database extends Connector
|
||||
{
|
||||
|
||||
protected $options = [
|
||||
'expire' => 60,
|
||||
'default' => 'default',
|
||||
'table' => 'jobs'
|
||||
];
|
||||
|
||||
public function __construct(array $options)
|
||||
{
|
||||
if (!empty($options)) {
|
||||
$this->options = array_merge($this->options, $options);
|
||||
}
|
||||
}
|
||||
|
||||
public function push($job, $data = '', $queue = null)
|
||||
{
|
||||
return $this->pushToDatabase(0, $queue, $this->createPayload($job, $data));
|
||||
}
|
||||
|
||||
public function later($delay, $job, $data = '', $queue = null)
|
||||
{
|
||||
return $this->pushToDatabase($delay, $queue, $this->createPayload($job, $data));
|
||||
}
|
||||
|
||||
public function pop($queue = null)
|
||||
{
|
||||
$queue = $this->getQueue($queue);
|
||||
|
||||
if (!is_null($this->options['expire'])) {
|
||||
$this->releaseJobsThatHaveBeenReservedTooLong($queue);
|
||||
}
|
||||
|
||||
if ($job = $this->getNextAvailableJob($queue)) {
|
||||
$this->markJobAsReserved($job->id);
|
||||
|
||||
Db::commit();
|
||||
|
||||
return new DatabaseJob($this, $job, $queue);
|
||||
}
|
||||
|
||||
Db::commit();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新发布任务
|
||||
*
|
||||
* @param string $queue
|
||||
* @param \StdClass $job
|
||||
* @param int $delay
|
||||
* @return mixed
|
||||
*/
|
||||
public function release($queue, $job, $delay)
|
||||
{
|
||||
return $this->pushToDatabase($delay, $queue, $job->payload, $job->attempts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Push a raw payload to the database with a given delay.
|
||||
*
|
||||
* @param \DateTime|int $delay
|
||||
* @param string|null $queue
|
||||
* @param string $payload
|
||||
* @param int $attempts
|
||||
* @return mixed
|
||||
*/
|
||||
protected function pushToDatabase($delay, $queue, $payload, $attempts = 0)
|
||||
{
|
||||
return Db::name($this->options['table'])->insert([
|
||||
'queue' => $this->getQueue($queue),
|
||||
'payload' => $payload,
|
||||
'attempts' => $attempts,
|
||||
'reserved' => 0,
|
||||
'reserved_at' => null,
|
||||
'available_at' => time() + $delay,
|
||||
'created_at' => time(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下个有效任务
|
||||
*
|
||||
* @param string|null $queue
|
||||
* @return \StdClass|null
|
||||
*/
|
||||
protected function getNextAvailableJob($queue)
|
||||
{
|
||||
Db::startTrans();
|
||||
|
||||
$job = Db::name($this->options['table'])
|
||||
->lock(true)
|
||||
->where('queue', $this->getQueue($queue))
|
||||
->where('reserved', 0)
|
||||
->where('available_at', '<=', time())
|
||||
->order('id', 'asc')
|
||||
->find();
|
||||
|
||||
return $job ? (object) $job : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记任务正在执行.
|
||||
*
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
protected function markJobAsReserved($id)
|
||||
{
|
||||
Db::name($this->options['table'])->where('id', $id)->update([
|
||||
'reserved' => 1,
|
||||
'reserved_at' => time(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新发布超时的任务
|
||||
*
|
||||
* @param string $queue
|
||||
* @return void
|
||||
*/
|
||||
protected function releaseJobsThatHaveBeenReservedTooLong($queue)
|
||||
{
|
||||
$expired = time() - $this->options['expire'];
|
||||
|
||||
Db::name($this->options['table'])
|
||||
->where('queue', $this->getQueue($queue))
|
||||
->where('reserved', 1)
|
||||
->where('reserved_at', '<=', $expired)
|
||||
->update([
|
||||
'reserved' => 0,
|
||||
'reserved_at' => null,
|
||||
'attempts' => ['inc', 1],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除任务
|
||||
*
|
||||
* @param string $id
|
||||
* @return void
|
||||
*/
|
||||
public function deleteReserved($id)
|
||||
{
|
||||
Db::name($this->options['table'])->delete($id);
|
||||
}
|
||||
|
||||
protected function getQueue($queue)
|
||||
{
|
||||
return $queue ?: $this->options['default'];
|
||||
}
|
||||
}
|
@ -1,236 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\queue\connector;
|
||||
|
||||
use Exception;
|
||||
use think\helper\Str;
|
||||
use think\queue\Connector;
|
||||
use think\queue\job\Redis as RedisJob;
|
||||
|
||||
class Redis extends Connector
|
||||
{
|
||||
/** @var \Redis */
|
||||
protected $redis;
|
||||
|
||||
protected $options = [
|
||||
'expire' => 60,
|
||||
'default' => 'default',
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6379,
|
||||
'password' => '',
|
||||
'select' => 0,
|
||||
'timeout' => 0,
|
||||
'persistent' => false,
|
||||
];
|
||||
|
||||
public function __construct(array $options)
|
||||
{
|
||||
if (!extension_loaded('redis')) {
|
||||
throw new Exception('redis扩展未安装');
|
||||
}
|
||||
if (!empty($options)) {
|
||||
$this->options = array_merge($this->options, $options);
|
||||
}
|
||||
|
||||
$func = $this->options['persistent'] ? 'pconnect' : 'connect';
|
||||
$this->redis = new \Redis;
|
||||
$this->redis->$func($this->options['host'], $this->options['port'], $this->options['timeout']);
|
||||
|
||||
if ('' != $this->options['password']) {
|
||||
$this->redis->auth($this->options['password']);
|
||||
}
|
||||
|
||||
if (0 != $this->options['select']) {
|
||||
$this->redis->select($this->options['select']);
|
||||
}
|
||||
}
|
||||
|
||||
public function push($job, $data = '', $queue = null)
|
||||
{
|
||||
return $this->pushRaw($this->createPayload($job, $data), $queue);
|
||||
}
|
||||
|
||||
public function later($delay, $job, $data = '', $queue = null)
|
||||
{
|
||||
$payload = $this->createPayload($job, $data);
|
||||
|
||||
$this->redis->zAdd($this->getQueue($queue) . ':delayed', time() + $delay, $payload);
|
||||
}
|
||||
|
||||
public function pop($queue = null)
|
||||
{
|
||||
$original = $queue ?: $this->options['default'];
|
||||
|
||||
$queue = $this->getQueue($queue);
|
||||
|
||||
$this->migrateExpiredJobs($queue . ':delayed', $queue, false);
|
||||
|
||||
if (!is_null($this->options['expire'])) {
|
||||
$this->migrateExpiredJobs($queue . ':reserved', $queue);
|
||||
}
|
||||
|
||||
$job = $this->redis->lPop($queue);
|
||||
|
||||
if (false !== $job) {
|
||||
$this->redis->zAdd($queue . ':reserved', time() + $this->options['expire'], $job);
|
||||
|
||||
return new RedisJob($this, $job, $original);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新发布任务
|
||||
*
|
||||
* @param string $queue
|
||||
* @param string $payload
|
||||
* @param int $delay
|
||||
* @param int $attempts
|
||||
* @return void
|
||||
*/
|
||||
public function release($queue, $payload, $delay, $attempts)
|
||||
{
|
||||
$payload = $this->setMeta($payload, 'attempts', $attempts);
|
||||
|
||||
$this->redis->zAdd($this->getQueue($queue) . ':delayed', time() + $delay, $payload);
|
||||
}
|
||||
|
||||
public function pushRaw($payload, $queue = null)
|
||||
{
|
||||
$this->redis->rPush($this->getQueue($queue), $payload);
|
||||
|
||||
return json_decode($payload, true)['id'];
|
||||
}
|
||||
|
||||
protected function createPayload($job, $data = '', $queue = null)
|
||||
{
|
||||
$payload = $this->setMeta(
|
||||
parent::createPayload($job, $data), 'id', $this->getRandomId()
|
||||
);
|
||||
|
||||
return $this->setMeta($payload, 'attempts', 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除任务
|
||||
*
|
||||
* @param string $queue
|
||||
* @param string $job
|
||||
* @return void
|
||||
*/
|
||||
public function deleteReserved($queue, $job)
|
||||
{
|
||||
$this->redis->zRem($this->getQueue($queue) . ':reserved', $job);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动延迟任务
|
||||
*
|
||||
* @param string $from
|
||||
* @param string $to
|
||||
* @param bool $attempt
|
||||
*/
|
||||
public function migrateExpiredJobs($from, $to, $attempt = true)
|
||||
{
|
||||
$this->redis->watch($from);
|
||||
|
||||
$jobs = $this->getExpiredJobs(
|
||||
$from, $time = time()
|
||||
);
|
||||
if (count($jobs) > 0) {
|
||||
$this->transaction(function () use ($from, $to, $time, $jobs, $attempt) {
|
||||
$this->removeExpiredJobs($from, $time);
|
||||
$this->pushExpiredJobsOntoNewQueue($to, $jobs, $attempt);
|
||||
});
|
||||
}
|
||||
$this->redis->unwatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* redis事务
|
||||
* @param \Closure $closure
|
||||
*/
|
||||
protected function transaction(\Closure $closure)
|
||||
{
|
||||
$this->redis->multi();
|
||||
try {
|
||||
call_user_func($closure);
|
||||
if (!$this->redis->exec()) {
|
||||
$this->redis->discard();
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$this->redis->discard();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有到期任务
|
||||
*
|
||||
* @param string $from
|
||||
* @param int $time
|
||||
* @return array
|
||||
*/
|
||||
protected function getExpiredJobs($from, $time)
|
||||
{
|
||||
return $this->redis->zRangeByScore($from, '-inf', $time);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除过期任务
|
||||
*
|
||||
* @param string $from
|
||||
* @param int $time
|
||||
* @return void
|
||||
*/
|
||||
protected function removeExpiredJobs($from, $time)
|
||||
{
|
||||
$this->redis->zRemRangeByScore($from, '-inf', $time);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新发布到期任务
|
||||
*
|
||||
* @param string $to
|
||||
* @param array $jobs
|
||||
* @param boolean $attempt
|
||||
*/
|
||||
protected function pushExpiredJobsOntoNewQueue($to, $jobs, $attempt = true)
|
||||
{
|
||||
if ($attempt) {
|
||||
foreach ($jobs as &$job) {
|
||||
$attempts = json_decode($job, true)['attempts'];
|
||||
$job = $this->setMeta($job, 'attempts', $attempts + 1);
|
||||
}
|
||||
}
|
||||
call_user_func_array([$this->redis, 'rPush'], array_merge([$to], $jobs));
|
||||
}
|
||||
|
||||
/**
|
||||
* 随机id
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getRandomId()
|
||||
{
|
||||
return Str::random(32);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取队列名
|
||||
*
|
||||
* @param string|null $queue
|
||||
* @return string
|
||||
*/
|
||||
protected function getQueue($queue)
|
||||
{
|
||||
return 'queues:' . ($queue ?: $this->options['default']);
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\queue\connector;
|
||||
|
||||
use Exception;
|
||||
use think\queue\Connector;
|
||||
use think\queue\job\Sync as SyncJob;
|
||||
use Throwable;
|
||||
|
||||
class Sync extends Connector
|
||||
{
|
||||
|
||||
public function push($job, $data = '', $queue = null)
|
||||
{
|
||||
$queueJob = $this->resolveJob($this->createPayload($job, $data, $queue));
|
||||
|
||||
try {
|
||||
set_time_limit(0);
|
||||
$queueJob->fire();
|
||||
} catch (Exception $e) {
|
||||
$queueJob->failed();
|
||||
|
||||
throw $e;
|
||||
} catch (Throwable $e) {
|
||||
$queueJob->failed();
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function later($delay, $job, $data = '', $queue = null)
|
||||
{
|
||||
return $this->push($job, $data, $queue);
|
||||
}
|
||||
|
||||
public function pop($queue = null)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected function resolveJob($payload)
|
||||
{
|
||||
return new SyncJob($payload);
|
||||
}
|
||||
|
||||
}
|
@ -1,223 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\queue\connector;
|
||||
|
||||
use think\exception\HttpException;
|
||||
use think\facade\Request;
|
||||
use think\queue\Connector;
|
||||
use think\queue\job\Topthink as TopthinkJob;
|
||||
use think\Response;
|
||||
|
||||
class Topthink extends Connector
|
||||
{
|
||||
protected $options = [
|
||||
'token' => '',
|
||||
'project_id' => '',
|
||||
'protocol' => 'https',
|
||||
'host' => 'qns.topthink.com',
|
||||
'port' => 443,
|
||||
'api_version' => 1,
|
||||
'max_retries' => 3,
|
||||
'default' => 'default',
|
||||
];
|
||||
|
||||
/** @var Request */
|
||||
protected $request;
|
||||
|
||||
protected $url;
|
||||
|
||||
protected $curl = null;
|
||||
|
||||
protected $last_status;
|
||||
|
||||
protected $headers = [];
|
||||
|
||||
public function __construct(array $options)
|
||||
{
|
||||
if (!empty($options)) {
|
||||
$this->options = array_merge($this->options, $options);
|
||||
}
|
||||
|
||||
$this->url = "{$this->options['protocol']}://{$this->options['host']}:{$this->options['port']}/v{$this->options['api_version']}/";
|
||||
|
||||
$this->headers['Authorization'] = "Bearer {$this->options['token']}";
|
||||
}
|
||||
|
||||
public function push($job, $data = '', $queue = null)
|
||||
{
|
||||
return $this->pushRaw(0, $queue, $this->createPayload($job, $data));
|
||||
}
|
||||
|
||||
public function later($delay, $job, $data = '', $queue = null)
|
||||
{
|
||||
return $this->pushRaw($delay, $queue, $this->createPayload($job, $data));
|
||||
}
|
||||
|
||||
public function release($queue, $job, $delay)
|
||||
{
|
||||
return $this->pushRaw($delay, $queue, $job->payload, $job->attempts);
|
||||
}
|
||||
|
||||
public function marshal()
|
||||
{
|
||||
$job = new TopthinkJob($this, $this->marshalPushedJob(), Request::header('topthink-message-queue'));
|
||||
if (Request::header('topthink-message-status') == 'success') {
|
||||
$job->fire();
|
||||
} else {
|
||||
$job->failed();
|
||||
}
|
||||
return new Response('OK');
|
||||
}
|
||||
|
||||
public function pushRaw($delay, $queue, $payload, $attempts = 0)
|
||||
{
|
||||
$queue_name = $this->getQueue($queue);
|
||||
$queue = rawurlencode($queue_name);
|
||||
$url = "project/{$this->options['project_id']}/queue/{$queue}/message";
|
||||
$message = [
|
||||
'payload' => $payload,
|
||||
'attempts' => $attempts,
|
||||
'delay' => $delay,
|
||||
];
|
||||
|
||||
return $this->apiCall('POST', $url, $message)->id;
|
||||
}
|
||||
|
||||
public function deleteMessage($queue, $id)
|
||||
{
|
||||
$queue = rawurlencode($queue);
|
||||
$url = "project/{$this->options['project_id']}/queue/{$queue}/message/{$id}";
|
||||
return $this->apiCall('DELETE', $url);
|
||||
}
|
||||
|
||||
protected function apiCall($type, $url, $params = [])
|
||||
{
|
||||
$url = "{$this->url}$url";
|
||||
|
||||
if (null == $this->curl) {
|
||||
$this->curl = curl_init();
|
||||
}
|
||||
|
||||
switch ($type = strtoupper($type)) {
|
||||
case 'DELETE':
|
||||
curl_setopt($this->curl, CURLOPT_URL, $url);
|
||||
curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, $type);
|
||||
curl_setopt($this->curl, CURLOPT_POSTFIELDS, json_encode($params));
|
||||
break;
|
||||
case 'PUT':
|
||||
curl_setopt($this->curl, CURLOPT_URL, $url);
|
||||
curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, $type);
|
||||
curl_setopt($this->curl, CURLOPT_POSTFIELDS, json_encode($params));
|
||||
break;
|
||||
case 'POST':
|
||||
curl_setopt($this->curl, CURLOPT_URL, $url);
|
||||
curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, $type);
|
||||
curl_setopt($this->curl, CURLOPT_POST, true);
|
||||
curl_setopt($this->curl, CURLOPT_POSTFIELDS, $params);
|
||||
break;
|
||||
case 'GET':
|
||||
curl_setopt($this->curl, CURLOPT_POSTFIELDS, null);
|
||||
curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, $type);
|
||||
curl_setopt($this->curl, CURLOPT_HTTPGET, true);
|
||||
$url .= '?' . http_build_query($params);
|
||||
curl_setopt($this->curl, CURLOPT_URL, $url);
|
||||
break;
|
||||
}
|
||||
|
||||
curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
$headers = [];
|
||||
foreach ($this->headers as $k => $v) {
|
||||
if ('Connection' == $k) {
|
||||
$v = 'Close';
|
||||
}
|
||||
$headers[] = "$k: $v";
|
||||
}
|
||||
|
||||
curl_setopt($this->curl, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($this->curl, CURLOPT_CONNECTTIMEOUT, 10);
|
||||
|
||||
return $this->callWithRetries();
|
||||
}
|
||||
|
||||
protected function callWithRetries()
|
||||
{
|
||||
for ($retry = 0; $retry < $this->options['max_retries']; $retry++) {
|
||||
$out = curl_exec($this->curl);
|
||||
if (false === $out) {
|
||||
$this->reportHttpError(0, curl_error($this->curl));
|
||||
}
|
||||
$this->last_status = curl_getinfo($this->curl, CURLINFO_HTTP_CODE);
|
||||
|
||||
if ($this->last_status >= 200 && $this->last_status < 300) {
|
||||
return self::jsonDecode($out);
|
||||
} elseif ($this->last_status >= 500) {
|
||||
self::waitRandomInterval($retry);
|
||||
} else {
|
||||
$this->reportHttpError($this->last_status, $out);
|
||||
}
|
||||
}
|
||||
$this->reportHttpError($this->last_status, "Service unavailable");
|
||||
return;
|
||||
}
|
||||
|
||||
protected static function jsonDecode($response)
|
||||
{
|
||||
$data = json_decode($response);
|
||||
|
||||
$json_error = json_last_error();
|
||||
if (JSON_ERROR_NONE != $json_error) {
|
||||
throw new \RuntimeException($json_error);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected static function waitRandomInterval($retry)
|
||||
{
|
||||
$max_delay = pow(4, $retry) * 100 * 1000;
|
||||
usleep(rand(0, $max_delay));
|
||||
}
|
||||
|
||||
protected function reportHttpError($status, $text)
|
||||
{
|
||||
throw new HttpException($status, "http error: {$status} | {$text}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Marshal out the pushed job and payload.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
protected function marshalPushedJob()
|
||||
{
|
||||
return (object) [
|
||||
'id' => Request::header('topthink-message-id'),
|
||||
'payload' => Request::getContent(),
|
||||
'attempts' => Request::header('topthink-message-attempts'),
|
||||
];
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if (null != $this->curl) {
|
||||
curl_close($this->curl);
|
||||
$this->curl = null;
|
||||
}
|
||||
}
|
||||
|
||||
public function pop($queue = null)
|
||||
{
|
||||
throw new \RuntimeException('pop queues not support for this type');
|
||||
}
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
namespace think\queue\job;
|
||||
|
||||
use think\queue\Job;
|
||||
use think\queue\connector\Database as DatabaseQueue;
|
||||
|
||||
class Database extends Job
|
||||
{
|
||||
/**
|
||||
* The database queue instance.
|
||||
* @var DatabaseQueue
|
||||
*/
|
||||
protected $database;
|
||||
|
||||
/**
|
||||
* The database job payload.
|
||||
* @var Object
|
||||
*/
|
||||
protected $job;
|
||||
|
||||
public function __construct(DatabaseQueue $database, $job, $queue)
|
||||
{
|
||||
$this->job = $job;
|
||||
$this->queue = $queue;
|
||||
$this->database = $database;
|
||||
$this->job->attempts = $this->job->attempts + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行任务
|
||||
* @return void
|
||||
*/
|
||||
public function fire()
|
||||
{
|
||||
$this->resolveAndFire(json_decode($this->job->payload, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除任务
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
parent::delete();
|
||||
$this->database->deleteReserved($this->job->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新发布任务
|
||||
* @param int $delay
|
||||
* @return void
|
||||
*/
|
||||
public function release($delay = 0)
|
||||
{
|
||||
parent::release($delay);
|
||||
|
||||
$this->delete();
|
||||
|
||||
$this->database->release($this->queue, $this->job, $delay);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前任务尝试次数
|
||||
* @return int
|
||||
*/
|
||||
public function attempts()
|
||||
{
|
||||
return (int) $this->job->attempts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw body string for the job.
|
||||
* @return string
|
||||
*/
|
||||
public function getRawBody()
|
||||
{
|
||||
return $this->job->payload;
|
||||
}
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\queue\job;
|
||||
|
||||
use think\queue\Job;
|
||||
use think\queue\connector\Redis as RedisQueue;
|
||||
|
||||
class Redis extends Job
|
||||
{
|
||||
|
||||
/**
|
||||
* The redis queue instance.
|
||||
* @var RedisQueue
|
||||
*/
|
||||
protected $redis;
|
||||
|
||||
/**
|
||||
* The database job payload.
|
||||
* @var Object
|
||||
*/
|
||||
protected $job;
|
||||
|
||||
public function __construct(RedisQueue $redis, $job, $queue)
|
||||
{
|
||||
$this->job = $job;
|
||||
$this->queue = $queue;
|
||||
$this->redis = $redis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire the job.
|
||||
* @return void
|
||||
*/
|
||||
public function fire()
|
||||
{
|
||||
$this->resolveAndFire(json_decode($this->getRawBody(), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of times the job has been attempted.
|
||||
* @return int
|
||||
*/
|
||||
public function attempts()
|
||||
{
|
||||
return json_decode($this->job, true)['attempts'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw body string for the job.
|
||||
* @return string
|
||||
*/
|
||||
public function getRawBody()
|
||||
{
|
||||
return $this->job;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除任务
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
parent::delete();
|
||||
|
||||
$this->redis->deleteReserved($this->queue, $this->job);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新发布任务
|
||||
*
|
||||
* @param int $delay
|
||||
* @return void
|
||||
*/
|
||||
public function release($delay = 0)
|
||||
{
|
||||
parent::release($delay);
|
||||
|
||||
$this->delete();
|
||||
|
||||
$this->redis->release($this->queue, $this->job, $delay, $this->attempts() + 1);
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\queue\job;
|
||||
|
||||
use think\queue\Job;
|
||||
|
||||
class Sync extends Job
|
||||
{
|
||||
/**
|
||||
* The queue message data.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $payload;
|
||||
|
||||
public function __construct($payload)
|
||||
{
|
||||
$this->payload = $payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire the job.
|
||||
* @return void
|
||||
*/
|
||||
public function fire()
|
||||
{
|
||||
$this->resolveAndFire(json_decode($this->payload, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of times the job has been attempted.
|
||||
* @return int
|
||||
*/
|
||||
public function attempts()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw body string for the job.
|
||||
* @return string
|
||||
*/
|
||||
public function getRawBody()
|
||||
{
|
||||
return $this->payload;
|
||||
}
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\queue\job;
|
||||
|
||||
use think\queue\Job;
|
||||
use think\queue\connector\Topthink as TopthinkQueue;
|
||||
|
||||
class Topthink extends Job
|
||||
{
|
||||
|
||||
/**
|
||||
* The Iron queue instance.
|
||||
*
|
||||
* @var TopthinkQueue
|
||||
*/
|
||||
protected $topthink;
|
||||
|
||||
/**
|
||||
* The IronMQ message instance.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $job;
|
||||
|
||||
public function __construct(TopthinkQueue $topthink, $job, $queue)
|
||||
{
|
||||
$this->topthink = $topthink;
|
||||
$this->job = $job;
|
||||
$this->queue = $queue;
|
||||
$this->job->attempts = $this->job->attempts + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire the job.
|
||||
* @return void
|
||||
*/
|
||||
public function fire()
|
||||
{
|
||||
$this->resolveAndFire(json_decode($this->job->payload, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of times the job has been attempted.
|
||||
* @return int
|
||||
*/
|
||||
public function attempts()
|
||||
{
|
||||
return (int) $this->job->attempts;
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
parent::delete();
|
||||
|
||||
$this->topthink->deleteMessage($this->queue, $this->job->id);
|
||||
}
|
||||
|
||||
public function release($delay = 0)
|
||||
{
|
||||
parent::release($delay);
|
||||
|
||||
$this->delete();
|
||||
|
||||
$this->topthink->release($this->queue, $this->job, $delay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw body string for the job.
|
||||
* @return string
|
||||
*/
|
||||
public function getRawBody()
|
||||
{
|
||||
return $this->job->payload;
|
||||
}
|
||||
|
||||
}
|
@ -253,7 +253,7 @@ Console::addDefaultCommands([
|
||||
'library\command\task\Stop',
|
||||
'library\command\task\State',
|
||||
'library\command\task\Start',
|
||||
'library\command\task\Reset',
|
||||
// 'library\command\task\Reset',
|
||||
'library\command\sync\Admin',
|
||||
'library\command\sync\Plugs',
|
||||
'library\command\sync\Config',
|
||||
|
Loading…
x
Reference in New Issue
Block a user