CodeDoc/Data/Method.php
[PHP_CodeDoc] / CodeDoc.php
1 <?php
2
3 // +----------------------------------------------------------------------+
4 // | PHP Version 4                                                        |
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 // +----------------------------------------------------------------------+
18 //
19 /**
20 *   Docbook data container (for pages and sections)
21 *
22 *   @package  PHP_CodeDoc
23 *   @access   public
24 *   @author   Alan Knowles <alan@akbkhome.com>
25 *
26 */ 
27
28 ini_set("memory_limit","128M");
29 set_time_limit(0);
30 error_reporting(E_ALL);
31
32 require_once("PEAR.php");
33 require_once("HTML/Template/Flexy.php");
34 require_once("PHP/CodeDoc/Parser.php");
35
36 require_once("PHP/CodeDoc/Error.php");
37
38 /*
39 * @Docbook
40 * @Docbook_package_section  packages.php.codedoc
41 * @Docbook_title            PHP Code Documenter
42 * @Docbook_page             INDEX 
43 *
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
46 *
47 * @Docbook_page           Introduction
48 * @Docbook_page_summary   what is PHP_CodeDoc all about? 
49 *
50 * @Docbook_section        Introduction
51 *
52 * PHP_CodeDoc was written for a number of reasons
53 * @Docbook_list    
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..
57
58 *
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.
63 *\r\r
64 * @Docbook_page           Configuring PHP_CodeDoc
65 * @Docbook_page_summary   Setting up PHP_CodeDoc
66 *
67 * @Docbook_section        Main configuration options
68
69 *
70 */
71
72 /**
73 * The Main PHP_CodeDoc class - only really public class...
74 *
75 * @version    $Id: CodeDoc.php,v 1.15 2002/12/22 13:51:23 alan Exp $
76 */
77
78 class PHP_CodeDoc {
79
80     static $parser;
81     static $options;
82
83     /**
84     * Start the Parsing and Generation Process
85     *
86     * based on information contained in the PEAR::getStaticProperty('PHP_CodeDoc','options')
87     * parse all the directories and generate all the requested documentation
88     * 
89     * 
90     * @return   none
91     */
92     function __construct()
93     {
94         
95         self::$options = PEAR::getStaticProperty('PHP_CodeDoc','options');
96             
97         self::$parser = new PHP_CodeDoc_Parser();
98         self::$parser->start(); 
99         
100         $this->_prepareOutput();
101         $this->outputJs();
102         
103         
104         
105         die("done");
106                 
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();
113         
114         
115     }
116
117    
118  
119     // -------------------------------Outputting Methods ---------------
120
121     /**
122     * Output parser's data using a template 
123     *
124     * Takes the parser object and overlays that on the template,
125     * outputing to a file
126     * 
127     * 
128     * @param   string    Template filename
129     * @param   string    Output filename
130     * 
131     *
132     * @return   none
133     * @access   private
134     */
135   
136     function _outputFromTemplate($template="test.html",$output_file_name) {
137         
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";
142         }
143         echo "Building $template: $output_file_name\n";
144         $template_engine = new HTML_Template_Flexy($toptions);
145         
146             
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
152         }
153         
154         $fh = fopen($poptions['destDir'].$output_file_name,"w");
155         fputs($fh,$data);
156         fclose($fh);              
157     }
158     /**
159     * Output individual classes a single files using template and directory
160     *
161     * @return   none
162     * @access   private
163     */
164     function _outputClasses() {
165         
166         
167         
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" );
173         }
174     }
175     /* Output Defines from class directories 
176     *
177     * @return   none
178     * @access   private
179     */
180     function _outputDefines() {
181     
182          
183         
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");
193             }
194         }
195     }
196     /* 
197     * Output Functions in a package
198     *
199     * @return   none
200     * @access   private
201     */
202     function _outputFunctions() {
203         
204         
205         
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");
215             }
216         }
217     }
218     /*
219     * Output Docbook
220     *
221     * @return   none
222     * @access   private
223     */
224     function _outputDocbook() {
225         
226         if (!@self::$options['makeDocbook']) {
227             return;   
228         }
229         
230         
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]);
236                 continue;
237             }
238             if (!method_exists(self::$parser->active_package->docbook, 'mergeMethods')) {
239                 unset(self::$parser->packages[$i]);
240                 continue;
241             }
242             if (self::$parser->active_package->name == "No Package") {
243                 unset(self::$parser->packages[$i]);
244                 continue;
245             }
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);
249             }
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");
253         }
254          PHP_CodeDoc::_outputFromTemplate( "manual.template.xml.in", "/docbook/manual.xml.in");
255         
256     }
257      /*
258     * Prepare Output for display
259     * - eg. sort some of the classes and functions by name
260     * apply extends
261     *
262     * @return   none
263     * @access   private
264     */
265      
266         
267
268     function _prepareOutput() {
269         
270         PHP_CodeDoc::_buildExtends();
271         
272       
273         echo "\n starting sorting \n";
274          
275         uksort(self::$parser->classes_by_name, "strnatcasecmp");
276         
277         $highlight = 1;
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");
284             
285             $highlight = !$highlight;
286         }
287         // set highlihgts by name
288         $highlight = 1;
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;
293         }
294         
295        
296        
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) {
301                 continue;
302             }
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
308             } 
309         }
310         
311         //print_r($this->classes);
312         //ob_start()
313     }
314     
315    /*
316     * build the extends arrays for classes
317     *
318     * @return   none
319     * @access   private
320     */
321      
322     function _buildExtends() {
323         
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]);
329                     exit;
330             }
331             */
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);
335         
336         }
337         echo "\n";
338     }
339     /*
340     * Merge the Operations/Attributes for classes
341     *
342     * @return   none
343     * @access   private
344     */
345      
346     function _mergeExtends($original_id,$Parent) {
347         
348       
349         if (!$Parent) return;
350         $id = @self::$parser->classes_by_name[$Parent]->id; 
351         if (!$id) return;
352         self::$parser->classes[$original_id]->extends[] = $Parent;
353         
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
358             }
359             if (@self::$parser->classes[$original_id]->iOperations[$k]) 
360                 continue;
361                 
362             self::$parser->classes[$original_id]->iOperations[$k] = 
363                 &self::$parser->classes[$id]->Operations[$k];
364                 
365             
366         }
367         
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;
371                 continue;
372             }
373             if (@self::$parser->classes[$original_id]->iAttributes[$k]) 
374                 continue;
375             
376             self::$parser->classes[$original_id]->iAttributes[$k] = 
377                 &self::$parser->classes[$id]->Attributes[$k];
378             
379         }
380         
381         PHP_CodeDoc::_mergeExtends($original_id,self::$parser->classes[$id]->Parent);
382         
383     }    
384      
385     function outputJs()
386     {
387         if (!isset(self::$options['targetJS'])) {
388             return;
389         }
390         $cats = array();
391         foreach(self::$parser->classes as $k=>$cls) {
392             var_dump($cls->name);
393             $ar = $cls->toJs();
394             if (!$ar) {
395                 continue;
396             }
397             foreach($ar[$cls->name] as $cat=>$catdata) {
398                 $cats[$cat] = isset($cats[$cat]) ? array_merge($cats[$cat], $catdata) : $catdata;
399             }
400             unset($ar[$cls->name]);
401             print_R($cats);
402             //print_R($cls);            exit;
403             foreach($ar as $fn => $data) {
404                 if (!$data){
405                     continue;
406                 }
407                 
408                 $file = self::$options['targetJS'].'/'.$fn.'.bjs';
409                 if (!file_exists(dirname($file))) {
410                     mkdir(dirname($file),0755,true);
411                 }
412                 echo "$file\n";
413                 
414                 
415                 file_put_contents($file, json_encode($data,JSON_PRETTY_PRINT));
416             }
417             
418             
419         }
420         $file = self::$options['targetJS'].'/categories.json';
421         file_put_contents($file, json_encode($cats ,JSON_PRETTY_PRINT));
422             
423         
424     }
425     
426