Sistema de documentación y gestión de páginas Web para un entorno o proyecto Web.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
WMarkDown/PHP/WMarkDown.ScriptsAnalyzer.php

401 lines
17 KiB

<?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"
]);
}
};