[
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2007-2014, Jakob Westhoff\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice, this\n  list of conditions and the following disclaimer in the documentation and/or\n  other materials provided with the distribution.\n\n* Neither the name of the {organization} nor the names of its\n  contributors may be used to endorse or promote products derived from\n  this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "README.rst",
    "content": ".. note:: **WARNING**: This project isn't actively maintained anymore, mainly due to\n    the lack of time. I migrated it to github by request. Hopefully somebody\n    might find this useful as a base to work on again. Eventhough it should\n    still be compatible with current PHP versions. It does not support *newer*\n    features like namespace and such. Of course Pull-Requests are always\n    welcome. If somebody wants to take over maintership completely I would be\n    happy to discuss that.\n\n=====\nphUML\n=====\n\nWhat is this all about?\n=======================\n\nphUML is fully automatic UML_ class diagramm generator written PHP_. It is\ncapable of parsing any PHP5_ object oriented source code and create an\nappropriate image representation of the oo structure based on the UML_\nspecification.\n\n.. _UML: http://en.wikipedia.org/wiki/Unified_Modeling_Language\n.. _PHP: http://php.net\n.. _PHP5: http://www.php.net/downloads.php#v5\n\n\nWhat does it look like?\n=======================\n\n.. image:: https://raw.githubusercontent.com/jakobwesthoff/phuml/master/images/phuml_example_thumbnail.jpg\n   :alt: Class diagram of the phUML generator\n   :align: center\n   :target: https://raw.githubusercontent.com/jakobwesthoff/phuml/master/images/phuml_example.png\n\nThe image shown here is the class diagramm which phUML created when run on\nits own codebase. This image is hardly readable, because it has been resized\nto fit in the layout of this page. You can take a look at the complete image\nby clicking here_\n\n.. _here: https://raw.githubusercontent.com/jakobwesthoff/phuml/master/images/phuml_example.png\n\n\nCan I use this for my own projects?\n===================================\n\nphUML should be compatible with any object oriented code written in PHP5_. At\nthe moment it unfortunatly does not support any PHP4_ code. \n\n.. _PHP4:  http://php.net\n\nphUML has quite a informative help interface, which can be accessed by calling\nit with the -h option. ::\n\t\n\t$ phuml -h\n\nThe phUML generator works with so called processors, which may be used in a\nchain to create a lot of different output formats. Every available processor\ncan be listed by calling phUML with the -l option. ::\n\n\t$ phuml -l\n\nThe most important processor used to create images of any kind is the\ngraphviz processor. As its name indicates it outputs information in the so\ncalled dot language used by graphviz_. To sucessfully handle this output\nformat and create the desired images you will need the graphviz_ toolkit\ninstalled on your system. You may then call the neato or dot\nexecutables, which are part of graphviz_, to process the created file\nmanually or you may phUML do this for you by using the dot or neato\nprocessor.\n\n.. _graphviz: http://www.graphviz.org\n\nYou should just play around with the phUML commandline tool to get a better\nunderstanding of what the processors do and how they work. To give you a short\nexample of how a complete phUML call could look like, this is the one used\ngenerate the example you can see above. ::\n\n\t$ phuml -r ./ -dot -createAssociations false -neato example.png\n"
  },
  {
    "path": "src/app/phuml",
    "content": "#!/usr/bin/env php\n<?php\n\nrequire_once( dirname( __FILE__ ) . '/../config/config.php' );\n\nfunction showHeader() \n{\n    echo <<<HEADER\nphUML Version 0.2 (Jakob Westhoff <jakob@php.net>)\n\nHEADER;\n}\n\nfunction showUsage() \n{\n    echo <<<USAGE\nUsage: phuml [-h|-l] [OPTIONS] <DIRECTORY> <PROCESSOR> [PROCESSOR OPTIONS] ... <OUTFILE>\n\nCommands:\n    -h      Display this help text\n    -l      List all available processors\n\nOptions: \n    -r      Scan given directorie recursively\n\nExample:\n    phuml -r ./ -graphviz -createAssociations false -neato out.png\n\n    This example will scan the current directory recursively for php files.\n    Send them to the \"dot\" processor which will process them with the option\n    \"createAssociations\" set to false. After that it will be send to the neato\n    processor and saved to the file out.png\n\n\nUSAGE;\n}\n\nfunction showProcessorList() \n{\n    echo \"The following processors are available:\\n\\n\";\n    foreach( plProcessor::getProcessors() as $processor ) \n    {\n        echo \"* Processor: \", $processor, \"\\n\";\n        echo \"  - Options:\", \"\\n\";\n        \n        $class = 'pl' . $processor . 'Processor';\n        $p = new $class();\n        $o = $p->options;\n\n        if ( count( $o->getOptions() ) === 0 ) \n        {\n            echo \"    This processor does not have any options.\", \"\\n\\n\";\n            continue;\n        }\n        \n        foreach ( $o->getOptions() as $option ) \n        {\n            echo \"    \", $option, ' (', getOptionTypeRepresentation( $o->getOptionType( $option ) ), '):', \"\\n\";\n            \n            // Get the description as an word wrapped array to add the padding\n            $description = explode( \"\\n\", wordwrap( $o->getOptionDescription( $option ), 73, \"\\n\", true ) );\n            foreach( $description as $descriptionLine ) \n            {\n                echo \"      \", $descriptionLine, \"\\n\";\n            }\n            echo \"\\n\";\n        }\n    }\n}\n\nfunction getOptionTypeRepresentation( $type ) \n{\n    switch ( $type ) \n    {\n        case plProcessorOptions::BOOL:\n            return 'boolean';\n        break;\n        case plProcessorOptions::STRING:\n            return 'string';\n        break;\n        case plProcessorOptions::DECIMAL:\n            return 'decimal';\n        break;\n        default:\n            return 'unknown type';\n    }\n}\n\nfunction updateArguments( $count ) \n{\n    global $argc, $argv;\n\n    $argv = array_slice( $argv, $count );\n    $argc = count( $argv );\n}\n\nfunction cmdActions() \n{\n    global $argc, $argv;\n\n    if ( strtolower( $argv[0] ) === '-h' ) \n    {\n        showUsage();\n        exit( 1 );\n    }\n    else if ( strtolower( $argv[0] ) === '-l' ) \n    {\n        showProcessorList();\n        exit( 0 );\n    }\n}\n\nfunction cmdOptions() \n{\n    global $argc, $argv;    \n    global $recursive;\n\n    if ( strtolower( $argv[0] ) === '-r' ) \n    {\n        $recursive = true;\n        updateArguments( 1 );\n    }\n}\n\nfunction cmdDirOrFile() \n{\n    global $argc, $argv;\n    global $phuml, $recursive;\n\n    if ( is_dir( $argv[0] ) ) \n    {\n        $phuml->addDirectory( $argv[0], 'php', $recursive );\n        updateArguments( 1 );\n    }\n    else\n    {\n        showUsage();\n        exit( 1 );\n    }\n}\n\nfunction cmdProcessor() \n{\n    global $argc, $argv;\n    global $phuml;\n\n    if ( substr( $argv[0], 0, 1 ) !== '-' ) \n    {\n        showUsage();\n        exit( 1 );\n    }\n    \n    // We do not need to check for correct options here, because the option\n    // will throw an exception if there is something wrong\n\n    $processor = plProcessor::factory( \n        substr( $argv[0], 1 ) \n    );\n\n    updateArguments( 1 );\n\n    while( $argc > 1 && !in_array( ucfirst( $option = substr( $argv[0], 1 ) ), plProcessor::getProcessors() ) ) \n    {        \n        $processor->options->$option = $argv[1];\n        updateArguments( 2 );\n    }\n\n    $phuml->addProcessor( $processor );\n}\n\nfunction cmdOutFile() \n{\n    global $argc, $argv;\n    global $outfile;\n\n    $outfile = $argv[0];\n    updateArguments( 1 );\n}\n\nshowHeader();\n\n// The absolute minimum of parameters is 2\nif ( $argc < 2 ) \n{\n    showUsage();\n    exit( 1 );\n}\n\n$recursive = false;\n$outfile   = 'out';\n\n$phuml            = new plPhuml();\n$phuml->generator = plStructureGenerator::factory( 'tokenparser' );\n\n// Remove the application name\nupdateArguments( 1 );\n\ntry \n{\n    cmdActions();\n    cmdOptions();\n    cmdDirOrFile();\n    while( $argc > 1 ) \n    {\n        cmdProcessor();\n    }\n    cmdOutFile();\n\n    echo '[|] Running... (This may take some time)', \"\\n\";\n\n    $phuml->generate( $outfile );\n}\ncatch ( Exception $e ) \n{\n    echo 'A fatal error occured during the process:', \"\\n\";\n    echo $e->getMessage(), \"\\n\";\n}\n\n?>\n"
  },
  {
    "path": "src/autoload/base_autoload.php",
    "content": "<?php\n\nreturn array( \n    'plBasePropertyException'           =>  'exceptions/base/property.php',\n);\n\n?>\n"
  },
  {
    "path": "src/autoload/php_autoload.php",
    "content": "<?php\n\nreturn array( \n    'plPhpClass'                => 'classes/php/class.php',\n    'plPhpFunction'             => 'classes/php/function.php',\n    'plPhpInterface'            => 'classes/php/interface.php',\n    'plPhpAttribute'            => 'classes/php/attribute.php',\n    'plPhpFunctionParameter'    => 'classes/php/functionParameter.php',\n);\n\n?>\n"
  },
  {
    "path": "src/autoload/phuml_autoload.php",
    "content": "<?php\n\nreturn array( \n    'plPhuml'                                    =>  'classes/phuml.php',\n    'plPhumlInvalidProcessorException'           =>  'exceptions/phuml/invalidProcessor.php',\n    'plPhumlInvalidProcessorChainException'      =>  'exceptions/phuml/invalidProcessorChain.php',\n);\n\n?>\n"
  },
  {
    "path": "src/autoload/processor_autoload.php",
    "content": "<?php\n\nreturn array( \n\n    'plProcessor'                                   =>  'interfaces/processor.php',\n    'plProcessorOptions'                            =>  'classes/processor/options.php',\n    'plProcessorOptionException'                    =>  'exceptions/processor/option.php',\n\n    'plGraphvizProcessor'                           =>  'classes/processor/graphviz.php',\n    'plGraphvizProcessorOptions'                    =>  'classes/processor/graphviz/options.php',\n\n    'plProcessorNotFoundException'                  =>  'exceptions/processor/notFound.php',\n\n    'plGraphvizProcessorStyle'                      =>  'interfaces/processor/graphviz/style.php',\n    'plGraphvizProcessorDefaultStyle'               =>  'classes/processor/graphviz/style/default.php',\n\n    'plGraphvizProcessorStyleNotFoundException'     =>  'exceptions/processor/graphviz/style/notFound.php',\n\n    'plExternalCommandProcessor'                    =>  'interfaces/processor/externalCommand.php',\n    'plNeatoProcessor'                              =>  'classes/processor/neato.php',\n    'plDotProcessor'                                =>  'classes/processor/dot.php',\n    'plStatisticsProcessor'                         =>  'classes/processor/statistics.php',\n    'plProcessorExternalExecutionException'         =>  'exceptions/processor/externalExecution.php',\n);\n\n?>\n"
  },
  {
    "path": "src/autoload/structure_autoload.php",
    "content": "<?php\n\nreturn array( \n    'plStructureGenerator'                          =>  'interfaces/generator.php',\n    'plStructureTokenparserGenerator'               =>  'classes/generator/tokenparser.php',\n\n    'plStructureGeneratorNotFoundException'         =>  'exceptions/generator/notFound.php',\n);\n\n?>\n"
  },
  {
    "path": "src/classes/base.php",
    "content": "<?php\n\nclass plBase \n{\n    private static $autoload = array();\n    private static $autoloadDirectory = array();\n\n    public static function autoload( $classname )\n    {\n        if ( isset( self::$autoload[$classname] ) ) \n        {\n            include_once( self::$autoload[$classname] );\n        }\n    }\n\n    public static function addAutoloadDirectory( $directory ) \n    {\n        if ( !in_array( $directory, self::$autoloadDirectory ) && is_dir( $directory ) && is_readable( $directory ) )\n        {\n            self::$autoloadDirectory[] = $directory;\n            foreach( $glob = glob( $directory.\"/*.php\" ) as $file )\n            {\n                if ( is_array( $autoload = include( $file ) ) ) \n                {\n                    self::$autoload = array_merge( $autoload, self::$autoload );\n                }\n            }\n        }\n    }\n\n    public static function getAutoloadClasses() \n    {\n        return array_keys( self::$autoload );\n    }\n}\n\n?>\n"
  },
  {
    "path": "src/classes/generator/tokenparser.php",
    "content": "<?php\n\nclass plStructureTokenparserGenerator extends plStructureGenerator \n{\n    private $classes;\n    private $interfaces;\n\n    private $parserStruct;\n    private $lastToken;\n\n    public function __construct() \n    {\n        $this->initGlobalAttributes();\n        $this->initParserAttributes();\n    }\n\n    private function initGlobalAttributes() \n    {\n        $this->classes      = array();\n        $this->interfaces   = array();\n    }\n\n    private function initParserAttributes() \n    {\n        $this->parserStruct = array( \n            'class'         => null,\n            'interface'     => null,\n            'function'      => null,\n            'attributes'    => array(),\n            'functions'     => array(),\n            'typehint'      => null,\n            'params'        => array(),\n            'implements'    => array(),\n            'extends'       => null,\n            'modifier'      => 'public',            \n            'docblock'      => null,\n        );\n\n        $this->lastToken = array();\n    }\n\n    public function createStructure( array $files ) \n    {\n        $this->initGlobalAttributes();\n\n        foreach( $files as $file ) \n        {\n            $this->initParserAttributes();\n            $tokens = token_get_all( file_get_contents( $file ) );\n\n            // Loop through all tokens\n            foreach( $tokens as $token ) \n            {\n                // Split into Simple and complex token\n                if ( is_array( $token ) !== true ) \n                {\n                    switch( $token ) \n                    {\n                        case ',':\n                            $this->comma();\n                        break;\n\n                        case '(':\n                            $this->opening_bracket();\n                        break;\n\n                        case ')':\n                            $this->closing_bracket();\n                        break;\n                        \n                        case '=':\n                            $this->equal_sign();\n                        break;\n                        default:\n                            // Ignore everything else\n                            $this->lastToken = null;                        \n                    }\n                }\n                else if ( is_array( $token ) === true ) \n                {\n                    switch ( $token[0] ) \n                    {\n                        case T_WHITESPACE:\n                            $this->t_whitespace( $token );\n                        break;\n\n                        case T_FUNCTION:\n                            $this->t_function( $token );\n                        break;\n\n                        case T_VAR:\n                            $this->t_var( $token );\n                        break;\n\n                        case T_VARIABLE:\n                            $this->t_variable( $token );\n                        break;\n\n                        case T_ARRAY:\n                            $this->t_array( $token );\n                        break;\n\n                        case T_CONSTANT_ENCAPSED_STRING:\n                            $this->t_constant_encapsed_string( $token );\n                        break;\n\n                        case T_LNUMBER:\n                            $this->t_lnumber( $token );\n                        break;\n\n                        case T_DNUMBER:\n                            $this->t_dnumber( $token );\n                        break;\n\n                        case T_PAAMAYIM_NEKUDOTAYIM:\n                            $this->t_paamayim_neukudotayim( $token );\n                        break;\n\n                        case T_STRING:\n                            $this->t_string( $token );\n                        break;\n\n                        case T_INTERFACE:           \n                            $this->t_interface( $token );\n                        break;\n\n                        case T_CLASS:\n                            $this->t_class( $token );\n                        break;\n                        \n                        case T_IMPLEMENTS:\n                            $this->t_implements( $token );\n                        break;\n\n                        case T_EXTENDS:\n                            $this->t_extends( $token );\n                        break;\n\n                        case T_PUBLIC:\n                            $this->t_public( $token );\n                        break;\n\n                        case T_PROTECTED:\n                            $this->t_protected( $token );\n                        break;\n\n                        case T_PRIVATE:\n                            $this->t_private( $token );\n                        break;\n\n                        case T_DOC_COMMENT:\n                            $this->t_doc_comment( $token );\n                        break;\n\n                        default:\n                            // Ignore everything else\n                            $this->lastToken = null;                        \n                            // And reset the docblock\n                            $this->parserStruct['docblock'] = null;\n                    }\n                }\n            }\n            // One file is completely scanned here\n\n            // Store interface or class in the parser arrays\n            $this->storeClassOrInterface();\n        }\n\n        // Fix the class and interface connections\n        $this->fixObjectConnections();\n\n        // Return the class and interface structure\n        return array_merge( $this->classes, $this->interfaces );\n    }\n\n    private function comma() \n    {\n        // Reset typehints on each comma\n        $this->parserStruct['typehint'] = null;\n    }\n\n    private function opening_bracket() \n    {\n        // Ignore opening brackets\n    }\n\n    private function closing_bracket() \n    {\n        switch ( $this->lastToken ) \n        {\n            case T_FUNCTION:\n                // The function declaration has been closed\n\n                // Add the current function\n                $this->parserStruct['functions'][] = array(\n                    $this->parserStruct['function'],\n                    $this->parserStruct['modifier'],\n                    $this->parserStruct['params'],\n                    $this->parserStruct['docblock']\n                );                           \n                // Reset the last token\n                $this->lastToken = null;\n                //Reset the modifier state\n                $this->parserStruct['modifier'] = 'public';\n                // Reset the params array\n                $this->parserStruct['params'] = array();\n                $this->parserStruct['typehint'] = null;\n                // Reset the function name\n                $this->parserStruct['function'] = null;\n                // Reset the docblock\n                $this->parserStruct['docblock'] = null;\n            break;\n            default:\n                $this->lastToken = null;\n        }\n    }\n\n    private function equal_sign() \n    {\n        switch ( $this->lastToken ) \n        {\n            case T_FUNCTION:\n                // just ignore the equal sign\n            break;\n            default:\n                $this->lastToken = null;\n        }\n    }\n\n    private function t_whitespace( $token ) \n    {\n        // Ignore whitespaces\n    }\n\n    private function t_function( $token ) \n    {\n        switch( $this->lastToken ) \n        {\n            case null:\n            case T_PUBLIC:\n            case T_PROTECTED:\n            case T_PRIVATE:\n                $this->lastToken = $token[0];\n            break;\n            default:\n                $this->lastToken = null;\n        }\n    }\n\n    private function t_var( $token ) \n    {\n        switch ( $this->lastToken ) \n        {\n            case T_FUNCTION:\n                // just ignore the T_VAR\n            break;\n            default:\n                $this->lastToken = null;\n        }\n    }\n\n    private function t_variable( $token ) \n    {\n        switch( $this->lastToken ) \n        {\n            case T_PUBLIC:\n            case T_PROTECTED:\n            case T_PRIVATE:\n                // A new class attribute\n                $this->parserStruct['attributes'][] = array( \n                    $token[1],\n                    $this->parserStruct['modifier'],\n                    $this->parserStruct['docblock'],\n                );\n                $this->lastToken = null;\n                $this->parserStruct['modifier'] = 'public';\n                $this->parserStruct['docblock'] = null;\n            break;\n            case T_FUNCTION:\n                // A new function parameter\n                $this->parserStruct['params'][] = array( \n                    $this->parserStruct['typehint'], \n                    $token[1]\n                );\n            break;\n        }\n    }\n\n    private function t_array( $token ) \n    {\n        switch ( $this->lastToken ) \n        {\n            case T_FUNCTION:\n                // just ignore the T_ARRAY\n            break;\n            default:\n                $this->lastToken = null;\n        }\n    }\n\n    private function t_constant_encapsed_string( $token ) \n    {\n        switch ( $this->lastToken ) \n        {\n            case T_FUNCTION:\n                // just ignore the T_CONSTANT_ENCAPSED_STRING\n            break;\n            default:\n                $this->lastToken = null;\n        }\n    }\n\n    private function t_lnumber( $token ) \n    {\n        switch ( $this->lastToken ) \n        {\n            case T_FUNCTION:\n                // just ignore the T_LNUMBER\n            break;\n            default:\n                $this->lastToken = null;\n        }\n    }\n\n    private function t_dnumber( $token ) \n    {\n        switch ( $this->lastToken ) \n        {\n            case T_FUNCTION:\n                // just ignore the T_DNUMBER\n            break;\n            default:\n                $this->lastToken = null;\n        }\n    }\n\n    private function t_paamayim_neukudotayim( $token ) \n    {\n        switch ( $this->lastToken ) \n        {\n            case T_FUNCTION:\n                // just ignore the T_PAAMAYIM_NEKUDOTAYIM\n            break;\n            default:\n                $this->lastToken = null;\n        }\n    }\n\n    private function t_string( $token ) \n    {\n        switch( $this->lastToken ) \n        {\n            case T_IMPLEMENTS:\n                // Add interface to implements array\n                $this->parserStruct['implements'][] = $token[1];\n                // We do not reset the last token here, because \n                // there might be multiple interfaces\n            break;\n            case T_EXTENDS:\n                // Set the superclass\n                $this->parserStruct['extends'] = $token[1];\n                // Reset the last token\n                $this->lastToken = null;\n            break;                        \n            case T_FUNCTION:\n                // Add the current function only if there is no function name already\n                // Because if we know the function name already this is a type hint\n                if ( $this->parserStruct['function'] === null ) \n                {\n                    // Function name\n                    $this->parserStruct['function'] = $token[1];                           \n                }\n                else \n                {\n                    // Type hint\n                    $this->parserStruct['typehint'] = $token[1];\n                }\n            break;\n            case T_CLASS:\n                // Set the class name\n                $this->parserStruct['class'] = $token[1];\n                // Reset the last token\n                $this->lastToken = null;\n            break;\n            case T_INTERFACE:\n                // Set the interface name\n                $this->parserStruct['interface'] = $token[1];\n                // Reset the last Token\n                $this->lastToken = null;\n            break;\n            default:\n                $this->lastToken = null;\n        }\n    }\n\n    private function t_interface( $token )  \n    {\n        switch( $this->lastToken ) \n        {\n            case null:\n                // New initial interface token\n                // Store the class or interface definition if there is any in the \n                // parser arrays ( There might be more than one class/interface per\n                // file )\n                $this->storeClassOrInterface();\n\n                // Remember the last token\n                $this->lastToken = $token[0];\n            break;\n            default:\n                $this->lastToken = null;\n        }\n    }\n\n    private function t_class( $token ) \n    {\n        switch( $this->lastToken ) \n        {\n            case null:\n                // New initial interface token\n                // Store the class or interface definition if there is any in the \n                // parser arrays ( There might be more than one class/interface per\n                // file )\n                $this->storeClassOrInterface();\n\n                // Remember the last token\n                $this->lastToken = $token[0];\n            break;\n            default:\n                $this->lastToken = null;\n        }\n    }\n\n    private function t_implements( $token ) \n    {\n        switch ( $this->lastToken ) \n        {\n            case null:\n                $this->lastToken = $token[0];\n            break;\n            default:\n                $this->lastToken = null;\n        }\n    }\n\n    private function t_extends( $token ) \n    {\n        switch ( $this->lastToken ) \n        {\n            case null:\n                $this->lastToken = $token[0];\n            break;\n            default:\n                $this->lastToken = null;\n        }\n    }\n\n    private function t_public( $token ) \n    {\n        switch ( $this->lastToken ) \n        {\n            case null:\n                $this->lastToken                 = $token[0];\n                $this->parserStruct['modifier']  = $token[1];\n            break;\n            default:\n                $this->lastToken = null;\n        }\n    }\n\n    private function t_protected( $token ) \n    {\n        switch ( $this->lastToken ) \n        {\n            case null:\n                $this->lastToken                 = $token[0];\n                $this->parserStruct['modifier']  = $token[1];\n            break;\n            default:\n                $this->lastToken = null;\n        }\n    }\n\n    private function t_private( $token ) \n    {\n        switch ( $this->lastToken ) \n        {\n            case null:\n                $this->lastToken                 = $token[0];\n                $this->parserStruct['modifier']  = $token[1];\n            break;\n            default:\n                $this->lastToken = null;\n        }\n    }\n\n    private function t_doc_comment( $token ) \n    {\n        switch ( $this->lastToken ) \n        {\n            case null:\n                $this->parserStruct['docblock'] = $token[1];\n            break;\n            default:\n                $this->lastToken = null;\n                $this->parserStruct['docblock'] = null;\n        }\n    }\n\n    private function storeClassOrInterface() \n    {\n        // First we need to check if we should store interface data found so far\n        if ( $this->parserStruct['interface'] !== null ) \n        {\n            // Init data storage\n            $functions = array();\n\n            // Create the data objects\n            foreach( $this->parserStruct['functions'] as $function ) \n            {\n                // Create the needed parameter objects\n                $params = array();\n                foreach( $function[2] as $param) \n                {\n                    $params[] = new plPhpFunctionParameter( $param[1], $param[0] );\n                }\n                $functions[] = new plPhpFunction( \n                    $function[0],\n                    $function[1],\n                    $params\n                );                                    \n            }\n            $interface = new plPhpInterface( \n                $this->parserStruct['interface'],\n                $functions,\n                $this->parserStruct['extends']\n            );                              \n            \n            // Store in the global interface array\n            $this->interfaces[$this->parserStruct['interface']] = $interface;\n        }\n        // If there is no interface, we maybe need to store a class\n        else if ( $this->parserStruct['class'] !== null ) \n        {\n            // Init data storage\n            $functions  = array();\n            $attributes = array();\n\n            // Create the data objects\n            foreach( $this->parserStruct['functions'] as $function ) \n            {\n                // Create the needed parameter objects\n                $params = array();\n                foreach( $function[2] as $param) \n                {\n                    $params[] = new plPhpFunctionParameter( $param[1], $param[0] );\n                }\n                $functions[] = new plPhpFunction( \n                    $function[0],\n                    $function[1],\n                    $params\n                );                                    \n            }\n            foreach ( $this->parserStruct['attributes'] as $attribute ) \n            {\n                $type = null;\n                // If there is a docblock try to isolate the attribute type\n                if ( $attribute[2] !== null ) \n                {\n                    // Regular expression that extracts types in array annotations\n                    $regexp = '/^[\\s*]*@var\\s+array\\(\\s*(\\w+\\s*=>\\s*)?(\\w+)\\s*\\).*$/m';\n                    if ( preg_match( $regexp, $attribute[2], $matches ) )\n                    {\n                        $type = $matches[2];\n                    }\n                    else if ( $return = preg_match( '/^[\\s*]*@var\\s+(\\S+).*$/m', $attribute[2], $matches ) )\n                    {\n                        $type = trim( $matches[1] );\n                    }\n                }\n                $attributes[] = new plPhpAttribute( \n                    $attribute[0],\n                    $attribute[1],\n                    $type\n                );\n            }\n            $class = new plPhpClass( \n                $this->parserStruct['class'],\n                $attributes,\n                $functions,\n                $this->parserStruct['implements'],\n                $this->parserStruct['extends']\n            );                              \n            \n            $this->classes[$this->parserStruct['class']] = $class;\n        }\n\n        $this->initParserAttributes();\n    }\n\n    private function fixObjectConnections() \n    {\n        foreach( $this->classes as $class ) \n        {\n            $implements = array();\n            foreach( $class->implements as $key => $impl ) \n            {\n                $implements[$key] = array_key_exists( $impl, $this->interfaces ) \n                                    ? $this->interfaces[$impl]\n                                    : $this->interfaces[$impl] = new plPhpInterface( $impl );\n            }\n            $class->implements = $implements;\n\n            if ( $class->extends === null ) \n            {\n                continue;\n            }\n            $class->extends = array_key_exists( $class->extends, $this->classes ) \n                              ? $this->classes[$class->extends] \n                              : ( $this->classes[$class->extends] = new plPhpClass( $class->extends ) );\n        }\n        foreach( $this->interfaces as $interface ) \n        {           \n            if ( $interface->extends === null ) \n            {\n                continue;\n            }\n            $interface->extends = array_key_exists( $interface->extends, $this->interfaces ) \n                                 ? $this->interfaces[$interface->extends] \n                                 : ( $this->interfaces[$interface->extends] = new plPhpInterface( $interface->extends ) );\n        }\n    }\n}\n\n?>\n"
  },
  {
    "path": "src/classes/php/attribute.php",
    "content": "<?php\n\nclass plPhpAttribute\n{\n    private $properties;\n\n    public function __construct( $name, $modifier = 'public', $type = null ) \n    {\n        $this->properties = array( \n            'name'      =>  $name,\n            'modifier'  =>  $modifier,\n            'type'      =>  $type,\n        );\n    }\n\n    public function __get( $key )\n    {\n        if ( !array_key_exists( $key, $this->properties ) )\n        {\n            throw new plBasePropertyException( $key, plBasePropertyException::READ );\n        }\n        return $this->properties[$key];\n    }\n\n    public function __set( $key, $val )\n    {\n        if ( !array_key_exists( $key, $this->properties ) )\n        {\n            throw new plBasePropertyException( $key, plBasePropertyException::WRITE );\n        }\n        $this->properties[$key] = $val;            \n    }\n}\n\n?>\n"
  },
  {
    "path": "src/classes/php/class.php",
    "content": "<?php\n\nclass plPhpClass\n{\n    private $properties;\n\n    public function __construct( $name, $attributes = array(), $functions = array(), $implements = array(), $extends = null ) \n    {\n        $this->properties = array( \n            'name'          =>  $name,\n            'attributes'    =>  $attributes,\n            'functions'     =>  $functions,\n            'implements'    =>  $implements,\n            'extends'       =>  $extends,\n        );\n    }\n\n    public function __get( $key )\n    {\n        if ( !array_key_exists( $key, $this->properties ) )\n        {\n            throw new plBasePropertyException( $key, plBasePropertyException::READ );\n        }\n        return $this->properties[$key];\n    }\n\n    public function __set( $key, $val )\n    {\n        if ( !array_key_exists( $key, $this->properties ) )\n        {\n            throw new plBasePropertyException( $key, plBasePropertyException::WRITE );\n        }\n        $this->properties[$key] = $val;            \n    }\n}\n\n?>\n"
  },
  {
    "path": "src/classes/php/function.php",
    "content": "<?php\n\nclass plPhpFunction\n{\n    private $properties;\n\n    public function __construct( $name, $modifier = 'public', $params = array() ) \n    {\n        $this->properties = array( \n            'name'      =>  $name,\n            'modifier'  =>  $modifier,\n            'params'    =>  $params,\n        );\n    }\n\n    public function __get( $key )\n    {\n        if ( !array_key_exists( $key, $this->properties ) )\n        {\n            throw new plBasePropertyException( $key, plBasePropertyException::READ );\n        }\n        return $this->properties[$key];\n    }\n\n    public function __set( $key, $val )\n    {\n        if ( !array_key_exists( $key, $this->properties ) )\n        {\n            throw new plBasePropertyException( $key, plBasePropertyException::WRITE );\n        }\n        $this->properties[$key] = $val;            \n    }\n}\n\n?>\n"
  },
  {
    "path": "src/classes/php/functionParameter.php",
    "content": "<?php\n\nclass plPhpFunctionParameter\n{\n    private $properties;\n\n    public function __construct( $name, $type = null ) \n    {\n        $this->properties = array( \n            'name'      =>  $name,\n            'type'      =>  $type,\n        );\n    }\n\n    public function __get( $key )\n    {\n        if ( !array_key_exists( $key, $this->properties ) )\n        {\n            throw new plBasePropertyException( $key, plBasePropertyException::READ );\n        }\n        return $this->properties[$key];\n    }\n\n    public function __set( $key, $val )\n    {\n        if ( !array_key_exists( $key, $this->properties ) )\n        {\n            throw new plBasePropertyException( $key, plBasePropertyException::WRITE );\n        }\n        $this->properties[$key] = $val;            \n    }\n}\n\n?>\n"
  },
  {
    "path": "src/classes/php/interface.php",
    "content": "<?php\n\nclass plPhpInterface\n{\n    private $properties;\n\n    public function __construct( $name, $functions = array(), $extends = null ) \n    {\n        $this->properties = array( \n            'name'      =>  $name,\n            'functions' =>  $functions,\n            'extends'   =>  $extends,\n        );\n    }\n\n    public function __get( $key )\n    {\n        if ( !array_key_exists( $key, $this->properties ) )\n        {\n            throw new plBasePropertyException( $key, plBasePropertyException::READ );\n        }\n        return $this->properties[$key];\n    }\n\n    public function __set( $key, $val )\n    {\n        if ( !array_key_exists( $key, $this->properties ) )\n        {\n            throw new plBasePropertyException( $key, plBasePropertyException::WRITE );\n        }\n        $this->properties[$key] = $val;            \n    }\n}\n\n?>\n"
  },
  {
    "path": "src/classes/phuml.php",
    "content": "<?php\n\nclass plPhuml \n{\n    private $properties;\n    \n    private $files;\n    private $processors;\n\n    public function __construct() \n    {\n        $this->properties = array( \n            'generator'     => plStructureGenerator::factory( 'tokenparser' ),\n        );\n\n        $this->files = array();\n    }\n\n    public function addFile( $file ) \n    {\n        $this->files[] = $file;\n    }\n\n    public function addDirectory( $directory, $extension = 'php', $recursive = true ) \n    {\n        if ( $recursive === false ) \n        {\n            $iterator = new DirectoryIterator( $directory );\n        }\n        else\n        {\n            $iterator = new RecursiveIteratorIterator(\n                new RecursiveDirectoryIterator( $directory )\n            );\n        }\n\n        foreach( $iterator as $entry ) \n        {\n            if ( $entry->isDir() === true ) \n            {\n                continue;\n            }\n            \n            if ( $sub = strtolower( substr( $entry->getFilename(), -1 * strlen( $extension ) ) ) !== strtolower( $extension ) ) \n            {\n                continue;\n            }\n\n            $this->files[] = $entry->getPathname();\n        }       \n    }\n\n    public function addProcessor( $processor ) \n    {\n        if ( count( $this->processors ) === 0 ) \n        {\n            // First processor must support application/phuml-structure\n            if ( !in_array( 'application/phuml-structure', $processor->getInputTypes() ) ) \n            {\n                throw new plPhumlInvalidProcessorChainException( 'application/phuml-structure', $processor->getInputTypes() );\n            }\n        }\n        else\n        {\n            $this->checkProcessorCompatibility( end( $this->processors ), $processor );\n\n        }\n        $this->processors[] = $processor;\n    }\n\n    private function checkProcessorCompatibility( $first, $second ) \n    {\n        if ( !( $first instanceof plProcessor ) || !( $second instanceof plProcessor ) ) \n        {\n            throw new plPhumlInvalidProcessorException();\n        }\n\n        if ( !in_array( $first->getOutputType(), $second->getInputTypes() ) ) \n        {\n            throw new plPhumlInvalidProcessorChainException( $first->getOutputType(), $second->getInputTypes() );\n        }\n    }\n\n    public function generate( $outfile ) \n    {\n        echo \"[|] Parsing class structure\", \"\\n\";\n        $structure = $this->generator->createStructure( $this->files );\n        \n        $temporary = array( $structure, 'application/phuml-structure' );\n        foreach( $this->processors as $processor ) \n        {            \n            preg_match( \n                '@^pl([A-Z][a-z]*)Processor$@',\n                get_class( $processor ),\n                $matches\n            );\n\n            echo \"[|] Running '\" . $matches[1] . \"' processor\", \"\\n\";\n            $temporary = array( \n                $processor->process( $temporary[0], $temporary[1] ),\n                $processor->getOutputType(),\n            );\n        }\n\n        echo \"[|] Writing generated data to disk\", \"\\n\";\n        end( $this->processors )->writeToDisk( $temporary[0], $outfile );\n    }\n\n\n    public function __get( $key )\n    {\n        if ( !array_key_exists( $key, $this->properties ) )\n        {\n            throw new plBasePropertyException( $key, plBasePropertyException::READ );\n        }\n        return $this->properties[$key];\n    }\n\n    public function __set( $key, $val )\n    {\n        if ( !array_key_exists( $key, $this->properties ) )\n        {\n            throw new plBasePropertyException( $key, plBasePropertyException::WRITE );\n        }\n        $this->properties[$key] = $val;            \n    }\n\n}\n\n?>\n"
  },
  {
    "path": "src/classes/processor/dot.php",
    "content": "<?php\n\nclass plDotProcessor extends plExternalCommandProcessor \n{\n    public $options;\n\n    public function __construct() \n    {\n        $this->options = new plProcessorOptions();\n    }\n\n    public function getInputTypes() \n    {\n        return array( \n            'text/dot',\n        );\n    }\n\n    public function getOutputType() \n    {\n        return 'image/png';\n    }\n\n    public function execute( $infile, $outfile, $type ) \n    {\n        exec(\n            'dot -Tpng -o ' . escapeshellarg( $outfile ) . ' ' . escapeshellarg( $infile ),\n            $output,\n            $return\n        );\n\n        if ( $return !== 0 ) \n        {\n            throw new plProcessorExternalExecutionException( $output );\n        }\n    }\n}\n\n?>\n"
  },
  {
    "path": "src/classes/processor/graphviz/options.php",
    "content": "<?php\n\nclass plGraphvizProcessorOptions extends plProcessorOptions \n{    \n    public function __construct() \n    {\n        $this->properties = array( \n            'style'                 =>  array( \n                'data'          => plGraphvizProcessorStyle::factory( 'default' ),\n                'type'          => self::STRING,\n                'description'   => 'Style to use for the dot creation'\n            ),\n            'createAssociations'    =>  array( \n                'data'          => true,\n                'type'          => self::BOOL,\n                'description'   => 'Create connections between classes that include each other. (This information can only be extracted if it is present in docblock comments)'\n            ),\n        );\n    }\n\n    public function __set( $key, $val ) \n    {\n        switch( $key ) \n        {\n            case 'style':\n                $this->properties[$key]['data'] = plGraphvizProcessorStyle::factory( (string)$val );\n            break;\n            case 'createAssociations':\n                $this->properties[$key]['data'] = ( $val === '0' || $val === 'false' ) ? false : true;\n            break;\n            default:\n                throw new plProcessorOptionException( $key, plProcessorOptionException::WRITE );\n        }\n\n    }\n}\n\n?>\n"
  },
  {
    "path": "src/classes/processor/graphviz/style/default.php",
    "content": "<?php\n\nclass plGraphvizProcessorDefaultStyle extends plGraphvizProcessorStyle\n{\n}\n\n?>\n"
  },
  {
    "path": "src/classes/processor/graphviz.php",
    "content": "<?php\n\nclass plGraphvizProcessor extends plProcessor \n{\n    private $properties;\n\n    private $output;\n\n    private $structure;\n\n    public $options;\n\n    public function __construct() \n    {\n        $this->options   = new plGraphvizProcessorOptions();\n\n        $this->structure = null;\n        $this->output    = null;\n    }\n\n    public function getInputTypes() \n    {\n        return array( \n            'application/phuml-structure'\n        );\n    }\n\n    public function getOutputType() \n    {\n        return 'text/dot';\n    }\n\n    public function process( $input, $type ) \n    {\n        $this->structure = $input;\n\n        $this->output  = 'digraph \"' . sha1( mt_rand() ) . '\" {' . \"\\n\";\n        $this->output .= 'splines = true;' . \"\\n\";\n        $this->output .= 'overlap = false;' . \"\\n\";\n        $this->output .= 'mindist = 0.6;' . \"\\n\";\n\n        foreach( $this->structure as $object ) \n        {\n            if ( $object instanceof plPhpClass ) \n            {\n                $this->output .= $this->getClassDefinition( $object );\n            } \n            else if ( $object instanceof plPhpInterface ) \n            {\n                $this->output .= $this->getInterfaceDefinition( $object );\n            }\n        }\n\n        $this->output .= \"}\";\n\n        return $this->output;\n    }\n\n    private function getClassDefinition( $o ) \n    {\n        $def = '';\n\n        // First we need to create the needed data arrays\n        $name = $o->name;\n        \n        $attributes = array();\n        $associations = array();\n        foreach( $o->attributes as $attribute ) \n        {\n            $attributes[] = $this->getModifierRepresentation( $attribute->modifier ) . $attribute->name;\n\n            // Association creation is optional\n            if ( $this->options->createAssociations === false ) \n            {\n                continue;\n            }\n\n            // Create associations if the attribute type is set\n            if ( $attribute->type !== null && array_key_exists( $attribute->type, $this->structure ) && !array_key_exists( strtolower( $attribute->type ), $associations ) ) \n            {\n                $def .= $this->createNodeRelation( \n                    $this->getUniqueId( $this->structure[$attribute->type] ),\n                    $this->getUniqueId( $o ),\n                    array( \n                        'dir'       => 'back',\n                        'arrowtail' => 'none',\n                        'style'     => 'dashed',\n                    )\n                );\n                $associations[strtolower( $attribute->type )] = true;\n            }\n        }\n\n        $functions = array();\n        foreach( $o->functions as $function ) \n        {\n            $functions[] = $this->getModifierRepresentation( $function->modifier ) . $function->name . $this->getParamRepresentation( $function->params );\n\n            // Association creation is optional\n            if ( $this->options->createAssociations === false ) \n            {\n                continue;\n            }\n\n            // Create association if the function is the constructor and takes\n            // other classes as parameters\n            if ( strtolower( $function->name ) === '__construct' ) \n            {\n                foreach( $function->params as $param ) \n                {\n                    if ( $param->type !== null && array_key_exists( $param->type, $this->structure ) && !array_key_exists( strtolower( $param->type ), $associations ) ) \n                    {\n                        $def .= $this->createNodeRelation( \n                            $this->getUniqueId( $this->structure[$param->type] ),\n                            $this->getUniqueId( $o ),\n                            array( \n                                'dir'       => 'back',\n                                'arrowtail' => 'none',\n                                'style'     => 'dashed',\n                            )\n                        );\n                        $associations[strtolower( $param->type )] = true;\n                    }\n                }\n            }\n        }\n        \n        // Create the node\n        $def .= $this->createNode( \n            $this->getUniqueId( $o ),\n            array(\n                'label' => $this->createClassLabel( $name, $attributes, $functions ),\n                'shape' => 'plaintext',\n            )\n        );\n\n        // Create class inheritance relation\n        if ( $o->extends !== null ) \n        {\n            // Check if we need an \"external\" class node\n            if ( in_array( $o->extends, $this->structure ) !== true ) \n            {\n                $def .= $this->getClassDefinition( $o->extends );\n            }\n\n            $def .= $this->createNodeRelation( \n                $this->getUniqueId( $o->extends ),\n                $this->getUniqueId( $o ),\n                array( \n                    'dir'       => 'back',\n                    'arrowtail' => 'empty',\n                    'style'     => 'solid'\n                )\n            );\n        }\n\n        // Create class implements relation\n        foreach( $o->implements as $interface ) \n        {\n            // Check if we need an \"external\" interface node\n            if ( in_array( $interface, $this->structure ) !== true ) \n            {\n                $def .= $this->getInterfaceDefinition( $interface );\n            }\n\n            $def .= $this->createNodeRelation( \n                $this->getUniqueId( $interface ),\n                $this->getUniqueId( $o ),\n                array( \n                    'dir'       => 'back',\n                    'arrowtail' => 'normal',\n                    'style'     => 'dashed',\n                )\n            );\n        }\n\n        return $def;\n    }\n\n    private function getInterfaceDefinition( $o ) \n    {\n        $def = '';\n\n        // First we need to create the needed data arrays\n        $name = $o->name;\n        \n        $functions = array();\n        foreach( $o->functions as $function ) \n        {\n            $functions[] = $this->getModifierRepresentation( $function->modifier ) . $function->name . $this->getParamRepresentation( $function->params );\n        }\n        \n        // Create the node\n        $def .= $this->createNode( \n            $this->getUniqueId( $o ),\n            array(\n                'label' => $this->createInterfaceLabel( $name, array(), $functions ),\n                'shape' => 'plaintext',\n            )\n        );\n\n        // Create interface inheritance relation        \n        if ( $o->extends !== null ) \n        {\n            // Check if we need an \"external\" interface node\n            if ( in_array( $o->extends, $this->structure ) !== true ) \n            {\n                $def .= $this->getInterfaceDefinition( $o->extends );\n            }\n\n            $def .= $this->createNodeRelation( \n                $this->getUniqueId( $o->extends ),\n                $this->getUniqueId( $o ),\n                array( \n                    'dir'       => 'back',\n                    'arrowtail' => 'empty',\n                    'style'     => 'solid'\n                )\n            );\n        }\n\n        return $def;\n    }\n\n    private function getModifierRepresentation( $modifier ) \n    {\n        return ( $modifier === 'public' )\n               ? ( '+' )\n               : ( ( $modifier === 'protected' )\n                 ? ( '#' )\n                 : ( '-' ) );\n    }\n\n    private function getParamRepresentation( $params ) \n    {\n        if ( count( $params ) === 0 ) \n        {\n            return '()';\n        }\n\n        $representation = '( ';\n        for( $i = 0; $i<count( $params ); $i++ ) \n        {\n            if ( $params[$i]->type !== null ) \n            {\n                $representation .= $params[$i]->type . ' ';\n            }\n\n            $representation .= $params[$i]->name;\n            if ( $i < count( $params ) - 1 ) \n            {\n                $representation .= ', ';\n            }\n        }\n        $representation .= ' )';\n\n        return $representation;\n    }\n\n    private function getUniqueId( $object ) \n    {\n        return '\"' . spl_object_hash( $object ) . '\"';\n    }\n\n    private function createNode( $name, $options ) \n    {\n        $node = $name . \" [\";\n        foreach( $options as $key => $value ) \n        {\n            $node .= $key . '=' . $value . ' ';\n        }\n        $node .= \"]\\n\";\n        return $node;\n    }\n\n    private function createNodeRelation( $node1, $node2, $options ) \n    {\n        $relation = $node1 . ' -> ' . $node2 . ' [';\n        foreach( $options as $key => $value ) \n        {\n            $relation .= $key . '=' . $value . ' ';\n        }\n        $relation .= \"]\\n\";\n        return $relation;\n    }\n\n    private function createInterfaceLabel( $name, $attributes, $functions )     \n    {\n        // Start the table\n        $label = '<<TABLE CELLSPACING=\"0\" BORDER=\"0\" ALIGN=\"LEFT\">';\n        \n        // The title\n        $label .= '<TR><TD BORDER=\"' . $this->options->style->interfaceTableBorder . '\" ALIGN=\"CENTER\" BGCOLOR=\"' . $this->options->style->interfaceTitleBackground . '\"><FONT COLOR=\"' . $this->options->style->interfaceTitleColor . '\" FACE=\"' . $this->options->style->interfaceTitleFont . '\" POINT-SIZE=\"' . $this->options->style->interfaceTitleFontsize . '\">' . $name . '</FONT></TD></TR>';\n\n        // The attributes block\n        $label .= '<TR><TD BORDER=\"' . $this->options->style->interfaceTableBorder . '\" ALIGN=\"LEFT\" BGCOLOR=\"' . $this->options->style->interfaceAttributesBackground . '\">';\n        if ( count( $attributes ) === 0 ) \n        {\n            $label .= ' ';\n        }\n        foreach( $attributes as $attribute ) \n        {\n            $label .= '<FONT COLOR=\"' . $this->options->style->interfaceAttributesColor . '\" FACE=\"' . $this->options->style->interfaceAttributesFont . '\" POINT-SIZE=\"' . $this->options->style->interfaceAttributesFontsize . '\">' . $attribute . '</FONT><BR ALIGN=\"LEFT\"/>';\n        }\n        $label .= '</TD></TR>';\n\n        // The function block\n        $label .= '<TR><TD BORDER=\"' . $this->options->style->interfaceTableBorder . '\" ALIGN=\"LEFT\" BGCOLOR=\"' . $this->options->style->interfaceFunctionsBackground . '\">';\n        if ( count( $functions ) === 0 ) \n        {\n            $label .= ' ';\n        }\n        foreach( $functions as $function ) \n        {\n            $label .= '<FONT COLOR=\"' . $this->options->style->interfaceFunctionsColor . '\" FACE=\"' . $this->options->style->interfaceFunctionsFont . '\" POINT-SIZE=\"' . $this->options->style->interfaceFunctionsFontsize . '\">' . $function . '</FONT><BR ALIGN=\"LEFT\"/>';\n        }\n        $label .= '</TD></TR>';\n\n        // End the table\n        $label .= '</TABLE>>';\n\n        return $label;\n    }\n\n    private function createClassLabel( $name, $attributes, $functions )     \n    {\n        // Start the table\n        $label = '<<TABLE CELLSPACING=\"0\" BORDER=\"0\" ALIGN=\"LEFT\">';\n        \n        // The title\n        $label .= '<TR><TD BORDER=\"' . $this->options->style->classTableBorder . '\" ALIGN=\"CENTER\" BGCOLOR=\"' . $this->options->style->classTitleBackground . '\"><FONT COLOR=\"' . $this->options->style->classTitleColor . '\" FACE=\"' . $this->options->style->classTitleFont . '\" POINT-SIZE=\"' . $this->options->style->classTitleFontsize . '\">' . $name . '</FONT></TD></TR>';\n\n        // The attributes block\n        $label .= '<TR><TD BORDER=\"' . $this->options->style->classTableBorder . '\" ALIGN=\"LEFT\" BGCOLOR=\"' . $this->options->style->classAttributesBackground . '\">';\n        if ( count( $attributes ) === 0 ) \n        {\n            $label .= ' ';\n        }\n        foreach( $attributes as $attribute ) \n        {\n            $label .= '<FONT COLOR=\"' . $this->options->style->classAttributesColor . '\" FACE=\"' . $this->options->style->classAttributesFont . '\" POINT-SIZE=\"' . $this->options->style->classAttributesFontsize . '\">' . $attribute . '</FONT><BR ALIGN=\"LEFT\"/>';\n        }\n        $label .= '</TD></TR>';\n\n        // The function block\n        $label .= '<TR><TD BORDER=\"' . $this->options->style->classTableBorder . '\" ALIGN=\"LEFT\" BGCOLOR=\"' . $this->options->style->classFunctionsBackground . '\">';\n        if ( count( $functions ) === 0 ) \n        {\n            $label .= ' ';\n        }\n        foreach( $functions as $function ) \n        {\n            $label .= '<FONT COLOR=\"' . $this->options->style->classFunctionsColor . '\" FACE=\"' . $this->options->style->classFunctionsFont . '\" POINT-SIZE=\"' . $this->options->style->classFunctionsFontsize . '\">' . $function . '</FONT><BR ALIGN=\"LEFT\"/>';\n        }\n        $label .= '</TD></TR>';\n\n        // End the table\n        $label .= '</TABLE>>';\n\n        return $label;\n    }\n}\n\n?>\n"
  },
  {
    "path": "src/classes/processor/neato.php",
    "content": "<?php\n\nclass plNeatoProcessor extends plExternalCommandProcessor \n{\n    public $options;\n\n    public function __construct() \n    {\n        $this->options = new plProcessorOptions();\n    }\n\n    public function getInputTypes() \n    {\n        return array( \n            'text/dot',\n        );\n    }\n\n    public function getOutputType() \n    {\n        return 'image/png';\n    }\n\n    public function execute( $infile, $outfile, $type ) \n    {\n        exec(\n            'neato -Tpng -o ' . escapeshellarg( $outfile ) . ' ' . escapeshellarg( $infile ),\n            $output,\n            $return\n        );\n\n        if ( $return !== 0 ) \n        {\n            throw new plProcessorExternalExecutionException( $output );\n        }\n    }\n}\n\n?>\n"
  },
  {
    "path": "src/classes/processor/options.php",
    "content": "<?php\n\nclass plProcessorOptions \n{\n    const BOOL    = 1;\n    const STRING  = 2;\n    const DECIMAL = 3;\n\n    protected $properties = array();    \n\n    public function __get( $key )\n    {\n        if ( !array_key_exists( $key, $this->properties ) )\n        {\n            throw new plProcessorOptionException( $key, plProcessorOptionException::READ );\n        }\n        return $this->properties[$key]['data'];\n    }\n\n    public function __set( $key, $val )\n    {\n        if ( !array_key_exists( $key, $this->properties ) )\n        {\n            throw new plProcessorOptionException( $key, plProcessorOptionException::WRITE );\n        }\n        $this->properties[$key]['data'] = $val;            \n    }\n\n    public function getOptions() \n    {\n        $options = array();\n        foreach( $this->properties as $key => $property ) \n        {\n            $options[] = $key;\n        }\n        return $options;\n    }\n\n    public function getOptionDescription( $option ) \n    {\n        if ( !array_key_exists( $option, $this->properties ) ) \n        {\n            throw new plProcessorOptionException( $option, plProcessorOptionException::UNKNOWN );\n        }\n        return $this->properties[$option]['description'];\n    }\n\n    public function getOptionType( $option ) \n    {\n        if ( !array_key_exists( $option, $this->properties ) ) \n        {\n            throw new plProcessorOptionException( $option, plProcessorOptionException::UNKNOWN );\n        }\n        return $this->properties[$option]['type'];\n    }\n}\n\n?>\n"
  },
  {
    "path": "src/classes/processor/statistics.php",
    "content": "<?php\n\nclass plStatisticsProcessor extends plProcessor\n{\n    private $information;\n    public $options;\n\n    public function __construct() \n    {\n        $this->options   = new plProcessorOptions();\n        $this->information = array();\n    }\n\n    public function getInputTypes() \n    {\n        return array( \n            'application/phuml-structure'\n        );\n    }\n\n    public function getOutputType() \n    {\n        return 'text/plain';\n    }\n\n    public function process( $input, $type ) \n    {\n        // Initialize the values        \n        $this->information['interfaceCount']           = 0;\n        $this->information['classCount']               = 0;\n        $this->information['publicFunctionCount']      = 0;\n        $this->information['publicAttributeCount']     = 0;\n        $this->information['publicTypedAttributes']    = 0;\n        $this->information['protectedFunctionCount']   = 0;\n        $this->information['protectedAttributeCount']  = 0;\n        $this->information['protectedTypedAttributes'] = 0;\n        $this->information['privateFunctionCount']     = 0;\n        $this->information['privateAttributeCount']    = 0;\n        $this->information['privateTypedAttributes']   = 0;\n\n        // Loop through the classes and interfaces\n        foreach ( $input as $definition ) \n        {\n            if ( $definition instanceof plPhpInterface ) \n            {\n                $this->information['interfaceCount']++;\n            }\n\n            if ( $definition instanceof plPhpClass ) \n            {\n                $this->information['classCount']++;\n\n                foreach( $definition->attributes as $attribute ) \n                {\n                    switch ( $attribute->modifier ) \n                    {\n                        case 'public':\n                            $this->information['publicAttributeCount']++;\n                            if ( $attribute->type !== null ) \n                            {\n                                $this->information['publicTypedAttributes']++;\n                            }\n                        break;\n                        case 'protected':\n                            $this->information['protectedAttributeCount']++;\n                            if ( $attribute->type !== null ) \n                            {\n                                $this->information['protectedTypedAttributes']++;\n                            }\n                        break;\n                        case 'private':\n                            $this->information['privateAttributeCount']++;\n                            if ( $attribute->type !== null ) \n                            {\n                                $this->information['privateTypedAttributes']++;\n                            }\n                        break;                    \n                    }\n                }\n            }\n\n            foreach( $definition->functions as $function ) \n            {\n                switch ( $function->modifier ) \n                {\n                    case 'public':\n                        $this->information['publicFunctionCount']++;\n                    break;\n                    case 'protected':\n                        $this->information['protectedFunctionCount']++;\n                    break;\n                    case 'private':\n                        $this->information['privateFunctionCount']++;\n                    break;                    \n                }\n            }\n        }\n\n        $this->information['functionCount']       = $this->information['publicFunctionCount'] + $this->information['protectedFunctionCount'] + $this->information['privateFunctionCount'];\n        $this->information['attributeCount']      = $this->information['publicAttributeCount'] + $this->information['protectedAttributeCount'] + $this->information['privateAttributeCount'];\n        $this->information['typedAttributeCount'] = $this->information['publicTypedAttributes'] + $this->information['protectedTypedAttributes'] + $this->information['privateTypedAttributes'];\n        $this->information['attributesPerClass']  = round( $this->information['attributeCount'] / $this->information['classCount'], 2 );\n        $this->information['functionsPerClass']   = round( $this->information['functionCount'] / $this->information['classCount'], 2 );\n        \n        // Generate the needed text output\n        return <<<END\nPhuml generated statistics\n==========================\n\nGeneral statistics\n------------------\n\nClasses:    {$this->information['classCount']}\nInterfaces: {$this->information['interfaceCount']}\n\nAttributes: {$this->information['attributeCount']} ({$this->information['typedAttributeCount']} are typed)\n    * private:   {$this->information['privateAttributeCount']}\n    * protected: {$this->information['protectedAttributeCount']}\n    * public:    {$this->information['publicAttributeCount']}\n\nFunctions:  {$this->information['functionCount']} \n    * private:   {$this->information['privateFunctionCount']}\n    * protected: {$this->information['protectedFunctionCount']}\n    * public:    {$this->information['publicFunctionCount']}\n\nAverage statistics\n------------------\n\nAttributes per class: {$this->information['attributesPerClass']}\nFunctions per class:  {$this->information['functionsPerClass']}\n\nEND;\n    }\n}\n\n?>\n"
  },
  {
    "path": "src/config/config.php",
    "content": "<?php\n\ndefine( \"BASEDIR\", dirname( __FILE__ ) . '/..' );\n\nini_set(\n    'include_path',\n    ini_get( \"include_path\" ) . PATH_SEPARATOR . BASEDIR\n);\n\nrequire_once( 'classes/base.php' );\n\nplBase::addAutoloadDirectory( dirname( __FILE__ ). '/../autoload' );\n\nfunction __autoload( $classname )\n{\n    plBase::autoload( $classname );\n}\n\n?>\n"
  },
  {
    "path": "src/exceptions/base/property.php",
    "content": "<?php\n\nclass plBasePropertyException extends Exception \n{\n    const READ = 1;\n    const WRITE = 2;\n    \n    public function __construct( $key, $type ) \n    {\n        parent::__construct( 'Invalid property access. The property \"' . $key . '\" is not '. ( $type === self::READ ? 'readable' : 'writable' ) . '.'  );\n    }\n}\n\n?>\n"
  },
  {
    "path": "src/exceptions/generator/notFound.php",
    "content": "<?php\n\nclass plStructureGeneratorNotFoundException extends Exception\n{\n    public function __construct( $generator ) \n    {\n        parent::__construct( 'The needed generator class \"' . $generator . '\" could not be found.' );\n    }\n}\n\n?>\n"
  },
  {
    "path": "src/exceptions/phuml/invalidProcessor.php",
    "content": "<?php\n\nclass plPhumlInvalidProcessorException extends Exception \n{\n    public function __construct() \n    {\n        parent::__construct( 'The supplied processor is invalid.' );\n    }\n}\n\n?>\n"
  },
  {
    "path": "src/exceptions/phuml/invalidProcessorChain.php",
    "content": "<?php\n\nclass plPhumlInvalidProcessorChainException extends Exception \n{\n    public function __construct( $first, $second ) \n    {\n        parent::__construct( \n            'To processors in the chain are incompatible. The first processor\\'s output is \"' \n          . $first \n          . '\". The next Processor in the queue does only support the following input types: ' \n          . implode( ', ', $second ) \n          . '.' \n       );\n    }\n}\n\n?>\n"
  },
  {
    "path": "src/exceptions/processor/externalExecution.php",
    "content": "<?php\n\nclass plProcessorExternalExecutionException extends Exception \n{\n    public function __construct( $output ) \n    {\n    \t// Convert array to string if is_array\n    \tif(is_array($output)) {\n    \t\t$output = var_export($output, true);\n    \t}\n        parent::__construct( 'Execution of external program failed:' . \"\\n\" . $output );\n    }\n}\n\n?>\n"
  },
  {
    "path": "src/exceptions/processor/graphviz/style/notFound.php",
    "content": "<?php\n\nclass plGraphvizProcessorStyleNotFoundException extends Exception\n{\n    public function __construct( $style ) \n    {\n        parent::__construct( 'The needed dot style \"' . $style . '\" could not be found.' );\n    }\n}\n\n?>\n"
  },
  {
    "path": "src/exceptions/processor/notFound.php",
    "content": "<?php\n\nclass plProcessorNotFoundException extends Exception\n{\n    public function __construct( $processor ) \n    {\n        parent::__construct( 'The needed processor class \"' . $processor . '\" could not be found.' );\n    }\n}\n\n?>\n"
  },
  {
    "path": "src/exceptions/processor/option.php",
    "content": "<?php\n\nclass plProcessorOptionException extends Exception \n{\n    const READ = 1;\n    const WRITE = 2;\n    const UNKNOWN = 3;\n    \n    public function __construct( $key, $type ) \n    {\n        parent::__construct( \n            'The option \"' \n            . $key \n            . '\" is not '\n            . ( $type === self::READ ) \n              ? ( 'readable' )\n              : ( ( $type === self::UNKNOWN )\n                ? ( 'existent' )\n                : ( 'writable')\n              ) \n            . ' in this context.'\n        );\n    }\n}\n\n?>\n"
  },
  {
    "path": "src/interfaces/generator.php",
    "content": "<?php\n\nabstract class plStructureGenerator \n{\n    public static function factory( $generator ) \n    {\n        $classname = 'plStructure' . ucfirst( $generator ) . 'Generator';\n        if ( class_exists( $classname ) === false ) \n        {\n            throw new plStructureGeneratorNotFoundException( $generator );\n        }\n        return new $classname();\n    }\n\n    public abstract function createStructure( array $files );    \n}\n\n?>\n"
  },
  {
    "path": "src/interfaces/processor/externalCommand.php",
    "content": "<?php\n\nabstract class plExternalCommandProcessor extends plProcessor \n{\n\n    abstract public function execute( $infile, $outfile, $type );\n\n    public function process( $input, $type ) \n    {\n        // Create temporary datafiles\n        $infile  = tempnam( '/tmp', 'phuml' );\n        $outfile = tempnam( '/tmp', 'phuml' );\n        \n        file_put_contents( $infile, $input );\n\n        unlink( $outfile );\n\n        $this->execute( $infile, $outfile, $type );\n        \n        $outdata = file_get_contents( $outfile );\n\n        unlink( $infile );\n        unlink( $outfile );\n\n        return $outdata;\n    }\n}\n\n?>\n"
  },
  {
    "path": "src/interfaces/processor/graphviz/style.php",
    "content": "<?php\n\nabstract class plGraphvizProcessorStyle \n{\n    public static function factory( $style ) \n    {\n        $classname = 'plGraphvizProcessor' . ucfirst( $style ) . 'Style';\n        if ( class_exists( $classname ) === false ) \n        {\n            throw new plGraphvizProcessorStyleNotFoundException( $style );\n        }\n        return new $classname();\n    }\n\n    public $interfaceTableBorder            = 1;\n    public $interfaceTitleBackground        = '#729fcf';\n    public $interfaceAttributesBackground   = '#eeeeec';\n    public $interfaceFunctionsBackground    = '#eeeeec';\n    public $interfaceTitleColor             = '#2e3436';\n    public $interfaceAttributesColor        = '#2e3436';\n    public $interfaceFunctionsColor         = '#2e3436';\n    public $interfaceTitleFont              = 'Helvetica';\n    public $interfaceAttributesFont         = 'Helvetica';\n    public $interfaceFunctionsFont          = 'Helvetica';\n    public $interfaceTitleFontsize          = 12;\n    public $interfaceAttributesFontsize     = 10;\n    public $interfaceFunctionsFontsize      = 10;\n\n    public $classTableBorder                = 1;\n    public $classTitleBackground            = '#fcaf3e';\n    public $classAttributesBackground       = '#eeeeec';\n    public $classFunctionsBackground        = '#eeeeec';\n    public $classTitleColor                 = '#2e3436';\n    public $classAttributesColor            = '#2e3436';\n    public $classFunctionsColor             = '#2e3436';\n    public $classTitleFont                  = 'Helvetica';\n    public $classAttributesFont             = 'Helvetica';\n    public $classFunctionsFont              = 'Helvetica';\n    public $classTitleFontsize              = 12;\n    public $classAttributesFontsize         = 10;\n    public $classFunctionsFontsize          = 10;\n}\n"
  },
  {
    "path": "src/interfaces/processor.php",
    "content": "<?php\n\nabstract class plProcessor \n{\n    public static function factory( $processor ) \n    {\n        $classname = 'pl' . ucfirst( $processor ) . 'Processor';\n        if ( class_exists( $classname ) === false ) \n        {\n            throw new plProcessorNotFoundException( $processor );\n        }\n        return new $classname();\n    }\n\n    public static function getProcessors() \n    {\n        $processors = array();\n        foreach( plBase::getAutoloadClasses() as $autoload ) \n        {\n            if ( preg_match( '@^pl([A-Z][a-z]*)Processor$@', $autoload, $matches ) ) \n            {\n                $processors[] = $matches[1];\n            }\n        }\n        return $processors;\n    }\n\n    public function writeToDisk( $input, $output ) \n    {\n        file_put_contents( $output, $input );\n    }\n    \n    abstract public function getInputTypes();\n    abstract public function getOutputType();\n    abstract public function process( $input, $type );\n\n}\n\n?>\n"
  },
  {
    "path": "src/scripts/checkAll.sh",
    "content": "#!/bin/sh\n\nfind ./ -iname \"*.php\" -exec php -l {} \\;\n"
  }
]