Simple Class API Generator
Posted: Sat Sep 15, 2007 4:12 pm
PHP 5 comes with a complete reflection API that adds the ability to reverse-engineer classes, interfaces, functions and methods as well as extensions. Additionally, the reflection API also offers ways of retrieving doc comments for functions, classes and methods. This is extremely handy when you want to generate an API for the code you are writing.
Now I know there are already projects dedicated for creating API's from documentation. Projects such as phpDocumentor do the job very well. But what I have here is a simple API Generator without all the bells and whistles.
This code was developed so that I can show the Class functions and its params which were exposed through Webservices. Nowadays I tend to use its functionality to just observe what functions are available within a class and its params. Example if I want to view the functions available in the SPL DirectoryIterator class, I don't have to head to the php.net manual, instead I just do the following:
cheers,
Jeffery
Now I know there are already projects dedicated for creating API's from documentation. Projects such as phpDocumentor do the job very well. But what I have here is a simple API Generator without all the bells and whistles.
This code was developed so that I can show the Class functions and its params which were exposed through Webservices. Nowadays I tend to use its functionality to just observe what functions are available within a class and its params. Example if I want to view the functions available in the SPL DirectoryIterator class, I don't have to head to the php.net manual, instead I just do the following:
Code: Select all
<?php
$api = new SCA_Generator('DirectoryIterator');
$api->create_class_api(true, true);
?>Code: Select all
<?php
/**
* This is an API generator Class.
*
* It will generate documentation for a given class which has already been
* loaded with an include or require call.
*
* @author Jeffery Fernandez <developer@jefferyfernandez.id.au>
* @copyright Free to use as long as you keep the Authors name intact
* @link http://jefferyfernandez.id.au/2007/09/0 ... generator/
*
* @todo Get the constants of the class
*
* Simple Class API Generator
* @since 1st September, 2007
* @version 0.3 Updated on 15th September, 2007
*/
Class SCA_Generator
{
/**
* To store the Class name
*
* @var $class_name
*/
private $class_name;
/**
* The constructor for the API Generator
*
* @param string $class_name The name of the Class for which to generate the API
* @return void
*/
public function __construct($class_name)
{
if (class_exists($class_name))
{
$this->class_name = $class_name;
}
else
{
echo "Class not loaded. Please include/require the Class ($class_name) you have specified";
exit;
}
}
/**
* A Test function with bogus params
*
* @param SCA_Generator $blah
* @param array $test
* @return void
*/
public static function test_function(SCA_Generator $blah, $test = array())
{
echo "This is just a test function to show you how the API is generated";
}
/**
* Generates the API for the Class
*
* @param boolean $show_private Decide to show private variables/functions
* @param boolean $show_protected Decide to show protected variables/functions
* @return void
*/
public function create_class_api($show_private = false, $show_protected = false)
{
$r_class = new reflectionClass($this->class_name);
###################### Class & its Definition ######################
// Get the Comments
$comments = $r_class->getDocComment();
// check if the class extends any other classes
$parent_class = $r_class->getParentClass();
$extends = (isset($parent_class->name)) ? " extends {$parent_class->name}" : '';
// Get the Class type
$class_type = $r_class->isInterface()
? 'Interface '
: (
($r_class->isAbstract())
? 'Abstract Class'
: (
($r_class->isFinal())
? 'Final Class '
: 'Class '
)
);
// Get the Class interfaces
$interfaces = $r_class->getInterfaces();
$implements = '';
if (count($interfaces))
{
foreach ($interfaces as $name => $reflection_object)
{
$implements .= ($implements == '')
? " implements {$reflection_object->name}"
: ", {$reflection_object->name}";
}
}
echo "<pre>$comments\n{$class_type}{$this->class_name}{$extends}{$implements}\n{</pre>";
###################### Class & its Definition ######################
###################### Class Properties & Comments #################
$class_constants = $r_class->getConstants();
//@todo print_r($class_constants);
$class_attributes = $r_class->getProperties();
$attributes = array();
foreach($class_attributes as $property)
{
// If we are allowed to see private/protected properties
if(
($show_private && $property->isPrivate()) ||
($show_protected && $property->isProtected()) ||
((!$property->isPrivate()) && (!$property->isProtected()))
)
{
$r_property = new reflectionProperty($this->class_name, $property->getName());
// Get the Comments for the property
$attributes[$property->name]['comment'] = $r_property->getDocComment();
// Get the Visibility
$property_visibility[$property->name] = ($property->isPrivate())
? 'private'
: ($property->isProtected() ? 'protected' : 'public');
}
}
ksort($attributes);
foreach ($attributes as $index => $attribute)
{
echo "<pre>\t{$attribute['comment']}\n\t{$property_visibility[$index]} \${$index};</pre>";
}
###################### Class Properties & Comments #################
###################### Methods & Parameters ########################
$class_methods = $r_class->getMethods();
foreach($class_methods as $method)
{
$r_method = new reflectionMethod($this->class_name, $method->name);
if (
($show_private && $r_method->isPrivate()) ||
($show_protected && $r_method->isProtected()) ||
((!$r_method->isPrivate()) && (!$r_method->isProtected()))
)
{
// Check if its a static method
$static = ($r_method->isStatic()) ? ' static' : '';
// check the visibility of the method
$visibility = ($r_method->isPrivate())
? 'private'
: ($r_method->isProtected() ? 'protected' : 'public');
// Get the comments for the method
$method_comments = $r_method->getDocComment();
$parameters = '';
$method->params = $method->getParameters();
$all_optional = false;
foreach ($method->params as $position => $parameter)
{
// Check if the first parameter is optional.
if ($position == 0)
{
$all_optional = ($parameter->isOptional()) ? true : false;
}
// Get the Default values for the parameter
$default_value = '';
if ($parameter->isDefaultValueAvailable())
{
$value = var_export($parameter->getDefaultValue(), true);
$default_value = ' = ' . str_replace("\n", '', $value);
}
// Check if the parameter is of a Class Type
$class_type = ($parameter->getClass()) ? $parameter->getClass()->name . ' ' : '';
// check if the parameter is passed by reference
$reference = ($parameter->isPassedByReference()) ? '&' : '';
// Build the parameter
$prmtr = (
($parameters != '')
? ", "
: ''
) .
"{$class_type}{$reference}\${$parameter->name}{$default_value}";
// Check if it is an optional parameter and add the square brackets
$prmtr = (
$parameter->isOptional() &&
(!
(
($position == 0) &&
($all_optional)
)
)
)
? "[{$prmtr}]"
: $prmtr;
$parameters .= $prmtr;
}
$parameters = ($all_optional) ? "[{$parameters}]" : $parameters;
echo "<pre>\t{$method_comments}\n\t{$visibility}{$static} function {$method->name}({$parameters})</pre>";
echo "<br />";
}
}
###################### Methods & Parameters ########################
echo "}";
}
}
$api = new SCA_Generator('SCA_Generator');
$api->create_class_api(true, true);
?>Jeffery