Skip to content

Instantly share code, notes, and snippets.

@krakjoe
Last active April 17, 2023 11:03
Show Gist options
  • Save krakjoe/4cf450771db2b4a2274bade5d2c7d025 to your computer and use it in GitHub Desktop.
Save krakjoe/4cf450771db2b4a2274bade5d2c7d025 to your computer and use it in GitHub Desktop.
for generating stubs for a loaded extension
<?php
/*
usage: php document.php --ext name [--output document.txt]
*/
function prototype(Reflector $reflector) {
$elements = [];
switch (get_class($reflector)) {
case "ReflectionClass":
if ($reflector->isFinal()) {
$elements[] = "final";
}
$elements[] = "class";
$elements[] = $reflector->getName();
if ($interfaces = $reflector->getInterfaces()) {
$elements[] = "implements";
foreach ($interfaces as $interface => $r)
$ifs[] = $interface;
$elements[] = implode(", ", $ifs);
}
if ($parent = $reflector->getParentClass()) {
$elements[] = "extends";
$elements[] = $parent->getName();
}
break;
case "ReflectionProperty":
if ($reflector->isPublic()) {
$elements[] = "public";
} else if ($reflector->isProtected()) {
$elements[] = "protected";
} else {
$elements[] = "private";
}
if ($reflector->isStatic()) {
$elements[] = "static";
}
$elements[] = sprintf("\$%s", $reflector->getName());
break;
case "ReflectionParameter":
if ($type = $reflector->getType()) {
$elements[] = (string) $type;
}
$elements[] = sprintf("\$%s", $reflector->getName());
break;
case "ReflectionMethod":
if ($reflector->isFinal()) {
$elements[] = "final";
}
if ($reflector->isPublic()) {
$elements[] = "public";
} else if ($reflector->isProtected()) {
$elements[] = "protected";
} else {
$elements[] = "private";
}
if ($reflector->isStatic()) {
$elements[] = "static";
}
/* intentional fall through */
case "ReflectionFunction":
$elements[] = "function";
$elements[] = $reflector->getName();
$elements[] = "(";
$ps = [];
foreach ($reflector->getParameters() as $parameter)
$ps[] = prototype($parameter);
$elements[] = implode(", ", $ps);
$elements[] = ")";
if ($return = $reflector->getReturnType()) {
$elements[] = ":";
$elements[] = (string) $return;
}
break;
}
return implode(" ", $elements);
}
function document(array $config, Reflector $reflector, ?Reflector $parent, $output) {
switch (get_class($reflector)) {
case "ReflectionExtension":
foreach ($reflector->getConstants() as $name => $constant)
fprintf($output, "const %s;\n", $name);
foreach ($reflector->getClasses() as $class)
document($config, $class, $reflector, $output);
foreach ($reflector->getFunctions() as $function)
document($config, $function, $refllector, $output);
break;
case "ReflectionClass":
fprintf($output, "%s {\n", prototype($reflector));
foreach ($reflector->getConstants() as $name => $constant)
fprintf($output, "\tconst %s;\n", $name);
foreach ($reflector->getProperties(REFLECTIONPROPERTY::IS_STATIC) as $property)
document($config, $property, $reflector, $output);
foreach ($reflector->getProperties(ReflectionProperty::IS_PUBLIC) as $property)
document($config, $property, $reflector, $output);
foreach ($reflector->getProperties(ReflectionProperty::IS_PROTECTED) as $property)
document($config, $property, $reflector, $output);
foreach ($reflector->getProperties(ReflectionProperty::IS_PRIVATE) as $property)
document($config, $property, $reflector, $output);
foreach ($reflector->getMethods() as $method)
document($config, $method, $reflector, $output);
fprintf($output, "}\n");
break;
case "ReflectionProperty":
if ($reflector->getDeclaringClass()->getName() == $parent->getName())
fprintf($output, "\t%s;\n", prototype($reflector));
break;
case "ReflectionMethod":
if ($reflector->getDeclaringClass()->getName() == $parent->getName())
fprintf($output, "\t%s;\n", prototype($reflector));
break;
case "ReflectionFunction":
fprintf($output,"%s;\n", prototype($reflector));
break;
}
}
$config = [
"exec" => array_shift($argv),
"ext" => null,
"output" => "document.txt",
"flags" => []
];
while ($arg = array_shift($argv)) {
switch ($arg[0]) {
case "-": switch ($arg[1]) {
case "-":
$config[substr($arg, 2)] = array_shift($argv);
break;
default:
$config["flags"][substr($arg, 1)] = true;
}
}
}
if (!$config["ext"] || !extension_loaded($config["ext"])) {
throw new \RuntimeException(
$config["ext"] ?
"{$config["ext"]} not loaded" :
"no extension specified");
}
$output = fopen($config["output"], "w+");
if (!$output) {
throw new \RuntimeException(
"could not open {$config["output"]} for writing");
}
document($config, new ReflectionExtension($config["ext"]), null, $output);
fclose($output);
?>
@jersonmartinez
Copy link

Excellent

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment