initialize(); AppService::clear(); } public function testMenusAcceptPluginDefinitionArray(): void { $plugin = AppService::resolvePlugin('system', true); $menus = AppService::menus('system', false, true); $this->assertIsArray($plugin); $this->assertNotSame([], $plugin); $this->assertSame('plugin\system\Service', $plugin['service'] ?? null); $this->assertTrue(boolval($plugin['show'] ?? false)); $this->assertFalse(method_exists($plugin['service'], 'menu')); $this->assertNotSame([], $menus); $this->assertSame('system/config/index', $menus[0]['subs'][0]['node'] ?? null); $this->assertSame( $menus, AppService::menus($plugin, false, true) ); } public function testRuntimeMenusAreLoadedFromComposerMetadata(): void { foreach ($this->pluginComposerManifests() as $service => $manifest) { $app = (array)($manifest['extra']['xadmin']['app'] ?? []); $meta = (array)($manifest['extra']['xadmin']['menu'] ?? []); $menus = (array)($manifest['extra']['xadmin']['menu']['items'] ?? []); $show = !array_key_exists('show', $meta) || !empty($meta['show']); $this->assertTrue(class_exists($service), "{$service} must be autoloadable"); $this->assertFalse(method_exists($service, 'menu'), "{$service} should not declare menu()"); if (array_key_exists('code', $app)) { $this->assertSame(strval($app['code']), $service::getAppCode(), "{$service} code must come from composer metadata"); } if (array_key_exists('name', $app)) { $this->assertSame(strval($app['name']), $service::getAppName(), "{$service} name must come from composer metadata"); } if (array_key_exists('prefix', $app)) { $this->assertSame(strval($app['prefix']), $service::getAppPrefix(), "{$service} prefix must come from composer metadata"); } $this->assertSame($show, $service::getMenuShow(), "{$service} menu show flag must come from composer metadata"); $this->assertSame($menus, $service::getMenus(), "{$service} menus must come from composer metadata"); } } /** * @return array> */ private function pluginComposerManifests(): array { $items = []; foreach (glob(TEST_PROJECT_ROOT . '/plugin/*/composer.json') ?: [] as $file) { $manifest = json_decode((string)file_get_contents($file), true); if (!is_array($manifest)) { continue; } $services = (array)($manifest['extra']['think']['services'] ?? []); $service = strval($services[0] ?? ''); if ($service === '' || !class_exists($service) || !is_subclass_of($service, Plugin::class)) { continue; } $items[$service] = $manifest; } ksort($items); return $items; } }