This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php defined('SYSPATH') or die('No direct access allowed.'); |
||
2 | /** |
||
3 | * Kohana - The Swift PHP Framework |
||
4 | * |
||
5 | * License: |
||
6 | * author - Kohana Team |
||
7 | * copyright - (c) 2007 Kohana Team |
||
8 | * license - <http://kohanaphp.com/license.html> |
||
9 | */ |
||
10 | |||
11 | /** |
||
12 | * Provides self-generating documentation about Kohana. |
||
13 | */ |
||
14 | class Kodoc_Core |
||
15 | { |
||
16 | protected static $types = array( |
||
17 | 'core', |
||
18 | 'config', |
||
19 | 'helpers', |
||
20 | 'libraries', |
||
21 | 'models', |
||
22 | 'views' |
||
23 | ); |
||
24 | |||
25 | public static function get_types() |
||
26 | { |
||
27 | return self::$types; |
||
28 | } |
||
29 | |||
30 | public static function get_files() |
||
31 | { |
||
32 | // Extension length |
||
33 | $ext_len = -(strlen(EXT)); |
||
34 | |||
35 | $files = array(); |
||
36 | foreach (self::$types as $type) { |
||
37 | $files[$type] = array(); |
||
38 | foreach (Kohana::list_files($type, true) as $file) { |
||
39 | // Not a source file |
||
40 | if (substr($file, $ext_len) !== EXT) { |
||
41 | continue; |
||
42 | } |
||
43 | |||
44 | // Remove the dirs from the filename |
||
45 | $file = preg_replace('!^.+'.$type.'/(.+)'.EXT.'$!', '$1', $file); |
||
46 | |||
47 | // Skip utf8 function files |
||
48 | if ($type === 'core' and substr($file, 0, 5) === 'utf8/') { |
||
49 | continue; |
||
50 | } |
||
51 | |||
52 | if ($type === 'libraries' and substr($file, 0, 8) === 'drivers/') { |
||
53 | // Remove the drivers directory from the file |
||
54 | $file = explode('_', substr($file, 8)); |
||
55 | |||
56 | if (count($file) === 1) { |
||
57 | // Driver interface |
||
58 | $files[$type][current($file)][] = current($file); |
||
59 | } else { |
||
60 | // Driver is class suffix |
||
61 | $driver = array_pop($file); |
||
62 | |||
63 | // Library is everything else |
||
64 | $library = implode('_', $file); |
||
65 | |||
66 | // Library driver |
||
67 | $files[$type][$library][] = $driver; |
||
68 | } |
||
69 | } else { |
||
70 | $files[$type][$file] = null; |
||
71 | } |
||
72 | } |
||
73 | } |
||
74 | |||
75 | return $files; |
||
76 | } |
||
77 | |||
78 | public static function remove_docroot($file) |
||
0 ignored issues
–
show
|
|||
79 | { |
||
80 | return preg_replace('!^'.preg_quote(DOCROOT, '!').'!', '', $file); |
||
81 | } |
||
82 | |||
83 | public static function humanize_type($types) |
||
84 | { |
||
85 | $types = is_array($types) ? $types : explode('|', $types); |
||
86 | |||
87 | $output = array(); |
||
88 | while ($t = array_shift($types)) { |
||
0 ignored issues
–
show
|
|||
89 | $output[] = '<tt>'.trim($t).'</tt>'; |
||
90 | } |
||
91 | |||
92 | return implode(' or ', $output); |
||
93 | } |
||
94 | |||
95 | public static function humanize_value($value) |
||
96 | { |
||
97 | if ($value === null) { |
||
98 | return 'NULL'; |
||
99 | } elseif (is_bool($value)) { |
||
100 | return $value ? 'TRUE' : 'FALSE'; |
||
101 | } elseif (is_string($value)) { |
||
102 | return 'string '.$value; |
||
103 | } elseif (is_numeric($value)) { |
||
104 | return (is_int($value) ? 'int' : 'float').' '.$value; |
||
105 | } elseif (is_array($value)) { |
||
106 | return 'array'; |
||
107 | } elseif (is_object($value)) { |
||
108 | return 'object '.get_class($value); |
||
109 | } |
||
110 | } |
||
111 | |||
112 | // All files to be parsed |
||
113 | protected $file = array(); |
||
114 | |||
115 | public function __construct($type, $filename) |
||
116 | { |
||
117 | // Parse the file |
||
118 | $this->file = $this->parse($type, $filename); |
||
119 | } |
||
120 | |||
121 | /** |
||
122 | * Fetch documentation for all files parsed. |
||
123 | * |
||
124 | * Returns: |
||
125 | * array: file documentation |
||
126 | */ |
||
127 | public function get() |
||
128 | { |
||
129 | return $this->file; |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * Parse a file for Kodoc commands, classes, and methods. |
||
134 | * |
||
135 | * Parameters: |
||
136 | * string: file type |
||
137 | * string: absolute filename path |
||
138 | */ |
||
139 | protected function parse($type, $filename) |
||
140 | { |
||
141 | // File definition |
||
142 | $file = array( |
||
143 | 'type' => $type, |
||
144 | 'comment' => '', |
||
145 | 'file' => self::remove_docroot($filename), |
||
146 | ); |
||
147 | |||
148 | // Read the entire file into an array |
||
149 | $data = file($filename); |
||
150 | |||
151 | foreach ($data as $line) { |
||
152 | if (strpos($line, 'class') !== false and preg_match('/(?:class|interface)\s+([a-z0-9_]+).+{$/i', $line, $matches)) { |
||
153 | // Include the file if it has not already been included |
||
154 | class_exists($matches[1], false) or include_once $filename; |
||
155 | |||
156 | // Add class to file info |
||
157 | $file['classes'][] = $this->parse_class($matches[1]); |
||
158 | } |
||
159 | } |
||
160 | |||
161 | if (empty($file['classes'])) { |
||
162 | $block = null; |
||
163 | $source = null; |
||
164 | |||
165 | foreach ($data as $line) { |
||
166 | switch (substr(trim($line), 0, 2)) { |
||
167 | case '/*': |
||
168 | $block = ''; |
||
169 | continue 2; |
||
170 | break; |
||
0 ignored issues
–
show
break; does not seem to be reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||
171 | case '*/': |
||
172 | $source = true; |
||
173 | continue 2; |
||
174 | break; |
||
0 ignored issues
–
show
break; does not seem to be reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||
175 | } |
||
176 | |||
177 | if ($source === true) { |
||
178 | if (preg_match('/\$config\[\'(.+?)\'\]\s+=\s+([^;].+)/', $line, $matches)) { |
||
179 | $source = array( |
||
180 | $matches[1], |
||
181 | $matches[2] |
||
182 | ); |
||
183 | } else { |
||
184 | $source = array(); |
||
185 | } |
||
186 | |||
187 | $file['comments'][] = array_merge($this->parse_comment($block), array('source' => $source)); |
||
188 | |||
189 | $block = null; |
||
190 | $source = false; |
||
191 | } elseif (is_string($block)) { |
||
192 | $block .= $line; |
||
193 | } |
||
194 | } |
||
195 | } |
||
196 | |||
197 | return $file; |
||
198 | } |
||
199 | |||
200 | /** |
||
201 | * @param null|string $block |
||
202 | */ |
||
203 | protected function parse_comment($block) |
||
204 | { |
||
205 | if (($block = trim($block)) == '') { |
||
206 | return $block; |
||
207 | } |
||
208 | |||
209 | // Explode the lines into an array and trim them |
||
210 | $block = array_map('trim', explode("\n", $block)); |
||
211 | |||
212 | if (current($block) === '/**') { |
||
213 | // Remove comment opening |
||
214 | array_shift($block); |
||
215 | } |
||
216 | |||
217 | if (end($block) === '*/') { |
||
218 | // Remove comment closing |
||
219 | array_pop($block); |
||
220 | } |
||
221 | |||
222 | // Start comment |
||
223 | $comment = array(); |
||
224 | |||
225 | while ($line = array_shift($block)) { |
||
226 | // Remove * from the line |
||
227 | $line = trim(substr($line, 2)); |
||
228 | |||
229 | if ($line[0] === '$' and substr($line, -1) === '$') { |
||
230 | // Skip SVN property inserts |
||
231 | continue; |
||
232 | } |
||
233 | |||
234 | if ($line[0] === '@') { |
||
235 | if (preg_match('/^@(.+?)\s+(.+)$/', $line, $matches)) { |
||
236 | $comment[$matches[1]][] = $matches[2]; |
||
237 | } |
||
238 | } else { |
||
239 | $comment['about'][] = $line; |
||
240 | } |
||
241 | } |
||
242 | |||
243 | if (! empty($comment['about'])) { |
||
244 | $token = ''; |
||
245 | $block = ''; |
||
246 | $about = ''; |
||
247 | |||
248 | foreach ($comment['about'] as $line) { |
||
249 | if (strpos($line, '`') !== false) { |
||
250 | $line = preg_replace('/`([^`].+?)`/', '<tt>$1</tt>', $line); |
||
251 | } |
||
252 | |||
253 | if (substr($line, 0, 2) === '- ') { |
||
254 | if ($token !== 'ul') { |
||
255 | $about .= $this->comment_block($token, $block); |
||
256 | $block = ''; |
||
257 | } |
||
258 | |||
259 | $token = 'ul'; |
||
260 | $line = '<li>'.trim(substr($line, 2)).'</li>'."\n"; |
||
261 | } elseif (preg_match('/(.+?)\s+-\s+(.+)/', $line, $matches)) { |
||
262 | if ($token !== 'dl') { |
||
263 | $about .= $this->comment_block($token, $block); |
||
264 | $block = ''; |
||
265 | } |
||
266 | |||
267 | $token = 'dl'; |
||
268 | $line = '<dt>'.$matches[1].'</dt>'."\n".'<dd>'.$matches[2].'</dd>'."\n"; |
||
269 | } else { |
||
270 | $token = 'p'; |
||
271 | $line .= ' '; |
||
272 | } |
||
273 | |||
274 | if (trim($line) === '') { |
||
275 | $about .= $this->comment_block($token, $block); |
||
276 | $block = ''; |
||
277 | } else { |
||
278 | $block .= $line; |
||
279 | } |
||
280 | } |
||
281 | |||
282 | if (! empty($block)) { |
||
283 | $about .= $this->comment_block($token, $block); |
||
284 | } |
||
285 | |||
286 | $comment['about'] = $about; |
||
287 | } |
||
288 | |||
289 | return $comment; |
||
290 | } |
||
291 | |||
292 | /** |
||
293 | * @param string $token |
||
294 | * @param string $block |
||
295 | */ |
||
296 | protected function comment_block($token, $block) |
||
297 | { |
||
298 | if (empty($token) or empty($block)) { |
||
299 | return ''; |
||
300 | } |
||
301 | |||
302 | $block = trim($block); |
||
303 | |||
304 | if ($block[0] === '<') { |
||
305 | // Insert newlines before and after the block |
||
306 | $block = "\n".$block."\n"; |
||
307 | } |
||
308 | |||
309 | return '<'.$token.'>'.$block.'</'.$token.'>'."\n"; |
||
310 | } |
||
311 | |||
312 | /** |
||
313 | * @param string $class |
||
314 | */ |
||
315 | protected function parse_class($class) |
||
316 | { |
||
317 | // Use reflection to find information |
||
318 | $reflection = new ReflectionClass($class); |
||
319 | |||
320 | // Class definition |
||
321 | $class = array( |
||
322 | 'name' => $reflection->getName(), |
||
0 ignored issues
–
show
![]() |
|||
323 | 'comment' => $this->parse_comment($reflection->getDocComment()), |
||
324 | 'final' => $reflection->isFinal(), |
||
325 | 'abstract' => $reflection->isAbstract(), |
||
326 | 'interface' => $reflection->isInterface(), |
||
327 | 'extends' => '', |
||
328 | 'implements' => array(), |
||
329 | 'methods' => array() |
||
330 | ); |
||
331 | |||
332 | if ($implements = $reflection->getInterfaces()) { |
||
333 | foreach ($implements as $interface) { |
||
334 | // Get implemented interfaces |
||
335 | $class['implements'][] = $interface->getName(); |
||
0 ignored issues
–
show
![]() |
|||
336 | } |
||
337 | } |
||
338 | |||
339 | if ($parent = $reflection->getParentClass()) { |
||
340 | // Get parent class |
||
341 | $class['extends'] = $parent->getName(); |
||
342 | } |
||
343 | |||
344 | if ($methods = $reflection->getMethods()) { |
||
345 | foreach ($methods as $method) { |
||
346 | // Don't try to document internal methods |
||
347 | if ($method->isInternal()) { |
||
348 | continue; |
||
349 | } |
||
350 | |||
351 | $class['methods'][] = array( |
||
352 | 'name' => $method->getName(), |
||
0 ignored issues
–
show
![]() |
|||
353 | 'comment' => $this->parse_comment($method->getDocComment()), |
||
354 | 'class' => $class['name'], |
||
355 | 'final' => $method->isFinal(), |
||
356 | 'static' => $method->isStatic(), |
||
357 | 'abstract' => $method->isAbstract(), |
||
358 | 'visibility' => $this->visibility($method), |
||
359 | 'parameters' => $this->parameters($method) |
||
360 | ); |
||
361 | } |
||
362 | } |
||
363 | |||
364 | return $class; |
||
365 | } |
||
366 | |||
367 | /** |
||
368 | * Finds the parameters for a ReflectionMethod. |
||
369 | * |
||
370 | * @param object ReflectionMethod |
||
371 | * @return array |
||
372 | */ |
||
373 | protected function parameters(ReflectionMethod $method) |
||
374 | { |
||
375 | $params = array(); |
||
376 | |||
377 | if ($parameters = $method->getParameters()) { |
||
378 | foreach ($parameters as $param) { |
||
379 | // Parameter data |
||
380 | $data = array( |
||
381 | 'name' => $param->getName() |
||
0 ignored issues
–
show
![]() |
|||
382 | ); |
||
383 | |||
384 | if ($param->isOptional()) { |
||
385 | // Set default value |
||
386 | $data['default'] = $param->getDefaultValue(); |
||
387 | } |
||
388 | |||
389 | $params[] = $data; |
||
390 | } |
||
391 | } |
||
392 | |||
393 | return $params; |
||
394 | } |
||
395 | |||
396 | /** |
||
397 | * Finds the visibility of a ReflectionMethod. |
||
398 | * |
||
399 | * @param object ReflectionMethod |
||
400 | * @return string |
||
0 ignored issues
–
show
|
|||
401 | */ |
||
402 | protected function visibility(ReflectionMethod $method) |
||
403 | { |
||
404 | $vis = array_flip(Reflection::getModifierNames($method->getModifiers())); |
||
405 | |||
406 | if (isset($vis['public'])) { |
||
407 | return 'public'; |
||
408 | } |
||
409 | |||
410 | if (isset($vis['protected'])) { |
||
411 | return 'protected'; |
||
412 | } |
||
413 | |||
414 | if (isset($vis['private'])) { |
||
415 | return 'private'; |
||
416 | } |
||
417 | |||
418 | return false; |
||
419 | } |
||
420 | } // End Kodoc |
||
421 | class Kodoc_xCore |
||
422 | { |
||
423 | |||
424 | /** |
||
425 | * libraries, helpers, etc |
||
426 | */ |
||
427 | protected $files = array( |
||
428 | 'core' => array(), |
||
429 | 'config' => array(), |
||
430 | 'helpers' => array(), |
||
431 | 'libraries' => array(), |
||
432 | 'models' => array(), |
||
433 | 'views' => array() |
||
434 | ); |
||
435 | |||
436 | /** |
||
437 | * $classes[$name] = array $properties; |
||
438 | * $properties = array |
||
439 | * ( |
||
440 | * 'drivers' => array $drivers |
||
441 | * 'properties' => array $properties |
||
442 | * 'methods' => array $methods |
||
443 | * ) |
||
444 | */ |
||
445 | protected $classes = array(); |
||
446 | |||
447 | // Holds the current data until parsed |
||
448 | protected $current_class; |
||
449 | |||
450 | // $packages[$name] = array $files; |
||
451 | protected $packages = array(); |
||
452 | |||
453 | // PHP's visibility types |
||
454 | protected static $php_visibility = array( |
||
455 | 'public', |
||
456 | 'protected', |
||
457 | 'private' |
||
458 | ); |
||
459 | |||
460 | public function __construct() |
||
461 | { |
||
462 | if (isset(self::$php_visibility[0])) { |
||
463 | self::$php_visibility = array_flip(self::$php_visibility); |
||
464 | } |
||
465 | |||
466 | foreach ($this->files as $type => $files) { |
||
467 | foreach (Kohana::list_files($type) as $filepath) { |
||
468 | // Get the filename with no extension |
||
469 | $file = pathinfo($filepath, PATHINFO_FILENAME); |
||
470 | |||
471 | // Skip indexes and drivers |
||
472 | if ($file === 'index' or strpos($filepath, 'libraries/drivers') !== false) { |
||
473 | continue; |
||
474 | } |
||
475 | |||
476 | // Add the file |
||
477 | $this->files[$type][$file] = $filepath; |
||
478 | |||
479 | // Parse the file |
||
480 | $this->parse_file($filepath); |
||
481 | } |
||
482 | } |
||
483 | |||
484 | Kohana::log('debug', 'Kodoc Library initialized'); |
||
485 | } |
||
486 | |||
487 | public function get_docs($format = 'html') |
||
0 ignored issues
–
show
The return type could not be reliably inferred; please add a
@return annotation.
Our type inference engine in quite powerful, but sometimes the code does not
provide enough clues to go by. In these cases we request you to add a ![]() |
|||
488 | { |
||
489 | switch ($format) { |
||
490 | default: |
||
0 ignored issues
–
show
default: // Generate...)->render(); break; does not seem to be reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||
491 | // Generate HTML via a View |
||
492 | $docs = new View('kodoc_html'); |
||
493 | |||
494 | $docs->set('classes', $this->classes)->render(); |
||
495 | break; |
||
496 | } |
||
497 | |||
498 | return $docs; |
||
0 ignored issues
–
show
The variable
$docs seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?
This error can happen if you refactor code and forget to move the variable initialization. Let’s take a look at a simple example: function someFunction() {
$x = 5;
echo $x;
}
The above code is perfectly fine. Now imagine that we re-order the statements: function someFunction() {
echo $x;
$x = 5;
}
In that case, ![]() |
|||
499 | } |
||
500 | |||
501 | protected function parse_file($file) |
||
502 | { |
||
503 | $file = fopen($file, 'r'); |
||
504 | |||
505 | $i = 1; |
||
506 | while ($line = fgets($file)) { |
||
507 | if (substr(trim($line), 0, 2) === '/*') { |
||
508 | // Reset vars |
||
509 | unset($current_doc, $section, $p); |
||
0 ignored issues
–
show
|
|||
510 | |||
511 | // Prepare for a new doc section |
||
512 | $current_doc = array(); |
||
513 | $closing_tag = '*/'; |
||
514 | |||
515 | $current_block = 'description'; |
||
516 | $p = 0; |
||
517 | |||
518 | // Assign the current doc |
||
519 | $this->current_doc =& $current_doc; |
||
0 ignored issues
–
show
The property
current_doc does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
520 | } elseif (isset($closing_tag)) { |
||
521 | if (substr(trim($line), 0, 1) === '*') { |
||
522 | // Remove the leading comment |
||
523 | $line = substr(ltrim($line), 2); |
||
524 | |||
525 | if (preg_match('/^([a-z ]+):/i', $line, $matches)) { |
||
526 | $current_block = trim($matches[1]); |
||
527 | } elseif (isset($current_doc)) { |
||
528 | $line = ltrim($line); |
||
529 | |||
530 | if (preg_match('/^\-\s+(.+)/', $line, $matches)) { |
||
531 | // An unordered list |
||
532 | $current_doc['html'][$current_block]['ul'][] = $matches[1]; |
||
0 ignored issues
–
show
The variable
$current_block does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
533 | } elseif (preg_match('/^[0-9]+\.\s+(.+)/', $line, $matches)) { |
||
534 | // An ordered list |
||
535 | $current_doc['html'][$current_block]['ol'][] = $matches[1]; |
||
536 | } elseif (preg_match('/^([a-zA-Z ]+)\s+\-\s+(.+)/', $line, $matches)) { |
||
537 | // Definition list |
||
538 | $current_doc['html'][$current_block]['dl'][trim($matches[1])] = trim($matches[2]); |
||
539 | } else { |
||
540 | if (trim($line) === '') { |
||
541 | // Start a new paragraph |
||
542 | $p++; |
||
0 ignored issues
–
show
The variable
$p does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
543 | } else { |
||
544 | // Make sure the current paragraph is set |
||
545 | if (! isset($current_doc['html'][$current_block]['p'][$p])) { |
||
546 | $current_doc['html'][$current_block]['p'][$p] = ''; |
||
547 | } |
||
548 | |||
549 | // Add to the current paragraph |
||
550 | $current_doc['html'][$current_block]['p'][$p] .= str_replace("\n", ' ', $line); |
||
551 | } |
||
552 | } |
||
553 | } |
||
554 | } else { |
||
555 | switch (substr(trim($line), 0, 2)) { |
||
556 | case '//': |
||
557 | case '* ': break; |
||
558 | default: |
||
559 | $line = trim($line); |
||
560 | |||
561 | if ($this->is_function($line) or $this->is_property($line) or $this->is_class($line)) { |
||
562 | $clear = null; |
||
563 | $this->current_doc =& $clear; |
||
564 | |||
565 | // Restarts searching |
||
566 | unset($closing_tag, $current_doc); |
||
567 | } |
||
568 | break; |
||
569 | } |
||
570 | } |
||
571 | } |
||
572 | |||
573 | $i++; |
||
574 | } |
||
575 | |||
576 | // Close the file |
||
577 | fclose($file); |
||
578 | } |
||
579 | |||
580 | /** |
||
581 | * Method: |
||
582 | * Checks if a line is a class, and parses the data out. |
||
583 | * |
||
584 | * Parameters: |
||
585 | * line - a line from a file |
||
586 | * |
||
587 | * Returns: |
||
588 | * TRUE or FALSE. |
||
589 | * @param string $line |
||
590 | */ |
||
591 | protected function is_class($line) |
||
592 | { |
||
593 | if (strpos($line, 'class') === false) { |
||
594 | return false; |
||
595 | } |
||
596 | |||
597 | $line = explode(' ', trim($line)); |
||
598 | |||
599 | $class = array( |
||
600 | 'name' => '', |
||
601 | 'final' => false, |
||
602 | 'extends' => false, |
||
603 | 'drivers' => false |
||
604 | ); |
||
605 | |||
606 | if (current($line) === 'final') { |
||
607 | $class['final'] = (bool) array_shift($line); |
||
608 | } |
||
609 | |||
610 | if (current($line) === 'class') { |
||
611 | // Remove "class" |
||
612 | array_shift($line); |
||
613 | |||
614 | $name = array_shift($line); |
||
615 | } |
||
616 | |||
617 | if (count($line) > 1) { |
||
618 | // Remove "extends" |
||
619 | array_shift($line); |
||
620 | |||
621 | $class['extends'] = array_shift($line); |
||
622 | } |
||
623 | |||
624 | if (isset($name)) { |
||
625 | // Add the class into the docs |
||
626 | $this->classes[$name] = array_merge($this->current_doc, $class); |
||
627 | |||
628 | // Set the current class |
||
629 | $this->current_class =& $this->classes[$name]; |
||
630 | |||
631 | return true; |
||
632 | } |
||
633 | |||
634 | return false; |
||
635 | } |
||
636 | |||
637 | /** |
||
638 | * Method: |
||
639 | * Checks if a line is a property, and parses the data out. |
||
640 | * |
||
641 | * Parameters: |
||
642 | * line - a line from a file |
||
643 | * |
||
644 | * Returns: |
||
645 | * TRUE or FALSE. |
||
646 | * @param string $line |
||
647 | */ |
||
648 | protected function is_property($line) |
||
649 | { |
||
650 | static $preg_vis; |
||
651 | |||
652 | if ($preg_vis === null) { |
||
653 | $preg_vis = 'var|'.implode('|', self::$php_visibility); |
||
654 | } |
||
655 | |||
656 | if (strpos($line, '$') === false or ! preg_match('/^(?:'.$preg_vis.')/', $line)) { |
||
657 | return false; |
||
658 | } |
||
659 | |||
660 | $line = explode(' ', $line); |
||
661 | |||
662 | $var = array( |
||
663 | 'visibility' => false, |
||
664 | 'static' => false, |
||
665 | 'default' => null |
||
666 | ); |
||
667 | |||
668 | if (current($line) === 'var') { |
||
669 | // Remove "var" |
||
670 | array_shift($line); |
||
671 | |||
672 | $var['visibility'] = 'public'; |
||
673 | } |
||
674 | |||
675 | if (current($line) === 'static') { |
||
676 | $var['visibility'] = (bool) array_shift($line); |
||
677 | } |
||
678 | |||
679 | // If the visibility is not set, this is not a |
||
680 | if ($var['visibility'] === false) { |
||
681 | return false; |
||
682 | } |
||
683 | |||
684 | if (substr(current($line), 0, 1) === '$') { |
||
685 | $name = substr(array_shift($line), 1); |
||
686 | $name = rtrim($name, ';'); |
||
687 | } |
||
688 | |||
689 | if (count($line) and current($line) === '=') { |
||
690 | array_shift($line); |
||
691 | |||
692 | $var['default'] = implode(' ', $line); |
||
693 | } |
||
694 | |||
695 | if (isset($name)) { |
||
696 | // Add property to class |
||
697 | $this->current_class['properties'][$name] = array_merge($this->current_doc, $var); |
||
698 | |||
699 | return true; |
||
700 | } |
||
701 | |||
702 | return false; |
||
703 | } |
||
704 | |||
705 | /** |
||
706 | * Method: |
||
707 | * Checks if a line is a function, and parses the data out. |
||
708 | * |
||
709 | * Parameters: |
||
710 | * line - a line from a file |
||
711 | * |
||
712 | * Returns: |
||
713 | * TRUE or FALSE. |
||
714 | * @param string $line |
||
715 | */ |
||
716 | protected function is_function($line) |
||
717 | { |
||
718 | if (strpos($line, 'function') === false) { |
||
719 | return false; |
||
720 | } |
||
721 | |||
722 | $line = explode(' ', trim(strtolower($line))); |
||
723 | |||
724 | $func = array( |
||
725 | 'final' => false, |
||
726 | 'visibility' => 'public', |
||
727 | 'static' => false, |
||
728 | ); |
||
729 | |||
730 | if (current($line) === 'final') { |
||
731 | $func['final'] = true; |
||
732 | } |
||
733 | |||
734 | if (isset(self::$php_visibility[current($line)])) { |
||
735 | $func['visibility'] = array_shift($line); |
||
736 | } |
||
737 | |||
738 | if (current($line) === 'static') { |
||
739 | $func['static'] = (bool) array_shift($line); |
||
740 | } |
||
741 | |||
742 | if (current($line) === 'function') { |
||
743 | // Remove "function" |
||
744 | array_shift($line); |
||
745 | |||
746 | // Get name |
||
747 | $name = array_shift($line); |
||
748 | |||
749 | // Remove arguments |
||
750 | if (strpos($name, '(') !== false) { |
||
751 | $name = current(explode('(', $name, 2)); |
||
752 | } |
||
753 | |||
754 | // Register the method |
||
755 | $this->current_class['methods'][$name] = array_merge($this->current_doc, $func); |
||
756 | |||
757 | return true; |
||
758 | } |
||
759 | |||
760 | return false; |
||
761 | } |
||
762 | } // End Kodoc |
||
763 |
Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a
@return
annotation as described here.