审查视图

application/admin/command/Api.php 6.7 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
<?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
Karson authored
20 21 22 23 24 25 26 27 28 29 30
            ->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('author', 'a', Option::VALUE_OPTIONAL, 'document author', $site['name'])
            ->addOption('class', 'c', Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'extend class', null)
            ->addOption('language', 'l', Option::VALUE_OPTIONAL, 'language', 'zh-cn')
            ->setDescription('Compress js and css file');
31 32 33 34 35 36 37 38 39
    }

    protected function execute(Input $input, Output $output)
    {
        $apiDir = __DIR__ . DS . 'Api' . DS;

        $force = $input->getOption('force');
        $url = $input->getOption('url');
        $language = $input->getOption('language');
Karson authored
40
        $language = $language ? $language : 'zh-cn';
41
        $langFile = $apiDir . 'lang' . DS . $language . '.php';
Karson authored
42
        if (!is_file($langFile)) {
43 44
            throw new Exception('language file not found');
        }
Karson authored
45
        $lang = include_once $langFile;
46 47 48
        // 目标目录
        $output_dir = ROOT_PATH . 'public' . DS;
        $output_file = $output_dir . $input->getOption('output');
Karson authored
49
        if (is_file($output_file) && !$force) {
50 51 52 53 54
            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 . $input->getOption('template');
Karson authored
55
        if (!is_file($template_file)) {
56 57 58 59 60 61 62 63 64 65 66 67
            throw new Exception('template file not found');
        }
        // 额外的类
        $classes = $input->getOption('class');
        // 标题
        $title = $input->getOption('title');
        // 作者
        $author = $input->getOption('author');
        // 模块
        $module = $input->getOption('module');

        $moduleDir = APP_PATH . $module . DS;
Karson authored
68
        if (!is_dir($moduleDir)) {
69 70
            throw new Exception('module not found');
        }
Karson authored
71 72

        if (version_compare(PHP_VERSION, '7.0.0', '<')) {
73
            if (extension_loaded('Zend OPcache')) {
Karson authored
74 75 76 77
                $configuration = opcache_get_configuration();
                $directives = $configuration['directives'];
                $configName = request()->isCli() ? 'opcache.enable_cli' : 'opcache.enable';
                if (!$directives[$configName]) {
Karson authored
78
                    throw new Exception("Please make sure {$configName} is turned on, Get help:https://forum.fastadmin.net/d/1321");
Karson authored
79 80
                }
            } else {
Karson authored
81
                throw new Exception("Please make sure opcache already enabled, Get help:https://forum.fastadmin.net/d/1321");
Karson authored
82 83 84
            }
        }
85 86
        $controllerDir = $moduleDir . Config::get('url_controller_layer') . DS;
        $files = new \RecursiveIteratorIterator(
Karson authored
87
            new \RecursiveDirectoryIterator($controllerDir), \RecursiveIteratorIterator::LEAVES_ONLY
88 89
        );
Karson authored
90 91
        foreach ($files as $name => $file) {
            if (!$file->isDir()) {
92 93 94 95 96 97 98 99 100 101
                $filePath = $file->getRealPath();
                $classes[] = $this->get_class_from_file($filePath);
            }
        }

        $config = [
            'title'       => $title,
            'author'      => $author,
            'description' => '',
            'apiurl'      => $url,
Karson authored
102
            'language'    => $language,
103 104 105 106
        ];
        $builder = new Builder($classes);
        $content = $builder->render($template_file, ['config' => $config, 'lang' => $lang]);
Karson authored
107
        if (!file_put_contents($output_file, $content)) {
108 109 110 111 112 113 114
            throw new Exception('Cannot save the content to ' . $output_file);
        }
        $output->info("Build Successed!");
    }

    /**
     * get full qualified class name
Karson authored
115
     *
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
     * @param string $path_to_file
     * @author JBYRNE http://jarretbyrne.com/2015/06/197/
     * @return string
     */
    protected function get_class_from_file($path_to_file)
    {
        //Grab the contents of the file
        $contents = file_get_contents($path_to_file);

        //Start with a blank namespace and class
        $namespace = $class = "";

        //Set helper values to know that we have found the namespace/class token and need to collect the string values after them
        $getting_namespace = $getting_class = false;

        //Go through each token and evaluate it as necessary
Karson authored
132
        foreach (token_get_all($contents) as $token) {
133 134

            //If this token is the namespace declaring, then flag that the next tokens will be the namespace name
Karson authored
135
            if (is_array($token) && $token[0] == T_NAMESPACE) {
136 137 138 139
                $getting_namespace = true;
            }

            //If this token is the class declaring, then flag that the next tokens will be the class name
Karson authored
140
            if (is_array($token) && $token[0] == T_CLASS) {
141 142 143 144
                $getting_class = true;
            }

            //While we're grabbing the namespace name...
Karson authored
145
            if ($getting_namespace === true) {
146 147

                //If the token is a string or the namespace separator...
Karson authored
148
                if (is_array($token) && in_array($token[0], [T_STRING, T_NS_SEPARATOR])) {
149 150 151

                    //Append the token's value to the name of the namespace
                    $namespace .= $token[1];
Karson authored
152
                } else if ($token === ';') {
153 154 155 156 157 158 159

                    //If the token is the semicolon, then we're done with the namespace declaration
                    $getting_namespace = false;
                }
            }

            //While we're grabbing the class name...
Karson authored
160
            if ($getting_class === true) {
161 162

                //If the token is a string, it's the name of the class
Karson authored
163
                if (is_array($token) && $token[0] == T_STRING) {
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178

                    //Store the token's value as the class name
                    $class = $token[1];

                    //Got what we need, stope here
                    break;
                }
            }
        }

        //Build the fully-qualified class name and return it
        return $namespace ? $namespace . '\\' . $class : $class;
    }

}