2 //==============================================================================
3 // Name: JPCLASSREF.PHP
4 // Description: Basic framework to extract information about class hierarchi
5 // and structure from DB. To do specific output this framework
6 // expects a "formatter" plugin which handles the actual
7 // layout and formatting of class, functions and variables.
8 // See jpgenhtmldoc.php for example on how to write a simple
10 // Created: 2002-04-12
11 // Author: johanp@aditus.nu
12 // Version: $Id: jpclassref.php,v 1.15 2002/07/10 23:57:40 aditus Exp $
15 // Copyright (C) 2001,2002 Johan Persson
17 //==============================================================================
18 include_once("jpdb.php");
19 include_once("de_utils.php");
21 DEFINE("MAX_METHODREF",5);
22 DEFINE("MAX_METHODARGS",10);
24 DEFINE("FMT_CLASSVARS",1);
26 DEFINE('GLOBFUNCCLASS','GLOBALFUNCS');
31 var $iClasses=array(),
32 $iClassesByName=array(),
33 $iClassMethods=array(),
34 $iClassMethodsByName=array(),
40 function DBCache($aDB,$aProjName) {
41 $this->iProjName = '_'.$aProjName;
43 $this->iDBUtils = new DBUtils($aDB);
44 $this->iShowPrivate = $this->iDBUtils->GetShowPrivate($aProjName);
47 function RefreshMethods() {
48 $q = 'SELECT * FROM tbl_method'.$this->iProjName.' ORDER BY fld_name';
49 $res = $this->iDB->query($q);
51 $this->iMethods = array();
52 $this->iClassMethods = array();
53 $this->iClassMethodsByName = array();
54 for( $i=0; $i < $n; ++$i ) {
56 if( empty($row['fld_classidx']) || $row['fld_classidx']===0 )
57 $classname = GLOBFUNCCLASS;
59 $classname = $this->iClasses[$row['fld_classidx']][0];
60 $this->iMethods[$row["fld_key"]] = array($classname,$row['fld_name'],$row['fld_public']);
61 $this->iClassMethods[$classname][] = array('fld_name' => $row['fld_name'],
62 'fld_public' => $row['fld_public'],
63 'fld_file' => $row['fld_file'],
64 'fld_linenbr' => $row['fld_linenbr']);
65 $this->iClassMethodsByName[$classname][$row['fld_name']] = array($row['fld_name'],$row['fld_public']);
69 function RefreshClasses() {
70 $q = 'SELECT * FROM tbl_class'.$this->iProjName.' ORDER BY fld_name';
71 $res = $this->iDB->query($q);
73 $this->iMethods = array();
74 for( $i=0; $i < $n; ++$i ) {
76 $this->iClasses[$row["fld_key"]] = array($row["fld_name"],$row["fld_parentname"],$row["fld_public"]);
77 $this->iClassesByName[$row["fld_name"]] = array($row["fld_key"],$row["fld_parentname"],$row["fld_public"]);
84 class ClassFormatter {
92 var $iDocType = 0; // 0=Framed document, each class one file. 1=Everything in one file
93 var $iStatAverage = 0;
94 var $iStatNumClasses = 0;
95 var $iStatNumMethods = 0;
97 function ClassFormatter($aDBCache,$aFlags="") {
98 $this->iDBCache = $aDBCache;
99 $this->iFlags = $aFlags;
102 // Empty stubs ("virtual functions")
103 // A subclass needs to override this methods to actual achieve the
104 // desired formatting. The framework will call these formatting
105 // functions at the appropriate time.
107 function FmtClassHierarchySetup($aHier,$aNbr) {}
108 function FmtClassHierarchyExit($aHier,$aNbr) {}
109 function FmtClassHierarchyHeaders($aHier,$aNbr) {}
110 function FmtClassHierarchyColumnSetup($aClassName,$aColNbr) {}
111 function FmtClassHierarchyColumnExit($aClassName,$aColNbr) {}
112 function FmtClassHierarchyRow($aClassName,$aMethodName,$aOverridden,$aPublic) {}
113 function FmtClassSetup($aClassInfo) {}
114 function FmtClassOverview($aClassInfo) {}
115 function FmtClassVars($aVars) {}
116 function FmtClassRefs($aClassInfo) {}
117 function FmtFuncReturn($aFunc) {}
118 function FmtFuncPrototype($aClassName,$aFunc,$aShowFile=false) {}
119 function FmtFuncArgs($aFunc) {}
120 function FmtFuncDesc($aFunc) {}
121 function FmtFuncRef($aRef) {}
122 function FmtFuncExample($aFunc) {}
123 function FmtIndexSetup() {}
124 function FmtIndexClass($aClassName) {}
125 function FmtIndexMethod($aClassName,$aMethodName) {}
126 function FmtIndexExit() {}
128 // Called before/after global funcs
129 function GlobalFuncEntry($aNumFuncs) {}
130 function GlobalFuncExit() {}
132 // Called before/after any new class.
133 function ClassExit() {}
134 function ClassEntry($aClassName) {}
136 // Called before and after all formatting is done
141 // ------- END OF STUBS -----------
143 function Init($aProjName,$aProjDesc,$aDocType,$aDocDir,$aShowPrivate,$aShowGlobFuncs) {
145 $this->iDirectory = $aDocDir;
146 $this->iProjName = $aProjName;
147 $this->iProjDesc = $aProjDesc;
148 $this->iShowPrivate = $aShowPrivate;
149 $this->iDocType = $aDocType;
150 $this->iShowGlobFuncs = $aShowGlobFuncs;
154 function InitStat($aAverage,$aNumClasses,$aNumMethods) {
155 $this->iStatAverage = $aAverage;
156 $this->iStatNumClasses = $aNumClasses;
157 $this->iStatNumMethods = $aNumMethods;
160 function ClassHierarchy($aHier) {
162 $this->FmtClassHierarchySetup($aHier,$n);
163 $this->FmtClassHierarchyHeaders($aHier,$n);
165 for( $i=0; $i<$n; ++$i ) {
166 $this->FmtClassHierarchyColumnSetup($aHier[$i],$i);
168 if( empty($this->iDBCache->iClassMethods[$aHier[$i]]) ) {
169 $this->FmtClassHierarchyRow($aHier[$i],"",false,false);
172 $methods = $this->iDBCache->iClassMethods[$aHier[$i]];
173 $m = count($methods);
174 for( $j=0; $j<$m; ++$j ) {
177 if( !empty($supermethods[$methods[$j]['fld_name']]) )
180 $this->FmtClassHierarchyRow($aHier[$i],$methods[$j]['fld_name'],$overridden,$methods[$j]['fld_public']);
183 if( !empty($this->iDBCache->iClassMethodsByName[$aHier[$i]]) )
184 $supermethods = $this->iDBCache->iClassMethodsByName[$aHier[$i]];
186 $supermethods = array();
187 $this->FmtClassHierarchyColumnExit($aHier[$i],$i);
189 $this->FmtClassHierarchyExit($aHier,$n);
193 function DoClass($aClass,$aHier) {
194 $this->FmtClassSetup($aClass);
195 $this->ClassHierarchy($aHier);
196 $this->FmtClassOverview($aClass);
197 $this->FmtClassRefs($aClass);
198 $this->FmtClassOverviewExit($aClass);
201 function DoVars($aVars) {
202 if( !($this->iFlags & FMT_CLASSVARS) )
204 $this->FmtClassVars($aVars);
207 function ResolvMethRef($aRef) {
208 if( empty( $this->iDBCache->iMethods[$aRef] ) )
209 Utils::Error("Unknown method reference=$aRef");
210 else return $this->iDBCache->iMethods[$aRef];
213 function DoFuncs($aFuncs,$aClassName,$aShowFile=false) {
215 for( $i=0; $i < $n; ++$i ) {
217 if( $aClassName == GLOBFUNCCLASS ) {
218 echo '<br>'.($i+1).' : <font color=blue>'.$aFuncs[$i]['fld_name']."()</font>...\n";
221 if( $aFuncs[$i]['fld_public'] == 0 && !$this->iDBCache->iShowPrivate )
223 $this->FmtFuncPrototype($aClassName,$aFuncs[$i],$aShowFile);
224 $this->FmtFuncArgs($aFuncs[$i]);
225 $this->FmtFuncDesc($aFuncs[$i]);
226 $this->FmtFuncReturn($aFuncs[$i]);
230 while( $j <= MAX_METHODREF ) {
231 if( !empty($aFuncs[$i]["fld_methref$j"]) && $aFuncs[$i]["fld_methref$j"] > 0)
232 $ref[]=$aFuncs[$i]["fld_methref$j"];
238 for( $j=0; $j < $m; ++$j ) {
239 if( empty( $this->iDBCache->iMethods[$ref[$j]] ) )
240 Utils::Error("Unknown method reference key=$ref[$j] in method : $aClassName::".$aFuncs[$i]['fld_name']);
241 else $refarr[] = $this->iDBCache->iMethods[$ref[$j]];
243 $this->FmtFuncRef($refarr);
245 $this->FmtFuncExample($aFuncs[$i]);
252 var $iIdx, $iRow, $iVars, $iFuncs, $iDBCache, $iHierarchy;
253 function ClassRef($aRow,$aHierarchy,$aVars,$aFuncs,$aIdx,$aDBCache) {
256 $this->iVars = $aVars;
257 $this->iFuncs = $aFuncs;
258 $this->iDBCache = $aDBCache;
259 $this->iHierarchy = $aHierarchy;
262 function Stroke(&$aFormatter) {
263 $aFormatter->ClassEntry($this->iRow["fld_name"]);
264 $aFormatter->DoClass($this->iRow,$this->iHierarchy);
265 $aFormatter->DoVars($this->iVars);
266 $aFormatter->DoFuncs($this->iFuncs,$this->iRow["fld_name"]);
267 $aFormatter->ClassExit();
272 var $iDB, $iDBCache, $iFlags;
275 var $iNumIndexCols = 3;
277 function ClassReader($aFormatter,$aDBCache,$aFlags="") {
278 $this->iDB = $aDBCache->iDB;
279 $this->iDBCache = $aDBCache;
280 $this->iFlags = $aFlags;
281 $this->iFormatter = $aFormatter;
282 $this->iProjName = $aDBCache->iProjName;
285 function SetNumIndexCols($aNum) {
286 $this->iNumIndexCols = $aNum;
289 function GetHierarchy($aClassName) {
290 $h = array($aClassName);
291 $parent = $this->iDBCache->iClassesByName[$aClassName][1];
292 while( $parent != "" ) {
294 if( empty($this->iDBCache->iClassesByName[$parent][1]) ) {
298 $parent = $this->iDBCache->iClassesByName[$parent][1];
303 function GenClassIndex() {
304 $this->iFormatter->FmtIndexSetup(count($this->iDBCache->iClasses),count($this->iDBCache->iMethods),$this->iNumIndexCols);
305 foreach( $this->iDBCache->iClasses as $c ) {
306 if( $c[2] == 0 && !$this->iDBCache->iShowPrivate )
309 $this->iFormatter->FmtIndexClass($c[0]);
310 if( !empty($this->iDBCache->iClassMethods[$c[0]]) && count($this->iDBCache->iClassMethods[$c[0]]) > 0 ) {
311 foreach( $this->iDBCache->iClassMethods[$c[0]] as $m ) {
312 if( $m['fld_public'] == 0 && !$this->iDBCache->iShowPrivate )
314 $this->iFormatter->FmtIndexMethod($c[0], $m['fld_name']);
318 $this->iFormatter->FmtIndexExit();
322 function Run($aClass) {
324 $q = 'SELECT * FROM tbl_class'.$this->iProjName.' ORDER BY fld_name ';
326 $q .= " WHERE fld_name='".$aClass."'";
327 $classres = $this->iDB->query($q);
328 $n = $classres->NumRows();
331 $this->GenClassIndex();
333 for( $i=0; $i < $n; ++$i ) {
334 $row = $classres->Fetch();
336 if( $row['fld_public'] == 0 && !$this->iDBCache->iShowPrivate )
339 $hier = $this->GetHierarchy($row["fld_name"]);
341 $q = 'SELECT * FROM tbl_classvars'.$this->iProjName.' WHERE fld_classidx='.$row['fld_key'].' ORDER BY fld_name';
342 $varres = $this->iDB->query($q);
343 $nn = $varres->NumRows();
345 for( $j=0; $j < $nn; ++$j ) {
346 $vars[] = $varres->Fetch();
349 $q = 'SELECT * FROM tbl_method'.$this->iProjName.' WHERE fld_classidx='.$row['fld_key'].' ORDER BY fld_name';
350 $funcres = $this->iDB->query($q);
351 $nn = $funcres->NumRows();
353 for( $j=0; $j < $nn; ++$j ) {
354 $funcs[] = $funcres->Fetch();
357 $c = new ClassRef($row,$hier,$vars,$funcs,$i,$this->iDBCache);
358 $c->Stroke($this->iFormatter);
363 // Read all global functions and format them
364 class GlobalFuncReader {
365 var $iDB,$iDBCache,$iFlags;
369 function GlobalFuncReader($aFormatter,$aDBCache,$aFlags="") {
370 $this->iDBCache = $aDBCache;
371 $this->iDB = $aDBCache->iDB;
372 $this->iFlags = $aFlags;
373 $this->iFormatter = $aFormatter;
374 $this->iProjName = $aDBCache->iProjName;
378 $q = 'SELECT * FROM tbl_method'.$this->iProjName.' WHERE fld_classidx=0 ORDER BY fld_name';
379 $res = $this->iDB->query($q);
380 $n = $res->NumRows();
382 for($i=0; $i < $n; ++$i ) {
383 $funcs[] = $res->Fetch();
385 $this->iFormatter->GlobalFuncEntry($n);
386 $this->iFormatter->DoFuncs($funcs,GLOBFUNCCLASS,true);
387 $this->iFormatter->GlobalFuncExit();
393 class ClassRefDriver {
395 var $iProjName, $iProjIdx;
396 var $iNumIndexCols=3;
398 function NewClassFormatter($aDBCache,$aFlags) {
399 Utils::Error("ERROR: NewClassFormatter must be overridden to provide the actual formatter");
402 function SetNumIndexCols($aNum) {
403 $this->iNumIndexCols = $aNum;
406 function ClassRefDriver() {
407 global $HTTP_COOKIE_VARS;
409 $this->iDB = DBFactory::InitDB();
411 $this->iProjname = strtok(@$HTTP_COOKIE_VARS['ddda_project'],':');
412 if( $this->iProjname != '' ) {
413 $this->iProjidx = strtok(':');
414 $this->iDBCache = new DBCache($this->iDB,$this->iProjname);
417 die('No, no project specified.');
420 function Run($aClass,$aFlags="") {
422 $dbutils = $this->iDBCache->iDBUtils;
423 $dbutils->SetProject($this->iProjname);
424 $proj = $dbutils->GetProject();
425 $docdir = $proj['fld_docdir'];
426 $showPrivate = $proj['fld_showprivate'];
427 $docType = $proj['fld_doctype'];
428 $showGlobFuncs = $proj['fld_showglobfuncs'];
430 $this->iDBCache->RefreshClasses();
431 $this->iDBCache->RefreshMethods();
433 $fmt = $this->NewClassFormatter($this->iDBCache,$aFlags);
434 $fmt->Init($this->iProjname,$proj['fld_desc'],$docType,$docdir,$showPrivate,$showGlobFuncs);
435 $ds = new DocStat($dbutils);
436 list($avg,$nc,$nm) = $ds->ProjStat($this->iProjname);
437 $fmt->InitStat($avg,$nc,$nm);
441 // Format all the classes and their methods
442 $cr = new ClassReader($fmt,$this->iDBCache,$aFlags);
443 $cr->SetNumIndexCols($this->iNumIndexCols);
446 // Format all global functions
447 if( $showGlobFuncs ) {
448 $gf = new GlobalFuncReader($fmt,$this->iDBCache,$aFlags);