3 // +----------------------------------------------------------------------+
5 // +----------------------------------------------------------------------+
6 // | Copyright (c) 1997-2002 The PHP Group |
7 // +----------------------------------------------------------------------+
8 // | This source file is subject to version 2.02 of the PHP license, |
9 // | that is bundled with this package in the file LICENSE, and is |
10 // | available at through the world-wide-web at |
11 // | http://www.php.net/license/2_02.txt. |
12 // | If you did not receive a copy of the PHP license and are unable to |
13 // | obtain it through the world-wide-web, please send a note to |
14 // | license@php.net so we can mail you a copy immediately. |
15 // +----------------------------------------------------------------------+
16 // | Authors: Alan Knowles <alan@akbkhome.com> |
17 // +----------------------------------------------------------------------+
20 * Docbook data container (for pages and sections)
22 * @package PHP_CodeDoc
24 * @author Alan Knowles <alan@akbkhome.com>
28 ini_set("memory_limit","128M");
30 error_reporting(E_ALL);
32 require_once("PEAR.php");
33 require_once("HTML/Template/Flexy.php");
34 require_once("PHP/CodeDoc/Parser.php");
36 require_once("PHP/CodeDoc/Error.php");
40 * @Docbook_package_section packages.php.codedoc
41 * @Docbook_title PHP Code Documenter
44 * This chapter expains how to use the phpcodedoc tool which can generate lxr type html and docbook
45 * output from comments embedded in class files
47 * @Docbook_page Introduction
48 * @Docbook_page_summary what is PHP_CodeDoc all about?
50 * @Docbook_section Introduction
52 * PHP_CodeDoc was written for a number of reasons
54 * - To make use of the php tokenizer module to generate documentation
55 * - To produce documentation that showed the source code as well as the notes
56 * - Because I saw the ruby class documentation, and thought it looked very clear..
59 * PHP_CodeDoc was not written (unlike most other similar applications) to emulate javadoc,
60 * my main logic here was that javadoc is focused on documenting closed source applicaitons
61 * where as most of the stuff I need to document is open source - so including the source
62 * in the output was essential to understanding what the class really did.
64 * @Docbook_page Configuring PHP_CodeDoc
65 * @Docbook_page_summary Setting up PHP_CodeDoc
67 * @Docbook_section Main configuration options
73 * The Main PHP_CodeDoc class - only really public class...
75 * @version $Id: CodeDoc.php,v 1.15 2002/12/22 13:51:23 alan Exp $
84 * Start the Parsing and Generation Process
86 * based on information contained in the PEAR::getStaticProperty('PHP_CodeDoc','options')
87 * parse all the directories and generate all the requested documentation
92 function __construct()
95 self::$options = PEAR::getStaticProperty('PHP_CodeDoc','options');
97 self::$parser = new PHP_CodeDoc_Parser();
98 self::$parser->start();
100 $this->_prepareOutput();
107 PHP_CodeDoc::_outputFromTemplate("navigation.template.html", '/nav.html');
108 PHP_CodeDoc::_outputFromTemplate("index.template.html",'/index.html');
109 PHP_CodeDoc::_outputFunctions();
110 PHP_CodeDoc::_outputDefines();
111 PHP_CodeDoc::_outputClasses();
112 PHP_CodeDoc::_outputDocbook();
119 // -------------------------------Outputting Methods ---------------
122 * Output parser's data using a template
124 * Takes the parser object and overlays that on the template,
125 * outputing to a file
128 * @param string Template filename
129 * @param string Output filename
136 function _outputFromTemplate($template="test.html",$output_file_name) {
138 $toptions = PEAR::getStaticProperty('HTML_Template_Flexy','options');
139 $poptions = PEAR::getStaticProperty('PHP_CodeDoc','options');
140 if (!@$toptions['templateDir']) {
141 $toptions['templateDir'] = dirname(__FILE__)."/CodeDoc/templates";
143 echo "Building $template: $output_file_name\n";
144 $template_engine = new HTML_Template_Flexy($toptions);
147 $template_engine->compile($template);
148 $data = $template_engine->bufferedOutputObject(self::$parser);
149 $dir = dirname($poptions['destDir'].$output_file_name);
150 if (!@file_exists($dir)) {
151 `mkdir -p $dir`; // not very portable
154 $fh = fopen($poptions['destDir'].$output_file_name,"w");
159 * Output individual classes a single files using template and directory
164 function _outputClasses() {
168 foreach(array_keys(self::$parser->classes) as $i) {
169 self::$parser->active_class = &self::$parser->classes[$i];
170 if (@!self::$parser->active_class->name) continue;
171 echo "Outputing {self::$parser->active_class->name}\n";
172 PHP_CodeDoc::_outputFromTemplate( "class.template.html", "/{self::$parser->active_class->name}.html" );
175 /* Output Defines from class directories
180 function _outputDefines() {
184 foreach(array_keys(self::$parser->packages) as $packagename) {
185 if (!self::$parser->packages[$packagename]->directories) continue;
186 self::$parser->active_package = &self::$parser->packages[$packagename];
187 foreach(array_keys(self::$parser->packages[$packagename]->directories) as $dir) {
188 if (!self::$parser->packages[$packagename]->directories[$dir]->defines) continue;
189 self::$parser->defines = & self::$parser->packages[$packagename]->directories[$dir]->defines;
190 echo "Outputing Defines for {$packagename}:{$dir}\n";
191 self::$parser->output_active_directory = self::$parser->packages[$packagename]->directories[$dir];
192 PHP_CodeDoc::_outputFromTemplate("defines.template.html", "/".urlencode($dir). "-defines.html");
197 * Output Functions in a package
202 function _outputFunctions() {
206 foreach(array_keys(self::$parser->packages) as $packagename) {
207 if (!self::$parser->packages[$packagename]->directories) continue;
208 self::$parser->active_package = &self::$parser->packages[$packagename];
209 foreach(array_keys(self::$parser->packages[$packagename]->directories) as $dir) {
210 if (!self::$parser->packages[$packagename]->directories[$dir]->functions) continue;
211 self::$parser->functions = & self::$parser->packages[$packagename]->directories[$dir]->functions;
212 echo "Outputing Defines for {$packagename}:{$dir}\n";
213 self::$parser->output_active_directory = self::$parser->packages[$packagename]->directories[$dir];
214 PHP_CodeDoc::_outputFromTemplate("functions.template.html","/".urlencode($dir). "-functions.html");
224 function _outputDocbook() {
226 if (!@self::$options['makeDocbook']) {
231 foreach(array_keys(self::$parser->packages) as $i) {
232 self::$parser->active_package = &self::$parser->packages[$i];
233 //print_r(self::$parser->active_package->docbook);
234 if (@!self::$parser->active_package->docbook) {
235 unset(self::$parser->packages[$i]);
238 if (!method_exists(self::$parser->active_package->docbook, 'mergeMethods')) {
239 unset(self::$parser->packages[$i]);
242 if (self::$parser->active_package->name == "No Package") {
243 unset(self::$parser->packages[$i]);
246 self::$parser->active_package->docbook->mergeMethods();
247 if (!@self::$parser->active_package->docbookBase) {
248 self::$parser->active_package->docbookBase = "packages." . str_replace('_','.',self::$parser->active_package->name);
250 echo "Outputing {self::$parser->active_package->name}\n";
251 $filename = str_replace('_', '/', self::$parser->active_package->name);
252 PHP_CodeDoc::_outputFromTemplate( "docbook.template.xml", "/docbook/en/packages/$filename.xml");
254 PHP_CodeDoc::_outputFromTemplate( "manual.template.xml.in", "/docbook/manual.xml.in");
258 * Prepare Output for display
259 * - eg. sort some of the classes and functions by name
268 function _prepareOutput() {
270 PHP_CodeDoc::_buildExtends();
273 echo "\n starting sorting \n";
275 uksort(self::$parser->classes_by_name, "strnatcasecmp");
278 foreach(array_keys(self::$parser->classes) as $k) {
279 self::$parser->classes[$k]->highlight = $highlight;
280 //if (@$this->classes[$k]->Operations)
281 // uksort($this->classes[$k]->Operations, "strnatcasecmp");
282 if (@self::$parser->classes[$k]->Attributes)
283 uksort(self::$parser->classes[$k]->Attributes, "strnatcasecmp");
285 $highlight = !$highlight;
287 // set highlihgts by name
289 foreach(array_keys(self::$parser->classes_by_name) as $k) {
290 $id = self::$parser->classes_by_name[$k]->id;
291 self::$parser->classes[$id]->highlight_by_name = $highlight;
292 $highlight = !$highlight;
297 uksort(self::$parser->packages, "strnatcasecmp"); // sorts package names
298 foreach(array_keys(self::$parser->packages) as $packagename) {
299 $package = & self::$parser->packages[$packagename];
300 if (!$package->directories) {
303 uksort($package->directories, "strnatcasecmp"); // sorts dirs
304 foreach(array_keys($package->directories) as $directoryname) {
305 $directory = &$package->directories[$directoryname];
306 if (@$directory->classes)
307 uksort($directory->classes, "strnatcasecmp"); // sorts classes
311 //print_r($this->classes);
316 * build the extends arrays for classes
322 function _buildExtends() {
324 echo "BUIDLING EXTENDS";
325 foreach(array_keys(self::$parser->classes) as $k) {
326 echo self::$parser->classes[$k]->name ."\n";
327 /*if (self::$parser->classes[$k]->name == 'PDO_DataObject') {
328 print_r(self::$parser->classes[$k]);
332 PHP_CodeDoc::_mergeExtends($k,self::$parser->classes[$k]->Parent);
333 if (self::$parser->classes[$k]->extends)
334 self::$parser->classes[$k]->extends = array_reverse(self::$parser->classes[$k]->extends);
340 * Merge the Operations/Attributes for classes
346 function _mergeExtends($original_id,$Parent) {
349 if (!$Parent) return;
350 $id = @self::$parser->classes_by_name[$Parent]->id;
352 self::$parser->classes[$original_id]->extends[] = $Parent;
354 foreach(self::$parser->classes[$id]->Operations as $k=>$v) {
355 if (@self::$parser->classes[$original_id]->Operations[$k]) {
356 self::$parser->classes[$original_id]->Operations[$k]->override =1;
357 continue; // ignore overrides
359 if (@self::$parser->classes[$original_id]->iOperations[$k])
362 self::$parser->classes[$original_id]->iOperations[$k] =
363 &self::$parser->classes[$id]->Operations[$k];
368 foreach(self::$parser->classes[$id]->Attributes as $k=>$v) {
369 if (@self::$parser->classes[$original_id]->Attributes[$k]) {
370 self::$parser->classes[$original_id]->Attributes[$k]->override =1;
373 if (@self::$parser->classes[$original_id]->iAttributes[$k])
376 self::$parser->classes[$original_id]->iAttributes[$k] =
377 &self::$parser->classes[$id]->Attributes[$k];
381 PHP_CodeDoc::_mergeExtends($original_id,self::$parser->classes[$id]->Parent);
387 if (!isset(self::$options['targetJS'])) {
391 foreach(self::$parser->classes as $k=>$cls) {
392 var_dump($cls->name);
397 foreach($ar[$cls->name] as $cat=>$catdata) {
398 $cats[$cat] = isset($cats[$cat]) ? array_merge($cats[$cat], $catdata) : $catdata;
400 unset($ar[$cls->name]);
402 //print_R($cls); exit;
403 foreach($ar as $fn => $data) {
408 $file = self::$options['targetJS'].'/'.$fn.'.bjs';
409 if (!file_exists(dirname($file))) {
410 mkdir(dirname($file),0755,true);
415 file_put_contents($file, json_encode($data,JSON_PRETTY_PRINT));
420 $file = self::$options['targetJS'].'/categories.json';
421 file_put_contents($file, json_encode($cats ,JSON_PRETTY_PRINT));