Commit 7e1a11d2 authored by wangzhengwen's avatar wangzhengwen

pay

parent b204303f
......@@ -6,7 +6,7 @@ DEFAULT_TIMEZONE = Asia/Shanghai
[DATABASE]
TYPE = mysql
HOSTNAME = 192.168.4.26
HOSTNAME = 192.168.4.28
DATABASE = veitooldata
USERNAME = root
PASSWORD = root
......@@ -16,7 +16,7 @@ CHARSET = utf8
DEBUG = true
[CACHE]
DRIVER = file
DRIVER = redis
[REDIS]
HOSTNAME = 127.0.0.1
......
......@@ -2,7 +2,7 @@
/.vscode
/nbproject
*.log
.env
/.env
/runtime
/public
/addons
\ No newline at end of file
......@@ -2,8 +2,10 @@
namespace app\api\controller;
use app\api\middleware\Auth;
use app\api\service\UtilService;
use app\model\CourseTeacher;
use think\Request;
use app\Request;
use app\api\validate\CourseValidate;
use app\BaseController;
use app\model\Course as CourseModel;
......@@ -132,10 +134,7 @@ class Course extends BaseController
return $this->returnMsg('success',1,$data);
}
public function coureseStudy()
{
}
......
......@@ -136,12 +136,12 @@ class CourseProgress extends BaseController
])->find();
if (!$course) {
return $this->returnMsg('视频不存在');
return $this->returnMsg('课程不存在');
}
// 验证购买状态(1表示视频类型)
if ($course['price'] > 0 && !UtilService::checkPurchase($userId, $courseId, 1)) {
return $this->returnMsg('视频未购买', 202);
return $this->returnMsg('课程未购买', 202);
}
// 更新点击量
......
<?php
namespace app\api\controller;
use app\api\middleware\Auth;
use app\BaseController;
use think\facade\Log;
use think\facade\View;
use Yansongda\Pay\Pay;
use app\api\service\PayService;
use think\facade\Db;
use think\App;
class PayController
{
protected $middleware = [
Auth::class,
];
/**
* 创建支付订单
*/
public function create($params)
{
// $params = request()->only([
// 'order_id',
// 'order_type',
// 'pay_method',
// 'amount',
// 'user_id'
// ]);
//
// // 验证参数
// $validate = validate('Pay');
// if (!$validate->scene('create')->check($params)) {
// return json(['code' => 400, 'msg' => $validate->getError()]);
// }
// 创建支付订单
$result = PayService::createPayment(
$params['user_id'],
$params['order_id'],
$params['amount'],
$params['pay_method'],
$params['order_type'],
request()->param()
);
if (!$result['status']) {
return json(['code' => 0, 'msg' => $result['msg']]);
}
return json([
'code' => 1,
'data' => [
'payment_id' => $result['data']['payment_id'],
'order_no' => $result['data']['order_no']
]
]);
}
/**
* 发起支付宝支付
*/
public function alipay()
{
$orderNo = request()->param('order_no');
try {
// 查询支付订单
$payment = Db::name('payment')
->where('order_no', $orderNo)
->find();
if (!$payment || $payment['pay_method'] != PayService::PAY_METHOD_ALIPAY) {
throw new \Exception("支付订单不存在或支付方式不匹配");
}
// 构造支付宝订单
$order = [
'out_trade_no' => $orderNo,
'total_amount' => $payment['pay_amount'],
'subject' => $payment['order_type'] == PayService::ORDER_TYPE_COURSE ?
'课程购买' : '证书购买',
];
// 发起支付
$alipay = Pay::alipay(PayService::getPayConfig(PayService::PAY_METHOD_ALIPAY))->web($order);
return $alipay->send();
// return redirect($alipay->getTargetUrl());
} catch (\Exception $e) {
Log::error("支付创建错误: {$orderNo} - " . $e->getMessage());
return json(['code' => 500, 'msg' => $e->getMessage()]);
}
}
/**
* 发起微信支付
*/
public function wechat()
{
$orderNo = request()->param('order_no');
try {
// 查询支付订单
$payment = Db::name('payment')
->where('order_no', $orderNo)
->find();
if (!$payment || $payment['pay_method'] != PayService::PAY_METHOD_WECHAT) {
throw new \Exception("支付订单不存在或支付方式不匹配");
}
// 构造微信订单
$order = [
'out_trade_no' => $orderNo,
'description' => $payment['order_type'] == PayService::ORDER_TYPE_COURSE ?
'课程购买' : '证书购买',
'amount' => [
'total' => intval($payment['pay_amount'] * 100), // 转为分
],
];
// 发起支付
$response = Pay::wechat(PayService::getPayConfig(PayService::PAY_METHOD_WECHAT))->scan($order);
return json([
'code' => 200,
'data' => [
'code_url' => $response->code_url,
'order_no' => $orderNo
]
]);
} catch (\Exception $e) {
return json(['code' => 500, 'msg' => $e->getMessage()]);
}
}
/**
* 支付宝回调处理
*/
public function alipayNotify()
{
$alipay = Pay::alipay(PayService::getPayConfig(PayService::PAY_METHOD_ALIPAY));
try {
$data = $alipay->verify();
// 处理支付回调
$result = PayService::handlePaymentNotify($data->out_trade_no, $data->all());
if ($result) {
return $alipay->success();
} else {
return json(['code' => 500, 'msg' => '处理失败']);
}
} catch (\Exception $e) {
Log::error('支付宝回调异常: ' . $e->getMessage());
return json(['code' => 500, 'msg' => $e->getMessage()]);
}
}
/**
* 微信支付回调处理
*/
public function wechatNotify()
{
$wechat = Pay::wechat(PayService::getPayConfig(PayService::PAY_METHOD_WECHAT));
try {
$data = $wechat->verify();
// 处理支付回调
$result = PayService::handlePaymentNotify($data->out_trade_no, $data->all());
if ($result) {
return $wechat->success();
} else {
return json(['code' => 500, 'msg' => '处理失败']);
}
} catch (\Exception $e) {
Log::error('微信回调异常: ' . $e->getMessage());
return json(['code' => 500, 'msg' => $e->getMessage()]);
}
}
/**
* 查询支付状态
*/
public function query()
{
$orderNo = request()->param('order_no');
try {
$payment = Db::name('fj_payment')
->where('order_no', $orderNo)
->find();
if (!$payment) {
throw new \Exception("支付订单不存在");
}
return json([
'code' => 200,
'data' => [
'order_no' => $payment['order_no'],
'pay_status' => $payment['pay_status'],
'pay_time' => $payment['pay_time'],
'pay_amount' => $payment['pay_amount']
]
]);
} catch (\Exception $e) {
return json(['code' => 500, 'msg' => $e->getMessage()]);
}
}
}
\ No newline at end of file
......@@ -37,7 +37,9 @@ class Index extends BaseController
// 2. 获取支付相关统计数据
$paymentStats = Db::name('payment')
->where('sf_id', 'in', $courseIds)
->where('order_id', 'in', $courseIds)
// ->where('sf_id', 'in', $courseIds)
->where('order_type', 1)
->field([
'SUM(CASE WHEN pay_status = 1 THEN pay_amount ELSE 0 END) as order_money_sum',
......
......@@ -2,10 +2,14 @@
namespace app\api\controller\mine;
use app\api\controller\PayController;
use app\api\middleware\Auth;
use app\api\service\UserService;
use app\api\service\UtilService;
use app\api\validate\CourseValidate;
use app\api\validate\UserValidate;
use app\BaseController;
use app\model\Course as CourseModel;
use app\model\project\Mail;
use app\model\project\UserAccount;
use app\model\project\UserMoneyLog;
......@@ -181,5 +185,49 @@ class User extends BaseController
return $this->returnMsg('success',1,$list);
}
public function buyCourse(\think\Request $request)
{
$vo = (new CourseValidate())->goCheck(['course_id']);
if ($vo !== true) {
return $vo;
}
$data = $request->param();
$userId = $request->userId;
$course = CourseModel::where([
'id' => $data['course_id'],
'status' => 3,
'is_sell' => 1,
'is_del' => 0
])->find();
if (!$course) {
return $this->returnMsg('课程不存在');
}
if ($course['price']<=0)
{
return $this->returnMsg('免费课程无需购买');
}
// 验证购买状态(1表示视频类型)
if (UtilService::checkPurchase($userId, $data['course_id'], 1)) {
return $this->returnMsg('请勿重复购买');
}
$params = [
'order_id'=>$data['course_id'],
'order_type'=>1,
'pay_method'=>$data['pay_method'],
'amount'=>$course['price'],
'user_id'=>$userId,
];
$payController = new PayController();
return $payController->create($params);
}
}
\ No newline at end of file
<?php
namespace app\api\service;
use think\facade\Db;
use Yansongda\Pay\Pay;
use think\facade\Log;
class PayService
{
// 支付方式映射
const PAY_METHOD_ALIPAY = 1;
const PAY_METHOD_WECHAT = 2;
// 支付状态
const PAY_STATUS_UNPAID = 0;
const PAY_STATUS_SUCCESS = 1;
const PAY_STATUS_FAILED = 2;
// 订单类型
const ORDER_TYPE_COURSE = 1;
const ORDER_TYPE_CERT = 2;
/**
* 创建支付订单
* @param int $userId 用户ID
* @param int $orderId 关联订单ID
* @param float $amount 支付金额
* @param int $payMethod 支付方式
* @param int $orderType 订单类型
* @param array $reqInfo 请求参数
* @return array
*/
public static function createPayment($userId, $orderId, $amount, $payMethod, $orderType, $reqInfo = [])
{
try {
// 生成支付订单号
$orderNo = UtilService::generateCompactOrderNo($userId,'kc');
// 支付订单数据
$paymentData = [
'order_id' => $orderId,
'pay_method' => $payMethod,
'order_no' => $orderNo,
'pay_status' => self::PAY_STATUS_UNPAID,
'pay_amount' => $amount,
'order_price' => $amount,
'order_type' => $orderType,
'user_id' => $userId,
'req_info' => json_encode($reqInfo, JSON_UNESCAPED_UNICODE),
'createtime' => time(),
'updatetime' => time(),
'expire_time' => time() + 7200 // 2小时过期
];
// 写入数据库
$paymentId = Db::name('payment')->insertGetId($paymentData);
return [
'status' => true,
'data' => [
'payment_id' => $paymentId,
'order_no' => $orderNo
]
];
} catch (\Exception $e) {
Log::error('创建支付订单失败: ' . $e->getMessage());
return [
'status' => false,
'msg' => '创建支付订单失败'
];
}
}
/**
* 生成支付订单号
* @param int $payMethod 支付方式
* @return string
*/
private static function generateOrderNo($payMethod)
{
$prefix = $payMethod == self::PAY_METHOD_ALIPAY ? 'ALI' : 'WX';
return $prefix . date('YmdHis') . mt_rand(1000, 9999);
}
/**
* 处理支付回调
* @param string $orderNo 支付订单号
* @param array $notifyData 回调数据
* @return bool
*/
public static function handlePaymentNotify($orderNo, $notifyData)
{
Db::startTrans();
try {
// 查询支付订单
$payment = Db::name('fj_payment')
->where('order_no', $orderNo)
->lock(true)
->find();
if (!$payment) {
throw new \Exception("支付订单不存在: {$orderNo}");
}
// 已处理过的订单不再处理
if ($payment['pay_status'] == self::PAY_STATUS_SUCCESS) {
Db::commit();
return true;
}
// 验证金额
$amount = $payment['pay_method'] == self::PAY_METHOD_ALIPAY ?
$notifyData['total_amount'] : ($notifyData['total_fee'] / 100);
if (bccomp($amount, $payment['pay_amount'], 2) !== 0) {
throw new \Exception("金额不一致: 订单{$payment['pay_amount']}, 回调{$amount}");
}
// 更新支付状态
$updateData = [
'pay_status' => self::PAY_STATUS_SUCCESS,
'pay_time' => strtotime($notifyData['gmt_payment'] ?? date('Y-m-d H:i:s')),
'pay_info' => json_encode($notifyData, JSON_UNESCAPED_UNICODE),
'updatetime' => time()
];
$result = Db::name('fj_payment')
->where('order_no', $orderNo)
->update($updateData);
if (!$result) {
throw new \Exception("更新支付状态失败");
}
// 根据订单类型处理业务逻辑
self::handleBusinessAfterPayment($payment);
Db::commit();
return true;
} catch (\Exception $e) {
Db::rollback();
Log::error("支付回调处理失败: {$orderNo} - " . $e->getMessage());
return false;
}
}
/**
* 支付成功后处理业务逻辑
* @param array $payment 支付订单数据
*/
private static function handleBusinessAfterPayment($payment)
{
try {
if ($payment['order_type'] == self::ORDER_TYPE_COURSE) {
// 处理课程购买逻辑
// 例如: 更新课程订单状态, 分配课程权限等
// Db::name('fj_course_order')->where('id', $payment['order_id'])->update(['status' => 1]);
} elseif ($payment['order_type'] == self::ORDER_TYPE_CERT) {
// 处理证书购买逻辑
// Db::name('fj_cert_order')->where('id', $payment['order_id'])->update(['status' => 1]);
}
// 可以添加其他业务逻辑,如发送通知等
} catch (\Exception $e) {
Log::error("支付后业务处理失败: " . $e->getMessage());
}
}
/**
* 获取支付配置
* @param int $payMethod 支付方式
* @return array
*/
public static function getPayConfig($payMethod)
{
return $payMethod == self::PAY_METHOD_ALIPAY ?
config('pay.alipay') : config('pay.wechat');
}
}
\ No newline at end of file
This diff is collapsed.
<?php
return [
'alipay' => [
'default' => [
// 「必填」支付宝分配的 app_id
'app_id' => '2016082000295641',
// 「必填」应用私钥 字符串或路径
// 在 https://open.alipay.com/develop/manage 《应用详情->开发设置->接口加签方式》中设置
'app_secret_cert' => 'MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCDRjOg5DnX+8L+rB8d2MbrQ30Z7JPM4hiDhawHSwQCQ7RlmQNpl6b/N6IrPLcPFC1uii179U5Il5xTZynfjkUyJjnHusqnmHskftLJDKkmGbSUFMAlOv+NlpUWMJ2A+VUopl+9FLyqcV+XgbaWizxU3LsTtt64v89iZ2iC16H6/6a3YcP+hDZUjiNGQx9cuwi9eJyykvcwhDkFPxeBxHbfwppsul+DYUyTCcl0Ltbga/mUechk5BksW6yPPwprYHQBXyM16Jc3q5HbNxh3660FyvUBFLuVWIBs6RtR2gZCa6b8rOtCkPQKhUKvzRMlgheOowXsWdk99GjxGQDK5W4XAgMBAAECggEAYPKnjlr+nRPBnnNfR5ugzH67FToyrU0M7ZT6xygPfdyijaXDb2ggXLupeGUOjIRKSSijDrjLZ7EQMkguFHvtfmvcoDTDFaL2zq0a3oALK6gwRGxOuzAnK1naINkmeOmqiqrUab+21emEv098mRGbLNEXGCgltCtz7SiRdo/pgIPZ1wHj4MH0b0K2bFG3xwr51EyaLXKYH4j6w9YAXXsTdvzcJ+eRE0Yq4uGPfkziqg8d0xXSEt90HmCGHKo4O2eh1w1IlBcHfK0F6vkeUAtrtAV01MU2bNoRU147vKFxjDOVBlY1nIZY/drsbiPMuAfSsodL0hJxGSYivbKTX4CWgQKBgQDd0MkF5AIPPdFC+fhWdNclePRw4gUkBwPTIUljMP4o+MhJNrHp0sEy0sr1mzYsOT4J20hsbw/qTnMKGdgy784bySf6/CC7lv2hHp0wyS3Es0DRJuN+aTyyONOKGvQqd8gvuQtuYJy+hkIoHygjvC3TKndX1v66f9vCr/7TS0QPywKBgQCXgVHERHP+CarSAEDG6bzI878/5yqyJVlUeVMG5OXdlwCl0GAAl4mDvfqweUawSVFE7qiSqy3Eaok8KHkYcoRlQmAefHg/C8t2PNFfNrANDdDB99f7UhqhXTdBA6DPyW02eKIaBcXjZ7jEXZzA41a/zxZydKgHvz4pUq1BdbU5ZQKBgHyqGCDgaavpQVAUL1df6X8dALzkuqDp9GNXxOgjo+ShFefX/pv8oCqRQBJTflnSfiSKAqU2skosdwlJRzIxhrQlFPxBcaAcl0VTcGL33mo7mIU0Bw2H1d4QhAuNZIbttSvlIyCQ2edWi54DDMswusyAhHxwz88/huJfiad1GLaLAoGASIweMVNuD5lleMWyPw2x3rAJRnpVUZTc37xw6340LBWgs8XCEsZ9jN4t6s9H8CZLiiyWABWEBufU6z+eLPy5NRvBlxeXJOlq9iVNRMCVMMsKybb6b1fzdI2EZdds69LSPyEozjkxdyE1sqH468xwv8xUPV5rD7qd83+pgwzwSJkCgYBrRV0OZmicfVJ7RqbWyneBG03r7ziA0WTcLdRWDnOujQ9orhrkm+EY2evhLEkkF6TOYv4QFBGSHfGJ0SwD7ghbCQC/8oBvNvuQiPWI8B+00LwyxXNrkFOxy7UfIUdUmLoLc1s/VdBHku+JEd0YmEY+p4sjmcRnlu4AlzLxkWUTTg==',
// 「必填」应用公钥证书 路径
// 设置应用私钥后,即可下载得到以下3个证书
'app_public_cert_path' => '/Users/yansongda/pay/cert/appCertPublicKey_2016082000295641.crt',
// 「必填」支付宝公钥证书 路径
'alipay_public_cert_path' => '/Users/yansongda/pay/cert/alipayCertPublicKey_RSA2.crt',
// 「必填」支付宝根证书 路径
'alipay_root_cert_path' => '/Users/yansongda/pay/cert/alipayRootCert.crt',
'return_url' => 'https://yansongda.cn/alipay/return',
'notify_url' => 'https://yansongda.cn/alipay/notify',
// 「选填」第三方应用授权token
'app_auth_token' => '',
// 「选填」服务商模式下的服务商 id,当 mode 为 Pay::MODE_SERVICE 时使用该参数
'service_provider_id' => '',
// 「选填」默认为正常模式。可选为: MODE_NORMAL, MODE_SANDBOX, MODE_SERVICE
'mode' => \Yansongda\Pay\Pay::MODE_NORMAL,
]
],
'wechat' => [
'default' => [
// 「必填」商户号,服务商模式下为服务商商户号
// 可在 https://pay.weixin.qq.com/ 账户中心->商户信息 查看
'mch_id' => '',
// 「选填」v2商户私钥
'mch_secret_key_v2' => '',
// 「必填」v3 商户秘钥
// 即 API v3 密钥(32字节,形如md5值),可在 账户中心->API安全 中设置
'mch_secret_key' => '',
// 「必填」商户私钥 字符串或路径
// 即 API证书 PRIVATE KEY,可在 账户中心->API安全->申请API证书 里获得
// 文件名形如:apiclient_key.pem
'mch_secret_cert' => '',
// 「必填」商户公钥证书路径
// 即 API证书 CERTIFICATE,可在 账户中心->API安全->申请API证书 里获得
// 文件名形如:apiclient_cert.pem
'mch_public_cert_path' => '',
// 「必填」微信回调url
// 不能有参数,如?号,空格等,否则会无法正确回调
'notify_url' => 'https://yansongda.cn/wechat/notify',
// 「选填」公众号 的 app_id
// 可在 mp.weixin.qq.com 设置与开发->基本配置->开发者ID(AppID) 查看
'mp_app_id' => '2016082000291234',
// 「选填」小程序 的 app_id
'mini_app_id' => '',
// 「选填」app 的 app_id
'app_id' => '',
// 「选填」服务商模式下,子公众号 的 app_id
'sub_mp_app_id' => '',
// 「选填」服务商模式下,子 app 的 app_id
'sub_app_id' => '',
// 「选填」服务商模式下,子小程序 的 app_id
'sub_mini_app_id' => '',
// 「选填」服务商模式下,子商户id
'sub_mch_id' => '',
// 「选填」(适用于 2024-11 及之前开通微信支付的老商户)微信支付平台证书序列号及证书路径,强烈建议 php-fpm 模式下配置此参数
// 「必填」微信支付公钥ID及证书路径,key 填写形如 PUB_KEY_ID_0000000000000024101100397200000006 的公钥id,见 https://pay.weixin.qq.com/doc/v3/merchant/4013053249
'wechat_public_cert_path' => [
'45F59D4DABF31918AFCEC556D5D2C6E376675D57' => __DIR__.'/Cert/wechatPublicKey.crt',
'PUB_KEY_ID_0000000000000024101100397200000006' => __DIR__.'/Cert/publickey.pem',
],
// 「选填」默认为正常模式。可选为: MODE_NORMAL, MODE_SERVICE
'mode' => \Yansongda\Pay\Pay::MODE_NORMAL,
]
],
];
\ No newline at end of file
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php$1 last;
}
\ No newline at end of file
......@@ -16,13 +16,16 @@ return array(
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'662a729f963d39afe703c9d9b7ab4a8c' => $vendorDir . '/symfony/polyfill-php83/bootstrap.php',
'6b998e7ad3182c0d21d23780badfa07b' => $vendorDir . '/yansongda/supports/src/Functions.php',
'd767e4fc2dc52fe66584ab8c6684783e' => $vendorDir . '/adbario/php-dot-notation/src/helpers.php',
'9c7a683baffd24f5595c1dc5f5273030' => $vendorDir . '/hyperf/engine/src/Functions.php',
'b067bc7112e384b61c701452d53a14a8' => $vendorDir . '/mtdowling/jmespath.php/src/JmesPath.php',
'2203a247e6fda86070a5e4e07aed533a' => $vendorDir . '/symfony/clock/Resources/now.php',
'a1105708a18b76903365ca1c4aa61b02' => $vendorDir . '/symfony/translation/Resources/functions.php',
'66453932bc1be9fb2f910a27947d11b6' => $vendorDir . '/alibabacloud/client/src/Functions.php',
'9a31621970d4295d5f00acf4e277e6f9' => $vendorDir . '/stechstudio/backoff/src/helpers.php',
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
'988d02680beedec88d52f2787b2d2007' => $vendorDir . '/yansongda/artful/src/Functions.php',
'cd5441689b14144e5573bf989ee47b34' => $vendorDir . '/qcloud/cos-sdk-v5/src/Common.php',
'841780ea2e1d6545ea3a253239d59c05' => $vendorDir . '/qiniu/php-sdk/src/Qiniu/functions.php',
'5dd19d8a547b7318af0c3a93c8bd6565' => $vendorDir . '/qiniu/php-sdk/src/Qiniu/Http/Middleware/Middleware.php',
......@@ -30,4 +33,5 @@ return array(
'd79a0e13e295db93891a9377e0888496' => $vendorDir . '/topthink/think-dumper/src/helper.php',
'cc56288302d9df745d97c934d6a6e5f0' => $vendorDir . '/topthink/think-queue/src/common.php',
'af46dcea2921209ac30627b964175f13' => $vendorDir . '/topthink/think-swoole/src/helpers.php',
'8c783b3a3de2f6d9177022b5ccdcc841' => $vendorDir . '/yansongda/pay/src/Functions.php',
);
......@@ -6,5 +6,6 @@ $vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'Pimple' => array($vendorDir . '/pimple/pimple/src'),
'' => array($baseDir . '/extend'),
);
......@@ -19,6 +19,9 @@ return array(
'app\\' => array($baseDir . '/app'),
'addons\\' => array($baseDir . '/addons'),
'ZipStream\\' => array($vendorDir . '/maennchen/zipstream-php/src'),
'Yansongda\\Supports\\' => array($vendorDir . '/yansongda/supports/src'),
'Yansongda\\Pay\\' => array($vendorDir . '/yansongda/pay/src'),
'Yansongda\\Artful\\' => array($vendorDir . '/yansongda/artful/src'),
'Workerman\\' => array($vendorDir . '/workerman/workerman'),
'Symfony\\Polyfill\\Php83\\' => array($vendorDir . '/symfony/polyfill-php83'),
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
......@@ -37,6 +40,7 @@ return array(
'Psr\\Log\\' => array($vendorDir . '/psr/log/src'),
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'),
'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'),
'Psr\\EventDispatcher\\' => array($vendorDir . '/psr/event-dispatcher/src'),
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
'Psr\\Clock\\' => array($vendorDir . '/psr/clock/src'),
'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
......@@ -51,6 +55,11 @@ return array(
'League\\Flysystem\\Cached\\' => array($vendorDir . '/league/flysystem-cached-adapter/src'),
'League\\Flysystem\\' => array($vendorDir . '/league/flysystem/src'),
'JmesPath\\' => array($vendorDir . '/mtdowling/jmespath.php/src'),
'Hyperf\\Pimple\\' => array($vendorDir . '/hyperf/pimple/src'),
'Hyperf\\Engine\\Contract\\' => array($vendorDir . '/hyperf/engine-contract/src'),
'Hyperf\\Engine\\' => array($vendorDir . '/hyperf/engine/src'),
'Hyperf\\Contract\\' => array($vendorDir . '/hyperf/contract/src'),
'Hyperf\\Context\\' => array($vendorDir . '/hyperf/context/src'),
'GuzzleHttp\\UriTemplate\\' => array($vendorDir . '/guzzlehttp/uri-template/src'),
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
......
......@@ -17,13 +17,16 @@ class ComposerStaticInit118552ef2b3077b276422e248ece3c62
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'662a729f963d39afe703c9d9b7ab4a8c' => __DIR__ . '/..' . '/symfony/polyfill-php83/bootstrap.php',
'6b998e7ad3182c0d21d23780badfa07b' => __DIR__ . '/..' . '/yansongda/supports/src/Functions.php',
'd767e4fc2dc52fe66584ab8c6684783e' => __DIR__ . '/..' . '/adbario/php-dot-notation/src/helpers.php',
'9c7a683baffd24f5595c1dc5f5273030' => __DIR__ . '/..' . '/hyperf/engine/src/Functions.php',
'b067bc7112e384b61c701452d53a14a8' => __DIR__ . '/..' . '/mtdowling/jmespath.php/src/JmesPath.php',
'2203a247e6fda86070a5e4e07aed533a' => __DIR__ . '/..' . '/symfony/clock/Resources/now.php',
'a1105708a18b76903365ca1c4aa61b02' => __DIR__ . '/..' . '/symfony/translation/Resources/functions.php',
'66453932bc1be9fb2f910a27947d11b6' => __DIR__ . '/..' . '/alibabacloud/client/src/Functions.php',
'9a31621970d4295d5f00acf4e277e6f9' => __DIR__ . '/..' . '/stechstudio/backoff/src/helpers.php',
'667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
'988d02680beedec88d52f2787b2d2007' => __DIR__ . '/..' . '/yansongda/artful/src/Functions.php',
'cd5441689b14144e5573bf989ee47b34' => __DIR__ . '/..' . '/qcloud/cos-sdk-v5/src/Common.php',
'841780ea2e1d6545ea3a253239d59c05' => __DIR__ . '/..' . '/qiniu/php-sdk/src/Qiniu/functions.php',
'5dd19d8a547b7318af0c3a93c8bd6565' => __DIR__ . '/..' . '/qiniu/php-sdk/src/Qiniu/Http/Middleware/Middleware.php',
......@@ -31,6 +34,7 @@ class ComposerStaticInit118552ef2b3077b276422e248ece3c62
'd79a0e13e295db93891a9377e0888496' => __DIR__ . '/..' . '/topthink/think-dumper/src/helper.php',
'cc56288302d9df745d97c934d6a6e5f0' => __DIR__ . '/..' . '/topthink/think-queue/src/common.php',
'af46dcea2921209ac30627b964175f13' => __DIR__ . '/..' . '/topthink/think-swoole/src/helpers.php',
'8c783b3a3de2f6d9177022b5ccdcc841' => __DIR__ . '/..' . '/yansongda/pay/src/Functions.php',
);
public static $prefixLengthsPsr4 = array (
......@@ -62,6 +66,12 @@ class ComposerStaticInit118552ef2b3077b276422e248ece3c62
array (
'ZipStream\\' => 10,
),
'Y' =>
array (
'Yansongda\\Supports\\' => 19,
'Yansongda\\Pay\\' => 14,
'Yansongda\\Artful\\' => 17,
),
'W' =>
array (
'Workerman\\' => 10,
......@@ -91,6 +101,7 @@ class ComposerStaticInit118552ef2b3077b276422e248ece3c62
'Psr\\Log\\' => 8,
'Psr\\Http\\Message\\' => 17,
'Psr\\Http\\Client\\' => 16,
'Psr\\EventDispatcher\\' => 20,
'Psr\\Container\\' => 14,
'Psr\\Clock\\' => 10,
'Psr\\Cache\\' => 10,
......@@ -118,6 +129,14 @@ class ComposerStaticInit118552ef2b3077b276422e248ece3c62
array (
'JmesPath\\' => 9,
),
'H' =>
array (
'Hyperf\\Pimple\\' => 14,
'Hyperf\\Engine\\Contract\\' => 23,
'Hyperf\\Engine\\' => 14,
'Hyperf\\Contract\\' => 16,
'Hyperf\\Context\\' => 15,
),
'G' =>
array (
'GuzzleHttp\\UriTemplate\\' => 23,
......@@ -205,6 +224,18 @@ class ComposerStaticInit118552ef2b3077b276422e248ece3c62
array (
0 => __DIR__ . '/..' . '/maennchen/zipstream-php/src',
),
'Yansongda\\Supports\\' =>
array (
0 => __DIR__ . '/..' . '/yansongda/supports/src',
),
'Yansongda\\Pay\\' =>
array (
0 => __DIR__ . '/..' . '/yansongda/pay/src',
),
'Yansongda\\Artful\\' =>
array (
0 => __DIR__ . '/..' . '/yansongda/artful/src',
),
'Workerman\\' =>
array (
0 => __DIR__ . '/..' . '/workerman/workerman',
......@@ -278,6 +309,10 @@ class ComposerStaticInit118552ef2b3077b276422e248ece3c62
array (
0 => __DIR__ . '/..' . '/psr/http-client/src',
),
'Psr\\EventDispatcher\\' =>
array (
0 => __DIR__ . '/..' . '/psr/event-dispatcher/src',
),
'Psr\\Container\\' =>
array (
0 => __DIR__ . '/..' . '/psr/container/src',
......@@ -334,6 +369,26 @@ class ComposerStaticInit118552ef2b3077b276422e248ece3c62
array (
0 => __DIR__ . '/..' . '/mtdowling/jmespath.php/src',
),
'Hyperf\\Pimple\\' =>
array (
0 => __DIR__ . '/..' . '/hyperf/pimple/src',
),
'Hyperf\\Engine\\Contract\\' =>
array (
0 => __DIR__ . '/..' . '/hyperf/engine-contract/src',
),
'Hyperf\\Engine\\' =>
array (
0 => __DIR__ . '/..' . '/hyperf/engine/src',
),
'Hyperf\\Contract\\' =>
array (
0 => __DIR__ . '/..' . '/hyperf/contract/src',
),
'Hyperf\\Context\\' =>
array (
0 => __DIR__ . '/..' . '/hyperf/context/src',
),
'GuzzleHttp\\UriTemplate\\' =>
array (
0 => __DIR__ . '/..' . '/guzzlehttp/uri-template/src',
......@@ -392,6 +447,16 @@ class ComposerStaticInit118552ef2b3077b276422e248ece3c62
),
);
public static $prefixesPsr0 = array (
'P' =>
array (
'Pimple' =>
array (
0 => __DIR__ . '/..' . '/pimple/pimple/src',
),
),
);
public static $fallbackDirsPsr0 = array (
0 => __DIR__ . '/../..' . '/extend',
);
......@@ -512,6 +577,7 @@ class ComposerStaticInit118552ef2b3077b276422e248ece3c62
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit118552ef2b3077b276422e248ece3c62::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit118552ef2b3077b276422e248ece3c62::$prefixDirsPsr4;
$loader->prefixesPsr0 = ComposerStaticInit118552ef2b3077b276422e248ece3c62::$prefixesPsr0;
$loader->fallbackDirsPsr0 = ComposerStaticInit118552ef2b3077b276422e248ece3c62::$fallbackDirsPsr0;
$loader->classMap = ComposerStaticInit118552ef2b3077b276422e248ece3c62::$classMap;
......
This diff is collapsed.
......@@ -1135,6 +1135,51 @@
'aliases' => array(),
'dev_requirement' => false,
),
'hyperf/context' => array(
'pretty_version' => 'v3.1.42',
'version' => '3.1.42.0',
'reference' => 'ac666862d644db7d813342c880826a1fda599bdf',
'type' => 'library',
'install_path' => __DIR__ . '/../hyperf/context',
'aliases' => array(),
'dev_requirement' => false,
),
'hyperf/contract' => array(
'pretty_version' => 'v3.1.42',
'version' => '3.1.42.0',
'reference' => '6ef2c7f98917c52ccda3a37ae65b190848dde6c4',
'type' => 'library',
'install_path' => __DIR__ . '/../hyperf/contract',
'aliases' => array(),
'dev_requirement' => false,
),
'hyperf/engine' => array(
'pretty_version' => 'v2.14.0',
'version' => '2.14.0.0',
'reference' => '74ec5130fa0838e285a24292a232ce455edccff8',
'type' => 'library',
'install_path' => __DIR__ . '/../hyperf/engine',
'aliases' => array(),
'dev_requirement' => false,
),
'hyperf/engine-contract' => array(
'pretty_version' => 'v1.13.0',
'version' => '1.13.0.0',
'reference' => '26a18ec0375147546bf9702b0fd737fdd2cec1d6',
'type' => 'library',
'install_path' => __DIR__ . '/../hyperf/engine-contract',
'aliases' => array(),
'dev_requirement' => false,
),
'hyperf/pimple' => array(
'pretty_version' => 'v2.2.2',
'version' => '2.2.2.0',
'reference' => '7bd07745c256b83679471c06ec2a11e901d37277',
'type' => 'library',
'install_path' => __DIR__ . '/../hyperf/pimple',
'aliases' => array(),
'dev_requirement' => false,
),
'league/flysystem' => array(
'pretty_version' => '1.1.10',
'version' => '1.1.10.0',
......@@ -1279,6 +1324,15 @@
'aliases' => array(),
'dev_requirement' => false,
),
'pimple/pimple' => array(
'pretty_version' => 'v3.5.0',
'version' => '3.5.0.0',
'reference' => 'a94b3a4db7fb774b3d78dad2315ddc07629e1bed',
'type' => 'library',
'install_path' => __DIR__ . '/../pimple/pimple',
'aliases' => array(),
'dev_requirement' => false,
),
'psr/cache' => array(
'pretty_version' => '1.0.1',
'version' => '1.0.1.0',
......@@ -1312,6 +1366,15 @@
'aliases' => array(),
'dev_requirement' => false,
),
'psr/event-dispatcher' => array(
'pretty_version' => '1.0.0',
'version' => '1.0.0.0',
'reference' => 'dbefd12671e8a14ec7f180cab83036ed26714bb0',
'type' => 'library',
'install_path' => __DIR__ . '/../psr/event-dispatcher',
'aliases' => array(),
'dev_requirement' => false,
),
'psr/http-client' => array(
'pretty_version' => '1.0.3',
'version' => '1.0.3.0',
......@@ -1705,5 +1768,32 @@
'aliases' => array(),
'dev_requirement' => false,
),
'yansongda/artful' => array(
'pretty_version' => 'v1.1.2',
'version' => '1.1.2.0',
'reference' => 'bad726c6287aca219750823bff46f70287ec3995',
'type' => 'library',
'install_path' => __DIR__ . '/../yansongda/artful',
'aliases' => array(),
'dev_requirement' => false,
),
'yansongda/pay' => array(
'pretty_version' => 'v3.7.14',
'version' => '3.7.14.0',
'reference' => 'a000bd7dec9c98f64e70173559b9656702b21a79',
'type' => 'library',
'install_path' => __DIR__ . '/../yansongda/pay',
'aliases' => array(),
'dev_requirement' => false,
),
'yansongda/supports' => array(
'pretty_version' => 'v4.0.12',
'version' => '4.0.12.0',
'reference' => '308de376d20cb1cd4f959644793e0582ccd1ef6d',
'type' => 'library',
'install_path' => __DIR__ . '/../yansongda/supports',
'aliases' => array(),
'dev_requirement' => false,
),
),
);
/tests export-ignore
/.github export-ignore
The MIT License (MIT)
Copyright (c) Hyperf
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
{
"name": "hyperf/context",
"description": "A coroutine/application context library.",
"license": "MIT",
"keywords": [
"php",
"swoole",
"hyperf",
"context"
],
"homepage": "https://hyperf.io",
"support": {
"issues": "https://github.com/hyperf/hyperf/issues",
"source": "https://github.com/hyperf/hyperf",
"docs": "https://hyperf.wiki",
"pull-request": "https://github.com/hyperf/hyperf/pulls"
},
"require": {
"php": ">=8.1",
"hyperf/engine": "^2.0"
},
"suggest": {
"swow/psr7-plus": "Required to use RequestContext and ResponseContext"
},
"autoload": {
"psr-4": {
"Hyperf\\Context\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"HyperfTest\\Context\\": "tests/"
}
},
"config": {
"sort-packages": true
},
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
}
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Context;
use Psr\Container\ContainerInterface;
use TypeError;
class ApplicationContext
{
protected static ?ContainerInterface $container = null;
/**
* @throws TypeError
*/
public static function getContainer(): ContainerInterface
{
return self::$container;
}
public static function hasContainer(): bool
{
return isset(self::$container);
}
public static function setContainer(ContainerInterface $container): ContainerInterface
{
self::$container = $container;
return $container;
}
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Context;
use ArrayObject;
use Closure;
use Hyperf\Engine\Coroutine;
use function Hyperf\Support\value;
/**
* @template TKey of string
* @template TValue
*/
class Context
{
/**
* @var array<TKey, TValue>
*/
protected static array $nonCoContext = [];
/**
* @param TKey $id
* @param TValue $value
* @return TValue
*/
public static function set(string $id, mixed $value, ?int $coroutineId = null): mixed
{
if (Coroutine::id() > 0) {
Coroutine::getContextFor($coroutineId)[$id] = $value;
} else {
static::$nonCoContext[$id] = $value;
}
return $value;
}
/**
* @param TKey $id
* @return TValue
*/
public static function get(string $id, mixed $default = null, ?int $coroutineId = null): mixed
{
if (Coroutine::id() > 0) {
return Coroutine::getContextFor($coroutineId)[$id] ?? $default;
}
return static::$nonCoContext[$id] ?? $default;
}
/**
* @param TKey $id
*/
public static function has(string $id, ?int $coroutineId = null): bool
{
if (Coroutine::id() > 0) {
return isset(Coroutine::getContextFor($coroutineId)[$id]);
}
return isset(static::$nonCoContext[$id]);
}
/**
* Release the context when you are not in coroutine environment.
*
* @param TKey $id
*/
public static function destroy(string $id, ?int $coroutineId = null): void
{
if (Coroutine::id() > 0) {
unset(Coroutine::getContextFor($coroutineId)[$id]);
}
unset(static::$nonCoContext[$id]);
}
/**
* Copy the context from a coroutine to current coroutine.
* This method will delete the origin values in current coroutine.
*/
public static function copy(int $fromCoroutineId, array $keys = []): void
{
$from = Coroutine::getContextFor($fromCoroutineId);
if ($from === null) {
return;
}
$current = Coroutine::getContextFor();
if ($keys) {
$map = array_intersect_key($from->getArrayCopy(), array_flip($keys));
} else {
$map = $from->getArrayCopy();
}
$current->exchangeArray($map);
}
/**
* Retrieve the value and override it by closure.
*
* @param TKey $id
* @param (Closure(TValue):TValue) $closure
*/
public static function override(string $id, Closure $closure, ?int $coroutineId = null): mixed
{
$value = null;
if (self::has($id, $coroutineId)) {
$value = self::get($id, null, $coroutineId);
}
$value = $closure($value);
self::set($id, $value, $coroutineId);
return $value;
}
/**
* Retrieve the value and store it if not exists.
*
* @param TKey $id
* @param TValue $value
* @return TValue
*/
public static function getOrSet(string $id, mixed $value, ?int $coroutineId = null): mixed
{
if (! self::has($id, $coroutineId)) {
return self::set($id, value($value), $coroutineId);
}
return self::get($id, null, $coroutineId);
}
/**
* @return null|array<TKey, TValue>|ArrayObject<TKey, TValue>
*/
public static function getContainer(?int $coroutineId = null)
{
if (Coroutine::id() > 0) {
return Coroutine::getContextFor($coroutineId);
}
return static::$nonCoContext;
}
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Context;
use Psr\Http\Message\ServerRequestInterface;
use RuntimeException;
use Swow\Psr7\Message\ServerRequestPlusInterface;
class RequestContext
{
public static function get(?int $coroutineId = null): ServerRequestPlusInterface
{
return Context::get(ServerRequestInterface::class, null, $coroutineId);
}
public static function set(ServerRequestInterface $request, ?int $coroutineId = null): ServerRequestPlusInterface
{
if (! $request instanceof ServerRequestPlusInterface) {
throw new RuntimeException('The request must instanceof ServerRequestPlusInterface');
}
return Context::set(ServerRequestInterface::class, $request, $coroutineId);
}
public static function has(?int $coroutineId = null): bool
{
return Context::has(ServerRequestInterface::class, $coroutineId);
}
public static function getOrNull(?int $coroutineId = null): ?ServerRequestPlusInterface
{
return Context::get(ServerRequestInterface::class, null, $coroutineId);
}
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Context;
use Psr\Http\Message\ResponseInterface;
use RuntimeException;
use Swow\Psr7\Message\ResponsePlusInterface;
class ResponseContext
{
public static function get(?int $coroutineId = null): ResponsePlusInterface
{
return Context::get(ResponseInterface::class, null, $coroutineId);
}
public static function set(ResponseInterface $response, ?int $coroutineId = null): ResponsePlusInterface
{
if (! $response instanceof ResponsePlusInterface) {
throw new RuntimeException('The response must instanceof ResponsePlusInterface');
}
return Context::set(ResponseInterface::class, $response, $coroutineId);
}
public static function has(?int $coroutineId = null): bool
{
return Context::has(ResponseInterface::class, $coroutineId);
}
public static function getOrNull(?int $coroutineId = null): ?ResponsePlusInterface
{
return Context::get(ResponseInterface::class, null, $coroutineId);
}
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Context\Traits;
use Hyperf\Context\Context;
use RuntimeException;
trait CoroutineProxy
{
public function __call($name, $arguments)
{
$target = $this->getTargetObject();
return $target->{$name}(...$arguments);
}
public function __get($name)
{
$target = $this->getTargetObject();
return $target->{$name};
}
public function __set($name, $value)
{
$target = $this->getTargetObject();
return $target->{$name} = $value;
}
protected function getTargetObject()
{
if (! isset($this->proxyKey)) {
throw new RuntimeException(sprintf('Missing $proxyKey property in %s.', $this::class));
}
return Context::get($this->proxyKey);
}
}
/tests export-ignore
/.github export-ignore
The MIT License (MIT)
Copyright (c) Hyperf
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
{
"name": "hyperf/contract",
"description": "The contracts of Hyperf.",
"license": "MIT",
"keywords": [
"php",
"swoole",
"hyperf"
],
"homepage": "https://hyperf.io",
"support": {
"issues": "https://github.com/hyperf/hyperf/issues",
"source": "https://github.com/hyperf/hyperf",
"docs": "https://hyperf.wiki",
"pull-request": "https://github.com/hyperf/hyperf/pulls"
},
"require": {
"php": ">=8.1"
},
"autoload": {
"psr-4": {
"Hyperf\\Contract\\": "src/"
}
},
"config": {
"sort-packages": true
},
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
}
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
use Hyperf\Framework\ApplicationFactory;
use Symfony\Component\Console\Application;
/**
* @see ApplicationFactory
* @mixin Application
*/
interface ApplicationInterface
{
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
/**
* @template TKey of array-key
* @template TValue
*/
interface Arrayable
{
/**
* @return array<TKey, TValue>
*/
public function toArray(): array;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface CanBeEscapedWhenCastToString
{
/**
* Indicate that the object's string representation should be escaped when __toString is invoked.
*
* @param bool $escape
* @return $this
*/
public function escapeWhenCastingToString($escape = true);
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface Castable
{
/**
* Get the name of the caster class to use when casting from / to this cast target.
*
* @return CastsAttributes|CastsInboundAttributes|string
*/
public static function castUsing();
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface CastsAttributes
{
/**
* Transform the attribute from the underlying model values.
*
* @param object $model
* @param mixed $value
* @return mixed
*/
public function get($model, string $key, $value, array $attributes);
/**
* Transform the attribute to its underlying model values.
*
* @param object $model
* @param mixed $value
* @return array|string
*/
public function set($model, string $key, $value, array $attributes);
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface CastsInboundAttributes
{
/**
* Transform the attribute to its underlying model values.
*
* @param object $model
* @param mixed $value
* @return array
*/
public function set($model, string $key, $value, array $attributes);
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface CompressInterface
{
public function compress(): UnCompressInterface;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface ConfigInterface
{
/**
* Finds an entry of the container by its identifier and returns it.
*
* @param string $key identifier of the entry to look for
* @param mixed $default default value of the entry when does not found
* @return mixed entry
*/
public function get(string $key, mixed $default = null): mixed;
/**
* Returns true if the container can return an entry for the given identifier.
* Returns false otherwise.
*
* @param string $keys identifier of the entry to look for
*/
public function has(string $keys): bool;
/**
* Set a value to the container by its identifier.
*
* @param string $key identifier of the entry to set
* @param mixed $value the value that save to container
*/
public function set(string $key, mixed $value): void;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface ConnectionInterface
{
/**
* Get the real connection from pool.
*/
public function getConnection();
/**
* Reconnect the connection.
*/
public function reconnect(): bool;
/**
* Check the connection is valid.
*/
public function check(): bool;
/**
* Close the connection.
*/
public function close(): bool;
/**
* Release the connection to pool.
*/
public function release(): void;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface as PsrContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
use Throwable;
interface ContainerInterface extends PsrContainerInterface
{
/**
* Build an entry of the container by its name.
* This method behave like get() except resolves the entry again every time.
* For example if the entry is a class then a new instance will be created each time.
* This method makes the container behave like a factory.
*
* @template TClass
*
* @param class-string<TClass>|string $name entry name or a class name
* @param array $parameters Optional parameters to use to build the entry. Use this to force specific parameters to specific values. Parameters not defined in this array will be resolved using the container.
*
* @return ($name is class-string<TClass> ? TClass : mixed)
*
* @throws ContainerExceptionInterface&Throwable the name parameter must be of type string
* @throws NotFoundExceptionInterface&Throwable no entry found for the given name
*/
public function make(string $name, array $parameters = []);
/**
* Bind an arbitrary resolved entry to an identifier.
* Useful for testing 'get'.
*
* @param mixed $entry
*/
public function set(string $name, $entry): void;
/**
* Unbind an arbitrary resolved entry.
*/
public function unbind(string $name): void;
/**
* Bind an arbitrary definition to an identifier.
* Useful for testing 'make'.
*
* @param array|callable|string $definition
*/
public function define(string $name, $definition): void;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface DispatcherInterface
{
public function dispatch(...$params);
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface FrequencyInterface
{
/**
* Number of hit per time.
*/
public function hit(int $number = 1): bool;
/**
* Hits per second.
*/
public function frequency(): float;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface IPReaderInterface
{
public function read(): string;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface IdGeneratorInterface
{
public function generate();
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface JsonDeSerializable
{
public static function jsonDeSerialize(mixed $data): static;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
use Stringable;
interface Jsonable extends Stringable
{
public function __toString(): string;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface LengthAwarePaginatorInterface extends PaginatorInterface
{
/**
* Create a range of pagination URLs.
*/
public function getUrlRange(int $start, int $end): array;
/**
* Determine the total number of items in the data store.
*/
public function total(): int;
/**
* Get the page number of the last available page.
*/
public function lastPage(): int;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface MessageBag
{
/**
* Get the keys present in the message bag.
*/
public function keys(): array;
/**
* Add a message to the bag.
*/
public function add(string $key, string $message): MessageBag;
/**
* Merge a new array of messages into the bag.
*
* @param array|MessageProvider $messages
* @return $this
*/
public function merge($messages);
/**
* Determine if messages exist for a given key.
*
* @param array|string $key
*/
public function has($key): bool;
/**
* Get the first message from the bag for a given key.
*/
public function first(?string $key = null, ?string $format = null): string;
/**
* Get all of the messages from the bag for a given key.
*/
public function get(string $key, ?string $format = null): array;
/**
* Get all of the messages for every key in the bag.
*/
public function all(?string $format = null): array;
/**
* Get the raw messages in the container.
*/
public function getMessages(): array;
/**
* Get the default message format.
*/
public function getFormat(): string;
/**
* Set the default message format.
*
* @return $this
*/
public function setFormat(string $format = ':message');
/**
* Determine if the message bag has any messages.
*/
public function isEmpty(): bool;
/**
* Determine if the message bag has any messages.
*/
public function isNotEmpty(): bool;
/**
* Get the number of messages in the container.
*/
public function count(): int;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface MessageProvider
{
/**
* Get the messages for the instance.
*/
public function getMessageBag(): MessageBag;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface MiddlewareInitializerInterface
{
public function initCoreMiddleware(string $serverName): void;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
use ArrayObject;
interface NormalizerInterface
{
/**
* Normalizes an object into a set of arrays/scalars.
*
* @param mixed $object
* @return null|array|ArrayObject|bool|float|int|string
*/
public function normalize($object);
/**
* Denormalizes data back into an object of the given class.
*
* @param mixed $data Data to restore
* @param string $class The expected class to instantiate
* @return mixed|object
*/
public function denormalize($data, string $class);
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
use Swoole\Http\Response;
use Swoole\Server;
interface OnCloseInterface
{
/**
* @param Response|Server $server
*/
public function onClose($server, int $fd, int $reactorId): void;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
use Swoole\Http\Request;
use Swoole\Http\Response;
interface OnHandShakeInterface
{
/**
* @param Request $request
* @param Response $response
*/
public function onHandShake($request, $response): void;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
use Swoole\Http\Response;
use Swoole\WebSocket\Frame;
use Swoole\WebSocket\Server;
interface OnMessageInterface
{
/**
* @param Response|Server $server
* @param Frame $frame
*/
public function onMessage($server, $frame): void;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
use Swoole\Http\Request;
use Swoole\Http\Response;
use Swoole\WebSocket\Server;
use Swow\Psr7\Server\ServerConnection;
interface OnOpenInterface
{
/**
* @param Response|Server|ServerConnection $server
* @param Request $request
*/
public function onOpen($server, $request): void;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
use Swoole\WebSocket\Server;
interface OnPacketInterface
{
/**
* @param Server $server
* @param mixed $data
* @param array $clientInfo
*/
public function onPacket($server, $data, $clientInfo): void;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
use Hyperf\Server\Connection as HyperfConnection;
use Swoole\Coroutine\Server\Connection;
use Swoole\Server as SwooleServer;
use Swow\Socket;
interface OnReceiveInterface
{
/**
* @param Connection|HyperfConnection|Socket|SwooleServer $server
*/
public function onReceive($server, int $fd, int $reactorId, string $data): void;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface OnRequestInterface
{
/**
* @param mixed $request swoole request or psr server request
* @param mixed $response swoole response or swow session
*/
public function onRequest($request, $response): void;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface PackerInterface
{
public function pack($data): string;
public function unpack(string $data);
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface PaginatorInterface
{
/**
* Get the URL for a given page.
*/
public function url(int $page): string;
/**
* Add a set of query string values to the paginator.
*
* @param array|string $key
* @return static
*/
public function appends($key, ?string $value = null);
/**
* Get / set the URL fragment to be appended to URLs.
*
* @return static|string
*/
public function fragment(?string $fragment = null);
/**
* The URL for the next page, or null.
*/
public function nextPageUrl(): ?string;
/**
* Get the URL for the previous page, or null.
*/
public function previousPageUrl(): ?string;
/**
* Get all of the items being paginated.
*/
public function items(): array;
/**
* Get the "index" of the first item being paginated.
*/
public function firstItem(): ?int;
/**
* Get the "index" of the last item being paginated.
*/
public function lastItem(): ?int;
/**
* Determine how many items are being shown per page.
*/
public function perPage(): int;
/**
* Determine the current page being paginated.
*/
public function currentPage(): int;
/**
* Determine if there are enough items to split into multiple pages.
*/
public function hasPages(): bool;
/**
* Determine if there is more items in the data store.
*/
public function hasMorePages(): bool;
/**
* Determine if the list of items is empty or not.
*/
public function isEmpty(): bool;
/**
* Determine if the list of items is not empty.
*/
public function isNotEmpty(): bool;
/**
* Render the paginator using a given view.
*/
public function render(?string $view = null, array $data = []): string;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface PoolInterface
{
/**
* Get a connection from the connection pool.
*/
public function get(): ConnectionInterface;
/**
* Release a connection back to the connection pool.
*/
public function release(ConnectionInterface $connection): void;
/**
* Close and clear the connection pool.
*/
public function flush(): void;
public function getOption(): PoolOptionInterface;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface PoolOptionInterface
{
public function getMaxConnections(): int;
public function getMinConnections(): int;
public function getConnectTimeout(): float;
public function getWaitTimeout(): float;
public function getHeartbeat(): float;
public function getMaxIdleTime(): float;
public function getEvents(): array;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
use Swoole\Coroutine\Http\Server as CoHttpServer;
use Swoole\Coroutine\Server as CoServer;
use Swoole\Server;
interface ProcessInterface
{
/**
* Create the process object according to process number and bind to server.
* @param CoHttpServer|CoServer|Server $server
*/
public function bind($server): void;
/**
* Determine if the process should start ?
* @param CoServer|Server $server
*/
public function isEnable($server): bool;
/**
* The logical of process will place in here.
*/
public function handle(): void;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
use Psr\Http\Message\ResponseInterface;
interface ResponseEmitterInterface
{
/**
* @param mixed $connection swoole response or swow session
*/
public function emit(ResponseInterface $response, mixed $connection, bool $withContent = true): void;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
use RuntimeException;
interface SessionInterface
{
/**
* Starts the session storage.
*
* @return bool True if session started
* @throws RuntimeException if session fails to start
*/
public function start(): bool;
/**
* Returns the session ID.
*
* @return string The session ID
*/
public function getId(): string;
/**
* Sets the session ID.
*/
public function setId(string $id);
/**
* Returns the session name.
*/
public function getName(): string;
/**
* Sets the session name.
*/
public function setName(string $name);
/**
* Invalidates the current session.
*
* Clears all session attributes and flashes and regenerates the
* session and deletes the old session from persistence.
*
* @param int $lifetime Sets the cookie lifetime for the session cookie. A null value
* will leave the system settings unchanged, 0 sets the cookie
* to expire with browser session. Time is in seconds, and is
* not a Unix timestamp.
*
* @return bool True if session invalidated, false if error
*/
public function invalidate(?int $lifetime = null): bool;
/**
* Migrates the current session to a new session id while maintaining all
* session attributes.
*
* @param bool $destroy Whether to delete the old session or leave it to garbage collection
* @param int $lifetime Sets the cookie lifetime for the session cookie. A null value
* will leave the system settings unchanged, 0 sets the cookie
* to expire with browser session. Time is in seconds, and is
* not a Unix timestamp.
*
* @return bool True if session migrated, false if error
*/
public function migrate(bool $destroy = false, ?int $lifetime = null): bool;
/**
* Force the session to be saved and closed.
*
* This method is generally not required for real sessions as
* the session will be automatically saved at the end of
* code execution.
*/
public function save(): void;
/**
* Checks if an attribute is defined.
*
* @param string $name The attribute name
*
* @return bool true if the attribute is defined, false otherwise
*/
public function has(string $name): bool;
/**
* Returns an attribute.
*
* @param string $name The attribute name
* @param mixed $default The default value if not found
*/
public function get(string $name, $default = null);
/**
* Sets an attribute.
* @param mixed $value
*/
public function set(string $name, $value): void;
/**
* Put a key / value pair or array of key / value pairs in the session.
*
* @param array|string $key
* @param null|mixed $value
*/
public function put($key, $value = null): void;
/**
* Returns attributes.
*/
public function all(): array;
/**
* Sets attributes.
*/
public function replace(array $attributes): void;
/**
* Removes an attribute, returning its value.
*
* @return mixed The removed value or null when it does not exist
*/
public function remove(string $name);
/**
* Remove one or many items from the session.
*
* @param array|string $keys
*/
public function forget($keys): void;
/**
* Clears all attributes.
*/
public function clear(): void;
/**
* Checks if the session was started.
*/
public function isStarted(): bool;
/**
* Get the previous URL from the session.
*/
public function previousUrl(): ?string;
/**
* Set the "previous" URL in the session.
*/
public function setPreviousUrl(string $url): void;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
use Psr\Log\LoggerInterface;
interface StdoutLoggerInterface extends LoggerInterface
{
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface Synchronized
{
/**
* Whether the data has been synchronized.
*/
public function isSynchronized(): bool;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
use Countable;
interface TranslatorInterface
{
/**
* Get the translation for a given key.
*/
public function trans(string $key, array $replace = [], ?string $locale = null): array|string;
/**
* Get a translation according to an integer value.
*
* @param array|Countable|int $number
*/
public function transChoice(string $key, $number, array $replace = [], ?string $locale = null): string;
/**
* Get the default locale being used.
*/
public function getLocale(): string;
/**
* Set the default locale.
*/
public function setLocale(string $locale);
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface TranslatorLoaderInterface
{
/**
* Load the messages for the given locale.
*/
public function load(string $locale, string $group, ?string $namespace = null): array;
/**
* Add a new namespace to the loader.
*/
public function addNamespace(string $namespace, string $hint);
/**
* Add a new JSON path to the loader.
*/
public function addJsonPath(string $path);
/**
* Get an array of all the registered namespaces.
*/
public function namespaces(): array;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface UnCompressInterface
{
public function uncompress();
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
interface ValidatorInterface extends MessageProvider
{
/**
* Run the validator's rules against its data.
*/
public function validate(): array;
/**
* Get the attributes and values that were validated.
*/
public function validated(): array;
/**
* Determine if the data fails the validation rules.
*/
public function fails(): bool;
/**
* Get the failed validation rules.
*/
public function failed(): array;
/**
* Add conditions to a given field based on a Closure.
*
* @param array|string $attribute
* @param array|string $rules
* @return $this
*/
public function sometimes($attribute, $rules, callable $callback);
/**
* Add an after validation callback.
*
* @param callable|string $callback
* @return $this
*/
public function after($callback);
/**
* Get all of the validation error messages.
*/
public function errors(): MessageBag;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Contract;
use Stringable;
interface Xmlable extends Stringable
{
public function __toString(): string;
}
/tests export-ignore
/.github export-ignore
/vendor/
composer.lock
*.cache
*.log
.vscode
.idea/*
\ No newline at end of file
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
$header = <<<'EOF'
This file is part of Hyperf.
@link https://www.hyperf.io
@document https://hyperf.wiki
@contact group@hyperf.io
@license https://github.com/hyperf/hyperf/blob/master/LICENSE
EOF;
return (new PhpCsFixer\Config())
->setRiskyAllowed(true)
->setRules([
'@PSR2' => true,
'@Symfony' => true,
'@DoctrineAnnotation' => true,
'@PhpCsFixer' => true,
'header_comment' => [
'comment_type' => 'PHPDoc',
'header' => $header,
'separate' => 'none',
'location' => 'after_declare_strict',
],
'array_syntax' => [
'syntax' => 'short',
],
'list_syntax' => [
'syntax' => 'short',
],
'concat_space' => [
'spacing' => 'one',
],
'blank_line_before_statement' => [
'statements' => [
'declare',
],
],
'general_phpdoc_annotation_remove' => [
'annotations' => [
'author',
],
],
'ordered_imports' => [
'imports_order' => [
'class', 'function', 'const',
],
'sort_algorithm' => 'alpha',
],
'single_line_comment_style' => [
'comment_types' => [
],
],
'yoda_style' => [
'always_move_variable' => false,
'equal' => false,
'identical' => false,
],
'phpdoc_align' => [
'align' => 'left',
],
'multiline_whitespace_before_semicolons' => [
'strategy' => 'no_multi_line',
],
'constant_case' => [
'case' => 'lower',
],
'global_namespace_import' => [
'import_classes' => true,
'import_constants' => true,
'import_functions' => true,
],
'class_attributes_separation' => true,
'combine_consecutive_unsets' => true,
'declare_strict_types' => true,
'linebreak_after_opening_tag' => true,
'lowercase_static_reference' => true,
'no_useless_else' => true,
'no_unused_imports' => true,
'not_operator_with_successor_space' => true,
'not_operator_with_space' => false,
'ordered_class_elements' => true,
'php_unit_strict' => false,
'phpdoc_separation' => false,
'single_quote' => true,
'standardize_not_equals' => true,
'multiline_comment_opening_closing' => true,
'single_line_empty_body' => false,
])
->setFinder(
PhpCsFixer\Finder::create()
->exclude('vendor')
->in(__DIR__)
)
->setUsingCache(false);
<?php
namespace PHPSTORM_META {
// Reflect
override(\Psr\Container\ContainerInterface::get(0), map('@'));
}
\ No newline at end of file
The MIT License (MIT)
Copyright (c) Hyperf
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# Contract for Coroutine Engine
[![PHPUnit](https://github.com/hyperf/engine-contract/actions/workflows/test.yml/badge.svg)](https://github.com/hyperf/engine-contract/actions/workflows/test.yml)
## How to install
```
composer require hyperf/engine-contract
```
{
"name": "hyperf/engine-contract",
"type": "library",
"license": "MIT",
"keywords": [
"php",
"hyperf",
"coroutine",
"contract",
"engine"
],
"description": "Contract for Coroutine Engine",
"autoload": {
"psr-4": {
"Hyperf\\Engine\\Contract\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"HyperfTest\\": "tests"
}
},
"require": {
"php": ">=8.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.0",
"mockery/mockery": "^1.0",
"phpstan/phpstan": "^1.0",
"phpunit/phpunit": ">=7.0",
"psr/http-message": "^1.0",
"swoole/ide-helper": "^4.5"
},
"suggest": {
"psr/http-message": "Required to use WebSocket Frame."
},
"minimum-stability": "dev",
"prefer-stable": true,
"config": {
"optimize-autoloader": true,
"sort-packages": true
},
"extra": {
"branch-alias": {
"dev-master": "1.11-dev"
}
},
"scripts": {
"test": "phpunit -c phpunit.xml --colors=always",
"analyse": "phpstan analyse --memory-limit 1024M -l 0 ./src",
"cs-fix": "php-cs-fixer fix $1"
}
}
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
bootstrap="tests/bootstrap.php"
backupGlobals="false"
colors="true"
processIsolation="false"
stopOnFailure="false"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.0/phpunit.xsd"
cacheDirectory=".phpunit.cache"
backupStaticProperties="false"
>
<testsuite name="Testsuite">
<directory>./tests/</directory>
</testsuite>
</phpunit>
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Engine\Contract;
interface BarrierInterface
{
/**
* Wait for the barrier to be released.
*/
public static function wait(object &$barrier, int $timeout = -1): void;
/**
* Create a new barrier instance.
*
* @return BarrierInterface
*/
public static function create(): object;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Engine\Contract;
/**
* @template TValue of mixed
*/
interface ChannelInterface
{
/**
* @param TValue $data
* @param float|int $timeout seconds [optional] = -1
*/
public function push(mixed $data, float $timeout = -1): bool;
/**
* @param float $timeout seconds [optional] = -1
* @return false|TValue when pop failed, return false
*/
public function pop(float $timeout = -1): mixed;
/**
* Swow: When the channel is closed, all the data in it will be destroyed.
* Swoole: When the channel is closed, the data in it can still be popped out, but push behavior will no longer succeed.
*/
public function close(): bool;
public function getCapacity(): int;
public function getLength(): int;
public function isAvailable(): bool;
public function hasProducers(): bool;
public function hasConsumers(): bool;
public function isEmpty(): bool;
public function isFull(): bool;
public function isReadable(): bool;
public function isWritable(): bool;
public function isClosing(): bool;
public function isTimeout(): bool;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Engine\Contract;
use ArrayObject;
use Hyperf\Engine\Exception\CoroutineDestroyedException;
use Hyperf\Engine\Exception\RunningInNonCoroutineException;
interface CoroutineInterface
{
/**
* @param callable $callable [required]
*/
public function __construct(callable $callable);
/**
* @param mixed ...$data
*/
public function execute(...$data): static;
public function getId(): int;
/**
* @param callable $callable [required]
* @param mixed ...$data
* @return $this
*/
public static function create(callable $callable, ...$data): static;
/**
* @return int returns coroutine id from current coroutine, -1 in non coroutine environment
*/
public static function id(): int;
/**
* Returns the parent coroutine ID.
* Returns 0 when running in the top level coroutine.
* @throws RunningInNonCoroutineException when running in non-coroutine context
* @throws CoroutineDestroyedException when the coroutine has been destroyed
*/
public static function pid(?int $id = null): int;
/**
* Set config to coroutine.
*/
public static function set(array $config): void;
/**
* @param null|int $id coroutine id
*/
public static function getContextFor(?int $id = null): ?ArrayObject;
/**
* Execute callback when coroutine destruct.
*/
public static function defer(callable $callable): void;
/**
* Yield the current coroutine.
* @param mixed $data only Support Swow
* @return bool|mixed Swow:mixed, Swoole:bool
*/
public static function yield(mixed $data = null): mixed;
/**
* Resume the coroutine by coroutine Id.
* @param mixed $data only Support Swow
* @return bool|mixed Swow:mixed, Swoole:bool
*/
public static function resumeById(int $id, mixed ...$data): mixed;
/**
* Get the coroutine stats.
*/
public static function stats(): array;
/**
* Check if a coroutine exists or not.
*/
public static function exists(int $id): bool;
/**
* @return iterable<int> returns all coroutine IDs
*/
public static function list(): iterable;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Engine\Contract;
interface DefaultOptionInterface
{
/**
* Get Hook Coroutine Flags.
*/
public static function hookFlags(): int;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Engine\Contract\Http;
interface ClientInterface
{
public function set(array $settings): bool;
/**
* @param string[][] $headers
*/
public function request(string $method = 'GET', string $path = '/', array $headers = [], string $contents = '', string $version = '1.1'): RawResponseInterface;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Engine\Contract\Http;
use Stringable;
interface Http
{
public const DEFAULT_PROTOCOL_VERSION = '1.1';
public static function packRequest(string $method, string|Stringable $path, array $headers = [], string|Stringable $body = '', string $protocolVersion = self::DEFAULT_PROTOCOL_VERSION): string;
public static function packResponse(int $statusCode, string $reasonPhrase = '', array $headers = [], string|Stringable $body = '', string $protocolVersion = self::DEFAULT_PROTOCOL_VERSION): string;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Engine\Contract\Http;
interface RawResponseInterface
{
public function getStatusCode(): int;
/**
* @return string[][]
*/
public function getHeaders(): array;
public function getBody(): string;
public function getVersion(): string;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Engine\Contract\Http;
interface ServerFactoryInterface
{
public function make(string $name, int $port = 0): ServerInterface;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Engine\Contract\Http;
interface ServerInterface
{
public function handle(callable $callable): static;
public function start(): void;
public function close(): bool;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Engine\Contract\Http\V2;
interface ClientFactoryInterface
{
public function make(string $host, int $port = 80, bool $ssl = false);
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Engine\Contract\Http\V2;
interface ClientInterface
{
public function set(array $settings): bool;
/**
* @return int StreamID
*/
public function send(RequestInterface $request): int;
public function recv(float $timeout = 0): ResponseInterface;
public function write(int $streamId, mixed $data, bool $end = false): bool;
public function ping(): bool;
public function close(): bool;
public function isConnected(): bool;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Engine\Contract\Http\V2;
interface RequestInterface
{
public function getPath(): string;
public function getMethod(): string;
public function getHeaders(): array;
public function getBody(): string;
public function isPipeline(): bool;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Engine\Contract\Http\V2;
interface ResponseInterface
{
public function getStreamId(): int;
public function getStatusCode(): int;
public function getHeaders(): array;
public function getBody(): ?string;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Engine\Contract\Http;
interface Writable
{
public function getSocket(): mixed;
public function write(string $data): bool;
public function end(): ?bool;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Engine\Contract;
use Psr\Http\Message\ResponseInterface;
interface ResponseEmitterInterface
{
/**
* @param mixed $connection swoole response or swow session
*/
public function emit(ResponseInterface $response, mixed $connection, bool $withContent = true): void;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Engine\Contract;
interface SignalInterface
{
public static function wait(int $signo, float $timeout = -1): bool;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Engine\Contract\Socket;
use Hyperf\Engine\Contract\SocketInterface;
interface SocketFactoryInterface
{
public function make(SocketOptionInterface $option): SocketInterface;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Engine\Contract\Socket;
interface SocketOptionInterface
{
public function getHost(): string;
public function getPort(): int;
/**
* Connect timeout, seconds.
*/
public function getTimeout(): ?float;
/**
* @return [
* 'open_length_check' => true,
* 'package_max_length' => 1024 * 1024 * 2,
* 'package_length_type' => 'N',
* 'package_length_offset' => 0,
* 'package_body_offset' => 4,
* ]
*/
public function getProtocol(): array;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Engine\Contract;
interface SocketInterface
{
public function sendAll(string $data, float $timeout = 0): false|int;
public function recvAll(int $length = 65536, float $timeout = 0): false|string;
public function recvPacket(float $timeout = 0): false|string;
public function close(): bool;
}
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Engine\Contract\WebSocket;
use Psr\Http\Message\StreamInterface;
use Stringable;
interface FrameInterface extends Stringable
{
public function getOpcode(): int;
public function setOpcode(int $opcode): static;
public function withOpcode(int $opcode): static;
public function getFin(): bool;
public function setFin(bool $fin): static;
public function withFin(bool $fin): static;
public function getRSV1(): bool;
public function setRSV1(bool $rsv1): static;
public function withRSV1(bool $rsv1): static;
public function getRSV2(): bool;
public function setRSV2(bool $rsv2): static;
public function withRSV2(bool $rsv2): static;
public function getRSV3(): bool;
public function setRSV3(bool $rsv3): static;
public function withRSV3(bool $rsv3): static;
public function getPayloadLength(): int;
public function setPayloadLength(int $payloadLength): static;
public function withPayloadLength(int $payloadLength): static;
public function getMask(): bool;
public function getMaskingKey(): string;
public function setMaskingKey(string $maskingKey): static;
public function withMaskingKey(string $maskingKey): static;
public function getPayloadData(): StreamInterface;
public function setPayloadData(mixed $payloadData): static;
public function withPayloadData(mixed $payloadData): static;
public function toString(bool $withoutPayloadData = false): string;
public static function from(mixed $frame): static;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment