feat(utils): 重写了构造URL的方法,增加对应的单元测试

This commit is contained in:
李东云
2023-01-13 18:00:33 +08:00
parent e705bedd5d
commit 9f79d1465b
3 changed files with 145 additions and 45 deletions

View File

@@ -7,9 +7,8 @@ namespace Singularity\HDK\Core\Service;
use Closure; use Closure;
use Exception; use Exception;
use Generator; use Generator;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Contract\RequestInterface; use Hyperf\HttpServer\Contract\RequestInterface;
use JetBrains\PhpStorm\NoReturn;
use JetBrains\PhpStorm\Pure; use JetBrains\PhpStorm\Pure;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
@@ -18,47 +17,38 @@ use Psr\Http\Message\ResponseInterface;
*/ */
class UtilsService class UtilsService
{ {
/**
* @Inject
* @var RequestInterface
*/
private RequestInterface $request;
/**
* @Inject()
* @var StdoutLoggerInterface
*/
private StdoutLoggerInterface $logger;
/** /**
* 生成验证码 * 生成验证码
* *
* @param int $length * @param int $length
* *
* @return string * @return string
* @throws Exception
*/ */
#[Pure]
public function generateSecureCode(int $length = 4): string public function generateSecureCode(int $length = 4): string
{ {
$code = ''; $code = '';
for ($times = 0; $times < $length; $times++) { for ($times = 0; $times < $length; $times++) {
$code .= rand(1, 9); $code .= random_int(1, 9);
} }
return $code; return $code;
} }
public function getRealIpAddress(): string /**
* 获取真实IP
* @param RequestInterface $request
* @return string
*/
public function getRealIpAddress(RequestInterface $request): string
{ {
$ip = $this->request->server('remote_addr'); $x_real_ip = $request->header('x-real-ip');
if (empty($ip) or in_array( var_dump(__METHOD__ . 'x-real-ip: ' . $x_real_ip);
$ip, $remote_addr = $request->server('remote_addr');
[ var_dump(__METHOD__ . 'remote_addr: ' . $remote_addr);
'localhost', return $x_real_ip
'127.0.0.1', ?? $remote_addr
] ?? 'unknown';
)) {
$ip = $this->request->header('x-real-ip');
}
return $ip ?? 'unknown';
} }
/** /**
@@ -108,18 +98,74 @@ class UtilsService
* 构建 URL * 构建 URL
* *
* @param string $url * @param string $url
* @param array<string, string> $params * @param array<string, string> $moreQueries 要附加的 query 参数
* * @param bool $anchorQuery 开启后query 参数将被尽量组合到锚点中,以支持 spa 路由
* @return string * @return string
*/ */
public function buildUrl(string $url, array $params = []): string #[Pure]
public function buildUrl(string $url, array $moreQueries = [], bool $anchorQuery = false): string
{ {
$url_info = parse_url($url); if (count($moreQueries) === 0) {
$base_url = str_replace('?' . $url_info['query'], '', $url); return $url;
parse_str($url_info['query'], $origin_params); }
$origin_params += $params;
return $base_url . '?' . http_build_query($origin_params); $url_info = parse_url($url);
$result = '';
// 协议
if (isset($url_info['scheme'])) {
$result .= $url_info['scheme'];
}
// 域名
if (isset($url_info['host'])) {
if (!empty($result)) {
$result .= ':';
}
$result .= '//';
// 用户名
if (isset($url_info['user'])) {
$result .= $url_info['user'];
// 密码
if (isset($url_info['pass'])) {
$result .= ':' . $url_info['pass'];
}
$result .= '@';
}
$result .= $url_info['host'];
}
// 端口
if (isset($url_info['port'])) {
$result .= ':' . $url_info['port'];
}
// 路径
$result .= $url_info['path'];
// 查询参数
if (!empty($url_info['query'])) {
$query_params = $url_info['query'];
parse_str($query_params, $origin_params);
if (!$anchorQuery) {
$origin_params += $moreQueries;
}
$result .= '?' . http_build_query($origin_params);
} else {
if (!$anchorQuery) {
$result .= '?' . http_build_query($moreQueries);
}
}
// 锚点
if (!empty($url_info['fragment'])) {
$fragment = $url_info['fragment'];
if ($anchorQuery) {
$fragment_data = parse_url($url_info['fragment']);
parse_str($fragment_data['query'] ?? '', $hash_queries);
$hash_queries += $moreQueries;
$fragment = $fragment_data['path'] . '?' . http_build_query($hash_queries);
}
$result .= '#' . $fragment;
}
return $result;
} }
/** /**
@@ -191,6 +237,7 @@ class UtilsService
* *
* @return void * @return void
*/ */
#[NoReturn]
public function unlimitedSubCategoriesQuicklyWithLevel( public function unlimitedSubCategoriesQuicklyWithLevel(
array &$list, array &$list,
int $level = 1, int $level = 1,
@@ -198,11 +245,7 @@ class UtilsService
string $childrenName = 'children', string $childrenName = 'children',
?Closure $filterCallback = null ?Closure $filterCallback = null
): void { ): void {
$start_time = microtime(true);
$max_times = count($list);
$current_times = 0;
foreach ($list as $i => &$item) { foreach ($list as $i => &$item) {
$current_times++;
if (!isset($item[$parentIdName])) { if (!isset($item[$parentIdName])) {
break; break;
} }
@@ -221,11 +264,6 @@ class UtilsService
} }
} }
$list = $list[$childrenName]; $list = $list[$childrenName];
$end_time = microtime(true);
$this->logger->debug("快速无极分类循环{$current_times}次,数组元素数量$max_times");
$cost_time = ($end_time - $start_time) * 1000;
$this->logger->debug("快速无极分类用时{$cost_time}ms");
} }

