Home/Section index
 www.icosaedro.it 

 PHPLint Documentator

Latest updated: 2009-04-25

Index

Introduction
What will be reported
The description
Documenting the package
Documenting constants
Documenting variables
Documenting functions
Documenting classes
Special tags
Specifying items
Handling the project layout
Support for internationalization
Generating the documentation
Examples

Introduction

PHPLint support a "documentator" facility, a tool that automatically generates the documentation about a PHP source. Basically, the programmer adds some comments, appropriately formatted, and PHPLint merges them with the informations it gathered from the parsing stage. All these informations are formatted and saved in a file in HTML format. PHPLint supports either the phpDocumentor commenting style and its own commenting style. This latter, named "PHPLint Documentor" is described here.

For example, take this source:


<?php

/*. DOC Sample package.

    <@package DoNothing>
    This package does nothing, it's only an example.
    Items internal to the package, as <@item HowManyEmptyElems()>,
    and external to the package, can be referenced.
.*/

/*. require_module 'standard';
    require_module 'mysql';
.*/

$myData = array("one", "two", "");
/*. DOC  No much to say about this array... .*/


/*. int .*/ function HowManyEmptyElems(/*. array .*/ $a)
/*.
    DOC  Returns the number of empty elements

    The array is scanned, element by element. All the elements that
    result to be <@item empty()> are counted, and the result is
    returned.

    <@see count()>
    <@see array_count_values()>
.*/
{
    if( $a === NULL )  return 0;
    $n = 0;
    foreach($a as $v)
        if( empty($v) )  $n++;
    return $n;
}
?>

The generated output for this package will look similar to this:


DoNothing

Sample package.

PHP version: 5

Required modules:

Required packages: none

This package does nothing, it's only an example. Items internal to the package, as HowManyEmptyElems(), and external to the package, can be referenced.



array[int]string $myData

No much to say about this array...


int HowManyEmptyElems(array $a)

Returns the number of empty elements

The array is scanned, element by element. All the elements that result to be are counted, and the result is returned.

See also:



What will be reported

These items are reported:

PHP 4 lacks the visibility attribute "private", but PHPLint provides a meta-code alternative. See the section about PHP 4 classes in the PHPLint manual for more details.

PHP 5 lacks the visibility attribute "private" for constants, functions, classes and class constants, but PHPLint provides a meta-code alternative. See the section about PHP 5 classes in the PHPLint manual for more details.

For functions and methods also the thrown exceptions are listed. Thrown exceptions are are collected by PHPLint from several sources:

All the exceptions generated, inherited and declared are collected by PHPLint and then listed in the generated documentation in the order from more specialized ones, to less specialized ones; then exceptions are listed just in the same recommended order them should be handled a chain of catch() branches.

These are the items not documented that are listed inside the section "Private items" of the generated document:

These items are not reported at all:

The description

At the base of the PHPLint Documentator is the description, a special formatted multi-line comment. This comment contains a short description and a long description. After the starting symbol "/*." there must be the word "DOC" that marks this comment to be a description (rather than a chunk of PHPLint meta-code). The short description is the string that continue from this word up-to the end of the line or the end of the comment. The long description is all the text remaining from the short description up-to the end of the comment. For example:

/*. DOC This is the short description
    This is the long description. This is the long
    description. This is the long description. .*/

The spaces before the word "DOC" are ignored. After the DOC word, the linear spaces " " and "\t" are skipped. Another valid form, perfectly equivalent but more readable:

/*.
    DOC    This is the short description

    This is the long description. This is the long
    description. This is the long description.
.*/

The format of a description is the HTML code. Note that the special sequences "?>" and "*/" cannot be inserted directly inside a description, since them would confuse either PHP and PHPLint. These sequences can be inserted respectively as "?&gt;" and "&#42;/".

Documenting the package

A "package" in the sense of PHPLint, is simply the file from which the documentation has to be extracted. For example:

