]> git.mxchange.org Git - friendica-addons.git/blob - dav/SabreDAV/bin/gwdg.php
Merge pull request #585 from annando/nicer-cat
[friendica-addons.git] / dav / SabreDAV / bin / gwdg.php
1 #!/usr/bin/env php
2 <?php
3
4 /**
5  * Documentation generator
6  *
7  * This scripts scans all files in the lib/ directory, and generates
8  * Google Code wiki documentation.
9  *
10  * This script is rather crappy. It does what it needs to do, but uses global
11  * variables and it might be a hard to read.
12  *
13  * I'm not sure if I care though. Maybe one day this can become a separate
14  * project
15  *
16  * To run this script, just execute on the command line. The script assumes
17  * it's in the standard bin/ directory.
18  */
19 date_default_timezone_set('UTC');
20
21 $libDir = realpath(__DIR__ . '/../lib');
22 $outputDir = __DIR__ . '/../docs/wikidocs';
23
24 if (!is_dir($outputDir)) mkdir($outputDir);
25
26 $files = new RecursiveDirectoryIterator($libDir);
27 $files = new RecursiveIteratorIterator($files, RecursiveIteratorIterator::LEAVES_ONLY);
28
29 include_once $libDir . '/Sabre/autoload.php';
30
31 // Finding all classnames
32 $classNames = findClassNames($files);
33 echo "Found: " . count($classNames) . " classes and interfaces\n";
34
35 echo "Generating class tree\n";
36 $classTree = getClassTree($classNames);
37
38 $packageList = array();
39
40 foreach($classNames as $className) {
41
42     echo "Creating docs for: " . $className . "\n";
43
44     $output = createDoc($className,isset($classTree[$className])?$classTree[$className]:array());
45     file_put_contents($outputDir . '/' . $className . '.wiki', $output);
46
47 }
48
49 echo "Creating indexes\n";
50 $output = createSidebarIndex($packageList);
51 file_put_contents($outputDir . '/APIIndex.wiki', $output);
52
53
54 function findClassNames($files) {
55
56     $classNames = array();
57     foreach($files as $fileName=>$fileInfo) {
58
59         $tokens = token_get_all(file_get_contents($fileName));
60         foreach($tokens as $tokenIndex=>$token) {
61
62             if ($token[0]===T_CLASS || $token[0]===T_INTERFACE) {
63                 $classNames[] = $tokens[$tokenIndex+2][1];
64             }
65
66         }
67
68     }
69
70     return $classNames;
71
72 }
73
74 function getClassTree($classNames) {
75
76     $classTree = array();
77
78     foreach($classNames as $className) {
79
80         if (!class_exists($className) && !interface_exists($className)) continue;
81         $rClass = new ReflectionClass($className);
82
83         $parent = $rClass->getParentClass();
84         if ($parent) $parent = $parent->name;
85
86         if (!isset($classTree[$parent])) $classTree[$parent] = array();
87         $classTree[$parent][] = $className;
88
89         foreach($rClass->getInterfaceNames() as $interface) {
90
91             if (!isset($classTree[$interface])) {
92                 $classTree[$interface] = array();
93             }
94             $classTree[$interface][] = $className;
95
96         }
97
98     }
99     return $classTree;
100
101 }
102
103 function createDoc($className, $extendedBy) {
104
105     // ew
106     global $packageList;
107
108     ob_start();
109     $rClass = new ReflectionClass($className);
110
111     echo "#summary API documentation for: ", $rClass->getName() , "\n";
112     echo "#labels APIDoc\n";
113     echo "#sidebar APIIndex\n";
114     echo "=`" . $rClass->getName() . "`=\n";
115     echo "\n";
116
117     $docs = parseDocs($rClass->getDocComment());
118     echo $docs['description'] . "\n";
119     echo "\n";
120
121     $parentClass = $rClass->getParentClass();
122
123     if($parentClass) {
124         echo "  * Parent class: [" . $parentClass->getName() . "]\n";
125     }
126     if ($interfaces = $rClass->getInterfaceNames()) {
127         $interfaces = array_map(function($int) { return '[' . $int . ']'; },$interfaces);
128         echo "  * Implements: " . implode(", ", $interfaces) . "\n";
129     }
130     $classType = $rClass->isInterface()?'interface':'class';
131     if (isset($docs['deprecated'])) {
132         echo "  * *Warning: This $classType is deprecated, and should not longer be used.*\n";
133     }
134     if ($rClass->isInterface()) {
135         echo "  * This is an interface.\n";
136     } elseif ($rClass->isAbstract()) {
137         echo "  * This is an abstract class.\n";
138     }
139     if (isset($docs['package'])) {
140         $package = $docs['package'];
141         if (isset($docs['subpackage'])) {
142             $package.='_' . $docs['subpackage'];
143         }
144         if (!isset($packageList[$package])) {
145             $packageList[$package] = array();
146         }
147         $packageList[$package][] = $rClass->getName();
148     }
149
150     if ($extendedBy) {
151
152         echo "\n";
153         if ($classType==='interface') {
154             echo "This interface is extended by the following interfaces:\n";
155             foreach($extendedBy as $className) {
156                 if (interface_exists($className)) {
157                     echo "  * [" . $className . "]\n";
158                 }
159             }
160             echo "\n";
161             echo "This interface is implemented by the following classes:\n";
162         } else {
163             echo "This class is extended by the following classes:\n";
164         }
165         foreach($extendedBy as $className) {
166             if (class_exists($className)) {
167                 echo "  * [" . $className . "]\n";
168             }
169         }
170         echo "\n";
171
172     }
173     echo "\n";
174
175     echo "==Properties==\n";
176
177     echo "\n";
178
179     $properties = $rClass->getProperties(ReflectionProperty::IS_STATIC | ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED);
180
181     if (count($properties)>0) {
182         foreach($properties as $rProperty) {
183
184             createPropertyDoc($rProperty);
185
186         }
187     } else {
188         echo "This $classType does not define any public or protected properties.\n";
189     }
190
191     echo "\n";
192
193     echo "==Methods==\n";
194
195     echo "\n";
196
197     $methods = $rClass->getMethods(ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED);
198
199     if (count($methods)>0) {
200         foreach($methods as $rMethod) {
201
202             createMethodDoc($rMethod, $rClass);
203
204         }
205     } else {
206         echo "\nThis $classType does not define any public or protected methods.\n";
207     }
208
209     return ob_get_clean();
210
211 }
212
213 function createMethodDoc($rMethod, $rClass) {
214
215     echo "===`" . $rMethod->getName() . "`===\n";
216     echo "\n";
217
218     $docs = parseDocs($rMethod->getDocComment());
219
220     $return = isset($docs['return'])?$docs['return']:'void';
221
222     echo "{{{\n";
223     echo $return . " " . $rMethod->class . "::" . $rMethod->getName() . "(";
224     foreach($rMethod->getParameters() as $parameter) {
225         if ($parameter->getPosition()>0) echo ", ";
226         if ($class = $parameter->getClass()) {
227             echo $class->name . " ";
228         } elseif (isset($docs['param'][$parameter->name])) {
229             echo $docs['param'][$parameter->name] . " ";
230         }
231
232         echo '$' . $parameter->name;
233
234         if ($parameter->isOptional() && $parameter->isDefaultValueAvailable()) {
235             $default = $parameter->getDefaultValue();
236             $default = var_export($default,true);
237             $default = str_replace("\n","",$default);
238             echo " = " . $default;
239
240         }
241     }
242     echo ")\n";
243     echo "}}}\n";
244     echo "\n";
245
246     echo $docs['description'] . "\n";
247
248     echo "\n";
249
250     $hasProp = false;
251     if (isset($docs['deprecated'])) {
252         echo "  * *Warning: This method is deprecated, and should not longer be used.*\n";
253         $hasProp = true;
254     }
255     if ($rMethod->isProtected()) {
256         echo "  * This method is protected.\n";
257         $hasProp = true;
258     }
259     if ($rMethod->isPrivate()) {
260         echo "  * This method is private.\n";
261         $hasProp = true;
262     }
263     if ($rMethod->isAbstract()) {
264         echo "  * This is an abstract method\n";
265         $hasProp = true;
266     }
267
268     if ($rMethod->class != $rClass->name) {
269         echo " * Defined in [" . $rMethod->class . "]\n";
270         $hasProp = true;
271     }
272
273     if ($hasProp) echo "\n";
274
275 }
276
277 function createPropertyDoc($rProperty) {
278
279     echo "===`" . $rProperty->getName() . "`===\n";
280     echo "\n";
281
282     $docs = parseDocs($rProperty->getDocComment());
283
284     $visibility = 'public';
285     if ($rProperty->isProtected()) $visibility = 'protected';
286     if ($rProperty->isPrivate()) $visibility = 'private';
287
288     echo "{{{\n";
289     echo $visibility . " " . $rProperty->class . "::$" . $rProperty->getName();
290     echo "\n}}}\n";
291     echo "\n";
292
293     echo $docs['description'] . "\n";
294
295     echo "\n";
296
297     $hasProp = false;
298     if (isset($docs['deprecated'])) {
299         echo "  * *Warning: This property is deprecated, and should not longer be used.*\n";
300         $hasProp = true;
301     }
302     if ($rProperty->isProtected()) {
303         echo "  * This property is protected.\n";
304         $hasProp = true;
305     }
306     if ($rProperty->isPrivate()) {
307         echo "  * This property is private.\n";
308         $hasProp = true;
309     }
310     if ($rProperty->isStatic()) {
311         echo "  * This property is static.\n";
312         $hasProp = true;
313     }
314
315     if ($hasProp) echo "\n";
316
317 }
318
319 function parseDocs($docString) {
320
321     $params = array();
322     $description = array();
323
324     // Trimming all the comment characters
325     $docString = trim($docString,"\n*/ ");
326     $docString = explode("\n",$docString);
327
328     foreach($docString as $str) {
329
330         $str = ltrim($str,'* ');
331         $str = trim($str);
332         if ($str && $str[0]==='@') {
333             $r = explode(' ',substr($str,1),2);
334             $paramName = $r[0];
335             $paramValue = (count($r)>1)?$r[1]:'';
336
337             // 'param' paramName is special. Confusing, I know.
338             if ($paramName==='param') {
339                 if (!isset($params['param'])) $params['param'] = array();
340                 $paramValue = explode(' ', $paramValue,3);
341                 $params['param'][substr($paramValue[1],1)] = $paramValue[0];
342             } else {
343                 $params[$paramName] = trim($paramValue);
344             }
345         } else {
346             $description[]=$str;
347         }
348
349     }
350
351     $params['description'] = trim(implode("\n",$description),"\n ");
352
353     return $params;
354
355 }
356
357 function createSidebarIndex($packageList) {
358
359     ob_start();
360     echo "#labels APIDocs\n";
361     echo "#summary List of all classes, neatly organized\n";
362     echo "=API Index=\n";
363
364     foreach($packageList as $package=>$classes) {
365
366         echo "  * $package\n";
367         sort($classes);
368         foreach($classes as $class) {
369
370             echo "    * [$class $class]\n";
371
372         }
373
374     }
375
376     return ob_get_clean();
377
378 }