"constructor", "__destruct" => "destructor", "__call" => "mágico" ]; public function analyze($file, $path = null, &$languages = [], $level = 0){ if(!($content = \WMarkDown\ScriptsAnalyzer::get_content($file, $path))) return; $namespace = ""; $class_name = ""; $class_type = "default"; $security = [0]; $p = [1, 2, 4]; // Cursor position. $data = \WMarkDown::string_variables(file_exists($wmd_path = $this->parent->get_wmd_path($file, $path)) ? file_get_contents($wmd_path) : $this->original_wmd, array_merge([ "subkey_words" => preg_match('/^.+' . $this->common["project"] . '\.([^\/]+)\.php\.w\.md$/', $wmd_path) ? preg_replace_callback('/^.+' . $this->common["project"] . '\.([^\/]+)\.php\.w\.md$/', function($values){ return substr(preg_replace('/[,\.]+/', ",", preg_replace_callback('/([A-Z]+)?([A-Z][a-z0-9]+)/', function($subvalues){ return ($subvalues[1] ? "," . $subvalues[1] : "") . "," . strtolower($subvalues[2]); }, $values[1])), 1); }, $wmd_path) : "main", "path" => substr($wmd_path, $this->root_l + 8), "subpath" => substr($wmd_path, $this->root_l + 8, -5), "file" => preg_replace('/^.+\/([^\/]+)\.w\.md$/', "$1", $wmd_path) ], $this->common)); $last_method = null; !isset($languages["php"]) && ($languages["php"] = []); $languages["php"][$x = count($languages["php"])] = ["path" => $wmd_path, "level" => $level, "methods" => []]; // Limpiamos el Script de saltos de línea y comentarios y unificamos los espaciados. $content = preg_replace_callback('/("(([^\\\\"]+|\\\\.)*)"|\'(([^\\\\\']+|\\\\.)*)\')|([\t\s]|[\r\n]|\/\/[^\r\n]*|\/\*(([\r\n]+|[^\*]+|\*[^\/])*)\*\/)+/', function($values){ return $values[1] ? $values[0] : " "; }, $content); // Buscamos espacios de nombres, clases, interfaces, abstracciones y métodos. while((true || $security[0] ++ < 100) && preg_match('/\b(' . 'namespace ([^; ]+);|' . '(class|interface) ([a-zA-Z0-9_]+)|' . '((public|protected|private) )?(static )?function ([a-zA-Z0-9_]+) ?\(' . ')/', $content, $matches, PREG_OFFSET_CAPTURE)){ $l = count($matches); $content = substr($content, $matches[0][1] + strlen($matches[0][0])); if($l > $p[2] + 1){ // Método. $method_access = trim($matches[$p[2] + 1][0]); $method_name = $matches[$p[2] + 4][0]; $languages["php"][$x]["methods"][] = $method_full_name = $class_name . ($matches[$p[2] + 3][0] ? "::" : "->") . $method_name; $method_type = isset(self::$custom_types[$method_name]) ? self::$custom_types[$method_name] : ($matches[$p[2] + 3][0] ? "static" : "object"); $parameters = []; $see = []; $return = null; $security[1] = 0; $security[2] = 0; if(trim($content)[0] != ")"){ // Verificamos que tiene parámetros. $i = 1; // Si llega a 0 es que se cerró el bloque de los parámetros. $default_value = ""; $parameter_name = null; $parameter_type = null; $parameter_reference = false; // Analizamos los parámetros. while((true || $security[1] ++ < 20) && preg_match('/' . '(((?![\$\&])[a-zA-Z0-9_])+ )?(\&)?\$([a-zA-Z0-9_]+)|' . ' ?(=) ?(null|true|false|\d+|"(([\\\\"]+|\\\\.)*)"|\'(([\\\\\']+|\\\\.)*)\')?|' . ' ?(,) ?|' . '([^,\(\)\[\]\{\}"\']+|"(([\\\\"]+|\\\\.)*)"|\'(([\\\\\']+|\\\\.)*)\')|' . '([\(\[\{])|([\}\]\)])' . '/', $content, $submatches, PREG_OFFSET_CAPTURE)){ $m = count($submatches); $content = substr($content, $submatches[0][1] + strlen($submatches[0][0])); if($m > 17 && $submatches[17][0]) // Apertura de bloque. $i ++; else if($m > 18 && $submatches[18][0]){ // Cierre de bloque. if(!-- $i){ $parameters[] = [ "name" => $parameter_name, "type" => $parameter_type, "reference" => $parameter_reference, "default" => $default_value ]; break; }; }elseif($m > 11 && $submatches[11][0]){ // Se cierra un parámetro. if($i > 1) $default_value = $default_value . $submatches[0][0]; else{ $parameters[] = [ "name" => $parameter_name, "type" => $parameter_type, "reference" => $parameter_reference, "default" => $default_value ]; $default_value = ""; $parameter_name = null; $parameter_type = null; $parameter_reference = false; }; }elseif($submatches[4][0]){ // Se crea un nuevo parámetro. $parameter_name = ($submatches[3][0] ? "&" : "") . "$" . $submatches[4][0]; $parameter_type = $submatches[1][0] ? $submatches : null; $parameter_reference = !!$submatches[3][0]; }elseif($m > 6 && $submatches[6][0]) // Valor por defecto. $default_value = $submatches[6][0]; }; }else // No tiene párametros de entrada. $content = substr($content, 1); $i = 0; $body = ""; // Analizamos bloques de sentencias para analizar inicio y fin del método. while((true || $security[2] ++ < 40) && preg_match('/[\{\}]/', $content, $submatches, PREG_OFFSET_CAPTURE)){ $end = false; $body .= substr($content, 0, $submatches[0][1]) . $submatches[0][0]; $content = substr($content, $submatches[0][1] + strlen($submatches[0][0])); switch($submatches[0][0]){ case "{": $i ++; break; case "}": $end = !-- $i; break; }; if($end) break; }; // Analizamos retorno. $return = preg_match('/\breturn[^;]+[; ]*}$/', $body) ? true : null; // Buscamos dependencias de sí mismo. preg_replace_callback('/"(([^\\\\"]+|\\\\.)*)"|\'(([^\\\\\']+|\\\\.)*)\'|(\$this\->([a-zA-Z0-9_]+|\->)+|\\\\?([a-zA-Z0-9_\\\\]+|\\\\)::[a-zA-Z0-9_]+)\(/', function($values) use(&$see, $class_name){ if(count($values) < 6 || ($values[6] && !preg_match('/\$this\->([^\-\(]+\(|wmarkdown\->)/', $values[0]))) return; !in_array($method = ($method = preg_replace('/^(\$this(\->)|self(\:{2}))/', $class_name . "$2$3", preg_replace('/^\$this\->wmarkdown/', "\\WMarkDown", substr($values[0], 0, -1))))[0] == '\\' ? substr($method, 1) : $method, $see) && ($see[] = $method); }, $body); // Añadimos el método al código WMD almacenado en $data tras el último método registrado. $data = $this->parent->add_method($data, $last_method, [ "access" => $method_access, "language_script" => "PHP", "name" => $method_full_name, "type" => $method_type, "see" => $see, "parameters" => $parameters, "return" => $return, "hash" => md5($content) ]); $last_method = $method_full_name; }elseif($l > $p[1] + 1){ // Clase $class_type = $matches[$p[1] + 1][0]; $class_name = $namespace . '\\' . $matches[$p[1] + 2][0]; }else // Espacio de nombres. $class_name = $namespace = $matches[$p[0] + 1][0]; }; // Creamos el fichero WMD del fichero PHP. \WMarkDown::save_file($wmd_path, $data); } };