/*.
    DOC  General data manipulation and utilities

    <@package MyPackage>
    <@version 1.0 revision 2>
    <@author Umberto Salsi>
    This package can handle nearly any thing: numbers, strings,
    books, paintings, songs, humans and animals. Amazing and
    simple to use. Really!
.*/

Note the special sequences of the form <@...>: we will describe them below.

Typically the description of the package is placed at the top of the source and before any declaration, but this is not mandatory. If two or more package descriptions are present, their contents are concatenated to the first description.

Since a package is a generic PHP program, it might declare several constants, variables, functions and classes, in any order. Only the variables that are global are reported: variables that are local to the functions are not considered. Items imported from other included packages are not reported.

Documenting constants

The description of a constant must follow immediately its definition, and before any other PHP instruction or PHPLint meta-code:

define('PI', 3.14);
/*.
    DOC  Popular value of the greek "pee" constant

    The value is approximated to two decimals, but for some
    applications it might be required a more accurate value, for
    example 3.141592.  The <code>standard</code> module provides the
    constant <code>M_PI</code> that is far more accurate.
.*/

Documenting variables

The description of a global variable must follow immediately its first assignment, and before any other PHP instruction or PHPLint meta-code:

$logged_users = /*. (array[int]string) .*/ array();
/*. DOC List of the logged users, initially empty .*/

In this example we have omitted the long description, since the short description seems to be enough. Note that we don't need to specify the type of the variable, since this information is already available to the parser and it will be reported into the documentation. The initial value assigned to the variable, however, is not gathered by the parser and, if required, it must be specified along the description.

Documenting functions

The description of a function must follow the list of the formal arguments, just before the open curly brace:

/*. void .*/ function logIt(/*.resource.*/ $fd, /*.string.*/ $msg /*., args .*/)
/*.
    DOC   Write the message to the file

    Write the message $msg to the opened file $fd, adding
    a terminating "\n". If $msg is NULL or empty, raises a
    E_USER_WARNING and the argument is ignored. If $msg is
    longer than 100 bytes it is shortened to 100 bytes. If
    more arguments are passed to the function, they are
    expected to be strings and are treated exactly as $msg.
.*/
{
    ...code here...
}

The type of the formal arguments and the type of the returned value are already gathered by PHPLint, so they don't need to be specified again inside the description.

Documenting classes

In the paragraphs above we familiarized with the basic principles of the PHPLint Documentator: first the declaration, then the description. Since the declaration alone already carries so much informations, the description may concentrate on the other details, without repeating what PHPLint already knows. Similar concepts applies to the classes as well:


class ChildClass extends ParentClass
/*.
    DOC  Implements some beautiful/specialized features

    Long description of the class here. It might include a survey of
    all the public and protected items, along with some examples of
    code and <a href="http://www.xyz.com/">external</a> references
    for insights.
.*/
{
    const A_CLASS_CONST = 'ssss';
    /*. DOC  Description of a class constant .*/


    protected static /*. mixed .*/ $my_data = NULL;
    /*. DOC  Description of a property .*/


    public /*. void .*/ function __construct()
    /*.
        DOC  Description of the class constructor

        You might want to provide more information about this
        special method inside the long description section of
        the DOC.  Note that the description of a method must
        follow the list of the formal arguments and must precede
        the open curly brace {.
    .*/
    { }


    public /*. void .*/ function set(/*. mixed .*/ $value)
    /*.
        DOC  Sets the internal state of this object

        Guess what: this method just sets the protected variable
        <@item ::my_data>.  No much to say about this method -
        it's really simple.
        <@see ::Get()>
    .*/
    {
        $this->my_data = $value;
    }


    public /*. mixed .*/ function get()
    /*.
        DOC  Returns the internal state of this object

        Please, note that if you haven't set before the state of
        this object, the value returned will be NULL.
        <@see ::Set()>
    .*/
    {
        return $this->my_data;
    }

}

