<?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/01/simple-class-api-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(truetrue);

?>