Compare commits

...

122 Commits

Author SHA1 Message Date
as2252258 f46af653f2 1 2022-01-09 14:33:33 +08:00
as2252258 5e02a79bf0 e 2022-01-09 03:50:38 +08:00
as2252258 08dc3e262b 1 2022-01-09 03:46:42 +08:00
as2252258 8c5e52940f 1 2022-01-09 02:44:09 +08:00
as2252258 4dbcacdd1f Revert "改名"
This reverts commit fdf58326
2022-01-08 19:11:23 +08:00
as2252258 97cd1a0ebf Revert "改名"
This reverts commit fdf58326
2022-01-08 18:49:08 +08:00
as2252258 7165a67294 Revert "改名"
This reverts commit fdf58326
2022-01-08 18:10:52 +08:00
as2252258 4bc7451424 Revert "改名"
This reverts commit fdf58326
2022-01-08 18:10:41 +08:00
as2252258 d7d0f685dc Revert "改名"
This reverts commit fdf58326
2022-01-08 10:07:19 +08:00
as2252258 8ee7d30d6a Revert "改名"
This reverts commit fdf58326
2022-01-07 19:01:00 +08:00
as2252258 224009e7e6 Revert "改名"
This reverts commit fdf58326
2022-01-07 19:00:45 +08:00
as2252258 b4551ae2fd Revert "改名"
This reverts commit fdf58326
2022-01-07 18:16:30 +08:00
as2252258 5ca94925e3 Revert "改名"
This reverts commit fdf58326
2022-01-07 18:05:17 +08:00
as2252258 0afa8fc400 Revert "改名"
This reverts commit fdf58326
2022-01-07 17:59:37 +08:00
as2252258 842220e4de Revert "改名"
This reverts commit fdf58326
2022-01-07 17:57:27 +08:00
as2252258 c9726e5778 Revert "改名"
This reverts commit fdf58326
2022-01-07 14:38:36 +08:00
as2252258 f867f4be9e Revert "改名"
This reverts commit fdf58326
2022-01-06 19:05:15 +08:00
as2252258 45319c3733 Revert "改名"
This reverts commit fdf58326
2022-01-04 17:27:37 +08:00
as2252258 06c9459f14 Revert "改名"
This reverts commit fdf58326
2022-01-04 16:25:03 +08:00
as2252258 5fd2abcb69 Revert "改名"
This reverts commit fdf58326
2022-01-04 16:22:37 +08:00
as2252258 58a3d91df3 Merge remote-tracking branch 'origin/master' 2022-01-04 16:05:08 +08:00
as2252258 c61842402a Revert "改名"
This reverts commit fdf58326
2022-01-04 16:04:22 +08:00
as2252258 623bae9e97 1 2022-01-04 00:07:26 +08:00
as2252258 12610c218c 1 2022-01-04 00:07:14 +08:00
as2252258 c3ca24884e Revert "改名"
This reverts commit fdf58326
2021-12-31 16:47:17 +08:00
as2252258 02c14874a2 Revert "改名"
This reverts commit fdf58326
2021-12-31 16:46:13 +08:00
as2252258 6eff48e22f Revert "改名"
This reverts commit fdf58326
2021-12-30 18:10:51 +08:00
as2252258 6c46a54d4b Revert "改名"
This reverts commit fdf58326
2021-12-28 17:54:51 +08:00
as2252258 03287cfd65 Revert "改名"
This reverts commit fdf58326
2021-12-28 14:16:45 +08:00
as2252258 93ce4c16b6 Revert "改名"
This reverts commit fdf58326
2021-12-27 15:24:29 +08:00
as2252258 4b92edd40f 1 2021-12-24 01:19:43 +08:00
as2252258 a76c81df8e 改名 2021-12-23 18:36:14 +08:00
as2252258 aa59caad07 改名 2021-12-23 18:22:27 +08:00
as2252258 6fd8a5dd34 1 2021-12-22 03:29:27 +08:00
as2252258 9ca53a73ce 1 2021-12-22 03:29:14 +08:00
as2252258 d904e78864 1 2021-12-18 03:27:14 +08:00
as2252258 0d64ef7ac4 1 2021-12-17 04:57:46 +08:00
as2252258 154d9d74d6 1 2021-12-17 04:43:20 +08:00
as2252258 2c61abff01 1 2021-12-17 04:41:00 +08:00
as2252258 b4ce762cf3 1 2021-12-17 04:26:54 +08:00
as2252258 4b3c2234af 1 2021-12-17 04:24:40 +08:00
as2252258 7ee78a9642 1 2021-12-17 04:24:01 +08:00
as2252258 f9838f781d 1 2021-12-17 04:23:12 +08:00
as2252258 848416af4f 1 2021-12-17 04:22:13 +08:00
as2252258 0216e761be 1 2021-12-17 04:17:53 +08:00
as2252258 acf6631c5c 1 2021-12-17 04:15:59 +08:00
as2252258 64e4307a57 1 2021-12-12 06:37:52 +08:00
as2252258 ab672127e6 1 2021-12-12 02:46:30 +08:00
as2252258 6e5b545a1e 1 2021-12-12 02:45:39 +08:00
as2252258 8229395e6d 1 2021-12-12 02:41:31 +08:00
as2252258 d5d2b04321 1 2021-12-11 17:56:35 +08:00
as2252258 ce9c184c83 1 2021-12-11 17:40:16 +08:00
as2252258 620de34559 1 2021-12-11 17:38:53 +08:00
as2252258 b01c71ea5e 1 2021-12-11 17:38:15 +08:00
as2252258 90e1f7eb29 1 2021-12-11 17:35:44 +08:00
as2252258 f3ad09ef66 1 2021-12-11 17:34:05 +08:00
as2252258 dfccb8816c 1 2021-12-11 17:32:28 +08:00
as2252258 1670ff3fef 1 2021-12-11 05:33:46 +08:00
as2252258 8870a7ca27 1 2021-12-11 05:33:00 +08:00
as2252258 ebb7ac9673 改名 2021-12-09 17:01:18 +08:00
as2252258 5aad8d2001 改名 2021-12-08 11:45:19 +08:00
as2252258 80713788c9 改名 2021-12-08 11:39:57 +08:00
as2252258 9f36acbbca 改名 2021-12-08 11:32:32 +08:00
as2252258 044d213a69 改名 2021-12-07 16:44:12 +08:00
as2252258 e5fe525f82 改名 2021-12-07 16:02:07 +08:00
as2252258 39e4e52908 改名 2021-12-07 16:00:52 +08:00
as2252258 f62014ff34 改名 2021-12-07 15:59:13 +08:00
as2252258 7935e6a6a3 改名 2021-12-07 15:53:56 +08:00
as2252258 d2acd50352 改名 2021-12-06 18:07:33 +08:00
as2252258 d02337ec22 改名 2021-12-06 17:58:11 +08:00
as2252258 57f12b6701 改名 2021-12-06 17:22:26 +08:00
as2252258 d500fd21ce 改名 2021-12-06 16:14:48 +08:00
as2252258 30d7b8684e 改名 2021-12-06 16:13:52 +08:00
as2252258 d8eb4d4e45 改名 2021-12-06 16:03:39 +08:00
as2252258 7004c5c0f8 改名 2021-12-06 15:54:31 +08:00
as2252258 81e55ecdf1 改名 2021-12-06 15:52:05 +08:00
as2252258 20adc186d4 改名 2021-12-06 15:51:29 +08:00
as2252258 8c16d9f4b3 改名 2021-12-06 15:48:57 +08:00
as2252258 b3e06a680a 改名 2021-12-06 15:47:12 +08:00
as2252258 3176443e5c 改名 2021-12-06 15:39:35 +08:00
as2252258 83962fa3ba 改名 2021-12-06 14:49:47 +08:00
as2252258 5475f2cd51 改名 2021-12-06 14:45:12 +08:00
as2252258 30212c0b86 改名 2021-12-06 14:44:18 +08:00
as2252258 4731463897 改名 2021-12-06 14:43:46 +08:00
as2252258 87e901f5b1 改名 2021-12-06 14:42:54 +08:00
as2252258 66f87b6da4 改名 2021-12-06 14:41:05 +08:00
as2252258 0007242b70 改名 2021-12-06 14:40:18 +08:00
as2252258 8653e6914b 改名 2021-12-06 14:39:03 +08:00
as2252258 816fec8ef4 改名 2021-12-06 14:38:17 +08:00
as2252258 b0ef09fd35 改名 2021-12-06 14:38:06 +08:00
as2252258 f7a2d6f30e 改名 2021-12-06 14:32:04 +08:00
as2252258 2950ba8fd5 改名 2021-12-06 14:24:41 +08:00
as2252258 2de5c82a73 改名 2021-12-06 14:22:08 +08:00
as2252258 758c4e7d5b 改名 2021-12-06 14:12:03 +08:00
as2252258 33f045aec7 改名 2021-12-06 13:49:01 +08:00
as2252258 35189de442 改名 2021-12-06 11:44:01 +08:00
as2252258 34e7fc0392 改名 2021-12-03 18:40:27 +08:00
as2252258 a3ce9f52ba 改名 2021-12-03 18:22:26 +08:00
as2252258 6e7da1b0ed 改名 2021-12-03 17:40:21 +08:00
as2252258 a6e0b5c1a2 改名 2021-12-03 16:24:44 +08:00
as2252258 13ab14f965 改名 2021-12-03 15:42:05 +08:00
as2252258 6729094f63 改名 2021-12-03 15:35:16 +08:00
as2252258 e1aeb17a5a 改名 2021-12-03 14:46:38 +08:00
as2252258 b9e20051ef 改名 2021-12-02 14:06:57 +08:00
as2252258 4ab6332176 改名 2021-12-01 19:05:10 +08:00
as2252258 abe2dad521 改名 2021-12-01 19:05:00 +08:00
as2252258 b0f70a13da 改名 2021-12-01 15:16:08 +08:00
as2252258 1e8aca91dd 改名 2021-12-01 14:08:09 +08:00
as2252258 b4ac5c4758 改名 2021-11-30 19:04:29 +08:00
as2252258 d161477957 改名 2021-11-30 19:04:16 +08:00
as2252258 a26b99dd1e 改名 2021-11-30 18:33:22 +08:00
as2252258 86e4a92ab0 改名 2021-11-30 18:31:41 +08:00
as2252258 ea425bb82d 改名 2021-11-30 18:30:15 +08:00
as2252258 ad0154d319 改名 2021-11-30 18:29:10 +08:00
as2252258 edb70d2b9b 改名 2021-11-30 18:26:23 +08:00
as2252258 9f3355cab4 改名 2021-11-30 18:23:56 +08:00
as2252258 4107b5bb07 改名 2021-11-30 15:48:18 +08:00
as2252258 048960c572 改名 2021-11-30 15:14:42 +08:00
as2252258 b826e1f594 改名 2021-11-30 15:10:01 +08:00
as2252258 e5b57cbcdb 改名 2021-11-30 14:59:51 +08:00
as2252258 2870a64792 改名 2021-11-30 14:32:56 +08:00
as2252258 4d1587bc8d 改名 2021-11-29 14:35:09 +08:00
114 changed files with 12713 additions and 11942 deletions
+9 -9
View File
@@ -1,9 +1,9 @@
### 該問題是如何引起的?
### 重現步驟
### 報錯信息
### 該問題是如何引起的?
### 重現步驟
### 報錯信息
+12 -12
View File
@@ -1,12 +1,12 @@
### 該Pull Request關聯的Issue
### 修改描述
### 測試用例
### 修復效果的截屏
### 該Pull Request關聯的Issue
### 修改描述
### 測試用例
### 修復效果的截屏
+37 -37
View File
@@ -1,37 +1,37 @@
# Created by .ignore support plugin (hsz.mobi)
### Yii template
assets/*
!assets/.gitignore
protected/runtime/*
!protected/runtime/.gitignore
protected/data/*.db
themes/classic/views/
### Example user template template
### Example user template
# IntelliJ project files
.idea
*.iml
out
gen
db/
async-queue/
composer.lock
*.log
commands/result
config/setting.php
tests/
vendor/
runtime/
*.xml
*.lock
oot
d
composer.lock
# Created by .ignore support plugin (hsz.mobi)
### Yii template
assets/*
!assets/.gitignore
protected/runtime/*
!protected/runtime/.gitignore
protected/data/*.db
themes/classic/views/
### Example user template template
### Example user template
# IntelliJ project files
.idea
*.iml
out
gen
db/
async-queue/
composer.lock
*.log
commands/result
config/setting.php
tests/
vendor/
runtime/
*.xml
*.lock
oot
d
composer.lock
+18 -18
View File
@@ -1,18 +1,18 @@
<?php
namespace PHPSTORM_META {
// Reflect
use Kiri\Di\Container;
use Psr\Container\ContainerInterface;
override(ContainerInterface::get(0), map('@'));
override(Container::get(0), map('@'));
override(Container::make(0), map('@'));
override(Container::create(0), map('@'));
// override(\Hyperf\Utils\Context::get(0), map('@'));
// override(\make(0), map('@'));
override(\di(0), map('@'));
override(\duplicate(0), map('@'));
}
<?php
namespace PHPSTORM_META {
// Reflect
use Kiri\Di\Container;
use Psr\Container\ContainerInterface;
override(ContainerInterface::get(0), map('@'));
override(Container::get(0), map('@'));
override(Container::make(0), map('@'));
override(Container::create(0), map('@'));
// override(\Hyperf\Utils\Context::get(0), map('@'));
// override(\make(0), map('@'));
override(\di(0), map('@'));
override(\duplicate(0), map('@'));
}
+21 -21
View File
@@ -1,21 +1,21 @@
MIT License
Copyright (c) 2020 向林
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.
MIT License
Copyright (c) 2020 向林
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.
+23 -23
View File
@@ -1,23 +1,23 @@
<?php
function version($oldVersion, $newVersion): bool
{
$first = explode('.', $oldVersion);
$end = explode('.', $newVersion);
while (count($first) > 0) {
$shift = (int)array_shift($first);
$endShift = (int)array_shift($end);
if ($endShift == $shift) {
continue;
}
if ($endShift < $shift) {
return true;
} else {
return false;
}
}
return false;
}
var_dump(version('1.4.4','1.4.3'));
<?php
function version($oldVersion, $newVersion): bool
{
$first = explode('.', $oldVersion);
$end = explode('.', $newVersion);
while (count($first) > 0) {
$shift = (int)array_shift($first);
$endShift = (int)array_shift($end);
if ($endShift == $shift) {
continue;
}
if ($endShift < $shift) {
return TRUE;
} else {
return FALSE;
}
}
return FALSE;
}
var_dump(version('1.4.4', '1.4.3'));
+46 -47
View File
@@ -1,47 +1,46 @@
{
"name": "game-worker/kiri-core",
"description": "test framework",
"authors": [
{
"name": "XiangLin",
"email": "as2252258@163.com"
}
],
"license": "MIT",
"require": {
"php": ">=8.0",
"ext-json": "*",
"ext-fileinfo": "*",
"ext-pdo": "*",
"ext-redis": "*",
"ext-simplexml": "*",
"ext-libxml": "*",
"ext-iconv": "*",
"ext-mbstring": "*",
"ext-xml": "*",
"ext-curl": "*",
"ext-openssl": "*",
"symfony/console": "v5.3.10",
"psr/log": "1.*",
"ext-sockets": "*",
"ext-pcntl": "*",
"ext-posix": "*",
"composer-runtime-api": "^2.0",
"swiftmailer/swiftmailer": "v6.3.*",
"psr/container": "^2.0",
"psr/http-server-middleware": "1.0.1",
"game-worker/kiri-event": "v1.0",
"ext-inotify": "*"
},
"autoload": {
"psr-4": {
"Kiri\\": "kiri-engine/",
"Gii\\": "kiri-gii/",
"Annotation\\": "kiri-note/"
},
"files": [
"error.php",
"function.php"
]
}
}
{
"name": "game-worker/kiri-core",
"description": "test framework",
"authors": [
{
"name": "XiangLin",
"email": "as2252258@163.com"
}
],
"license": "MIT",
"require": {
"php": ">=8.1",
"ext-json": "*",
"ext-fileinfo": "*",
"ext-pdo": "*",
"ext-redis": "*",
"ext-simplexml": "*",
"ext-libxml": "*",
"ext-iconv": "*",
"ext-mbstring": "*",
"ext-xml": "*",
"ext-curl": "*",
"ext-openssl": "*",
"symfony/console": "~v5.3.10",
"psr/log": "1.*",
"composer-runtime-api": "^2.0",
"psr/container": "^2.0",
"psr/http-server-middleware": "1.0.1",
"game-worker/kiri-event": "~v2.0",
"ext-inotify": "*"
},
"autoload": {
"psr-4": {
"Kiri\\": "kiri-engine/",
"Kiri\\Gateway\\": "kiri-gateway/",
"Kiri\\Websocket\\": "kiri-websocket-server/",
"Gii\\": "kiri-gii/",
"Kiri\\Annotation\\": "kiri-annotation/",
"Kiri\\Task\\": "kiri-task/"
},
"files": [
"error.php",
"function.php"
]
}
}
+31 -31
View File
@@ -1,31 +1,31 @@
<?php
define('SUCCESS', 0);
define('NO_AUTH', 401);
define('ERROR_MESSAGES', [
SUCCESS => 'ok',
NO_AUTH => ''
]);
if (!function_exists('message')) {
/**
* @param $code
* @param $replace
* @param string $default
* @return mixed|string
*/
function message($code, $replace, $default = '')
{
if (!isset(ERROR_MESSAGES[$code])) {
if (!empty($default)) {
return $default;
}
return 'unknown error';
}
return sprintf(ERROR_MESSAGES[$code], $replace);
}
}
<?php
define('SUCCESS', 0);
define('NO_AUTH', 401);
define('ERROR_MESSAGES', [
SUCCESS => 'ok',
NO_AUTH => ''
]);
if (!function_exists('message')) {
/**
* @param $code
* @param $replace
* @param string $default
* @return mixed|string
*/
function message($code, $replace, $default = '')
{
if (!isset(ERROR_MESSAGES[$code])) {
if (!empty($default)) {
return $default;
}
return 'unknown error';
}
return sprintf(ERROR_MESSAGES[$code], $replace);
}
}
+1234 -1155
View File
File diff suppressed because it is too large Load Diff
@@ -1,86 +1,86 @@
<?php
namespace Annotation;
use DirectoryIterator;
use Exception;
use ReflectionException;
use Kiri\Abstracts\Component;
/**
* Class Annotation
* @package Annotation
*/
class Annotation extends Component
{
private Loader $_loader;
/**
*
*/
public function init(): void
{
$this->_loader = new Loader();
}
/**
* @return Loader
*/
public function getLoader(): Loader
{
return $this->_loader;
}
/**
* @param Loader $loader
* @return Loader
*/
public function setLoader(Loader $loader): Loader
{
return $this->_loader = $loader;
}
/**
* @param object $class
* @throws ReflectionException
*/
public function injectProperty(object $class)
{
$this->_loader->injectProperty($class::class, $class);
}
/**
* @param string $path
* @param string $namespace
* @param array $exclude
* @return static
* @throws Exception
*/
public function read(string $path, string $namespace = 'App', array $exclude = []): static
{
$this->_loader->_scanDir(new DirectoryIterator($path), $namespace, $exclude);
return $this;
}
/**
* @param string $dir
* @param array $exclude
* @return array
* @throws Exception
*/
public function runtime(string $dir, array $exclude = []): array
{
return $this->_loader->loadByDirectory($dir, $exclude);
}
}
<?php
namespace Kiri\Annotation;
use DirectoryIterator;
use Exception;
use ReflectionException;
use Kiri\Abstracts\Component;
/**
* Class Annotation
* @package Annotation
*/
class Annotation extends Component
{
private Loader $_loader;
/**
*
*/
public function init(): void
{
$this->_loader = new Loader();
}
/**
* @return Loader
*/
public function getLoader(): Loader
{
return $this->_loader;
}
/**
* @param Loader $loader
* @return Loader
*/
public function setLoader(Loader $loader): Loader
{
return $this->_loader = $loader;
}
/**
* @param object $class
* @throws ReflectionException
*/
public function injectProperty(object $class)
{
$this->_loader->injectProperty($class::class, $class);
}
/**
* @param string $path
* @param string $namespace
* @param array $exclude
* @return static
* @throws Exception
*/
public function read(string $path, string $namespace = 'App', array $exclude = []): static
{
$this->_loader->_scanDir(new DirectoryIterator($path), $namespace, $exclude);
return $this;
}
/**
* @param string $dir
* @param array $exclude
* @return array
* @throws Exception
*/
public function runtime(string $dir, array $exclude = []): array
{
return $this->_loader->loadByDirectory($dir, $exclude);
}
}
@@ -1,37 +1,37 @@
<?php
namespace Annotation;
use Exception;
defined('ASPECT_ERROR') or define('ASPECT_ERROR', 'Aspect annotation must implement ');
/**
* Class Aspect
* @package Annotation
*/
#[\Attribute(\Attribute::TARGET_METHOD)] class Aspect extends Attribute
{
/**
* Aspect constructor.
* @param string $aspect
*/
public function __construct(public string $aspect)
{
}
/**
* @throws Exception
*/
public function execute(mixed $class, mixed $method = ''): bool
{
return true;
}
}
<?php
namespace Kiri\Annotation;
use Exception;
defined('ASPECT_ERROR') or define('ASPECT_ERROR', 'Aspect annotation must implement ');
/**
* Class Aspect
* @package Annotation
*/
#[\Attribute(\Attribute::TARGET_METHOD)] class Aspect extends Attribute
{
/**
* Aspect constructor.
* @param string $aspect
*/
public function __construct(public string $aspect)
{
}
/**
* @throws Exception
*/
public function execute(mixed $class, mixed $method = ''): bool
{
return true;
}
}
@@ -1,26 +1,27 @@
<?php
namespace Annotation;
/**
* Class Attribute
* @package Annotation
*/
abstract class Attribute implements IAnnotation
{
/**
* @param static $class
* @param mixed|string $method
* @return mixed
*/
public function execute(mixed $class, mixed $method = ''): mixed
{
// TODO: Implement execute() method.
return true;
}
}
<?php
namespace Kiri\Annotation;
/**
* Class Attribute
* @package Annotation
*/
abstract class Attribute implements IAnnotation
{
/**
* @param static $class
* @param mixed|string $method
* @return mixed
*/
#[\ReturnTypeWillChange]
public function execute(mixed $class, mixed $method = ''): mixed
{
// TODO: Implement execute() method.
return true;
}
}
@@ -1,46 +1,46 @@
<?php
namespace Annotation;
use Exception;
use Kiri\Events\EventProvider;
use Kiri\Kiri;
/**
* Class Event
* @package Annotation
*/
#[\Attribute(\Attribute::TARGET_METHOD)] class Event extends Attribute
{
/**
* Event constructor.
* @param string $name
* @param array $params
*/
public function __construct(public string $name, public array $params = [])
{
}
/**
* @param mixed $class
* @param mixed|null $method
* @return bool
* @throws Exception
*/
public function execute(mixed $class, mixed $method = null): bool
{
$pro = Kiri::getDi()->get(EventProvider::class);
if (is_string($class)) {
$class = Kiri::getDi()->get($class);
}
$pro->on($this->name, [$class, $method]);
return true;
}
}
<?php
namespace Kiri\Annotation;
use Exception;
use Kiri\Events\EventProvider;
use Kiri\Kiri;
/**
* Class Event
* @package Annotation
*/
#[\Attribute(\Attribute::TARGET_METHOD)] class Event extends Attribute
{
/**
* Event constructor.
* @param string $name
* @param array $params
*/
public function __construct(public string $name, public array $params = [])
{
}
/**
* @param mixed $class
* @param mixed|null $method
* @return bool
* @throws Exception
*/
public function execute(mixed $class, mixed $method = null): bool
{
$pro = Kiri::getDi()->get(EventProvider::class);
if (is_string($class)) {
$class = Kiri::getDi()->get($class);
}
$pro->on($this->name, [$class, $method]);
return true;
}
}
@@ -1,19 +1,19 @@
<?php
namespace Annotation;
interface IAnnotation
{
/**
* @param mixed $class
* @param mixed $method
* @return mixed
*/
public function execute(mixed $class, mixed $method = ''): mixed;
}
<?php
namespace Kiri\Annotation;
interface IAnnotation
{
/**
* @param mixed $class
* @param mixed $method
* @return mixed
*/
public function execute(mixed $class, mixed $method = ''): mixed;
}
@@ -1,105 +1,104 @@
<?php
namespace Annotation;
use Exception;
use Kiri\Core\Str;
use Kiri\Kiri;
use ReflectionException;
use ReflectionProperty;
/**
* Class Inject
* @package Annotation
*/
#[\Attribute(\Attribute::TARGET_PROPERTY)] class Inject extends Attribute
{
/**
* Inject constructor.
* @param string $value
* @param array $construct
*/
public function __construct(public string $value, public array $construct = [])
{
}
/**
* @param mixed $class
* @param mixed|null $method
* @return bool
* @throws ReflectionException
* @throws Exception
*/
public function execute(mixed $class, mixed $method = null): bool
{
if (!($method = $this->getProperty($class, $method))) {
return false;
}
/** @var ReflectionProperty $class */
$injectValue = static::parseInjectValue();
if ($method->isPrivate() || $method->isProtected()) {
$this->setter($class, $method, $injectValue);
} else {
$class->{$method->getName()} = $injectValue;
}
return true;
}
/**
* @param $class
* @param $method
* @param $injectValue
*/
private function setter($class, $method, $injectValue)
{
$method = 'set' . ucfirst(Str::convertUnderline($method->getName()));
if (!method_exists($class, $method)) {
return;
}
$class->$method($injectValue);
}
/**
* @param $class
* @param $method
* @return ReflectionProperty|bool
* @throws ReflectionException
*/
private function getProperty($class, $method): ReflectionProperty|bool
{
if ($method instanceof ReflectionProperty && !$method->isStatic()) {
return $method;
}
if (is_object($class)) $class = $class::class;
$method = Kiri::getDi()->getClassReflectionProperty($class, $method);
if (!$method || $method->isStatic()) {
return false;
}
return $method;
}
/**
* @return mixed
* @throws Exception
*/
private function parseInjectValue(): mixed
{
if (!Kiri::app()->has($this->value)) {
if (!empty($this->construct)) {
return Kiri::getDi()->create($this->value, $this->construct);
}
return Kiri::getDi()->get($this->value);
} else {
return Kiri::app()->get($this->value);
}
}
}
<?php
namespace Kiri\Annotation;
use Exception;
use Kiri\Core\Str;
use Kiri\Kiri;
use ReflectionException;
use ReflectionProperty;
/**
* Class Inject
* @package Annotation
*/
#[\Attribute(\Attribute::TARGET_PROPERTY)] class Inject extends Attribute
{
/**
* Inject constructor.
* @param string $value
* @param array $construct
*/
public function __construct(public string $value, public array $construct = [])
{
}
/**
* @param mixed $class
* @param mixed|null $method
* @return bool
* @throws ReflectionException
* @throws Exception
*/
public function execute(mixed $class, mixed $method = null): bool
{
if (!($method = $this->getProperty($class, $method))) {
return false;
}
/** @var ReflectionProperty $class */
$injectValue = static::parseInjectValue();
if ($method->isPrivate() || $method->isProtected()) {
$this->setter($class, $method, $injectValue);
} else {
$class->{$method->getName()} = $injectValue;
}
return true;
}
/**
* @param $class
* @param $method
* @param $injectValue
*/
private function setter($class, $method, $injectValue)
{
$method = 'set' . ucfirst(Str::convertUnderline($method->getName()));
if (!method_exists($class, $method)) {
return;
}
$class->$method($injectValue);
}
/**
* @param $class
* @param $method
* @return ReflectionProperty|bool
*/
private function getProperty($class, $method): ReflectionProperty|bool
{
if ($method instanceof ReflectionProperty && !$method->isStatic()) {
return $method;
}
if (is_object($class)) $class = $class::class;
$method = Kiri::getDi()->getClassReflectionProperty($class, $method);
if (!$method || $method->isStatic()) {
return false;
}
return $method;
}
/**
* @return mixed
* @throws Exception
*/
private function parseInjectValue(): mixed
{
if (!Kiri::app()->has($this->value)) {
if (!empty($this->construct)) {
return Kiri::getDi()->create($this->value, $this->construct);
}
return Kiri::getDi()->get($this->value);
} else {
return Kiri::app()->get($this->value);
}
}
}
@@ -1,243 +1,225 @@
<?php
namespace Annotation;
use DirectoryIterator;
use Exception;
use Kiri\Abstracts\BaseObject;
use Kiri\Kiri;
use ReflectionClass;
use ReflectionException;
use Throwable;
/**
* Class Loader
* @package Annotation
*/
class Loader extends BaseObject
{
private array $_classes = [];
private array $_directory = [];
private array $_property = [];
private array $_methods = [];
/**
* @param $path
* @param $namespace
* @throws Exception
*/
public function loader($path, $namespace)
{
$this->_scanDir(new DirectoryIterator($path), $namespace);
}
/**
* @param string $class
* @param string $property
* @return \ReflectionProperty|array|null
* @throws ReflectionException
*/
public function getProperty(string $class, string $property = ''): \ReflectionProperty|array|null
{
return Kiri::getDi()->getClassReflectionProperty($class, $property);
}
/**
* @param string $class
* @param object $handler
* @return $this
* @throws ReflectionException
* @throws Exception
*/
public function injectProperty(string $class, object $handler): static
{
$di = Kiri::getDi();
$reflect = $di->getReflect($class);
$di->propertyInject($reflect, $handler);
return $this;
}
/**
* @param string $class
* @param string $method
* @return mixed
*/
public function getMethod(string $class, string $method = ''): array
{
if (!isset($this->_methods[$class])) {
return [];
}
$properties = $this->_methods[$class];
if (!empty($method) && isset($properties[$method])) {
return $properties[$method];
}
return $properties;
}
/**
* @param DirectoryIterator $paths
* @param $namespace
* @param array $exclude
* @throws Exception
*/
public function _scanDir(DirectoryIterator $paths, $namespace, array $exclude = [])
{
foreach ($paths as $path) {
if ($path->isDot() || str_starts_with($path->getFilename(), '.')) {
continue;
}
if ($this->inExclude($exclude, $path->getRealPath())) {
continue;
}
if ($path->isDir()) {
$iterator = new DirectoryIterator($path->getRealPath());
$directory = rtrim($path->getRealPath(), '/');
if (!isset($this->_directory[$directory])) {
$this->_directory[$directory] = [];
}
$this->_scanDir($iterator, $namespace);
} else {
$this->readFile($path, $namespace);
}
}
}
/**
* @param DirectoryIterator $path
* @param $namespace
* @throws Exception
*/
private function readFile(DirectoryIterator $path, $namespace)
{
try {
if ($path->getExtension() !== 'php') {
return;
}
$replace = $this->getReflect($path, $namespace);
if (!$replace || !$replace->getAttributes(Target::class)) {
return;
}
$this->appendFileToDirectory($path->getRealPath(), $replace->getName());
} catch (Throwable $throwable) {
$this->error(jTraceEx($throwable), 'throwable');
}
}
/**
* @param DirectoryIterator $path
* @param string $namespace
* @return ReflectionClass|null
* @throws ReflectionException
*/
private function getReflect(DirectoryIterator $path, string $namespace): ?ReflectionClass
{
$class = $this->explodeFileName($path, $namespace);
if (!class_exists($class)) {
return null;
}
return Kiri::getDi()->getReflect($class);
}
/**
* @param string $path
* @param array $exclude
* @return array
* @throws Exception
*/
public function loadByDirectory(string $path, array $exclude = []): array
{
try {
$path = '/' . trim($path, '/');
$paths = [];
foreach ($this->_directory as $key => $_path) {
$key = '/' . trim($key, '/');
if (!str_starts_with($key, $path) || $this->inExclude($exclude, $path)) {
continue;
}
unset($this->_directory[$key]);
foreach ($_path as $item) {
$paths[] = $item;
}
}
return $paths;
} catch (Throwable $exception) {
$this->addError($exception, 'throwable');
return [];
}
}
/**
* @param array $exclude
* @param $path
* @return bool
*/
private function inExclude(array $exclude, $path): bool
{
if (empty($exclude)) {
return false;
}
foreach ($exclude as $value) {
if (str_starts_with($path, $value)) {
return true;
}
}
return false;
}
/**
* @param DirectoryIterator $path
* @param string $namespace
* @return string
*/
private function explodeFileName(DirectoryIterator $path, string $namespace): string
{
$replace = str_replace(APP_PATH, '', $path->getRealPath());
$replace = str_replace('.php', '', $replace);
$replace = str_replace(DIRECTORY_SEPARATOR, '\\', $replace);
$explode = explode('\\', $replace);
array_shift($explode);
return $namespace . '\\' . implode('\\', $explode);
}
/**
* @param string $filePath
* @param string $className
*/
public function appendFileToDirectory(string $filePath, string $className)
{
$array = explode('/', $filePath);
unset($array[count($array) - 1]);
$array = '/' . trim(implode('/', $array), '/');
$this->_directory[$array][] = $className;
}
}
<?php
namespace Kiri\Annotation;
use DirectoryIterator;
use Exception;
use Kiri\Abstracts\Component;
use Kiri\Kiri;
use ReflectionClass;
use ReflectionException;
use Throwable;
/**
* Class Loader
* @package Annotation
*/
class Loader extends Component
{
private array $_directory = [];
private array $_methods = [];
/**
* @param $path
* @param $namespace
* @throws Exception
*/
public function loader($path, $namespace)
{
$this->_scanDir(new DirectoryIterator($path), $namespace);
}
/**
* @param string $class
* @param object $handler
* @return $this
* @throws ReflectionException
* @throws Exception
*/
public function injectProperty(string $class, object $handler): static
{
$di = Kiri::getDi();
$reflect = $di->getReflect($class);
$di->propertyInject($reflect, $handler);
return $this;
}
/**
* @param string $class
* @param string $method
* @return mixed
*/
public function getMethod(string $class, string $method = ''): array
{
if (!isset($this->_methods[$class])) {
return [];
}
$properties = $this->_methods[$class];
if (!empty($method) && isset($properties[$method])) {
return $properties[$method];
}
return $properties;
}
/**
* @param DirectoryIterator $paths
* @param $namespace
* @param array $exclude
* @throws Exception
*/
public function _scanDir(DirectoryIterator $paths, $namespace, array $exclude = [])
{
foreach ($paths as $path) {
if ($path->isDot() || str_starts_with($path->getFilename(), '.')) {
continue;
}
if ($this->inExclude($exclude, $path->getRealPath())) {
continue;
}
if ($path->isDir()) {
$iterator = new DirectoryIterator($path->getRealPath());
$directory = rtrim($path->getRealPath(), '/');
if (!isset($this->_directory[$directory])) {
$this->_directory[$directory] = [];
}
$this->_scanDir($iterator, $namespace);
} else {
$this->readFile($path, $namespace);
}
}
}
/**
* @param DirectoryIterator $path
* @param $namespace
* @throws Exception
*/
private function readFile(DirectoryIterator $path, $namespace)
{
try {
if ($path->getExtension() !== 'php') {
return;
}
$replace = $this->getReflect($path, $namespace);
if (!$replace || !$replace->getAttributes(Target::class)) {
return;
}
$this->appendFileToDirectory($path->getRealPath(), $replace->getName());
} catch (Throwable $throwable) {
$this->error(jTraceEx($throwable), 'throwable');
}
}
/**
* @param DirectoryIterator $path
* @param string $namespace
* @return ReflectionClass|null
*/
private function getReflect(DirectoryIterator $path, string $namespace): ?ReflectionClass
{
$class = $this->explodeFileName($path, $namespace);
if (!class_exists($class)) {
return null;
}
return Kiri::getDi()->getReflect($class);
}
/**
* @param string $path
* @param array $exclude
* @return array
* @throws Exception
*/
public function loadByDirectory(string $path, array $exclude = []): array
{
try {
$path = '/' . trim($path, '/');
$paths = [];
foreach ($this->_directory as $key => $_path) {
$key = '/' . trim($key, '/');
if (!str_starts_with($key, $path) || $this->inExclude($exclude, $path)) {
continue;
}
unset($this->_directory[$key]);
foreach ($_path as $item) {
$paths[] = $item;
}
}
return $paths;
} catch (Throwable $exception) {
$this->addError($exception, 'throwable');
return [];
}
}
/**
* @param array $exclude
* @param $path
* @return bool
*/
private function inExclude(array $exclude, $path): bool
{
if (empty($exclude)) {
return false;
}
foreach ($exclude as $value) {
if (str_starts_with($path, $value)) {
return true;
}
}
return false;
}
/**
* @param DirectoryIterator $path
* @param string $namespace
* @return string
*/
private function explodeFileName(DirectoryIterator $path, string $namespace): string
{
$replace = str_replace(APP_PATH, '', $path->getRealPath());
$replace = str_replace('.php', '', $replace);
$replace = str_replace(DIRECTORY_SEPARATOR, '\\', $replace);
$explode = explode('\\', $replace);
array_shift($explode);
return $namespace . '\\' . implode('\\', $explode);
}
/**
* @param string $filePath
* @param string $className
*/
public function appendFileToDirectory(string $filePath, string $className)
{
$array = explode('/', $filePath);
unset($array[count($array) - 1]);
$array = '/' . trim(implode('/', $array), '/');
$this->_directory[$array][] = $className;
}
}
@@ -1,31 +1,31 @@
<?php
namespace Annotation;
use Kiri\Kiri;
#[\Attribute(\Attribute::TARGET_CLASS)] class Mapping extends Attribute
{
/**
* @param string $class
*/
public function __construct(public string $class)
{
}
/**
* @param mixed $class
* @param mixed|string $method
* @return mixed
*/
public function execute(mixed $class, mixed $method = ''): mixed
{
Kiri::getDi()->mapping($this->class, $class);
return parent::execute($class, $method);
}
}
<?php
namespace Kiri\Annotation;
use Kiri\Kiri;
#[\Attribute(\Attribute::TARGET_CLASS)] class Mapping extends Attribute
{
/**
* @param string $class
*/
public function __construct(public string $class)
{
}
/**
* @param mixed $class
* @param mixed|string $method
* @return mixed
*/
public function execute(mixed $class, mixed $method = ''): mixed
{
Kiri::getDi()->mapping($this->class, $class);
return parent::execute($class, $method);
}
}
@@ -1,34 +1,34 @@
<?php
namespace Annotation\Route;
use Annotation\Attribute;
/**
* Class Document
* @package Annotation\Route
*/
#[\Attribute(\Attribute::TARGET_METHOD)] class Document extends Attribute
{
const INTEGER = 'int';
const STRING = 'string';
const BOOLEAN = 'bool';
const FLOAT = 'float';
const ALIAS = [
self::INTEGER => '整数',
self::STRING => '字符串',
self::BOOLEAN => '布尔值',
self::FLOAT => '浮点',
];
public function __construct(array $request, array $response)
{
}
}
<?php
namespace Kiri\Annotation\Route;
use Kiri\Annotation\Attribute;
/**
* Class Document
* @package Annotation\Route
*/
#[\Attribute(\Attribute::TARGET_METHOD)] class Document extends Attribute
{
const INTEGER = 'int';
const STRING = 'string';
const BOOLEAN = 'bool';
const FLOAT = 'float';
const ALIAS = [
self::INTEGER => '整数',
self::STRING => '字符串',
self::BOOLEAN => '布尔值',
self::FLOAT => '浮点',
];
public function __construct(array $request, array $response)
{
}
}
@@ -1,52 +1,53 @@
<?php
namespace Annotation\Route;
use Annotation\Attribute;
use Http\Handler\Abstracts\MiddlewareManager;
use Psr\Http\Server\MiddlewareInterface;
/**
* Class Middleware
* @package Annotation\Route
*/
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] class Middleware extends Attribute
{
/**
* Interceptor constructor.
* @param string|array $middleware
* @throws
*/
public function __construct(public string|array $middleware)
{
if (is_string($this->middleware)) {
$this->middleware = [$this->middleware];
}
$array = [];
foreach ($this->middleware as $value) {
if (!in_array(MiddlewareInterface::class, class_implements($value))) {
throw new \Exception('The middleware');
}
$array[] = $value;
}
$this->middleware = $array;
}
/**
* @param mixed $class
* @param mixed|null $method
* @return $this
*/
public function execute(mixed $class, mixed $method = null): mixed
{
MiddlewareManager::add($class, $method, $this->middleware);
return parent::execute($class, $method);
}
}
<?php
namespace Kiri\Annotation\Route;
use Kiri\Annotation\Attribute;
use Http\Handler\Abstracts\MiddlewareManager;
use Psr\Http\Server\MiddlewareInterface;
/**
* Class Middleware
* @package Annotation\Route
*/
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] class Middleware extends Attribute
{
/**
* Interceptor constructor.
* @param string|array $middleware
* @throws
*/
public function __construct(public string|array $middleware)
{
if (is_string($this->middleware)) {
$this->middleware = [$this->middleware];
}
$array = [];
foreach ($this->middleware as $value) {
if (!in_array(MiddlewareInterface::class, class_implements($value))) {
throw new \Exception('The middleware');
}
$array[] = $value;
}
$this->middleware = $array;
}
/**
* @param mixed $class
* @param mixed|null $method
* @return $this
* @throws \ReflectionException
*/
public function execute(mixed $class, mixed $method = null): mixed
{
MiddlewareManager::add($class, $method, $this->middleware);
return parent::execute($class, $method);
}
}
@@ -1,41 +1,41 @@
<?php
namespace Annotation\Route;
use Annotation\Attribute;
use Http\Handler\Router;
use Kiri\Kiri;
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] class Route extends Attribute
{
/**
* Route constructor.
* @param string $uri
* @param string $method
* @param string $version
*/
public function __construct(public string $uri, public string $method, public string $version = 'v.1.0')
{
$this->uri = '/' . ltrim($this->uri, '/');
$this->method = strtoupper($this->method);
}
/**
* @param mixed $class
* @param mixed|null $method
* @return bool
* @throws \ReflectionException
*/
public function execute(mixed $class, mixed $method = null): bool
{
$di = Kiri::getDi()->get(Router::class);
$di->addRoute($this->method, $this->uri, $class . '@' . $method);
return parent::execute($class, $method);
}
}
<?php
namespace Kiri\Annotation\Route;
use Kiri\Annotation\Attribute;
use Http\Handler\Router;
use Kiri\Kiri;
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] class Route extends Attribute
{
/**
* Route constructor.
* @param string $uri
* @param string $method
* @param string $version
*/
public function __construct(public string $uri, public string $method, public string $version = 'v.1.0')
{
$this->uri = '/' . ltrim($this->uri, '/');
$this->method = strtoupper($this->method);
}
/**
* @param mixed $class
* @param mixed|null $method
* @return bool
* @throws \ReflectionException
*/
public function execute(mixed $class, mixed $method = null): bool
{
$di = Kiri::getDi()->get(Router::class);
$di->addRoute($this->method, $this->uri, $class . '@' . $method);
return parent::execute($class, $method);
}
}
@@ -1,31 +1,31 @@
<?php
namespace Annotation\Route;
use Annotation\Attribute;
/**
* Class Socket
* @package Annotation
*/
#[\Attribute(\Attribute::TARGET_METHOD)] class Socket extends Attribute
{
const CLOSE = 'CLOSE';
const MESSAGE = 'MESSAGE';
const HANDSHAKE = 'HANDSHAKE';
/**
* Socket constructor.
* @param string $event
* @param string|null $uri
* @param string $version
*/
public function __construct(string $event, ?string $uri = null, string $version = 'v.1.0')
{
}
}
<?php
namespace Kiri\Annotation\Route;
use Kiri\Annotation\Attribute;
/**
* Class Socket
* @package Annotation
*/
#[\Attribute(\Attribute::TARGET_METHOD)] class Socket extends Attribute
{
const CLOSE = 'CLOSE';
const MESSAGE = 'MESSAGE';
const HANDSHAKE = 'HANDSHAKE';
/**
* Socket constructor.
* @param string $event
* @param string|null $uri
* @param string $version
*/
public function __construct(string $event, ?string $uri = null, string $version = 'v.1.0')
{
}
}
@@ -1,28 +1,28 @@
<?php
namespace Annotation;
/**
* Class Target
* @package Annotation
*/
#[\Attribute(\Attribute::TARGET_CLASS)] class Target extends Attribute
{
const WORKER = 'worker';
const ALL = 'any';
const PROCESS = 'process';
const TASK = 'task';
/**
* @param string $only
*/
public function __construct(string $only = Target::ALL)
{
}
}
<?php
namespace Kiri\Annotation;
/**
* Class Target
* @package Annotation
*/
#[\Attribute(\Attribute::TARGET_CLASS)] class Target extends Attribute
{
const WORKER = 'worker';
const ALL = 'any';
const PROCESS = 'process';
const TASK = 'task';
/**
* @param string $only
*/
public function __construct(string $only = Target::ALL)
{
}
}
@@ -1,43 +1,44 @@
<?php
namespace Annotation;
use Exception;
use Kiri\Kiri;
/**
* Class Asynchronous
* @package Annotation
* Task任务
*/
#[\Attribute(\Attribute::TARGET_CLASS)] class Asynchronous extends Attribute
{
/**
* Asynchronous constructor.
* @param string $name
*/
public function __construct(public string $name)
{
}
/**
* @param mixed $class
* @param mixed|null $method
* @return bool
* @throws Exception
*/
public function execute(mixed $class, mixed $method = null): bool
{
$async = Kiri::app()->getAsync();
$async->addAsync($this->name, $class);
return true;
}
}
<?php
namespace Kiri\Annotation;
use Exception;
use Kiri\Kiri;
use Server\Tasker\AsyncTaskExecute;
/**
* Class Task
* @package Annotation
* Task任务
*/
#[\Attribute(\Attribute::TARGET_CLASS)] class Task extends Attribute
{
/**
* Task constructor.
* @param string $name
*/
public function __construct(public string $name)
{
}
/**
* @param mixed $class
* @param mixed|null $method
* @return bool
* @throws Exception
*/
public function execute(mixed $class, mixed $method = null): bool
{
$task = Kiri::getDi()->get(AsyncTaskExecute::class);
$task->reg($this->name, $class);
return true;
}
}
+12
View File
@@ -0,0 +1,12 @@
<?php
namespace Kiri\Abstracts;
abstract class AbstractServer extends Component
{
public string $name = 'http';
}
+451 -460
View File
@@ -1,460 +1,451 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/10/7 0007
* Time: 2:13
*/
declare(strict_types=1);
namespace Kiri\Abstracts;
use Annotation\Annotation as SAnnotation;
use Database\Connection;
use Exception;
use Http\Handler\Router;
use Kiri\Events\OnBeforeCommandExecute;
use Server\Server;
use Kafka\KafkaProvider;
use Kiri\Async;
use Kiri\Cache\Redis;
use Kiri\Di\LocalService;
use Kiri\Error\ErrorHandler;
use Kiri\Error\Logger;
use Kiri\Events\EventProvider;
use Kiri\Exception\InitException;
use Kiri\Exception\NotFindClassException;
use Kiri\Kiri;
use ReflectionException;
use Server\ServerManager;
use Server\Contract\OnTaskInterface;
use Swoole\Table;
/**
* Class BaseApplication
* @package Kiri\Kiri\Base
*/
abstract class BaseApplication extends Component
{
use TraitApplication;
/**
* @var string
*/
public string $storage = APP_PATH . 'storage';
public string $envPath = APP_PATH . '.env';
/**
* Init constructor.
*
*
* @throws
*/
public function __construct()
{
Kiri::init($this);
$config = sweep(APP_PATH . '/config');
$this->moreComponents();
$this->parseInt($config);
$this->parseEvents($config);
$this->initErrorHandler();
$this->enableEnvConfig();
$this->mapping($config['mapping'] ?? []);
parent::__construct();
}
/**
* @param array $mapping
*/
public function mapping(array $mapping)
{
$di = Kiri::getDi();
foreach ($mapping as $interface => $class) {
$di->mapping($interface, $class);
}
}
/**
* @return array
*/
public function enableEnvConfig(): array
{
if (!file_exists($this->envPath)) {
return [];
}
$lines = $this->readLinesFromFile($this->envPath);
foreach ($lines as $line) {
if (!$this->isComment($line) && $this->looksLikeSetter($line)) {
[$key, $value] = explode('=', $line);
putenv(trim($key) . '=' . trim($value));
}
}
return $lines;
}
/**
* Read lines from the file, auto detecting line endings.
*
* @param string $filePath
*
* @return array
*/
protected function readLinesFromFile(string $filePath): array
{
// Read file into an array of lines with auto-detected line endings
$autodetect = ini_get('auto_detect_line_endings');
ini_set('auto_detect_line_endings', '1');
$lines = file($filePath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
ini_set('auto_detect_line_endings', $autodetect);
return $lines;
}
/**
* Determine if the line in the file is a comment, e.g. begins with a #.
*
* @param string $line
*
* @return bool
*/
protected function isComment(string $line): bool
{
$line = ltrim($line);
return isset($line[0]) && $line[0] === '#';
}
/**
* Determine if the given line looks like it's setting a variable.
*
* @param string $line
*
* @return bool
*/
protected function looksLikeSetter(string $line): bool
{
return str_contains($line, '=');
}
/**
* @param $config
*
* @throws
*/
public function parseInt($config)
{
Config::sets($config);
if ($storage = Config::get('storage', 'storage')) {
if (!str_contains($storage, APP_PATH)) {
$storage = APP_PATH . $storage . '/';
}
if (!is_dir($storage)) {
mkdir($storage);
}
if (!is_dir($storage) || !is_writeable($storage)) {
throw new InitException("Directory {$storage} does not have write permission");
}
}
}
/**
* @param $name
* @return mixed
* @throws ReflectionException
* @throws NotFindClassException
* @throws Exception
*/
public function __get($name): mixed
{
if ($this->has($name)) {
return $this->get($name);
}
return parent::__get($name); // TODO: Change the autogenerated stub
}
/**
* @param $config
*
* @throws
*/
public function parseEvents($config)
{
if (!isset($config['events']) || !is_array($config['events'])) {
return;
}
foreach ($config['events'] as $key => $value) {
if (is_string($value)) {
$value = Kiri::createObject($value);
}
$this->addEvent($key, $value);
}
}
/**
* @param OnTaskInterface $execute
* @throws ReflectionException
*/
public function task(OnTaskInterface $execute): void
{
di(ServerManager::class)->task($execute);
}
/**
* @param $key
* @param $value
* @throws InitException
* @throws Exception
*/
private function addEvent($key, $value): void
{
$eventProvider = di(EventProvider::class);
if ($value instanceof \Closure || is_object($value)) {
$eventProvider->on($key, $value, 0);
return;
}
if (is_array($value)) {
if (is_object($value[0]) && !($value[0] instanceof \Closure)) {
$eventProvider->on($key, $value, 0);
return;
}
if (is_string($value[0])) {
$value[0] = Kiri::createObject($value[0]);
$eventProvider->on($key, $value, 0);
return;
}
foreach ($value as $item) {
if (!is_callable($item, true)) {
throw new InitException("Class does not hav callback.");
}
$eventProvider->on($key, $item, 0);
}
}
}
/**
* @param $name
* @return mixed
* @throws Exception
*/
public function clone($name): mixed
{
return clone $this->get($name);
}
/**
*
* @throws Exception
*/
public function initErrorHandler()
{
$this->get('error')->register();
}
/**
* @param $name
* @return mixed
* @throws
*/
public function get($name): mixed
{
return di(LocalService::class)->get($name);
}
/**
* @return mixed
*/
public function getLocalIps(): mixed
{
return swoole_get_local_ip();
}
/**
* @return mixed
*/
public function getFirstLocal(): mixed
{
return current($this->getLocalIps());
}
/**
* @return Logger
* @throws
*/
public function getLogger(): Logger
{
return $this->get('logger');
}
/**
* @return \Redis|Redis
* @throws
*/
public function getRedis(): Redis|\Redis
{
return Kiri::getDi()->get(Redis::class);
}
/**
* @param $ip
* @return bool
*/
public function isLocal($ip): bool
{
return $this->getFirstLocal() == $ip;
}
/**
* @return ErrorHandler
* @throws
*/
public function getError(): ErrorHandler
{
return $this->get('error');
}
/**
* @param $name
* @return Table
* @throws
*/
public function getTable($name): Table
{
return $this->get($name);
}
/**
* @return Config
* @throws
*/
public function getConfig(): Config
{
return $this->get('config');
}
/**
* @return Router
* @throws
*/
public function getRouter(): Router
{
return Kiri::getDi()->get(Router::class);
}
/**
* @return Server
* @throws
*/
public function getServer(): Server
{
return $this->get('server');
}
/**
* @return \Swoole\Http\Server|\Swoole\Server|\Swoole\WebSocket\Server|null
* @throws
*/
public function getSwoole(): \Swoole\Http\Server|\Swoole\Server|\Swoole\WebSocket\Server|null
{
return di(ServerManager::class)->getServer();
}
/**
* @return SAnnotation
* @throws
*/
public function getAnnotation(): SAnnotation
{
return $this->get('annotation');
}
/**
* @return Async
* @throws
*/
public function getAsync(): Async
{
return $this->get('async');
}
/**
* @param $array
*/
private function setComponents($array): void
{
di(LocalService::class)->setComponents($array);
}
/**
* @param $id
* @param $definition
*/
public function set($id, $definition): void
{
di(LocalService::class)->set($id, $definition);
}
/**
* @param $id
* @return bool
*/
public function has($id): bool
{
return di(LocalService::class)->has($id);
}
/**
* @throws Exception
*/
protected function moreComponents(): void
{
$this->setComponents([
'error' => ['class' => ErrorHandler::class],
'config' => ['class' => Config::class],
'logger' => ['class' => Logger::class],
'annotation' => ['class' => SAnnotation::class],
'databases' => ['class' => Connection::class],
'jwt' => ['class' => Jwt::class],
'async' => ['class' => Async::class],
'kafka-container' => ['class' => KafkaProvider::class],
]);
}
}
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/10/7 0007
* Time: 2:13
*/
declare(strict_types=1);
namespace Kiri\Abstracts;
use Database\Connection;
use Exception;
use Http\Handler\Router;
use Kafka\KafkaProvider;
use Kiri\{Async, Kiri};
use Kiri\Annotation\Annotation as SAnnotation;
use Kiri\Cache\Redis;
use Kiri\Di\LocalService;
use Kiri\Error\{ErrorHandler, Logger};
use Kiri\Exception\{InitException, NotFindClassException};
use ReflectionException;
use Server\{Contract\OnTaskInterface, Server, ServerManager, Tasker\AsyncTaskExecute};
use Swoole\Table;
/**
* Class BaseApplication
* @package Kiri\Kiri\Base
*/
abstract class BaseApplication extends Component
{
use TraitApplication;
/**
* @var string
*/
public string $storage = APP_PATH . 'storage';
public string $envPath = APP_PATH . '.env';
/**
* Init constructor.
*
*
* @throws
*/
public function __construct()
{
Kiri::init($this);
$config = sweep(APP_PATH . '/config');
$this->moreComponents();
$this->parseInt($config);
$this->parseEvents($config);
$this->initErrorHandler();
$this->enableEnvConfig();
$this->mapping($config['mapping'] ?? []);
parent::__construct();
}
/**
* @param array $mapping
*/
public function mapping(array $mapping)
{
$di = Kiri::getDi();
foreach ($mapping as $interface => $class) {
$di->mapping($interface, $class);
}
}
/**
* @return array
*/
public function enableEnvConfig(): array
{
if (!file_exists($this->envPath)) {
return [];
}
$lines = $this->readLinesFromFile($this->envPath);
foreach ($lines as $line) {
if (!$this->isComment($line) && $this->looksLikeSetter($line)) {
[$key, $value] = explode('=', $line);
putenv(trim($key) . '=' . trim($value));
}
}
return $lines;
}
/**
* Read lines from the file, auto detecting line endings.
*
* @param string $filePath
*
* @return array
*/
protected function readLinesFromFile(string $filePath): array
{
// Read file into an array of lines with auto-detected line endings
$autodetect = ini_get('auto_detect_line_endings');
ini_set('auto_detect_line_endings', '1');
$lines = file($filePath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
ini_set('auto_detect_line_endings', $autodetect);
return $lines;
}
/**
* Determine if the line in the file is a comment, e.g. begins with a #.
*
* @param string $line
*
* @return bool
*/
protected function isComment(string $line): bool
{
$line = ltrim($line);
return isset($line[0]) && $line[0] === '#';
}
/**
* Determine if the given line looks like it's setting a variable.
*
* @param string $line
*
* @return bool
*/
protected function looksLikeSetter(string $line): bool
{
return str_contains($line, '=');
}
/**
* @param $config
*
* @throws
*/
public function parseInt($config)
{
Config::sets($config);
if ($storage = Config::get('storage', 'storage')) {
if (!str_contains($storage, APP_PATH)) {
$storage = APP_PATH . $storage . '/';
}
if (!is_dir($storage)) {
mkdir($storage);
}
if (!is_dir($storage) || !is_writeable($storage)) {
throw new InitException("Directory {$storage} does not have write permission");
}
}
}
/**
* @param $name
* @return mixed
* @throws ReflectionException
* @throws NotFindClassException
* @throws Exception
*/
public function __get($name): mixed
{
if ($this->has($name)) {
return $this->get($name);
}
return parent::__get($name); // TODO: Change the autogenerated stub
}
/**
* @param $config
*
* @throws
*/
public function parseEvents($config)
{
if (!isset($config['events']) || !is_array($config['events'])) {
return;
}
foreach ($config['events'] as $key => $value) {
if (is_string($value)) {
$value = Kiri::createObject($value);
}
$this->addEvent($key, $value);
}
}
/**
* @param OnTaskInterface $execute
* @throws ReflectionException
*/
public function task(OnTaskInterface $execute): void
{
di(AsyncTaskExecute::class)->execute($execute);
}
/**
* @param $key
* @param $value
* @throws InitException
* @throws Exception
*/
private function addEvent($key, $value): void
{
if ($value instanceof \Closure || is_object($value)) {
$this->eventProvider->on($key, $value, 0);
return;
}
if (is_array($value)) {
if (is_object($value[0]) && !($value[0] instanceof \Closure)) {
$this->eventProvider->on($key, $value, 0);
return;
}
if (is_string($value[0])) {
$value[0] = Kiri::createObject($value[0]);
$this->eventProvider->on($key, $value, 0);
return;
}
foreach ($value as $item) {
if (!is_callable($item, true)) {
throw new InitException("Class does not hav callback.");
}
$this->eventProvider->on($key, $item, 0);
}
}
}
/**
* @param $name
* @return mixed
* @throws Exception
*/
public function clone($name): mixed
{
return clone $this->get($name);
}
/**
*
* @throws Exception
*/
public function initErrorHandler()
{
$this->get('error')->register();
}
/**
* @param $name
* @return mixed
* @throws
*/
public function get($name): mixed
{
return di(LocalService::class)->get($name);
}
/**
* @return mixed
*/
public function getLocalIps(): mixed
{
return swoole_get_local_ip();
}
/**
* @return mixed
*/
public function getFirstLocal(): mixed
{
return current($this->getLocalIps());
}
/**
* @return Logger
* @throws
*/
public function getLogger(): Logger
{
return $this->get('logger');
}
/**
* @return \Redis|Redis
* @throws
*/
public function getRedis(): Redis|\Redis
{
return Kiri::getDi()->get(Redis::class);
}
/**
* @param $ip
* @return bool
*/
public function isLocal($ip): bool
{
return $this->getFirstLocal() == $ip;
}
/**
* @return ErrorHandler
* @throws
*/
public function getError(): ErrorHandler
{
return $this->get('error');
}
/**
* @param $name
* @return Table
* @throws
*/
public function getTable($name): Table
{
return $this->get($name);
}
/**
* @return Config
* @throws
*/
public function getConfig(): Config
{
return $this->get('config');
}
/**
* @return Router
* @throws
*/
public function getRouter(): Router
{
return Kiri::getDi()->get(Router::class);
}
/**
* @return Server
* @throws
*/
public function getServer(): Server
{
return $this->get('server');
}
/**
* @return \Swoole\Http\Server|\Swoole\Server|\Swoole\WebSocket\Server|null
* @throws
*/
public function getSwoole(): \Swoole\Http\Server|\Swoole\Server|\Swoole\WebSocket\Server|null
{
return di(ServerManager::class)->getServer();
}
/**
* @return SAnnotation
* @throws
*/
public function getAnnotation(): SAnnotation
{
return $this->get('Annotation');
}
/**
* @return Async
* @throws
*/
public function getAsync(): Async
{
return $this->get('async');
}
/**
* @param $array
*/
private function setComponents($array): void
{
di(LocalService::class)->setComponents($array);
}
/**
* @param $id
* @param $definition
*/
public function set($id, $definition): void
{
di(LocalService::class)->set($id, $definition);
}
/**
* @param $id
* @return bool
*/
public function has($id): bool
{
return di(LocalService::class)->has($id);
}
/**
* @throws Exception
*/
protected function moreComponents(): void
{
$this->setComponents([
'error' => ['class' => ErrorHandler::class],
'config' => ['class' => Config::class],
'logger' => ['class' => Logger::class],
'Annotation' => ['class' => SAnnotation::class],
'databases' => ['class' => Connection::class],
'jwt' => ['class' => Jwt::class],
'async' => ['class' => Async::class],
'kafka-container' => ['class' => KafkaProvider::class],
]);
}
}
+13 -13
View File
@@ -1,13 +1,13 @@
<?php
declare(strict_types=1);
namespace Kiri\Abstracts;
use Swoole\Coroutine;
abstract class BaseContext
{
protected static array $pool = [];
}
<?php
declare(strict_types=1);
namespace Kiri\Abstracts;
use Swoole\Coroutine;
abstract class BaseContext
{
protected static array $pool = [];
}
+28 -28
View File
@@ -1,28 +1,28 @@
<?php
declare(strict_types=1);
namespace Kiri\Abstracts;
use Exception;
use Kiri\Core\Json;
/**
* Class BaseGoto
* @package Kiri\Abstracts
*/
class BaseGoto extends Component
{
/**
* @param string $message
* @param int $statusCode
* @return mixed
* @throws Exception
*/
public function end(string $message, int $statusCode = 200): mixed
{
throw new Exception(Json::to(12350, $message), $statusCode);
}
}
<?php
declare(strict_types=1);
namespace Kiri\Abstracts;
use Exception;
use Kiri\Core\Json;
/**
* Class BaseGoto
* @package Kiri\Abstracts
*/
class BaseGoto extends Component
{
/**
* @param string $message
* @param int $statusCode
* @return mixed
* @throws Exception
*/
public function end(string $message, int $statusCode = 200): mixed
{
throw new Exception(Json::to(12350, $message), $statusCode);
}
}
-243
View File
@@ -1,243 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/3/30 0030
* Time: 14:10
*/
declare(strict_types=1);
namespace Kiri\Abstracts;
use Exception;
use JetBrains\PhpStorm\Pure;
use Kiri\Kiri;
use Swoole\Coroutine;
/**
* Class BaseObject
* @package Kiri\Kiri\Base
*/
class BaseObject implements Configure
{
/**
* BaseAbstract constructor.
*
* @param array $config
* @throws Exception
*/
public function __construct(array $config = [])
{
if (!empty($config) && is_array($config)) {
Kiri::configure($this, $config);
}
}
/**
* @throws Exception
*/
public function init()
{
}
/**
* @param array|callable $callback
* @param object $scope
*/
public function async_create(array|callable $callback, object $scope)
{
Coroutine::create($callback, $scope);
}
/**
* @return string
*/
#[Pure] public static function className(): string
{
return static::class;
}
/**
* @param $name
* @param $value
*
* @throws Exception
*/
public function __set($name, $value)
{
$method = 'set' . ucfirst($name);
if (method_exists($this, $method)) {
$this->{$method}($value);
} else {
throw new Exception('The set name ' . $name . ' not find in class ' . static::class);
}
}
/**
* @param $name
*
* @return mixed
* @throws Exception
*/
public function __get($name): mixed
{
$method = 'get' . ucfirst($name);
if (method_exists($this, $method)) {
return $this->$method();
} else {
throw new Exception('The get name ' . $name . ' not find in class ' . static::class);
}
}
/**
* @param $message
* @param string $model
* @return bool
* @throws Exception
*/
public function addError($message, string $model = 'app'): bool
{
if ($message instanceof \Throwable) {
$this->error(jTraceEx($message));
} else {
if (!is_string($message)) {
$message = json_encode($message, JSON_UNESCAPED_UNICODE);
}
$this->error($message);
}
return FALSE;
}
/**
* @return Logger
* @throws Exception
*/
private function logger(): Logger
{
return Kiri::getDi()->get(Logger::class);
}
/**
* @param mixed $message
* @param string $method
* @param string $file
* @throws Exception
*/
public function debug(mixed $message, string $method = '', string $file = '')
{
if (!is_string($message)) {
$message = print_r($message, true);
}
$message = "\033[35m" . $message . "\033[0m";
$context = [];
if (!empty($method)) $context['method'] = $method;
if (!empty($file)) $context['file'] = $file;
$this->logger()->debug($message, $context);
}
/**
* @param mixed $message
* @param string $method
* @param string $file
* @throws Exception
*/
public function info(mixed $message, string $method = '', string $file = '')
{
if (!is_string($message)) {
$message = print_r($message, true);
}
$message = "\033[34m" . $message . "\033[0m";
$context = [];
if (!empty($method)) $context['method'] = $method;
if (!empty($file)) $context['file'] = $file;
$this->logger()->info($message, $context);
}
/**
* @param mixed $message
* @param string $method
* @param string $file
* @throws Exception
*/
public function success(mixed $message, string $method = '', string $file = '')
{
if (!is_string($message)) {
$message = print_r($message, true);
}
$message = "\033[36m" . $message . "\033[0m";
$context = [];
if (!empty($method)) $context['method'] = $method;
if (!empty($file)) $context['file'] = $file;
$this->logger()->notice($message, $context);
}
/**
* @param mixed $message
* @param string $method
* @param string $file
* @throws Exception
*/
public function warning(mixed $message, string $method = '', string $file = '')
{
if (!is_string($message)) {
$message = print_r($message, true);
}
$message = "\033[33m" . $message . "\033[0m";
$context = [];
if (!empty($method)) $context['method'] = $method;
if (!empty($file)) $context['file'] = $file;
$this->logger()->critical($message, $context);
}
/**
* @param mixed $message
* @param null $method
* @param null $file
* @throws Exception
*/
public function error(mixed $message, $method = null, $file = null)
{
if ($message instanceof \Throwable) {
$message = $message->getMessage() . " on line " . $message->getLine() . " at file " . $message->getFile();
}
$content = (empty($method) ? '' : $method . ': ') . $message;
$message = "\033[41;37m" . $content . "\033[0m";
if (!empty($file)) {
$message .= PHP_EOL . "\03341;37m[" . $file . "\033[0m";
}
$context = [];
if (!empty($method)) $context['method'] = $method;
if (!empty($file)) $context['file'] = $file;
$this->logger()->error($message, $context);
}
}
+10 -10
View File
@@ -1,10 +1,10 @@
<?php
declare(strict_types=1);
namespace Kiri\Abstracts;
abstract class Command extends Component
{
}
<?php
declare(strict_types=1);
namespace Kiri\Abstracts;
abstract class Command extends Component
{
}
+260 -55
View File
@@ -1,55 +1,260 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/3/30 0030
* Time: 14:28
*/
declare(strict_types=1);
namespace Kiri\Abstracts;
use Exception;
use JetBrains\PhpStorm\Pure;
use Kiri\Exception\ComponentException;
use Kiri\Kiri;
/**
* Class Component
* @package Kiri\Kiri\Base
*/
class Component extends BaseObject
{
/**
* @param $name
* @param $value
* @throws Exception
*/
public function __set($name, $value)
{
if (property_exists($this, $name)) {
$this->$name = $value;
} else {
parent::__set($name, $value);
}
}
/**
* @param $name
* @return mixed
* @throws Exception
*/
public function __get($name): mixed
{
if (property_exists($this, $name)) {
return $this->$name ?? null;
} else {
return parent::__get($name);
}
}
}
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/3/30 0030
* Time: 14:28
*/
declare(strict_types=1);
namespace Kiri\Abstracts;
use Exception;
use JetBrains\PhpStorm\Pure;
use Kiri\Di\Container;
use Kiri\Events\EventDispatch;
use Kiri\Events\EventProvider;
use Kiri\Kiri;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
/**
* Class Component
* @package Kiri\Kiri\Base
* @property ContainerInterface|Container $container
* @property EventProvider $eventProvider
* @property EventDispatch $eventDispatch
*/
class Component implements Configure
{
/**
* BaseAbstract constructor.
*
* @param array $config
* @throws Exception
*/
public function __construct(array $config = [])
{
if (!empty($config) && is_array($config)) {
Kiri::configure($this, $config);
}
}
/**
* @return Container|ContainerInterface
*/
#[Pure] public function getContainer(): ContainerInterface|Container
{
return Kiri::getDi();
}
/**
* @return EventProvider
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function getEventProvider(): EventProvider
{
return $this->getContainer()->get(EventProvider::class);
}
/**
* @return EventDispatch
*/
protected function getEventDispatch(): EventDispatch
{
return Kiri::getDi()->get(EventDispatch::class);
}
/**
* @throws Exception
*/
public function init()
{
}
/**
* @return string
*/
#[Pure] public static function className(): string
{
return static::class;
}
/**
* @param $name
* @param $value
*
* @throws Exception
*/
public function __set($name, $value)
{
$method = 'set' . ucfirst($name);
if (method_exists($this, $method)) {
$this->{$method}($value);
} else {
throw new Exception('The set name ' . $name . ' not find in class ' . static::class);
}
}
/**
* @param $name
*
* @return mixed
* @throws Exception
*/
public function __get($name): mixed
{
$method = 'get' . ucfirst($name);
if (method_exists($this, $method)) {
return $this->$method();
} else {
throw new Exception('The get name ' . $name . ' not find in class ' . static::class);
}
}
/**
* @param $message
* @param string $model
* @return bool
* @throws Exception
*/
public function addError($message, string $model = 'app'): bool
{
if ($message instanceof \Throwable) {
$this->error($message = jTraceEx($message));
} else {
if (!is_string($message)) {
$message = json_encode($message, JSON_UNESCAPED_UNICODE);
}
$this->error($message);
}
Kiri::app()->getLogger()->fail($message, $model);
return FALSE;
}
/**
* @return Logger
* @throws Exception
*/
private function logger(): Logger
{
return Kiri::getDi()->get(Logger::class);
}
/**
* @param mixed $message
* @param string $method
* @param string $file
* @throws Exception
*/
public function debug(mixed $message, string $method = '', string $file = '')
{
if (!is_string($message)) {
$message = print_r($message, true);
}
$context = [];
if (!empty($method)) $context['method'] = $method;
if (!empty($file)) $context['file'] = $file;
$this->logger()->debug($message, $context);
}
/**
* @param mixed $message
* @param string $method
* @param string $file
* @throws Exception
*/
public function info(mixed $message, string $method = '', string $file = '')
{
if (!is_string($message)) {
$message = print_r($message, true);
}
$context = [];
if (!empty($method)) $context['method'] = $method;
if (!empty($file)) $context['file'] = $file;
$this->logger()->info($message, $context);
}
/**
* @param mixed $message
* @param string $method
* @param string $file
* @throws Exception
*/
public function success(mixed $message, string $method = '', string $file = '')
{
if (!is_string($message)) {
$message = print_r($message, true);
}
$context = [];
if (!empty($method)) $context['method'] = $method;
if (!empty($file)) $context['file'] = $file;
$this->logger()->notice($message, $context);
}
/**
* @param mixed $message
* @param string $method
* @param string $file
* @throws Exception
*/
public function warning(mixed $message, string $method = '', string $file = '')
{
if (!is_string($message)) {
$message = print_r($message, true);
}
$context = [];
if (!empty($method)) $context['method'] = $method;
if (!empty($file)) $context['file'] = $file;
$this->logger()->critical($message, $context);
}
/**
* @param mixed $message
* @param null $method
* @param null $file
* @throws Exception
*/
public function error(mixed $message, $method = null, $file = null)
{
if ($message instanceof \Throwable) {
$message = $message->getMessage() . " on line " . $message->getLine() . " at file " . $message->getFile();
}
$context = [];
if (is_string($method)) {
$message = (empty($method) ? '' : $method . ': ') . $message;
} else {
if (is_null($method)) {
$method = [];
}
$context = $method;
}
if (!empty($method)) $context['method'] = $method;
if (!empty($file)) $context['file'] = $file;
$this->logger()->error($message, $context);
}
}
+128 -124
View File
@@ -1,124 +1,128 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/5/24 0024
* Time: 11:50
*/
declare(strict_types=1);
namespace Kiri\Abstracts;
use Exception;
use Kiri\Exception\ConfigException;
use Kiri\Kiri;
/**
* Class Config
* @package Kiri\Kiri\Base
*/
class Config extends Component
{
const ERROR_MESSAGE = 'The not find %s in app configs.';
protected mixed $data = [];
/**
* @return mixed
*/
public function getData(): mixed
{
return $this->data;
}
/**
* @param $key
* @param $value
* @return mixed
*/
public function setData($key, $value): mixed
{
return $this->data[$key] = $value;
}
/**
* @param array $configs
* @throws Exception
*/
public static function sets(array $configs)
{
$config = Kiri::app()->getConfig();
if (empty($configs)) {
return;
}
$config->data = $configs;
}
/**
* @param $key
* @param bool $try
* @param mixed|null $default
* @return mixed
* @throws
*/
public static function get($key, mixed $default = null, bool $try = FALSE): mixed
{
$instance = Kiri::app()->getConfig()->getData();
if (!str_contains($key, '.')) {
return $instance[$key] ?? $default;
}
foreach (explode('.', $key) as $value) {
if (empty($value)) {
continue;
}
if (!isset($instance[$value])) {
if ($try) {
throw new ConfigException(sprintf(self::ERROR_MESSAGE, $key));
}
return $default;
}
if (!is_array($instance[$value])) {
return $instance[$value];
}
$instance = $instance[$value];
}
return empty($instance) ? $default : $instance;
}
/**
* @param $key
* @param $value
* @return mixed
* @throws Exception
*/
public static function set($key, $value): mixed
{
$config = Kiri::app()->getConfig();
return $config->setData($key, $value);
}
/**
* @param $key
* @param bool $must_not_null
* @return bool
* @throws Exception
*/
public static function has($key, bool $must_not_null = false): bool
{
$config = Kiri::app()->getConfig();
if (!isset($config->data[$key])) {
return false;
}
$config = $config->data[$key];
if ($must_not_null === false) {
return true;
}
return !empty($config);
}
}
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/5/24 0024
* Time: 11:50
*/
declare(strict_types=1);
namespace Kiri\Abstracts;
use Kiri\Exception\ConfigException;
/**
* Class Config
* @package Kiri\Kiri\Base
*/
class Config extends Component
{
const ERROR_MESSAGE = 'The not find %s in app configs.';
protected static mixed $data = [];
/**
* @return mixed
*/
public static function getData(): mixed
{
return static::$data;
}
/**
* @param $key
* @param $value
* @return mixed
*/
public static function setData($key, $value): mixed
{
return static::$data[$key] = $value;
}
/**
* @param array $configs
*/
public static function sets(array $configs)
{
if (empty($configs)) {
return;
}
static::$data = $configs;
}
/**
* @param $key
* @param bool $try
* @param mixed|null $default
* @return mixed
* @throws ConfigException
*/
public static function get($key, mixed $default = null, bool $try = FALSE): mixed
{
$instance = static::$data;
if (!str_contains($key, '.')) {
return $instance[$key] ?? $default;
}
foreach (explode('.', $key) as $value) {
if (empty($value)) {
continue;
}
if (!isset($instance[$value])) {
if ($try) {
throw new ConfigException(sprintf(self::ERROR_MESSAGE, $key));
}
return $default;
}
if (!is_array($instance[$value])) {
return $instance[$value];
}
$instance = $instance[$value];
}
return empty($instance) ? $default : $instance;
}
/**
* @param $key
* @param $value
* @return mixed
*/
public static function set($key, $value): mixed
{
$explode = explode('.', $key);
$parent = &static::$data;
foreach ($explode as $item) {
if (!isset($parent[$item])) {
$parent[$item] = [];
}
$parent = &$parent[$item];
}
$parent = $value;
unset($parent);
return static::$data;
}
/**
* @param $key
* @param bool $must_not_null
* @return bool
*/
public static function has($key, bool $must_not_null = false): bool
{
if (!isset(static::$data[$key])) {
return false;
}
$config = static::$data[$key];
if ($must_not_null === false) {
return true;
}
return !empty($config);
}
}
+18 -18
View File
@@ -1,18 +1,18 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/3/30 0030
* Time: 14:11
*/
declare(strict_types=1);
namespace Kiri\Abstracts;
/**
* Interface Configure
* @package Kiri\Kiri\Base
*/
interface Configure
{
}
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/3/30 0030
* Time: 14:11
*/
declare(strict_types=1);
namespace Kiri\Abstracts;
/**
* Interface Configure
* @package Kiri\Kiri\Base
*/
interface Configure
{
}
+26 -26
View File
@@ -1,26 +1,26 @@
<?php
declare(strict_types=1);
namespace Kiri\Abstracts;
use Kiri\Core\Dtl;
/**
* Interface IListener
* @package Kiri\Abstracts
*/
interface IListener
{
/**
* @param Dtl $dtl
* @return mixed
*/
public function execute(Dtl $dtl): mixed;
}
<?php
declare(strict_types=1);
namespace Kiri\Abstracts;
use Kiri\Core\Dtl;
/**
* Interface IListener
* @package Kiri\Abstracts
*/
interface IListener
{
/**
* @param Dtl $dtl
* @return mixed
*/
public function execute(Dtl $dtl): mixed;
}
+111 -111
View File
@@ -1,111 +1,111 @@
<?php
declare(strict_types=1);
namespace Kiri\Abstracts;
use Exception;
class Input
{
private array $_argv = [];
private string $_command = '';
/**
* Input constructor.
* @param $argv
* @throws
*/
public function __construct($argv)
{
$this->_argv = $this->resolve($argv);
}
/**
* @return string
*/
public function getCommandName(): string
{
return $this->_command;
}
/**
* @param $key
* @param null $default
* @return mixed
*/
public function get($key, $default = null): mixed
{
return $this->_argv[$key] ?? $default;
}
/**
* @param $key
* @return bool
*/
public function exists($key): bool
{
return isset($this->_argv[$key]);
}
/**
* @param $key
* @param $value
* @return $this
*/
public function set($key, $value): static
{
$this->_argv[$key] = $value;
return $this;
}
/**
* @return false|string
*/
public function toJson(): bool|string
{
return json_encode($this->_argv, JSON_UNESCAPED_UNICODE);
}
/**
* @param $parameters
* @return array
* @throws Exception
*/
public function resolve($parameters): array
{
$arrays = [];
$parameters = array_slice($parameters, 1);
if (empty($parameters)) {
return $arrays;
}
$this->_command = array_shift($parameters);
foreach ($parameters as $parameter) {
$explode = explode('=', $parameter);
if (count($explode) < 2) {
continue;
}
$arrays[array_shift($explode)] = current($explode);
}
return $arrays;
}
/**
* @return string
*/
public function getCommand(): string
{
return $this->_command;
}
}
<?php
declare(strict_types=1);
namespace Kiri\Abstracts;
use Exception;
class Input
{
private array $_argv = [];
private string $_command = '';
/**
* Input constructor.
* @param $argv
* @throws
*/
public function __construct($argv)
{
$this->_argv = $this->resolve($argv);
}
/**
* @return string
*/
public function getCommandName(): string
{
return $this->_command;
}
/**
* @param $key
* @param null $default
* @return mixed
*/
public function get($key, $default = null): mixed
{
return $this->_argv[$key] ?? $default;
}
/**
* @param $key
* @return bool
*/
public function exists($key): bool
{
return isset($this->_argv[$key]);
}
/**
* @param $key
* @param $value
* @return $this
*/
public function set($key, $value): static
{
$this->_argv[$key] = $value;
return $this;
}
/**
* @return false|string
*/
public function toJson(): bool|string
{
return json_encode($this->_argv, JSON_UNESCAPED_UNICODE);
}
/**
* @param $parameters
* @return array
* @throws Exception
*/
public function resolve($parameters): array
{
$arrays = [];
$parameters = array_slice($parameters, 1);
if (empty($parameters)) {
return $arrays;
}
$this->_command = array_shift($parameters);
foreach ($parameters as $parameter) {
$explode = explode('=', $parameter);
if (count($explode) < 2) {
continue;
}
$arrays[array_shift($explode)] = current($explode);
}
return $arrays;
}
/**
* @return string
*/
public function getCommand(): string
{
return $this->_command;
}
}
+15 -15
View File
@@ -1,15 +1,15 @@
<?php
namespace Kiri\Abstracts;
interface Kernel
{
/**
* @return array
*/
public function getCommands(): array;
}
<?php
namespace Kiri\Abstracts;
interface Kernel
{
/**
* @return array
*/
public function getCommands(): array;
}
+18 -18
View File
@@ -1,18 +1,18 @@
<?php
declare(strict_types=1);
namespace Kiri\Abstracts;
use Exception;
/**
* Class Listener
* @package Kiri\Abstracts
* 监听的名称
*/
abstract class Listener extends Component implements IListener
{
}
<?php
declare(strict_types=1);
namespace Kiri\Abstracts;
use Exception;
/**
* Class Listener
* @package Kiri\Abstracts
* 监听的名称
*/
abstract class Listener extends Component implements IListener
{
}
+229 -201
View File
@@ -1,201 +1,229 @@
<?php
namespace Kiri\Abstracts;
use Annotation\Inject;
use Exception;
use Kiri\Events\EventProvider;
use Kiri\Exception\ConfigException;
use Psr\Log\LoggerInterface;
use Server\Events\OnWorkerStop;
/**
*
*/
class Logger implements LoggerInterface
{
const EMERGENCY = 'emergency';
const ALERT = 'alert';
const CRITICAL = 'critical';
const ERROR = 'error';
const WARNING = 'warning';
const NOTICE = 'notice';
const INFO = 'info';
const DEBUG = 'debug';
/**
* @var EventProvider
*/
#[Inject(EventProvider::class)]
public EventProvider $eventProvider;
private array $_loggers = [];
const LOGGER_LEVELS = [Logger::EMERGENCY, Logger::ALERT, Logger::CRITICAL, Logger::ERROR, Logger::WARNING, Logger::NOTICE, Logger::INFO, Logger::DEBUG];
/**
* 监听事件
*/
public function init()
{
$this->eventProvider->on(OnWorkerStop::class, [$this, 'onAfterRequest']);
}
/**
* @param string $message
* @param array $context
* @throws ConfigException
*
* 紧急情况
*/
public function emergency($message, array $context = [])
{
// TODO: Implement emergency() method.
$this->log(Logger::EMERGENCY, $message, $context);
}
/**
* @param string $message
* @param array $context
* @throws ConfigException
*
* 应该警惕的
*/
public function alert($message, array $context = [])
{
// TODO: Implement alert() method.
$this->log(Logger::ALERT, $message, $context);
}
/**
* @param string $message
* @param array $context
* @throws ConfigException
*
* 关键性的日志
*/
public function critical($message, array $context = [])
{
// TODO: Implement critical() method.
$this->log(Logger::CRITICAL, $message, $context);
}
/**
* @param string $message
* @param array $context
* @throws ConfigException
*/
public function error($message, array $context = [])
{
// TODO: Implement error() method.
$this->log(Logger::ERROR, $message, $context);
}
/**
* @param string $message
* @param array $context
* @throws ConfigException
*/
public function warning($message, array $context = [])
{
// TODO: Implement warning() method.
$this->log(Logger::WARNING, $message, $context);
}
/**
* @param string $message
* @param array $context
* @throws ConfigException
*/
public function notice($message, array $context = [])
{
// TODO: Implement notice() method.
$this->log(Logger::NOTICE, $message, $context);
}
/**
* @param string $message
* @param array $context
* @throws ConfigException
*/
public function info($message, array $context = [])
{
// TODO: Implement info() method.
$this->log(Logger::INFO, $message, $context);
}
/**
* @param string $message
* @param array $context
* @throws ConfigException
*/
public function debug($message, array $context = [])
{
// TODO: Implement debug() method.
$this->log(Logger::DEBUG, $message, $context);
}
/**
* @param mixed $level
* @param string $message
* @param array $context
* @throws ConfigException
*/
public function log($level, $message, array $context = [])
{
// TODO: Implement log() method.
$levels = Config::get('log.level', Logger::LOGGER_LEVELS);
if (!in_array($level, $levels)) {
return;
}
$_string = '[' . now() . '] production.' . $level . ': ' . $this->_string($message, $context);
file_put_contents('php://output', $_string);
$this->_loggers[] = $_string;
}
/**
* @param OnWorkerStop $param
* @throws Exception
*/
public function onAfterRequest(OnWorkerStop $param)
{
$loggers = implode(PHP_EOL, $this->_loggers);
$this->_loggers = [];
if (!empty($loggers)) {
$filename = storage('log-' . date('Y-m-d') . '.log', 'logs/');
file_put_contents($filename, $loggers);
}
}
/**
* @param $message
* @param $context
* @return string
*/
private function _string($message, $context): string
{
if (!empty($context)) {
return $message . ' ' . print_r($context, true) . PHP_EOL;
}
return $message . PHP_EOL;
}
}
<?php
namespace Kiri\Abstracts;
use DirectoryIterator;
use Exception;
use Kiri\Events\EventProvider;
use Kiri\Exception\ConfigException;
use Kiri\Kiri;
use Psr\Log\LoggerInterface;
use ReflectionException;
use Server\Events\OnWorkerStop;
/**
*
*/
class Logger implements LoggerInterface
{
const EMERGENCY = 'emergency';
const ALERT = 'alert';
const CRITICAL = 'critical';
const ERROR = 'error';
const WARNING = 'warning';
const NOTICE = 'notice';
const INFO = 'info';
const DEBUG = 'debug';
private array $_loggers = [];
const LOGGER_LEVELS = [Logger::EMERGENCY, Logger::ALERT, Logger::CRITICAL, Logger::ERROR, Logger::WARNING, Logger::NOTICE, Logger::INFO, Logger::DEBUG];
/**
* @return void
* @throws ReflectionException
*/
public function init()
{
Kiri::getDi()->get(EventProvider::class)->on(OnWorkerStop::class, [$this, 'onAfterRequest']);
}
/**
* @param string $message
* @param array $context
* @throws ConfigException
*
* 紧急情况
*/
public function emergency($message, array $context = [])
{
// TODO: Implement emergency() method.
$this->log(Logger::EMERGENCY, $message, $context);
}
/**
* @param string $message
* @param array $context
* @throws ConfigException
*
* 应该警惕的
*/
public function alert($message, array $context = [])
{
// TODO: Implement alert() method.
$this->log(Logger::ALERT, $message, $context);
}
/**
* @param string $message
* @param array $context
* @throws ConfigException
*
* 关键性的日志
*/
public function critical($message, array $context = [])
{
// TODO: Implement critical() method.
$this->log(Logger::CRITICAL, $message, $context);
}
/**
* @param string $message
* @param array $context
* @throws ConfigException
*/
public function error($message, array $context = [])
{
// TODO: Implement error() method.
$this->log(Logger::ERROR, $message, $context);
}
/**
* @param string $message
* @param array $context
* @throws ConfigException
*/
public function warning($message, array $context = [])
{
// TODO: Implement warning() method.
$this->log(Logger::WARNING, $message, $context);
}
/**
* @param string $message
* @param array $context
* @throws ConfigException
*/
public function notice($message, array $context = [])
{
// TODO: Implement notice() method.
$this->log(Logger::NOTICE, $message, $context);
}
/**
* @param string $message
* @param array $context
* @throws ConfigException
*/
public function info($message, array $context = [])
{
// TODO: Implement info() method.
$this->log(Logger::INFO, $message, $context);
}
/**
* @param string $message
* @param array $context
* @throws ConfigException
*/
public function debug($message, array $context = [])
{
// TODO: Implement debug() method.
$this->log(Logger::DEBUG, $message, $context);
}
/**
* @param mixed $level
* @param string $message
* @param array $context
* @throws ConfigException
*/
public function log($level, $message, array $context = [])
{
// TODO: Implement log() method.
$levels = Config::get('log.level', Logger::LOGGER_LEVELS);
if (!in_array($level, $levels) || str_contains($message, 'Event::rshutdown')) {
return;
}
$_string = '[' . now() . '] production.' . $level . ': ' . $this->_string($message, $context);
file_put_contents('php://output', $_string);
$this->_loggers[] = $_string;
}
/**
* @param OnWorkerStop $param
* @throws Exception
*/
public function onAfterRequest(OnWorkerStop $param)
{
$loggers = implode(PHP_EOL, $this->_loggers);
$this->_loggers = [];
if (!empty($loggers)) {
$filename = storage('log-' . date('Y-m-d') . '.log', 'log/');
file_put_contents($filename, $loggers);
}
}
/**
* @return void
* @throws Exception
*/
public function flush()
{
$this->removeFile(storage());
}
/**
* @param string $dirname
* @return void
*/
private function removeFile(string $dirname)
{
$paths = new DirectoryIterator($dirname);
/** @var DirectoryIterator $path */
foreach ($paths as $path) {
if ($path->isDot() || str_starts_with($path->getFilename(), '.')) {
continue;
}
if ($path->isDir()) {
$directory = rtrim($path->getRealPath(), '/');
$this->removeFile($directory);
}
@unlink($path->getRealPath());
}
}
/**
* @param $message
* @param $context
* @return string
*/
private function _string($message, $context): string
{
if (!empty($context)) {
return $message . ' ' . PHP_EOL . print_r($context, TRUE) . PHP_EOL;
}
return $message . PHP_EOL;
}
}
+14 -14
View File
@@ -1,14 +1,14 @@
<?php
declare(strict_types=1);
namespace Kiri\Abstracts;
use Kiri\Application;
interface Provider
{
public function onImport(Application $application);
}
<?php
declare(strict_types=1);
namespace Kiri\Abstracts;
use Kiri\Application;
interface Provider
{
public function onImport(Application $application);
}
+15 -15
View File
@@ -1,15 +1,15 @@
<?php
declare(strict_types=1);
namespace Kiri\Abstracts;
/**
* Class Providers
* @package Kiri\Abstracts
*/
abstract class Providers extends Component implements Provider
{
}
<?php
declare(strict_types=1);
namespace Kiri\Abstracts;
/**
* Class Providers
* @package Kiri\Abstracts
*/
abstract class Providers extends Component implements Provider
{
}
+32 -37
View File
@@ -1,37 +1,32 @@
<?php
namespace Kiri\Abstracts;
use Annotation\Annotation as SAnnotation;
use Database\Connection;
use Database\DatabasesProviders;
use Http\Handler\Client\Client;
use Http\Handler\Client\Curl;
use Http\Handler\Router;
use Server\Server;
use Kiri\Crontab\Producer;
use Kiri\Async;
use Kiri\Error\Logger;
use Kiri\Jwt\JWTAuth;
/**
* Trait TraitApplication
* @package Kiri\Abstracts
* @property Router $router
* @property Server $server
* @property DatabasesProviders $db
* @property Async $async
* @property Logger $logger
* @property JWTAuth $jwt
* @property SAnnotation $annotation
* @property BaseGoto $goto
* @property Client $client
* @property Connection $databases
* @property Curl $curl
*/
trait TraitApplication
{
}
<?php
namespace Kiri\Abstracts;
use Kiri\Annotation\Annotation as SAnnotation;
use Database\Connection;
use Database\DatabasesProviders;
use Http\Handler\Router;
use Server\Server;
use Kiri\Async;
use Kiri\Error\Logger;
use Kiri\Jwt\JWTAuth;
/**
* Trait TraitApplication
* @package Kiri\Abstracts
* @property Router $router
* @property Server $server
* @property DatabasesProviders $db
* @property Async $async
* @property Logger $logger
* @property JWTAuth $jwt
* @property SAnnotation $annotation
* @property BaseGoto $goto
* @property Connection $databases
*/
trait TraitApplication
{
}
+253 -256
View File
@@ -1,256 +1,253 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/4/25 0025
* Time: 18:38
*/
declare(strict_types=1);
namespace Kiri;
use Closure;
use Database\DatabasesProviders;
use Exception;
use Kiri\Abstracts\BaseApplication;
use Kiri\Abstracts\Config;
use Kiri\Abstracts\Kernel;
use Kiri\Crontab\CrontabProviders;
use Kiri\Events\OnAfterCommandExecute;
use Kiri\Events\OnBeforeCommandExecute;
use Kiri\Exception\NotFindClassException;
use Kiri\FileListen\HotReload;
use ReflectionException;
use Server\ServerProviders;
use stdClass;
use Swoole\Process;
use Swoole\Timer;
use Symfony\Component\Console\Application as ConsoleApplication;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\ConsoleOutput;
/**
* Class Init
*
* @package Kiri
*
* @property-read Config $config
*/
class Application extends BaseApplication
{
/**
* @var string
*/
public string $id = 'uniqueId';
public string $state = '';
/** @var array<array<Process>> */
private array $_process = [];
/**
*/
public function init()
{
$this->import(ServerProviders::class);
$this->register(Runtime::class);
}
/**
* @throws
*/
public function withDatabase()
{
$this->import(DatabasesProviders::class);
}
/**
* @throws
*/
public function withCrontab()
{
$this->import(CrontabProviders::class);
}
/**
* @param string $class
* @param Process $process
*/
public function addProcess(string $class, Process $process)
{
}
/**
* @return Process[]
*/
public function getProcess(): array
{
return $this->_process;
}
/**
* @param string $class
* @return Process|null
*/
public function getProcessName(string $class): ?Process
{
return $this->_process[$class] ?? null;
}
/**
* @throws
*/
public function withFileChangeListen()
{
$container = Kiri::getDi();
$console = $container->get(ConsoleApplication::class);
$console->add($container->get(HotReload::class));
}
/**
* @param Closure|array $closure
* @return $this
* @throws Exception
*/
public function middleware(Closure|array $closure): static
{
return $this;
}
/**
* @param bool $useTree
* @return $this
* @throws Exception
*/
public function setUseTree(bool $useTree): static
{
return $this;
}
/**
* @param string $service
* @return $this
* @throws
*/
public function import(string $service): static
{
if (!class_exists($service)) {
return $this;
}
$class = Kiri::getDi()->get($service);
if (method_exists($class, 'onImport')) {
$class->onImport($this);
}
return $this;
}
/**
* @param Kernel $kernel
* @return $this
*/
public function commands(Kernel $kernel): static
{
foreach ($kernel->getCommands() as $command) {
$this->register($command);
}
return $this;
}
/**
* @param string $command
* @throws
*/
public function register(string $command)
{
di(ConsoleApplication::class)->add(di($command));
}
/**
* @param array $argv
* @return void
*/
public function execute(array $argv): void
{
/** @var InputInterface $input */
[$input, $output] = $this->argument($argv);
try {
$console = di(ConsoleApplication::class);
$command = $input->getFirstArgument();
if (empty($command)) {
$command = 'sw:server';
}
$command = $console->find($command);
if ($command instanceof Command) {
$this->enableFileChange($command, $input, $output);
}
} catch (\Throwable $exception) {
$output->writeln(jTraceEx($exception));
} finally {
Timer::clearAll();
}
}
/**
* @param $argv
* @return array
*/
private function argument($argv): array
{
return [new ArgvInput($argv), new ConsoleOutput()];
}
/**
* @throws NotFindClassException
* @throws ReflectionException
* @throws Exception
*/
private function enableFileChange(Command $class, $input, $output): void
{
fire(new OnBeforeCommandExecute());
if (!($class instanceof HotReload)) {
scan_directory(directory('app'), 'App');
}
$class->run($input, $output);
fire(new OnAfterCommandExecute());
$output->writeln('ok' . PHP_EOL);
}
/**
* @param $className
* @param null $abstracts
* @return stdClass
* @throws Exception
*/
public function make($className, $abstracts = null): stdClass
{
return make($className, $abstracts);
}
}
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/4/25 0025
* Time: 18:38
*/
declare(strict_types=1);
namespace Kiri;
use Closure;
use Database\DatabasesProviders;
use Exception;
use Kiri\Abstracts\{BaseApplication, Config, Kernel};
use Kiri\Crontab\CrontabProviders;
use Kiri\Events\{OnAfterCommandExecute, OnBeforeCommandExecute};
use Kiri\FileListen\HotReload;
use ReflectionException;
use Server\ServerProviders;
use stdClass;
use Swoole\Process;
use Swoole\Timer;
use Symfony\Component\Console\{Application as ConsoleApplication,
Command\Command,
Input\ArgvInput,
Input\InputInterface,
Output\ConsoleOutput,
Output\OutputInterface
};
/**
* Class Init
*
* @package Kiri
*
* @property-read Config $config
*/
class Application extends BaseApplication
{
/**
* @var string
*/
public string $id = 'uniqueId';
public string $state = '';
/** @var array<array<Process>> */
private array $_process = [];
/**
*/
public function init()
{
$this->import(ServerProviders::class);
$this->register(Runtime::class);
}
/**
* @throws
*/
public function withDatabase()
{
$this->import(DatabasesProviders::class);
}
/**
* @throws
*/
public function withCrontab()
{
$this->import(CrontabProviders::class);
}
/**
* @param string $class
* @param Process $process
*/
public function addProcess(string $class, Process $process)
{
}
/**
* @return Process[]
*/
public function getProcess(): array
{
return $this->_process;
}
/**
* @param string $class
* @return Process|null
*/
public function getProcessName(string $class): ?Process
{
return $this->_process[$class] ?? null;
}
/**
* @throws
*/
public function withFileChangeListen()
{
$container = Kiri::getDi();
$console = $container->get(ConsoleApplication::class);
$console->add($container->get(HotReload::class));
}
/**
* @param Closure|array $closure
* @return $this
* @throws Exception
*/
public function middleware(Closure|array $closure): static
{
return $this;
}
/**
* @param bool $useTree
* @return $this
* @throws Exception
*/
public function setUseTree(bool $useTree): static
{
return $this;
}
/**
* @param string $service
* @return $this
* @throws
*/
public function import(string $service): static
{
if (!class_exists($service)) {
return $this;
}
$class = Kiri::getDi()->get($service);
if (method_exists($class, 'onImport')) {
$class->onImport($this);
}
return $this;
}
/**
* @param Kernel $kernel
* @return $this
*/
public function commands(Kernel $kernel): static
{
foreach ($kernel->getCommands() as $command) {
$this->register($command);
}
return $this;
}
/**
* @param string $command
* @throws
*/
public function register(string $command)
{
di(ConsoleApplication::class)->add(di($command));
}
/**
* @param array $argv
* @return void
*/
public function execute(array $argv): void
{
ini_set('swoole.enable_preemptive_scheduler', 'On');
ini_set('swoole.enable_library', 'On');
[$input, $output] = $this->argument($argv);
try {
$console = di(ConsoleApplication::class);
$command = $input->getFirstArgument();
if (empty($command)) {
$command = 'sw:server';
}
$command = $console->find($command);
if ($command instanceof Command) {
$this->enableFileChange($command, $input, $output);
}
} catch (\Throwable $exception) {
$output->writeln(jTraceEx($exception));
} finally {
Timer::clearAll();
}
}
/**
* @param $argv
* @return array
*/
private function argument($argv): array
{
return [new ArgvInput($argv), new ConsoleOutput()];
}
/**
* @throws ReflectionException
* @throws Exception
*/
private function enableFileChange(Command $class, $input, $output): void
{
fire(new OnBeforeCommandExecute());
if (!($class instanceof HotReload)) {
scan_directory(directory('app'), 'App');
}
$this->container->setBindings(OutputInterface::class, $output);
$class->run($input, $output);
fire(new OnAfterCommandExecute());
$output->writeln('ok' . PHP_EOL);
}
/**
* @param $className
* @param null $abstracts
* @return stdClass
* @throws Exception
*/
public function make($className, $abstracts = null): stdClass
{
return make($className, $abstracts);
}
}
+44 -43
View File
@@ -1,43 +1,44 @@
<?php
namespace Kiri;
use Exception;
use Kiri\Abstracts\Component;
use Server\ServerManager;
/**
* Class Async
* @package Kiri
*/
class Async extends Component
{
private static array $_absences = [];
/**
* @param string $name
* @param string $handler
*/
public function addAsync(string $name, string $handler)
{
static::$_absences[$name] = $handler;
}
/**
* @param string $name
* @param array $params
* @throws Exception
*/
public function dispatch(string $name, array $params = [])
{
$context = di(ServerManager::class);
$context->task(static::$_absences[$name], $params);
}
}
<?php
namespace Kiri;
use Exception;
use Kiri\Abstracts\Component;
use Server\ServerManager;
use Server\Tasker\AsyncTaskExecute;
/**
* Class Async
* @package Kiri
*/
class Async extends Component
{
private static array $_absences = [];
/**
* @param string $name
* @param string $handler
*/
public function addAsync(string $name, string $handler)
{
static::$_absences[$name] = $handler;
}
/**
* @param string $name
* @param array $params
* @throws Exception
*/
public function dispatch(string $name, array $params = [])
{
$context = di(AsyncTaskExecute::class);
$context->execute(static::$_absences[$name], $params);
}
}
+171 -152
View File
@@ -1,152 +1,171 @@
<?php
namespace Kiri\Cache\Base;
use Kiri\Abstracts\Logger;
use Kiri\Exception\RedisConnectException;
use Kiri\Kiri;
use Kiri\Pool\StopHeartbeatCheck;
use RedisException;
use Kiri\Context;
use Swoole\Timer;
/**
*
*/
class Redis implements StopHeartbeatCheck
{
const DB_ERROR_MESSAGE = 'The system is busy, please try again later.';
private ?\Redis $pdo = null;
private int $_transaction = 0;
private int $_timer = -1;
private int $_last = 0;
/**
* @param string $host
* @param int $port
* @param int $database
* @param string $auth
* @param string $prefix
* @param int $timeout
* @param int $read_timeout
*/
public function __construct(public string $host, public int $port, public int $database = 0,
public string $auth = '', public string $prefix = '', public int $timeout = 30,
public int $read_timeout = 30)
{
}
public function init()
{
$this->heartbeat_check();
}
/**
*
*/
public function heartbeat_check(): void
{
if (env('state', 'start') == 'exit') {
return;
}
if ($this->_timer === -1 && Context::inCoroutine()) {
$this->_timer = Timer::tick(1000, function () {
try {
if (env('state', 'start') == 'exit') {
Kiri::getDi()->get(Logger::class)->critical('timer end');
$this->stopHeartbeatCheck();
}
if (time() - $this->_last > 10 * 60) {
$this->stopHeartbeatCheck();
$this->pdo = null;
}
} catch (\Throwable $throwable) {
error($throwable);
}
});
}
}
/**
*
*/
public function stopHeartbeatCheck(): void
{
if ($this->_timer > -1) {
Timer::clear($this->_timer);
}
$this->_timer = -1;
}
/**
* @param string $name
* @param array $arguments
* @return mixed
* @throws RedisConnectException|RedisException
*/
public function __call(string $name, array $arguments)
{
if (!method_exists($this, $name)) {
return $this->_pdo()->{$name}(...$arguments);
}
return $this->{$name}(...$arguments);
}
/**
* @return \Redis
* @throws RedisConnectException
* @throws RedisException
*/
public function _pdo(): \Redis
{
if ($this->_timer === -1) {
$this->heartbeat_check();
}
if (!($this->pdo instanceof \Redis) || !$this->pdo->ping('isOk')) {
$this->pdo = $this->newClient();
}
return $this->pdo;
}
/**
* @return \Redis
* @throws RedisConnectException
*/
private function newClient(): \Redis
{
$redis = new \Redis();
if (!$redis->connect($this->host, $this->port, $this->timeout)) {
throw new RedisConnectException(sprintf('The Redis Connect %s::%d Fail.', $this->host, $this->port));
}
if (!empty($this->auth) && !$redis->auth($this->auth)) {
throw new RedisConnectException(sprintf('Redis Error: %s, Host %s, Auth %s', $redis->getLastError(), $this->host, $this->auth));
}
if ($this->read_timeout < 0) {
$this->read_timeout = 0;
}
$redis->select($this->database);
if ($this->read_timeout > 0) {
$redis->setOption(\Redis::OPT_READ_TIMEOUT, $this->read_timeout);
}
$redis->setOption(\Redis::OPT_PREFIX, $this->prefix);
return $redis;
}
}
<?php
namespace Kiri\Cache\Base;
use Exception;
use Kiri\Abstracts\Logger;
use Kiri\Exception\RedisConnectException;
use Kiri\Kiri;
use Kiri\Pool\StopHeartbeatCheck;
use RedisException;
use Swoole\Timer;
/**
*
*/
class Redis implements StopHeartbeatCheck
{
const DB_ERROR_MESSAGE = 'The system is busy, please try again later.';
private ?\Redis $pdo = null;
public string $host;
public int $port;
public int $database = 0;
public string $auth = '';
public string $prefix = '';
public int $timeout = 30;
public int $read_timeout = 30;
public array $pool = [];
private int $_timer = -1;
private int $_last = 0;
/**
* @param array $config
*/
public function __construct(array $config)
{
$this->host = $config['host'];
$this->port = $config['port'];
$this->database = $config['databases'];
$this->auth = $config['auth'];
$this->prefix = $config['prefix'];
$this->timeout = $config['timeout'];
$this->read_timeout = $config['read_timeout'];
$this->pool = $config['pool'];
}
public function init()
{
$this->heartbeat_check();
}
/**
*
*/
public function heartbeat_check(): void
{
if (env('state', 'start') == 'exit') {
return;
}
if ($this->_timer === -1) {
$this->_timer = Timer::tick(1000, fn() => $this->waite());
}
}
/**
* @throws Exception
*/
private function waite(): void
{
try {
if (env('state', 'start') == 'exit') {
Kiri::getDi()->get(Logger::class)->critical('timer end');
$this->stopHeartbeatCheck();
}
if (time() - $this->_last > intval($this->pool['tick'] ?? 60)) {
$this->stopHeartbeatCheck();
$this->pdo = null;
}
} catch (\Throwable $throwable) {
error($throwable);
}
}
/**
*
*/
public function stopHeartbeatCheck(): void
{
if ($this->_timer > -1) {
Timer::clear($this->_timer);
}
$this->_timer = -1;
}
/**
* @param string $name
* @param array $arguments
* @return mixed
* @throws RedisConnectException|RedisException
*/
public function __call(string $name, array $arguments)
{
if (!method_exists($this, $name)) {
return $this->_pdo()->{$name}(...$arguments);
}
return $this->{$name}(...$arguments);
}
/**
* @return \Redis
* @throws RedisConnectException
* @throws RedisException
*/
public function _pdo(): \Redis
{
if ($this->_timer === -1) {
$this->heartbeat_check();
}
if (!($this->pdo instanceof \Redis) || !$this->pdo->ping('isOk')) {
$this->pdo = $this->newClient();
}
return $this->pdo;
}
/**
* @return \Redis
* @throws RedisConnectException
*/
private function newClient(): \Redis
{
$redis = new \Redis();
if (!$redis->connect($this->host, $this->port, $this->timeout)) {
throw new RedisConnectException(sprintf('The Redis Connect %s::%d Fail.', $this->host, $this->port));
}
if (!empty($this->auth) && !$redis->auth($this->auth)) {
throw new RedisConnectException(sprintf('Redis Error: %s, Host %s, Auth %s', $redis->getLastError(), $this->host, $this->auth));
}
if ($this->read_timeout < 0) {
$this->read_timeout = 0;
}
$redis->select($this->database);
if ($this->read_timeout > 0) {
$redis->setOption(\Redis::OPT_READ_TIMEOUT, $this->read_timeout);
}
$redis->setOption(\Redis::OPT_PREFIX, $this->prefix);
return $redis;
}
}
+141 -141
View File
@@ -1,141 +1,141 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/5/2 0002
* Time: 14:51
*/
declare(strict_types=1);
namespace Kiri\Cache;
use JetBrains\PhpStorm\Pure;
use Kiri\Abstracts\Component;
use Swoole\Coroutine\System;
/**
* Class File
* @package Kiri\Kiri\Cache
*/
class File extends Component implements ICache
{
public string $path;
/**
* @param $key
* @param $val
* @return string|int
*/
public function set($key, $val): string|int
{
if (is_array($val) || is_object($val)) {
$val = swoole_serialize($val);
}
$tmpFile = $this->getCacheKey($key);
if (!$this->exists($tmpFile)) {
touch($tmpFile);
}
return System::writeFile($tmpFile, $val, LOCK_EX);
}
/**
* @param $key
* @param array $hashKeys
* @return array|bool
*/
public function hMGet($key, array $hashKeys): array|bool
{
$hash = $this->get($key);
if (!is_array($hash)) {
return false;
}
$nowHash = [];
foreach ($hashKeys as $hashKey) {
$nowHash[$hashKey] = $hash[$hashKey] ?? null;
}
return $nowHash;
}
/**
* @param $key
* @param array $val
* @return bool|int|string
*/
public function hMSet($key, array $val): bool|int|string
{
$hash = $this->get($key);
if (!is_array($hash)) {
return false;
}
$merge = array_merge($hash, $val);
return $this->set($key, $merge);
}
/**
* @param string $key
* @param string $hashKey
* @return string|int|bool
*/
public function hGet(string $key, string $hashKey): string|int|bool
{
$hash = $this->get($key);
if (!is_array($hash)) {
return false;
}
return $hash[$hashKey] ?? false;
}
/**
* @param $key
* @param $hashKey
* @param $hashValue
* @return bool|int|string
*/
public function hSet($key, $hashKey, $hashValue): bool|int|string
{
$hash = $this->get($key);
if (!is_array($hash)) {
return false;
}
$hash[$hashKey] = $hashValue;
return $this->set($key, $hash);
}
/**
* @param $key
* @return bool
*/
#[Pure] public function exists($key): bool
{
return file_exists($key);
}
/**
* @param $key
* @return mixed|bool
*/
public function get($key): string|bool
{
$tmpFile = $this->getCacheKey($key);
if (!$this->exists($tmpFile)) {
return false;
}
$content = file_get_contents($tmpFile);
return swoole_unserialize($content);
}
/**
* @param $key
* @return string
* @throws
*/
private function getCacheKey($key): string
{
return storage($key, 'cache');
}
}
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/5/2 0002
* Time: 14:51
*/
declare(strict_types=1);
namespace Kiri\Cache;
use JetBrains\PhpStorm\Pure;
use Kiri\Abstracts\Component;
use Swoole\Coroutine\System;
/**
* Class File
* @package Kiri\Kiri\Cache
*/
class File extends Component implements ICache
{
public string $path;
/**
* @param $key
* @param $val
* @return string|int
*/
public function set($key, $val): string|int
{
if (is_array($val) || is_object($val)) {
$val = swoole_serialize($val);
}
$tmpFile = $this->getCacheKey($key);
if (!$this->exists($tmpFile)) {
touch($tmpFile);
}
return System::writeFile($tmpFile, $val, LOCK_EX);
}
/**
* @param $key
* @param array $hashKeys
* @return array|bool
*/
public function hMGet($key, array $hashKeys): array|bool
{
$hash = $this->get($key);
if (!is_array($hash)) {
return false;
}
$nowHash = [];
foreach ($hashKeys as $hashKey) {
$nowHash[$hashKey] = $hash[$hashKey] ?? null;
}
return $nowHash;
}
/**
* @param $key
* @param array $val
* @return bool|int|string
*/
public function hMSet($key, array $val): bool|int|string
{
$hash = $this->get($key);
if (!is_array($hash)) {
return false;
}
$merge = array_merge($hash, $val);
return $this->set($key, $merge);
}
/**
* @param string $key
* @param string $hashKey
* @return string|int|bool
*/
public function hGet(string $key, string $hashKey): string|int|bool
{
$hash = $this->get($key);
if (!is_array($hash)) {
return false;
}
return $hash[$hashKey] ?? false;
}
/**
* @param $key
* @param $hashKey
* @param $hashValue
* @return bool|int|string
*/
public function hSet($key, $hashKey, $hashValue): bool|int|string
{
$hash = $this->get($key);
if (!is_array($hash)) {
return false;
}
$hash[$hashKey] = $hashValue;
return $this->set($key, $hash);
}
/**
* @param $key
* @return bool
*/
#[Pure] public function exists($key): bool
{
return file_exists($key);
}
/**
* @param $key
* @return mixed|bool
*/
public function get($key): string|bool
{
$tmpFile = $this->getCacheKey($key);
if (!$this->exists($tmpFile)) {
return false;
}
$content = file_get_contents($tmpFile);
return swoole_unserialize($content);
}
/**
* @param $key
* @return string
* @throws
*/
private function getCacheKey($key): string
{
return storage($key, 'cache');
}
}
+65 -65
View File
@@ -1,65 +1,65 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/11/8 0008
* Time: 16:35
*/
declare(strict_types=1);
namespace Kiri\Cache;
/**
* Interface ICache
* @package Kiri\Kiri\Cache
*/
interface ICache
{
/**
* @param $key
* @param $val
* @return string|int
*/
public function set($key, $val): string|int;
/**
* @param $key
* @return string|int|bool
*/
public function get($key): string|int|bool;
/**
* @param $key
* @param array $hashKeys
* @return array|bool|null
*/
public function hMGet($key, array $hashKeys): array|bool|null;
/**
* @param $key
* @param array $val
* @return mixed
*/
public function hMSet($key, array $val): mixed;
/**
* @param string $key
* @param string $hashKey
* @return string|int|bool
*/
public function hGet(string $key, string $hashKey): string|int|bool;
/**
* @param $key
* @param $hashKey
* @param $hashValue
* @return mixed
*/
public function hSet($key, $hashKey, $hashValue): mixed;
/**
* @param $key
* @return bool
*/
public function exists($key): bool;
}
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/11/8 0008
* Time: 16:35
*/
declare(strict_types=1);
namespace Kiri\Cache;
/**
* Interface ICache
* @package Kiri\Kiri\Cache
*/
interface ICache
{
/**
* @param $key
* @param $val
* @return string|int
*/
public function set($key, $val): string|int;
/**
* @param $key
* @return string|int|bool
*/
public function get($key): string|int|bool;
/**
* @param $key
* @param array $hashKeys
* @return array|bool|null
*/
public function hMGet($key, array $hashKeys): array|bool|null;
/**
* @param $key
* @param array $val
* @return mixed
*/
public function hMSet($key, array $val): mixed;
/**
* @param string $key
* @param string $hashKey
* @return string|int|bool
*/
public function hGet(string $key, string $hashKey): string|int|bool;
/**
* @param $key
* @param $hashKey
* @param $hashValue
* @return mixed
*/
public function hSet($key, $hashKey, $hashValue): mixed;
/**
* @param $key
* @return bool
*/
public function exists($key): bool;
}
+186 -160
View File
@@ -1,160 +1,186 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/4/27 0027
* Time: 11:00
*/
declare(strict_types=1);
namespace Kiri\Cache;
use Annotation\Inject;
use Exception;
use Server\Events\OnWorkerExit;
use Kiri\Abstracts\Component;
use Kiri\Abstracts\Config;
use Kiri\Core\Json;
use Kiri\Events\EventProvider;
use Kiri\Exception\ConfigException;
use Kiri\Kiri;
use Kiri\Pool\Redis as PoolRedis;
/**
* Class Redis
* @package Kiri\Kiri\Cache
* @mixin \Redis
*/
class Redis extends Component
{
/**
* @var EventProvider
*/
#[Inject(EventProvider::class)]
public EventProvider $eventProvider;
/**
* @throws ConfigException
* @throws Exception
*/
public function init()
{
$connections = Kiri::getDi()->get(PoolRedis::class);
$config = $this->get_config();
$length = Config::get('connections.pool.max', 10);
$this->eventProvider->on(OnWorkerExit::class, [$this, 'destroy'], 0);
$connections->initConnections('Redis:' . $config['host'], true, $length);
}
/**
* @param $name
* @param $arguments
* @return mixed
* @throws
*/
public function __call($name, $arguments): mixed
{
$time = microtime(true);
if (method_exists($this, $name)) {
$data = $this->{$name}(...$arguments);
} else {
$data = $this->proxy($name, $arguments);
}
if (microtime(true) - $time >= 0.02) {
$this->warning('Redis:' . Json::encode([$name, $arguments]) . (microtime(true) - $time));
}
return $data;
}
/**
* @param $key
* @param int $timeout
* @return bool|int
* @throws Exception
*/
public function lock($key, int $timeout = 5): bool|int
{
$script = <<<SCRIPT
local _nx = redis.call('setnx',KEYS[1], ARGV[1])
if (_nx ~= 0) then
redis.call('expire',KEYS[1], ARGV[1])
return 1
end
return 0
SCRIPT;
return $this->eval($script, ['{lock}:' . $key, $timeout], 1);
}
/**
* @param $key
* @return int
* @throws Exception
*/
public function unlock($key): int
{
return $this->del('{lock}:' . $key);
}
/**
* @throws ConfigException
* @throws Exception
*/
public function release()
{
$connections = Kiri::getDi()->get(PoolRedis::class);
$connections->release($this->get_config(), true);
}
/**
* 销毁连接池
* @throws ConfigException
* @throws Exception
*/
public function destroy()
{
$connections = Kiri::getDi()->get(PoolRedis::class);
$connections->connection_clear($this->get_config(), true);
}
/**
* @param $name
* @param $arguments
* @return mixed
* @throws ConfigException
* @throws Exception
*/
public function proxy($name, $arguments): mixed
{
$connections = Kiri::getDi()->get(PoolRedis::class);
$config = $this->get_config();
$client = $connections->get($config, true);
if (!($client instanceof Base\Redis)) {
throw new Exception('Redis connections more.');
}
$response = $client->{$name}(...$arguments);
$this->release();
return $response;
}
/**
* @return array
* @throws ConfigException
*/
public function get_config(): array
{
return Config::get('cache.redis', null, true);
}
}
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/4/27 0027
* Time: 11:00
*/
declare(strict_types=1);
namespace Kiri\Cache;
use Exception;
use Kiri\Abstracts\Component;
use Kiri\Abstracts\Config;
use Kiri\Core\Json;
use Kiri\Events\EventProvider;
use Kiri\Exception\ConfigException;
use Kiri\Kiri;
use Kiri\Pool\Redis as PoolRedis;
use Kiri\Annotation\Inject;
use Server\Events\OnWorkerExit;
use Swoole\Timer;
/**
* Class Redis
* @package Kiri\Kiri\Cache
* @mixin \Redis
*/
class Redis extends Component
{
const REDIS_OPTION_HOST = 'host';
const REDIS_OPTION_PORT = 'port';
const REDIS_OPTION_PREFIX = 'prefix';
const REDIS_OPTION_AUTH = 'auth';
const REDIS_OPTION_DATABASES = 'databases';
const REDIS_OPTION_TIMEOUT = 'timeout';
const REDIS_OPTION_POOL = 'pool';
const REDIS_OPTION_POOL_TICK = 'tick';
const REDIS_OPTION_POOL_MIN = 'min';
const REDIS_OPTION_POOL_MAX = 'max';
/**
* @throws ConfigException
* @throws Exception
*/
public function init()
{
$connections = Kiri::getDi()->get(PoolRedis::class);
$config = $this->get_config();
$length = Config::get('cache.redis.pool.max', 10);
$this->eventProvider->on(OnWorkerExit::class, [$this, 'destroy'], 0);
$connections->initConnections('Redis:' . $config['host'], true, $length);
}
/**
* @param $name
* @param $arguments
* @return mixed
* @throws
*/
public function __call($name, $arguments): mixed
{
$time = microtime(true);
if (method_exists($this, $name)) {
$data = $this->{$name}(...$arguments);
} else {
$data = $this->proxy($name, $arguments);
}
if (microtime(true) - $time >= 0.02) {
$this->warning('Redis:' . Json::encode([$name, $arguments]) . (microtime(true) - $time));
}
return $data;
}
/**
* @param $key
* @param int $timeout
* @return bool
*/
public function waite($key, int $timeout = 5): bool
{
$time = time();
while (!$this->setNx($key, 1)) {
if (time()- $time >= $timeout) {
return FALSE;
}
usleep(1000);
}
$this->expire($key, $timeout);
return TRUE;
}
/**
* @param $key
* @param int $timeout
* @return bool|int
* @throws Exception
*/
public function lock($key, int $timeout = 5): bool|int
{
$script = <<<SCRIPT
local _nx = redis.call('setnx',KEYS[1], ARGV[1])
if (_nx ~= 0) then
redis.call('expire',KEYS[1], ARGV[1])
return 1
end
return 0
SCRIPT;
return $this->eval($script, ['{lock}:' . $key, $timeout], 1);
}
/**
* @param $key
* @return int
* @throws Exception
*/
public function unlock($key): int
{
return $this->del('{lock}:' . $key);
}
/**
* @throws ConfigException
* @throws Exception
*/
public function release()
{
$connections = Kiri::getDi()->get(PoolRedis::class);
$connections->release($this->get_config(), true);
}
/**
* 销毁连接池
* @throws ConfigException
* @throws Exception
*/
public function destroy()
{
$connections = Kiri::getDi()->get(PoolRedis::class);
$connections->connection_clear($this->get_config(), true);
}
/**
* @param $name
* @param $arguments
* @return mixed
* @throws ConfigException
* @throws Exception
*/
public function proxy($name, $arguments): mixed
{
$connections = Kiri::getDi()->get(PoolRedis::class);
$config = $this->get_config();
$client = $connections->get($config, true);
if (!($client instanceof Base\Redis)) {
throw new Exception('Redis connections more.');
}
$response = $client->{$name}(...$arguments);
$this->release();
return $response;
}
/**
* @return array
* @throws ConfigException
*/
public function get_config(): array
{
return Config::get('cache.redis', null, true);
}
}
+209 -189
View File
@@ -1,189 +1,209 @@
<?php
namespace Kiri;
use Kiri\Abstracts\BaseContext;
use Swoole\Coroutine;
/**
* Class Context
* @package Yoc\http
*/
class Context extends BaseContext
{
protected static array $_contents = [];
/**
* @param $id
* @param $context
* @param null $coroutineId
* @return mixed
*/
public static function setContext($id, $context, $coroutineId = null): mixed
{
if (Coroutine::getCid() === -1) {
return static::$_contents[$id] = $context;
}
return Coroutine::getContext($coroutineId)[$id] = $context;
}
/**
* @param $id
* @param int $value
* @param null $coroutineId
* @return bool|int
*/
public static function increment($id, int $value = 1, $coroutineId = null): bool|int
{
if (!isset(Coroutine::getContext($coroutineId)[$id])) {
Coroutine::getContext($coroutineId)[$id] = 0;
}
return Coroutine::getContext($coroutineId)[$id] += $value;
}
/**
* @param $id
* @param int $value
* @param null $coroutineId
* @return bool|int
*/
public static function decrement($id, int $value = 1, $coroutineId = null): bool|int
{
if (!isset(Coroutine::getContext($coroutineId)[$id])) {
Coroutine::getContext($coroutineId)[$id] = 0;
}
return Coroutine::getContext($coroutineId)[$id] -= $value;
}
/**
* @param $id
* @param null $default
* @param null $coroutineId
* @return mixed
*/
public static function getContext($id, $default = null, $coroutineId = null): mixed
{
if (Coroutine::getCid() === -1) {
return static::loadByStatic($id, $default);
}
return static::loadByContext($id, $default, $coroutineId);
}
/**
* @param $id
* @param null $default
* @param null $coroutineId
* @return mixed
*/
private static function loadByContext($id, $default = null, $coroutineId = null): mixed
{
return Coroutine::getContext($coroutineId)[$id] ?? $default;
}
/**
* @param $id
* @param null $default
* @return mixed
*/
private static function loadByStatic($id, $default = null): mixed
{
return static::$_contents[$id] ?? $default;
}
/**
* @param null $coroutineId
* @return mixed
*/
public static function getAllContext($coroutineId = null): mixed
{
if (Coroutine::getCid() === -1) {
return Coroutine::getContext($coroutineId) ?? [];
} else {
return static::$_contents ?? [];
}
}
/**
* @param string $id
* @param null $coroutineId
*/
public static function remove(string $id, $coroutineId = null)
{
if (!static::hasContext($id, $coroutineId)) {
return;
}
if (Coroutine::getCid() === -1) {
unset(static::$_contents[$id]);
} else {
unset(Coroutine::getContext($coroutineId)[$id]);
}
}
/**
* @param $id
* @param null $key
* @param null $coroutineId
* @return bool
*/
public static function hasContext($id, $key = null, $coroutineId = null): bool
{
if (Coroutine::getCid() === -1) {
return static::searchByStatic($id, $key);
}
return static::searchByCoroutine($id, $key, $coroutineId);
}
/**
* @param $id
* @param null $key
* @return bool
*/
private static function searchByStatic($id, $key = null): bool
{
if (!isset(static::$_contents[$id])) {
return false;
}
if (!empty($key) && !isset(static::$_contents[$id][$key])) {
return false;
}
return true;
}
/**
* @param $id
* @param null $key
* @param null $coroutineId
* @return bool
*/
private static function searchByCoroutine($id, $key = null, $coroutineId = null): bool
{
if (!isset(Coroutine::getContext($coroutineId)[$id])) {
return false;
}
if ($key !== null) {
return isset((Coroutine::getContext($coroutineId)[$id] ?? [])[$key]);
}
return true;
}
/**
* @return bool
*/
public static function inCoroutine(): bool
{
return Coroutine::getCid() !== -1;
}
}
<?php
namespace Kiri;
use Kiri\Abstracts\BaseContext;
use Swoole\Coroutine;
/**
* Class Context
* @package Yoc\http
*/
class Context extends BaseContext
{
protected static array $_contents = [];
/**
* @param $id
* @param $context
* @param null $coroutineId
* @return mixed
*/
public static function setContext($id, $context, $coroutineId = null): mixed
{
if (is_null($coroutineId)) {
$coroutineId = Coroutine::getCid();
}
if (Coroutine::getCid() !== -1) {
return Coroutine::getContext($coroutineId)[$id] = $context;
}
return static::$_contents[$id] = $context;
}
/**
* @param $id
* @param int $value
* @param null $coroutineId
* @return bool|int
*/
public static function increment($id, int $value = 1, $coroutineId = null): bool|int
{
if (is_null($coroutineId)) {
$coroutineId = Coroutine::getCid();
}
if (!isset(Coroutine::getContext($coroutineId)[$id])) {
Coroutine::getContext($coroutineId)[$id] = 0;
}
return Coroutine::getContext($coroutineId)[$id] += $value;
}
/**
* @param $id
* @param int $value
* @param null $coroutineId
* @return bool|int
*/
public static function decrement($id, int $value = 1, $coroutineId = null): bool|int
{
if (is_null($coroutineId)) {
$coroutineId = Coroutine::getCid();
}
if (!isset(Coroutine::getContext($coroutineId)[$id])) {
Coroutine::getContext($coroutineId)[$id] = 0;
}
return Coroutine::getContext($coroutineId)[$id] -= $value;
}
/**
* @param $id
* @param null $default
* @param null $coroutineId
* @return mixed
*/
public static function getContext($id, $default = null, $coroutineId = null): mixed
{
if (Coroutine::getCid() === -1) {
return static::loadByStatic($id, $default);
}
return static::loadByContext($id, $default, $coroutineId);
}
/**
* @param $id
* @param null $default
* @param null $coroutineId
* @return mixed
*/
private static function loadByContext($id, $default = null, $coroutineId = null): mixed
{
if (is_null($coroutineId)) {
$coroutineId = Coroutine::getCid();
}
return Coroutine::getContext($coroutineId)[$id] ?? $default;
}
/**
* @param $id
* @param null $default
* @return mixed
*/
private static function loadByStatic($id, $default = null): mixed
{
return static::$_contents[$id] ?? $default;
}
/**
* @param null $coroutineId
* @return mixed
*/
public static function getAllContext($coroutineId = null): mixed
{
if (Coroutine::getCid() === -1) {
return Coroutine::getContext($coroutineId) ?? [];
} else {
return static::$_contents ?? [];
}
}
/**
* @param string $id
* @param null $coroutineId
*/
public static function remove(string $id, $coroutineId = null)
{
if (is_null($coroutineId)) {
$coroutineId = Coroutine::getCid();
}
if (!static::hasContext($id, $coroutineId)) {
return;
}
if (Coroutine::getCid() === -1) {
unset(static::$_contents[$id]);
} else {
unset(Coroutine::getContext($coroutineId)[$id]);
}
}
/**
* @param $id
* @param null $key
* @param null $coroutineId
* @return bool
*/
public static function hasContext($id, $key = null, $coroutineId = null): bool
{
if (Coroutine::getCid() === -1) {
return static::searchByStatic($id, $key);
}
return static::searchByCoroutine($id, $key, $coroutineId);
}
/**
* @param $id
* @param null $key
* @return bool
*/
private static function searchByStatic($id, $key = null): bool
{
if (!isset(static::$_contents[$id])) {
return false;
}
$value = static::$_contents[$id];
if (!empty($key) && is_array($value)) {
return isset($value[$key]);
}
return true;
}
/**
* @param $id
* @param null $key
* @param null $coroutineId
* @return bool
*/
private static function searchByCoroutine($id, $key = null, $coroutineId = null): bool
{
if (is_null($coroutineId)) {
$coroutineId = Coroutine::getCid();
}
if (!isset(Coroutine::getContext($coroutineId)[$id])) {
return false;
}
$value = Coroutine::getContext($coroutineId)[$id];
if ($key !== null && is_array($value)) {
return isset($value[$key]);
}
return true;
}
/**
* @return bool
*/
public static function inCoroutine(): bool
{
return Coroutine::getCid() !== -1;
}
}
+100 -100
View File
@@ -1,100 +1,100 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/4/4 0004
* Time: 14:57
*/
declare(strict_types=1);
namespace Kiri\Core;
use Exception;
/**
* Class ArrayAccess
* @package Kiri\Core
*/
class ArrayAccess
{
/**
* @param $data
* @return array
* @throws Exception
*/
public static function toArray($data): array
{
if (!is_object($data) && !is_array($data)) {
return [];
}
if (is_object($data)) {
$data = self::objToArray($data);
}
$tmp = [];
if (!is_array($data)) {
return $tmp;
}
foreach ($data as $key => $val) {
if (is_array($val) || is_object($val)) {
$tmp[$key] = self::toArray($val);
} else {
$tmp[$key] = $val;
}
}
return $tmp;
}
/**
* @param $data
* @return array
* @throws Exception
*/
public static function objToArray($data): array
{
if (!is_object($data)) {
return $data;
}
if (method_exists($data, 'get')) {
$data = $data->get();
if (is_array($data)) {
return $data;
}
}
if (method_exists($data, 'toArray')) {
$data = $data->toArray();
} else {
$data = get_object_vars((object)$data);
}
return $data;
}
/**
* @param array $oldArray
* @param array $newArray
* @return array
*/
public static function merge(array $oldArray, array $newArray): array
{
if (empty($oldArray)) {
return $newArray;
} else if (empty($newArray)) {
return $oldArray;
}
foreach ($newArray as $item => $value) {
if (!isset($oldArray[$item])) {
$oldArray[$item] = $value;
}
if (is_array($value)) {
$oldArray[$item] = self::merge($oldArray[$item], $value);
} else {
$oldArray[$item] = $value;
}
}
return $oldArray;
}
}
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/4/4 0004
* Time: 14:57
*/
declare(strict_types=1);
namespace Kiri\Core;
use Exception;
/**
* Class ArrayAccess
* @package Kiri\Core
*/
class ArrayAccess
{
/**
* @param $data
* @return array
* @throws Exception
*/
public static function toArray($data): array
{
if (!is_object($data) && !is_array($data)) {
return [];
}
if (is_object($data)) {
$data = self::objToArray($data);
}
$tmp = [];
if (!is_array($data)) {
return $tmp;
}
foreach ($data as $key => $val) {
if (is_array($val) || is_object($val)) {
$tmp[$key] = self::toArray($val);
} else {
$tmp[$key] = $val;
}
}
return $tmp;
}
/**
* @param $data
* @return array
* @throws Exception
*/
public static function objToArray($data): array
{
if (!is_object($data)) {
return $data;
}
if (method_exists($data, 'get')) {
$data = $data->get();
if (is_array($data)) {
return $data;
}
}
if (method_exists($data, 'toArray')) {
$data = $data->toArray();
} else {
$data = get_object_vars((object)$data);
}
return $data;
}
/**
* @param array $oldArray
* @param array $newArray
* @return array
*/
public static function merge(array $oldArray, array $newArray): array
{
if (empty($oldArray)) {
return $newArray;
} else if (empty($newArray)) {
return $oldArray;
}
foreach ($newArray as $item => $value) {
if (!isset($oldArray[$item])) {
$oldArray[$item] = $value;
}
if (is_array($value)) {
$oldArray[$item] = self::merge($oldArray[$item], $value);
} else {
$oldArray[$item] = $value;
}
}
return $oldArray;
}
}
+104 -106
View File
@@ -1,106 +1,104 @@
<?php
/**
* Created by PhpStorm.
* User: dell
* Date: 2019/1/14 0014
* Time: 13:50
*/
declare(strict_types=1);
namespace Kiri\Core;
/**
* Class DateFormat
* @package Kiri\Kiri\Core
*/
class DateFormat
{
/**
* @param $time
* @return bool|false|int|string
*/
private static function check($time): bool|int|string
{
if ($time === null) {
$time = time();
} else if (is_numeric($time)) {
$length = strlen(floatval($time));
if ($length != 10 && $length != 13) {
return false;
}
} else if (is_string($time)) {
$time = strtotime($time);
}
if (date('Y-m-d', $time)) {
return $time;
}
return false;
}
/**
* @param null $time
* @return bool|false|int
*
* 获取指定日期当周第一天的时间
*/
public static function getWeekCurrentDay($time = null): bool|int
{
if (!($time = static::check($time))) {
return false;
}
$time = strtotime('-' . (date('N') - 1) . 'days', $time);
return strtotime(date('Y-m-d'), $time);
}
/**
* @param null $time
* @return bool|false|int
*
* 获取指定日期当月第一天的时间
*/
public static function getMonthCurrentDay($time = null): bool|int
{
if (!($time = static::check($time))) {
return false;
}
return strtotime(date('Y-m', $time) . '-01');
}
/**
* @param $time
* @return bool|int|string 指定的月份有几天
* 指定的月份有几天
*/
public static function getMonthTotalDay($time): bool|int|string
{
if (!($time = static::check($time))) {
return false;
}
$time = date('t', $time);
return $time;
}
/**
* @param $startTime
* @param null $endTime
* @return string
*/
public static function mtime($startTime, $endTime = null)
{
if ($endTime === null) {
$endTime = microtime(true);
}
return sprintf('%.7f', $endTime - $startTime);
}
}
<?php
/**
* Created by PhpStorm.
* User: dell
* Date: 2019/1/14 0014
* Time: 13:50
*/
declare(strict_types=1);
namespace Kiri\Core;
/**
* Class DateFormat
* @package Kiri\Kiri\Core
*/
class DateFormat
{
/**
* @param $time
* @return bool|false|int|string
*/
private static function check($time): bool|int|string
{
if ($time === null) {
$time = time();
} else if (is_numeric($time)) {
$length = strlen((string)$time);
if ($length != 10 && $length != 13) {
return false;
}
} else if (is_string($time)) {
$time = strtotime($time);
}
if (date('Y-m-d', $time)) {
return $time;
}
return false;
}
/**
* @param null $time
* @return bool|false|int
*
* 获取指定日期当周第一天的时间
*/
public static function getWeekCurrentDay($time = null): bool|int
{
if (!($time = static::check($time))) {
return false;
}
$time = strtotime('-' . (date('N') - 1) . 'days', $time);
return strtotime(date('Y-m-d'), $time);
}
/**
* @param null $time
* @return bool|false|int
*
* 获取指定日期当月第一天的时间
*/
public static function getMonthCurrentDay($time = null): bool|int
{
if (!($time = static::check($time))) {
return false;
}
return strtotime(date('Y-m', $time) . '-01');
}
/**
* @param $time
* @return bool|int|string 指定的月份有几天
* 指定的月份有几天
*/
public static function getMonthTotalDay($time): bool|int|string
{
if (!($time = static::check($time))) {
return false;
}
return date('t', $time);
}
/**
* @param $startTime
* @param null $endTime
* @return string
*/
public static function mtime($startTime, $endTime = null)
{
if ($endTime === null) {
$endTime = microtime(true);
}
return sprintf('%.7f', $endTime - $startTime);
}
}
+58 -60
View File
@@ -1,60 +1,58 @@
<?php
declare(strict_types=1);
namespace Kiri\Core;
use Exception;
use Kiri\Abstracts\Component;
/**
* Class Dtl
* @package Kiri\Core
*/
class Dtl extends Component
{
protected array $params;
/**
* Dtl constructor.
* @param $params
*/
public function __construct($params)
{
parent::__construct([]);
$this->params = $params;
}
/**
* @return array
* @throws Exception
*/
public function toArray(): array
{
if (!is_array($this->params)) {
return ArrayAccess::toArray($this->params);
}
return $this->params;
}
/**
* @param $name
* @return mixed
* @throws Exception
*/
public function get($name): mixed
{
$array = $this->toArray();
if (!isset($array[$name])) {
return null;
}
return $array[$name];
}
}
<?php
declare(strict_types=1);
namespace Kiri\Core;
use Exception;
use Kiri\Abstracts\Component;
/**
* Class Dtl
* @package Kiri\Core
*/
class Dtl extends Component
{
protected array $params;
/**
* Dtl constructor.
* @param $params
* @throws Exception
*/
public function __construct($params)
{
parent::__construct([]);
$this->params = $params;
}
/**
* @return array
* @throws Exception
*/
public function toArray(): array
{
return $this->params;
}
/**
* @param $name
* @return mixed
* @throws Exception
*/
public function get($name): mixed
{
$array = $this->toArray();
if (!isset($array[$name])) {
return null;
}
return $array[$name];
}
}
+101
View File
@@ -0,0 +1,101 @@
<?php
namespace Kiri\Core;
use JetBrains\PhpStorm\Pure;
use ReturnTypeWillChange;
class HashMap implements \ArrayAccess
{
/**
* @var array
*/
private array $lists = [];
/**
* @param string $key
* @param $value
*/
public function put(string $key, $value)
{
$this->lists[$key] = $value;
}
/**
* @param string $key
* @return mixed
*/
#[Pure] public function get(string $key): mixed
{
if (!$this->has($key)) {
return null;
}
return $this->lists[$key];
}
/**
* @param string $key
*/
public function del(string $key)
{
if (!$this->has($key)) {
return;
}
unset($this->lists[$key]);
}
/**
* @param string $key
* @return bool
*/
public function has(string $key): bool
{
return array_key_exists($key, $this->lists);
}
/**
* @param mixed $offset
* @return bool
*/
public function offsetExists(mixed $offset): bool
{
return isset($this->lists[$offset]);
}
/**
* @param mixed $offset
* @return mixed
*/
#[Pure] public function offsetGet(mixed $offset): mixed
{
return $this->get($offset);
}
/**
* @param mixed $offset
* @param mixed $value
*/
#[ReturnTypeWillChange]
public function offsetSet(mixed $offset, mixed $value)
{
$this->put($offset, $value);
}
/**
* @param mixed $offset
*/
#[ReturnTypeWillChange]
public function offsetUnset(mixed $offset)
{
unset($this->lists[$offset]);
}
}
+219 -215
View File
@@ -1,215 +1,219 @@
<?php
declare(strict_types=1);
namespace Kiri\Core;
use Exception;
/**
* Class Help
* @package Kiri\Kiri\Core
*/
class Help
{
/**
* @param array $data
* @return string
*/
public static function toXml(array $data): string
{
$xml = "<xml>";
foreach ($data as $key => $val) {
if (is_array($val)) {
$xml .= "<" . $key . ">" . static::xmlChild($val) . "</" . $key . ">";
} else if (is_numeric($val)) {
$xml .= "<" . $key . ">" . $val . "</" . $key . ">";
} else {
$xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
}
}
$xml .= "</xml>";
return $xml;
}
/**
* @param array $array
* @return string
*/
private static function xmlChild(array $array): string
{
$string = '';
foreach ($array as $key => $value) {
if (is_array($value)) {
$string .= static::xmlChild($value);
} else if (is_numeric($value)) {
$string .= "<" . $key . ">" . $value . "</" . $key . ">";
} else {
$string .= "<" . $key . "><![CDATA[" . $value . "]]></" . $key . ">";
}
}
return $string;
}
/**
* @param $xml
* @return mixed
*/
public static function toArray($xml): mixed
{
if (empty($xml)) {
return [];
} else if (is_array($xml)) {
return $xml;
}
if (!($_xml = Xml::isXml($xml))) {
return static::jsonToArray($xml);
}
return $_xml;
}
/**
* @param $xml
* @return mixed
*/
public static function jsonToArray($xml): mixed
{
$_xml = json_decode($xml, true);
if (is_null($_xml)) {
return [];
}
return $_xml;
}
/**
* @param $xml
* @return mixed
*/
public static function xmlToArray($xml): mixed
{
if (is_array($xml)) {
return $xml;
}
if (($data = @simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)) !== false) {
return json_decode(json_encode($data), TRUE);
}
if (!is_null($json = json_decode($xml, TRUE))) {
return $json;
}
return $xml;
}
/**
* @param $parameter
* @return array|false|string
* @throws Exception
*/
public static function toString($parameter): bool|array|string
{
if (!is_string($parameter)) {
$parameter = ArrayAccess::toArray($parameter);
if (is_array($parameter)) {
$parameter = Json::encode($parameter);
}
}
return $parameter;
}
/**
* @param mixed $json
* @return bool|string
*/
public static function toJson(mixed $json): bool|string
{
if (is_object($json)) {
$json = get_object_vars($json);
}
if (is_array($json)) {
return json_encode($json, JSON_UNESCAPED_UNICODE);
}
$matchQuote = '/(<\?xml.*?\?>)?<([a-zA-Z_]+)>(<([a-zA-Z_]+)><!.*?><\/\4>)+<\/\2>/';
if (preg_match($matchQuote, $json)) {
$json = self::xmlToArray($json);
} else {
$json = json_decode($json, true);
}
if (!is_array($json)) {
$json = [];
}
return json_encode($json, JSON_UNESCAPED_UNICODE);
}
/**
* @param int $length
* @return string
*
* 随机字符串
*/
public static function random($length = 20): string
{
$res = [];
$str = 'abcdefghijklmnopqrstuvwxyz';
$str .= strtoupper($str) . '1234567890';
for ($i = 0; $i < $length; $i++) {
$rand = substr($str, rand(0, strlen($str) - 2), 1);
if (empty($rand)) {
$rand = substr($str, strlen($str) - 3, 1);
}
array_push($res, $rand);
}
return implode($res);
}
/**
* @param array $array
* @param $key
* @param string $type
* @return string
*/
public static function sign(array $array, $key, string $type = 'MD5'): string
{
ksort($array, SORT_ASC);
$string = [];
foreach ($array as $hashKey => $val) {
if (empty($val)) {
continue;
}
$string[] = $hashKey . '=' . $val;
}
$string[] = 'key=' . $key;
$string = implode('&', $string);
if ($type == 'MD5') {
return strtoupper(md5($string));
} else {
return hash('sha256', $string);
}
}
/**
* @param $email
* @param string $Subject
* @param $messageContent
*/
public static function sendEmail($email, string $Subject, $messageContent)
{
$mailer = new \Swift_Mailer((new \Swift_SmtpTransport($email['host'], $email['port']))
->setUsername($email['username'])->setPassword($email['password']));
$message = (new \Swift_Message($Subject))
->setFrom([$email['send']['address'] => $email['send']['nickname']])
->setBody('Here is the message itself');
foreach ($email['receive'] as $item) {
$message->setTo([$item['address'], $item['address'] => $item['nickname']]);
}
$mailer->send($messageContent);
}
}
<?php
declare(strict_types=1);
namespace Kiri\Core;
use Exception;
/**
* Class Help
* @package Kiri\Kiri\Core
*/
class Help
{
/**
* @param array $data
* @return string
*/
public static function toXml(array $data): string
{
$xml = "<xml>";
foreach ($data as $key => $val) {
if (is_array($val)) {
$xml .= "<" . $key . ">" . static::xmlChild($val) . "</" . $key . ">";
} else if (is_numeric($val)) {
$xml .= "<" . $key . ">" . $val . "</" . $key . ">";
} else {
$xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
}
}
$xml .= "</xml>";
return $xml;
}
/**
* @param array $array
* @return string
*/
private static function xmlChild(array $array): string
{
$string = '';
foreach ($array as $key => $value) {
if (is_array($value)) {
$string .= static::xmlChild($value);
} else if (is_numeric($value)) {
$string .= "<" . $key . ">" . $value . "</" . $key . ">";
} else {
$string .= "<" . $key . "><![CDATA[" . $value . "]]></" . $key . ">";
}
}
return $string;
}
/**
* @param $xml
* @return mixed
* @throws Exception
*/
public static function toArray($xml): mixed
{
if (empty($xml)) {
return [];
} else if (is_array($xml)) {
return $xml;
}
if (!($_xml = Xml::isXml($xml))) {
return static::jsonToArray($xml);
}
return $_xml;
}
/**
* @param $xml
* @return mixed
*/
public static function jsonToArray($xml): mixed
{
$_xml = json_decode($xml, true);
if (is_null($_xml)) {
return [];
}
return $_xml;
}
/**
* @param $xml
* @return mixed
*/
public static function xmlToArray($xml): mixed
{
if (is_array($xml)) {
return $xml;
}
if (($data = @simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)) !== false) {
return json_decode(json_encode($data), TRUE);
}
if (!is_null($json = json_decode($xml, TRUE))) {
return $json;
}
return $xml;
}
/**
* @param $parameter
* @return array|false|string
* @throws Exception
*/
public static function toString($parameter): bool|array|string
{
if (!is_string($parameter)) {
$parameter = ArrayAccess::toArray($parameter);
if (is_array($parameter)) {
$parameter = Json::encode($parameter);
}
}
return $parameter;
}
/**
* @param mixed $json
* @return bool|string
*/
public static function toJson(mixed $json): bool|string
{
if (is_object($json)) {
$json = get_object_vars($json);
}
if (is_array($json)) {
return json_encode($json, JSON_UNESCAPED_UNICODE);
}
$matchQuote = '/(<\?xml.*?\?>)?<([a-zA-Z_]+)>(<([a-zA-Z_]+)><!.*?><\/\4>)+<\/\2>/';
if (preg_match($matchQuote, $json)) {
$json = self::xmlToArray($json);
} else {
$json = json_decode($json, true);
}
if (!is_array($json)) {
$json = [];
}
return json_encode($json, JSON_UNESCAPED_UNICODE);
}
/**
* @param int $length
* @return string
*
* 随机字符串
*/
public static function random($length = 20): string
{
$res = [];
$str = 'abcdefghijklmnopqrstuvwxyz';
$str .= strtoupper($str) . '1234567890';
for ($i = 0; $i < $length; $i++) {
$rand = substr($str, rand(0, strlen($str) - 2), 1);
if (empty($rand)) {
$rand = substr($str, strlen($str) - 3, 1);
}
array_push($res, $rand);
}
return implode($res);
}
/**
* @param array $array
* @param $key
* @param string $type
* @return string
*/
public static function sign(array $array, $key, string $type = 'MD5'): string
{
ksort($array, SORT_ASC);
$string = [];
foreach ($array as $hashKey => $val) {
if (empty($val)) {
continue;
}
$string[] = $hashKey . '=' . $val;
}
$string[] = 'key=' . $key;
$string = implode('&', $string);
if ($type == 'MD5') {
return strtoupper(md5($string));
} else {
return hash('sha256', $string);
}
}
/**
* @param $email
* @param string $Subject
* @param $messageContent
*/
public static function sendEmail($email, string $Subject, $messageContent)
{
if (!class_exists('\Swift_Mailer')) {
return;
}
$mailer = new \Swift_Mailer((new \Swift_SmtpTransport($email['host'], $email['port']))
->setUsername($email['username'])->setPassword($email['password']));
$message = (new \Swift_Message($Subject))
->setFrom([$email['send']['address'] => $email['send']['nickname']])
->setBody('Here is the message itself');
foreach ($email['receive'] as $item) {
$message->setTo([$item['address'], $item['address'] => $item['nickname']]);
}
$mailer->send($messageContent);
}
}
+121 -122
View File
@@ -1,122 +1,121 @@
<?php
/**
* Created by PhpStorm.
* User: admin
* Date: 2019-03-20
* Time: 01:04
*/
declare(strict_types=1);
namespace Kiri\Core;
use Error;
use Exception;
use Throwable;
/**
* Class JSON
* @package Kiri\Kiri\Core
*/
class Json
{
/**
* @param $data
* @return false|string
*/
public static function encode($data): bool|string
{
if (empty($data)) {
return false;
}
if (is_array($data)) {
return json_encode($data, JSON_UNESCAPED_UNICODE);
}
return $data;
}
/**
* @param $data
* @param bool $asArray
* @return mixed
*/
public static function decode($data, $asArray = true): mixed
{
if (is_array($data) || is_numeric($data)) {
return $data;
}
if (!is_string($data)) return null;
return json_decode($data, $asArray);
}
/**
* @param $code
* @param string $message
* @param array $data
* @param int $count
* @param array $exPageInfo
* @return mixed
* @throws
*/
public static function to($code, $message = '', $data = [], $count = 0, $exPageInfo = []): mixed
{
$params['code'] = $code;
if (!is_string($message)) {
$params['param'] = $message;
if (!empty($data)) {
$params['exPageInfo'] = $data;
}
$params['message'] = 'System success.';
} else {
$params['message'] = $message;
$params['param'] = $data;
}
if (!empty($exPageInfo)) {
$params['exPageInfo'] = $exPageInfo;
}
$params['count'] = $count;
if (is_numeric($data) || !is_numeric($count)) {
$params['count'] = $data;
$params['exPageInfo'] = $count;
}
if ((int)$params['count'] == -100) {
$params['count'] = 1;
}
return static::encode($params);
}
/**
* @param Throwable|Error $throwable
* @return bool|string
*/
public static function error(Throwable|Error $throwable): bool|string
{
$array['code'] = $throwable->getCode() == 0 ? 500 : $throwable->getCode();
$array['message'] = $throwable->getMessage();
$array['param'] = [
'file' => $throwable->getFile(),
'line' => $throwable->getLine()
];
return Json::encode($array);
}
/**
* @param $state
* @param $body
* @return false|int|string
* @throws Exception
*/
public static function output($state, $body): bool|int|string
{
$params['state'] = $state;
$params['body'] = ArrayAccess::toArray($body);
return static::encode($params);
}
}
<?php
/**
* Created by PhpStorm.
* User: admin
* Date: 2019-03-20
* Time: 01:04
*/
declare(strict_types=1);
namespace Kiri\Core;
use Error;
use Exception;
use Throwable;
/**
* Class JSON
* @package Kiri\Kiri\Core
*/
class Json
{
/**
* @param $data
* @return false|string
*/
public static function encode($data): bool|string
{
if (empty($data)) {
return false;
}
if (is_array($data)) {
return json_encode($data, JSON_UNESCAPED_UNICODE);
}
return $data;
}
/**
* @param $data
* @param bool $asArray
* @return mixed
*/
public static function decode($data, bool $asArray = true): mixed
{
if (is_array($data) || is_numeric($data)) {
return $data;
}
if (!is_string($data)) return null;
return json_decode($data, $asArray);
}
/**
* @param $code
* @param string|array $message
* @param array|int $data
* @param int $count
* @param array $exPageInfo
* @return string|bool
*/
public static function to($code, string|array $message = '', array|int $data = [], int $count = 0, array $exPageInfo = []): string|bool
{
$params['code'] = $code;
if (!is_string($message)) {
$params['message'] = 'System success.';
$params['param'] = $message;
if (!empty($data)) {
$params['exPageInfo'] = $data;
}
} else {
$params['message'] = $message;
$params['param'] = $data;
}
if (!empty($exPageInfo)) {
$params['exPageInfo'] = $exPageInfo;
}
$params['count'] = $count;
if (is_numeric($data) || !is_numeric($count)) {
$params['count'] = $data;
$params['exPageInfo'] = $count;
}
if ((int)$params['count'] == -100) {
$params['count'] = 1;
}
return static::encode($params);
}
/**
* @param Throwable|Error $throwable
* @return bool|string
*/
public static function error(Throwable|Error $throwable): bool|string
{
$array['code'] = $throwable->getCode() == 0 ? 500 : $throwable->getCode();
$array['message'] = $throwable->getMessage();
$array['param'] = [
'file' => $throwable->getFile(),
'line' => $throwable->getLine()
];
return Json::encode($array);
}
/**
* @param $state
* @param $body
* @return false|int|string
* @throws Exception
*/
public static function output($state, $body): bool|int|string
{
$params['state'] = $state;
$params['body'] = ArrayAccess::toArray($body);
return static::encode($params);
}
}
+18
View File
@@ -0,0 +1,18 @@
<?php
namespace Kiri\Core;
class Network
{
/**
* @return string
*/
public static function local(): string
{
return current(swoole_get_local_ip());
}
}
+31 -31
View File
@@ -1,31 +1,31 @@
<?php
namespace Kiri\Core;
class Number
{
/**
* @param int $userId
* @return string
*/
public static function order(int $userId): string
{
$explode = current(explode(' ', str_replace('0.', '', microtime())));
return 'No.' . sprintf('%010d', $userId) . '.' . date('Ymd.His') . '.' . $explode;
}
/**
* @param int $userId
* @return string
*/
public static function create(int $userId): string
{
return static::order($userId);
}
}
<?php
namespace Kiri\Core;
class Number
{
/**
* @param int $userId
* @return string
*/
public static function order(int $userId): string
{
$explode = current(explode(' ', str_replace('0.', '', microtime())));
return 'No.' . sprintf('%010d', $userId) . '.' . date('Ymd.His') . '.' . $explode;
}
/**
* @param int $userId
* @return string
*/
public static function create(int $userId): string
{
return static::order($userId);
}
}
+172 -172
View File
@@ -1,172 +1,172 @@
<?php
declare(strict_types=1);
namespace Kiri\Core;
/**
* Class Reader
* @package Kiri\Kiri\Core
*/
class Reader
{
/**
* @param $filepath
* @param int $page
* @param int $size
* @return array and int
*/
public static function readerServerLogPagination($filepath, int $page = 1, int $size = 20): array
{
$count = 0;
$strings = [];
$offset = ($page - 1) * $size;
if (!file_exists($filepath)) {
return [0, []];
}
//只读方式打开文件
$fp = fopen($filepath, "r");
//开始循环读取$buffer_size
while (!feof($fp)) {
//读文件到缓冲区
$buffer = fgets($fp);
$count++;
if ($count > $offset && count($strings) < $size) {
$strings[] = [
'id' => $count,
'content' => $buffer
];
}
}
//关闭文件
fclose($fp);
unset($fp);
return ['total' => $count, 'list' => $strings];
}
/**
* @param $filename
* @param $start
* @param $lines
* @return array
*/
public static function read_backward_line($filename, $start, $lines): array
{
$lines++;
$offset = -1;
$read = '';
$fp = @fopen($filename, "r");
$tmpStart = 0;
while ($lines && fseek($fp, $offset, SEEK_END) >= 0) {
$c = fgetc($fp);
if ($c == "\n" || $c == "\r") {
if (++$tmpStart >= $start)
$lines--;
}
if ($tmpStart >= $start)
$read .= $c;
$offset--;
}
$read = trim($read);
$contents = [];
$read = array_reverse(explode("\n", strrev($read)));
foreach ($read as $key => $value) {
if (empty($value)) {
unset($read[$key]);
} else {
$contents[] = ['content' => $value, 'id' => $key + $start];
}
}
$response['total'] = self::read_count_by_file($filename);
$response['list'] = $contents;
return $response;
}
/**
* @param $filepath
* @return int
*/
private static function read_count_by_file($filepath): int
{
$count = 0;
//只读方式打开文件
$fp = fopen($filepath, "r");
//开始循环读取$buffer_size
while (fgets($fp)) {
$count++;
}
//关闭文件
fclose($fp);
unset($fp);
return $count;
}
/**
* @param $filepath
* @param int $page
* @param int $size
* @return array
*/
public static function folderPagination($filepath, int $page = 1, int $size = 20): array
{
$count = 0;
$strings = [];
$offset = ($page - 1) * $size;
if (!is_dir($filepath)) {
return [0, []];
}
foreach (glob($filepath . '/*') as $key => $value) {
$count++;
if ($key < $offset || count($strings) >= $size) {
continue;
}
$explode = explode(DIRECTORY_SEPARATOR, $value);
$addTime = fileatime($value);
$changeTime = filectime($value);
$modifyTime = filemtime($value);
$strings[] = [
'id' => $count,
'path' => $value,
'isDir' => (int)is_dir($value),
'name' => end($explode),
'atime' => [
'format' => date('Y-m-d H:i:s', $addTime),
'microtime' => $addTime
],
'ctime' => [
'format' => date('Y-m-d H:i:s', $changeTime),
'microtime' => $changeTime
],
'mtime' => [
'format' => date('Y-m-d H:i:s', $modifyTime),
'microtime' => $modifyTime
],
];
}
array_multisort($strings, array_column($strings, 'isDir'), SORT_DESC);
return ['total' => $count, 'list' => $strings];
}
}
<?php
declare(strict_types=1);
namespace Kiri\Core;
/**
* Class Reader
* @package Kiri\Kiri\Core
*/
class Reader
{
/**
* @param $filepath
* @param int $page
* @param int $size
* @return array and int
*/
public static function readerServerLogPagination($filepath, int $page = 1, int $size = 20): array
{
$count = 0;
$strings = [];
$offset = ($page - 1) * $size;
if (!file_exists($filepath)) {
return [0, []];
}
//只读方式打开文件
$fp = fopen($filepath, "r");
//开始循环读取$buffer_size
while (!feof($fp)) {
//读文件到缓冲区
$buffer = fgets($fp);
$count++;
if ($count > $offset && count($strings) < $size) {
$strings[] = [
'id' => $count,
'content' => $buffer
];
}
}
//关闭文件
fclose($fp);
unset($fp);
return ['total' => $count, 'list' => $strings];
}
/**
* @param $filename
* @param $start
* @param $lines
* @return array
*/
public static function read_backward_line($filename, $start, $lines): array
{
$lines++;
$offset = -1;
$read = '';
$fp = @fopen($filename, "r");
$tmpStart = 0;
while ($lines && fseek($fp, $offset, SEEK_END) >= 0) {
$c = fgetc($fp);
if ($c == "\n" || $c == "\r") {
if (++$tmpStart >= $start)
$lines--;
}
if ($tmpStart >= $start)
$read .= $c;
$offset--;
}
$read = trim($read);
$contents = [];
$read = array_reverse(explode("\n", strrev($read)));
foreach ($read as $key => $value) {
if (empty($value)) {
unset($read[$key]);
} else {
$contents[] = ['content' => $value, 'id' => $key + $start];
}
}
$response['total'] = self::read_count_by_file($filename);
$response['list'] = $contents;
return $response;
}
/**
* @param $filepath
* @return int
*/
private static function read_count_by_file($filepath): int
{
$count = 0;
//只读方式打开文件
$fp = fopen($filepath, "r");
//开始循环读取$buffer_size
while (fgets($fp)) {
$count++;
}
//关闭文件
fclose($fp);
unset($fp);
return $count;
}
/**
* @param $filepath
* @param int $page
* @param int $size
* @return array
*/
public static function folderPagination($filepath, int $page = 1, int $size = 20): array
{
$count = 0;
$strings = [];
$offset = ($page - 1) * $size;
if (!is_dir($filepath)) {
return [0, []];
}
foreach (glob($filepath . '/*') as $key => $value) {
$count++;
if ($key < $offset || count($strings) >= $size) {
continue;
}
$explode = explode(DIRECTORY_SEPARATOR, $value);
$addTime = fileatime($value);
$changeTime = filectime($value);
$modifyTime = filemtime($value);
$strings[] = [
'id' => $count,
'path' => $value,
'isDir' => (int)is_dir($value),
'name' => end($explode),
'atime' => [
'format' => date('Y-m-d H:i:s', $addTime),
'microtime' => $addTime
],
'ctime' => [
'format' => date('Y-m-d H:i:s', $changeTime),
'microtime' => $changeTime
],
'mtime' => [
'format' => date('Y-m-d H:i:s', $modifyTime),
'microtime' => $modifyTime
],
];
}
array_multisort($strings, array_column($strings, 'isDir'), SORT_DESC);
return ['total' => $count, 'list' => $strings];
}
}
+283 -283
View File
@@ -1,283 +1,283 @@
<?php
declare(strict_types=1);
namespace Kiri\Core;
use Exception;
/**
* Class Str
* @package Kiri\Kiri\Core
*/
class Str
{
const STRING = 'abcdefghijklmnopqrstuvwxyz';
const NUMBER = '01234567890';
/**
* @param int $length
*
* @return string
* 获取随机字符串
*/
public static function rand(int $length = 20): string
{
$string = '';
if ($length < 1) $length = 20;
$default = self::STRING . strtoupper(self::STRING) . self::NUMBER;
$default = str_split($default);
for ($i = 0; $i < $length; $i++) {
shuffle($default);
$string .= $default[array_rand($default)];
}
return $string;
}
/**
* @param int $length
*
* @return int|string 获取随机数字
* 获取随机数字
*/
public static function random(int $length = 20): int|string
{
$number = '';
$default = str_split(self::NUMBER);
if ($length < 1) $length = 1;
for ($i = 0; $i < $length; $i++) {
shuffle($default);
$number .= $default[array_rand($default)];
}
return $number;
}
/**
* @param $string
* @param $sullen
* @param bool $strip_tags
* @param string $append
*
* @return string
*/
public static function cut_str_utf8($string, $sullen, bool $strip_tags = TRUE, string $append = '...'): string
{
if ($strip_tags) {
$string = strip_tags($string);
}//去掉签标
$pa = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xef][\x80-\xbf][\x80-\xbf]|\xf0[\x90-\xbf][\x80-\xbf][\x80-\xbf]|[\xf1-\xf7][\x80-\xbf][\x80-\xbf][\x80-\xbf]/";
preg_match_all($pa, $string, $t_string);
$str = "";
for ($i = 0; $i < count($t_string[0]); $i++) {
$str .= $t_string[0][$i];
//转为gbk,一个汉字长度为2
if (strlen(@iconv('utf-8', 'gbk', $str)) >= $sullen) {
if ($i != count($t_string[0]) - 1) $str .= $append;
break;
}
}
return $str;
}
/**
* @param $data
*
* @param null $callback
* @return bool
* 判断是否为json字符串
*/
public static function isJson($data, $callback = NULL): bool
{
$json = !is_null(json_decode($data)) && !is_numeric($data);
if ($json && is_callable($callback, TRUE)) {
return call_user_func($callback, $data);
}
return $json;
}
/**
* @param $data
*
* @param null $callBack
* @return bool
* 判断是否序列化字符串
*/
public static function isSerialize($data, $callBack = NULL): bool
{
$false = !empty($data) && swoole_unserialize($data) !== FALSE;
if ($false && is_callable($callBack, TRUE)) {
return call_user_func($callBack, $data);
}
return $false;
}
/**
* @param $string
* @param int $length
*
* @param string $append
* @return string
*/
public static function cut($string, int $length = 20, string $append = '...'): string
{
if (empty($string)) {
return '';
}
if ($length < 1) {
$length = 1;
}
$array = str_split($string);
if (count($array) <= $length) {
return implode('', $array);
}
$string = implode('', array_slice($array, 0, $length));
if (!empty($append)) {
$string .= $append;
}
return $string;
}
/**
* @param $str
* @param int $number
* @param string $key
*
* @return string
*/
public static function encrypt($str, int $number = 10, string $key = 'xshucai.com'): string
{
$res = [];
$add = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$len = strlen($key) < 0 ? 1 : (strlen($key) + 5 > strlen($add) ? strlen($add) - 5 : strlen($key));
if ($number < 1) $number = 10;
$array = str_split($str);
asort($array);
$str = implode('', $array);
for ($i = 0; $i < $number; $i++) {
$_tmp = md5($key) . md5($str) . mb_substr($add, $len, $len + 5, 'utf-8');
$res[] = md5($_tmp);
}
sort($res, SORT_STRING);
return hash('sha384', implode('', $res));
}
/**
* @param $file
* @param $type
* @return string
*/
public static function filename($file, $type): string
{
switch ($type) {
case 'image/png':
return md5_file($file) . '.png';
case 'image/jpeg':
case 'image/jpg':
return md5_file($file) . '.jpg';
case 'image/gif':
return md5_file($file) . '.gif';
break;
}
return md5_file($file);
}
/**
* @param $endTime
* @param int|null $startTime
* @return array
* 剩余天,带分秒
*/
public static function timeout($endTime, int $startTime = NULL): array
{
$endTime = $endTime - (!empty($startTime) ? $startTime : time());
$day = intval($endTime / (3600 * 24));
$hours = intval(($endTime - ($day * (3600 * 24))) / 3600);
$minute = intval(($endTime - ($day * (3600 * 24) + $hours * 3600)) / 60);
$scrod = intval(($endTime - ($day * (3600 * 24) + $hours * 3600 + $minute * 60)));
return [$day, $hours, $minute, $scrod];
}
/**
* @return false|int
*/
public static function get_sy_time(): bool|int
{
$time = strtotime('+1days', strtotime(date('Y-m-d')));
return $time - time();
}
/**
* @param string $string
* @return string
*/
public static function encode(string $string): string
{
return addslashes($string);
}
/**
* @param string $string
* @return string|string[]|null
* 清除标点符号
*/
public static function clear(string $string): array|string|null
{
$char = '。、!?:;﹑•"…‘’“”〝〞∕¦‖— 〈〉﹞﹝「」‹›〖〗】【»«』『〕〔》《﹐¸﹕︰﹔!¡?¿﹖﹌﹏﹋'´ˊˋ―﹫︳︴¯_ ̄﹢﹦﹤‐­˜﹟﹩﹠﹪﹡﹨﹍﹉﹎﹊ˇ︵︶︷︸︹︿﹀︺︽︾ˉ﹁﹂﹃﹄︻︼()';
return preg_replace(["/[[:punct:]]/i", '/[' . $char . ']/u', '/[ ]{2,}/'], '', $string);
}
/**
* @param int $user
* @param array $param
* @param null $requestTime
*
* @return string
* @throws Exception
*/
public static function token(int $user, array $param = [], $requestTime = NULL): string
{
$str = '';
if (!$requestTime) {
$requestTime = microtime(TRUE);
}
$_user = str_split(md5($user . md5((string)$user)));
ksort($_user);
foreach ($_user as $key => $val) {
$str .= md5(sha1($key . $val . 'www.xshucai.com'));
}
if (is_array($param)) {
foreach ($param as $key => $val) {
$str .= md5($str . sha1($key . md5($val)));
}
}
$str .= sha1(base64_encode((string)$requestTime));
$md5 = md5($str . $user);
return preg_replace('/(\w{10})(\w{3})(\w{4})(\w{9})(\w{6})/', '$1-$2-$3-$4-$5', $md5);
}
/**
* @param string $str
* @param bool $unfairest
* @return string
*/
public static function convertUnderline(string $str, bool $unfairest = TRUE): string
{
$str = ucwords(str_replace('_', ' ', $str));
$str = str_replace(' ', '', lcfirst($str));
return $unfairest ? ucfirst($str) : $str;
}
}
<?php
declare(strict_types=1);
namespace Kiri\Core;
use Exception;
/**
* Class Str
* @package Kiri\Kiri\Core
*/
class Str
{
const STRING = 'abcdefghijklmnopqrstuvwxyz';
const NUMBER = '01234567890';
/**
* @param int $length
*
* @return string
* 获取随机字符串
*/
public static function rand(int $length = 20): string
{
$string = '';
if ($length < 1) $length = 20;
$default = self::STRING . strtoupper(self::STRING) . self::NUMBER;
$default = str_split($default);
for ($i = 0; $i < $length; $i++) {
shuffle($default);
$string .= $default[array_rand($default)];
}
return $string;
}
/**
* @param int $length
*
* @return int|string 获取随机数字
* 获取随机数字
*/
public static function random(int $length = 20): int|string
{
$number = '';
$default = str_split(self::NUMBER);
if ($length < 1) $length = 1;
for ($i = 0; $i < $length; $i++) {
shuffle($default);
$number .= $default[array_rand($default)];
}
return $number;
}
/**
* @param $string
* @param $sullen
* @param bool $strip_tags
* @param string $append
*
* @return string
*/
public static function cut_str_utf8($string, $sullen, bool $strip_tags = TRUE, string $append = '...'): string
{
if ($strip_tags) {
$string = strip_tags($string);
}//去掉签标
$pa = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xef][\x80-\xbf][\x80-\xbf]|\xf0[\x90-\xbf][\x80-\xbf][\x80-\xbf]|[\xf1-\xf7][\x80-\xbf][\x80-\xbf][\x80-\xbf]/";
preg_match_all($pa, $string, $t_string);
$str = "";
for ($i = 0; $i < count($t_string[0]); $i++) {
$str .= $t_string[0][$i];
//转为gbk,一个汉字长度为2
if (strlen(@iconv('utf-8', 'gbk', $str)) >= $sullen) {
if ($i != count($t_string[0]) - 1) $str .= $append;
break;
}
}
return $str;
}
/**
* @param $data
*
* @param null $callback
* @return bool
* 判断是否为json字符串
*/
public static function isJson($data, $callback = NULL): bool
{
$json = !is_null(json_decode($data)) && !is_numeric($data);
if ($json && is_callable($callback, TRUE)) {
return call_user_func($callback, $data);
}
return $json;
}
/**
* @param $data
*
* @param null $callBack
* @return bool
* 判断是否序列化字符串
*/
public static function isSerialize($data, $callBack = NULL): bool
{
$false = !empty($data) && swoole_unserialize($data) !== FALSE;
if ($false && is_callable($callBack, TRUE)) {
return call_user_func($callBack, $data);
}
return $false;
}
/**
* @param $string
* @param int $length
*
* @param string $append
* @return string
*/
public static function cut($string, int $length = 20, string $append = '...'): string
{
if (empty($string)) {
return '';
}
if ($length < 1) {
$length = 1;
}
$array = str_split($string);
if (count($array) <= $length) {
return implode('', $array);
}
$string = implode('', array_slice($array, 0, $length));
if (!empty($append)) {
$string .= $append;
}
return $string;
}
/**
* @param $str
* @param int $number
* @param string $key
*
* @return string
*/
public static function encrypt($str, int $number = 10, string $key = 'xshucai.com'): string
{
$res = [];
$add = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$len = strlen($key) < 0 ? 1 : (strlen($key) + 5 > strlen($add) ? strlen($add) - 5 : strlen($key));
if ($number < 1) $number = 10;
$array = str_split($str);
asort($array);
$str = implode('', $array);
for ($i = 0; $i < $number; $i++) {
$_tmp = md5($key) . md5($str) . mb_substr($add, $len, $len + 5, 'utf-8');
$res[] = md5($_tmp);
}
sort($res, SORT_STRING);
return hash('sha384', implode('', $res));
}
/**
* @param $file
* @param $type
* @return string
*/
public static function filename($file, $type): string
{
switch ($type) {
case 'image/png':
return md5_file($file) . '.png';
case 'image/jpeg':
case 'image/jpg':
return md5_file($file) . '.jpg';
case 'image/gif':
return md5_file($file) . '.gif';
break;
}
return md5_file($file);
}
/**
* @param $endTime
* @param int|null $startTime
* @return array
* 剩余天,带分秒
*/
public static function timeout($endTime, int $startTime = NULL): array
{
$endTime = $endTime - (!empty($startTime) ? $startTime : time());
$day = intval($endTime / (3600 * 24));
$hours = intval(($endTime - ($day * (3600 * 24))) / 3600);
$minute = intval(($endTime - ($day * (3600 * 24) + $hours * 3600)) / 60);
$scrod = intval(($endTime - ($day * (3600 * 24) + $hours * 3600 + $minute * 60)));
return [$day, $hours, $minute, $scrod];
}
/**
* @return false|int
*/
public static function get_sy_time(): bool|int
{
$time = strtotime('+1days', strtotime(date('Y-m-d')));
return $time - time();
}
/**
* @param string $string
* @return string
*/
public static function encode(string $string): string
{
return addslashes($string);
}
/**
* @param string $string
* @return string|string[]|null
* 清除标点符号
*/
public static function clear(string $string): array|string|null
{
$char = '。、!?:;﹑•"…‘’“”〝〞∕¦‖— 〈〉﹞﹝「」‹›〖〗】【»«』『〕〔》《﹐¸﹕︰﹔!¡?¿﹖﹌﹏﹋'´ˊˋ―﹫︳︴¯_ ̄﹢﹦﹤‐­˜﹟﹩﹠﹪﹡﹨﹍﹉﹎﹊ˇ︵︶︷︸︹︿﹀︺︽︾ˉ﹁﹂﹃﹄︻︼()';
return preg_replace(["/[[:punct:]]/i", '/[' . $char . ']/u', '/[ ]{2,}/'], '', $string);
}
/**
* @param int $user
* @param array $param
* @param null $requestTime
*
* @return string
* @throws Exception
*/
public static function token(int $user, array $param = [], $requestTime = NULL): string
{
$str = '';
if (!$requestTime) {
$requestTime = microtime(TRUE);
}
$_user = str_split(md5($user . md5((string)$user)));
ksort($_user);
foreach ($_user as $key => $val) {
$str .= md5(sha1($key . $val . 'www.xshucai.com'));
}
if (is_array($param)) {
foreach ($param as $key => $val) {
$str .= md5($str . sha1($key . md5($val)));
}
}
$str .= sha1(base64_encode((string)$requestTime));
$md5 = md5($str . $user);
return preg_replace('/(\w{10})(\w{3})(\w{4})(\w{9})(\w{6})/', '$1-$2-$3-$4-$5', $md5);
}
/**
* @param string $str
* @param bool $unfairest
* @return string
*/
public static function convertUnderline(string $str, bool $unfairest = TRUE): string
{
$str = ucwords(str_replace('_', ' ', $str));
$str = str_replace(' ', '', lcfirst($str));
return $unfairest ? ucfirst($str) : $str;
}
}
+57 -57
View File
@@ -1,57 +1,57 @@
<?php
/**
* Created by PhpStorm.
* User: admin
* Date: 2019-03-20
* Time: 01:03
*/
declare(strict_types=1);
namespace Kiri\Core;
use Exception;
/**
* Class Xml
* @package Kiri\Kiri\Core
*/
class Xml
{
/**
* @param $data
* @param bool $asArray
* @return array|object
* @throws Exception
*/
public static function toArray($data, bool $asArray = true): object|array
{
$data = simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA);
if ($data === false) {
throw new Exception('Parameter format error.');
}
$array = get_object_vars($data);
if (isset($array[0])) {
$array[$data->getName()] = $array[0];
unset($array[0]);
}
return $array;
}
/**
* @param $str
* @return array|bool|object
* @throws Exception
*/
public static function isXml($str): object|bool|array
{
$xml_parser = xml_parser_create();
if (!xml_parse($xml_parser, $str, true)) {
xml_parser_free($xml_parser);
return false;
} else {
return self::toArray($str);
}
}
}
<?php
/**
* Created by PhpStorm.
* User: admin
* Date: 2019-03-20
* Time: 01:03
*/
declare(strict_types=1);
namespace Kiri\Core;
use Exception;
/**
* Class Xml
* @package Kiri\Kiri\Core
*/
class Xml
{
/**
* @param $data
* @param bool $asArray
* @return array|object
* @throws Exception
*/
public static function toArray($data, bool $asArray = true): object|array
{
$data = simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA);
if ($data === false) {
throw new Exception('Parameter format error.');
}
$array = get_object_vars($data);
if (isset($array[0])) {
$array[$data->getName()] = $array[0];
unset($array[0]);
}
return $array;
}
/**
* @param $str
* @return array|bool|object
* @throws Exception
*/
public static function isXml($str): object|bool|array
{
$xml_parser = xml_parser_create();
if (!xml_parse($xml_parser, $str, true)) {
xml_parser_free($xml_parser);
return false;
} else {
return self::toArray($str);
}
}
}
+450 -461
View File
@@ -1,461 +1,450 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/4/24 0024
* Time: 17:27
*/
declare(strict_types=1);
namespace Kiri\Di;
use Annotation\Inject;
use Closure;
use Exception;
use Kiri\Abstracts\BaseObject;
use Kiri\Abstracts\Logger;
use Kiri\Kiri;
use Psr\Log\LoggerInterface;
use ReflectionClass;
use ReflectionException;
use ReflectionFunction;
use ReflectionMethod;
use ReflectionProperty;
use Psr\Container\ContainerInterface;
/**
* Class Container
* @package Kiri\Di
*/
class Container extends BaseObject implements ContainerInterface
{
/**
* @var array
*
* instance class by className
*/
private array $_singletons = [];
/**
* @var ReflectionMethod[]
*
* class new instance construct parameter
*/
private array $_constructs = [];
/**
* @var array
*
* implements \ReflectClass
*/
private array $_reflection = [];
/** @var array */
private array $_parameters = [];
/** @var array|string[] */
private array $_interfaces = [
LoggerInterface::class => Logger::class
];
/**
* @param string $id
* @return mixed
* @throws ReflectionException
*/
public function get(string $id): mixed
{
return $this->make($id, [], []);
}
/**
* @param $class
* @param array $constrict
* @param array $config
* @return mixed
* @throws ReflectionException
* @throws Exception
*/
public function make($class, array $constrict = [], array $config = []): mixed
{
if ($this->isInterface($class)) {
$class = $this->_interfaces[$class];
}
if (!isset($this->_singletons[$class])) {
$this->_singletons[$class] = $this->resolve($class, $constrict, $config);
}
return $this->_singletons[$class];
}
/**
* @param string $interface
* @param string $class
*/
public function mapping(string $interface, string $class)
{
$this->_interfaces[$interface] = $class;
}
/**
* @param $class
* @return bool
* @throws ReflectionException
*/
public function isInterface($class): bool
{
$reflect = $this->getReflect($class);
if ($reflect->isInterface()) {
return true;
}
return false;
}
/**
* @param string $interface
* @param $object
*/
public function setBindings(string $interface, $object)
{
if (is_string($object)) {
$this->_interfaces[$interface] = $object;
} else {
$className = get_class($object);
$this->_interfaces[$interface] = $className;
$this->_singletons[$className] = $object;
}
}
/**
* @param $class
* @param array $constrict
* @param array $config
* @return object
* @throws
*/
public function create($class, array $constrict = [], array $config = []): object
{
return $this->resolve($class, $constrict, $config);
}
/**
* @param $class
* @param $constrict
* @param $config
*
* @return object
* @throws Exception
*/
private function resolve($class, $constrict, $config): object
{
$reflect = $this->resolveDependencies($class);
if (!$reflect->isInstantiable()) {
throw new ReflectionException('Class ' . $class . ' cannot be instantiated');
}
$object = $this->newInstance($reflect, $constrict);
$this->propertyInject($reflect, $object);
return $this->onAfterInit($object, $config);
}
/**
* @param ReflectionClass $reflect
* @param $dependencies
* @return object
* @throws ReflectionException
*/
private function newInstance(ReflectionClass $reflect, $dependencies): object
{
if (!isset($this->_constructs[$reflect->getName()])) {
return $reflect->newInstance();
}
$construct = $this->_constructs[$reflect->getName()];
if ($construct->getNumberOfParameters() < 1) {
return $reflect->newInstance();
}
$parameters = $this->mergeParam($this->resolveMethodParameters($construct), $dependencies);
return $reflect->newInstanceArgs($parameters);
}
/**
* @param ReflectionClass $reflect
* @param $object
* @return mixed
* @throws Exception
*/
public function propertyInject(ReflectionClass $reflect, $object): mixed
{
foreach (NoteManager::getPropertyNote($reflect) as $property => $inject) {
/** @var Inject $inject */
$inject->execute($object, $property);
}
return $object;
}
/**
* @param $className
* @param $method
* @return array
* @throws ReflectionException
*/
public function getMethodAttribute($className, $method = null): array
{
$methods = NoteManager::getMethodNote($this->getReflect($className));
if (!empty($method)) {
return $methods[$method] ?? [];
}
return $methods;
}
/**
* @param string $class
* @param string|null $property
* @return ReflectionProperty|ReflectionProperty[]|null
* @throws ReflectionException
*/
public function getClassReflectionProperty(string $class, string $property = null): ReflectionProperty|null|array
{
$lists = NoteManager::getProperty($this->getReflect($class));
if (empty($lists)) {
return null;
}
if (!empty($property)) {
return $lists[$property] ?? null;
}
return $lists;
}
/**
* @param $object
* @param $config
* @return mixed
*/
private function onAfterInit($object, $config): mixed
{
Kiri::configure($object, $config);
if (method_exists($object, 'init') && is_callable([$object, 'init'])) {
call_user_func([$object, 'init']);
}
return $object;
}
/**
* @param $class
* @return ReflectionClass
* @throws ReflectionException
*/
private function resolveDependencies($class): ReflectionClass
{
if (isset($this->_reflection[$class])) {
return $this->_reflection[$class];
}
$reflect = new ReflectionClass($class);
if ($reflect->isAbstract() || $reflect->isTrait() || $reflect->isInterface()) {
return $this->_reflection[$class] = $reflect;
}
$construct = NoteManager::resolveTarget($reflect);
if (!empty($construct) && $construct->getNumberOfParameters() > 0) {
$this->_constructs[$class] = $construct;
}
return $this->_reflection[$class] = $reflect;
}
/**
* @param ReflectionClass|string $class
* @return ReflectionMethod[]
* @throws ReflectionException
*/
public function getReflectMethods(ReflectionClass|string $class): array
{
if (is_string($class)) {
$class = $this->getReflect($class);
}
return NoteManager::getMethods($class);
}
/**
* @param ReflectionClass|string $class
* @param string $method
* @return ReflectionMethod|null
* @throws ReflectionException
*/
public function getReflectMethod(ReflectionClass|string $class, string $method): ?ReflectionMethod
{
return $this->getReflectMethods($class)[$method] ?? null;
}
/**
* @param string $className
* @param string $method
* @return array|null
* @throws ReflectionException
*/
public function getMethodParameters(string $className, string $method): ?array
{
if (isset($this->_parameters[$className]) && isset($this->_parameters[$className][$method])) {
return $this->_parameters[$className][$method];
}
$reflectMethod = $this->getReflectMethod($this->getReflect($className), $method);
if (!($reflectMethod instanceof ReflectionMethod)) {
throw new ReflectionException("Class does not have a function $className::$method");
}
$className = $reflectMethod->getDeclaringClass()->getName();
if (isset($this->_parameters[$className]) && isset($this->_parameters[$className][$reflectMethod->getName()])) {
return $this->_parameters[$className][$reflectMethod->getName()];
}
return $this->setParameters($className, $reflectMethod->getName(), $this->resolveMethodParameters($reflectMethod));
}
/**
* @param $class
* @param $method
* @param $parameters
* @return mixed
*/
private function setParameters($class, $method, $parameters): mixed
{
if (!isset($this->_parameters[$class])) {
$this->_parameters[$class] = [];
}
if (!isset($this->_parameters[$class][$method])) {
$this->_parameters[$class][$method] = [];
}
return $this->_parameters[$class][$method] = $parameters;
}
/**
* @param Closure $reflectionMethod
* @return array
* @throws ReflectionException
*/
public function getFunctionParameters(Closure $reflectionMethod): array
{
return $this->resolveMethodParameters(new ReflectionFunction($reflectionMethod));
}
/**
* @param ReflectionMethod|ReflectionFunction $reflectionMethod
* @return array
* @throws ReflectionException
*/
private function resolveMethodParameters(ReflectionMethod|ReflectionFunction $reflectionMethod): array
{
if ($reflectionMethod->getNumberOfParameters() < 1) {
return [];
}
$params = [];
foreach ($reflectionMethod->getParameters() as $key => $parameter) {
if ($parameter->isDefaultValueAvailable()) {
$params[$key] = $parameter->getDefaultValue();
} else if ($parameter->getType() === null) {
$params[$key] = $parameter->getType();
} else {
$type = $parameter->getType()->getName();
if (is_string($type) && class_exists($type) || isset($this->_interfaces[$type])) {
$type = Kiri::getDi()->get($type);
}
$params[$key] = match ($parameter->getType()) {
'string' => '',
'int', 'float' => 0,
'', null, 'object', 'mixed' => NULL,
'bool' => false,
default => $type
};
}
}
return $params;
}
/**
* @param $class
* @return ReflectionClass|null
* @throws ReflectionException
*/
public function getReflect($class): ?ReflectionClass
{
if (!isset($this->_reflection[$class])) {
return $this->resolveDependencies($class);
}
return $this->_reflection[$class];
}
/**
* @param $class
*/
public function unset($class)
{
if (is_array($class) && isset($class['class'])) {
$class = $class['class'];
} else if (is_object($class)) {
$class = $class::class;
}
unset(
$this->_reflection[$class], $this->_singletons[$class], $this->_constructs[$class]
);
}
/**
* @return $this
*/
public function flush(): static
{
$this->_reflection = [];
$this->_singletons = [];
$this->_constructs = [];
return $this;
}
/**
* @param $old
* @param $newParam
*
* @return mixed
*/
private function mergeParam($old, $newParam): array
{
if (empty($old)) {
return $newParam;
} else if (empty($newParam)) {
return $old;
}
foreach ($newParam as $key => $val) {
$old[$key] = $val;
}
return $old;
}
/**
* @param string $id
* @return bool
*/
public function has(string $id): bool
{
return isset($this->_singletons[$id]) || isset($this->_interfaces[$id]);
}
}
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/4/24 0024
* Time: 17:27
*/
declare(strict_types=1);
namespace Kiri\Di;
use Kiri\Annotation\Inject;
use Closure;
use Exception;
use Kiri\Abstracts\Logger;
use Kiri\Kiri;
use Psr\Log\LoggerInterface;
use ReflectionClass;
use ReflectionException;
use ReflectionFunction;
use ReflectionMethod;
use ReflectionProperty;
use Psr\Container\ContainerInterface;
/**
* Class Container
* @package Kiri\Di
*/
class Container implements ContainerInterface
{
/**
* @var array
*
* instance class by className
*/
private array $_singletons = [];
/**
* @var ReflectionMethod[]
*
* class new instance construct parameter
*/
private array $_constructs = [];
/**
* @var array
*
* implements \ReflectClass
*/
private array $_reflection = [];
/** @var array */
private array $_parameters = [];
/** @var array|string[] */
private array $_interfaces = [
LoggerInterface::class => Logger::class
];
/**
* @param string $id
* @return mixed
* @throws
*/
public function get(string $id): mixed
{
return $this->make($id, [], []);
}
/**
* @param $class
* @param array $constrict
* @param array $config
* @return mixed
* @throws
*/
public function make($class, array $constrict = [], array $config = []): mixed
{
if ($this->isInterface($class)) {
$class = $this->_interfaces[$class];
}
if (!isset($this->_singletons[$class])) {
$this->_singletons[$class] = $this->resolve($class, $constrict, $config);
}
return $this->_singletons[$class];
}
/**
* @param string $interface
* @param string $class
*/
public function mapping(string $interface, string $class)
{
$this->_interfaces[$interface] = $class;
}
/**
* @param $class
* @return bool
*/
public function isInterface($class): bool
{
$reflect = $this->getReflect($class);
if ($reflect->isInterface()) {
return true;
}
return false;
}
/**
* @param string $interface
* @param $object
*/
public function setBindings(string $interface, $object)
{
if (is_string($object)) {
$this->_interfaces[$interface] = $object;
} else {
$className = get_class($object);
$this->_interfaces[$interface] = $className;
$this->_singletons[$className] = $object;
}
}
/**
* @param $class
* @param array $constrict
* @param array $config
* @return object
* @throws
*/
public function create($class, array $constrict = [], array $config = []): object
{
return $this->resolve($class, $constrict, $config);
}
/**
* @param $class
* @param $constrict
* @param $config
*
* @return object
* @throws Exception
*/
private function resolve($class, $constrict, $config): object
{
$reflect = $this->resolveDependencies($class);
if (!$reflect->isInstantiable()) {
throw new ReflectionException('Class ' . $class . ' cannot be instantiated');
}
$object = $this->newInstance($reflect, $constrict);
$this->propertyInject($reflect, $object);
return $this->onAfterInit($object, $config);
}
/**
* @param ReflectionClass $reflect
* @param $dependencies
* @return object
* @throws ReflectionException
*/
private function newInstance(ReflectionClass $reflect, $dependencies): object
{
if (!isset($this->_constructs[$reflect->getName()])) {
return $reflect->newInstance();
}
$construct = $this->_constructs[$reflect->getName()];
if ($construct->getNumberOfParameters() < 1) {
return $reflect->newInstance();
}
$parameters = $this->mergeParam($this->resolveMethodParameters($construct), $dependencies);
return $reflect->newInstanceArgs($parameters);
}
/**
* @param ReflectionClass $reflect
* @param $object
* @return mixed
* @throws Exception
*/
public function propertyInject(ReflectionClass $reflect, $object): mixed
{
foreach (NoteManager::getPropertyAnnotation($reflect) as $property => $inject) {
/** @var Inject $inject */
$inject->execute($object, $property);
}
return $object;
}
/**
* @param $className
* @param $method
* @return array
*/
public function getMethodAttribute($className, $method = null): array
{
$methods = NoteManager::getMethodAnnotation($this->getReflect($className));
if (!empty($method)) {
return $methods[$method] ?? [];
}
return $methods;
}
/**
* @param string $class
* @param string|null $property
* @return ReflectionProperty|ReflectionProperty[]|null
*/
public function getClassReflectionProperty(string $class, string $property = null): ReflectionProperty|null|array
{
$lists = NoteManager::getProperty($this->getReflect($class));
if (empty($lists)) {
return null;
}
if (!empty($property)) {
return $lists[$property] ?? null;
}
return $lists;
}
/**
* @param $object
* @param $config
* @return mixed
*/
private function onAfterInit($object, $config): mixed
{
Kiri::configure($object, $config);
if (method_exists($object, 'init') && is_callable([$object, 'init'])) {
call_user_func([$object, 'init']);
}
return $object;
}
/**
* @param $class
* @return ReflectionClass
*/
private function resolveDependencies($class): ReflectionClass
{
if (isset($this->_reflection[$class])) {
return $this->_reflection[$class];
}
$reflect = new ReflectionClass($class);
if ($reflect->isAbstract() || $reflect->isTrait() || $reflect->isInterface()) {
return $this->_reflection[$class] = $reflect;
}
$construct = NoteManager::resolveTarget($reflect);
if (!empty($construct) && $construct->getNumberOfParameters() > 0) {
$this->_constructs[$class] = $construct;
}
return $this->_reflection[$class] = $reflect;
}
/**
* @param ReflectionClass|string $class
* @return ReflectionMethod[]
* @throws ReflectionException
*/
public function getReflectMethods(ReflectionClass|string $class): array
{
if (is_string($class)) {
$class = $this->getReflect($class);
}
return NoteManager::getMethods($class);
}
/**
* @param ReflectionClass|string $class
* @param string $method
* @return ReflectionMethod|null
* @throws ReflectionException
*/
public function getReflectMethod(ReflectionClass|string $class, string $method): ?ReflectionMethod
{
return $this->getReflectMethods($class)[$method] ?? null;
}
/**
* @param string $className
* @param string $method
* @return array|null
* @throws ReflectionException
*/
public function getMethodParameters(string $className, string $method): ?array
{
if (isset($this->_parameters[$className]) && isset($this->_parameters[$className][$method])) {
return $this->_parameters[$className][$method];
}
$reflectMethod = $this->getReflectMethod($this->getReflect($className), $method);
if (!($reflectMethod instanceof ReflectionMethod)) {
throw new ReflectionException("Class does not have a function $className::$method");
}
$className = $reflectMethod->getDeclaringClass()->getName();
if (isset($this->_parameters[$className]) && isset($this->_parameters[$className][$reflectMethod->getName()])) {
return $this->_parameters[$className][$reflectMethod->getName()];
}
return $this->setParameters($className, $reflectMethod->getName(), $this->resolveMethodParameters($reflectMethod));
}
/**
* @param $class
* @param $method
* @param $parameters
* @return mixed
*/
private function setParameters($class, $method, $parameters): mixed
{
if (!isset($this->_parameters[$class])) {
$this->_parameters[$class] = [];
}
return $this->_parameters[$class][$method] = $parameters;
}
/**
* @param Closure $reflectionMethod
* @return array
* @throws ReflectionException
*/
public function getFunctionParameters(Closure $reflectionMethod): array
{
return $this->resolveMethodParameters(new ReflectionFunction($reflectionMethod));
}
/**
* @param ReflectionMethod|ReflectionFunction $reflectionMethod
* @return array
*/
private function resolveMethodParameters(ReflectionMethod|ReflectionFunction $reflectionMethod): array
{
if ($reflectionMethod->getNumberOfParameters() < 1) {
return [];
}
$params = [];
foreach ($reflectionMethod->getParameters() as $key => $parameter) {
if ($parameter->isDefaultValueAvailable()) {
$params[$key] = $parameter->getDefaultValue();
} else if ($parameter->getType() === null) {
$params[$key] = $parameter->getType();
} else {
$type = $parameter->getType()->getName();
if (is_string($type) && class_exists($type) || isset($this->_interfaces[$type])) {
$type = Kiri::getDi()->get($type);
}
$params[$key] = match ($parameter->getType()) {
'string' => '',
'int', 'float' => 0,
'', null, 'object', 'mixed' => NULL,
'bool' => false,
default => $type
};
}
}
return $params;
}
/**
* @param $class
* @return ReflectionClass|null
*/
public function getReflect($class): ?ReflectionClass
{
if (!isset($this->_reflection[$class])) {
return $this->resolveDependencies($class);
}
return $this->_reflection[$class];
}
/**
* @param $class
*/
public function unset($class)
{
if (is_array($class) && isset($class['class'])) {
$class = $class['class'];
} else if (is_object($class)) {
$class = $class::class;
}
unset(
$this->_reflection[$class], $this->_singletons[$class], $this->_constructs[$class]
);
}
/**
* @return $this
*/
public function flush(): static
{
$this->_reflection = [];
$this->_singletons = [];
$this->_constructs = [];
return $this;
}
/**
* @param $old
* @param $newParam
*
* @return mixed
*/
private function mergeParam($old, $newParam): array
{
if (empty($old)) {
return $newParam;
} else if (empty($newParam)) {
return $old;
}
foreach ($newParam as $key => $val) {
$old[$key] = $val;
}
return $old;
}
/**
* @param string $id
* @return bool
*/
public function has(string $id): bool
{
return isset($this->_singletons[$id]) || isset($this->_interfaces[$id]);
}
}
+88 -88
View File
@@ -1,88 +1,88 @@
<?php
namespace Kiri\Di;
use Kiri\Abstracts\Component;
use Kiri\Kiri;
/**
* 服务定位器
*/
class LocalService extends Component
{
private array $_components = [];
private array $_definition = [];
/**
* @param $name
* @param $define
*/
public function set($name, $define)
{
unset($this->_components[$name]);
$this->_definition[$name] = $define;
if (is_object($define) || $define instanceof \Closure) {
$this->_components[$name] = $define;
}
}
/**
* @throws \Exception
*/
public function get(string $name, $throwException = true)
{
if (isset($this->_components[$name])) {
return $this->_components[$name];
}
if (isset($this->_definition[$name])) {
$definition = $this->_definition[$name];
if (is_object($definition) && !$definition instanceof \Closure) {
return $this->_components[$name] = $definition;
}
return $this->_components[$name] = Kiri::createObject($definition);
} else if ($throwException) {
throw new \Exception("Unknown component ID: $name");
}
return null;
}
/**
* @param array $components
*/
public function setComponents(array $components)
{
foreach ($components as $name => $component) {
$this->set($name, $component);
}
}
/**
* @param $id
* @return bool
*/
public function has($id): bool
{
return isset($this->_components[$id]) || isset($this->_definition[$id]);
}
/**
* @param $id
*/
public function remove($id): void
{
unset($this->_components[$id], $this->_definition[$id]);
}
}
<?php
namespace Kiri\Di;
use Kiri\Abstracts\Component;
use Kiri\Kiri;
/**
* 服务定位器
*/
class LocalService extends Component
{
private array $_components = [];
private array $_definition = [];
/**
* @param $name
* @param $define
*/
public function set($name, $define)
{
unset($this->_components[$name]);
$this->_definition[$name] = $define;
if (is_object($define) || $define instanceof \Closure) {
$this->_components[$name] = $define;
}
}
/**
* @throws \Exception
*/
public function get(string $name, $throwException = true)
{
if (isset($this->_components[$name])) {
return $this->_components[$name];
}
if (isset($this->_definition[$name])) {
$definition = $this->_definition[$name];
if (is_object($definition) && !$definition instanceof \Closure) {
return $this->_components[$name] = $definition;
}
return $this->_components[$name] = Kiri::createObject($definition);
} else if ($throwException) {
throw new \Exception("Unknown component ID: $name");
}
return null;
}
/**
* @param array $components
*/
public function setComponents(array $components)
{
foreach ($components as $name => $component) {
$this->set($name, $component);
}
}
/**
* @param $id
* @return bool
*/
public function has($id): bool
{
return isset($this->_components[$id]) || isset($this->_definition[$id]);
}
/**
* @param $id
*/
public function remove($id): void
{
unset($this->_components[$id], $this->_definition[$id]);
}
}
+303 -289
View File
@@ -1,289 +1,303 @@
<?php
namespace Kiri\Di;
use JetBrains\PhpStorm\Pure;
use ReflectionAttribute;
use ReflectionClass;
use ReflectionProperty;
class NoteManager
{
private static array $_classTarget = [];
private static array $_classMethodNote = [];
private static array $_classMethod = [];
private static array $_classPropertyNote = [];
private static array $_classProperty = [];
private static array $_mapping = [];
/**
* @param ReflectionClass $class
*/
public static function setTargetNote(ReflectionClass $class)
{
$className = $class->getName();
if (!isset(static::$_classTarget[$className])) {
static::$_classTarget[$className] = [];
}
foreach ($class->getAttributes() as $attribute) {
if (!class_exists($attribute->getName())) {
continue;
}
$instance = $attribute->newInstance();
static::$_classTarget[$className][] = $instance;
self::setMappingClass($attribute, $className);
}
}
/**
* @param ReflectionAttribute $attribute
* @param string $class
*/
public static function setMappingClass(ReflectionAttribute $attribute, string $class)
{
if (!isset(static::$_mapping[$attribute->getName()])) {
static::$_mapping[$attribute->getName()] = [];
}
if (!isset(static::$_mapping[$attribute->getName()][$class])) {
static::$_mapping[$attribute->getName()][$class] = [];
}
}
/**
* @param ReflectionAttribute $attribute
* @param string $class
* @param string $method
* @param mixed $instance
*/
public static function setMappingMethod(ReflectionAttribute $attribute, string $class, string $method, mixed $instance)
{
self::setMappingClass($attribute, $class);
if (!isset(static::$_mapping[$attribute->getName()][$class]['method'])) {
static::$_mapping[$attribute->getName()][$class]['method'] = [];
}
static::$_mapping[$attribute->getName()][$class]['method'][] = [$method => $instance];
}
/**
* @param ReflectionAttribute $attribute
* @param string $class
* @param string $property
* @param $instance
*/
public static function setMappingProperty(ReflectionAttribute $attribute, string $class, string $property, $instance)
{
self::setMappingClass($attribute, $class);
$mapping = static::$_mapping[$attribute->getName()][$class];
if (!isset($mapping['property'])) {
$mapping['property'] = [];
}
$mapping['property'][] = [$property => $instance];
static::$_mapping[$attribute->getName()][$class] = $mapping;
}
/**
* @param mixed $class
* @return array
*/
public static function getTargetNote(mixed $class): array
{
if (!is_string($class)) {
$class = $class::class;
}
return static::$_classTarget[$class] ?? [];
}
/**
* @param ReflectionClass $class
*/
public static function setMethodNote(ReflectionClass $class)
{
$className = $class->getName();
static::$_classMethodNote[$className] = static::$_classMethod[$className] = [];
foreach ($class->getMethods() as $ReflectionMethod) {
static::$_classMethod[$className][$ReflectionMethod->getName()] = $ReflectionMethod;
static::$_classMethodNote[$className][$ReflectionMethod->getName()] = [];
foreach ($ReflectionMethod->getAttributes() as $attribute) {
if (!class_exists($attribute->getName())) {
continue;
}
$instance = $attribute->newInstance();
static::$_classMethodNote[$className][$ReflectionMethod->getName()][] = $instance;
self::setMappingMethod($attribute, $className, $ReflectionMethod->getName(), $instance);
}
}
}
/**
* @param string $class
* @param string $method
* @return bool
*/
public static function hasMethod(string $class, string $method): bool
{
return isset(static::$_classMethod[$class]) && isset(static::$_classMethod[$class][$method]);
}
/**
* @param ReflectionClass $class
* @return array
*/
#[Pure] public static function getMethodNote(ReflectionClass $class): array
{
return static::$_classMethodNote[$class->getName()] ?? [];
}
/**
* @param \ReflectionClass $reflect
* @return \ReflectionMethod|null
*/
public static function resolveTarget(ReflectionClass $reflect): ?\ReflectionMethod
{
NoteManager::setPropertyNote($reflect);
NoteManager::setTargetNote($reflect);
NoteManager::setMethodNote($reflect);
return $reflect->getConstructor();
}
/**
* @param ReflectionClass $class
*/
public static function setPropertyNote(ReflectionClass $class)
{
$className = $class->getName();
static::$_classProperty[$className] = static::$_classPropertyNote[$className] = [];
foreach ($class->getProperties(ReflectionProperty::IS_PRIVATE | ReflectionProperty::IS_PUBLIC |
ReflectionProperty::IS_PROTECTED) as $ReflectionMethod) {
static::$_classProperty[$className][$ReflectionMethod->getName()] = $ReflectionMethod;
foreach ($ReflectionMethod->getAttributes() as $attribute) {
if (!class_exists($attribute->getName())) {
continue;
}
$instance = $attribute->newInstance();
static::$_classPropertyNote[$className][$ReflectionMethod->getName()] = $instance;
self::setMappingProperty($attribute, $className, $ReflectionMethod->getName(), $instance);
}
}
}
/**
* @param string $attribute
* @param string|null $class
* @return array[]
*/
public static function getAttributeTrees(string $attribute, string $class = null): array
{
$mapping = static::$_mapping[$attribute] ?? [];
if (empty($mapping) || empty($class)) {
return $mapping;
}
return $mapping[$class] ?? [];
}
/**
* @param string $attribute
* @param string $class
* @param string|null $method
* @return array
*/
public static function getSpecify_annotation(string $attribute, string $class, string $method = null): mixed
{
$class = self::getAttributeTrees($attribute, $class);
if (empty($class) || !isset($class['method'])){
return null;
}
if (empty($method)) {
return $class['method'];
}
foreach ($class['method'] as $value) {
$key = key($value);
if ($method == $key) {
return $value[$key];
}
}
return null;
}
/**
* @param string $attribute
* @param string $class
* @param string $method
* @return mixed
*/
public static function getPropertyByAnnotation(string $attribute, string $class, string $method): mixed
{
$class = self::getAttributeTrees($attribute, $class);
if (empty($class) || !isset($class['property'])) {
return [];
}
foreach ($class['property'] as $value) {
$key = key($value);
if ($method == $key) {
return $value[$key];
}
}
return null;
}
/**
* @param ReflectionClass|string $class
* @return array
* @throws \ReflectionException
*/
public static function getMethods(ReflectionClass|string $class): array
{
if (is_string($class)) {
$class = self::getReflect($class);
}
return static::$_classMethod[$class->getName()] ?? [];
}
/**
* @param ReflectionClass $class
* @return ReflectionProperty[]
*/
#[Pure] public static function getProperty(ReflectionClass $class): array
{
return static::$_classProperty[$class->getName()] ?? [];
}
/**
* @param ReflectionClass $class
* @return array
*/
#[Pure] public static function getPropertyNote(ReflectionClass $class): array
{
return static::$_classPropertyNote[$class->getName()] ?? [];
}
}
<?php
namespace Kiri\Di;
use JetBrains\PhpStorm\Pure;
use ReflectionAttribute;
use ReflectionClass;
use ReflectionProperty;
class NoteManager
{
private static array $_classTarget = [];
private static array $_classMethodAnnotation = [];
private static array $_classMethod = [];
private static array $_classPropertyAnnotation = [];
private static array $_classProperty = [];
private static array $_mapping = [];
/**
* @return void
*/
public static function clear()
{
static::$_classTarget = [];
static::$_classMethodAnnotation = [];
static::$_classMethod = [];
static::$_classPropertyAnnotation = [];
static::$_classProperty = [];
static::$_mapping = [];
}
/**
* @param ReflectionClass $class
*/
public static function setTargetAnnotation(ReflectionClass $class)
{
$className = $class->getName();
if (!isset(static::$_classTarget[$className])) {
static::$_classTarget[$className] = [];
}
foreach ($class->getAttributes() as $attribute) {
if (!class_exists($attribute->getName())) {
continue;
}
$instance = $attribute->newInstance();
static::$_classTarget[$className][] = $instance;
self::setMappingClass($attribute, $className);
}
}
/**
* @param ReflectionAttribute $attribute
* @param string $class
*/
public static function setMappingClass(ReflectionAttribute $attribute, string $class)
{
if (!isset(static::$_mapping[$attribute->getName()])) {
static::$_mapping[$attribute->getName()] = [];
}
if (!isset(static::$_mapping[$attribute->getName()][$class])) {
static::$_mapping[$attribute->getName()][$class] = [];
}
}
/**
* @param ReflectionAttribute $attribute
* @param string $class
* @param string $method
* @param mixed $instance
*/
public static function setMappingMethod(ReflectionAttribute $attribute, string $class, string $method, mixed $instance)
{
self::setMappingClass($attribute, $class);
if (!isset(static::$_mapping[$attribute->getName()][$class]['method'])) {
static::$_mapping[$attribute->getName()][$class]['method'] = [];
}
static::$_mapping[$attribute->getName()][$class]['method'][] = [$method => $instance];
}
/**
* @param ReflectionAttribute $attribute
* @param string $class
* @param string $property
* @param $instance
*/
public static function setMappingProperty(ReflectionAttribute $attribute, string $class, string $property, $instance)
{
self::setMappingClass($attribute, $class);
$mapping = static::$_mapping[$attribute->getName()][$class];
if (!isset($mapping['property'])) {
$mapping['property'] = [];
}
$mapping['property'][] = [$property => $instance];
static::$_mapping[$attribute->getName()][$class] = $mapping;
}
/**
* @param mixed $class
* @return array
*/
public static function getTargetAnnotation(mixed $class): array
{
if (!is_string($class)) {
$class = $class::class;
}
return static::$_classTarget[$class] ?? [];
}
/**
* @param ReflectionClass $class
*/
public static function setMethodAnnotation(ReflectionClass $class)
{
$className = $class->getName();
static::$_classMethodAnnotation[$className] = static::$_classMethod[$className] = [];
foreach ($class->getMethods() as $ReflectionMethod) {
static::$_classMethod[$className][$ReflectionMethod->getName()] = $ReflectionMethod;
static::$_classMethodAnnotation[$className][$ReflectionMethod->getName()] = [];
foreach ($ReflectionMethod->getAttributes() as $attribute) {
if (!class_exists($attribute->getName())) {
continue;
}
$instance = $attribute->newInstance();
static::$_classMethodAnnotation[$className][$ReflectionMethod->getName()][] = $instance;
self::setMappingMethod($attribute, $className, $ReflectionMethod->getName(), $instance);
}
}
}
/**
* @param string $class
* @param string $method
* @return bool
*/
public static function hasMethod(string $class, string $method): bool
{
return isset(static::$_classMethod[$class]) && isset(static::$_classMethod[$class][$method]);
}
/**
* @param ReflectionClass $class
* @return array
*/
#[Pure] public static function getMethodAnnotation(ReflectionClass $class): array
{
return static::$_classMethodAnnotation[$class->getName()] ?? [];
}
/**
* @param \ReflectionClass $reflect
* @return \ReflectionMethod|null
*/
public static function resolveTarget(ReflectionClass $reflect): ?\ReflectionMethod
{
NoteManager::setPropertyAnnotation($reflect);
NoteManager::setTargetAnnotation($reflect);
NoteManager::setMethodAnnotation($reflect);
return $reflect->getConstructor();
}
/**
* @param ReflectionClass $class
*/
public static function setPropertyAnnotation(ReflectionClass $class)
{
$className = $class->getName();
static::$_classProperty[$className] = static::$_classPropertyAnnotation[$className] = [];
foreach ($class->getProperties(ReflectionProperty::IS_PRIVATE | ReflectionProperty::IS_PUBLIC |
ReflectionProperty::IS_PROTECTED) as $ReflectionMethod) {
static::$_classProperty[$className][$ReflectionMethod->getName()] = $ReflectionMethod;
foreach ($ReflectionMethod->getAttributes() as $attribute) {
if (!class_exists($attribute->getName())) {
continue;
}
$instance = $attribute->newInstance();
static::$_classPropertyAnnotation[$className][$ReflectionMethod->getName()] = $instance;
self::setMappingProperty($attribute, $className, $ReflectionMethod->getName(), $instance);
}
}
}
/**
* @param string $attribute
* @param string|null $class
* @return array[]
*/
public static function getAttributeTrees(string $attribute, string $class = null): array
{
$mapping = static::$_mapping[$attribute] ?? [];
if (empty($mapping) || empty($class)) {
return $mapping;
}
return $mapping[$class] ?? [];
}
/**
* @param string $attribute
* @param string $class
* @param string|null $method
* @return array
*/
public static function getSpecify_annotation(string $attribute, string $class, string $method = null): mixed
{
$class = self::getAttributeTrees($attribute, $class);
if (empty($class) || !isset($class['method'])) {
return null;
}
if (empty($method)) {
return $class['method'];
}
foreach ($class['method'] as $value) {
$key = key($value);
if ($method == $key) {
return $value[$key];
}
}
return null;
}
/**
* @param string $attribute
* @param string $class
* @param string $method
* @return mixed
*/
public static function getPropertyByAnnotation(string $attribute, string $class, string $method): mixed
{
$class = self::getAttributeTrees($attribute, $class);
if (empty($class) || !isset($class['property'])) {
return [];
}
foreach ($class['property'] as $value) {
$key = key($value);
if ($method == $key) {
return $value[$key];
}
}
return null;
}
/**
* @param ReflectionClass|string $class
* @return array
* @throws \ReflectionException
*/
public static function getMethods(ReflectionClass|string $class): array
{
if (is_string($class)) {
$class = self::getReflect($class);
}
return static::$_classMethod[$class->getName()] ?? [];
}
/**
* @param ReflectionClass $class
* @return ReflectionProperty[]
*/
#[Pure] public static function getProperty(ReflectionClass $class): array
{
return static::$_classProperty[$class->getName()] ?? [];
}
/**
* @param ReflectionClass $class
* @return array
*/
#[Pure] public static function getPropertyAnnotation(ReflectionClass $class): array
{
return static::$_classPropertyAnnotation[$class->getName()] ?? [];
}
}
+46 -46
View File
@@ -1,46 +1,46 @@
<?php
namespace Kiri;
use JetBrains\PhpStorm\Pure;
/**
* Class Environmental
* @package Kiri
*/
class Environmental
{
/**
* @return bool
*/
public function isMac(): bool
{
$output = strtolower(PHP_OS | PHP_OS_FAMILY);
if (str_contains('mac', $output)) {
return true;
} else if (str_contains('darwin', $output)) {
return true;
} else {
return false;
}
}
/**
* @return bool
*/
#[Pure] public function isLinux(): bool
{
if (!static::isMac()) {
return true;
} else {
return false;
}
}
}
<?php
namespace Kiri;
use JetBrains\PhpStorm\Pure;
/**
* Class Environmental
* @package Kiri
*/
class Environmental
{
/**
* @return bool
*/
public function isMac(): bool
{
$output = strtolower(PHP_OS | PHP_OS_FAMILY);
if (str_contains('mac', $output)) {
return true;
} else if (str_contains('darwin', $output)) {
return true;
} else {
return false;
}
}
/**
* @return bool
*/
#[Pure] public function isLinux(): bool
{
if (!static::isMac()) {
return true;
} else {
return false;
}
}
}
+158 -158
View File
@@ -1,158 +1,158 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/4/26 0026
* Time: 10:00
*/
declare(strict_types=1);
namespace Kiri\Error;
use Exception;
use Http\Handler\Formatter\IFormatter;
use Kiri\Abstracts\Component;
use Kiri\Core\Json;
use Kiri\Events\EventDispatch;
use Kiri\Kiri;
use Http\Events\OnAfterRequest;
/**
* Class ErrorHandler
*
* @package Kiri\Kiri\Base
* @property-read $asError
*/
class ErrorHandler extends Component implements ErrorInterface
{
/** @var ?IFormatter $message */
private ?IFormatter $message = NULL;
public string $category = 'app';
/**
* 错误处理注册
*/
public function register()
{
// ini_set('display_errors', '1');
set_exception_handler([$this, 'exceptionHandler']);
if (defined('HHVM_VERSION')) {
set_error_handler([$this, 'errorHandler']);
} else {
set_error_handler([$this, 'errorHandler']);
}
register_shutdown_function([$this, 'shutdown']);
}
/**
* @throws Exception
*/
public function shutdown()
{
$lastError = error_get_last();
if (empty($lastError) || $lastError['type'] !== E_ERROR) {
return;
}
$this->category = 'shutdown';
$messages = explode(PHP_EOL, $lastError['message']);
$message = array_shift($messages);
$this->sendError($message, $lastError['file'], $lastError['line']);
}
/**
* @param \Throwable $exception
*
* @throws Exception
*/
public function exceptionHandler(\Throwable $exception)
{
$this->category = 'exception';
di(EventDispatch::class)->dispatch(new OnAfterRequest());
$this->sendError($exception->getMessage(), $exception->getFile(), $exception->getLine());
}
/**
* @throws Exception
*
* 以异常形式抛出错误,防止执行后续程序
*/
public function errorHandler()
{
$error = func_get_args();
$path = ['file' => $error[2], 'line' => $error[3]];
if ($error[0] === 0) {
$error[0] = 500;
}
$data = Json::to(500, $error[1], $path);
Kiri::app()->error($data, 'error');
di(EventDispatch::class)->dispatch(new OnAfterRequest());
throw new \ErrorException($error[1], $error[0], 1, $error[2], $error[3]);
}
/**
* @param $message
* @param $file
* @param $line
* @param int $code
* @return false|string
* @throws Exception
*/
public function sendError($message, $file, $line, $code = 500): bool|string
{
$path = ['file' => $file, 'line' => $line];
var_dump(func_get_args());
$data = Json::to($code, $this->category . ': ' . $message, $path);
write($data, $this->category);
return $data;
}
/**
* @return mixed
*/
public function getErrorMessage(): mixed
{
$message = $this->message;
$this->message = NULL;
return $message->getData();
}
/**
* @return bool
*/
public function getAsError(): bool
{
return $this->message !== NULL;
}
/**
* @param $message
* @param string $category
*
* @throws Exception
*/
public function writer($message, string $category = 'app')
{
Kiri::app()->debug($message, $category);
}
}
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/4/26 0026
* Time: 10:00
*/
declare(strict_types=1);
namespace Kiri\Error;
use Exception;
use Http\Handler\Formatter\IFormatter;
use Kiri\Abstracts\Component;
use Kiri\Core\Json;
use Kiri\Events\EventDispatch;
use Kiri\Kiri;
use Http\Events\OnAfterRequest;
/**
* Class ErrorHandler
*
* @package Kiri\Kiri\Base
* @property-read $asError
*/
class ErrorHandler extends Component implements ErrorInterface
{
/** @var ?IFormatter $message */
private ?IFormatter $message = NULL;
public string $category = 'app';
/**
* 错误处理注册
*/
public function register()
{
// ini_set('display_errors', '1');
set_exception_handler([$this, 'exceptionHandler']);
if (defined('HHVM_VERSION')) {
set_error_handler([$this, 'errorHandler']);
} else {
set_error_handler([$this, 'errorHandler']);
}
register_shutdown_function([$this, 'shutdown']);
}
/**
* @throws Exception
*/
public function shutdown()
{
$lastError = error_get_last();
if (empty($lastError) || $lastError['type'] !== E_ERROR) {
return;
}
$this->category = 'shutdown';
$messages = explode(PHP_EOL, $lastError['message']);
$message = array_shift($messages);
$this->sendError($message, $lastError['file'], $lastError['line']);
}
/**
* @param \Throwable $exception
*
* @throws Exception
*/
public function exceptionHandler(\Throwable $exception)
{
$this->category = 'exception';
di(EventDispatch::class)->dispatch(new OnAfterRequest());
$this->sendError($exception->getMessage(), $exception->getFile(), $exception->getLine());
}
/**
* @throws Exception
*
* 以异常形式抛出错误,防止执行后续程序
*/
public function errorHandler()
{
$error = func_get_args();
$path = ['file' => $error[2], 'line' => $error[3]];
if ($error[0] === 0) {
$error[0] = 500;
}
$data = Json::to(500, $error[1], $path);
Kiri::app()->error($data, 'error');
di(EventDispatch::class)->dispatch(new OnAfterRequest());
throw new \ErrorException($error[1], $error[0], 1, $error[2], $error[3]);
}
/**
* @param $message
* @param $file
* @param $line
* @param int $code
* @return false|string
* @throws Exception
*/
public function sendError($message, $file, $line, $code = 500): bool|string
{
$path = ['file' => $file, 'line' => $line];
var_dump(func_get_args());
$data = Json::to($code, $this->category . ': ' . $message, $path);
write($data, $this->category);
return $data;
}
/**
* @return mixed
*/
public function getErrorMessage(): mixed
{
$message = $this->message;
$this->message = NULL;
return $message->getData();
}
/**
* @return bool
*/
public function getAsError(): bool
{
return $this->message !== NULL;
}
/**
* @param $message
* @param string $category
*
* @throws Exception
*/
public function writer($message, string $category = 'app')
{
Kiri::app()->debug($message, $category);
}
}
+28 -28
View File
@@ -1,28 +1,28 @@
<?php
/**
* Created by PhpStorm.
* User: admin
* Date: 2019-03-20
* Time: 10:25
*/
declare(strict_types=1);
namespace Kiri\Error;
/**
* Interface ErrorInterface
* @package Kiri\Kiri\Error
*/
interface ErrorInterface
{
/**
* @param $message
* @param $file
* @param $line
* @param int $code
* @return mixed
*/
public function sendError($message, $file, $line, $code = 500): mixed;
}
<?php
/**
* Created by PhpStorm.
* User: admin
* Date: 2019-03-20
* Time: 10:25
*/
declare(strict_types=1);
namespace Kiri\Error;
/**
* Interface ErrorInterface
* @package Kiri\Kiri\Error
*/
interface ErrorInterface
{
/**
* @param $message
* @param $file
* @param $line
* @param int $code
* @return mixed
*/
public function sendError($message, $file, $line, $code = 500): mixed;
}
+117 -111
View File
@@ -1,111 +1,117 @@
<?php
/**
* Created by PhpStorm.
* User: admin
* Date: 2019-03-22
* Time: 14:36
*/
declare(strict_types=1);
namespace Kiri\Error;
use Annotation\Inject;
use Exception;
use Kiri\Abstracts\Component;
use Kiri\Core\Json;
use Kiri\Events\EventProvider;
use Kiri\Kiri;
use Psr\Log\LoggerInterface;
use Throwable;
/**
* Class Logger
* @package Kiri\Kiri\Error
* @mixin \Kiri\Abstracts\Logger
*/
class Logger extends Component
{
private array $logs = [];
/** @var EventProvider */
#[Inject(EventProvider::class)]
public EventProvider $eventProvider;
/**
* inject logger
*
* @var LoggerInterface
*/
#[Inject(LoggerInterface::class)]
public LoggerInterface $logger;
private array $sources = [];
/**
* @param string $application
* @return string
*/
public function getLastError(string $application = 'app'): string
{
return 'Unknown error.';
}
/**
* @param string $messages
* @param string $method
* @throws Exception
*/
public function write(string $messages, string $method = 'app')
{
if (empty($messages)) {
return;
}
$to_day = date('Y-m-d');
$fileName = storage('server-' . $to_day . '.log', $dirName = 'log/' . ($method ?? 'app'));
file_put_contents($fileName, '[' . date('Y-m-d H:i:s') . ']:' . PHP_EOL . $messages . PHP_EOL);
}
/**
* @param Throwable $exception
* @return mixed
* @throws Exception
*/
public function exception(Throwable $exception): mixed
{
$code = $exception->getCode() == 0 ? 500 : $exception->getCode();
$logger = Kiri::app()->getLogger();
$logger->write(jTraceEx($exception), 'exception');
return Json::to($code, $exception->getMessage(), [
'file' => $exception->getFile(),
'line' => $exception->getLine()
]);
}
/**
* @param string $name
* @param array $arguments
* @return mixed
*/
public function __call(string $name, array $arguments): mixed
{
if (!method_exists($this, $name)) {
return $this->logger->{$name}(...$arguments);
} else {
return $this->{$name}(...$arguments);
}
}
}
<?php
/**
* Created by PhpStorm.
* User: admin
* Date: 2019-03-22
* Time: 14:36
*/
declare(strict_types=1);
namespace Kiri\Error;
use Exception;
use Kiri\Abstracts\Component;
use Kiri\Core\Json;
use Kiri\Kiri;
use Kiri\Annotation\Inject;
use Psr\Log\LoggerInterface;
use Throwable;
/**
* Class Logger
* @package Kiri\Kiri\Error
* @mixin \Kiri\Abstracts\Logger
*/
class Logger extends Component
{
private array $logs = [];
/**
* inject logger
*
* @var LoggerInterface
*/
#[Inject(LoggerInterface::class)]
public LoggerInterface $logger;
private array $sources = [];
/**
* @param string $application
* @return string
*/
public function getLastError(string $application = 'app'): string
{
return $this->logs[$application] ?? 'Unknown error.';
}
/**
* @param $message
* @param $method
* @return void
*/
public function fail($message, $method)
{
$this->logs[$method] = $message;
}
/**
* @param string $messages
* @param string $method
* @throws Exception
*/
public function write(string $messages, string $method = 'app')
{
if (empty($messages)) {
return;
}
$to_day = date('Y-m-d');
$fileName = storage('server-' . $to_day . '.log', $dirName = 'log/' . ($method ?? 'app'));
file_put_contents($fileName, '[' . date('Y-m-d H:i:s') . ']:' . PHP_EOL . $messages . PHP_EOL);
}
/**
* @param Throwable $exception
* @return mixed
* @throws Exception
*/
public function exception(Throwable $exception): mixed
{
$code = $exception->getCode() == 0 ? 500 : $exception->getCode();
$logger = Kiri::app()->getLogger();
$logger->write(jTraceEx($exception), 'exception');
return Json::to($code, $exception->getMessage(), [
'file' => $exception->getFile(),
'line' => $exception->getLine()
]);
}
/**
* @param string $name
* @param array $arguments
* @return mixed
*/
public function __call(string $name, array $arguments): mixed
{
if (!method_exists($this, $name)) {
return $this->logger->{$name}(...$arguments);
} else {
return $this->{$name}(...$arguments);
}
}
}
+53 -52
View File
@@ -1,52 +1,53 @@
<?php
namespace Kiri\Error;
use Exception;
use Http\Aspect\OnAspectInterface;
use Http\Aspect\OnJoinPointInterface;
use Http\Constrict\RequestInterface;
use Kiri\Kiri;
/**
* Class LoggerAspect
* @package Kiri\Error
*/
class LoggerAspect implements OnAspectInterface
{
/**
* @param OnJoinPointInterface $joinPoint
* @return mixed
* @throws Exception
*/
public function process(OnJoinPointInterface $joinPoint): mixed
{
$time = microtime(true);
$response = $joinPoint->process();
$this->print_runtime($time);
return $response;
}
/**
* @param $startTime
* @throws Exception
*/
private function print_runtime($startTime)
{
$request = Kiri::getDi()->get(RequestInterface::class);
$runTime = round(microtime(true) - $startTime, 6);
echo sprintf('run %s use time %6f', $request->getUri()->__toString(), $runTime);
echo PHP_EOL;
}
}
<?php
namespace Kiri\Error;
use Exception;
use Http\Aspect\OnAspectInterface;
use Http\Aspect\OnJoinPointInterface;
use Http\Constrict\RequestInterface;
use Kiri\Kiri;
use Psr\Log\LoggerInterface;
/**
* Class LoggerAspect
* @package Kiri\Error
*/
class LoggerAspect implements OnAspectInterface
{
/**
* @param OnJoinPointInterface $joinPoint
* @return mixed
* @throws Exception
*/
public function process(OnJoinPointInterface $joinPoint): mixed
{
$time = microtime(true);
$response = $joinPoint->process();
$this->print_runtime($time);
return $response;
}
/**
* @param $startTime
* @throws Exception
*/
private function print_runtime($startTime)
{
$request = Kiri::getDi()->get(RequestInterface::class);
$runTime = round(microtime(true) - $startTime, 6);
$logger = Kiri::getDi()->get(LoggerInterface::class);
$logger->debug(sprintf('run %s use time %6f', $request->getUri()->__toString(), $runTime));
}
}
+84 -83
View File
@@ -1,83 +1,84 @@
<?php
namespace Kiri\Error;
use Exception;
use JetBrains\PhpStorm\Pure;
use Kiri\Core\Json;
use Kiri\Exception\ComponentException;
use Kiri\Kiri;
use Swoole\Coroutine;
use Swoole\Process;
use Server\Abstracts\BaseProcess;
/**
* Class LoggerProcess
* @package Kiri\Error
*/
class LoggerProcess extends BaseProcess
{
public string $name = 'logger process';
/**
* @param Process $process
* @throws ComponentException
*/
public function process(Process $process): void
{
// TODO: Implement onHandler() method.
$this->message($process);
}
/**
* @param Process $process
* @throws ComponentException
* @throws Exception
*/
public function message(Process $process)
{
$message = Json::decode($process->read());
if (!empty($message)) {
Kiri::writeFile($this->getDirName($message), $message[0], FILE_APPEND);
$this->checkLogFile($message[1]);
}
Coroutine\System::sleep(1);
$this->message($process);
}
/**
* @param $message
* @return string
* @throws Exception
*/
private function getDirName($message): string
{
return storage('server-' . date('Y-m-d') . '.log', $message[1]);
}
/**
* @param $dirName
* @throws Exception
*/
private function checkLogFile($dirName)
{
$files = new \DirectoryIterator(storage(null, $dirName));
if ($files->getSize() < 15) {
return;
}
Coroutine\System::exec('find ' . storage(null, $dirName) . '/ -mtime +15 -name "*.log" -exec rm -rf {} \;');
}
}
<?php
namespace Kiri\Error;
use Exception;
use Kiri\Core\Json;
use Kiri\Exception\ComponentException;
use Kiri\Kiri;
use Server\Abstracts\BaseProcess;
use Swoole\Coroutine;
use Swoole\Process;
/**
* Class LoggerProcess
* @package Kiri\Error
*/
class LoggerProcess extends BaseProcess
{
public string $name = 'logger process';
/**
* @param Process $process
* @throws ComponentException
*/
public function process(Process $process): void
{
// TODO: Implement onHandler() method.
$this->message($process);
}
/**
* @param Process $process
* @throws ComponentException
* @throws Exception
*/
public function message(Process $process)
{
if ($this->isStop()) {
return;
}
$message = Json::decode($process->read());
if (!empty($message)) {
Kiri::writeFile($this->getDirName($message), $message[0], FILE_APPEND);
$this->checkLogFile($message[1]);
}
Coroutine\System::sleep(1);
$this->message($process);
}
/**
* @param $message
* @return string
* @throws Exception
*/
private function getDirName($message): string
{
return storage('server-' . date('Y-m-d') . '.log', $message[1]);
}
/**
* @param $dirName
* @throws Exception
*/
private function checkLogFile($dirName)
{
$files = new \DirectoryIterator(storage(null, $dirName));
if ($files->getSize() < 15) {
return;
}
Coroutine\System::exec('find ' . storage(null, $dirName) . '/ -mtime +15 -name "*.log" -exec rm -rf {} \;');
}
}
+238 -239
View File
@@ -1,239 +1,238 @@
<?php
declare(strict_types=1);
namespace Kiri;
use Exception;
use Kiri\Abstracts\BaseObject;
use Swoole\Coroutine;
/**
* Class Event
* @package Kiri
*/
class Event extends BaseObject
{
public bool $isVide = true;
private static array $_events = [];
const PIPE_MESSAGE = 'SERVER:PIPE:MESSAGE';
const TASK_FINISH = 'SERVER:TASK::FINISH';
const EVENT_AFTER_REQUEST = 'SERVER:REQUEST:AFTER:START';
const EVENT_BEFORE_REQUEST = 'SERVER:REQUEST:BEFORE:START';
const RECEIVE_CONNECTION = 'SERVER:RECEIVE:CONNECTION';
const SYSTEM_RESOURCE_RELEASES = 'SYSTEM::RESOURCE::RELEASES';
const SYSTEM_RESOURCE_CLEAN = 'SYSTEM::RESOURCE::CLEAN';
const PROCESS_WORKER_STOP = 'SERVER:PROCESS:WORKER:STOP';
const SERVER_AFTER_RELOAD = 'SERVER:AFTER:RELOAD';
const SERVER_BEFORE_RELOAD = 'SERVER:BEFORE:RELOAD';
const SERVER_CONNECT = 'SERVER:CONNECT';
const SERVER_PACKAGE = 'SERVER:PACKAGE';
const SERVER_RECEIVE = 'SERVER:RECEIVE';
const SERVER_EVENT_START = 'SERVER:EVENT:START';
const SERVER_MANAGER_START = 'SERVER:EVENT:MANAGER:START';
const SERVER_MANAGER_STOP = 'SERVER:EVENT:MANAGER:START';
const SERVER_WORKER_STOP = 'SERVER:EVENT:WORKER:STOP';
const SERVER_WORKER_START = 'SERVER:EVENT:WORKER:START';
const SERVER_AFTER_WORKER_START = 'SERVER:EVENT:AFTER:WORKER:START';
const SERVER_BEFORE_START = 'SERVER:EVENT:BEFORE:START';
const BEFORE_COMMAND_EXECUTE = 'COMMAND:EVENT:BEFORE:EXECUTE';
const AFTER_COMMAND_EXECUTE = 'COMMAND:EVENT:AFTER:EXECUTE';
const SERVER_TASK_START = 'SERVER:EVENT:TASK:START';
const SERVER_WORKER_EXIT = 'SERVER:EVENT:WORKER:EXIT';
const SERVER_WORKER_ERROR = 'SERVER:EVENT:WORKER:ERROR';
const SERVER_SHUTDOWN = 'SERVER:EVENT:SHUTDOWN';
const SERVER_HANDSHAKE = 'on handshake';
const SERVER_MESSAGE = 'on message';
const SERVER_CLIENT_CLOSE = 'SERVER:CLIENT:CLOSE';
const SERVER_ON_START = 'Start';
const SERVER_ON_SHUTDOWN = 'Shutdown';
const SERVER_ON_WORKER_START = 'WorkerStart';
const SERVER_ON_WORKER_STOP = 'WorkerStop';
const SERVER_ON_WORKER_EXIT = 'WorkerExit';
const SERVER_ON_CONNECT = 'Connect';
const SERVER_ON_RECEIVE = 'Receive';
const SERVER_ON_PACKET = 'Packet';
const SERVER_ON_REQUEST = 'request';
const SERVER_ON_CLOSE = 'Close';
const SERVER_ON_TASK = 'Task';
const SERVER_ON_FINISH = 'Finish';
const SERVER_ON_PIPE_MESSAGE = 'OnPipeMessageInterface';
const SERVER_ON_WORKER_ERROR = 'WorkerError';
const SERVER_ON_MANAGER_START = 'ManagerStart';
const SERVER_ON_MANAGER_STOP = 'ManagerStop';
const SERVER_ON_BEFORE_RELOAD = 'BeforeReload';
const SERVER_ON_AFTER_RELOAD = 'AfterReload';
/**
* @param $name
* @param $callback
* @param bool $isAppend
* @throws Exception
*/
public static function on($name, $callback, bool $isAppend = false)
{
if (!isset(static::$_events[$name])) {
static::$_events[$name] = [];
}
if (is_array($callback) && is_string($callback[0])) {
if (!class_exists($callback[0])) {
throw new Exception('Undefined callback class.');
}
$callback[0] = di($callback[0]);
}
if (static::exists($name, $callback)) {
return;
}
if (!empty(static::$_events[$name]) && $isAppend === true) {
array_unshift(static::$_events[$name], [$callback]);
} else {
static::$_events[$name][] = [$callback];
}
}
/**
* @param $name
* @param $callback
*/
public static function of($name, $callback): void
{
if (!isset(static::$_events[$name])) {
return;
}
foreach (static::$_events[$name] as $index => $event) {
[$handler] = $event;
if ($handler !== $callback) {
continue;
}
unset(static::$_events[$name][$index]);
}
}
/**
* @param $name
*/
public static function offName($name): void
{
unset(static::$_events[$name]);
}
/**
* @param $name
* @param null $callback
* @return bool
*/
public static function exists($name, $callback): bool
{
if ($callback instanceof \Closure || !isset(static::$_events[$name])) {
return false;
}
foreach (static::$_events[$name] as $event) {
[$handler] = $event;
if ($handler === $callback) {
return true;
}
}
return false;
}
/**
* @param $name
* @param $handler
* @return mixed
*/
public static function get($name, $handler): mixed
{
if (!static::exists($name, $handler)) {
return null;
}
if (empty($handler)) {
return static::$_events[$name];
}
foreach (static::$_events[$name] as $event) {
[$callback] = $event;
if ($callback === $handler) {
return [$event];
}
}
return null;
}
public static function clean()
{
static::$_events = [];
}
/**
* @param $name
* @param array $params
* @return bool
* @throws Exception
*/
public function dispatch($name, array $params = []): bool
{
return static::trigger($name, $params);
}
/**
* @param $name
* @param null $parameter
* @param false $is_remove
* @return bool
* @throws Exception
*/
public static function trigger($name, $parameter = null, bool $is_remove = false): bool
{
foreach ((static::$_events[$name] ?? []) as $key => $event) {
static::execute($event, $parameter);
if ($event instanceof \Closure) {
unset(static::$_events[$name][$key]);
}
}
if ($is_remove) {
unset(static::$_events[$name]);
}
return true;
}
/**
* @param $event
* @param $parameter
* @return void
* @throws Exception
*/
private static function execute($event, $parameter): void
{
try {
call_user_func($event[0], ...$parameter);
} catch (\Throwable $throwable) {
logger()->addError($throwable, 'throwable');
return;
}
}
}
<?php
declare(strict_types=1);
namespace Kiri;
use Exception;
use Kiri\Abstracts\Component;
/**
* Class Event
* @package Kiri
*/
class Event extends Component
{
public bool $isVide = true;
private static array $_events = [];
const PIPE_MESSAGE = 'SERVER:PIPE:MESSAGE';
const TASK_FINISH = 'SERVER:TASK::FINISH';
const EVENT_AFTER_REQUEST = 'SERVER:REQUEST:AFTER:START';
const EVENT_BEFORE_REQUEST = 'SERVER:REQUEST:BEFORE:START';
const RECEIVE_CONNECTION = 'SERVER:RECEIVE:CONNECTION';
const SYSTEM_RESOURCE_RELEASES = 'SYSTEM::RESOURCE::RELEASES';
const SYSTEM_RESOURCE_CLEAN = 'SYSTEM::RESOURCE::CLEAN';
const PROCESS_WORKER_STOP = 'SERVER:PROCESS:WORKER:STOP';
const SERVER_AFTER_RELOAD = 'SERVER:AFTER:RELOAD';
const SERVER_BEFORE_RELOAD = 'SERVER:BEFORE:RELOAD';
const SERVER_CONNECT = 'SERVER:CONNECT';
const SERVER_PACKAGE = 'SERVER:PACKAGE';
const SERVER_RECEIVE = 'SERVER:RECEIVE';
const SERVER_EVENT_START = 'SERVER:EVENT:START';
const SERVER_MANAGER_START = 'SERVER:EVENT:MANAGER:START';
const SERVER_MANAGER_STOP = 'SERVER:EVENT:MANAGER:START';
const SERVER_WORKER_STOP = 'SERVER:EVENT:WORKER:STOP';
const SERVER_WORKER_START = 'SERVER:EVENT:WORKER:START';
const SERVER_AFTER_WORKER_START = 'SERVER:EVENT:AFTER:WORKER:START';
const SERVER_BEFORE_START = 'SERVER:EVENT:BEFORE:START';
const BEFORE_COMMAND_EXECUTE = 'COMMAND:EVENT:BEFORE:EXECUTE';
const AFTER_COMMAND_EXECUTE = 'COMMAND:EVENT:AFTER:EXECUTE';
const SERVER_TASK_START = 'SERVER:EVENT:TASK:START';
const SERVER_WORKER_EXIT = 'SERVER:EVENT:WORKER:EXIT';
const SERVER_WORKER_ERROR = 'SERVER:EVENT:WORKER:ERROR';
const SERVER_SHUTDOWN = 'SERVER:EVENT:SHUTDOWN';
const SERVER_HANDSHAKE = 'on handshake';
const SERVER_MESSAGE = 'on message';
const SERVER_CLIENT_CLOSE = 'SERVER:CLIENT:CLOSE';
const SERVER_ON_START = 'Start';
const SERVER_ON_SHUTDOWN = 'Shutdown';
const SERVER_ON_WORKER_START = 'WorkerStart';
const SERVER_ON_WORKER_STOP = 'WorkerStop';
const SERVER_ON_WORKER_EXIT = 'WorkerExit';
const SERVER_ON_CONNECT = 'Connect';
const SERVER_ON_RECEIVE = 'Receive';
const SERVER_ON_PACKET = 'Packet';
const SERVER_ON_REQUEST = 'request';
const SERVER_ON_CLOSE = 'Close';
const SERVER_ON_TASK = 'Task';
const SERVER_ON_FINISH = 'Finish';
const SERVER_ON_PIPE_MESSAGE = 'OnPipeMessageInterface';
const SERVER_ON_WORKER_ERROR = 'WorkerError';
const SERVER_ON_MANAGER_START = 'ManagerStart';
const SERVER_ON_MANAGER_STOP = 'ManagerStop';
const SERVER_ON_BEFORE_RELOAD = 'BeforeReload';
const SERVER_ON_AFTER_RELOAD = 'AfterReload';
/**
* @param $name
* @param $callback
* @param bool $isAppend
* @throws Exception
*/
public static function on($name, $callback, bool $isAppend = false)
{
if (!isset(static::$_events[$name])) {
static::$_events[$name] = [];
}
if (is_array($callback) && is_string($callback[0])) {
if (!class_exists($callback[0])) {
throw new Exception('Undefined callback class.');
}
$callback[0] = di($callback[0]);
}
if (static::exists($name, $callback)) {
return;
}
if (!empty(static::$_events[$name]) && $isAppend === true) {
array_unshift(static::$_events[$name], [$callback]);
} else {
static::$_events[$name][] = [$callback];
}
}
/**
* @param $name
* @param $callback
*/
public static function of($name, $callback): void
{
if (!isset(static::$_events[$name])) {
return;
}
foreach (static::$_events[$name] as $index => $event) {
[$handler] = $event;
if ($handler !== $callback) {
continue;
}
unset(static::$_events[$name][$index]);
}
}
/**
* @param $name
*/
public static function offName($name): void
{
unset(static::$_events[$name]);
}
/**
* @param $name
* @param null $callback
* @return bool
*/
public static function exists($name, $callback): bool
{
if ($callback instanceof \Closure || !isset(static::$_events[$name])) {
return false;
}
foreach (static::$_events[$name] as $event) {
[$handler] = $event;
if ($handler === $callback) {
return true;
}
}
return false;
}
/**
* @param $name
* @param $handler
* @return mixed
*/
public static function get($name, $handler): mixed
{
if (!static::exists($name, $handler)) {
return null;
}
if (empty($handler)) {
return static::$_events[$name];
}
foreach (static::$_events[$name] as $event) {
[$callback] = $event;
if ($callback === $handler) {
return [$event];
}
}
return null;
}
public static function clean()
{
static::$_events = [];
}
/**
* @param $name
* @param array $params
* @return bool
* @throws Exception
*/
public function dispatch($name, array $params = []): bool
{
return static::trigger($name, $params);
}
/**
* @param $name
* @param null $parameter
* @param false $is_remove
* @return bool
* @throws Exception
*/
public static function trigger($name, $parameter = null, bool $is_remove = false): bool
{
foreach ((static::$_events[$name] ?? []) as $key => $event) {
static::execute($event, $parameter);
if ($event instanceof \Closure) {
unset(static::$_events[$name][$key]);
}
}
if ($is_remove) {
unset(static::$_events[$name]);
}
return true;
}
/**
* @param $event
* @param $parameter
* @return void
* @throws Exception
*/
private static function execute($event, $parameter): void
{
try {
call_user_func($event[0], ...$parameter);
} catch (\Throwable $throwable) {
logger()->addError($throwable, 'throwable');
return;
}
}
}
+16 -16
View File
@@ -1,16 +1,16 @@
<?php
namespace Kiri\Events;
class OnAfterCommandExecute
{
/**
*
*/
public function __construct()
{
}
}
<?php
namespace Kiri\Events;
class OnAfterCommandExecute
{
/**
*
*/
public function __construct()
{
}
}
@@ -1,8 +1,8 @@
<?php
namespace Kiri\Events;
class OnBeforeCommandExecute
{
}
<?php
namespace Kiri\Events;
class OnBeforeCommandExecute
{
}
+29 -29
View File
@@ -1,29 +1,29 @@
<?php
declare(strict_types=1);
namespace Kiri\Exception;
use Throwable;
/**
* Class AuthException
* @package Kiri\Exception
*/
class AuthException extends \Exception
{
/**
* AuthException constructor.
* @param string $message
* @param int $code
* @param Throwable|null $previous
*/
public function __construct($message = "", $code = 0, Throwable $previous = null)
{
parent::__construct($message, 4001, $previous);
}
}
<?php
declare(strict_types=1);
namespace Kiri\Exception;
use Throwable;
/**
* Class AuthException
* @package Kiri\Exception
*/
class AuthException extends \Exception
{
/**
* AuthException constructor.
* @param string $message
* @param int $code
* @param Throwable|null $previous
*/
public function __construct($message = "", $code = 0, Throwable $previous = null)
{
parent::__construct($message, 4001, $previous);
}
}
+35 -35
View File
@@ -1,35 +1,35 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/4/25 0025
* Time: 18:34
*/
declare(strict_types=1);
namespace Kiri\Exception;
use Throwable;
/**
* Class ComponentException
* @package Kiri\Kiri\Exception
*/
class ComponentException extends \Exception
{
/**
* ComponentException constructor.
* @param string $message
* @param int $code
* @param Throwable|null $previous
*/
public function __construct(string $message = "", int $code = 0, Throwable $previous = NULL)
{
parent::__construct($message, 5000, $previous);
}
}
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/4/25 0025
* Time: 18:34
*/
declare(strict_types=1);
namespace Kiri\Exception;
use Throwable;
/**
* Class ComponentException
* @package Kiri\Kiri\Exception
*/
class ComponentException extends \Exception
{
/**
* ComponentException constructor.
* @param string $message
* @param int $code
* @param Throwable|null $previous
*/
public function __construct(string $message = "", int $code = 0, Throwable $previous = NULL)
{
parent::__construct($message, 5000, $previous);
}
}
+15 -15
View File
@@ -1,15 +1,15 @@
<?php
declare(strict_types=1);
namespace Kiri\Exception;
/**
* Class ConfigException
* @package Kiri\Exception
*/
class ConfigException extends \Exception
{
}
<?php
declare(strict_types=1);
namespace Kiri\Exception;
/**
* Class ConfigException
* @package Kiri\Exception
*/
class ConfigException extends \Exception
{
}
+14 -14
View File
@@ -1,14 +1,14 @@
<?php
declare(strict_types=1);
namespace Kiri\Exception;
/**
* Class InitException
* @package Kiri\Exception
*/
class InitException extends \Exception
{
}
<?php
declare(strict_types=1);
namespace Kiri\Exception;
/**
* Class InitException
* @package Kiri\Exception
*/
class InitException extends \Exception
{
}
+36 -36
View File
@@ -1,36 +1,36 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/4/24 0024
* Time: 17:32
*/
declare(strict_types=1);
namespace Kiri\Exception;
use JetBrains\PhpStorm\Pure;
use Throwable;
/**
* Class NotFindClassException
* @package Kiri\Kiri\Exception
*/
class NotFindClassException extends \Exception
{
/**
* NotFindClassException constructor.
* @param string $message
* @param int $code
* @param Throwable|null $previous
*/
#[Pure] public function __construct(string $message = "", int $code = 0, Throwable $previous = null)
{
$message = "No class named `$message` was found, please check if the class name is correct";
parent::__construct($message, 404, $previous);
}
}
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/4/24 0024
* Time: 17:32
*/
declare(strict_types=1);
namespace Kiri\Exception;
use JetBrains\PhpStorm\Pure;
use Throwable;
/**
* Class NotFindClassException
* @package Kiri\Kiri\Exception
*/
class NotFindClassException extends \Exception
{
/**
* NotFindClassException constructor.
* @param string $message
* @param int $code
* @param Throwable|null $previous
*/
#[Pure] public function __construct(string $message = "", int $code = 0, Throwable $previous = null)
{
$message = "No class named `$message` was found, please check if the class name is correct";
parent::__construct($message, 404, $previous);
}
}
@@ -1,35 +1,35 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/4/24 0024
* Time: 17:32
*/
declare(strict_types=1);
namespace Kiri\Exception;
use Throwable;
/**
* Class NotFindClassException
* @package Kiri\Kiri\Exception
*/
class NotFindPropertyException extends \Exception
{
/**
* NotFindClassException constructor.
* @param string $message
* @param int $code
* @param Throwable|null $previous
*/
public function __construct(string $message = "", int $code = 0, Throwable $previous = null)
{
$message = "No class named `$message` was found, please check if the class name is correct";
parent::__construct($message, 404, $previous);
}
}
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/4/24 0024
* Time: 17:32
*/
declare(strict_types=1);
namespace Kiri\Exception;
use Throwable;
/**
* Class NotFindClassException
* @package Kiri\Kiri\Exception
*/
class NotFindPropertyException extends \Exception
{
/**
* NotFindClassException constructor.
* @param string $message
* @param int $code
* @param Throwable|null $previous
*/
public function __construct(string $message = "", int $code = 0, Throwable $previous = null)
{
$message = "No class named `$message` was found, please check if the class name is correct";
parent::__construct($message, 404, $previous);
}
}
+15 -15
View File
@@ -1,15 +1,15 @@
<?php
declare(strict_types=1);
namespace Kiri\Exception;
/**
* Class RedisConnectException
* @package Kiri\Exception
*/
class RedisConnectException extends \Exception
{
}
<?php
declare(strict_types=1);
namespace Kiri\Exception;
/**
* Class RedisConnectException
* @package Kiri\Exception
*/
class RedisConnectException extends \Exception
{
}
+235 -154
View File
@@ -1,154 +1,235 @@
<?php
namespace Kiri\FileListen;
use Annotation\Inject;
use Exception;
use Kiri\Abstracts\Config;
use Kiri\Error\Logger;
use Kiri\Exception\ConfigException;
use Kiri\Kiri;
use Swoole\Coroutine;
use Swoole\Process;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
*
*/
class HotReload extends Command
{
public bool $isReloading = false;
public bool $isReloadingOut = false;
public ?array $dirs = [];
public int $events;
public int $int = -1;
private ?Process $process = null;
public Inotify|Scaner $driver;
#[Inject(Logger::class)]
public Logger $logger;
protected mixed $source = null;
protected mixed $pipes = [];
protected ?Coroutine\Channel $channel = null;
/**
*
*/
protected function configure()
{
$this->setName('sw:wather')
->setDescription('server start');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
* @throws ConfigException
* @throws Exception
*/
public function execute(InputInterface $input, OutputInterface $output): int
{
// TODO: Implement onHandler() method.
set_error_handler([$this, 'onErrorHandler']);
$this->dirs = Config::get('inotify', [APP_PATH . 'app']);
swoole_async_set(['enable_coroutine' => false]);
if (!extension_loaded('inotify')) {
$this->driver = Kiri::getDi()->make(Scaner::class, [$this->dirs, $this]);
} else {
$this->driver = Kiri::getDi()->make(Inotify::class, [$this->dirs, $this]);
}
if (Kiri::getPlatform()->isLinux()) {
swoole_set_process_name('[' . Config::get('id', 'sw service.') . '].sw:wather');
}
$this->trigger_reload();
var_dump(getmypid());
Process::signal(SIGTERM, [$this, 'onSignal']);
Process::signal(SIGKILL, [$this, 'onSignal']);
$this->driver->start();
return 0;
}
/**
* @param $data
* @throws Exception
*/
public function onSignal($data)
{
if (!$data) {
return;
}
$this->driver->clear();
$pid = file_get_contents(storage('.swoole.pid'));
if (!empty($pid) && Process::kill($pid, 0)) {
Process::kill($pid, SIGTERM);
}
if ($this->process && Process::kill($this->process->pid, 0)) {
Process::kill($this->process->pid) && Process::wait(true);
}
while ($ret = Process::wait(true)) {
echo "PID={$ret['pid']}\n";
sleep(1);
}
}
/**
* @param $code
* @param $message
* @param $file
* @param $line
* @throws Exception
*/
public function onErrorHandler($code, $message, $file, $line)
{
if (str_contains($message, 'The file descriptor is not an inotify instance')) {
return;
}
debug('Error:' . $message . ' at ' . $file . ':' . $line);
}
/**
* 重启
*
* @throws Exception
*/
public function trigger_reload()
{
$this->logger->warning('change reload');
$pid = $this->process?->pid;
$process = new Process(function (Process $process) {
$process->exec(PHP_BINARY, [APP_PATH . "kiri.php", "sw:server", "restart"]);
});
$process->start();
if ($pid && Process::kill($pid, 0)) {
Process::kill($pid) && Process::wait(true);
}
$this->process = null;
$this->process = $process;
}
}
<?php
namespace Kiri\FileListen;
use Exception;
use Kiri\Abstracts\Config;
use Kiri\Core\Json;
use Kiri\Error\Logger;
use Kiri\Exception\ConfigException;
use Kiri\Kiri;
use Kiri\Annotation\Inject;
use Swoole\Coroutine;
use Swoole\Process;
use Swoole\Timer;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
*
*/
class HotReload extends Command
{
public bool $isReloading = FALSE;
public bool $isReloadingOut = FALSE;
public ?array $dirs = [];
public int $events;
public int $int = -1;
private ?Process $process = NULL;
public Inotify|Scaner $driver;
#[Inject(Logger::class)]
public Logger $logger;
protected mixed $source = NULL;
protected mixed $pipes = [];
protected ?Coroutine\Channel $channel = NULL;
/**
*/
protected function configure()
{
$this->setName('sw:wather')->setDescription('server start');
}
/**
* @throws ConfigException
* @throws \ReflectionException
* @throws Exception
*/
protected function initCore()
{
set_error_handler([$this, 'errorHandler']);
$this->dirs = Config::get('inotify', [APP_PATH . 'app']);
if (!extension_loaded('inotify')) {
$this->driver = Kiri::getDi()->make(Scaner::class, [$this->dirs, $this]);
} else {
$this->driver = Kiri::getDi()->make(Inotify::class, [$this->dirs, $this]);
}
$this->clearOtherService();
$this->setProcessName();
}
/**
* @throws ConfigException
*/
public function setProcessName()
{
swoole_async_set(['enable_coroutine' => FALSE]);
if (Kiri::getPlatform()->isLinux()) {
swoole_set_process_name('[' . Config::get('id', 'sw service.') . '].sw:wather');
}
}
/**
* @throws Exception
*/
public function clearOtherService()
{
if (file_exists(storage('.manager.pid'))) {
$pid = (int)file_get_contents(storage('.manager.pid'));
if ($pid > 0 && Process::kill($pid, 0)) {
Process::kill($pid, 15) && Process::wait(TRUE);
}
}
file_put_contents(storage('.manager.pid'), getmypid());
}
/**
* @throws Exception
*/
public function errorHandler()
{
$error = func_get_args();
$path = ['file' => $error[2], 'line' => $error[3]];
if ($error[0] === 0) {
$error[0] = 500;
}
$data = Json::to(500, $error[1], $path);
$this->logger->error($data, 'error');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
* @throws ConfigException
* @throws Exception
*/
public function execute(InputInterface $input, OutputInterface $output): int
{
$this->initCore();
$this->trigger_reload();
Timer::tick(1000, fn() => $this->healthCheck());
Process::signal(SIGTERM, [$this, 'onSignal']);
Process::signal(SIGKILL, [$this, 'onSignal']);
$this->driver->start();
return 0;
}
/**
* @throws Exception
*/
public function healthCheck()
{
$pid = (int)file_get_contents(storage('.swoole.pid'));
if ($this->int == 1) {
return;
}
if (empty($pid)) {
$this->logger->warning('service is shutdown you need reload.');
$this->trigger_reload();
} else if (!Process::kill($pid, 0)) {
$this->logger->warning('service is shutdown you need reload.');
$this->trigger_reload();
}
}
/**
* @param $data
* @throws Exception
*/
public function onSignal($data)
{
if (!$data) {
return;
}
Timer::clearAll();
$this->driver->clear();
$this->stopServer();
$this->stopManager();
while ($ret = Process::wait(TRUE)) {
echo "PID={$ret['pid']}\n";
sleep(1);
}
}
/**
* @throws Exception
*/
protected function stopServer()
{
$pid = file_get_contents(storage('.swoole.pid'));
if (!empty($pid) && Process::kill($pid, 0)) {
Process::kill($pid, SIGTERM);
}
}
/**
*
*/
protected function stopManager()
{
if ($this->process && Process::kill($this->process->pid, 0)) {
Process::kill($this->process->pid) && Process::wait(TRUE);
}
}
/**
* 重启
*
* @throws Exception
*/
public function trigger_reload()
{
if ($this->int == 1) {
return;
}
$this->int = 1;
$this->logger->warning('change reload');
$this->stopServer();
$this->stopManager();
$this->process = new Process(function (Process $process) {
$process->exec(PHP_BINARY, [APP_PATH . "kiri.php", "sw:server", "start"]);
});
$this->process->start();
$this->int = -1;
}
}
+169 -158
View File
@@ -1,158 +1,169 @@
<?php
namespace Kiri\FileListen;
use Exception;
use Swoole\Event;
use Swoole\Timer;
class Inotify
{
private mixed $inotify;
private mixed $events;
private array $watchFiles = [];
protected bool $isReloading = FALSE;
protected int $cid;
const IG_DIR = [APP_PATH . 'commands', APP_PATH . '.git', APP_PATH . '.gitee'];
/**
* @param array $dirs
* @param HotReload $process
*/
public function __construct(protected array $dirs, public HotReload $process)
{
}
/**
* @throws Exception
*/
public function start()
{
$this->inotify = inotify_init();
$this->events = IN_MODIFY | IN_DELETE | IN_CREATE | IN_MOVE;
foreach ($this->dirs as $dir) {
if (!is_dir($dir)) continue;
$this->watch($dir);
}
Event::add($this->inotify, [$this, 'check']);
Event::wait();
}
public function clear()
{
Event::del($this->inotify);
Event::exit();
}
/**
* 开始监听
* @throws Exception
*/
public function check()
{
if (!($events = inotify_read($this->inotify))) {
return;
}
if ($this->isReloading) {
return;
}
$LISTEN_TYPE = [IN_CREATE, IN_DELETE, IN_MODIFY, IN_MOVED_TO, IN_MOVED_FROM];
foreach ($events as $ev) {
if (!in_array($ev['mask'], $LISTEN_TYPE)) {
continue;
}
//非重启类型
if (str_ends_with($ev['name'], '.php')) {
Timer::after(3000, fn()=>$this->reload());
$this->isReloading = TRUE;
}
}
}
/**
* @throws Exception
*/
public function reload()
{
$this->process->trigger_reload();
$this->clearWatch();
foreach ($this->dirs as $root) {
$this->watch($root);
}
$this->process->int = -1;
$this->isReloading = FALSE;
}
/**
* @throws Exception
*/
public function clearWatch()
{
foreach ($this->watchFiles as $wd) {
try {
inotify_rm_watch($this->inotify, $wd);
} catch (\Throwable $exception) {
logger()->addError($exception, 'throwable');
}
}
$this->watchFiles = [];
}
/**
* @param $dir
* @return bool
* @throws Exception
*/
public function watch($dir): bool
{
//目录不存在
if (!is_dir($dir)) {
return logger()->addError("[$dir] is not a directory.");
}
//避免重复监听
if (isset($this->watchFiles[$dir])) {
return FALSE;
}
if (in_array($dir, self::IG_DIR)) {
return FALSE;
}
$wd = @inotify_add_watch($this->inotify, $dir, $this->events);
$this->watchFiles[$dir] = $wd;
$files = scandir($dir);
foreach ($files as $f) {
if ($f == '.' || $f == '..') {
continue;
}
$path = $dir . '/' . $f;
//递归目录
if (is_dir($path)) {
$this->watch($path);
} else if (!str_ends_with($f, '.php')) {
continue;
}
//检测文件类型
if (strstr($f, '.') == '.php') {
$wd = @inotify_add_watch($this->inotify, $path, $this->events);
$this->watchFiles[$path] = $wd;
}
}
return TRUE;
}
}
<?php
namespace Kiri\FileListen;
use Exception;
use Swoole\Event;
use Swoole\Timer;
class Inotify
{
private mixed $inotify;
private mixed $events;
private array $watchFiles = [];
public bool $isReloading = FALSE;
protected int $cid;
const IG_DIR = [APP_PATH . 'commands', APP_PATH . '.git', APP_PATH . '.gitee'];
/**
* @param array $dirs
* @param HotReload $process
*/
public function __construct(protected array $dirs, public HotReload $process)
{
set_error_handler([$this, 'error']);
set_exception_handler([$this, 'error']);
}
/**
* @return void
*/
public function error(): void
{
}
/**
* @throws Exception
*/
public function start()
{
$this->inotify = inotify_init();
$this->events = IN_MODIFY | IN_DELETE | IN_CREATE | IN_MOVE;
foreach ($this->dirs as $dir) {
if (!is_dir($dir)) continue;
$this->watch($dir);
}
Event::add($this->inotify, [$this, 'check']);
Event::wait();
}
public function clear()
{
Event::del($this->inotify);
Event::exit();
}
/**
* 开始监听
* @throws Exception
*/
public function check()
{
if (!($events = inotify_read($this->inotify))) {
return;
}
if ($this->isReloading) {
return;
}
$LISTEN_TYPE = [IN_CREATE, IN_DELETE, IN_MODIFY, IN_MOVED_TO, IN_MOVED_FROM];
foreach ($events as $ev) {
if (!in_array($ev['mask'], $LISTEN_TYPE)) {
continue;
}
//非重启类型
if (str_ends_with($ev['name'], '.php')) {
Timer::after(3000, fn() => $this->reload());
$this->isReloading = TRUE;
}
}
}
/**
* @throws Exception
*/
public function reload()
{
$this->process->trigger_reload();
$this->clearWatch();
foreach ($this->dirs as $root) {
$this->watch($root);
}
$this->process->int = -1;
$this->isReloading = FALSE;
}
/**
* @throws Exception
*/
public function clearWatch()
{
foreach ($this->watchFiles as $wd) {
try {
@inotify_rm_watch($this->inotify, $wd);
} catch (\Throwable $exception) {
// logger()->addError($exception->getMessage(), 'throwable');
}
}
$this->watchFiles = [];
}
/**
* @param $dir
* @return bool
* @throws Exception
*/
public function watch($dir): bool
{
//目录不存在
if (!is_dir($dir)) {
return logger()->addError("[$dir] is not a directory.");
}
//避免重复监听
if (isset($this->watchFiles[$dir])) {
return FALSE;
}
if (in_array($dir, self::IG_DIR)) {
return FALSE;
}
$wd = @inotify_add_watch($this->inotify, $dir, $this->events);
$this->watchFiles[$dir] = $wd;
$files = scandir($dir);
foreach ($files as $f) {
if ($f == '.' || $f == '..') {
continue;
}
$path = $dir . '/' . $f;
//递归目录
if (is_dir($path)) {
$this->watch($path);
} else if (!str_ends_with($f, '.php')) {
continue;
}
//检测文件类型
if (strstr($f, '.') == '.php') {
$wd = @inotify_add_watch($this->inotify, $path, $this->events);
$this->watchFiles[$path] = $wd;
}
}
return TRUE;
}
}
+149 -147
View File
@@ -1,147 +1,149 @@
<?php
namespace Kiri\FileListen;
use Exception;
class Scaner
{
private array $md5Map = [];
/**
* @param array $dirs
* @param HotReload $process
*/
public function __construct(protected array $dirs, public HotReload $process)
{
}
/**
* @throws Exception
*/
public function start(): void
{
$this->loadDirs();
$this->tick();
}
/**
* @param bool $isReload
* @throws Exception
*/
private function loadDirs(bool $isReload = false)
{
foreach ($this->dirs as $value) {
if (is_bool($path = realpath($value))) {
continue;
}
if (!is_dir($path)) continue;
$this->loadByDir($path, $isReload);
}
}
/**
* @param $path
* @param bool $isReload
* @return void
* @throws Exception
*/
private function loadByDir($path, bool $isReload = false): void
{
if (!is_string($path)) {
return;
}
$path = rtrim($path, '/');
foreach (glob(realpath($path) . '/*') as $value) {
if (is_dir($value)) {
$this->loadByDir($value, $isReload);
}
if (is_file($value)) {
if ($this->checkFile($value, $isReload)) {
$this->timerReload();
break;
}
}
}
}
/**
* @param $value
* @param $isReload
* @return bool
*/
private function checkFile($value, $isReload): bool
{
$md5 = md5($value);
$mTime = filectime($value);
if (!isset($this->md5Map[$md5])) {
if ($isReload) {
return true;
}
$this->md5Map[$md5] = $mTime;
} else {
if ($this->md5Map[$md5] != $mTime) {
if ($isReload) {
return true;
}
$this->md5Map[$md5] = $mTime;
}
}
return false;
}
/**
* @throws Exception
*/
public function timerReload()
{
if ($this->process->isReloading) {
return;
}
$this->process->isReloading = true;
$this->process->trigger_reload();
$this->process->int = -1;
$this->loadDirs();
$this->process->isReloading = FALSE;
$this->process->isReloadingOut = FALSE;
$this->tick();
}
private bool $isStop = false;
public function clear()
{
$this->isStop = true;
}
/**
* @throws Exception
*/
public function tick()
{
if ($this->process->isReloading || $this->isStop) {
return;
}
$this->loadDirs(true);
sleep(2);
$this->tick();
}
}
<?php
namespace Kiri\FileListen;
use Exception;
use Swoole\Timer;
class Scaner
{
private array $md5Map = [];
public bool $isReloading = FALSE;
/**
* @param array $dirs
* @param HotReload $process
*/
public function __construct(protected array $dirs, public HotReload $process)
{
}
/**
* @throws Exception
*/
public function start(): void
{
$this->loadDirs();
$this->tick();
}
/**
* @param bool $isReload
* @throws Exception
*/
private function loadDirs(bool $isReload = FALSE)
{
foreach ($this->dirs as $value) {
if (is_bool($path = realpath($value))) {
continue;
}
if (!is_dir($path)) continue;
$this->loadByDir($path, $isReload);
}
}
/**
* @param $path
* @param bool $isReload
* @return void
* @throws Exception
*/
private function loadByDir($path, bool $isReload = FALSE): void
{
if (!is_string($path)) {
return;
}
$path = rtrim($path, '/');
foreach (glob(realpath($path) . '/*') as $value) {
if (is_dir($value)) {
$this->loadByDir($value, $isReload);
}
if (is_file($value)) {
if ($this->checkFile($value, $isReload)) {
Timer::after(2000, fn() => $this->timerReload());
$this->isReloading = TRUE;
break;
}
}
}
}
/**
* @param $value
* @param $isReload
* @return bool
*/
private function checkFile($value, $isReload): bool
{
$md5 = md5($value);
$mTime = filectime($value);
if (!isset($this->md5Map[$md5])) {
if ($isReload) {
return TRUE;
}
$this->md5Map[$md5] = $mTime;
} else {
if ($this->md5Map[$md5] != $mTime) {
if ($isReload) {
return TRUE;
}
$this->md5Map[$md5] = $mTime;
}
}
return FALSE;
}
/**
* @throws Exception
*/
public function timerReload()
{
$this->isReloading = TRUE;
$this->process->trigger_reload();
$this->process->int = -1;
$this->loadDirs();
$this->isReloading = FALSE;
$this->process->isReloadingOut = FALSE;
$this->tick();
}
private bool $isStop = FALSE;
public function clear()
{
$this->isStop = TRUE;
}
/**
* @throws Exception
*/
public function tick()
{
if ($this->isReloading || $this->isStop) {
return;
}
$this->loadDirs(TRUE);
sleep(2);
$this->tick();
}
}
+27 -27
View File
@@ -1,27 +1,27 @@
<?php
namespace Kiri;
interface IAspect
{
public function before(): void;
/**
* @param mixed $response
*/
public function after(mixed $response): void;
/**
* @param mixed $handler
* @param array $params
* @return mixed
*/
public function invoke(mixed $handler, array $params = []): mixed;
}
<?php
namespace Kiri;
interface IAspect
{
public function before(): void;
/**
* @param mixed $response
*/
public function after(mixed $response): void;
/**
* @param mixed $handler
* @param array $params
* @return mixed
*/
public function invoke(mixed $handler, array $params = []): mixed;
}
+13 -13
View File
@@ -1,13 +1,13 @@
<?php
namespace Kiri;
interface IProxy
{
public function execute();
}
<?php
namespace Kiri;
interface IProxy
{
public function execute();
}
+636 -633
View File
File diff suppressed because it is too large Load Diff
+24 -24
View File
@@ -1,24 +1,24 @@
<?php
namespace Kiri\Pool;
use JetBrains\PhpStorm\Pure;
trait Alias
{
/**
* @param $cds
* @param false $isMaster
* @return string
*/
#[Pure] public function name($cds, bool $isMaster = false): string
{
if ($isMaster === true) {
return $cds . '_master';
} else {
return $cds . '_slave';
}
}
}
<?php
namespace Kiri\Pool;
use JetBrains\PhpStorm\Pure;
trait Alias
{
/**
* @param $cds
* @param false $isMaster
* @return string
*/
#[Pure] public function name($cds, bool $isMaster = false): string
{
if ($isMaster === true) {
return $cds . '_master';
} else {
return $cds . '_slave';
}
}
}
+217 -219
View File
@@ -1,219 +1,217 @@
<?php
declare(strict_types=1);
namespace Kiri\Pool;
use Closure;
use Database\Mysql\PDO;
use Exception;
use Kiri\Abstracts\Component;
use Kiri\Abstracts\Config;
use Kiri\Context;
use Kiri\Kiri;
use Swoole\Error;
use Throwable;
/**
* Class Connection
* @package Kiri\Pool
*/
class Connection extends Component
{
use Alias;
/**
* @param $cds
* @return bool
*
* db is in transaction
* @throws Exception
*/
public function inTransaction($cds): bool
{
$name = $this->name('Mysql:' . $cds, true);
$connection = Context::getContext($name);
if ($connection instanceof PDO) {
return $connection->inTransaction();
}
return false;
}
/**
* @param $coroutineName
* @throws Exception
*/
public function beginTransaction($coroutineName)
{
$coroutineName = $this->name('Mysql:' . $coroutineName, true);
$connection = Context::getContext($coroutineName);
if ($connection instanceof PDO) {
$connection->beginTransaction();
}
}
/**
* @param $coroutineName
* @throws Exception
*/
public function commit($coroutineName)
{
$coroutineName = $this->name('Mysql:' . $coroutineName, true);
$connection = Context::getContext($coroutineName);
if ($connection instanceof PDO) {
$connection->commit();
}
}
/**
* @param $coroutineName
* @throws Exception
*/
public function rollback($coroutineName)
{
$coroutineName = $this->name('Mysql:' . $coroutineName, true);
$connection = Context::getContext($coroutineName);
if ($connection instanceof PDO) {
$connection->rollBack();
}
}
/**
* @param mixed $config
* @param bool $isMaster
* @return PDO|null
* @throws Exception
*/
public function get(mixed $config, bool $isMaster = false): ?PDO
{
$coroutineName = $this->name('Mysql:' . $config['cds'], $isMaster);
if (($pdo = Context::getContext($coroutineName)) instanceof PDO) {
return $pdo;
}
$minx = Config::get('databases.pool.min', 1);
/** @var PDO $connections */
$connections = $this->getPool()->get($coroutineName, $this->create($coroutineName, $config), $minx);
if (Context::hasContext('begin_' . $coroutineName)) {
$connections->beginTransaction();
}
return Context::setContext($coroutineName, $connections);
}
/**
* @param $coroutineName
* @param $config
* @return Closure
*/
public function create($coroutineName, $config): Closure
{
return static function () use ($coroutineName, $config) {
return Kiri::getDi()->create(PDO::class, [
$config['database'], $config['cds'], $config['username'], $config['password'], $config['charset'] ?? 'utf8mb4'
]);
};
}
/**
* @param $name
* @param $isMaster
* @param $max
* @throws Exception
*/
public function initConnections($name, $isMaster, $max)
{
$this->getPool()->initConnections($name, $isMaster, $max);
}
/**
* @param $coroutineName
* @param $isMaster
* @throws Exception
*/
public function release($coroutineName, $isMaster)
{
$coroutineName = $this->name('Mysql:' . $coroutineName, $isMaster);
/** @var PDO $client */
if (!($client = Context::getContext($coroutineName)) instanceof PDO) {
return;
}
if ($client->inTransaction()) {
return;
}
$this->getPool()->push($coroutineName, $client);
Context::remove($coroutineName);
}
/**
* @param $coroutineName
* @return bool
*/
private function hasClient($coroutineName): bool
{
return Context::hasContext($coroutineName);
}
/**
* batch release
* @throws Exception
*/
public function connection_clear($name, $isMaster)
{
$this->getPool()->clean($this->name($name, $isMaster));
}
/**
* @param string $name
* @param mixed $client
* @return bool
* @throws Exception
*/
public function checkCanUse(string $name, mixed $client): bool
{
try {
if (empty($client) || !($client instanceof PDO)) {
$result = false;
} else {
$result = true;
}
} catch (Error | Throwable $exception) {
$result = $this->addError($exception, 'mysql');
} finally {
return $result;
}
}
/**
* @param $coroutineName
* @param bool $isMaster
* @throws Exception
*/
public function disconnect($coroutineName, bool $isMaster = false)
{
Context::remove($coroutineName);
$coroutineName = $this->name('Mysql:' . $coroutineName, $isMaster);
$this->getPool()->clean($coroutineName);
}
/**
* @return Pool
* @throws Exception
*/
public function getPool(): Pool
{
return Kiri::getDi()->get(Pool::class);
}
}
<?php
declare(strict_types=1);
namespace Kiri\Pool;
use Closure;
use Database\Mysql\PDO;
use Exception;
use Kiri\Abstracts\Component;
use Kiri\Abstracts\Config;
use Kiri\Context;
use Kiri\Kiri;
use Swoole\Error;
use Throwable;
/**
* Class Connection
* @package Kiri\Pool
*/
class Connection extends Component
{
use Alias;
/**
* @param $cds
* @return bool
*
* db is in transaction
* @throws Exception
*/
public function inTransaction($cds): bool
{
$name = $this->name('Mysql:' . $cds, true);
$connection = Context::getContext($name);
if ($connection instanceof PDO) {
return $connection->inTransaction();
}
return false;
}
/**
* @param $coroutineName
* @throws Exception
*/
public function beginTransaction($coroutineName)
{
$coroutineName = $this->name('Mysql:' . $coroutineName, true);
$connection = Context::getContext($coroutineName);
if ($connection instanceof PDO) {
$connection->beginTransaction();
}
}
/**
* @param $coroutineName
* @throws Exception
*/
public function commit($coroutineName)
{
$coroutineName = $this->name('Mysql:' . $coroutineName, true);
$connection = Context::getContext($coroutineName);
if ($connection instanceof PDO) {
$connection->commit();
}
}
/**
* @param $coroutineName
* @throws Exception
*/
public function rollback($coroutineName)
{
$coroutineName = $this->name('Mysql:' . $coroutineName, true);
$connection = Context::getContext($coroutineName);
if ($connection instanceof PDO) {
$connection->rollBack();
}
}
/**
* @param mixed $config
* @param bool $isMaster
* @return PDO|null
* @throws Exception
*/
public function get(mixed $config, bool $isMaster = false): ?PDO
{
$coroutineName = $this->name('Mysql:' . $config['cds'], $isMaster);
if (($pdo = Context::getContext($coroutineName)) instanceof PDO) {
return $pdo;
}
$minx = Config::get('databases.pool.min', 1);
/** @var PDO $connections */
$connections = $this->getPool()->get($coroutineName, $this->create($coroutineName, $config), $minx);
if (Context::hasContext('begin_' . $coroutineName)) {
$connections->beginTransaction();
}
return Context::setContext($coroutineName, $connections);
}
/**
* @param $coroutineName
* @param $config
* @return Closure
*/
public function create($coroutineName, $config): Closure
{
return static function () use ($coroutineName, $config) {
return Kiri::getDi()->create(PDO::class, [$config]);
};
}
/**
* @param $name
* @param $isMaster
* @param $max
* @throws Exception
*/
public function initConnections($name, $isMaster, $max)
{
$this->getPool()->initConnections($name, $isMaster, $max);
}
/**
* @param $coroutineName
* @param $isMaster
* @throws Exception
*/
public function release($coroutineName, $isMaster)
{
$coroutineName = $this->name('Mysql:' . $coroutineName, $isMaster);
/** @var PDO $client */
if (!($client = Context::getContext($coroutineName)) instanceof PDO) {
return;
}
if ($client->inTransaction()) {
return;
}
$this->getPool()->push($coroutineName, $client);
Context::remove($coroutineName);
}
/**
* @param $coroutineName
* @return bool
*/
private function hasClient($coroutineName): bool
{
return Context::hasContext($coroutineName);
}
/**
* batch release
* @throws Exception
*/
public function connection_clear($name, $isMaster)
{
$this->getPool()->clean($this->name($name, $isMaster));
}
/**
* @param string $name
* @param mixed $client
* @return bool
* @throws Exception
*/
public function checkCanUse(string $name, mixed $client): bool
{
try {
if (empty($client) || !($client instanceof PDO)) {
$result = false;
} else {
$result = true;
}
} catch (Error | Throwable $exception) {
$result = $this->addError($exception, 'mysql');
} finally {
return $result;
}
}
/**
* @param $coroutineName
* @param bool $isMaster
* @throws Exception
*/
public function disconnect($coroutineName, bool $isMaster = false)
{
Context::remove($coroutineName);
$coroutineName = $this->name('Mysql:' . $coroutineName, $isMaster);
$this->getPool()->clean($coroutineName);
}
/**
* @return Pool
* @throws Exception
*/
public function getPool(): Pool
{
return Kiri::getDi()->get(Pool::class);
}
}
+28 -28
View File
@@ -1,28 +1,28 @@
<?php
namespace Kiri\Pool\Helper;
interface QueueInterface
{
public function isEmpty(): bool;
public function push(mixed $data, float $timeout = -1): bool;
public function pop(float $timeout = -1): mixed;
public function stats(): array;
public function close(): bool;
public function length(): int;
public function isFull(): bool;
}
<?php
namespace Kiri\Pool\Helper;
interface QueueInterface
{
public function isEmpty(): bool;
public function push(mixed $data, float $timeout = -1): bool;
public function pop(float $timeout = -1): mixed;
public function stats(): array;
public function close(): bool;
public function length(): int;
public function isFull(): bool;
}
+101 -101
View File
@@ -1,101 +1,101 @@
<?php
namespace Kiri\Pool\Helper;
use JetBrains\PhpStorm\Pure;
/**
*
*/
class SplQueue implements QueueInterface
{
private \SplQueue $channel;
public int $errCode = 0;
/**
* @param int $max
*/
#[Pure] public function __construct(public int $max)
{
$this->channel = new \SplQueue();
}
/**
* @return bool
*/
public function isEmpty(): bool
{
// TODO: Implement isEmpty() method.
return $this->channel->count() < 1;
}
/**
* @param mixed $data
* @param float $timeout
* @return bool
*/
public function push(mixed $data, float $timeout = -1): bool
{
// TODO: Implement push() method.
$this->channel->enqueue($data);
return true;
}
/**
* @param float $timeout
* @return mixed
*/
public function pop(float $timeout = -1): mixed
{
// TODO: Implement pop() method.
return $this->channel->dequeue();
}
/**
* @return array
*/
public function stats(): array
{
// TODO: Implement stats() method.
return [];
}
/**
* @return bool
*/
public function close(): bool
{
// TODO: Implement close() method.
return false;
}
/**
* @return int
*/
public function length(): int
{
// TODO: Implement length() method.
return $this->channel->count();
}
/**
* @return bool
*/
public function isFull(): bool
{
// TODO: Implement isFull() method.
return $this->channel->count() >= $this->max;
}
}
<?php
namespace Kiri\Pool\Helper;
use JetBrains\PhpStorm\Pure;
/**
*
*/
class SplQueue implements QueueInterface
{
private \SplQueue $channel;
public int $errCode = 0;
/**
* @param int $max
*/
#[Pure] public function __construct(public int $max)
{
$this->channel = new \SplQueue();
}
/**
* @return bool
*/
public function isEmpty(): bool
{
// TODO: Implement isEmpty() method.
return $this->channel->count() < 1;
}
/**
* @param mixed $data
* @param float $timeout
* @return bool
*/
public function push(mixed $data, float $timeout = -1): bool
{
// TODO: Implement push() method.
$this->channel->enqueue($data);
return true;
}
/**
* @param float $timeout
* @return mixed
*/
public function pop(float $timeout = -1): mixed
{
// TODO: Implement pop() method.
return $this->channel->dequeue();
}
/**
* @return array
*/
public function stats(): array
{
// TODO: Implement stats() method.
return [];
}
/**
* @return bool
*/
public function close(): bool
{
// TODO: Implement close() method.
return false;
}
/**
* @return int
*/
public function length(): int
{
// TODO: Implement length() method.
return $this->channel->count();
}
/**
* @return bool
*/
public function isFull(): bool
{
// TODO: Implement isFull() method.
return $this->channel->count() >= $this->max;
}
}
+249 -249
View File
@@ -1,249 +1,249 @@
<?php
namespace Kiri\Pool;
use Exception;
use Kiri\Context;
use Kiri\Abstracts\Component;
use Kiri\Abstracts\Config;
use Kiri\Exception\ConfigException;
use Kiri\Pool\Helper\SplQueue;
use Swoole\Coroutine;
use Swoole\Coroutine\Channel;
/**
* Class Pool
* @package Kiri\Pool
*/
class Pool extends Component
{
/** @var Channel[] */
private static array $_connections = [];
public int $max = 60;
use Alias;
/**
* @param $channel
* @param $retain_number
* @throws Exception
*/
public function flush($channel, $retain_number)
{
$this->pop($channel, $retain_number);
}
/**
* @param Channel $channel
* @param $retain_number
* @throws Exception
*/
protected function pop(Channel $channel, $retain_number): void
{
while ($channel->length() > $retain_number) {
if (Context::inCoroutine()) {
$connection = $channel->pop();
if ($connection instanceof StopHeartbeatCheck) {
$connection->stopHeartbeatCheck();
}
}
}
}
/**
* @param $name
* @param false $isMaster
* @param int $max
* @throws ConfigException
*/
public function initConnections($name, bool $isMaster = false, int $max = 60)
{
$name = $this->name($name, $isMaster);
if (isset(static::$_connections[$name])) {
$value = static::$_connections[$name];
if ($value instanceof Channel || $value instanceof SplQueue) {
return;
}
}
$this->newChannel($name, $max);
$this->max = $max;
}
/**
* @param $name
* @return Channel|SplQueue
* @throws ConfigException
* @throws Exception
*/
private function getChannel($name): Channel|SplQueue
{
if (!isset(static::$_connections[$name])) {
$this->newChannel($name);
}
if (static::$_connections[$name]->errCode == SWOOLE_CHANNEL_CLOSED) {
throw new Exception('Channel is Close.');
}
return static::$_connections[$name];
}
/**
* @throws ConfigException
*/
private function newChannel($name, $max = null)
{
if ($max == null) {
$max = Config::get('databases.pool.max', 10);
}
if (Coroutine::getCid() === -1) {
static::$_connections[$name] = new SplQueue($max);
} else {
static::$_connections[$name] = new Channel($max);
}
}
/**
* @param $name
* @param $callback
* @param $minx
* @return array
* @throws ConfigException
* @throws Exception
*/
public function get($name, $callback, $minx): mixed
{
$channel = $this->getChannel($name);
if (!$channel->isEmpty()) {
return $this->maxIdleQuantity($channel, $minx);
}
return $callback();
}
/**
* @param $channel
* @param $minx
* @return mixed
* @throws Exception
*/
protected function maxIdleQuantity($channel, $minx): mixed
{
$connection = $channel->pop();
if ($channel->length() > $minx) {
$this->pop($channel, $minx);
}
return $connection;
}
/**
* @param $name
* @return bool
* @throws ConfigException
*/
public function isNull($name): bool
{
return $this->getChannel($name)->isEmpty();
}
/**
* @param string $name
* @param mixed $client
* @return bool
* 检查连接可靠性
*/
public function checkCanUse(string $name, mixed $client): bool
{
return true;
}
/**
* @param string $name
* @return bool
*/
public function hasItem(string $name): bool
{
if (isset(static::$_connections[$name])) {
return !static::$_connections[$name]->isEmpty();
}
return false;
}
/**
* @param string $name
* @return mixed
*/
public function size(string $name): mixed
{
if (!isset(static::$_connections[$name])) {
return 0;
}
return static::$_connections[$name]->length();
}
/**
* @param string $name
* @param mixed $client
* @throws ConfigException
*/
public function push(string $name, mixed $client)
{
$channel = $this->getChannel($name);
if (!$channel->isFull()) {
$channel->push($client);
}
unset($client);
}
/**
* @param string $name
* @throws Exception
*/
public function clean(string $name)
{
if (!isset(static::$_connections[$name])) {
return;
}
while (static::$_connections[$name]->length() > 0) {
if (static::$_connections[$name] instanceof Channel)
{
if (!Context::inCoroutine())
{
break;
}
}
$client = static::$_connections[$name]->pop();
if ($client instanceof StopHeartbeatCheck) {
$client->stopHeartbeatCheck();
}
}
static::$_connections[$name] = null;
unset(static::$_connections[$name]);
}
/**
* @return Channel[]
*/
protected function getChannels(): array
{
return static::$_connections;
}
}
<?php
namespace Kiri\Pool;
use Exception;
use Kiri\Context;
use Kiri\Abstracts\Component;
use Kiri\Abstracts\Config;
use Kiri\Exception\ConfigException;
use Kiri\Pool\Helper\SplQueue;
use Swoole\Coroutine;
use Swoole\Coroutine\Channel;
/**
* Class Pool
* @package Kiri\Pool
*/
class Pool extends Component
{
/** @var Channel[] */
private static array $_connections = [];
public int $max = 60;
use Alias;
/**
* @param $channel
* @param $retain_number
* @throws Exception
*/
public function flush($channel, $retain_number)
{
$this->pop($channel, $retain_number);
}
/**
* @param Channel $channel
* @param $retain_number
* @throws Exception
*/
protected function pop(Channel $channel, $retain_number): void
{
while ($channel->length() > $retain_number) {
if (Context::inCoroutine()) {
$connection = $channel->pop();
if ($connection instanceof StopHeartbeatCheck) {
$connection->stopHeartbeatCheck();
}
}
}
}
/**
* @param $name
* @param false $isMaster
* @param int $max
* @throws ConfigException
*/
public function initConnections($name, bool $isMaster = false, int $max = 60)
{
$name = $this->name($name, $isMaster);
if (isset(static::$_connections[$name])) {
$value = static::$_connections[$name];
if ($value instanceof Channel || $value instanceof SplQueue) {
return;
}
}
$this->newChannel($name, $max);
$this->max = $max;
}
/**
* @param $name
* @return Channel|SplQueue
* @throws ConfigException
* @throws Exception
*/
private function getChannel($name): Channel|SplQueue
{
if (!isset(static::$_connections[$name])) {
$this->newChannel($name);
}
if (static::$_connections[$name]->errCode == SWOOLE_CHANNEL_CLOSED) {
throw new Exception('Channel is Close.');
}
return static::$_connections[$name];
}
/**
* @throws ConfigException
*/
private function newChannel($name, $max = null)
{
if ($max == null) {
$max = Config::get('databases.pool.max', 10);
}
if (Coroutine::getCid() === -1) {
static::$_connections[$name] = new SplQueue($max);
} else {
static::$_connections[$name] = new Channel($max);
}
}
/**
* @param $name
* @param $callback
* @param $minx
* @return array
* @throws ConfigException
* @throws Exception
*/
public function get($name, $callback, $minx): mixed
{
$channel = $this->getChannel($name);
if (!$channel->isEmpty()) {
return $this->maxIdleQuantity($channel, $minx);
}
return $callback();
}
/**
* @param $channel
* @param $minx
* @return mixed
* @throws Exception
*/
protected function maxIdleQuantity($channel, $minx): mixed
{
$connection = $channel->pop();
if ($channel->length() > $minx) {
$this->pop($channel, $minx);
}
return $connection;
}
/**
* @param $name
* @return bool
* @throws ConfigException
*/
public function isNull($name): bool
{
return $this->getChannel($name)->isEmpty();
}
/**
* @param string $name
* @param mixed $client
* @return bool
* 检查连接可靠性
*/
public function checkCanUse(string $name, mixed $client): bool
{
return true;
}
/**
* @param string $name
* @return bool
*/
public function hasItem(string $name): bool
{
if (isset(static::$_connections[$name])) {
return !static::$_connections[$name]->isEmpty();
}
return false;
}
/**
* @param string $name
* @return mixed
*/
public function size(string $name): mixed
{
if (!isset(static::$_connections[$name])) {
return 0;
}
return static::$_connections[$name]->length();
}
/**
* @param string $name
* @param mixed $client
* @throws ConfigException
*/
public function push(string $name, mixed $client)
{
$channel = $this->getChannel($name);
if (!$channel->isFull()) {
$channel->push($client);
}
unset($client);
}
/**
* @param string $name
* @throws Exception
*/
public function clean(string $name)
{
if (!isset(static::$_connections[$name])) {
return;
}
while (static::$_connections[$name]->length() > 0) {
if (static::$_connections[$name] instanceof Channel)
{
if (!Context::inCoroutine())
{
break;
}
}
$client = static::$_connections[$name]->pop();
if ($client instanceof StopHeartbeatCheck) {
$client->stopHeartbeatCheck();
}
}
static::$_connections[$name] = null;
unset(static::$_connections[$name]);
}
/**
* @return Channel[]
*/
protected function getChannels(): array
{
return static::$_connections;
}
}
+122 -126
View File
@@ -1,126 +1,122 @@
<?php
declare(strict_types=1);
namespace Kiri\Pool;
use Closure;
use Exception;
use Kiri\Abstracts\Component;
use Kiri\Context;
use Kiri\Exception\ConfigException;
use Kiri\Kiri;
/**
* Class RedisClient
* @package Kiri\Kiri\Pool
*/
class Redis extends Component
{
use Alias;
/**
* @param mixed $config
* @param bool $isMaster
* @return mixed
* @throws Exception
*/
public function get(mixed $config, bool $isMaster = false): mixed
{
$coroutineName = $this->name('Redis:' . $config['host'], $isMaster);
if (Context::hasContext($coroutineName)) {
return Context::getContext($coroutineName);
}
$pool = $config['pool'] ?? ['min' => 1, 'max' => 100];
$clients = $this->getPool()->get($coroutineName, $this->create($coroutineName, $config), $pool['min'] ?? 1);
return Context::setContext($coroutineName, $clients);
}
/**
* @param string $name
* @param mixed $config
* @return Closure
*/
public function create(string $name, mixed $config): Closure
{
return static function () use ($name, $config) {
return Kiri::getDi()->create(\Kiri\Cache\Base\Redis::class, [
$config['host'], (int)$config['port'], $config['databases'] ?? 0,
$config['auth'], $config['prefix'] ?? '', $config['timeout'] ?? 30,
$config['read_timeout'] ?? 30
]);
};
}
/**
* @param array $config
* @param bool $isMaster
* @throws ConfigException
* @throws Exception
*/
public function release(array $config, bool $isMaster = false)
{
$coroutineName = $this->name('Redis:' . $config['host'], $isMaster);
if (!Context::hasContext($coroutineName)) {
return;
}
$this->getPool()->push($coroutineName, Context::getContext($coroutineName));
Context::remove($coroutineName);
}
/**
* @param array $config
* @param bool $isMaster
* @throws Exception
*/
public function destroy(array $config, bool $isMaster = false)
{
$coroutineName = $this->name('Redis:' . $config['host'], $isMaster);
$this->getPool()->clean($coroutineName);
Context::remove($coroutineName);
}
/**
* @param array $config
* @param bool $isMaster
* @throws Exception
*/
public function connection_clear(array $config, bool $isMaster = false)
{
$coroutineName = $this->name('Redis:' . $config['host'], $isMaster);
$this->getPool()->clean($coroutineName);
}
/**
* @return Pool
* @throws Exception
*/
public function getPool(): Pool
{
return Kiri::getDi()->get(Pool::class);
}
/**
* @param $name
* @param $isMaster
* @param $max
* @throws Exception
*/
public function initConnections($name, $isMaster, $max)
{
$this->getPool()->initConnections($name, $isMaster, $max);
}
}
<?php
declare(strict_types=1);
namespace Kiri\Pool;
use Closure;
use Exception;
use Kiri\Abstracts\Component;
use Kiri\Context;
use Kiri\Exception\ConfigException;
use Kiri\Kiri;
/**
* Class RedisClient
* @package Kiri\Kiri\Pool
*/
class Redis extends Component
{
use Alias;
/**
* @param mixed $config
* @param bool $isMaster
* @return mixed
* @throws Exception
*/
public function get(mixed $config, bool $isMaster = false): mixed
{
$coroutineName = $this->name('Redis:' . $config['host'], $isMaster);
if (Context::hasContext($coroutineName)) {
return Context::getContext($coroutineName);
}
$pool = $config['pool'] ?? ['min' => 1, 'max' => 100];
$clients = $this->getPool()->get($coroutineName, $this->create($coroutineName, $config), $pool['min'] ?? 1);
return Context::setContext($coroutineName, $clients);
}
/**
* @param string $name
* @param mixed $config
* @return Closure
*/
public function create(string $name, mixed $config): Closure
{
return static function () use ($name, $config) {
return Kiri::getDi()->create(\Kiri\Cache\Base\Redis::class, [$config]);
};
}
/**
* @param array $config
* @param bool $isMaster
* @throws ConfigException
* @throws Exception
*/
public function release(array $config, bool $isMaster = false)
{
$coroutineName = $this->name('Redis:' . $config['host'], $isMaster);
if (!Context::hasContext($coroutineName)) {
return;
}
$this->getPool()->push($coroutineName, Context::getContext($coroutineName));
Context::remove($coroutineName);
}
/**
* @param array $config
* @param bool $isMaster
* @throws Exception
*/
public function destroy(array $config, bool $isMaster = false)
{
$coroutineName = $this->name('Redis:' . $config['host'], $isMaster);
$this->getPool()->clean($coroutineName);
Context::remove($coroutineName);
}
/**
* @param array $config
* @param bool $isMaster
* @throws Exception
*/
public function connection_clear(array $config, bool $isMaster = false)
{
$coroutineName = $this->name('Redis:' . $config['host'], $isMaster);
$this->getPool()->clean($coroutineName);
}
/**
* @return Pool
* @throws Exception
*/
public function getPool(): Pool
{
return Kiri::getDi()->get(Pool::class);
}
/**
* @param $name
* @param $isMaster
* @param $max
* @throws Exception
*/
public function initConnections($name, $isMaster, $max)
{
$this->getPool()->initConnections($name, $isMaster, $max);
}
}
+11 -11
View File
@@ -1,11 +1,11 @@
<?php
namespace Kiri\Pool;
interface StopHeartbeatCheck
{
public function stopHeartbeatCheck();
}
<?php
namespace Kiri\Pool;
interface StopHeartbeatCheck
{
public function stopHeartbeatCheck();
}
+27 -27
View File
@@ -1,27 +1,27 @@
<?php
namespace Kiri;
class Proxy
{
/**
* Proxy constructor.
* @param IProxy $IProxy
*/
public function __construct(public IProxy $IProxy)
{
}
/**
* @return mixed
*/
public function execute(): mixed
{
return $this->IProxy->execute();
}
}
<?php
namespace Kiri;
class Proxy
{
/**
* Proxy constructor.
* @param IProxy $IProxy
*/
public function __construct(public IProxy $IProxy)
{
}
/**
* @return mixed
*/
public function execute(): mixed
{
return $this->IProxy->execute();
}
}
+101 -101
View File
@@ -1,101 +1,101 @@
<?php
namespace Kiri;
use Exception;
use Kiri\Abstracts\Input;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Class Runtime
* @package Kiri
*/
class Runtime extends Command
{
public string $command = 'runtime:builder';
public string $description = 'create app file cache';
const CACHE_NAME = '.runtime.cache';
const CONFIG_NAME = '.config.cache';
protected function configure()
{
$this->setName('runtime:builder');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
* @throws Exception
*/
public function execute(InputInterface $input, OutputInterface $output): int
{
// TODO: Implement onHandler() method.
$annotation = Kiri::app()->getAnnotation();
$runtime = storage(static::CACHE_NAME);
$config = storage(static::CONFIG_NAME);
Kiri::writeFile($config, $this->configEach());
Kiri::writeFile($runtime, serialize($annotation->getLoader()));
return 1;
}
/**
* @return string
* @throws Exception
*/
public function configEach(): string
{
$array = [];
$configs = Kiri::app()->getConfig();
foreach ($configs->getData() as $key => $datum) {
if ($datum instanceof \Closure) {
continue;
}
if (is_array($datum)) {
$array[$key] = $this->arrayEach($datum);
} else {
$array[$key] = $datum;
}
}
return serialize($array);
}
/**
* @param array $value
* @return array
*/
private function arrayEach(array $value): array
{
$array = [];
foreach ($value as $key => $item) {
if ($item instanceof \Closure) {
continue;
}
if (is_array($item)) {
$array[$key] = $this->arrayEach($item);
} else {
$array[$key] = $item;
}
}
return $array;
}
}
<?php
namespace Kiri;
use Exception;
use Kiri\Abstracts\Config;
use Kiri\Abstracts\Input;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Class Runtime
* @package Kiri
*/
class Runtime extends Command
{
public string $command = 'runtime:builder';
public string $description = 'create app file cache';
const CACHE_NAME = '.runtime.cache';
const CONFIG_NAME = '.config.cache';
protected function configure()
{
$this->setName('runtime:builder');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
* @throws Exception
*/
public function execute(InputInterface $input, OutputInterface $output): int
{
// TODO: Implement onHandler() method.
$annotation = Kiri::app()->getAnnotation();
$runtime = storage(static::CACHE_NAME);
$config = storage(static::CONFIG_NAME);
Kiri::writeFile($config, $this->configEach());
Kiri::writeFile($runtime, serialize($annotation->getLoader()));
return 1;
}
/**
* @return string
* @throws Exception
*/
public function configEach(): string
{
$array = [];
foreach (Config::getData() as $key => $datum) {
if ($datum instanceof \Closure) {
continue;
}
if (is_array($datum)) {
$array[$key] = $this->arrayEach($datum);
} else {
$array[$key] = $datum;
}
}
return serialize($array);
}
/**
* @param array $value
* @return array
*/
private function arrayEach(array $value): array
{
$array = [];
foreach ($value as $key => $item) {
if ($item instanceof \Closure) {
continue;
}
if (is_array($item)) {
$array[$key] = $this->arrayEach($item);
} else {
$array[$key] = $item;
}
}
return $array;
}
}
+10 -10
View File
@@ -1,10 +1,10 @@
<?php
namespace Kiri;
interface ToArray
{
public function toArray();
}
<?php
namespace Kiri;
interface ToArray
{
public function toArray();
}
+14
View File
@@ -0,0 +1,14 @@
<?php
namespace Kiri\Gateway;
class Collector
{
public function get()
{
}
}
+23
View File
@@ -0,0 +1,23 @@
<?php
namespace Kiri\Gateway;
use Swoole\Http\Request;
use Swoole\Http\Response;
class GatewayServer
{
/**
* @param Request $request
* @param Response $response
*/
public function onRequest(Request $request, Response $response)
{
}
}
+35
View File
@@ -0,0 +1,35 @@
<?php
namespace Kiri\Gateway;
class HashMap
{
const HTTP = 1;
const TCP = 2;
const UDP = 2;
public string $domain;
public string $path;
public string $scheme;
public string $method;
public string $proxy_host;
public string $proxy_port;
public int $type = self::HTTP;
}
+342 -343
View File
@@ -1,343 +1,342 @@
<?php
/**
* Created by PhpStorm.
* User: 向林
* Date: 2016/8/9 0009
* Time: 17:43
*/
declare(strict_types=1);
namespace Gii;
use Database\Connection;
use Database\Db;
use Exception;
use Kiri\Cache\Redis;
use Kiri\Kiri;
use Symfony\Component\Console\Input\InputInterface;
/**
* Class gii
*
* @package Inter\utility
*/
class Gii
{
private ?string $tableName = NULL;
/** @var null|Connection */
private ?Connection $db;
private InputInterface $input;
public string $modelPath = APP_PATH . 'app/Model/';
public string $modelNamespace = 'App\\Model\\';
public string $controllerPath = APP_PATH . 'app/Http/Controller/';
public string $controllerNamespace = 'App\\Controller\\';
public static array $createSqls = [];
public array $keyword = [
'ADD', 'ALL', 'ALTER', 'AND', 'AS', 'ASC', 'ASENSITIVE', 'BEFORE', 'BETWEEN', 'BIGINT', 'BINARY', 'BLOB', 'BOTH', 'BY', 'CALL', 'CASCADE', 'CASE', 'CHANGE', 'CHAR', 'CHARACTER', 'CHECK', 'COLLATE', 'COLUMN', 'CONDITION', 'CONNECTION', 'CONSTRAINT', 'CONTINUE', 'CONVERT', 'CREATE', 'CROSS', 'CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'CURRENT_USER', 'CURSOR', 'DATABASE', 'DATABASES', 'DAY_HOUR', 'DAY_MICROSECOND', 'DAY_MINUTE', 'DAY_SECOND', 'DEC', 'DECIMAL', 'DECLARE', 'DEFAULT', 'DELAYED', 'DELETE', 'DESC', 'DESCRIBE', 'DETERMINISTIC', 'DISTINCT', 'DISTINCTROW', 'DIV', 'DOUBLE', 'DROP', 'DUAL', 'EACH', 'ELSE', 'ELSEIF', 'ENCLOSED', 'ESCAPED', 'EXISTS', 'EXIT', 'EXPLAIN', 'FALSE', 'FETCH', 'FLOAT', 'FLOAT4', 'FLOAT8', 'FOR', 'FORCE', 'FOREIGN', 'FROM', 'FULLTEXT', 'GOTO', 'GRANT', 'GROUP', 'HAVING', 'HIGH_PRIORITY', 'HOUR_MICROSECOND', 'HOUR_MINUTE', 'HOUR_SECOND', 'IF', 'IGNORE', 'IN', 'INDEX', 'INFILE', 'INNER', 'INOUT', 'INSENSITIVE', 'INSERT', 'INT', 'INT1', 'INT2', 'INT3', 'INT4', 'INT8', 'INTEGER', 'INTERVAL', 'INTO', 'IS', 'ITERATE', 'JOIN', 'KEY', 'KEYS', 'KILL', 'LABEL', 'LEADING', 'LEAVE', 'LEFT', 'LIKE', 'LIMIT', 'LINEAR', 'LINES', 'LOAD', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCK', 'LONG', 'LONGBLOB', 'LONGTEXT', 'LOOP', 'LOW_PRIORITY', 'MATCH', 'MEDIUMBLOB', 'MEDIUMINT', 'MEDIUMTEXT', 'MIDDLEINT', 'MINUTE_MICROSECOND', 'MINUTE_SECOND', 'MOD', 'MODIFIES', 'NATURAL', 'NOT', 'NO_WRITE_TO_BINLOG', 'NULL', 'NUMERIC', 'ON', 'OPTIMIZE', 'OPTION', 'OPTIONALLY', 'OR', 'ORDER', 'OUT', 'OUTER', 'OUTFILE', 'PRECISION', 'PRIMARY', 'PROCEDURE', 'PURGE', 'RAID0', 'RANGE', 'READ', 'READS', 'REAL', 'REFERENCES', 'REGEXP', 'RELEASE', 'RENAME', 'REPEAT', 'REPLACE', 'REQUIRE', 'RESTRICT', 'RETURN', 'REVOKE', 'RIGHT', 'RLIKE', 'SCHEMA', 'SCHEMAS', 'SECOND_MICROSECOND', 'SELECT', 'SENSITIVE', 'SEPARATOR', 'SET', 'SHOW', 'SMALLINT', 'SPATIAL', 'SPECIFIC', 'SQL', 'SQLEXCEPTION', 'SQLSTATE', 'SQLWARNING', 'SQL_BIG_RESULT', 'SQL_CALC_FOUND_ROWS', 'SQL_SMALL_RESULT', 'SSL', 'STARTING', 'STRAIGHT_JOIN', 'TABLE', 'TERMINATED', 'THEN', 'TINYBLOB', 'TINYINT', 'TINYTEXT', 'TO', 'TRAILING', 'TRIGGER', 'TRUE', 'UNDO', 'UNION', 'UNIQUE', 'UNLOCK', 'UNSIGNED', 'UPDATE', 'USAGE', 'USE', 'USING', 'UTC_DATE', 'UTC_TIME', 'UTC_TIMESTAMP', 'VALUES', 'VARBINARY', 'VARCHAR', 'VARCHARACTER', 'VARYING', 'WHEN', 'WHERE', 'WHILE', 'WITH', 'WRITE', 'X509', 'XOR', 'YEAR_MONTH', 'ZEROFILL'
];
/**
* @param Connection|null $db
*
* @param InputInterface $input
* @return array
* @throws Exception
*/
public function run(?Connection $db, InputInterface $input): array
{
return $this->gen($input, $db);
}
/**
* @param InputInterface $input
* @param $db
* @return array
* @throws Exception
*/
public function gen(InputInterface $input, $db): array
{
$this->input = $input;
$this->db = $db;
$make = $this->input->getArgument('action');
if (empty($make)) {
throw new Exception('构建类型不能为空~');
}
switch (strtolower($make)) {
case 'task':
$task = new GiiTask();
$task->setInput($this->input);
return $task->generate();
case 'middleware':
$task = new GiiMiddleware();
$task->setInput($this->input);
return $task->generate();
case 'rpc-client':
$task = new GiiRpcClient();
$task->setInput($this->input);
return $task->generate();
case 'rpc-service':
$task = new GiiRpcService();
$task->setInput($this->input);
return $task->generate();
case 'json-rpc':
$task = new GiiJsonRpc();
$task->setInput($this->input);
return $task->create();
default:
return $this->getModel($make, $input);
}
}
/**
* @param $make
* @param $input
* @return array
* @throws Exception
*/
private function getModel($make, $input): array
{
return $this->makeByDatabases($make, $input);
}
/**
* @param $make
* @param InputInterface $input
* @return array
* @throws Exception
*/
private function makeByDatabases($make, InputInterface $input): array
{
$redis = Kiri::getDi()->get(Redis::class);
if ($input->hasArgument('name')) {
$this->tableName = $input->getArgument('name');
$redis->del('column:' . $this->tableName);
}
return match ($make) {
'controller' => $this->getTable(1, 0),
'model' => $this->getTable(0, 1),
default => [],
};
}
/**
* @param $controller
* @param $model
* @return array
*
* @throws Exception
*/
private function getTable($controller, $model): array
{
$tables = $this->getFields($this->getTables());
if (empty($tables)) {
return [];
}
$fileList = [];
foreach ($tables as $key => $val) {
$data = $this->createModelFile($key, $val);
if ($controller == 1) {
$fileList[] = $this->generateController($data);
}
if ($model == 1) {
$fileList[] = $this->generateModel($data);
}
}
return $fileList;
}
/**
* @param array $data
* @return string
* @throws Exception
*/
private function generateModel(array $data): string
{
$controller = new GiiModel($data['classFileName'], $data['tableName'], $data['visible'], $data['res'], $data['fields']);
$controller->setConnection($this->db);
$controller->setModelPath($this->modelPath);
$controller->setModelNamespace($this->modelNamespace);
$controller->setInput($this->input);
// $controller->setModule($this->input->getArgument('module'));
$controller->setControllerPath($this->controllerPath);
$controller->setControllerNamespace($this->controllerNamespace);
return $controller->generate();
}
/**
* @param array $data
* @return string
* @throws Exception
*/
private function generateController(array $data): string
{
$controller = new GiiController($data['classFileName'], $data['fields']);
$controller->setConnection($this->db);
$controller->setModelPath($this->modelPath);
$controller->setInput($this->input);
$controller->setModelNamespace($this->modelNamespace);
$controller->setControllerPath($this->controllerPath);
$controller->setModule($this->input->getArgument('module'));
$controller->setControllerNamespace($this->controllerNamespace);
return $controller->generate();
}
/**
* @return array|string|null
* @throws Exception
*/
private function getTables(): array|string|null
{
if (empty($this->tableName)) {
return $this->showAll();
}
$res = $this->tableName;
if (is_string($res)) {
$res = explode(',', $this->tableName);
}
if (empty($res)) {
return [];
}
return $res;
}
/**
* @return array
* @throws Exception
*/
private function showAll(): array
{
$res = [];
$_tables = Db::findAllBySql('show tables from `' . $this->db->database . '`', [], $this->db);
if (empty($_tables)) {
return $res;
}
foreach ($_tables as $key => $val) {
$res[] = array_shift($val);
}
return $res;
}
/**
* @param $table
* @return bool|int|null
* @throws Exception
*/
private function getIndex($table): bool|int|null
{
$data = Db::findAllBySql('SHOW INDEX FROM ' . $table, [], $this->db);
return empty($data) ? NULL : $data[0];
}
/**
* @param $tables
*
* @return array
* @throws
*/
private function getFields($tables): array
{
$res = [];
if (!is_array($tables)) {
$tables = [$tables];
}
foreach ($tables as $key => $val) {
if (empty($val)) continue;
$_tmp = Db::findAllBySql('SHOW FULL FIELDS FROM `' . $this->db->database . '`.' . $val, [], $this->db);
if (empty($_tmp)) {
continue;
}
$res[$val] = $_tmp;
}
return $res;
}
/**
* @param $tableName
* @param $tables
*
* @return array
* @throws Exception
*/
public function createModelFile($tableName, $tables): array
{
$res = $visible = $fields = $keys = [];
foreach ($tables as $_key => $_val) {
$keys = $tableName;
if ($_val['Extra'] == 'auto_increment' || $_val['Key'] == 'PRI') {
$keys = $tableName;
}
if (!isset($keys) && !($index = $this->getIndex($tableName))) {
$keys = $index['Column_name'];
}
if (in_array(strtoupper($_val['Field']), $this->keyword)) {
throw new Exception('You can not use keyword "' . $_val['Field'] . '" as field at table "' . $tableName . '"');
}
array_push($visible, $this->createVisible($_val['Field']));
array_push($fields, $_val);
$res[] = $this->createSetFunc($_val['Field'], $_val['Comment']);
}
$classFileName = $this->getClassName($tableName);
return [
'classFileName' => $classFileName,
'tableName' => $keys,
'visible' => $visible,
'fields' => $fields,
'res' => $res,
];
}
/**
* @param $field
* @return string
* 创建变量注释
*/
private function createVisible($field): string
{
return '
* @property $' . $field;
}
/**
* @param $field
* @param $comment
* @return string
* 暂时不知道干嘛用的
*/
private function createSetFunc($field, $comment): string
{
return '
' . str_pad('\'' . $field . '\'', 20, ' ', STR_PAD_RIGHT) . '=> \'' . (empty($comment) ? ucfirst($field) : $comment) . '\',';
}
/**
* @param $tableName
* @return string
* 构建类名称
*/
private function getClassName($tableName): string
{
$res = [];
foreach (explode('_', $tableName) as $n => $val) {
$res[] = ucfirst($val);
}
return implode('', $res);
}
}
<?php
/**
* Created by PhpStorm.
* User: 向林
* Date: 2016/8/9 0009
* Time: 17:43
*/
declare(strict_types=1);
namespace Gii;
use Database\Connection;
use Database\Db;
use Exception;
use Kiri\Cache\Redis;
use Kiri\Kiri;
use Symfony\Component\Console\Input\InputInterface;
/**
* Class gii
*
* @package Inter\utility
*/
class Gii
{
private ?string $tableName = NULL;
/** @var null|Connection */
private ?Connection $db;
private InputInterface $input;
public string $modelPath = APP_PATH . 'app/Model/';
public string $modelNamespace = 'App\\Model\\';
public string $controllerPath = APP_PATH . 'app/Http/Controller/';
public string $controllerNamespace = 'App\\Controller\\';
public static array $createSqls = [];
public array $keyword = [
'ADD', 'ALL', 'ALTER', 'AND', 'AS', 'ASC', 'ASENSITIVE', 'BEFORE', 'BETWEEN', 'BIGINT', 'BINARY', 'BLOB', 'BOTH', 'BY', 'CALL', 'CASCADE', 'CASE', 'CHANGE', 'CHAR', 'CHARACTER', 'CHECK', 'COLLATE', 'COLUMN', 'CONDITION', 'CONNECTION', 'CONSTRAINT', 'CONTINUE', 'CONVERT', 'CREATE', 'CROSS', 'CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'CURRENT_USER', 'CURSOR', 'DATABASE', 'DATABASES', 'DAY_HOUR', 'DAY_MICROSECOND', 'DAY_MINUTE', 'DAY_SECOND', 'DEC', 'DECIMAL', 'DECLARE', 'DEFAULT', 'DELAYED', 'DELETE', 'DESC', 'DESCRIBE', 'DETERMINISTIC', 'DISTINCT', 'DISTINCTROW', 'DIV', 'DOUBLE', 'DROP', 'DUAL', 'EACH', 'ELSE', 'ELSEIF', 'ENCLOSED', 'ESCAPED', 'EXISTS', 'EXIT', 'EXPLAIN', 'FALSE', 'FETCH', 'FLOAT', 'FLOAT4', 'FLOAT8', 'FOR', 'FORCE', 'FOREIGN', 'FROM', 'FULLTEXT', 'GOTO', 'GRANT', 'GROUP', 'HAVING', 'HIGH_PRIORITY', 'HOUR_MICROSECOND', 'HOUR_MINUTE', 'HOUR_SECOND', 'IF', 'IGNORE', 'IN', 'INDEX', 'INFILE', 'INNER', 'INOUT', 'INSENSITIVE', 'INSERT', 'INT', 'INT1', 'INT2', 'INT3', 'INT4', 'INT8', 'INTEGER', 'INTERVAL', 'INTO', 'IS', 'ITERATE', 'JOIN', 'KEY', 'KEYS', 'KILL', 'LABEL', 'LEADING', 'LEAVE', 'LEFT', 'LIKE', 'LIMIT', 'LINEAR', 'LINES', 'LOAD', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCK', 'LONG', 'LONGBLOB', 'LONGTEXT', 'LOOP', 'LOW_PRIORITY', 'MATCH', 'MEDIUMBLOB', 'MEDIUMINT', 'MEDIUMTEXT', 'MIDDLEINT', 'MINUTE_MICROSECOND', 'MINUTE_SECOND', 'MOD', 'MODIFIES', 'NATURAL', 'NOT', 'NO_WRITE_TO_BINLOG', 'NULL', 'NUMERIC', 'ON', 'OPTIMIZE', 'OPTION', 'OPTIONALLY', 'OR', 'ORDER', 'OUT', 'OUTER', 'OUTFILE', 'PRECISION', 'PRIMARY', 'PROCEDURE', 'PURGE', 'RAID0', 'RANGE', 'READ', 'READS', 'REAL', 'REFERENCES', 'REGEXP', 'RELEASE', 'RENAME', 'REPEAT', 'REPLACE', 'REQUIRE', 'RESTRICT', 'RETURN', 'REVOKE', 'RIGHT', 'RLIKE', 'SCHEMA', 'SCHEMAS', 'SECOND_MICROSECOND', 'SELECT', 'SENSITIVE', 'SEPARATOR', 'SET', 'SHOW', 'SMALLINT', 'SPATIAL', 'SPECIFIC', 'SQL', 'SQLEXCEPTION', 'SQLSTATE', 'SQLWARNING', 'SQL_BIG_RESULT', 'SQL_CALC_FOUND_ROWS', 'SQL_SMALL_RESULT', 'SSL', 'STARTING', 'STRAIGHT_JOIN', 'TABLE', 'TERMINATED', 'THEN', 'TINYBLOB', 'TINYINT', 'TINYTEXT', 'TO', 'TRAILING', 'TRIGGER', 'TRUE', 'UNDO', 'UNION', 'UNIQUE', 'UNLOCK', 'UNSIGNED', 'UPDATE', 'USAGE', 'USE', 'USING', 'UTC_DATE', 'UTC_TIME', 'UTC_TIMESTAMP', 'VALUES', 'VARBINARY', 'VARCHAR', 'VARCHARACTER', 'VARYING', 'WHEN', 'WHERE', 'WHILE', 'WITH', 'WRITE', 'X509', 'XOR', 'YEAR_MONTH', 'ZEROFILL'
];
/**
* @param Connection|null $db
*
* @param InputInterface $input
* @return array
* @throws Exception
*/
public function run(?Connection $db, InputInterface $input): array
{
return $this->gen($input, $db);
}
/**
* @param InputInterface $input
* @param $db
* @return array
* @throws Exception
*/
public function gen(InputInterface $input, $db): array
{
$this->input = $input;
$this->db = $db;
$make = $this->input->getOption('make');
if (empty($make)) {
throw new Exception('构建类型不能为空~');
}
switch (strtolower($make)) {
case 'task':
$task = new GiiTask();
$task->setInput($this->input);
return $task->generate();
case 'middleware':
$task = new GiiMiddleware();
$task->setInput($this->input);
return $task->generate();
case 'rpc-client':
$task = new GiiRpcClient();
$task->setInput($this->input);
return $task->generate();
case 'rpc-service':
$task = new GiiRpcService();
$task->setInput($this->input);
return $task->generate();
case 'json-rpc':
$task = new GiiJsonRpc();
$task->setInput($this->input);
return $task->create();
default:
return $this->getModel($make, $input);
}
}
/**
* @param $make
* @param $input
* @return array
* @throws Exception
*/
private function getModel($make, $input): array
{
return $this->makeByDatabases($make, $input);
}
/**
* @param $make
* @param InputInterface $input
* @return array
* @throws Exception
*/
private function makeByDatabases($make, InputInterface $input): array
{
if ($input->hasOption('name')) {
$this->tableName = $input->getOption('name');
}
return match ($make) {
'controller' => $this->getTable(1, 0),
'model' => $this->getTable(0, 1),
default => [],
};
}
/**
* @param $controller
* @param $model
* @return array
*
* @throws Exception
*/
private function getTable($controller, $model): array
{
$tables = $this->getFields($this->getTables());
if (empty($tables)) {
return [];
}
$fileList = [];
foreach ($tables as $key => $val) {
$data = $this->createModelFile($key, $val);
if ($controller == 1) {
$fileList[] = $this->generateController($data);
}
if ($model == 1) {
$fileList[] = $this->generateModel($data);
}
}
return $fileList;
}
/**
* @param array $data
* @return string
* @throws Exception
*/
private function generateModel(array $data): string
{
$controller = new GiiModel($data['classFileName'], $data['tableName'], $data['visible'], $data['res'], $data['fields']);
$controller->setConnection($this->db);
$controller->setModelPath($this->modelPath);
$controller->setModelNamespace($this->modelNamespace);
$controller->setInput($this->input);
// $controller->setModule($this->input->getArgument('module'));
$controller->setControllerPath($this->controllerPath);
$controller->setControllerNamespace($this->controllerNamespace);
return $controller->generate();
}
/**
* @param array $data
* @return string
* @throws Exception
*/
private function generateController(array $data): string
{
$controller = new GiiController($data['classFileName'], $data['fields']);
$controller->setConnection($this->db);
$controller->setModelPath($this->modelPath);
$controller->setInput($this->input);
$controller->setModelNamespace($this->modelNamespace);
$controller->setControllerPath($this->controllerPath);
$controller->setModule($this->input->getArgument('module'));
$controller->setControllerNamespace($this->controllerNamespace);
return $controller->generate();
}
/**
* @return array|string|null
* @throws Exception
*/
private function getTables(): array|string|null
{
if (empty($this->tableName)) {
return $this->showAll();
}
$res = $this->tableName;
if (is_string($res)) {
$res = explode(',', $this->tableName);
}
if (empty($res)) {
return [];
}
return $res;
}
/**
* @return array
* @throws Exception
*/
private function showAll(): array
{
$res = [];
$_tables = Db::findAllBySql('show tables from `' . $this->db->database . '`', [], $this->db);
if (empty($_tables)) {
return $res;
}
foreach ($_tables as $key => $val) {
$res[] = array_shift($val);
}
return $res;
}
/**
* @param $table
* @return bool|int|null
* @throws Exception
*/
private function getIndex($table): bool|int|null
{
$data = Db::findAllBySql('SHOW INDEX FROM ' . $table, [], $this->db);
return empty($data) ? NULL : $data[0];
}
/**
* @param $tables
*
* @return array
* @throws
*/
private function getFields($tables): array
{
$res = [];
if (!is_array($tables)) {
$tables = [$tables];
}
foreach ($tables as $key => $val) {
if (empty($val)) continue;
$_tmp = Db::findAllBySql('SHOW FULL FIELDS FROM `' . $this->db->database . '`.' . $val, [], $this->db);
if (empty($_tmp)) {
continue;
}
$res[$val] = $_tmp;
}
return $res;
}
/**
* @param $tableName
* @param $tables
*
* @return array
* @throws Exception
*/
public function createModelFile($tableName, $tables): array
{
$res = $visible = $fields = $keys = [];
foreach ($tables as $_key => $_val) {
$keys = $tableName;
if ($_val['Extra'] == 'auto_increment' || $_val['Key'] == 'PRI') {
$keys = $tableName;
}
if (!isset($keys) && !($index = $this->getIndex($tableName))) {
$keys = $index['Column_name'];
}
if (in_array(strtoupper($_val['Field']), $this->keyword)) {
throw new Exception('You can not use keyword "' . $_val['Field'] . '" as field at table "' . $tableName . '"');
}
array_push($visible, $this->createVisible($_val['Field']));
array_push($fields, $_val);
$res[] = $this->createSetFunc($_val['Field'], $_val['Comment']);
}
$classFileName = $this->getClassName($tableName);
return [
'classFileName' => $classFileName,
'tableName' => $keys,
'visible' => $visible,
'fields' => $fields,
'res' => $res,
];
}
/**
* @param $field
* @return string
* 创建变量注释
*/
private function createVisible($field): string
{
return '
* @property $' . $field;
}
/**
* @param $field
* @param $comment
* @return string
* 暂时不知道干嘛用的
*/
private function createSetFunc($field, $comment): string
{
return '
' . str_pad('\'' . $field . '\'', 20, ' ', STR_PAD_RIGHT) . '=> \'' . (empty($comment) ? ucfirst($field) : $comment) . '\',';
}
/**
* @param $tableName
* @return string
* 构建类名称
*/
private function getClassName($tableName): string
{
$res = [];
$tableName = str_replace($this->db->tablePrefix,'', $tableName);
foreach (explode('_', $tableName) as $n => $val) {
$res[] = ucfirst($val);
}
return implode('', $res);
}
}
+411 -411
View File
@@ -1,411 +1,411 @@
<?php
declare(strict_types=1);
namespace Gii;
use Database\Connection;
use Exception;
use Kiri\Core\Json;
use ReflectionClass;
use ReflectionException;
use Symfony\Component\Console\Input\InputInterface;
/**
* Class GiiBase
* @package Gii
*/
abstract class GiiBase
{
public array $fileList = [];
protected InputInterface $input;
public string $modelPath = APP_PATH . 'app/Model/';
public string $modelNamespace = 'App\Model\\';
public string $controllerPath = APP_PATH . 'app/Http/Controller/';
public string $controllerNamespace = 'App\\Controller\\';
public ?string $module = null;
public array $rules = [];
public array $type = [
'int' => ['tinyint', 'smallint', 'mediumint', 'int', 'bigint'],
'string' => ['char', 'varchar', 'tinytext', 'text', 'mediumtext', 'longtext', 'enum'],
'date' => ['date'],
'time' => ['time'],
'year' => ['year'],
'datetime' => ['datetime'],
'timestamp' => ['timestamp'],
'float' => ['float', 'double', 'decimal',],
];
public ?string $tableName = NULL;
public ?Connection $db = null;
/**
* @param string $modelPath
*/
public function setModelPath(string $modelPath): void
{
$this->modelPath = $modelPath;
}
/**
* @param string $modelNamespace
*/
public function setModelNamespace(string $modelNamespace): void
{
$this->modelNamespace = $modelNamespace;
}
/**
* @param string $controllerPath
*/
public function setControllerPath(string $controllerPath): void
{
$this->controllerPath = $controllerPath;
}
/**
* @param $module
*/
public function setModule($module)
{
$this->module = $module;
}
/**
* @param string $controllerNamespace
*/
public function setControllerNamespace(string $controllerNamespace): void
{
$this->controllerNamespace = $controllerNamespace;
}
/**
* @param InputInterface $input
*/
public function setInput(InputInterface $input)
{
$this->input = $input;
}
/**
* @param ReflectionClass $object
* @param $className
*
* @return string
*/
public function getUseContent(ReflectionClass $object, $className): string
{
if (empty($object)) {
return '';
}
$file = $this->getFilePath($className);
if (!file_exists($file)) {
return '';
}
$content = file_get_contents($file);
$explode = explode(PHP_EOL, $content);
$exists = array_slice($explode, 0, $object->getStartLine());
$_tmp = [];
foreach ($exists as $key => $val) {
if (trim($val) == '/**') {
break;
}
$_tmp[] = $val;
}
return trim(implode(PHP_EOL, $_tmp));
}
/**
* @param string $fileName
* @param ReflectionClass $class
* @return string
*/
protected function getImports(string $fileName, ReflectionClass $class): string
{
$startLine = 1;
$array = [];
$fileOpen = fopen($fileName, 'r');
while (($content = fgets($fileOpen)) !== false) {
if (str_starts_with($content, 'use ')) {
$array[] = $content;
}
if ($startLine == $class->getStartLine()) {
break;
}
++$startLine;
}
return implode($array);
}
/**
* @param ReflectionClass $class
* @return string
* @throws ReflectionException
*/
protected function getClassProperty(ReflectionClass $class): string
{
$html = '';
$rc = $class->getParentClass()->getConstants();
foreach ($class->getConstants() as $key => $val) {
if (isset($rc[$key])) {
continue;
}
if (is_numeric($val)) {
$html .= '
const ' . $key . ' = ' . $val . ';' . "\n";
} else {
$html .= '
const ' . $key . ' = \'' . $val . '\';' . "\n";
}
}
foreach ($class->getDefaultProperties() as $key => $val) {
$property = $class->getProperty($key);
if ($key == 'primary' || $key == 'table' || $key == 'connection' || $key == 'rules') {
continue;
}
if ($property->class != $class->getName()) continue;
if (is_array($val)) {
$val = '[\'' . implode('\', \'', $val) . '\']';
} else if (!is_numeric($val)) {
$val = '\'' . $val . '\'';
}
if ($property->isProtected()) {
$debug = 'protected';
} else if ($property->isPrivate()) {
$debug = 'private';
} else {
$debug = 'public';
}
if ($property->hasType()) {
$type = ' ' . $property->getType() . ' $' . $key . ' = ' . $val . ';' . "\n";
} else {
$type = ' $' . $key . ' = ' . $val . ';' . "\n";
}
if ($property->isStatic()) {
$html .= '
' . $debug . ' static' . $type;
} else {
$html .= '
' . $debug . $type;
}
}
return $html;
}
/**
* @param ReflectionClass $class
* @param array $filters
* @return string
* @throws Exception
*/
protected function getClassMethods(ReflectionClass $class, array $filters = []): string
{
$methods = $class->getMethods();
$classFileName = str_replace(APP_PATH, '', $class->getFileName());
$content = [];
if (!empty($methods)) foreach ($methods as $key => $val) {
if ($val->class != $class->getName()) continue;
if (in_array($val->name, $filters)) continue;
$over = "
" . $val->getDocComment() . "\n";
$attributes = $val->getAttributes();
if (!empty($attributes)) {
foreach ($attributes as $attribute) {
$explode = explode('\\', $attribute->getName());
$_array = [];
foreach ($attribute->getArguments() as $_key => $argument) {
$argument = $this->resolveArray($argument);
if (is_numeric($_key)) {
$_array[] = $argument;
} else {
$_array[] = $_key . ': ' . $argument . '';
}
}
if (empty($_array)) {
$end = " #[" . end($explode) . "]
";
} else {
$end = " #[" . end($explode) . "(" . implode(',', $_array) . ")]
";
}
if (str_contains($over, $end)) {
$over = str_replace($end, '', $over);
}
$over .= $end;
}
}
$func = $this->getFuncLineContent($class, $classFileName, $val->name) . "\n";
$content[] = $over . $func;
}
return implode(PHP_EOL, $content);
}
/**
* @param $argument
* @return string
*/
private function resolveArray($argument): string
{
if (is_array($argument)) {
$__array = [];
foreach ($argument as $key => $value) {
if (is_string($value)) {
if (str_contains($value, '\\') && class_exists($value)) {
$explode_class = explode('\\', $value);
$__array[] = end($explode_class) . '::class';
} else {
$__array[] = '\'' . $value . '\'';
}
} else {
$value = str_replace('{', '[', Json::encode($value));
$value = str_replace('}', ']', Json::encode($value));
$value = str_replace(':', '=>', Json::encode($value));
$value = preg_replace('/"\d+"\=\>/', '', $value);
$__array[] = $value;
}
}
$argument = '[' . implode(', ', $__array) . ']';
} else {
$argument = '\'' . $argument . '\'';
}
return $argument;
}
/**
* @param $fields
* @return mixed 返回表主键
* 返回表主键
*/
public function getPrimaryKey($fields): mixed
{
$condition = ['PRI', 'UNI'];
foreach ($fields as $field) {
if ($field['Extra'] == 'auto_increment') {
return $field['Field'];
}
if (in_array($field['Key'], $condition)) {
return $field['Field'];
}
}
return null;
}
/**
* @param $className
* @return string
*/
private function getFilePath($className): string
{
if (strpos($className, '\\')) {
$className = str_replace('\\', '/', $className);
}
if (strpos($className, '\\')) {
$className = str_replace('\\', '/', $className);
}
return APP_PATH . $className;
}
/**
* @param ReflectionClass $object
* @param $className
* @param $method
* @return string
* @throws Exception
*/
public function getFuncLineContent(ReflectionClass $object, $className, $method): string
{
$fun = $object->getMethod($method);
$content = file_get_contents($this->getFilePath($className));
$explode = explode(PHP_EOL, $content);
$exists = array_slice($explode, $fun->getStartLine() - 1, $fun->getEndLine() - $fun->getStartLine() + 1);
return implode(PHP_EOL, $exists);
}
/**
* @return array
*/
protected function getModelPath(): array
{
$dbName = $this->db->id;
if (empty($dbName) || $dbName == 'db') {
$dbName = '';
}
$modelPath = [
'namespace' => $this->modelNamespace,
'path' => $this->modelPath,
];
if (!is_dir($modelPath['path'])) {
mkdir($modelPath['path']);
}
if (!empty($dbName)) {
$modelPath['namespace'] = $this->modelNamespace . ucfirst($dbName);
$modelPath['path'] = $this->modelPath . ucfirst($dbName);
}
if (!is_dir($modelPath['path'])) {
mkdir($modelPath['path']);
}
return $modelPath;
}
/**
* @param $db
*/
public function setConnection($db)
{
$this->db = $db;
}
/**
* @param $val
* @return string
*/
protected function checkIsRequired($val): string
{
return strtolower($val['Null']) == 'no' && $val['Default'] === NULL ? 'true' : 'false';
}
/**
* @return array
*/
public function getFileLists(): array
{
return $this->fileList;
}
}
<?php
declare(strict_types=1);
namespace Gii;
use Database\Connection;
use Exception;
use Kiri\Core\Json;
use ReflectionClass;
use ReflectionException;
use Symfony\Component\Console\Input\InputInterface;
/**
* Class GiiBase
* @package Gii
*/
abstract class GiiBase
{
public array $fileList = [];
protected InputInterface $input;
public string $modelPath = APP_PATH . 'app/Model/';
public string $modelNamespace = 'App\Model\\';
public string $controllerPath = APP_PATH . 'app/Http/Controller/';
public string $controllerNamespace = 'App\\Controller\\';
public ?string $module = null;
public array $rules = [];
public array $type = [
'int' => ['tinyint', 'smallint', 'mediumint', 'int', 'bigint'],
'string' => ['char', 'varchar', 'tinytext', 'text', 'mediumtext', 'longtext', 'enum'],
'date' => ['date'],
'time' => ['time'],
'year' => ['year'],
'datetime' => ['datetime'],
'timestamp' => ['timestamp'],
'float' => ['float', 'double', 'decimal',],
];
public ?string $tableName = NULL;
public ?Connection $db = null;
/**
* @param string $modelPath
*/
public function setModelPath(string $modelPath): void
{
$this->modelPath = $modelPath;
}
/**
* @param string $modelNamespace
*/
public function setModelNamespace(string $modelNamespace): void
{
$this->modelNamespace = $modelNamespace;
}
/**
* @param string $controllerPath
*/
public function setControllerPath(string $controllerPath): void
{
$this->controllerPath = $controllerPath;
}
/**
* @param $module
*/
public function setModule($module)
{
$this->module = $module;
}
/**
* @param string $controllerNamespace
*/
public function setControllerNamespace(string $controllerNamespace): void
{
$this->controllerNamespace = $controllerNamespace;
}
/**
* @param InputInterface $input
*/
public function setInput(InputInterface $input)
{
$this->input = $input;
}
/**
* @param ReflectionClass $object
* @param $className
*
* @return string
*/
public function getUseContent(ReflectionClass $object, $className): string
{
if (empty($object)) {
return '';
}
$file = $this->getFilePath($className);
if (!file_exists($file)) {
return '';
}
$content = file_get_contents($file);
$explode = explode(PHP_EOL, $content);
$exists = array_slice($explode, 0, $object->getStartLine());
$_tmp = [];
foreach ($exists as $key => $val) {
if (trim($val) == '/**') {
break;
}
$_tmp[] = $val;
}
return trim(implode(PHP_EOL, $_tmp));
}
/**
* @param string $fileName
* @param ReflectionClass $class
* @return string
*/
protected function getImports(string $fileName, ReflectionClass $class): string
{
$startLine = 1;
$array = [];
$fileOpen = fopen($fileName, 'r');
while (($content = fgets($fileOpen)) !== false) {
if (str_starts_with($content, 'use ')) {
$array[] = $content;
}
if ($startLine == $class->getStartLine()) {
break;
}
++$startLine;
}
return implode($array);
}
/**
* @param ReflectionClass $class
* @return string
* @throws ReflectionException
*/
protected function getClassProperty(ReflectionClass $class): string
{
$html = '';
$rc = $class->getParentClass()->getConstants();
foreach ($class->getConstants() as $key => $val) {
if (isset($rc[$key])) {
continue;
}
if (is_numeric($val)) {
$html .= '
const ' . $key . ' = ' . $val . ';' . "\n";
} else {
$html .= '
const ' . $key . ' = \'' . $val . '\';' . "\n";
}
}
foreach ($class->getDefaultProperties() as $key => $val) {
$property = $class->getProperty($key);
if ($key == 'primary' || $key == 'table' || $key == 'connection' || $key == 'rules') {
continue;
}
if ($property->class != $class->getName()) continue;
if (is_array($val)) {
$val = '[\'' . implode('\', \'', $val) . '\']';
} else if (!is_numeric($val)) {
$val = '\'' . $val . '\'';
}
if ($property->isProtected()) {
$debug = 'protected';
} else if ($property->isPrivate()) {
$debug = 'private';
} else {
$debug = 'public';
}
if ($property->hasType()) {
$type = ' ' . $property->getType() . ' $' . $key . ' = ' . $val . ';' . "\n";
} else {
$type = ' $' . $key . ' = ' . $val . ';' . "\n";
}
if ($property->isStatic()) {
$html .= '
' . $debug . ' static' . $type;
} else {
$html .= '
' . $debug . $type;
}
}
return $html;
}
/**
* @param ReflectionClass $class
* @param array $filters
* @return string
* @throws Exception
*/
protected function getClassMethods(ReflectionClass $class, array $filters = []): string
{
$methods = $class->getMethods();
$classFileName = str_replace(APP_PATH, '', $class->getFileName());
$content = [];
if (!empty($methods)) foreach ($methods as $key => $val) {
if ($val->class != $class->getName()) continue;
if (in_array($val->name, $filters)) continue;
$over = "
" . $val->getDocComment() . "\n";
$attributes = $val->getAttributes();
if (!empty($attributes)) {
foreach ($attributes as $attribute) {
$explode = explode('\\', $attribute->getName());
$_array = [];
foreach ($attribute->getArguments() as $_key => $argument) {
$argument = $this->resolveArray($argument);
if (is_numeric($_key)) {
$_array[] = $argument;
} else {
$_array[] = $_key . ': ' . $argument . '';
}
}
if (empty($_array)) {
$end = " #[" . end($explode) . "]
";
} else {
$end = " #[" . end($explode) . "(" . implode(',', $_array) . ")]
";
}
if (str_contains($over, $end)) {
$over = str_replace($end, '', $over);
}
$over .= $end;
}
}
$func = $this->getFuncLineContent($class, $classFileName, $val->name) . "\n";
$content[] = $over . $func;
}
return implode(PHP_EOL, $content);
}
/**
* @param $argument
* @return string
*/
private function resolveArray($argument): string
{
if (is_array($argument)) {
$__array = [];
foreach ($argument as $key => $value) {
if (is_string($value)) {
if (str_contains($value, '\\') && class_exists($value)) {
$explode_class = explode('\\', $value);
$__array[] = end($explode_class) . '::class';
} else {
$__array[] = '\'' . $value . '\'';
}
} else {
$value = str_replace('{', '[', Json::encode($value));
$value = str_replace('}', ']', Json::encode($value));
$value = str_replace(':', '=>', Json::encode($value));
$value = preg_replace('/"\d+"\=\>/', '', $value);
$__array[] = $value;
}
}
$argument = '[' . implode(', ', $__array) . ']';
} else {
$argument = '\'' . $argument . '\'';
}
return $argument;
}
/**
* @param $fields
* @return mixed 返回表主键
* 返回表主键
*/
public function getPrimaryKey($fields): mixed
{
$condition = ['PRI', 'UNI'];
foreach ($fields as $field) {
if ($field['Extra'] == 'auto_increment') {
return $field['Field'];
}
if (in_array($field['Key'], $condition)) {
return $field['Field'];
}
}
return null;
}
/**
* @param $className
* @return string
*/
private function getFilePath($className): string
{
if (strpos($className, '\\')) {
$className = str_replace('\\', '/', $className);
}
if (strpos($className, '\\')) {
$className = str_replace('\\', '/', $className);
}
return APP_PATH . $className;
}
/**
* @param ReflectionClass $object
* @param $className
* @param $method
* @return string
* @throws Exception
*/
public function getFuncLineContent(ReflectionClass $object, $className, $method): string
{
$fun = $object->getMethod($method);
$content = file_get_contents($this->getFilePath($className));
$explode = explode(PHP_EOL, $content);
$exists = array_slice($explode, $fun->getStartLine() - 1, $fun->getEndLine() - $fun->getStartLine() + 1);
return implode(PHP_EOL, $exists);
}
/**
* @return array
*/
protected function getModelPath(): array
{
$dbName = $this->db->id;
if (empty($dbName) || $dbName == 'db') {
$dbName = '';
}
$modelPath = [
'namespace' => $this->modelNamespace,
'path' => $this->modelPath,
];
if (!is_dir($modelPath['path'])) {
mkdir($modelPath['path']);
}
if (!empty($dbName)) {
$modelPath['namespace'] = $this->modelNamespace . ucfirst($dbName);
$modelPath['path'] = $this->modelPath . ucfirst($dbName);
}
if (!is_dir($modelPath['path'])) {
mkdir($modelPath['path']);
}
return $modelPath;
}
/**
* @param $db
*/
public function setConnection($db)
{
$this->db = $db;
}
/**
* @param $val
* @return string
*/
protected function checkIsRequired($val): string
{
return strtolower($val['Null']) == 'no' && $val['Default'] === NULL ? 'true' : 'false';
}
/**
* @return array
*/
public function getFileLists(): array
{
return $this->fileList;
}
}
+76 -76
View File
@@ -1,76 +1,76 @@
<?php
declare(strict_types=1);
namespace Gii;
use Exception;
use Kiri\Abstracts\Config;
use Kiri\Exception\ConfigException;
use Kiri\Kiri;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Class Command
* @package Http
*/
class GiiCommand extends Command
{
public string $command = 'sw:gii';
public string $description = './snowflake sw:gii make=model|controller|task|interceptor|limits|middleware name=xxxx';
/**
*
*/
protected function configure()
{
$this->setName('sw:gii')
->addArgument('action', InputArgument::REQUIRED)
->addArgument('name', InputArgument::OPTIONAL)
->addArgument('databases', InputArgument::OPTIONAL)
->setDescription('./snowflake sw:gii make=model|controller|task|interceptor|limits|middleware name=xxxx');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
* @throws ConfigException
* @throws Exception
*/
public function execute(InputInterface $input, OutputInterface $output): int
{
/** @var Gii $gii */
$gii = Kiri::app()->get('gii');
$connections = Kiri::app()->get('db');
if (($db = $input->getArgument('databases')) != null) {
$gii->run($connections->get($db), $input);
return 1;
}
$action = $input->getArgument('action');
if (!in_array($action, ['model', 'controller'])) {
$gii->run(null, $input);
return 1;
}
$array = [];
foreach (Config::get('databases.connections') as $key => $connection) {
$array[$key] = $gii->run($connections->get($key), $input);
}
$output->writeln(json_encode($array, JSON_UNESCAPED_UNICODE));
return 1;
}
}
<?php
declare(strict_types=1);
namespace Gii;
use Exception;
use Kiri\Abstracts\Config;
use Kiri\Exception\ConfigException;
use Kiri\Kiri;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Class Command
* @package Http
*/
class GiiCommand extends Command
{
public string $command = 'sw:gii';
public string $description = './snowflake sw:gii make=model|controller|task|interceptor|limits|middleware name=xxxx';
/**
*
*/
protected function configure()
{
$this->setName('sw:gii')
->addOption('make','m', InputArgument::OPTIONAL)
->addOption('name','t', InputArgument::OPTIONAL)
->addOption('databases','d', InputArgument::OPTIONAL)
->setDescription('./snowflake sw:gii make=model|controller|task|interceptor|limits|middleware name=xxxx');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
* @throws ConfigException
* @throws Exception
*/
public function execute(InputInterface $input, OutputInterface $output): int
{
/** @var Gii $gii */
$gii = Kiri::app()->get('gii');
$connections = Kiri::app()->get('db');
if (($db = $input->getOption('databases')) != null) {
$gii->run($connections->get($db), $input);
return 1;
}
$action = $input->getOption('make');
if (!in_array($action, ['model', 'controller'])) {
$gii->run(null, $input);
return 1;
}
$array = [];
foreach (Config::get('databases.connections') as $key => $connection) {
$array[$key] = $gii->run($connections->get($key), $input);
}
$output->writeln(json_encode($array, JSON_UNESCAPED_UNICODE));
return 1;
}
}
+536 -539
View File
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More