interface Tree
/*. DOC  Example of interface class .*/
{
    /*. void .*/ function left();
    /*. DOC  Move to the left branch .*/

    /*. void .*/ function right();
    /*. DOC  Move to the right branch .*/
}

abstract class File implements Tree
/*. DOC  Example of abstract class .*/
{
    public /*. File .*/ $current = NULL;
    /*. DOC  Current node of the file system tree .*/

    abstract /*. void .*/ function left();
    /*. DOC  Move to the left file (whatever this might mean...) .*/

    abstract /*. void .*/ function right();
    /*. DOC  Move to the right file (whatever this might mean...) .*/

    public /*. void .*/ function create(/*. string .*/ $name)
    /*. DOC  Create a new file in the current node .*/
    { }
}

This example is for PHP 5, but the same apply to PHP 4, with the only difference that there are not class constants and the visibility qualifiers and the "final" and "static" attributes are implemented via PHPLint meta-code. Private items are not reported, so that they don't need to be documented.

Special tags

Maybe you noticed some strange sequences of characters inside the descriptions having the form "<@tag arg>". These special tags are parsed by the documentator. Some of these special tags are substituted by another string; others provide some informations to the documentator and are removed from the description.

The "arg" part of the tag is a text of arbitrary length that can span several lines and must be in the HTML format. At least a space between the "tag" part and the "arg" part is required to separate the two elements. The "arg" part may include other special tags, typically the <@item> tags.

Here is the list of the available tags:

<@package canonical_name_of_the_package>
By default, the name of the package is its file name, with the path part and the extension removed. For example, if the file is /home/user/myclass.php the default name will be myclass. This special tag lets the programmer to assign a different name to the package. For example, writing "<@package MyClass>" inside the description of the package, the name of the package reported into the documentation will be "MyClass".

<@version html_text>
Sets the version of the documented item. The argument may be any valid HTML text. Typically this tag appears inside the package description or the class description, but you can provide a version to any item.

<@copyright html_text>
Sets the copyright of the documented item, typically the package.

<@license html_text>
Sets the license of the documented item, typically the package.

<@author html_text>
The author of the item. Typically this tag is part of the package description, but in bigger packages you might have many classes or functions, each one with its author. Two or more <@author> tags inside a description are combined in a comma-separated list, with the ordering of the authors preserved, and reported under the label "Author:" into the description of the item documented.

<@since html_text>
Sets since which version the item is available. The "version" we are referring to depends on the type of the item: normally it is the version of the package, but for items inside a class that provide its own version, this latter is the version we are referring to.

<@item item>
Inserts the HTML anchor to the given item: a constant, a global variable, a function, a class, a class constant, a property or a method. The item to which we are referring to might be either in the same package or in another package. For example, <@item ChildClass::set()> sets a "click-able" reference to the method set() of the class ChildClass. The format of the item specifier is described in the next paragraph "Specifying items".

<@see item>
Syntactically similar to the <@item> tag, with the difference that it is removed from the description. The format of the item specifier is describe in the next paragraph "Specifying items". All the items referred inside a description are summarized in a comma separated list and displayed at the end of the description under the label "See also:" of the generated document.
<@see strlen()>
<@see MyClass::strSize()>
<@deprecated html_text>
This tag marks the documented item as "deprecated". The text provided will be rendered under the label "Deprecated:" of the generated document. PHPLint also raises a warning message every time a deprecated item is used:
- require_module of a deprecated extension module
- require_once of a deprecated package
- usage of deprecated constant/ variable/ function/ class
- usage of deprecated class constant/ property/ method
- usage of non-deprecated class constant/ static property/ static method exported by a deprecated class
Typically, deprecated items are modules, packages, functions, classes, class constants, properties, and methods that should not be used anymore, and the text should explain why. Possible reasons might be: the item is no more supported; it is bugged; there is a better alternative; might be removed in future release of the package; it is still available for compatibility with older applications. Example:
<@deprecated  <@item ::oldMethod()> should not be used
anymore because it does not handle the new format of the data (it
raises an error).  Use <@item ::newMethod()> instead or, even better,
the new extended class <@item NewClass> >

