mirror of
https://gitee.com/zoujingli/ThinkAdmin.git
synced 2026-06-07 12:38:11 +08:00
将 v6 中直接放在本地 app 的后台与微信能力迁移为 v8 插件组件,并把运行时基础能力沉淀到独立插件包。 主要内容: - 新增 think-library、system、worker、static、install 等基础插件包。 - 新增 account、payment、wechat-client、wechat-service、wemall、wuma 等业务插件包。 - 移除 v6 的 app/admin 与 app/wechat 本地应用实现,改由插件分发接管。 - 将 Helper 能力彻底并入 System,统一为 plugin\system\helper\* 命名空间。 - 同步插件迁移发布清单与根 route 占位,保证安装发布流程可复现。
223 lines
7.0 KiB
PHP
223 lines
7.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
/**
|
|
* +----------------------------------------------------------------------
|
|
* | ThinkAdmin Plugin for ThinkAdminDeveloper
|
|
* +----------------------------------------------------------------------
|
|
* | Copyright (c) 2014~2026 ThinkAdmin [ thinkadmin.top ]
|
|
* +----------------------------------------------------------------------
|
|
* | Official Website: https://thinkadmin.top
|
|
* +----------------------------------------------------------------------
|
|
* | Licensed: https://mit-license.org
|
|
* | Disclaimer: https://thinkadmin.top/disclaimer
|
|
* | Vip Rights: https://thinkadmin.top/vip-introduce
|
|
* +----------------------------------------------------------------------
|
|
* | Gitee Repository: https://gitee.com/zoujingli/ThinkAdmin
|
|
* | Github Repository: https://github.com/zoujingli/ThinkAdmin
|
|
* +----------------------------------------------------------------------
|
|
*/
|
|
|
|
namespace think\admin\tests;
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
/**
|
|
* @internal
|
|
* @coversNothing
|
|
*/
|
|
class RouteTemplateBoundaryTest extends TestCase
|
|
{
|
|
private string $projectRoot;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
$this->projectRoot = TEST_PROJECT_ROOT;
|
|
}
|
|
|
|
public function testPhpAndTemplateSourcesDoNotReferenceLegacyAdminRoutesOrViews(): void
|
|
{
|
|
$forbidden = [
|
|
"sysuri('admin/",
|
|
'sysuri("admin/',
|
|
"url('admin/",
|
|
'url("admin/',
|
|
"auth('admin/",
|
|
'auth("admin/',
|
|
'admin/login/index',
|
|
'admin/index/index',
|
|
'admin/config/index',
|
|
'admin/api.',
|
|
'plugin/think-plugs-admin/src/view',
|
|
'view_path' . "' => TEST_PROJECT_ROOT . '/plugin/think-plugs-admin/src/view",
|
|
'view_path" => TEST_PROJECT_ROOT . \'/plugin/think-plugs-admin/src/view',
|
|
];
|
|
|
|
$violations = [];
|
|
$iterator = new \RecursiveIteratorIterator(
|
|
new \RecursiveDirectoryIterator($this->path('plugin'), \FilesystemIterator::SKIP_DOTS)
|
|
);
|
|
|
|
foreach ($iterator as $file) {
|
|
if (!$file->isFile()) {
|
|
continue;
|
|
}
|
|
|
|
$ext = strtolower($file->getExtension());
|
|
if (!in_array($ext, ['php', 'html'], true)) {
|
|
continue;
|
|
}
|
|
|
|
$path = $file->getPathname();
|
|
if ($this->isSelf($path)) {
|
|
continue;
|
|
}
|
|
$content = file_get_contents($path) ?: '';
|
|
foreach ($forbidden as $needle) {
|
|
if (strpos($content, $needle) !== false) {
|
|
$violations[] = [$needle, $path];
|
|
}
|
|
}
|
|
}
|
|
|
|
$appIterator = new \RecursiveIteratorIterator(
|
|
new \RecursiveDirectoryIterator($this->path('app'), \FilesystemIterator::SKIP_DOTS)
|
|
);
|
|
|
|
foreach ($appIterator as $file) {
|
|
if (!$file->isFile()) {
|
|
continue;
|
|
}
|
|
|
|
$ext = strtolower($file->getExtension());
|
|
if (!in_array($ext, ['php', 'html'], true)) {
|
|
continue;
|
|
}
|
|
|
|
$path = $file->getPathname();
|
|
if ($this->isSelf($path)) {
|
|
continue;
|
|
}
|
|
$content = file_get_contents($path) ?: '';
|
|
foreach ($forbidden as $needle) {
|
|
if (strpos($content, $needle) !== false) {
|
|
$violations[] = [$needle, $path];
|
|
}
|
|
}
|
|
}
|
|
|
|
$testIterator = new \RecursiveIteratorIterator(
|
|
new \RecursiveDirectoryIterator($this->path('tests'), \FilesystemIterator::SKIP_DOTS)
|
|
);
|
|
|
|
foreach ($testIterator as $file) {
|
|
if (!$file->isFile()) {
|
|
continue;
|
|
}
|
|
|
|
if (strtolower($file->getExtension()) !== 'php') {
|
|
continue;
|
|
}
|
|
|
|
$path = $file->getPathname();
|
|
if ($this->isSelf($path)) {
|
|
continue;
|
|
}
|
|
$content = file_get_contents($path) ?: '';
|
|
foreach ($forbidden as $needle) {
|
|
if (strpos($content, $needle) !== false) {
|
|
$violations[] = [$needle, $path];
|
|
}
|
|
}
|
|
}
|
|
|
|
$this->assertSame([], $violations, 'Legacy admin route or template references found: ' . json_encode($violations, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
|
|
}
|
|
|
|
public function testSourcesDoNotReferenceLegacyAdminStaticAssets(): void
|
|
{
|
|
$forbidden = [
|
|
'static/admin.js',
|
|
'plugs/admin/',
|
|
'window.taAdmin',
|
|
'ta-system-access-token',
|
|
'__FULL__/admin/',
|
|
];
|
|
|
|
$violations = [];
|
|
foreach ($this->scanFiles([
|
|
$this->path('plugin'),
|
|
$this->path('app'),
|
|
$this->path('tests'),
|
|
$this->path('public'),
|
|
$this->path('docs'),
|
|
$this->path('readme.md'),
|
|
$this->path('composer.json'),
|
|
], ['php', 'html', 'js', 'md', 'json']) as $path => $content) {
|
|
foreach ($forbidden as $needle) {
|
|
if (strpos($content, $needle) !== false) {
|
|
$violations[] = [$needle, $path];
|
|
}
|
|
}
|
|
}
|
|
|
|
$this->assertSame([], $violations, 'Legacy admin static references found: ' . json_encode($violations, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
|
|
}
|
|
|
|
/**
|
|
* @param list<string> $targets
|
|
* @param list<string> $extensions
|
|
* @return array<string, string>
|
|
*/
|
|
private function scanFiles(array $targets, array $extensions): array
|
|
{
|
|
$items = [];
|
|
foreach ($targets as $target) {
|
|
if (is_file($target)) {
|
|
if (!$this->isSelf($target) && in_array(strtolower(pathinfo($target, PATHINFO_EXTENSION)), $extensions, true)) {
|
|
$items[$target] = file_get_contents($target) ?: '';
|
|
}
|
|
continue;
|
|
}
|
|
if (!is_dir($target)) {
|
|
continue;
|
|
}
|
|
|
|
$iterator = new \RecursiveIteratorIterator(
|
|
new \RecursiveDirectoryIterator($target, \FilesystemIterator::SKIP_DOTS)
|
|
);
|
|
|
|
foreach ($iterator as $file) {
|
|
if (!$file->isFile()) {
|
|
continue;
|
|
}
|
|
|
|
$path = $file->getPathname();
|
|
if ($this->isSelf($path)) {
|
|
continue;
|
|
}
|
|
if (!in_array(strtolower($file->getExtension()), $extensions, true)) {
|
|
continue;
|
|
}
|
|
$items[$path] = file_get_contents($path) ?: '';
|
|
}
|
|
}
|
|
|
|
ksort($items);
|
|
return $items;
|
|
}
|
|
|
|
private function path(string $relative): string
|
|
{
|
|
return $this->projectRoot . '/' . ltrim($relative, '/');
|
|
}
|
|
|
|
private function isSelf(string $path): bool
|
|
{
|
|
$left = strtr(realpath($path) ?: $path, '\\', '/');
|
|
$right = strtr(realpath(__FILE__) ?: __FILE__, '\\', '/');
|
|
return $left === $right;
|
|
}
|
|
}
|