mirror of
http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore.git
synced 2026-01-15 07:15:06 +08:00
Compare commits
24 Commits
v1.0.0-bet
...
v0.1.7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52f4867c72 | ||
|
|
b51699b0d9 | ||
|
|
a570e1964e | ||
|
|
def9f0469d | ||
|
|
5ed5070f32 | ||
|
|
8dcf586baf | ||
|
|
a7a8087509 | ||
|
|
e50a2e08df | ||
|
|
fca8f9d013 | ||
|
|
113e7fca57 | ||
|
|
24161f0841 | ||
|
|
fe3181c7d1 | ||
|
|
6c27804856 | ||
|
|
c3eb95d300 | ||
|
|
a7a61bd674 | ||
|
|
7fd7d23051 | ||
|
|
0b4fb23779 | ||
|
|
eb20bc9fdb | ||
|
|
01350cbb6c | ||
|
|
1f0ef04c7a | ||
|
|
4b2c03f8ec | ||
|
|
0fa3c23a3e | ||
|
|
c83728cad2 | ||
|
|
3e2d3400b4 |
6
.idea/HDK-Core.iml
generated
6
.idea/HDK-Core.iml
generated
@@ -64,8 +64,6 @@
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/http-message" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/exception-handler" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/macroable" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/resource" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/paginator" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/engine" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/pool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/event" />
|
||||
@@ -135,14 +133,12 @@
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/nunomaduro/collision" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/pestphp/pest" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/stopwatch" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/spatie/test-time" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpstan/phpstan" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/pestphp/pest-plugin" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/friendsofphp/php-cs-fixer" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/facade/ignition-contracts" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/spatie/pest-plugin-test-time" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/filp/whoops" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/deprecations" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/facade/ignition-contracts" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
|
||||
6
.idea/php.xml
generated
6
.idea/php.xml
generated
@@ -79,8 +79,6 @@
|
||||
<path value="$PROJECT_DIR$/vendor/hyperf/http-message" />
|
||||
<path value="$PROJECT_DIR$/vendor/hyperf/exception-handler" />
|
||||
<path value="$PROJECT_DIR$/vendor/hyperf/macroable" />
|
||||
<path value="$PROJECT_DIR$/vendor/hyperf/resource" />
|
||||
<path value="$PROJECT_DIR$/vendor/hyperf/paginator" />
|
||||
<path value="$PROJECT_DIR$/vendor/hyperf/engine" />
|
||||
<path value="$PROJECT_DIR$/vendor/hyperf/pool" />
|
||||
<path value="$PROJECT_DIR$/vendor/hyperf/event" />
|
||||
@@ -151,8 +149,6 @@
|
||||
<path value="$PROJECT_DIR$/vendor/filp/whoops" />
|
||||
<path value="$PROJECT_DIR$/vendor/nunomaduro/collision" />
|
||||
<path value="$PROJECT_DIR$/vendor/facade/ignition-contracts" />
|
||||
<path value="$PROJECT_DIR$/vendor/spatie/test-time" />
|
||||
<path value="$PROJECT_DIR$/vendor/spatie/pest-plugin-test-time" />
|
||||
<path value="$PROJECT_DIR$/vendor/friendsofphp/php-cs-fixer" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/options-resolver" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/stopwatch" />
|
||||
@@ -160,7 +156,7 @@
|
||||
<path value="$PROJECT_DIR$/vendor/doctrine/deprecations" />
|
||||
</include_path>
|
||||
</component>
|
||||
<component name="PhpProjectSharedConfiguration" php_language_level="8.0" />
|
||||
<component name="PhpProjectSharedConfiguration" php_language_level="7.4" />
|
||||
<component name="PhpStan">
|
||||
<PhpStan_settings>
|
||||
<PhpStanConfiguration tool_path="$PROJECT_DIR$/vendor/bin/phpstan" />
|
||||
|
||||
119
CHANGELOG.md
Normal file
119
CHANGELOG.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# 版本更新日志
|
||||
### [0.1.7](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.1.6...v0.1.7) (2023-07-05)
|
||||
|
||||
|
||||
### 📦 Build System | 打包构建
|
||||
|
||||
* **composer:** 更新依赖 ([a570e19](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/a570e1964e01b9e29de05f4a7607a4ed567beffa))
|
||||
|
||||
|
||||
### ✨ Features | 新功能
|
||||
|
||||
* **session:** 增加了定制的 session 中间件 ([b51699b](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/b51699b0d98322df33fb3a0bccebe5f4034e2a71))
|
||||
|
||||
### [0.1.6](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.1.5...v0.1.6) (2023-03-21)
|
||||
|
||||
|
||||
### 🐛 Bug Fixes | Bug 修复
|
||||
|
||||
* **middleware.i18n:** 尝试修复了多语言无法正确获取的问题 ([a7a8087](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/a7a80875092653e56d8dc9351743a08933d59282))
|
||||
|
||||
|
||||
### ✅ Tests | 测试
|
||||
|
||||
* **email:** 更新了邮件发送的测试账号 ([8dcf586](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/8dcf586baf1960f906d63c15f3d659b16b456048))
|
||||
|
||||
|
||||
### 📦 Build System | 打包构建
|
||||
|
||||
* **composer:** 更新依赖 ([5ed5070](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/5ed5070f323d0ea34b8c99b5ac826dc6c24431df))
|
||||
|
||||
### [0.1.5](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.1.4...v0.1.5) (2023-02-03)
|
||||
|
||||
|
||||
### 🐛 Bug Fixes | Bug 修复
|
||||
|
||||
* **commonHandler:** 修复了一处兼容问题 ([fca8f9d](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/fca8f9d013e1d121bf8bc997710d77ff038fdae0))
|
||||
|
||||
### [0.1.4](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.1.3...v0.1.4) (2023-02-02)
|
||||
|
||||
|
||||
### 💄 Styles | 风格
|
||||
|
||||
* **cs-fixer:** prettier ([24161f0](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/24161f084127602a32d9a7ca3af122eb26169fec))
|
||||
|
||||
### [0.1.3](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.1.2...v0.1.3) (2023-02-02)
|
||||
|
||||
|
||||
### 📦 Build System | 打包构建
|
||||
|
||||
* **composer:** 修复 php 版本限制 ([0b4fb23](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/0b4fb2377985dc70a2cfa5a603f73e2ced14dc8c))
|
||||
* **composer:** 修复 php 版本限制 ([eb20bc9](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/eb20bc9fdbc887d0e478a3ceaa4396001fbbbdfd))
|
||||
|
||||
|
||||
### ✨ Features | 新功能
|
||||
|
||||
* **email/sms:** 添加了发送邮件和短信的事件 ([7fd7d23](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/7fd7d2305120f60b70390b49c6256b01fbec6485))
|
||||
|
||||
|
||||
### 🐛 Bug Fixes | Bug 修复
|
||||
|
||||
* **extend:** 修复了解析不到为null不为数组的问题 ([c3eb95d](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/c3eb95d300f312b14204edd6b97d80b76c273ff3))
|
||||
* **extend:** 修复了解析不到为null不为数组的问题 ([a7a61bd](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/a7a61bd6748ca432e95c396738ebdd7dcfe96463))
|
||||
* **extend:** 修复了解析不到为空不为数组的问题 ([6c27804](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/6c278048568c6b070192b290f54562f05c1803e6))
|
||||
|
||||
### [0.1.2](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.1.1...v0.1.2) (2023-01-28)
|
||||
|
||||
|
||||
### 📦 Build System | 打包构建
|
||||
|
||||
* **composer:** 修复 ConfigProvider 命名空间 ([1f0ef04](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/1f0ef04c7a092e2d7df1cafb94b3a50a04ee66cd))
|
||||
|
||||
### 0.1.1 (2023-01-28)
|
||||
|
||||
|
||||
### 🎉 Init | 初始化
|
||||
|
||||
* **core:** 初始化代码 ([f564d01](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/f564d01766f52fc57f07aa05bd995a5662c2ae45))
|
||||
* 初始化项目 ([a13779a](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/a13779ab3fb617189227b9d2c0462588be8ceee5))
|
||||
|
||||
|
||||
### ⚡ Performance Improvements | 性能优化
|
||||
|
||||
* **utils:** 获取真实IP方法,增加apache的处理 ([47e522c](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/47e522c67bf595282df7671f1d045e44593022bf))
|
||||
|
||||
|
||||
### 🚀 Chore | 构建/工程依赖/工具
|
||||
|
||||
* 移除调试用的打印语句 ([37ed1ce](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/37ed1cef77d094f6cd78dd1c97f5d2e3cf6376a3))
|
||||
* **tests:** 移除了示例测试文件 ([e705bed](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/e705bedd5d3e72887e9e5fac35926237db844116))
|
||||
|
||||
|
||||
### 📦 Build System | 打包构建
|
||||
|
||||
* **ci:** 完善 style-fix/syntax-check/unit-test ([52ff5cc](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/52ff5ccb048d41d003b7e044c446c2f04a013bdb))
|
||||
* **ci:** 完善 style-fix/syntax-check/unit-test ([4b7f118](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/4b7f1189d33e8871091d05d330ed16fa98048dd9))
|
||||
* **composer:** update dependencies ([e004ab4](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/e004ab402df9185ead225a3398077f3e39dffe92))
|
||||
* **composer:** 更新依赖 ([1e4fbe5](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/1e4fbe59276ed2913aa21973f9502505115d2628))
|
||||
* **composer:** 添加依赖到开发环境 ([9f5699f](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/9f5699f39cd7a89c37e9365322c6082a97a973f4))
|
||||
* **version:** 添加changelog配置 ([4deffe0](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/4deffe055ebe8586a183103d84dcd5b97969ca7d))
|
||||
|
||||
|
||||
### ✏️ Documentation | 文档
|
||||
|
||||
* **core:** 添加作者信息 ([096d4e5](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/096d4e56ed30c23de1338bb6f057a91e629c6ea5))
|
||||
* **README:** 修复一直报错的文件名 ([135db1b](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/135db1bf6aeeedbb0d59405567bb4837f3221e49))
|
||||
* **README:** 增加说明文件 ([4cf16ae](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/4cf16ae0cdcf6f7a1eb99fde95a6c3ef01bd7b2b))
|
||||
* **README:** 提示版本过期,需要更新 ([3e2d340](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/3e2d3400b45edf4b503a91c078aaa3ef0fff553e))
|
||||
|
||||
|
||||
### ✨ Features | 新功能
|
||||
|
||||
* 增加了inArray、hasExtends方法 ([c83728c](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/c83728cad28438c3bcef9d946680fe1637a6814f))
|
||||
* **utils:** 重写了构造URL的方法,增加对应的单元测试 ([9f79d14](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/9f79d1465ba6ed4b4c0d0c30e23ffa34bbeece65))
|
||||
* 迁移到了 Core 命名空间下 ([a8a582f](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/a8a582f3aa0948c982e31bf8938b6f3331d8dc6d))
|
||||
|
||||
|
||||
### ♻️ Code Refactoring | 代码重构
|
||||
|
||||
* 向后兼容到7.4 ([0fa3c23](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/0fa3c23a3e249cd2473a468ee64d7efc8b6eafe3))
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
The Common HDK for Any project by Hyperf.
|
||||
|
||||
> DEPRECATED!!!
|
||||
>
|
||||
> This Branch is outdated,
|
||||
> only used for support old versions.
|
||||
> Such as Hyperf 2.2 or less.
|
||||
>
|
||||
> Please UPGRADE your version to Hyperf 3.0
|
||||
> and HDK-Core 0.2.*
|
||||
|
||||
## PHP Versions
|
||||
|
||||
This version will work on Hyperf version 2.2 and above.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"description": "Common Hyperf Development Kit",
|
||||
"extra": {
|
||||
"hyperf": {
|
||||
"config": "Singularity\\HDK\\ConfigProvider"
|
||||
"config": "Singularity\\HDK\\Core\\ConfigProvider"
|
||||
}
|
||||
},
|
||||
"authors": [
|
||||
@@ -15,7 +15,7 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "~8.0",
|
||||
"php": "^7.4|^8.0",
|
||||
"ext-redis": "^5.3",
|
||||
"ext-swoole": "*",
|
||||
"composer/composer": ">=2.0",
|
||||
@@ -29,41 +29,48 @@
|
||||
"hyperf/http-server": "^2.2",
|
||||
"hyperf/logger": "^2.2",
|
||||
"hyperf/redis": "^2.2",
|
||||
"hyperf/resource": "^2.2",
|
||||
"hyperf/translation": "^2.2",
|
||||
"jetbrains/phpstorm-attributes": "^1.0",
|
||||
"lmc/http-constants": "^1.2",
|
||||
"myclabs/php-enum": "^1.8",
|
||||
"roave/dont": "^1.5",
|
||||
"symfony/polyfill-php81": "^1.26",
|
||||
"myclabs/php-enum": "^1.8.4",
|
||||
"roave/dont": "^1.1",
|
||||
"symfony/polyfill-php81": "^1.27",
|
||||
"teapot/status-code": "^1.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"alibabacloud/dysmsapi-20170525": "^2.0",
|
||||
"firebase/php-jwt": "^6.1",
|
||||
"firebase/php-jwt": "^6.3",
|
||||
"friendsofphp/php-cs-fixer": "^3.13",
|
||||
"guzzlehttp/guzzle": "^7.5",
|
||||
"hyperf/crontab": "<=3.0.9 || >3.0.13 <3.1",
|
||||
"hyperf/session": "^2.2",
|
||||
"hyperf/validation": "^2.2",
|
||||
"pestphp/pest": "^1.22",
|
||||
"phpstan/phpstan": "^1.9",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"roave/security-advisories": "dev-latest",
|
||||
"spatie/pest-plugin-test-time": "^1.1",
|
||||
"swoole/ide-helper": "*",
|
||||
"symfony/mailer": "^6.0"
|
||||
"symfony/mailer": "^5.4"
|
||||
},
|
||||
"suggest": {
|
||||
"hyperf/resource": "If you need",
|
||||
"firebase/php-jwt": "JWT 鉴权必需",
|
||||
"hyperf/session": "Session 鉴权必需",
|
||||
"symfony/mailer": "用于发送电子邮件",
|
||||
"guzzlehttp/guzzle": "需要发起 http 请求时必需",
|
||||
"alibabacloud/dysmsapi-20170525": "阿里云短信服务必需"
|
||||
"alibabacloud/dysmsapi-20170525": "阿里云短信服务必需",
|
||||
"laminas/laminas-text": "用于cli展示表格和大字",
|
||||
"gevman/interactive-cli": "用于提供漂亮的交互式命令行",
|
||||
"clue/stdio-react": "一个基于 reactphp 的交互式命令行",
|
||||
"brainmaestro/composer-git-hooks": "用于 php 项目的 git-hooks"
|
||||
},
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"sort-packages": true,
|
||||
"secure-http": false
|
||||
"secure-http": false,
|
||||
"allow-plugins": {
|
||||
"pestphp/pest-plugin": true
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
@@ -106,5 +113,6 @@
|
||||
"type": "composer",
|
||||
"url": "https://repo.huaweicloud.com/repository/php/"
|
||||
}
|
||||
}
|
||||
},
|
||||
"version": "0.1.7"
|
||||
}
|
||||
|
||||
779
composer.lock
generated
Executable file → Normal file
779
composer.lock
generated
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
76
docs/Email.md
Normal file
76
docs/Email.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Email | 邮件
|
||||
提供一套通用 Service 用于定制需求,和一套现成的事件/监听器用于异步发送。
|
||||
|
||||
## 服务类
|
||||
[\Singularity\HDK\Core\Service\EmailService](../src/Service/EmailService.php)
|
||||
* 发送纯文本邮件的 `\Singularity\HDK\Core\Service\EmailService::sendText()`
|
||||
* 发送 Html 富文本邮件的 `\Singularity\HDK\Core\Service\EmailService::sendHtml()`
|
||||
|
||||
## 事件机制
|
||||
> 这种方式无法监听邮件发送的结果!
|
||||
>
|
||||
> 如果你需要根据邮件发送的结果进行处理,
|
||||
> 请使用服务类进行自定义
|
||||
|
||||
更好的方法可能是在事件发生后触发异步队列,
|
||||
但如果将异步队列封装在本包中,
|
||||
相当于强制引用本库的项目使用异步队列机制,
|
||||
这是我们不愿意看到的。
|
||||
所以这里的监听器只是集成了同步发送的操作。
|
||||
|
||||
如果你想要定义更好的设计,
|
||||
你可以直接使用提供的 Service 类进行定制。
|
||||
> 或许这里还有优化空间😄
|
||||
|
||||
### 事件
|
||||
[\Singularity\HDK\Core\Events\EmailWillSent](../src/Events/EmailWillSent.php)
|
||||
### 监听器
|
||||
[\Singularity\HDK\Core\Listener\EmailWillSentListener](../src/Listener/EmailWillSentListener.php)
|
||||
### 使用方法
|
||||
监听器已经通过 [ConfigProvider](../src/ConfigProvider.php) 机制注册,
|
||||
所以你只需要在要发送邮件的地方调度这个事件即可。
|
||||
> 这也就意味着,你无法调用这个事件,但不触发这个监听器。
|
||||
> 如果你有这样做的必要,请创建一个自己的事件。
|
||||
> 这也是为了保证功能的完整性和原子性。
|
||||
|
||||
具体使用方法,如下代码所示:
|
||||
|
||||
```php
|
||||
<?php
|
||||
namespace App\Service;
|
||||
|
||||
use Hyperf\Di\Annotation\Inject;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use App\Event\UserRegistered;use Singularity\HDK\Core\Events\EmailWillSent;
|
||||
|
||||
class UserService
|
||||
{
|
||||
/**
|
||||
* @var EventDispatcherInterface
|
||||
*/
|
||||
#[Inject]
|
||||
private $eventDispatcher;
|
||||
|
||||
public function register()
|
||||
{
|
||||
// 我们假设存在 User 这个实体
|
||||
$user = new User();
|
||||
$result = $user->save();
|
||||
|
||||
// ↓
|
||||
// 这里 dispatch(object $event) 会逐个运行监听该事件的监听器
|
||||
$this->eventDispatcher->dispatch(new EmailWillSent(
|
||||
target: $user->mobile,
|
||||
subject: '注册成功通知',
|
||||
type: 'html', // 默认 text 可以不传
|
||||
content: <<<HTML
|
||||
<h1>恭喜你,注册成功!</h1>
|
||||
HTML,
|
||||
));
|
||||
// ↑
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
75
docs/Sms.md
Normal file
75
docs/Sms.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# SMS | 短信
|
||||
提供一套通用 Service 用于定制需求,和一套现成的事件/监听器用于异步发送。
|
||||
|
||||
## 服务类
|
||||
[\Singularity\HDK\Core\Service\SmsService](../src/Service/SmsService.php)
|
||||
* 发送国内短信的 `\Singularity\HDK\Core\Service\SmsService::sendSmsCountryside()`
|
||||
|
||||
## 事件机制
|
||||
> 这种方式无法监听短信发送的结果!
|
||||
>
|
||||
> 如果你需要根据短信发送的结果进行处理,
|
||||
> 请使用服务类进行自定义
|
||||
|
||||
更好的方法可能是在事件发生后触发异步队列,
|
||||
但如果将异步队列封装在本包中,
|
||||
相当于强制引用本库的项目使用异步队列机制,
|
||||
这是我们不愿意看到的。
|
||||
所以这里的监听器只是集成了同步发送的操作。
|
||||
|
||||
如果你想要定义更好的设计,
|
||||
你可以直接使用提供的 Service 类进行定制。
|
||||
> 或许这里还有优化空间😄
|
||||
|
||||
### 事件
|
||||
[\Singularity\HDK\Core\Events\SmsWillSent](../src/Events/SmsWillSent.php)
|
||||
### 监听器
|
||||
[\Singularity\HDK\Core\Listener\SmsWillSentListener](../src/Listener/SmsWillSentListener.php)
|
||||
### 使用方法
|
||||
监听器已经通过 [ConfigProvider](../src/ConfigProvider.php) 机制注册,
|
||||
所以你只需要在要发送短信的地方调度这个事件即可。
|
||||
> 这也就意味着,你无法调用这个事件,但不触发这个监听器。
|
||||
> 如果你有这样做的必要,请创建一个自己的事件。
|
||||
> 这也是为了保证功能的完整性和原子性。
|
||||
|
||||
具体使用方法,如下代码所示:
|
||||
|
||||
```php
|
||||
<?php
|
||||
namespace App\Service;
|
||||
|
||||
use Hyperf\Di\Annotation\Inject;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use App\Event\UserRegistered;use Singularity\HDK\Core\Events\EmailWillSent;
|
||||
|
||||
class UserService
|
||||
{
|
||||
/**
|
||||
* @var EventDispatcherInterface
|
||||
*/
|
||||
#[Inject]
|
||||
private $eventDispatcher;
|
||||
|
||||
public function register()
|
||||
{
|
||||
// 我们假设存在 User 这个实体
|
||||
$user = new User();
|
||||
$result = $user->save();
|
||||
|
||||
// ↓
|
||||
// 这里 dispatch(object $event) 会逐个运行监听该事件的监听器
|
||||
$this->eventDispatcher->dispatch(new EmailWillSent(
|
||||
target: $user->mobile,
|
||||
subject: '注册成功通知',
|
||||
type: 'html', // 默认 text 可以不传
|
||||
content: <<<HTML
|
||||
<h1>恭喜你,注册成功!</h1>
|
||||
HTML,
|
||||
));
|
||||
// ↑
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
@@ -6,4 +6,6 @@ parameters:
|
||||
- tests
|
||||
ignoreErrors:
|
||||
- '#Constant BASE_PATH not found#'
|
||||
- '#Property [a-zA-Z0-9\\_]+::\$[a-zA-Z0-9]+ is never written, only read.#'
|
||||
- '#Property [a-zA-Z0-9\\_]+::\$[a-zA-Z0-9]+ is never written, only read.#'
|
||||
- '#Method [a-zA-Z0-9\\_]+::[a-zA-Z0-9_]+\(\) has parameter \$[a-zA-Z0-9_]+ with no value type specified in iterable type array.#'
|
||||
- '#Method [a-zA-Z0-9\\_]+::[a-zA-Z0-9_]+\(\) has parameter \$[a-zA-Z0-9_]+ with no type specified.#'
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
docker login harbor.luxcreo.cn -u php -p fTr6oVvqqdzVlYgnZhRPPAP54u7SmqGA
|
||||
|
||||
image_name=harbor.luxcreo.cn/php/composer-template
|
||||
docker build --tag $image_name .
|
||||
|
||||
#docker push $image_name
|
||||
#docker push ${image_name}-dev
|
||||
@@ -6,4 +6,4 @@ docker run \
|
||||
-w "/srv/www" \
|
||||
-v "$(pwd)":/srv/www \
|
||||
-v ~/.ssh:/root/.ssh \
|
||||
harbor.luxcreo.cn/library/hyperf:8.0-swoole /bin/ash
|
||||
harbor.luxcreo.cn/library/hyperf:7.4-swoole /bin/ash
|
||||
|
||||
5
scripts/release.sh
Executable file
5
scripts/release.sh
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
docker run --rm -it \
|
||||
-v $(pwd):/app -e "GIT_AUTHOR_NAME=ch4o5" -e "EMAIL=dongyun.li@luxcreo.ai" \
|
||||
detouched/standard-version:latest $1
|
||||
@@ -14,6 +14,8 @@ namespace Singularity\HDK\Core;
|
||||
|
||||
use Hyperf\Contract\StdoutLoggerInterface;
|
||||
use Hyperf\Framework\Logger\StdoutLogger;
|
||||
use Singularity\HDK\Core\Listener\EmailWillSentListener;
|
||||
use Singularity\HDK\Core\Listener\SmsWillSentListener;
|
||||
|
||||
class ConfigProvider
|
||||
{
|
||||
@@ -38,7 +40,10 @@ class ConfigProvider
|
||||
'commands' => [
|
||||
],
|
||||
// 与 commands 类似
|
||||
'listeners' => [],
|
||||
'listeners' => [
|
||||
EmailWillSentListener::class,
|
||||
SmsWillSentListener::class
|
||||
],
|
||||
// 组件默认配置文件,即执行命令后会把 source 的对应的文件复制为 destination 对应的的文件
|
||||
'publish' => [
|
||||
[
|
||||
|
||||
@@ -16,7 +16,6 @@ use Dont\DontDeserialise;
|
||||
use Dont\DontGet;
|
||||
use Dont\DontSerialise;
|
||||
use Dont\DontSet;
|
||||
use Dont\DontToString;
|
||||
use Hyperf\Contract\ContainerInterface;
|
||||
use Hyperf\Contract\StdoutLoggerInterface;
|
||||
use Hyperf\Di\Annotation\Inject;
|
||||
@@ -40,7 +39,6 @@ abstract class AbstractController
|
||||
use DontClone;
|
||||
use DontSerialise;
|
||||
use DontDeserialise;
|
||||
use DontToString;
|
||||
|
||||
/**
|
||||
* @Inject
|
||||
|
||||
69
src/Events/EmailWillSent.php
Normal file
69
src/Events/EmailWillSent.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* EmailWillSent.php@HDK-Core
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2023/1/16
|
||||
*/
|
||||
|
||||
namespace Singularity\HDK\Core\Events;
|
||||
|
||||
/**
|
||||
* Singularity\HDK\Core\Events\EmailWillSent@HDK-Core
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2023/1/16
|
||||
*
|
||||
* @link ../../docs/Email.md
|
||||
*/
|
||||
class EmailWillSent
|
||||
{
|
||||
/**
|
||||
* @var string|string[] $target
|
||||
*/
|
||||
public $target;
|
||||
|
||||
/**
|
||||
* @var non-empty-string $subject
|
||||
*/
|
||||
public string $subject;
|
||||
|
||||
|
||||
/**
|
||||
* @var non-empty-string $content
|
||||
*/
|
||||
public string $content;
|
||||
|
||||
/**
|
||||
* @var string[] $cc
|
||||
*/
|
||||
public array $cc = [];
|
||||
|
||||
/**
|
||||
* @var string 'text'|'html' $type
|
||||
*/
|
||||
public string $type = 'text';
|
||||
|
||||
|
||||
public function __construct(
|
||||
/**
|
||||
* @phpstan-param string|string[] $target
|
||||
*/
|
||||
$target,
|
||||
string $subject,
|
||||
string $content,
|
||||
/**
|
||||
* @var non-empty-string[] $cc
|
||||
*/
|
||||
array $cc = [],
|
||||
string $type = 'text'
|
||||
) {
|
||||
$this->type = $type;
|
||||
$this->cc = $cc;
|
||||
$this->content = $content;
|
||||
$this->subject = $subject;
|
||||
$this->target = $target;
|
||||
}
|
||||
}
|
||||
75
src/Events/SmsWillSent.php
Normal file
75
src/Events/SmsWillSent.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
/**
|
||||
* SmsWillSent.php@HDK-Core
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2023/1/16
|
||||
*/
|
||||
|
||||
namespace Singularity\HDK\Core\Events;
|
||||
|
||||
/**
|
||||
* Singularity\HDK\Core\Events\SmsWillSent@HDK-Core
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2023/1/16
|
||||
*
|
||||
* @link ../../docs/SMS.md
|
||||
*/
|
||||
class SmsWillSent
|
||||
{
|
||||
/**
|
||||
* @var non-empty-string $phone 目标手机号
|
||||
* @example +8613700000001
|
||||
* @example 8613700000001
|
||||
* @example 13700000001
|
||||
*/
|
||||
public string $phone;
|
||||
|
||||
/**
|
||||
* @var array<literal-string, literal-string|int>|null $templateParam 模板变量
|
||||
*/
|
||||
public ?array $templateParam = null;
|
||||
|
||||
/**
|
||||
* @var literal-string|null $templateCode 模板代码
|
||||
*/
|
||||
public ?string $templateCode = null;
|
||||
|
||||
/**
|
||||
* @var literal-string|null $signName 模板签名
|
||||
*/
|
||||
public ?string $signName = null;
|
||||
|
||||
public function __construct(
|
||||
/**
|
||||
* @var non-empty-string $phone 目标手机号
|
||||
* @example +8613700000001
|
||||
* @example 8613700000001
|
||||
* @example 13700000001
|
||||
*/
|
||||
string $phone,
|
||||
|
||||
/**
|
||||
* @var array<literal-string, literal-string|int>|null $templateParam 模板变量
|
||||
*/
|
||||
?array $templateParam = null,
|
||||
|
||||
/**
|
||||
* @var literal-string|null $templateCode 模板代码
|
||||
*/
|
||||
?string $templateCode = null,
|
||||
|
||||
/**
|
||||
* @var literal-string|null $signName 模板签名
|
||||
*/
|
||||
?string $signName = null
|
||||
) {
|
||||
$this->signName = $signName;
|
||||
$this->templateCode = $templateCode;
|
||||
$this->templateParam = $templateParam;
|
||||
$this->phone = $phone;
|
||||
}
|
||||
}
|
||||
@@ -12,14 +12,17 @@ use Throwable;
|
||||
*/
|
||||
class DbException extends HttpException
|
||||
{
|
||||
public string $sql;
|
||||
|
||||
public function __construct(
|
||||
int $code = CommonErrorCode::PROGRAM_SQL_ERROR,
|
||||
?string $message = null,
|
||||
public string $sql = '',
|
||||
string $sql = '',
|
||||
Throwable $previous = null
|
||||
) {
|
||||
$this->sql = $sql;
|
||||
if ($code == CommonErrorCode::FORBIDDEN) {
|
||||
$previous_code = $previous?->getCode();
|
||||
$previous_code = empty($previous) ? null : $previous->getCode();
|
||||
$code = empty($previous_code) ? $code : $previous_code;
|
||||
}
|
||||
parent::__construct(
|
||||
|
||||
@@ -18,7 +18,7 @@ class Forbidden extends HttpException
|
||||
Throwable $previous = null
|
||||
) {
|
||||
if ($code == CommonErrorCode::FORBIDDEN) {
|
||||
$previous_code = $previous?->getCode();
|
||||
$previous_code = empty($previous) ? null : $previous->getCode();
|
||||
$code = empty($previous_code) ? $code : $previous_code;
|
||||
}
|
||||
parent::__construct(
|
||||
|
||||
@@ -72,24 +72,36 @@ class CommonHandler extends ExceptionHandler
|
||||
$message_name = config('common.response.message_name');
|
||||
|
||||
$is_testing = config('app_status') === true;
|
||||
$this->request?->url();
|
||||
|
||||
$is_debug = $this->request?->hasHeader('Postman-Token')
|
||||
|| str_starts_with($this->request?->header('User-Agent'), 'apifox');
|
||||
|
||||
$error_type = $throwable::class;
|
||||
$error_type = get_class($throwable);
|
||||
$request_time = date('Y-m-d H:i:s');
|
||||
$request_data = Json::encode($this->request?->getParsedBody());
|
||||
$request_headers = Json::encode($this->request?->getHeaders());
|
||||
|
||||
if (!empty($this->request)) {
|
||||
$this->request->url();
|
||||
|
||||
$is_debug = $this->request->hasHeader('Postman-Token')
|
||||
|| str_starts_with($this->request->header('User-Agent', ''), 'apifox');
|
||||
|
||||
$request_data = Json::encode($this->request->getParsedBody());
|
||||
$request_headers = Json::encode($this->request->getHeaders());
|
||||
} else {
|
||||
$is_debug = false;
|
||||
$request_data = null;
|
||||
$request_headers = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 901 程序语法错误
|
||||
|
||||
// 902 SQL 语法错误
|
||||
if ($throwable instanceof QueryException) {
|
||||
$code = match ($throwable->getCode()) {
|
||||
'42S22' => CommonErrorCode::PROGRAM_SQL_COLUMN_NOT_FOUND,
|
||||
default => CommonErrorCode::PROGRAM_SQL_ERROR
|
||||
};
|
||||
if ($throwable->getCode() === '42S22') {
|
||||
$code = CommonErrorCode::PROGRAM_SQL_COLUMN_NOT_FOUND;
|
||||
} else {
|
||||
$code = CommonErrorCode::PROGRAM_SQL_ERROR;
|
||||
}
|
||||
|
||||
$data = [
|
||||
$code_name => $code,
|
||||
@@ -117,7 +129,7 @@ class CommonHandler extends ExceptionHandler
|
||||
$message_name => CommonErrorCode::getMessage($code, [
|
||||
'methods' => join(', ', $allow_method),
|
||||
]),
|
||||
'currentMethod' => $this->request?->getMethod(),
|
||||
'currentMethod' => empty($this->request) ? null : $this->request->getMethod(),
|
||||
'allowedMethod' => $allow_method,
|
||||
];
|
||||
}
|
||||
@@ -248,7 +260,7 @@ class CommonHandler extends ExceptionHandler
|
||||
'errorTrack' => $throwable->getTrace(),
|
||||
];
|
||||
}
|
||||
$cookies = json_encode($this->request->getCookieParams(), JSON_UNESCAPED_UNICODE);
|
||||
$cookies = Json::encode($this->request->getCookieParams());
|
||||
$this->logger->error(
|
||||
<<<ERROR_LOG
|
||||
TYPE: $error_type
|
||||
@@ -264,13 +276,13 @@ REQUEST_COOKIES:
|
||||
$cookies
|
||||
-------------------------------
|
||||
REQUEST_METHOD:
|
||||
{$this->request?->getMethod()}
|
||||
{$this->request->getMethod()}
|
||||
-------------------------------
|
||||
REQUEST_URL:
|
||||
{$this->request?->getUri()}
|
||||
{$this->request->getUri()}
|
||||
-------------------------------
|
||||
REQUEST_QUERY:
|
||||
{$this->request?->getQueryString()}
|
||||
{$this->request->getQueryString()}
|
||||
-------------------------------
|
||||
REQUEST_DATA:
|
||||
$request_data
|
||||
|
||||
@@ -13,13 +13,17 @@ use Throwable;
|
||||
*/
|
||||
class Unauthorized extends HttpException
|
||||
{
|
||||
/** @var string $authenticationType */
|
||||
private string $authenticationType;
|
||||
|
||||
public function __construct(
|
||||
int $code = CommonErrorCode::UNAUTHORIZED,
|
||||
Throwable $previous = null,
|
||||
private string $authenticationType = RFC7616::DIGEST
|
||||
string $authenticationType = RFC7616::DIGEST
|
||||
) {
|
||||
$this->authenticationType = $authenticationType;
|
||||
if ($code == CommonErrorCode::UNAUTHORIZED) {
|
||||
$previous_code = $previous?->getCode();
|
||||
$previous_code = empty($previous) ? null : $previous->getCode();
|
||||
$code = empty($previous_code) ? $code : $previous_code;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,15 @@ use Throwable;
|
||||
*/
|
||||
class ValidateException extends HttpException
|
||||
{
|
||||
/** @var string $field */
|
||||
private $field;
|
||||
|
||||
/** @var mixed $currentValue */
|
||||
private $currentValue;
|
||||
|
||||
/** @var array<int, mixed> $availableValue */
|
||||
private $availableValue;
|
||||
|
||||
/**
|
||||
* @param int $code
|
||||
* @param string|null $message
|
||||
@@ -23,13 +32,16 @@ class ValidateException extends HttpException
|
||||
public function __construct(
|
||||
int $code = CommonErrorCode::FORMATTER_ERROR,
|
||||
?string $message = null,
|
||||
private string $field = '',
|
||||
private mixed $currentValue = null,
|
||||
private array $availableValue = [],
|
||||
string $field = '',
|
||||
$currentValue = null,
|
||||
array $availableValue = [],
|
||||
Throwable $previous = null
|
||||
) {
|
||||
$this->availableValue = $availableValue;
|
||||
$this->currentValue = $currentValue;
|
||||
$this->field = $field;
|
||||
if ($code == CommonErrorCode::FORMATTER_ERROR) {
|
||||
$previous_code = $previous?->getCode();
|
||||
$previous_code = empty($previous) ? null : $previous->getCode();
|
||||
$code = empty($previous_code) ? $code : $previous_code;
|
||||
}
|
||||
parent::__construct(
|
||||
@@ -54,7 +66,7 @@ class ValidateException extends HttpException
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCurrentValue(): mixed
|
||||
public function getCurrentValue()
|
||||
{
|
||||
return $this->currentValue;
|
||||
}
|
||||
|
||||
30
src/Listener/AbstractListener.php
Normal file
30
src/Listener/AbstractListener.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/**
|
||||
* AbstractListener.php@HDK-Core
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2023/1/16
|
||||
*/
|
||||
|
||||
namespace Singularity\HDK\Core\Listener;
|
||||
|
||||
use Hyperf\Contract\ContainerInterface;
|
||||
use Hyperf\Contract\StdoutLoggerInterface;
|
||||
use Hyperf\Di\Annotation\Inject;
|
||||
use Hyperf\Event\Contract\ListenerInterface;
|
||||
|
||||
abstract class AbstractListener implements ListenerInterface
|
||||
{
|
||||
/**
|
||||
* @var ContainerInterface
|
||||
* @Inject()
|
||||
*/
|
||||
protected ContainerInterface $container;
|
||||
|
||||
/**
|
||||
* @var StdoutLoggerInterface
|
||||
* @Inject()
|
||||
*/
|
||||
protected StdoutLoggerInterface $stdoutLogger;
|
||||
}
|
||||
90
src/Listener/EmailWillSentListener.php
Normal file
90
src/Listener/EmailWillSentListener.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
/**
|
||||
* EmailWillSentListener.php@HDK-Core
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2023/1/16
|
||||
*/
|
||||
|
||||
namespace Singularity\HDK\Core\Listener;
|
||||
|
||||
use Hyperf\Contract\ContainerInterface;
|
||||
use Hyperf\Contract\StdoutLoggerInterface;
|
||||
use Hyperf\Di\Annotation\Inject;
|
||||
use Hyperf\Event\Contract\ListenerInterface;
|
||||
use JetBrains\PhpStorm\NoReturn;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
use Singularity\HDK\Core\Constants\CommonErrorCode;
|
||||
use Singularity\HDK\Core\Events\EmailWillSent;
|
||||
use Singularity\HDK\Core\Service\EmailService;
|
||||
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
|
||||
|
||||
/**
|
||||
* Singularity\HDK\Core\Listener\EmailWillSentListener@HDK-Core
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2023/1/16
|
||||
*
|
||||
* @link ../../docs/Email.md
|
||||
*/
|
||||
class EmailWillSentListener extends AbstractListener
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function listen(): array
|
||||
{
|
||||
return [
|
||||
EmailWillSent::class,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EmailWillSent $event
|
||||
* @return void
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws NotFoundExceptionInterface
|
||||
*/
|
||||
public function process(object $event): void
|
||||
{
|
||||
$stdoutLogger = $this->container->get(StdoutLoggerInterface::class);
|
||||
$emailService = $this->container->get(EmailService::class);
|
||||
try {
|
||||
$event->type === 'html'
|
||||
? $emailService->sendHtml(
|
||||
$event->target,
|
||||
$event->subject,
|
||||
$event->content,
|
||||
$event->cc
|
||||
)
|
||||
: $emailService->sendText(
|
||||
$event->target,
|
||||
$event->subject,
|
||||
$event->content,
|
||||
$event->cc
|
||||
);
|
||||
|
||||
$stdoutLogger->info('邮件发送成功!');
|
||||
$stdoutLogger->info("To: $event->target");
|
||||
$stdoutLogger->info("Subject: $event->subject");
|
||||
$stdoutLogger->debug('Content: ');
|
||||
$stdoutLogger->debug($event->content);
|
||||
} catch (TransportExceptionInterface $e) {
|
||||
$code = CommonErrorCode::SERVER_MESSAGE_EMAIL_ERROR;
|
||||
$msg = $e->getMessage();
|
||||
if (strpos($msg, '500 Error: bad syntax')) {
|
||||
$code = CommonErrorCode::SERVER_MESSAGE_EMAIL_NOT_FOUND;
|
||||
$msg = CommonErrorCode::getMessage($code);
|
||||
}
|
||||
$stdoutLogger->alert('邮件发送失败!');
|
||||
$stdoutLogger->error(
|
||||
<<<ERROR_LOG
|
||||
[$code] $msg
|
||||
ERROR_LOG
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
60
src/Listener/SmsWillSentListener.php
Normal file
60
src/Listener/SmsWillSentListener.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/**
|
||||
* SmsWillSentListener.php@HDK-Core
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2023/1/16
|
||||
*/
|
||||
|
||||
namespace Singularity\HDK\Core\Listener;
|
||||
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
use Singularity\HDK\Core\Events\SmsWillSent;
|
||||
use Singularity\HDK\Core\Service\SmsService;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Singularity\HDK\Core\Listener\SmsWillSentListener@HDK-Core
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2023/1/16
|
||||
*/
|
||||
class SmsWillSentListener extends AbstractListener
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function listen(): array
|
||||
{
|
||||
return [
|
||||
SmsWillSent::class,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SmsWillSent $event
|
||||
* @return void
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws NotFoundExceptionInterface
|
||||
*/
|
||||
public function process(object $event): void
|
||||
{
|
||||
$smsService = $this->container->get(SmsService::class);
|
||||
try {
|
||||
$smsService->sendSmsCountryside(
|
||||
$event->phone,
|
||||
$event->templateCode,
|
||||
$event->templateParam,
|
||||
$event->signName
|
||||
);
|
||||
} catch (Throwable $throwable) {
|
||||
$code = $throwable->getCode();
|
||||
$message = $throwable->getMessage();
|
||||
$this->stdoutLogger->alert('短信发送失败!');
|
||||
$this->stdoutLogger->error(sprintf("[%u] %s", $code, $message));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,11 +35,17 @@ class InternationalizationMiddleware implements MiddlewareInterface
|
||||
$response = Context::get(ResponseInterface::class);
|
||||
$language = $request->getHeaderLine('Accept-Language');
|
||||
if (!empty($language)) {
|
||||
$language = match (strtolower($language)) {
|
||||
'en', 'en_us', 'en-us', 'en-uk', 'en_uk' => 'en',
|
||||
'zh', 'zh_cn', 'zh-cn' => 'zh_CN',
|
||||
default => config('translation.locale')
|
||||
};
|
||||
switch (true) {
|
||||
case in_array(strtolower($language), ['en', 'en_us', 'en-us', 'en-uk', 'en_uk']):
|
||||
$language = 'en';
|
||||
break;
|
||||
case in_array(strtolower($language), ['zh', 'zh_cn', 'zh-cn']):
|
||||
$language = 'zh_CN';
|
||||
break;
|
||||
default:
|
||||
$language = config('translation.locale') ;
|
||||
break;
|
||||
}
|
||||
$this->translator->setLocale($language);
|
||||
|
||||
$response = $response->withAddedHeader('Content-Language', strtr($this->translator->getLocale(), '_', '-'));
|
||||
|
||||
165
src/Middleware/SessionMiddleware.php
Normal file
165
src/Middleware/SessionMiddleware.php
Normal file
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
/**
|
||||
* SessionMiddleware.php@HDK-Core
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2023/3/8
|
||||
*/
|
||||
|
||||
namespace Singularity\HDK\Core\Middleware;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Hyperf\Contract\ConfigInterface;
|
||||
use Hyperf\Contract\SessionInterface;
|
||||
use Hyperf\HttpMessage\Cookie\Cookie;
|
||||
use Hyperf\HttpMessage\Server\Response;
|
||||
use Hyperf\Session\SessionManager;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
/**
|
||||
* Singularity\HDK\Auth\Middleware\SessionMiddleware@HDK-Core
|
||||
*
|
||||
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
|
||||
* Powered by PhpStorm
|
||||
* Created on 2023/3/8
|
||||
*/
|
||||
class SessionMiddleware implements MiddlewareInterface
|
||||
{
|
||||
private SessionManager $sessionManager;
|
||||
private ConfigInterface $config;
|
||||
|
||||
public function __construct(SessionManager $sessionManager, ConfigInterface $config)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->sessionManager = $sessionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an incoming server request.
|
||||
* Processes an incoming server request in order to produce a response.
|
||||
* If unable to produce the response itself, it may delegate to the provided
|
||||
* request handler to do so.
|
||||
*/
|
||||
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||
{
|
||||
if (!$this->isSessionAvailable()) {
|
||||
return $handler->handle($request);
|
||||
}
|
||||
|
||||
$session = $this->sessionManager->start($request);
|
||||
|
||||
try {
|
||||
$response = $handler->handle($request);
|
||||
} finally {
|
||||
$this->storeCurrentUrl($request, $session);
|
||||
$session = $this->sessionManager->getSession();
|
||||
|
||||
/*
|
||||
* 现在的机制,但凡写入 Redis 的数据,
|
||||
* 过期时间就是固定的 gc_maxlifetime
|
||||
*
|
||||
* 而 RedisHandler 只会被依赖注入时加载一次,
|
||||
* 后续无法临时修改 gc_maxlifetime
|
||||
*
|
||||
* 又因为现在没有其他情况用到 session
|
||||
* 只有登录之后才会记下用户信息
|
||||
*
|
||||
* 所以一个妥协的方案,就是只有登录了再写入 Redis
|
||||
*
|
||||
* (除非重写整套 RedisHandler/RedisHandlerFactory/...)
|
||||
*/
|
||||
if (!$this->auth($session)) {
|
||||
$this->sessionManager->end($session);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->addCookieToResponse($request, $response, $session);
|
||||
}
|
||||
|
||||
private function isSessionAvailable(): bool
|
||||
{
|
||||
return $this->config->has('session.handler');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the current URL for the request if necessary.
|
||||
*/
|
||||
private function storeCurrentUrl(RequestInterface $request, SessionInterface $session)
|
||||
{
|
||||
if ($request->getMethod() === 'GET') {
|
||||
$session->setPreviousUrl($this->fullUrl($request));
|
||||
}
|
||||
}
|
||||
|
||||
private function auth(SessionInterface $session): bool
|
||||
{
|
||||
return $session->has('userInfo');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the session cookie to the response·.
|
||||
*/
|
||||
private function addCookieToResponse(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response,
|
||||
SessionInterface $session
|
||||
): ResponseInterface {
|
||||
$cookie = new Cookie(
|
||||
$session->getName(),
|
||||
$session->getId(),
|
||||
$this->getCookieExpirationDate($session),
|
||||
$this->config->get('session.options.path', '/'),
|
||||
$this->config->get('session.options.domain', $request->getUri()->getHost()),
|
||||
$this->config->get(
|
||||
'session.options.secure',
|
||||
strtolower($request->getUri()->getScheme()) === 'https'
|
||||
),
|
||||
true,
|
||||
$this->config->get('session.options.samesite', Cookie::SAMESITE_LAX)
|
||||
);
|
||||
if (!method_exists($response, 'withCookie')) {
|
||||
return $response->withHeader('Set-Cookie', (string)$cookie);
|
||||
}
|
||||
/* @var Response $response */
|
||||
return $response->withCookie($cookie);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full URL for the request.
|
||||
*/
|
||||
private function fullUrl(RequestInterface $request): string
|
||||
{
|
||||
$uri = $request->getUri();
|
||||
$query = $uri->getQuery();
|
||||
$question = $uri->getHost() . $uri->getPath() == '/' ? '/?' : '?';
|
||||
return $query ? $this->url($request) . $question . $query : $this->url($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the session lifetime in seconds.
|
||||
*/
|
||||
private function getCookieExpirationDate(SessionInterface $session): int
|
||||
{
|
||||
// if ($this->config->get('session.options.expire_on_close')) {
|
||||
if (!$this->auth($session)) {
|
||||
$expirationDate = 0;
|
||||
} else {
|
||||
$expireSeconds = $this->config->get('session.options.cookie_lifetime', 5 * 60 * 60);
|
||||
$expirationDate = Carbon::now()->addSeconds($expireSeconds)->getTimestamp();
|
||||
}
|
||||
return $expirationDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL (no query string) for the request.
|
||||
*/
|
||||
private function url(RequestInterface $request): string
|
||||
{
|
||||
return rtrim(preg_replace('/\?.*/', '', (string)$request->getUri()));
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace Singularity\HDK\Core\Service;
|
||||
|
||||
use JetBrains\PhpStorm\Deprecated;
|
||||
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
|
||||
use Symfony\Component\Mailer\Mailer;
|
||||
use Symfony\Component\Mailer\Transport;
|
||||
@@ -54,8 +53,9 @@ class EmailService
|
||||
* @throws TransportExceptionInterface
|
||||
* @see EmailService::sendText
|
||||
* @see EmailService::sendHtml
|
||||
* @deprecated
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
#[Deprecated]
|
||||
public function sendCode(
|
||||
string $target,
|
||||
string $subject,
|
||||
@@ -74,7 +74,7 @@ class EmailService
|
||||
* @throws TransportExceptionInterface
|
||||
*/
|
||||
public function sendText(
|
||||
string|array $target,
|
||||
$target,
|
||||
string $subject,
|
||||
string $text,
|
||||
array $cc = []
|
||||
@@ -103,7 +103,7 @@ class EmailService
|
||||
* @throws TransportExceptionInterface
|
||||
*/
|
||||
public function sendHtml(
|
||||
string|array $target,
|
||||
$target,
|
||||
string $subject,
|
||||
string $html,
|
||||
array $cc = []
|
||||
|
||||
@@ -10,23 +10,31 @@ use Psr\Http\Message\ServerRequestInterface;
|
||||
*/
|
||||
class ExtendService
|
||||
{
|
||||
/** @var UtilsService $utils */
|
||||
private UtilsService $utils;
|
||||
|
||||
public function __construct(UtilsService $utils)
|
||||
{
|
||||
$this->utils = $utils;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ServerRequestInterface|null $request
|
||||
* @param array<string, string>|null $params
|
||||
* @param array<string, string>|string|null $params
|
||||
* @return string[]
|
||||
*/
|
||||
public function parse(
|
||||
?ServerRequestInterface $request,
|
||||
?array $params = null
|
||||
$params = null
|
||||
): array {
|
||||
$params ??= $request->getQueryParams();
|
||||
$extends = $params['extends'] ?? null;
|
||||
$params = $params ?? (isset($request) ? $request->getQueryParams() : null);
|
||||
$extends = empty($params['extends']) ? [] : $params['extends'];
|
||||
if (!empty($extends)) {
|
||||
$extends = explode(',', $extends);
|
||||
return Context::set(self::class, array_map('trim', $extends));
|
||||
$extends = array_map('trim', $extends);
|
||||
}
|
||||
|
||||
return [];
|
||||
Context::set(self::class, $extends);
|
||||
return $extends;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,6 +45,12 @@ class ExtendService
|
||||
return Context::get(self::class) ?? [];
|
||||
}
|
||||
|
||||
public function hasExtends(): bool
|
||||
{
|
||||
$extends = Context::get(self::class);
|
||||
return is_array($extends) && count($extends) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否传入了此扩展
|
||||
*
|
||||
@@ -44,8 +58,8 @@ class ExtendService
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasExtends(string $field): bool
|
||||
public function hasExtend(string $field): bool
|
||||
{
|
||||
return Context::has(self::class) && isset(array_flip(Context::get(self::class))[$field]);
|
||||
return $this->utils->inArray($field, Context::get(self::class));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,12 @@ use Hyperf\Utils\Codec\Json;
|
||||
|
||||
class OssService
|
||||
{
|
||||
public ?string $accessKeyId = null;
|
||||
public ?string $accessKeySecret = null;
|
||||
public ?string $host = null;
|
||||
public ?string $callbackUrl = null;
|
||||
public ?int $expiration = 30;
|
||||
|
||||
/**
|
||||
* @param string|null $accessKeyId 不传则取配置文件
|
||||
* @param string|null $accessKeySecret 不传则取配置文件
|
||||
@@ -20,16 +26,17 @@ class OssService
|
||||
* @param int|null $expiration 过期时间,默认30s
|
||||
*/
|
||||
public function __construct(
|
||||
public ?string $accessKeyId = null,
|
||||
public ?string $accessKeySecret = null,
|
||||
public ?string $host = null,
|
||||
public ?string $callbackUrl = null,
|
||||
public ?int $expiration = 30
|
||||
?string $accessKeyId = null,
|
||||
?string $accessKeySecret = null,
|
||||
?string $host = null,
|
||||
?string $callbackUrl = null,
|
||||
?int $expiration = 30
|
||||
) {
|
||||
$this->accessKeyId ??= config('common.third_party.storage.oss.access_key_id');
|
||||
$this->accessKeySecret ??= config('common.third_party.storage.oss.access_key_secret');
|
||||
$this->host ??= config('common.third_party.storage.oss.oss_host');
|
||||
$this->callbackUrl ??= config('oss_callback');
|
||||
$this->expiration = $expiration;
|
||||
$this->callbackUrl = $callbackUrl?? config('oss_callback');
|
||||
$this->host = $host?? config('common.third_party.storage.oss.oss_host');
|
||||
$this->accessKeySecret = $accessKeySecret ?? config('common.third_party.storage.oss.access_key_secret');
|
||||
$this->accessKeyId = $accessKeyId ?? config('common.third_party.storage.oss.access_key_id');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,6 +10,7 @@ use Hyperf\HttpMessage\Exception\HttpException;
|
||||
use Hyperf\Utils\Codec\Json;
|
||||
use Singularity\HDK\Core\Constants\CommonErrorCode;
|
||||
use Singularity\HDK\Core\Exceptions\ValidateException;
|
||||
use UnexpectedValueException;
|
||||
|
||||
/**
|
||||
* 短信服务
|
||||
@@ -17,9 +18,9 @@ use Singularity\HDK\Core\Exceptions\ValidateException;
|
||||
class SmsService
|
||||
{
|
||||
/**
|
||||
* @var \AlibabaCloud\SDK\Dysmsapi\V20170525\Dysmsapi
|
||||
* @var Dysmsapi
|
||||
*/
|
||||
private Dysmsapi $client;
|
||||
private $client;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
@@ -29,7 +30,7 @@ class SmsService
|
||||
/**
|
||||
* 初始化实例
|
||||
*
|
||||
* @return \AlibabaCloud\SDK\Dysmsapi\V20170525\Dysmsapi
|
||||
* @return Dysmsapi
|
||||
*/
|
||||
private function createClient(): Dysmsapi
|
||||
{
|
||||
@@ -44,22 +45,23 @@ class SmsService
|
||||
/**
|
||||
* 国内短信
|
||||
*
|
||||
* @param string $phone 接收短信的手机号码
|
||||
* @param string|null $templateCode 短信模板CODE
|
||||
* @param array<string, string>|null $templateParam 短信模板变量对应的实际值(不支持空数组)
|
||||
* @param string|null $signName 短信签名名称
|
||||
* @param string $phone 接收短信的手机号码
|
||||
* @param string|null $templateCode 短信模板CODE
|
||||
* @param array<string, string>|null $templateParam 短信模板变量对应的实际值(不支持空数组)
|
||||
* @param string|null $signName 短信签名名称
|
||||
*
|
||||
* @return bool
|
||||
* @link https://help.aliyun.com/document_detail/419273.htm
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function sendSmsCountryside(
|
||||
string $phone,
|
||||
?string $templateCode = null,
|
||||
?array $templateParam = null,
|
||||
?string $signName = null,
|
||||
?string $signName = null
|
||||
): bool {
|
||||
if (is_array($templateParam) && count($templateParam) <= 0) {
|
||||
throw new \UnexpectedValueException('不支持空数组,请用 null 代替或不传', CommonErrorCode::FORMATTER_ERROR);
|
||||
throw new UnexpectedValueException('不支持空数组,请用 null 代替或不传', CommonErrorCode::FORMATTER_ERROR);
|
||||
}
|
||||
$phone_number = strtr($phone, ['#' => '']);
|
||||
|
||||
@@ -89,12 +91,20 @@ class SmsService
|
||||
|
||||
// 频率太高
|
||||
if ($code === 'isv.BUSINESS_LIMIT_CONTROL') {
|
||||
$error_code = match (mb_substr($message, 2, 2)) {
|
||||
'天级' => CommonErrorCode::REQUEST_PARAMS_ERROR_CODE_MAX_TIMES_DAY,
|
||||
'小时' => CommonErrorCode::REQUEST_PARAMS_ERROR_CODE_MAX_TIMES_HOUR,
|
||||
'分钟' => CommonErrorCode::REQUEST_PARAMS_ERROR_CODE_MAX_TIMES_MINUTE,
|
||||
default => null
|
||||
};
|
||||
switch (mb_substr($message, 2, 2)) {
|
||||
case '天级':
|
||||
$error_code = CommonErrorCode::REQUEST_PARAMS_ERROR_CODE_MAX_TIMES_DAY;
|
||||
break;
|
||||
case '小时':
|
||||
$error_code = CommonErrorCode::REQUEST_PARAMS_ERROR_CODE_MAX_TIMES_HOUR;
|
||||
break;
|
||||
case '分钟':
|
||||
$error_code = CommonErrorCode::REQUEST_PARAMS_ERROR_CODE_MAX_TIMES_MINUTE;
|
||||
break;
|
||||
default:
|
||||
$error_code = null;
|
||||
break;
|
||||
}
|
||||
|
||||
if (isset($error_code)) {
|
||||
throw new ValidateException($error_code);
|
||||
|
||||
@@ -8,8 +8,6 @@ use Closure;
|
||||
use Exception;
|
||||
use Generator;
|
||||
use Hyperf\HttpServer\Contract\RequestInterface;
|
||||
use JetBrains\PhpStorm\NoReturn;
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
@@ -25,7 +23,6 @@ class UtilsService
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
#[Pure]
|
||||
public function generateSecureCode(int $length = 4): string
|
||||
{
|
||||
$code = '';
|
||||
@@ -102,7 +99,6 @@ class UtilsService
|
||||
* @param bool $anchorQuery 开启后,query 参数将被尽量组合到锚点中,以支持 spa 路由
|
||||
* @return string
|
||||
*/
|
||||
#[Pure]
|
||||
public function buildUrl(string $url, array $moreQueries = [], bool $anchorQuery = false): string
|
||||
{
|
||||
if (count($moreQueries) === 0) {
|
||||
@@ -237,7 +233,6 @@ class UtilsService
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
#[NoReturn]
|
||||
public function unlimitedSubCategoriesQuicklyWithLevel(
|
||||
array &$list,
|
||||
int $level = 1,
|
||||
@@ -276,9 +271,8 @@ class UtilsService
|
||||
*
|
||||
* @return array{'size': float, 'unit': string}
|
||||
*/
|
||||
#[Pure]
|
||||
public function convertStorageSize(
|
||||
float|int|string $size,
|
||||
$size,
|
||||
bool $unitToUpper = false,
|
||||
int $precision = 2
|
||||
): array {
|
||||
@@ -306,9 +300,8 @@ class UtilsService
|
||||
*
|
||||
* @return array{'duration': float, 'unit': string}
|
||||
*/
|
||||
#[Pure]
|
||||
public function convertDuration(
|
||||
int|float $duration,
|
||||
$duration,
|
||||
bool $unitToUpper = false,
|
||||
bool $format = true,
|
||||
int $precision = 3
|
||||
@@ -329,4 +322,16 @@ class UtilsService
|
||||
'unit' => $unitToUpper ? strtoupper($unit[$i]) : $unit[$i],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 更快的判断数组元素方法
|
||||
* @param string|int|float $needle
|
||||
* @param array<int, mixed> $haystack
|
||||
* @return bool
|
||||
*/
|
||||
public function inArray($needle, array $haystack): bool
|
||||
{
|
||||
$list = array_flip($haystack);
|
||||
return isset($list[$needle]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,25 +12,27 @@ namespace Singularity\HDK\Test\Core\Service;
|
||||
use Singularity\HDK\Core\Service\EmailService;
|
||||
use Symfony\Component\Mailer\Exception\TransportException;
|
||||
|
||||
$dsn = 'smtp://account@luxcreo.ai:Qfsd8866@smtp.qiye.aliyun.com:465';
|
||||
$dsn = 'smtp://account@luxcreo.com:Qfsd8866@smtp-mail.outlook.com:587';
|
||||
$mail_sender_name = 'LuxCreo';
|
||||
$mail_sender = 'account@luxcreo.ai';
|
||||
$mail_sender = 'account@luxcreo.com';
|
||||
$email = new EmailService($dsn, $mail_sender_name, $mail_sender);
|
||||
|
||||
it('assertions that send HTML is available', function () use ($email) {
|
||||
$result = $email->sendHtml(
|
||||
'dongyun.li@luxcreo.ai',
|
||||
'HDK Unit Test HTML',
|
||||
<<<HTML
|
||||
$target = 'dongyun.li@luxcreo.ai';
|
||||
|
||||
it('assertions that send HTML is available', function () use ($email, $target) {
|
||||
$result = $email->sendHtml(
|
||||
$target,
|
||||
'HDK Unit Test HTML',
|
||||
<<<HTML
|
||||
<h1>Hello, World!</h1>
|
||||
HTML
|
||||
);
|
||||
expect($result)->toBeTrue();
|
||||
);
|
||||
expect($result)->toBeTrue();
|
||||
});
|
||||
|
||||
it('assertions that send Text is available', function () use ($email) {
|
||||
it('assertions that send Text is available', function () use ($email, $target) {
|
||||
$result = $email->sendText(
|
||||
'dongyun.li@luxcreo.ai',
|
||||
$target,
|
||||
'HDK Unit Test Text',
|
||||
<<<Text
|
||||
<h1>Hello, World!</h1>
|
||||
@@ -41,24 +43,26 @@ Text
|
||||
|
||||
it('assertions Error Receiver can be catch', function () use ($email) {
|
||||
try {
|
||||
$email->sendHtml(
|
||||
$result = $email->sendHtml(
|
||||
'unknown@luxcreo.ai',
|
||||
'HDK Unit Test',
|
||||
<<<HTML
|
||||
<h1>Hello, World!</h1>
|
||||
HTML
|
||||
);
|
||||
expect($result)->toBeTrue();
|
||||
} catch (TransportException $t) {
|
||||
expect($t->getCode())->toBe(554);
|
||||
}
|
||||
try {
|
||||
$email->sendText(
|
||||
$result = $email->sendText(
|
||||
'unknown@luxcreo.ai',
|
||||
'HDK Unit Test',
|
||||
<<<Text
|
||||
<h1>Hello, World!</h1>
|
||||
Text
|
||||
);
|
||||
expect($result)->toBeTrue();
|
||||
} catch (TransportException $t) {
|
||||
expect($t->getCode())->toBe(554);
|
||||
}
|
||||
|
||||
@@ -10,23 +10,44 @@
|
||||
namespace Singularity\HDK\Test\Core\Unit;
|
||||
|
||||
use Singularity\HDK\Core\Service\ExtendService;
|
||||
use Singularity\HDK\Core\Service\UtilsService;
|
||||
|
||||
$service = new ExtendService();
|
||||
/** @var ExtendService $service */
|
||||
$service = make(ExtendService::class, ['utils' => new UtilsService()]);
|
||||
it('asserts no parameters can be parsed.', function (ExtendService $service, $params) {
|
||||
$service->parse(
|
||||
null,
|
||||
$params
|
||||
);
|
||||
$result = $service->getExtends();
|
||||
expect($result)->toBeArray()->toHaveCount(0)->toBe([]);
|
||||
})->with([
|
||||
[$service, null],
|
||||
[$service, ''],
|
||||
[$service, []],
|
||||
[$service, ['extends' => '']],
|
||||
[$service, ['extends' => null]],
|
||||
]);
|
||||
|
||||
it('asserts query parameters can be parsed.', function () use ($service) {
|
||||
$result = $service->parse(
|
||||
null,
|
||||
params: [
|
||||
[
|
||||
'id' => 5,
|
||||
'extends' => 'a,b',
|
||||
]
|
||||
);
|
||||
expect($result)->toBeArray()->toHaveCount(2)->toBe(['a', 'b']);
|
||||
});
|
||||
|
||||
it('asserts has extends', function () use ($service) {
|
||||
expect($service->hasExtends('a'))->toBeTrue()
|
||||
->and($service->hasExtends('b'))->toBeTrue()
|
||||
->and($service->hasExtends('c'))->toBeFalse();
|
||||
expect($service->hasExtends())->toBeTrue();
|
||||
});
|
||||
|
||||
it('asserts has specify extend', function () use ($service) {
|
||||
expect($service->hasExtend('a'))->toBeTrue()
|
||||
->and($service->hasExtend('b'))->toBeTrue()
|
||||
->and($service->hasExtend('c'))->toBeFalse();
|
||||
})->depends('it asserts query parameters can be parsed.');
|
||||
|
||||
it('asserts parsed extends', function () use ($service) {
|
||||
|
||||
@@ -10,10 +10,11 @@
|
||||
use Hyperf\Utils\Codec\Json;
|
||||
use Singularity\HDK\Core\Service\OssService;
|
||||
|
||||
use function Spatie\PestPluginTestTime\testTime;
|
||||
// use function Spatie\PestPluginTestTime\testTime;
|
||||
|
||||
it('asserts oss policy can be generated', function ($setDir, $isImage, $maxSize) {
|
||||
testTime()->freeze();
|
||||
$time = time();
|
||||
// testTime()->freeze();
|
||||
$oss = new OssService(
|
||||
'{MOCK_ACCESS_KEY_ID}',
|
||||
'{MOCK_ACCESS_KEY_SECRET}',
|
||||
@@ -40,8 +41,8 @@ it('asserts oss policy can be generated', function ($setDir, $isImage, $maxSize)
|
||||
->and($host)->toBe('{MOCK_HOST}')
|
||||
->and($dir)->toBe($setDir)
|
||||
->and($setDir)->toBe($policy['conditions'][1][2])
|
||||
->and($expire)->toBe(testTime()->addSeconds(30)->unix())
|
||||
->and($policy['expiration'])->toBe(testTime()->setMilli(0)->toIso8601ZuluString('m'))
|
||||
->and($expire)->toBe($time + 30)
|
||||
// ->and($policy['expiration'])->toBe(testTime()->setMilli(0)->toIso8601ZuluString('m'))
|
||||
->and($maxSize)->toBe($policy['conditions'][0][2])
|
||||
->and($callback['callbackUrl'])->toBe('{MOCK_CALLBACK_URL}')
|
||||
->and($signature)->toBe($sign);
|
||||
|
||||
@@ -29,7 +29,7 @@ test('断言验证码可以正常生成指定长度', function (int $length) use
|
||||
})->with($length_data)->group('pure', 'utils');
|
||||
|
||||
test('断言可以根据参数构建 URL', function (string $url, array $params, bool $anchorQuery, string $expect) use ($utils) {
|
||||
$url = $utils->buildUrl(url: $url, moreQueries: $params, anchorQuery: $anchorQuery);
|
||||
$url = $utils->buildUrl($url, $params, $anchorQuery);
|
||||
expect($url)->toBe($expect);
|
||||
})->with([
|
||||
['baidu.com/list', ['a' => 'b'], false, 'baidu.com/list?a=b'],
|
||||
@@ -58,5 +58,24 @@ test('断言可以根据参数构建 URL', function (string $url, array $params,
|
||||
['c' => 'd'],
|
||||
true,
|
||||
'http://username:password@127.0.0.1/git/resp?id=1#/page?a=b&c=d',
|
||||
]
|
||||
],
|
||||
])->group('pure', 'utils');
|
||||
|
||||
test('断言可以判断是否是数组中的元素', function (
|
||||
$needle,
|
||||
array $haystack,
|
||||
bool $expect,
|
||||
bool $exceptions = false
|
||||
) use ($utils) {
|
||||
try {
|
||||
expect($utils->inArray($needle, $haystack))->toBe($expect);
|
||||
} catch (Throwable $e) {
|
||||
if ($exceptions) {
|
||||
expect(true)->toBeTrue();
|
||||
}
|
||||
}
|
||||
})->with([
|
||||
[1, ['1', 2, 3], true, false],
|
||||
['1', ['1', 2, 3], true, false],
|
||||
[[1, 2, 3], ['1', 2, 3], false, true],
|
||||
])->group('pure', 'utils');
|
||||
|
||||
Reference in New Issue
Block a user