PHPLint raises an error if a non-private class (PublicChild) tries to extend a private one (PrivateParent), since the program can't sets the HTML anchor pointing to this private parent class, like in this example:

/*. private .*/ class PrivateParent { }

class PublicChild extends PrivateParent { }

Specifying items

The special tags <@items> and <@see> allows to specify an item exported by any package parsed by PHPLint, including the standard modules. An item may be a constant, a variable, a function, a class, e class constant (PHP 5), a property or a method.

Note. Private properties and private methods cannot be referenced inside the descriptions since they does not exit at all for the client packages so do not require to be documented.


Item specifierItem referred
CONSTA constant.
$variableA global variable. Local variables and function parameters cannot be referred.
Func()A function. Note that the parentheses are required. You might want to add some text inside the parentheses, for example the values of the arguments.
ClassA class.
Class::CONSTA class constant (PHP 5).
Class::$propertyA property.
Class::method()A method. Note that the parentheses are required. You might want to add some text inside the parentheses, for example the values of the arguments.

Commenting a class and the items exported by that class, the class name may be omitted for brevity when referring to items inside the same class the current description belongs. For example, <@item ::$prop> refers to the property $prop of the current class.

PHPLint Documentator raises an error if the item specified is misspelled or do not exist in the source just parsed. Items outside the set of sources parsed in the current run may be referenced by a hand-written HTML anchor, for example:

<a href="modules/pcre.html#preg_match()">preg_match()</a>

Handling the project layout

A project might consist of several files, spread over a variety of directories and sub-directories. The Documentator generates the documentation trying to preserve the original layout of the project, but some fine tuning might still be required. The features described here are intended just to this purpose.

Relative references. Since the source of a package and its documentation might be stored in different locations, or different computers, the Documentator has special provisions to handle the specific layout of your development system.

Internally, PHPLint store the path of every file as absolute paths. Then the Documentator always try to build relative path-files while composing the URLs of the references, so that the documents generated might be moved preserving the hypertextual links. For example, if the document located in the file

/home/MyName/php-src/MyWebApp.html
needs to reference the item
/home/MyName/php-libs/MyLib.html#$aVar
then the Documentator will guess the URL as
../php-libs/MyLib.html#$aVar

References remapping. As said, the Documentator always try to build HTML anchors as relative paths. This process begins first taking the absolute path of the file, then comparing this absolute path with the absolute path of the source currently being parsed. If a leading part of the two paths match, a relative path is made. For example:

Current source: /home/MyName/libs/utils/formatter.php
External file to be referenced: /home/MyName/libs/bignum/bigint.php
Resulting relative path: ../../bignum/bigint.php

Sometimes relative references aren't enough: if the destination of the generated documentation has a different layout, the documentation cannot be moved to that final destination without breaking the links. So, the Documentator provides another even more general mechanism: the reference remapping. A reference remap is set by the command line option --doc-ref-remap A B. This option says that if the absolute path of a reference begins with the string "A", then that string must be replaced by "B".

Suppose, for example, that both formatter.html and the bigint.html files generated from the example above have to be moved into the same destination directory /usr/www/lib/ so breaking the relative path form formatter.html to ../../bigint.html. In this case we may re-map /home/MyName/lib/bignum/ to /home/MyName/lib/:

phplint --php-version 4 --doc \
        --doc-ref-remap  /home/MyName/lib/bignum/  /home/MyName/lib/ \
        formatter.php
will map any reference to items defined inside

Several --doc-ref-remap options can be provided, and these are applied in the order to every link until a match is found. If no match is found, no replacement take place.

