402 lines
17 KiB
PHP
402 lines
17 KiB
PHP
|
<?php
|
||
|
|
||
|
namespace WMarkDown;
|
||
|
|
||
|
class ScriptsAnalyzer{
|
||
|
|
||
|
private $wmarkdown = null;
|
||
|
private $ignore = [];
|
||
|
private $root = null;
|
||
|
private $root_l = 0;
|
||
|
private $original_wmd = null;
|
||
|
private $file_wmd = null;
|
||
|
private $common = [];
|
||
|
private $class = null;
|
||
|
private $object = null;
|
||
|
private $only = null;
|
||
|
private static $types = [
|
||
|
"__construct" => "constructor",
|
||
|
"__init__" => "constructor",
|
||
|
"__destruct" => "destructor",
|
||
|
"__del__" => "destructor",
|
||
|
"object" => "objeto",
|
||
|
"static" => "estático",
|
||
|
"classmethod" => "de clase",
|
||
|
"staticmethod" => "estático"
|
||
|
];
|
||
|
private static $languages = [
|
||
|
"php" => "PHP",
|
||
|
"python" => "Python",
|
||
|
"js" => "JavaScript",
|
||
|
"ecma" => "ECMAScript",
|
||
|
"mariadb" => "MariaDB",
|
||
|
"transact_sql" => "Transact SQL",
|
||
|
"sql_lite" => "SQLite",
|
||
|
"c_sharp" => "C#"
|
||
|
];
|
||
|
private static $classes = [
|
||
|
"php" => "PHP",
|
||
|
"js" => "JS",
|
||
|
"cs" => "CSharp",
|
||
|
"py" => "Python",
|
||
|
"sql" => "SQL"
|
||
|
];
|
||
|
private static $languages_with_overloads = ["C#"];
|
||
|
private static $languages_typed = ["SQLite", "Transact SQL", "MariaDB", "C#"];
|
||
|
private static $languages_with_status = ["PHP", "Python", "SQLite", "Transact SQL", "MariaDB", "C#"];
|
||
|
public $php;
|
||
|
public $js;
|
||
|
public $sql;
|
||
|
public $py;
|
||
|
public $cs;
|
||
|
|
||
|
public function __construct($wmarkdown, $input = []){
|
||
|
|
||
|
$date = date("Ymd");
|
||
|
|
||
|
$this->wmarkdown = $wmarkdown;
|
||
|
$this->ignore = $this->wmarkdown->get_ignore_file_paths();
|
||
|
$this->root_l = strlen($this->root = $this->wmarkdown->get_root());
|
||
|
$this->original_wmd = file_exists($path = $this->wmarkdown->settings("wmd_file")) ? file_get_contents($path) : null;
|
||
|
$this->file_wmd = file_exists($path = $this->wmarkdown->settings("wmd_file_empty")) ? file_get_contents($path) : null;
|
||
|
$this->class = $this->wmarkdown->settings("class");
|
||
|
$this->object = $this->wmarkdown->settings("object");
|
||
|
$this->common = [
|
||
|
"author" => $this->wmarkdown->settings("author"),
|
||
|
"project" => $this->wmarkdown->settings("project"),
|
||
|
"url" => $this->wmarkdown->settings("url"),
|
||
|
"project_author" => $this->wmarkdown->settings("project_author"),
|
||
|
"key_words" => $this->wmarkdown->settings("key_words"),
|
||
|
"language" => $this->wmarkdown->settings("language"),
|
||
|
"logo" => $this->wmarkdown->settings("logo"),
|
||
|
"since" => $date,
|
||
|
"version" => $date
|
||
|
];
|
||
|
$this->only = $this->wmarkdown->settings("only");
|
||
|
|
||
|
}
|
||
|
|
||
|
public static function get_content($file, $path){
|
||
|
return file_exists($subpath = $path . "/" . $file) ? file_get_contents($subpath) : null;
|
||
|
}
|
||
|
|
||
|
public function get_wmd_path($file, $path){
|
||
|
return $this->root . "/WMD/dev" . substr($path . "/" . $file, $this->root_l) . ".w.md";
|
||
|
}
|
||
|
|
||
|
private function write($file, $path, $content){
|
||
|
file_put_contents($content, $this->get_wmd_path($file, $path));
|
||
|
}
|
||
|
|
||
|
private static function get_properties($value){
|
||
|
|
||
|
preg_match('/^\#([^\s\t\\\\]+)((\\\\t)+|[\s\t]+)+([^\s\t\\\\]+)((\\\\t)+|[\s\t]+)+([^\s\t\\\\]+)/', $value, $matches, PREG_OFFSET_CAPTURE);
|
||
|
|
||
|
return [$matches[1][0], $matches[4][0], $matches[7][0]];
|
||
|
}
|
||
|
|
||
|
private static function get_attributes($wdoc){
|
||
|
|
||
|
$see = [];
|
||
|
$language = null;
|
||
|
$access = null;
|
||
|
$parameters = [];
|
||
|
$return = null;
|
||
|
$parameters_full = [];
|
||
|
$hash = null;
|
||
|
|
||
|
preg_replace_callback('/^([\#\@])([^\s]+)\s+([^\r\n]+)/m', function($values) use(&$see, &$language, &$access, &$parameters, &$return, &$parameters_full, &$hash){
|
||
|
if($values[1] == "#"){
|
||
|
if($values[2] == "return")
|
||
|
$return = true;
|
||
|
else{
|
||
|
$parameters[] = $values[2];
|
||
|
$parameters_full[] = $values[0];
|
||
|
};
|
||
|
}else{
|
||
|
switch($values[2]){
|
||
|
case "lang":
|
||
|
$language = $values[3];
|
||
|
break;
|
||
|
case "see":
|
||
|
$see[] = $values[3];
|
||
|
break;
|
||
|
case "access":
|
||
|
$access = $values[3];
|
||
|
break;
|
||
|
case "hash":
|
||
|
$hash = $values[3];
|
||
|
break;
|
||
|
};
|
||
|
};
|
||
|
}, $wdoc);
|
||
|
|
||
|
return [
|
||
|
"see" => $see,
|
||
|
"language" => $language,
|
||
|
"access" => $access,
|
||
|
"parameters" => $parameters,
|
||
|
"return" => $return,
|
||
|
"parameters_full" => $parameters_full,
|
||
|
"hash" => $hash
|
||
|
];
|
||
|
}
|
||
|
|
||
|
private static function set_parameter($parameter){
|
||
|
return "#" . (is_string($parameter) ? $parameter = ["name" => $parameter] : $parameter)["name"] . "\t" . (empty($parameter["type"]) ? "-" : $parameter["type"]) . " " . (empty($parameter["default"]) ? "optional" : "required") . " Parámetro " . $parameter["name"] . "\n";
|
||
|
}
|
||
|
|
||
|
private static function set_return($return){
|
||
|
if(is_bool($return) || is_integer($return))
|
||
|
return $return ? "#return\t- - Retorno.\n" : "";
|
||
|
if(is_string($return))
|
||
|
return $return ? "#return\t" . $return . " - Retorno.\n" : "";
|
||
|
return "";
|
||
|
}
|
||
|
|
||
|
private function update_wdoc(&$wdoc, $current, $new){
|
||
|
|
||
|
$parameters = [];
|
||
|
$l = 0;
|
||
|
$last_parameter = null;
|
||
|
$return = null;
|
||
|
$parameters_final = [];
|
||
|
$m = count($current["parameters"]);
|
||
|
|
||
|
if(preg_match('/^(\#([^\r\n]+)[\r\n]+)+/m', $wdoc, $parameters, PREG_OFFSET_CAPTURE)){
|
||
|
$wdoc = substr($wdoc, 0, $parameters[0][1]) . substr($wdoc, $parameters[0][1] + strlen($parameters[0][0]), -3);
|
||
|
$parameters = preg_split('/(\r\n|[\r\n])/', trim($parameters[0][0]));
|
||
|
$l = count($parameters);
|
||
|
$last_parameter = $parameters[$l - 1];
|
||
|
}else
|
||
|
$wdoc = substr($wdoc, 0, -3);
|
||
|
|
||
|
if($last_parameter && preg_match('/^\#return[\\\\\s\t]/', $last_parameter, $matches, PREG_OFFSET_CAPTURE)){
|
||
|
$return = $last_parameter . "\n";
|
||
|
array_pop($parameters);
|
||
|
$l --;
|
||
|
}else if(isset($new["return"]))
|
||
|
$return = self::set_return($new["return"]);
|
||
|
|
||
|
$wdoc = preg_replace('/^(@see[^\r\n]+[\r\n]+)+/m', "@see\t" . implode("\n@see\t", $new["see"]) . "\n", $wdoc);
|
||
|
$wdoc = preg_replace('/^@access[^\r\n]+/m', "@access\t" . $new["access"], $wdoc);
|
||
|
$wdoc = preg_replace('/^@version[^\r\n]+/m', "@version\t" . $this->common["version"], $wdoc);
|
||
|
if($new["hash"])
|
||
|
$wdoc = preg_match('/^@hash/m', $wdoc) ? preg_replace('/^@hash[^\r\n]+/m', "@hash\t" . $new["hash"], $wdoc) : $wdoc . "\n@hash\t" . $new["hash"];
|
||
|
|
||
|
foreach($new["parameters"] as $i => $parameter)
|
||
|
$parameters_final[$i] = (
|
||
|
$i < $m && $current["parameters"][$i] == $parameter ? $parameters[$i] : (
|
||
|
($j = array_search($parameter, $current["parameters"])) !== false ? $current["parameters"][$j] :
|
||
|
$new["parameters_full"][$i]
|
||
|
));
|
||
|
|
||
|
$wdoc .= (substr($wdoc, -1) == "\n" ? "" : "\n") . (($parameters = implode("\n", $parameters_final)) ? $parameters . "\n" : "") . ($return ? $return : "") . "]]";
|
||
|
|
||
|
return $wdoc;
|
||
|
}
|
||
|
|
||
|
public function add_method($wmd, $last, $variables){
|
||
|
|
||
|
if(isset($variables["see"])){
|
||
|
if(is_array($variables["see"])){
|
||
|
|
||
|
$see = "";
|
||
|
|
||
|
foreach($variables["see"] as $item)
|
||
|
$see .= "@see " . $item . "\n";
|
||
|
$variables["see"] = $see;
|
||
|
|
||
|
};
|
||
|
}else
|
||
|
$variables["see"] = "";
|
||
|
|
||
|
if(isset($variables["parameters"])){
|
||
|
if(is_array($variables["parameters"])){
|
||
|
|
||
|
$parameters = "";
|
||
|
|
||
|
foreach($variables["parameters"] as $parameter)
|
||
|
$parameters .= self::set_parameter($parameter);
|
||
|
$variables["parameters"] = $parameters;
|
||
|
};
|
||
|
}else
|
||
|
$variables["parameters"] = $parameters;
|
||
|
|
||
|
$variables["return"] = isset($variables["return"]) ? self::set_return($variables["return"]) : "";
|
||
|
|
||
|
$method_variables = array_merge($variables, $this->common);
|
||
|
$new_method = \WMarkDown::string_variables("[[wdoc\n" .
|
||
|
"Método {type}.\n" .
|
||
|
"@name {name}\n" .
|
||
|
"{see}" .
|
||
|
"@lang {language_script}\n" .
|
||
|
"@author {author}\n" .
|
||
|
"@since {since}\n" .
|
||
|
"@version {version}\n" .
|
||
|
"@access {access}\n" .
|
||
|
"@hash {hash}\n" .
|
||
|
"{parameters}" .
|
||
|
"{return}" .
|
||
|
"]]", $method_variables);
|
||
|
$pattern = preg_replace('/\\\\{8}/', "\\\\\\\\\\\\\\\\", '/[\r\n]\#\# \[\[plain ' . preg_replace('/([\.\-\:\\\\])/', "\\\\$1", $variables["name"]) . '\]\]((?!(\#\# |\[\[html_data))(.|[\n\r]))+/');
|
||
|
$new = self::get_attributes($new_method);
|
||
|
$language = $new["language"];
|
||
|
|
||
|
if(preg_match($pattern, $wmd, $matches, PREG_OFFSET_CAPTURE)){
|
||
|
|
||
|
$content = "";
|
||
|
$temporary = $matches[0][0];
|
||
|
$done = false;
|
||
|
$overload = in_array($language, self::$languages_with_overloads);
|
||
|
|
||
|
while(preg_match('/([\r\n]\[\[wdoc((?!([\r\n]\]\]))(.|[\r\n]))+[\r\n]\]\])/', $temporary, $submatches, PREG_OFFSET_CAPTURE)){
|
||
|
|
||
|
$current = self::get_attributes($submatches[0][0]);
|
||
|
|
||
|
$wdoc = $submatches[0][0];
|
||
|
$content .= substr($temporary, 0, $submatches[0][1]);
|
||
|
$temporary = substr($temporary, $submatches[0][1] + strlen($submatches[0][0]));
|
||
|
|
||
|
if($overload){
|
||
|
|
||
|
if($done){
|
||
|
$content .= $wdoc;
|
||
|
continue;
|
||
|
};
|
||
|
|
||
|
$ok = true;
|
||
|
|
||
|
foreach($new as $key => $value)
|
||
|
if(!in_array($key, ["parameters_full", "hash"]) && !($ok = $value == $current[$key]))
|
||
|
break;
|
||
|
$content .= ($done = $ok) && $new["hash"] != $current["hash"] ? $this->update_wdoc($wdoc, $current, $new) : $wdoc;
|
||
|
|
||
|
}else{
|
||
|
$same = true;
|
||
|
foreach($new as $key => $value)
|
||
|
if(!in_array($key, ["parameters_full"]) && !($same = $value == $current[$key]))
|
||
|
break;
|
||
|
$content .= $same ? $wdoc : $this->update_wdoc($wdoc, $current, $new);
|
||
|
break;
|
||
|
};
|
||
|
|
||
|
};
|
||
|
|
||
|
$overload && !$done && ($content .= "\n\n" . $new_method);
|
||
|
|
||
|
return substr($wmd, 0, $matches[0][1]) . $content . "\n\n" . substr($wmd, $matches[0][1] + strlen($matches[0][0]));
|
||
|
};
|
||
|
|
||
|
$fragments = $last ? explode("## " . $last . "\n", $wmd) : [$wmd];
|
||
|
|
||
|
$new_method = \WmarkDown::string_variables("## [[plain {name}]]\n\n", $method_variables) . $new_method;
|
||
|
|
||
|
$results = null;
|
||
|
|
||
|
if(count($fragments) > 1)
|
||
|
$results = $fragments[0] . "## [[plain " . $last . "\n" . preg_replace('/^(\#{2} |\[{2}html_data)/m', $new_method . "]]\n\n$1", $fragments[1], 1);
|
||
|
else
|
||
|
$results = preg_replace('/^(\[{2}html_data)/m', $new_method . "\n\n$1", $fragments[0], 1);
|
||
|
|
||
|
return $results;
|
||
|
|
||
|
if(count($fragments) > 1)
|
||
|
return $fragments[0] . "## [[plain " . $last . "\n" . preg_replace('/^(\#{2} |\[{2}html_data)/m', $new_method . "]]\n\n$1", $fragments[1], 1);
|
||
|
return preg_replace('/^(\[{2}html_data)/m', $new_method . "\n\n$1", $fragments[0], 1);
|
||
|
}
|
||
|
|
||
|
private function get_commons(){
|
||
|
return [
|
||
|
"common" => $this->common,
|
||
|
"original_wmd" => $this->original_wmd,
|
||
|
"root" => $this->root,
|
||
|
"root_l" => $this->root_l,
|
||
|
"class" => $this->class,
|
||
|
"object" => $this->object
|
||
|
];
|
||
|
}
|
||
|
|
||
|
private function analyze($class, $object, $file, $path, &$languages, $i){
|
||
|
|
||
|
$class = '\WMarkDown\ScriptsAnalyzer\\' . $class;
|
||
|
|
||
|
!$this->$object && class_exists($class) && ($this->$object = new $class($this->wmarkdown, $this, $this->get_commons()));
|
||
|
$this->$object && $this->$object->analyze($file, $path, $languages, $i);
|
||
|
|
||
|
}
|
||
|
|
||
|
private function build($path, &$languages, $i = 0){
|
||
|
foreach(scandir($path) as $file){
|
||
|
if(preg_match('/^\.{1,2}$/', $file))
|
||
|
continue;
|
||
|
|
||
|
$subpath = $path . "/" . $file;
|
||
|
|
||
|
if(in_array(substr($subpath, $this->root_l), $this->ignore))
|
||
|
continue;
|
||
|
if(is_dir($subpath))
|
||
|
$this->build($subpath, $languages, $i + 1);
|
||
|
elseif(preg_match('/\.(py|php|js|sql|cs)$/', $file, $matches, PREG_OFFSET_CAPTURE) && isset(self::$classes[$matches[1][0]]))
|
||
|
$this->analyze(self::$classes[$matches[1][0]], $matches[1][0], $file, $path, $languages, $i);
|
||
|
|
||
|
};
|
||
|
}
|
||
|
|
||
|
private function write_wmd($path, $content, $variables){
|
||
|
\WMarkDown::save_file($path, \WMarkDown::string_variables($this->file_wmd, array_merge(["content" => $content], $this->common, $variables)));
|
||
|
}
|
||
|
|
||
|
public function update_files(){
|
||
|
|
||
|
$languages = [];
|
||
|
$wmd = "";
|
||
|
|
||
|
if($this->original_wmd){
|
||
|
if($this->only){
|
||
|
foreach(is_array($this->only) ? $this->only : [$this->only] as $path)
|
||
|
$this->build($this->root . $path, $languages);
|
||
|
}else
|
||
|
$this->build($this->root, $languages);
|
||
|
};
|
||
|
|
||
|
foreach($languages as $language => $files){
|
||
|
|
||
|
$index = "# " . self::$languages[$language] . "\n\n";
|
||
|
|
||
|
$wmd .= "\n# " . self::$languages[$language] . "\n";
|
||
|
foreach($files as $file){
|
||
|
|
||
|
$path = substr($file["path"], $this->root_l + 8);
|
||
|
|
||
|
$wmd .= "\n- [" . ($link = ($sublink = "/dev/" . self::$languages[$language]) . "#" . preg_replace('/[^a-z\d]+/i', "-", preg_replace('/^(.+?\/)?([^\/]+)\.w\.md$/', "$2-2", $path))) . " " . preg_replace('/\.w\.md$/', "", $path) . "]";
|
||
|
$index .= (
|
||
|
"[[header_level 0]]\n" .
|
||
|
"[[include /WMD/dev" . $path . "]]\n\n"
|
||
|
);
|
||
|
foreach($file["methods"] as $method)
|
||
|
$wmd .= "\n - [" . $sublink . "#" . preg_replace('/[^a-z\d]+/i', "-", $method) . "-2 " . preg_replace('/([_\\\\])/', "\\\\$1", $method) . "]";
|
||
|
|
||
|
};
|
||
|
$wmd .= "\n";
|
||
|
|
||
|
$this->write_wmd($this->root . "/WMD/dev/" . self::$languages[$language] . "/index.w.md", $index, [
|
||
|
"title" => self::$languages[$language],
|
||
|
"subpath" => "/dev/" . self::$languages[$language] . "/index",
|
||
|
"languages" => strtolower(self::$languages[$language]),
|
||
|
"language_name" => self::$languages[$language]
|
||
|
]);
|
||
|
|
||
|
};
|
||
|
|
||
|
$this->write_wmd($this->root . "/WMD/dev/index.w.md", $wmd, [
|
||
|
"title" => "Código",
|
||
|
"subpath" => "/dev/index",
|
||
|
"languages" => "todo,all",
|
||
|
"language_name" => "Todo"
|
||
|
]);
|
||
|
|
||
|
}
|
||
|
|
||
|
};
|