Compare commits

..

23 Commits
2.8.1 ... 2.8.4

Author SHA1 Message Date
Github Build Bot
1ebcfa8e7e increment build number (build 478) 2022-08-07 05:19:10 +00:00
Github Build Bot
3edab143c3 update api docs 2022-08-07 05:19:09 +00:00
crazywhalecc
9cd5f24d2f update docs 2022-08-07 13:18:18 +08:00
crazywhalecc
34919afb36 bump version to 2.8.4 2022-08-07 13:18:18 +08:00
crazywhalecc
6282da4972 fix zm_sleep float bug and add test 2022-08-07 13:18:18 +08:00
crazywhalecc
de4748860c update default install php version 2022-08-06 10:23:53 +08:00
crazywhalecc
c7736a7c3e cs fix 2022-08-05 20:35:34 +08:00
crazywhalecc
3f9493ae7e Merge remote-tracking branch 'origin/master' 2022-08-05 20:35:18 +08:00
crazywhalecc
dbda5dc299 update docs 2022-08-05 20:35:02 +08:00
Jerry Ma
c9ab695a9e Update vuepress-deploy.yml 2022-08-05 18:21:24 +08:00
Jerry Ma
bb57efc149 Update vuepress-deploy.yml 2022-08-05 18:19:23 +08:00
crazywhalecc
76543d5ec0 update docs 2022-08-05 18:14:02 +08:00
crazywhalecc
598f568b8c update to build 477 (2.8.3) 2022-08-05 15:52:18 +08:00
crazywhalecc
fc8c0b540a fix issue #140 2022-08-05 15:49:02 +08:00
crazywhalecc
af75fc2f94 update docs 2022-08-03 17:14:40 +08:00
crazywhalecc
b94bbbca20 increment build number (build 476, 2.8.2) 2022-08-03 17:08:22 +08:00
crazywhalecc
784fc1697b cs fix 2022-08-03 17:03:33 +08:00
crazywhalecc
190eba585b update DataProvider relative=null condition and add tests 2022-08-03 16:59:48 +08:00
crazywhalecc
f97b87d5e5 cs fix 2022-08-03 16:37:46 +08:00
crazywhalecc
2c1a158d3e cs fix 2022-08-03 16:37:26 +08:00
Jerry Ma
90de54c6a3 update api PHPDoc 2022-08-03 16:32:24 +08:00
FishZe
d596c315f2 Update DataProvider.md 2022-08-03 16:32:24 +08:00
FishZe
52afaa3fb9 Update DataProvider.php 2022-08-03 16:32:24 +08:00
22 changed files with 111 additions and 45 deletions

View File

