Last active
August 29, 2015 14:24
-
-
Save gwijayas/6d918809f11936b0e704 to your computer and use it in GitHub Desktop.
This script can be used for generating PHP model for IDE. I only successfully run on PHP>=5.4. For PHP 5.3, https://gist.github.com/gwijayas/dc7e85856860851728a5#file-gistfile1-php. Taken from http://git.eclipse.org/c/pdt/org.eclipse.pdt.git/tree/plugins/org.eclipse.php.core/Resources/language/generate.php?h=R3_5_0
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* This script can be used for generating PHP model for PDT. | |
* It builds PHP functions according to the loaded extensions in running PHP, | |
* using complementary information gathered from PHP.net documentation | |
* | |
* @author Michael Spector <[email protected]> | |
*/ | |
if (version_compare(phpversion(), "5.0.0") < 0) { | |
die ("This script requires PHP 5.0.0 or higher!\n"); | |
} | |
$splitFiles = true; | |
$phpdocDir = null; | |
preg_match('/^[^.]+\.[^.]+/', phpversion(), $matches); | |
echo "PHP version: {$matches[0]}\n"; | |
$phpDir = "php".$matches[0]; | |
// Parse arguments: | |
$argv = $_SERVER["argv"]; | |
$argv0 = array_shift ($argv); | |
for ($i = 0; $i < count($argv); ++$i) { | |
switch ($argv[$i]) { | |
case "-nosplit": | |
$splitFiles = false; | |
break; | |
case "-help": | |
show_help(); | |
break; | |
default: | |
$phpdocDir = $argv[$i]; | |
} | |
} | |
if (!$phpdocDir) { | |
show_help(); | |
} | |
$functionsDoc = parse_phpdoc_functions ($phpdocDir); | |
$classesDoc = parse_phpdoc_classes ($phpdocDir); | |
$constantsDoc = parse_phpdoc_constants ($phpdocDir); | |
$processedFunctions = array(); | |
$processedClasses = array(); | |
$processedConstants = array(); | |
@mkdir ($phpDir); | |
if (!$splitFiles) { | |
begin_file_output(); | |
} | |
$extensions = get_loaded_extensions(); | |
foreach ($extensions as $extName) { | |
if ($splitFiles) { | |
begin_file_output(); | |
} | |
print_extension (new ReflectionExtension ($extName)); | |
if ($splitFiles) { | |
finish_file_output("{$phpDir}/{$extName}.php"); | |
} | |
} | |
if ($splitFiles) { | |
begin_file_output(); | |
} | |
$intFunctions = get_defined_functions(); | |
foreach ($intFunctions["internal"] as $intFunction) { | |
if (!@$processedFunctions[strtolower($intFunction)]) { | |
print_function (new ReflectionFunction ($intFunction)); | |
} | |
} | |
$intClasses = array_merge (get_declared_classes(), get_declared_interfaces()); | |
foreach ($intClasses as $intClass) { | |
if (!@$processedClasses[strtolower($intClass)]) { | |
print_class (new ReflectionClass ($intClass)); | |
} | |
} | |
print "\n"; | |
$constants = get_defined_constants(true); | |
$intConstants = @$constants["internal"]; | |
// add magic constants: | |
$intConstants['__FILE__'] = null; | |
$intConstants['__LINE__'] = null; | |
$intConstants['__CLASS__'] = null; | |
$intConstants['__FUNCTION__'] = null; | |
$intConstants['__METHOD__'] = null; | |
if (version_compare(phpversion(), "5.3.0") >= 0) { | |
$intConstants['__DIR__'] = null; | |
$intConstants['__NAMESPACE__'] = null; | |
} | |
foreach ($intConstants as $name => $value) { | |
if (!@$processedConstants[$name]) { | |
print_constant ($name, $value); | |
} | |
} | |
finish_file_output("{$phpDir}/basic.php"); | |
// Create .list file | |
$fp = fopen ("{$phpDir}/.list", "w"); | |
foreach (glob("{$phpDir}/*.php") as $f) { | |
fwrite ($fp, basename($f)); | |
fwrite ($fp, "\n"); | |
} | |
fclose($fp); | |
echo 'Finished...'; | |
// === Functions === | |
/** | |
* Makes generic key from given function name | |
* @param name string Function name | |
* @return string generic key | |
*/ | |
function make_funckey_from_str ($name) { | |
$name = str_replace ("->", "::", $name); | |
$name = str_replace ("()", "", $name); | |
$name = strtolower ($name); | |
return $name; | |
} | |
/** | |
* Replaces all invalid charaters with '_' in PHP identifier | |
* @param name PHP identifier | |
* @return string PHP identifier with stripped invalid characters | |
*/ | |
function clean_php_identifier ($name) { | |
$name = preg_replace('/[^\$\w\_]+/', '_', $name); | |
return $name; | |
} | |
/** | |
* Makes generic key from given function reference | |
* @param name ReflectionMethod function reference | |
* @return string generic key | |
*/ | |
function make_funckey_from_ref ($ref) { | |
if ($ref instanceof ReflectionMethod) { | |
$funckey = strtolower($ref->getDeclaringClass()->getName())."::".strtolower($ref->getName()); | |
} else { | |
$funckey = strtolower($ref->getName()); | |
} | |
return $funckey; | |
} | |
/** | |
* Parses PHP documentation | |
* @param phpdocDir string PHP.net documentation directory | |
* @return array Function information gathered from the PHP.net documentation by parsing XML files | |
*/ | |
function parse_phpdoc_functions ($phpdocDir) { | |
$xml_files = array_merge ( | |
glob ("{$phpdocDir}/reference/*/*/*.xml") | |
); | |
$functionsDoc = array(); | |
foreach ($xml_files as $xml_file) { | |
$xml = load_xml ($xml_file); | |
if (preg_match ('@<refentry.*?xml:id=["\'](.*?)["\'].*?>.*?<refname>(.*?)</refname>.*?<refpurpose>(.*?)</refpurpose>@s', $xml, $match)) { | |
$refname = make_funckey_from_str ($match[2]); | |
$functionsDoc[$refname]['id'] = $match[1]; | |
$functionsDoc[$refname]['quickref'] = trim($match[3]); | |
if (preg_match ('@<refsect1\s+role=["\']description["\']>(.*?)</refsect1>@s', $xml, $match)) { | |
$description = $match[1]; | |
$function_alias = null; | |
$parameters = null; | |
$has_object_style = false; | |
if (preg_match ('@^(.*?)<classsynopsis>.*?<classname>(.*)</classname>.*?<methodsynopsis>.*?<type>(.*?)</type>.*?<methodname>(.*?)</methodname>(.*?)</methodsynopsis>.*?</classsynopsis>(.*)$@s', $description, $match)) { | |
$functionsDoc[$refname]['classname'] = trim($match[2]); | |
$functionsDoc[$refname]['returntype'] = trim($match[3]); | |
$functionsDoc[$refname]['methodname'] = trim($match[4]); | |
$parameters = $match[5]; | |
$description = $match[1].$match[6]; | |
$has_object_style = true; | |
} | |
if (preg_match ('@^(.*?)<classsynopsis>.*?<classname>(.*)</classname>.*?<constructorsynopsis>.*?<methodname>(.*?)</methodname>(.*?)</constructorsynopsis>.*?</classsynopsis>(.*)$@s', $description, $match)) { | |
$functionsDoc[$refname]['classname'] = trim($match[2]); | |
$functionsDoc[$refname]['methodname'] = trim($match[3]); | |
$parameters = $match[4]; | |
$description = $match[1].$match[5]; | |
$has_object_style = true; | |
} | |
if (preg_match ('@<methodsynopsis>.*?<type>(.*?)</type>.*?<methodname>(.*?)</methodname>(.*?)</methodsynopsis>@s', $description, $match)) { | |
if ($has_object_style) { | |
$function_alias = trim($match[2]); | |
} else { | |
//For return type of simplexml_load_string and simplexml_load_file. | |
if(preg_match ('@<refsect1\s+role=["\']returnvalues["\']>(.*?)</refsect1>@s', $xml, $match1)){ | |
$returnvalues = $match1[1]; | |
if(preg_match ('@<type>object</type> of class <type>(.*?)</type>@s', $returnvalues, $match1)){ | |
$functionsDoc[$refname]['returntype'] = trim($match1[1]); | |
}else{ | |
$functionsDoc[$refname]['returntype'] = trim($match[1]); | |
} | |
} | |
else{ | |
$functionsDoc[$refname]['returntype'] = trim($match[1]); | |
} | |
$functionsDoc[$refname]['methodname'] = trim($match[2]); | |
$parameters = $match[3]; | |
} | |
} | |
if ($parameters) { | |
if (preg_match_all ('@<methodparam\s*(.*?)>.*?<type>(.*?)</type>.*?<parameter\s*(.*?)>(.*?)</parameter>.*?</methodparam>@s', $parameters, $match)) { | |
for ($i = 0; $i < count($match[0]); ++$i) { | |
$parameter = array ( | |
'type' => trim($match[2][$i]), | |
'name' => clean_php_identifier(trim($match[4][$i])), | |
); | |
if (preg_match ('@choice=[\'"]opt[\'"]@', $match[1][$i])) { | |
$parameter['isoptional'] = true; | |
} | |
if (preg_match ('@role=[\'"]reference[\'"]@', $match[3][$i])) { | |
$parameter['isreference'] = true; | |
} | |
$functionsDoc[$refname]['parameters'][] = $parameter; | |
} | |
} | |
} | |
} | |
if (preg_match ('@<refsect1\s+role=["\']parameters["\']>(.*?)</refsect1>@s', $xml, $match)) { | |
$parameters = $match[1]; | |
if (preg_match_all('@<varlistentry\s*.*?>.*?<parameter>(.*?)</parameter>.*?<listitem\s*.*?>(.*?)</listitem>.*?</varlistentry>@s', $parameters, $match)) { | |
for ($i = 0; $i < count($match[0]); $i++) { | |
for ($j = 0; $j < count(@$functionsDoc[$refname]['parameters']); $j++) { | |
if ($match[1][$i] == $functionsDoc[$refname]['parameters'][$j]['name']) { | |
$functionsDoc[$refname]['parameters'][$j]['paramdoc'] = xml_to_phpdoc ($match[2][$i]); | |
break; | |
} | |
} | |
} | |
} | |
} | |
if (preg_match ('@<refsect1\s+role=["\']returnvalues["\']>(.*?)</refsect1>@s', $xml, $match)) { | |
$returnvalues = $match[1]; | |
if (preg_match ('@<para>\s*(Returns)?(.*)</para>?@s', $returnvalues, $match)) { | |
$functionsDoc[$refname]['returndoc'] = xml_to_phpdoc ($match[2]); | |
} | |
} | |
if (preg_match ('@&warn\.deprecated.func-(.*?);@s', $xml, $match)) { | |
$deprecatedSince = $match[1]; | |
$functionsDoc[$refname]['deprecated'] = 'Since ' . str_replace('-', '.',$deprecatedSince); | |
} | |
// Create information for function alias | |
if ($function_alias) { | |
$functionsDoc[$function_alias] = $functionsDoc[$refname]; | |
} | |
} | |
} | |
return $functionsDoc; | |
} | |
/** | |
* Parses PHP documentation | |
* @param phpdocDir string PHP.net documentation directory | |
* @return array Class information gathered from the PHP.net documentation by parsing XML files | |
*/ | |
function parse_phpdoc_classes ($phpdocDir) { | |
$classesDoc = array(); | |
$xml_files = array_merge ( | |
glob ("{$phpdocDir}/reference/*/reference |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment