123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- <?php
- namespace app\admin\command;
- use app\admin\command\Api\library\Builder;
- use think\Config;
- use think\console\Command;
- use think\console\Input;
- use think\console\input\Option;
- use think\console\Output;
- use think\Exception;
- class Api extends Command
- {
- protected function configure()
- {
- $site = Config::get('site');
- $this
- ->setName('api')
- ->addOption('url', 'u', Option::VALUE_OPTIONAL, 'default api url', '')
- ->addOption('module', 'm', Option::VALUE_OPTIONAL, 'module name(admin/index/api)', 'api')
- ->addOption('output', 'o', Option::VALUE_OPTIONAL, 'output index file name', 'api.html')
- ->addOption('template', 'e', Option::VALUE_OPTIONAL, '', 'index.html')
- ->addOption('force', 'f', Option::VALUE_OPTIONAL, 'force override general file', false)
- ->addOption('title', 't', Option::VALUE_OPTIONAL, 'document title', $site['name'] ?? '')
- ->addOption('class', 'c', Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'extend class', null)
- ->addOption('language', 'l', Option::VALUE_OPTIONAL, 'language', 'zh-cn')
- ->addOption('addon', 'a', Option::VALUE_OPTIONAL, 'addon name', null)
- ->addOption('controller', 'r', Option::VALUE_REQUIRED | Option::VALUE_IS_ARRAY, 'controller name', null)
- ->setDescription('Build Api document from controller');
- }
- protected function execute(Input $input, Output $output)
- {
- $apiDir = __DIR__ . DS . 'Api' . DS;
- $force = $input->getOption('force');
- $url = $input->getOption('url');
- $language = $input->getOption('language');
- $template = $input->getOption('template');
- if (!preg_match("/^([a-z0-9]+)\.html\$/i", $template)) {
- throw new Exception('template file not correct');
- }
- $language = $language ? $language : 'zh-cn';
- $langFile = $apiDir . 'lang' . DS . $language . '.php';
- if (!is_file($langFile)) {
- throw new Exception('language file not found');
- }
- $lang = include_once $langFile;
- // 目标目录
- $output_dir = ROOT_PATH . 'public' . DS;
- $output_file = $output_dir . $input->getOption('output');
- if (is_file($output_file) && !$force) {
- throw new Exception("api index file already exists!\nIf you need to rebuild again, use the parameter --force=true ");
- }
- // 模板文件
- $template_dir = $apiDir . 'template' . DS;
- $template_file = $template_dir . $template;
- if (!is_file($template_file)) {
- throw new Exception('template file not found');
- }
- // 额外的类
- $classes = $input->getOption('class');
- // 标题
- $title = $input->getOption('title');
- // 模块
- $module = $input->getOption('module');
- // 插件
- $addon = $input->getOption('addon');
- $moduleDir = $addonDir = '';
- if ($addon) {
- $addonInfo = get_addon_info($addon);
- if (!$addonInfo) {
- throw new Exception('addon not found');
- }
- $moduleDir = ADDON_PATH . $addon . DS;
- } else {
- $moduleDir = APP_PATH . $module . DS;
- }
- if (!is_dir($moduleDir)) {
- throw new Exception('module not found');
- }
- if (version_compare(PHP_VERSION, '7.0.0', '<')) {
- throw new Exception("Requires PHP version 7.0 or newer");
- }
- //控制器名
- $controller = $input->getOption('controller') ?: [];
- if (!$controller) {
- $controllerDir = $moduleDir . Config::get('url_controller_layer') . DS;
- $files = new \RecursiveIteratorIterator(
- new \RecursiveDirectoryIterator($controllerDir),
- \RecursiveIteratorIterator::LEAVES_ONLY
- );
- foreach ($files as $name => $file) {
- if (!$file->isDir() && $file->getExtension() == 'php') {
- $filePath = $file->getRealPath();
- $classes[] = $this->getClassFromFile($filePath);
- }
- }
- } else {
- foreach ($controller as $index => $item) {
- $filePath = $moduleDir . Config::get('url_controller_layer') . DS . $item . '.php';
- $classes[] = $this->getClassFromFile($filePath);
- }
- }
- $classes = array_unique(array_filter($classes));
- $config = [
- 'sitename' => config('site.name'),
- 'title' => $title,
- 'author' => config('site.name'),
- 'description' => '',
- 'apiurl' => $url,
- 'language' => $language,
- ];
- $builder = new Builder($classes);
- $content = $builder->render($template_file, ['config' => $config, 'lang' => $lang]);
- if (!file_put_contents($output_file, $content)) {
- throw new Exception('Cannot save the content to ' . $output_file);
- }
- $output->info("Build Successed!");
- }
- /**
- * 从文件获取命名空间和类名
- *
- * @param string $filename
- * @return string
- */
- protected function getClassFromFile($filename)
- {
- $getNext = null;
- $isNamespace = false;
- $skipNext = false;
- $namespace = '';
- $class = '';
- foreach (\PhpToken::tokenize(file_get_contents($filename)) as $token) {
- if (!$token->isIgnorable()) {
- $name = $token->getTokenName();
- switch ($name) {
- case 'T_NAMESPACE':
- $isNamespace = true;
- break;
- case 'T_EXTENDS':
- case 'T_USE':
- case 'T_IMPLEMENTS':
- $skipNext = true;
- break;
- case 'T_CLASS':
- if ($skipNext) {
- $skipNext = false;
- } else {
- $getNext = strtolower(substr($name, 2));
- }
- break;
- case 'T_NAME_QUALIFIED':
- case 'T_NS_SEPARATOR':
- case 'T_STRING':
- case ';':
- if ($isNamespace) {
- if ($name == ';') {
- $isNamespace = false;
- } else {
- $namespace .= $token->text;
- }
- } elseif ($skipNext) {
- $skipNext = false;
- } elseif ($getNext == 'class') {
- $class = $token->text;
- $getNext = null;
- break 2;
- }
- break;
- default:
- $getNext = null;
- }
- }
- }
- return $namespace . '\\' . $class;
- }
- }
|