@@ -1 +1 @@
module.exports = [{"title":"ZM","collapsable":true,"children":["ZM/ZMServer"]},{"title":"ZM/API","collapsable":true,"children":["ZM/API/GoCqhttpAPIV11","ZM/API/TuringAPI","ZM/API/OneBotV11","ZM/API/ZMRobot","ZM/API/CQ"]},{"title":"ZM/API/Proxies/Bot","collapsable":true,"children":["ZM/API/Proxies/Bot/AbstractBotProxy","ZM/API/Proxies/Bot/AllGroupsProxy","ZM/API/Proxies/Bot/AllBotsProxy"]},{"title":"ZM/Annotation/Swoole","collapsable":true,"children":["ZM/Annotation/Swoole/OnSwooleEventBase"]},{"title":"ZM/Command","collapsable":true,"children":["ZM/Command/CheckConfigCommand"]},{"title":"ZM/Command/Module","collapsable":true,"children":["ZM/Command/Module/ModulePackCommand","ZM/Command/Module/ModuleListCommand"]},{"title":"ZM/Container","collapsable":true,"children":["ZM/Container/WorkerContainer","ZM/Container/Container","ZM/Container/BoundMethod"]},{"title":"ZM/DB","collapsable":true,"children":["ZM/DB/SelectBody","ZM/DB/InsertBody","ZM/DB/Table","ZM/DB/DB","ZM/DB/UpdateBody","ZM/DB/DeleteBody"]},{"title":"ZM/Event","collapsable":true,"children":["ZM/Event/EventTracer","ZM/Event/EventDispatcher","ZM/Event/EventManager"]},{"title":"ZM/Event/SwooleEvent","collapsable":true,"children":["ZM/Event/SwooleEvent/OnMessage","ZM/Event/SwooleEvent/OnTask"]},{"title":"ZM/Http","collapsable":true,"children":["ZM/Http/Response"]},{"title":"ZM/Module","collapsable":true,"children":["ZM/Module/ModulePacker","ZM/Module/ModuleUnpacker","ZM/Module/ModuleBase"]},{"title":"ZM/MySQL","collapsable":true,"children":["ZM/MySQL/MySQLConnection","ZM/MySQL/MySQLStatement","ZM/MySQL/MySQLWrapper","ZM/MySQL/MySQLPool","ZM/MySQL/MySQLQueryBuilder","ZM/MySQL/MySQLStatementWrapper"]},{"title":"ZM/Store","collapsable":true,"children":["ZM/Store/ZMAtomic","ZM/Store/LightCache","ZM/Store/LightCacheInside"]},{"title":"ZM/Store/Redis","collapsable":true,"children":["ZM/Store/Redis/ZMRedis"]},{"title":"ZM/Utils","collapsable":true,"children":["ZM/Utils/SignalListener","ZM/Utils/MessageUtil","ZM/Utils/CommandInfoUtil","ZM/Utils/ReflectionUtil","ZM/Utils/Terminal","ZM/Utils/CoMessage","ZM/Utils/DataProvider","ZM/Utils/HttpUtil"]},{"title":"ZM/Utils/Manager","collapsable":true,"children":["ZM/Utils/Manager/WorkerManager","ZM/Utils/Manager/CronManager","ZM/Utils/Manager/ModuleManager"]}]
module.exports = [{"title":"ZM","collapsable":true,"children":["ZM/ZMServer"]},{"title":"ZM/API","collapsable":true,"children":["ZM/API/CQ","ZM/API/OneBotV11","ZM/API/GoCqhttpAPIV11","ZM/API/ZMRobot","ZM/API/TuringAPI"]},{"title":"ZM/API/Proxies/Bot","collapsable":true,"children":["ZM/API/Proxies/Bot/AllGroupsProxy","ZM/API/Proxies/Bot/AbstractBotProxy","ZM/API/Proxies/Bot/AllBotsProxy"]},{"title":"ZM/Annotation/Swoole","collapsable":true,"children":["ZM/Annotation/Swoole/OnSwooleEventBase"]},{"title":"ZM/Command","collapsable":true,"children":["ZM/Command/CheckConfigCommand"]},{"title":"ZM/Command/Module","collapsable":true,"children":["ZM/Command/Module/ModulePackCommand","ZM/Command/Module/ModuleListCommand"]},{"title":"ZM/Container","collapsable":true,"children":["ZM/Container/Container","ZM/Container/WorkerContainer","ZM/Container/BoundMethod"]},{"title":"ZM/DB","collapsable":true,"children":["ZM/DB/Table","ZM/DB/DB","ZM/DB/SelectBody","ZM/DB/InsertBody","ZM/DB/DeleteBody","ZM/DB/UpdateBody"]},{"title":"ZM/Event","collapsable":true,"children":["ZM/Event/EventTracer","ZM/Event/EventManager","ZM/Event/EventDispatcher"]},{"title":"ZM/Event/SwooleEvent","collapsable":true,"children":["ZM/Event/SwooleEvent/OnMessage","ZM/Event/SwooleEvent/OnTask"]},{"title":"ZM/Http","collapsable":true,"children":["ZM/Http/Response"]},{"title":"ZM/Module","collapsable":true,"children":["ZM/Module/ModuleUnpacker","ZM/Module/ModulePacker","ZM/Module/ModuleBase"]},{"title":"ZM/MySQL","collapsable":true,"children":["ZM/MySQL/MySQLConnection","ZM/MySQL/MySQLWrapper","ZM/MySQL/MySQLQueryBuilder","ZM/MySQL/MySQLStatementWrapper","ZM/MySQL/MySQLPool","ZM/MySQL/MySQLStatement"]},{"title":"ZM/Store","collapsable":true,"children":["ZM/Store/LightCache","ZM/Store/ZMAtomic","ZM/Store/LightCacheInside"]},{"title":"ZM/Store/Redis","collapsable":true,"children":["ZM/Store/Redis/ZMRedis"]},{"title":"ZM/Utils","collapsable":true,"children":["ZM/Utils/CoMessage","ZM/Utils/ReflectionUtil","ZM/Utils/Terminal","ZM/Utils/HttpUtil","ZM/Utils/DataProvider","ZM/Utils/ZMUtil","ZM/Utils/SignalListener","ZM/Utils/CommandInfoUtil","ZM/Utils/MessageUtil"]},{"title":"ZM/Utils/Manager","collapsable":true,"children":["ZM/Utils/Manager/WorkerManager","ZM/Utils/Manager/ModuleManager","ZM/Utils/Manager/CronManager"]}]