View File

@@ -47,4 +47,4 @@ it('asserts oss policy can be generated', function ($setDir, $isImage, $maxSize)
->and($signature)->toBe($sign); ->and($signature)->toBe($sign);
})->with([ })->with([
['uploaded', true, 1048576000], ['uploaded', true, 1048576000],
])->only(); ]);

View File

@@ -0,0 +1,62 @@
<?php
/**
* UtilsServiceTest.php@HDK-Core
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/1/12
*/
use Singularity\HDK\Core\Service\UtilsService;
$utils = new UtilsService();
$length_data = [];
for ($i = 0; $i < 5; $i++) {
try {
$length_data[] = random_int(1, 9);
} catch (Exception $e) {
continue;
}
}
test('断言验证码可以正常生成指定长度', function (int $length) use ($utils) {
try {
$code = $utils->generateSecureCode($length);
expect($code)->toHaveLength($length);
} catch (Exception $e) {
expect($e)->toBeNull();
}
})->with($length_data)->group('pure', 'utils');
test('断言可以根据参数构建 URL', function (string $url, array $params, bool $anchorQuery, string $expect) use ($utils) {
$url = $utils->buildUrl(url: $url, moreQueries: $params, anchorQuery: $anchorQuery);
expect($url)->toBe($expect);
})->with([
['baidu.com/list', ['a' => 'b'], false, 'baidu.com/list?a=b'],
['/api/v1/doc/categories/1?order=id', ['sort' => 'desc'], false, '/api/v1/doc/categories/1?order=id&sort=desc'],
['//google.com/search?c=d', ['a' => 'b'], false, '//google.com/search?c=d&a=b'],
[
'https://support.luxcreo.com/#/support?id=123',
['category' => 'abc'],
true,
'https://support.luxcreo.com/#/support?id=123&category=abc',
],
[
'https://support.luxcreo.com/#/support',
['category' => 'abc'],
true,
'https://support.luxcreo.com/#/support?category=abc',
],
[
'ssh://username:password@127.0.0.1/git/resp?id=1#/page?a=b',
['c' => 'd'],
false,
'ssh://username:password@127.0.0.1/git/resp?id=1&c=d#/page?a=b',
],
[
'http://username:password@127.0.0.1/git/resp?id=1#/page?a=b',
['c' => 'd'],
true,
'http://username:password@127.0.0.1/git/resp?id=1#/page?a=b&c=d',
]
])->group('pure', 'utils');