Files
premium/plugin/apidoc/library/Apidoc.php
T
2025-05-18 07:42:27 +00:00

188 lines
6.9 KiB
PHP

<?php
namespace plugin\apidoc\library;
use app\service\ConfServiceFacade;
use laytp\traits\Error;
use plugin\apidoc\library\apidoc\library\Builder;
use plugin\apidoc\library\apidoc\library\Extractor;
use laytp\library\DirFile;
use think\facade\Env;
use think\facade\View;
class Apidoc
{
use Error;
protected $template = 'index.html';
protected $output = 'api.html';
protected $force = true;
/**
* 执行生成程序
* @param $title
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function execute($title)
{
// $addon = $input->getOption('addon');
// if($addon){
// $addon_service = new Addons();
// $addon_info = $addon_service->_info->getPluginInfo($addon);
// $controllerDir = Env::get('root_path') . DS . 'addons' . DS . $addon . DS . $addon_info['api_module'] . DS;
// }else{
$controllerDir = app()->getRootPath() . DS . 'app' . DS . 'controller' . DS . 'api' . DS;
// }
$files = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($controllerDir), \RecursiveIteratorIterator::LEAVES_ONLY
);
$weighs = [];
$k = 0;
foreach ($files as $name => $file) {
if (!$file->isDir()) {
$filePath = $file->getRealPath();
$className = $this->getClassFromFile($filePath);
$classAnnotations = Extractor::getClassAnnotations($className);
if (isset($classAnnotations['ApiInternal'])) {
continue;
}
$weigh = isset($classAnnotations['ApiWeigh']) ? intval($classAnnotations['ApiWeigh'][0]) : $k;
$weighs[$this->getClassFromFile($filePath)] = $weigh;
$k++;
}
}
uasort($weighs, function ($a, $b) {
if ($a == $b) return 0;
return ($a > $b) ? -1 : 1;
});
$classes = array_flip($weighs);
$builder = new Builder($classes);
$apiDir = __DIR__ . DS . 'apidoc' . DS;
$templateDir = $apiDir . 'template' . DS;
$templateFile = $templateDir . $this->template;
$var['plugin'] = '';
$var['title'] = $title;
$var['apiDomain'] = Env::get('domain.api');
$var['createSignKey'] = ConfServiceFacade::get('system.basic.signKey');
$var['apidocList'] = \plugin\apidoc\model\Apidoc::select()->toArray();
// $content = $builder->render($templateFile, $var);
$docslist = $builder->render($templateFile, $var);
$menu = [];
$menu[] = [
'id' => 0,
'title' => '全局说明',
'docType' => 'meditor'
];
$key = 0;
foreach($var['apidocList'] as $k=>$v){
$key++;
$temp = [];
$temp['id'] = $key;
$temp['title'] = $v['title'];
$temp['docType'] = 'meditor';
$menu[0]['children'][] = $temp;
}
foreach($docslist as $k=>$v){
$key++;
$temp = [];
$temp['id'] = $key;
$temp['title'] = $k;
$temp['docType'] = 'api';
foreach($v as $api){
$key++;
$children = [];
$children['id'] = $key;
$children['title'] = $api['title'];
$children['docType'] = 'api';
$temp['children'][] = $children;
}
$menu[] = $temp;
}
$menuOutputFile = app()->getRootPath() . 'public' . DS . 'static' . DS . 'admin' . DS . 'data' . DS . 'apidocMenu.json';
file_put_contents($menuOutputFile, json_encode($menu, JSON_UNESCAPED_UNICODE));
View::engine()->layout(false);
$content = View::display(file_get_contents($templateFile), array_merge($var, ['docslist' => $docslist]));
$outputDir = app()->getRootPath() . DS . 'public' . DS;
$outputFile = $outputDir . $this->output;
DirFile::createDir(dirname($outputFile));
if (!file_put_contents($outputFile, $content)) {
$this->setError('Cannot save the content to ' . $outputFile);
return false;
}
return true;
}
/**
* get full qualified class name
*
* @param string $path_to_file
* @return string
* @author JBYRNE http://jarretbyrne.com/2015/06/197/
*/
protected function getClassFromFile($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
foreach (token_get_all($contents) as $token) {
//If this token is the namespace declaring, then flag that the next tokens will be the namespace name
if (is_array($token) && $token[0] == T_NAMESPACE) {
$getting_namespace = true;
}
//If this token is the class declaring, then flag that the next tokens will be the class name
if (is_array($token) && $token[0] == T_CLASS) {
$getting_class = true;
}
//While we're grabbing the namespace name...
if ($getting_namespace === true) {
//If the token is a string or the namespace separator...
if (is_array($token) && in_array($token[0], [T_STRING, T_NS_SEPARATOR])) {
//Append the token's value to the name of the namespace
$namespace .= $token[1];
} else if ($token === ';') {
//If the token is the semicolon, then we're done with the namespace declaration
$getting_namespace = false;
}
}
//While we're grabbing the class name...
if ($getting_class === true) {
//If the token is a string, it's the name of the class
if (is_array($token) && $token[0] == T_STRING) {
//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;
}
}