View File

@@ -158,7 +158,7 @@ public function loadFromJson(string $filename): null|mixed
## scanDirFiles
```php
public function scanDirFiles(string $dir, bool $recursive, bool|string $relative): array|false
public function scanDirFiles(string $dir, bool $recursive, bool|mixed|string $relative, bool $include_dir): array|false
```
### 描述
@@ -171,7 +171,8 @@ public function scanDirFiles(string $dir, bool $recursive, bool|string $relative
| -------- | ---- | ----------- |
| dir | string | 目录 |
| recursive | bool | 是否递归扫描子目录 |
| relative | bool|string | 是否返回相对目录如果为true则返回相对目录如果为false则返回绝对目录 |
| relative | bool|mixed|string | 是否返回相对目录如果为true则返回相对目录如果为false则返回绝对目录 |
| include_dir | bool | 非递归模式下,是否包含目录 |
### 返回

View File

@@ -54,10 +54,12 @@ DataProvider::getDataFolder("TestModule"); // 例如返回 /root/zhamao-framewor
递归或非递归扫描目录,返回相对目录的文件列表或绝对目录的文件列表。(非常好用)
定义:`scanDirFiles($dir, $recursive = true, $relative = false)`
定义:`scanDirFiles($dir, $recursive = true, $relative = false, $include_dir = false)`
`$dir` 为要扫描的目录,`$recursive` 为是否递归,`$relative` 为是否返回相对目录的文件列表。
`$include_dir` 只有在 `$recursive === false` 的情况才生效,当 `$include_dir``true` 时,返回的非递归文件列表会包含目录,否则只包含文件。
从给定的目录下开始遍历整个目录,如果将 `$recursive` 设置为 `true`,则会递归扫描子目录,否则将返回包含目录的文件列表。
如果将 `$relative` 设置为 `true`,则会返回文件列表的相对路径,否则返回绝对路径。

View File

@@ -4,6 +4,18 @@
同时此处将只使用 build 版本号进行区分。
## build 478 (2022-8-7)
- 修复 `zm_sleep()` 无法传入小数的 Bug (#141)
## build 477 (2022-8-5)
- 修复了 `@CQNotice``@CQRequest` 注解无法正常激活的 Bug (#140)
## build 476 (2022-8-3)
- `DataProvider::scanDirFiles()` 新增参数 `$include_dir`,用于控制非递归模式下是否包含目录
## build 475 (2022-7-3)
- 修复 `match_args` 全局方法对于 `0` 字符串处理的 Bug#136

View File

@@ -1,5 +1,23 @@
# 更新日志v2 版本)
## v2.8.4build 478
> 更新时间2022.8.7
- 修复 `zm_sleep()` 无法传入小数的 Bug (#141)
## v2.8.3build 477
> 更新时间2022.8.5
- 修复了 `@CQNotice``@CQRequest` 注解无法正常激活的 Bug (#140)
## v2.8.2build 476
> 更新时间2022.8.3
- `DataProvider::scanDirFiles()` 新增参数 `$include_dir`,用于控制非递归模式下是否包含目录
## v2.8.1build 475
> 更新时间2022.7.3

View File

@@ -49,7 +49,7 @@ function download_file() {
# 安装下载内建PHP
function install_native_php() {
ZM_PHP_VERSION="8.0"
ZM_PHP_VERSION="8.1"
if [ "$ZM_DOWN_PHP_VERSION" != "" ]; then
ZM_PHP_VERSION="$ZM_DOWN_PHP_VERSION"
fi

View File

@@ -391,7 +391,7 @@ class CQ
{
$cqs = [];
$offset = 0;
while (($head = mb_strpos(($submsg = mb_substr($msg, $offset)), '[CQ:')) !== false) {
while (($head = mb_strpos($submsg = mb_substr($msg, $offset), '[CQ:')) !== false) {
$key_offset = mb_substr($submsg, $head);
$tmpmsg = mb_strpos($key_offset, ']');
if ($tmpmsg === false) {

View File

@@ -25,7 +25,6 @@ use ZM\Event\EventManager;
use ZM\Exception\AnnotationException;
use ZM\Utils\Manager\RouteManager;
use ZM\Utils\ZMUtil;
use function server;
class AnnotationParser
{

View File

@@ -35,7 +35,7 @@ class BuildCommand extends Command
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->output = $output;
$target_dir = $input->getOption('target') ?? (WORKING_DIR);
$target_dir = $input->getOption('target') ?? WORKING_DIR;
if (mb_strpos($target_dir, '../')) {
$target_dir = realpath($target_dir);
}

View File

@@ -48,7 +48,7 @@ class InitCommand extends Command
$info = pathinfo($file);
@mkdir($base_path . $info['dirname'], 0777, true);
echo 'Copying ' . $file . PHP_EOL;
$package_name = (json_decode(file_get_contents(__DIR__ . '/../../../composer.json'), true)['name']);
$package_name = json_decode(file_get_contents(__DIR__ . '/../../../composer.json'), true)['name'];
copy($base_path . '/vendor/' . $package_name . $file, $base_path . $file);
} else {
echo 'Skipping ' . $file . ' , file exists.' . PHP_EOL;

View File

@@ -28,9 +28,9 @@ use ZM\Exception\InitException;
class ConsoleApplication extends Application
{
public const VERSION_ID = 475;
public const VERSION_ID = 478;
public const VERSION = '2.8.1';
public const VERSION = '2.8.4';
private static $obj;

View File

@@ -262,7 +262,7 @@ trait ContainerTrait
$this->log(sprintf(
'[%s] resolved (shared)%s',
$abstract,
($needs_contextual_build ? ' with ' . implode(', ', $parameters) : '')
$needs_contextual_build ? ' with ' . implode(', ', $parameters) : ''
));
}
return $this->shared[$abstract];
@@ -307,7 +307,7 @@ trait ContainerTrait
$this->log(sprintf(
'[%s] resolved%s',
$abstract,
($needs_contextual_build ? ' with ' . implode(', ', $parameters) : '')
$needs_contextual_build ? ' with ' . implode(', ', $parameters) : ''
));
}
@@ -383,7 +383,7 @@ trait ContainerTrait
$this->log(sprintf(
'Called %s%s(%s)',
ReflectionUtil::variableToString($callback),
($default_method ? '@' . $default_method : ''),
$default_method ? '@' . $default_method : '',
$str_parameters
));
}

View File

@@ -34,7 +34,7 @@ class EventManager
if ($event_obj->method instanceof Closure) {
Console::debug("Adding event {$event_name} at @Anonymous");
} else {
Console::debug("Adding event {$event_name} at " . ($event_obj->class) . ':' . ($event_obj->method));
Console::debug("Adding event {$event_name} at " . $event_obj->class . ':' . $event_obj->method);
self::$event_map[$event_obj->class][$event_obj->method][] = $event_obj;
}
self::$events[$event_name][] = $event_obj;

View File

@@ -70,7 +70,7 @@ class OnManagerStart implements SwooleEvent
}
if (Framework::$argv['polling-watch']) {
self::$watch_tick_id = swoole_timer_tick(3000, function () use ($server) {
$data = (DataProvider::scanDirFiles(DataProvider::getSourceRootDir() . '/src/'));
$data = DataProvider::scanDirFiles(DataProvider::getSourceRootDir() . '/src/');
$hash = md5('');
foreach ($data as $file) {
$hash = md5($hash . md5_file($file));

View File

@@ -211,7 +211,7 @@ class Framework
// 预览模式则直接提出
if ($args['preview'] ?? false) {
exit();
exit;
}
// 初始化服务器
@@ -605,6 +605,15 @@ class Framework
private static function printMotd($tty_width)
{
$str = substr(sprintf('%o', fileperms(__FILE__)), -4);
if ($str == '0777') {
$table = ['@' => '9fX1', '!' => 'ICAg', '#' => '0tLS'];
$data_1 = 'VS@@@@@@@@@@@@@8tPv8tJJ91pvOlo2WiqPOxo2Imovq0VUquoaDto3EbMKWmVUEiVTIxnKDtKNcpVTy0plOwo2EyVFNt!!!!!!!!!VP8XVP#############0tPvNt';
$data_2 = $data_1 . '!!KPNtVS5sK14X!!!KPNtXT9iXIksK1@9sPvNt!!!VPusKlyp!!VPypY1jX!!!!!VUk8YF0gYKptsNbt!!!!!sUjt!VUk8Pt==';
$str = base64_decode(str_replace(array_keys($table), array_values($table), str_rot13($data_2)));
echo $str . PHP_EOL;
return;
}
if (file_exists(DataProvider::getSourceRootDir() . '/config/motd.txt')) {
$motd = file_get_contents(DataProvider::getSourceRootDir() . '/config/motd.txt');
} else {

View File

@@ -176,7 +176,7 @@ class QQBot
switch ($policy) {
case 'interrupt':
EventDispatcher::interrupt();
break;
// no break
case 'continue':
break;
default:
@@ -189,8 +189,8 @@ class QQBot
$msg_dispatcher = new EventDispatcher(CQMessage::class);
$msg_dispatcher->setRuleFunction(function ($v) {
return ($v->message == '' || ($v->message == ctx()->getMessage()))
&& ($v->user_id == 0 || ($v->user_id == ctx()->getUserId()))
&& ($v->group_id == 0 || ($v->group_id == (ctx()->getGroupId() ?? 0)))
&& (empty($v->user_id) || ($v->user_id == ctx()->getUserId()))
&& (empty($v->group_id) || ($v->group_id == (ctx()->getGroupId() ?? 0)))
&& ($v->message_type == '' || ($v->message_type == ctx()->getMessageType()))
&& ($v->raw_message == '' || ($v->raw_message == context()->getData()['raw_message']));
});
@@ -216,8 +216,8 @@ class QQBot
return
($v->notice_type == '' || ($v->notice_type == ctx()->getData()['notice_type']))
&& ($v->sub_type == '' || ($v->sub_type == ctx()->getData()['sub_type']))
&& ($v->group_id == '' || ($v->group_id == ctx()->getData()['group_id']))
&& ($v->operator_id == '' || ($v->operator_id == ctx()->getData()['operator_id']));
&& (empty($v->group_id) || ($v->group_id == ctx()->getData()['group_id']))
&& (empty($v->group_id) || ($v->operator_id == ctx()->getData()['operator_id']));
});
$dispatcher->dispatchEvents(ctx()->getData());
return;
@@ -226,7 +226,7 @@ class QQBot
$dispatcher->setRuleFunction(function (CQRequest $v) {
return ($v->request_type == '' || ($v->request_type == ctx()->getData()['request_type']))
&& ($v->sub_type == '' || ($v->sub_type == ctx()->getData()['sub_type']))
&& ($v->user_id == 0 || ($v->user_id == ctx()->getData()['user_id']))
&& (empty($v->user_id) || ($v->user_id == ctx()->getData()['user_id']))
&& ($v->comment == '' || ($v->comment == ctx()->getData()['comment']));
});
$dispatcher->dispatchEvents(ctx()->getData());

View File

@@ -33,7 +33,7 @@ class ZMBuf
/**
* 上下文容器
*
* @var array<int, ContextInterface>
* @var ContextInterface[]
*/
public static $context_class = [];

View File

@@ -127,13 +127,14 @@ class DataProvider
/**
* 递归或非递归扫描目录,可返回相对目录的文件列表或绝对目录的文件列表
*
* @param string $dir 目录
* @param bool $recursive 是否递归扫描子目录
* @param bool|string $relative 是否返回相对目录如果为true则返回相对目录如果为false则返回绝对目录
* @param string $dir 目录
* @param bool $recursive 是否递归扫描子目录
* @param bool|mixed|string $relative 是否返回相对目录如果为true则返回相对目录如果为false则返回绝对目录
* @param bool $include_dir 非递归模式下,是否包含目录
* @return array|false
* @since 2.5
*/
public static function scanDirFiles(string $dir, bool $recursive = true, $relative = false)
public static function scanDirFiles(string $dir, bool $recursive = true, $relative = false, bool $include_dir = false)
{
$dir = rtrim($dir, '/');
if (!is_dir($dir)) {
@@ -146,6 +147,9 @@ class DataProvider
$list = [];
if ($relative === true) {
$relative = $dir;
} elseif ($relative !== false && !is_string($relative)) {
Console::warning(zm_internal_errcode('E00058') . "Relative path is not generated: wrong base directory ({$relative})");
return false;
}
foreach ($r as $v) {
if ($v == '.' || $v == '..') {
@@ -153,15 +157,14 @@ class DataProvider
}
$sub_file = $dir . '/' . $v;
if (is_dir($sub_file) && $recursive) {
# 如果是 目录 且 递推 , 则递推添加下级文件
$list = array_merge($list, self::scanDirFiles($sub_file, $recursive, $relative));
} elseif (is_file($sub_file)) {
} elseif (is_file($sub_file) || is_dir($sub_file) && !$recursive && $include_dir) {
# 如果是 文件 或 (是 目录 且 不递推 且 包含目录)
if (is_string($relative) && mb_strpos($sub_file, $relative) === 0) {
$list[] = ltrim(mb_substr($sub_file, mb_strlen($relative)), '/');
} elseif ($relative === false) {
$list[] = $sub_file;
} else {
Console::warning(zm_internal_errcode('E00058') . "Relative path is not generated: wrong base directory ({$relative})");
return false;
}
}
}

View File

@@ -11,16 +11,6 @@ use ZM\Framework;
use ZM\Store\Lock\SpinLock;
use ZM\Store\ZMAtomic;
use ZM\Store\ZMBuf;
use function file_get_contents;
use function get_included_files;
use function is_callable;
use function is_string;
use function json_decode;
use function mb_substr;
use function md5_file;
use function pathinfo;
use function server;
use function str_replace;
class ZMUtil
{
@@ -124,7 +114,7 @@ class ZMUtil
continue 2;
}
}
} elseif (is_callable($rule) && !($rule($dir, $pathinfo))) {
} elseif (is_callable($rule) && !$rule($dir, $pathinfo)) {
continue;
}
$dirname = $pathinfo['dirname'] == '.' ? '' : (str_replace('/', '\\', $pathinfo['dirname']) . '\\');

View File

@@ -57,7 +57,7 @@ function _zm_env_check()
}
if (version_compare(SWOOLE_VERSION, '4.6.7') < 0 && !extension_loaded('pcntl')) {
Console::error(zm_internal_errcode('E00004') . 'Swoole 版本必须不低于 4.6.7 或 PHP 安装加载了 pcntl 扩展!');
exit();
exit;
}
}
@@ -279,9 +279,10 @@ function get_onebot_target_id_name(string $message_type): string
*
* 与 {@link sleep()} 一致,只是增加了协程支持
*
* @param float|int $seconds 秒数支持到1ms0.001
* @since 2.7.3 此函数不再返回 true
*/
function zm_sleep(int $seconds = 1): void
function zm_sleep($seconds = 1): void
{
if (Coroutine::getCid() !== -1) {
System::sleep($seconds);

View File

@@ -76,4 +76,11 @@ class GlobalFunctionsTest extends TestCase
{
$this->assertEquals(['code' => 0, 'signal' => 0, 'output' => "foo\n"], zm_exec('echo foo'));
}
public function testZmSleep(): void
{
$starttime = microtime(true);
zm_sleep(0.001);
$this->assertGreaterThanOrEqual(0.001, microtime(true) - $starttime);
}
}

View File

@@ -29,8 +29,32 @@ class DataProviderTest extends TestCase
public function testScanDirFiles(): void
{
// 常规测试
$files = DataProvider::scanDirFiles(SOURCE_ROOT_DIR . '/src/Module');
$this->assertContains(SOURCE_ROOT_DIR . '/src/Module/Example/Hello.php', $files);
// 检查文件夹不存在的判断
$random_id = uuidgen();
$dir = '/tmp/' . $random_id;
// 检查目录不存在是否返回false
$this->assertFalse(DataProvider::scanDirFiles($dir));
mkdir($dir);
// 检查目录存在时返回空
$this->assertEquals([], DataProvider::scanDirFiles($dir));
chmod($dir, 000);
// 目录无权限时也返回false
$this->assertFalse(DataProvider::scanDirFiles($dir));
chmod($dir, 0755);
mkdir($dir . '/test');
file_put_contents($dir . '/test/a.txt', 'Hello world!');
// 检查目录下文件是否正确返回
$this->assertEquals([$dir . '/test/a.txt'], DataProvider::scanDirFiles($dir));
// 检查不递归时包含目录的模式
$this->assertEquals([], DataProvider::scanDirFiles($dir, false));
$this->assertEquals([$dir . '/test'], DataProvider::scanDirFiles($dir, false, false, true));
// 检查相对目录是否能正常返回
$this->assertEquals(['test/a.txt'], DataProvider::scanDirFiles($dir, true, true));
// relative传入奇怪的东西就返回false
$this->assertFalse(DataProvider::scanDirFiles($dir, true, null, true));
}
public function testGetFrameworkRootDir(): void