Trick. Set a reference remapping to a WEB application, giving the name of the the document as a parameter:

--doc-ref-remap  /home/MyName/lib/ \
                 http://www.mydomain.com/browse.php?lib=

Every reference to your library will be remapped to an URL having the form http://www.mydomain.com/browse.php?lib=xxxx.

Trick. Set a reference remapping to a label that is simple to parse later for string substitutions:

--doc-ref-remap  /home/MyName/lib/ \
                 /__THE_DIR__/

Any character between __THE_DIR__ and the following double-quote " if the item being referenced.

Order of the transformations. For every reference inside the documentation, the Documentator applies these transformations, in this order:

  1. Relative path-files are converted to absolute path-files. As said, PHPLint internally always store the paths as absolute paths: "." and ".." are resolved, multiple directory separators "//" are resolved to single directory separator "/", symbolic links are preserved (the Documentator operates only on strings and does not check for the actual existence of the path-files it found). For example, if the directory of the file being parsed is "/home/MyName/php-src/" then:
    MyAppl.php becomes
    /usr/MyName/php-src/MyAppl.php
  2. Then the extension is dropped and the defined extension is added. The default extension is ".html" but the option --doc-extension" lets to change it. For example:
    /usr/MyName/php-src/MyAppl.php becomes
    /usr/MyName/php-src/MyAppl.html
  3. The reference remappings are applied. Only the first remap that match is applied. If none match, no remapping is done. For example, if the remapping from "/home/MyName/php-src/" to "/var/www/doc/" has been defined, then:
    /usr/MyName/php-src/MyAppl.html becomes
    /var/www/doc/MyAppl.html
  4. Relative references are generated. The resulting reference is compared with the path-file of the current document (this latter already converted to absolute path-file and already remapped), and the Documentator try to set a relative path-file. For example, if the document of our examples needs to reference the class "Forms" declared inside the source file "/home/MyName/php-src/libs/Forms.php" through the special tag "<@item Forms>", then:
    /var/www/doc/libs/Utils.html#Forms
    becomes
    libs/Utils.html#Forms

Support for internationalization

Well, no support is currently provided by PHPLint... By default PHPLint raises a warning message if any ID or literal string contains non-ASCII caracters (i.e. bytes in the range from \0x80-\0xFF). These warning messages can be disabled with the option --no-ascii-ext-check. IDs containing non-ASCII chars and the text inside DOC blocks are printed verbatim into the generated HTML document, while literal strings are always encoded as ASCII strings using proper escaped sequences. For example, a PHP source, UTF-8 encoded, and containing this declaration

define("aaaà", "aaaà");

get documented as follows:

aaaà = "aaa\xC3\xA0"

That is because PHPLint is unaware of which actually is the encoding of the strings (PHP 6, some day, will allow the programmer to specify which literal strings are actual text, and which binary strings, so that PHPLint will distinguish the two cases, printing the first as human-readable and properly encoded strings, and the latter as escaped sequences.)

Solutions and workarounds. If you are not interested into internationalization or your PHP sources contains only ASCII characters (but still your program can be i18n-aware and have support for encoded strings, etc.), simply left enabled the option --ascii-ext-check (it is on by default).

Instead, if your source contains non-ASCII characters, you should first check it is properly encoded (for example UTF-8) then the option --no-ascii-ext-check should be given. The generated HTML documents will have the same encoding of the source, with the only exception of the literal strings that will be always ASCII.

Generating the documentation

phplint --doc MyPackage.php

will produce the file MyPackage.html containing the declarations and the respective descriptions. The exact format of this file is currently under development. Some examples are available from the on-line version of the PHPLint program when the check-box "Generate document" is enabled. You might want to thy the examples shown in this chapter to see how the generated document would look like.

Examples

Some examples of documentation generated by the PHPLint Documentator:





Umberto Salsi

Contact
Site map
Home/Section index