changed git call from https to git readonly
[atutor.git] / mods / phpdoc2 / PhpDocumentor / phpDocumentor / ParserElements.inc
1 <?php\r
2 /**\r
3  * Parser Elements, all classes representing documentable elements\r
4  * \r
5  * phpDocumentor :: automatic documentation generator\r
6  * \r
7  * PHP versions 4 and 5\r
8  *\r
9  * Copyright (c) 2002-2006 Gregory Beaver\r
10  * \r
11  * LICENSE:\r
12  * \r
13  * This library is free software; you can redistribute it\r
14  * and/or modify it under the terms of the GNU Lesser General\r
15  * Public License as published by the Free Software Foundation;\r
16  * either version 2.1 of the License, or (at your option) any\r
17  * later version.\r
18  * \r
19  * This library is distributed in the hope that it will be useful,\r
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
22  * Lesser General Public License for more details.\r
23  * \r
24  * You should have received a copy of the GNU Lesser General Public\r
25  * License along with this library; if not, write to the Free Software\r
26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
27  *\r
28  * @package    phpDocumentor\r
29  * @subpackage ParserElements\r
30  * @author     Gregory Beaver <cellog@php.net>\r
31  * @copyright  2002-2006 Gregory Beaver\r
32  * @license    http://www.opensource.org/licenses/lgpl-license.php LGPL\r
33  * @version    CVS: $Id: ParserElements.inc,v 1.19 2007/04/24 21:30:50 ashnazg Exp $\r
34  * @link       http://www.phpdoc.org\r
35  * @link       http://pear.php.net/PhpDocumentor\r
36  * @see        Parser, WordParser\r
37  * @since      1.1\r
38  */\r
39 \r
40 /**\r
41  * all elements except {@link parserPackagePage} descend from this abstract class\r
42  * @abstract\r
43  * @package phpDocumentor\r
44  * @subpackage ParserElements\r
45  * @author Greg Beaver <cellog@php.net>\r
46  * @since 1.0rc1\r
47  * @version $Id: ParserElements.inc,v 1.19 2007/04/24 21:30:50 ashnazg Exp $\r
48  */\r
49 class parserElement extends parserBase\r
50 {\r
51     /**\r
52      * @var mixed either false or a {@link parserDocBlock}\r
53      */\r
54     var $docblock = false;\r
55     /**\r
56      * name of this element, or include type if element is a {@link parserInclude}\r
57      */\r
58     var $name;\r
59     \r
60     /**\r
61      * @var mixed either false or an array of paths to files with conflicts\r
62      */\r
63     var $conflicts = false;\r
64     \r
65     /**\r
66      * location of this element (filename)\r
67      * @var string\r
68      */\r
69     var $file = '';\r
70     \r
71     /**\r
72      * full path location of this element (filename)\r
73      * @var string\r
74      */\r
75     var $path = '';\r
76     \r
77     /**\r
78      * line number on file where this element stops\r
79      * @since 1.2\r
80      * @var false|integer\r
81      */\r
82     var $endlinenumber = 0;\r
83     \r
84     /**\r
85      * Line number in the source on which this element appears\r
86      * @since 1.2\r
87      * @var false|integer\r
88      */\r
89     var $linenumber = false;\r
90     \r
91     /**\r
92      * @param parserDocBlock\r
93      */\r
94     function setDocBlock($docblock)\r
95     {\r
96         $this->docblock = $docblock;\r
97     }\r
98     \r
99     /**\r
100      * @param string\r
101      */\r
102     function setName($name)\r
103     {\r
104         $this->name = trim($name);\r
105     }\r
106     \r
107     /**\r
108      * Set starting line number\r
109      * @param integer\r
110      */\r
111     function setLineNumber($number)\r
112     {\r
113         $this->linenumber = $number;\r
114     }\r
115     \r
116     /**\r
117      * Sets the ending line number of elements\r
118      * @param integer\r
119      */\r
120     function setEndLineNumber($l)\r
121     {\r
122         $this->endlinenumber = $l;\r
123     }\r
124     \r
125     /**\r
126      * @return integer\r
127      */\r
128     function getLineNumber()\r
129     {\r
130         return $this->linenumber;\r
131     }\r
132     \r
133     /**\r
134      * @return integer\r
135      */\r
136     function getEndLineNumber()\r
137     {\r
138         return $this->endlinenumber;\r
139     }\r
140     \r
141     /** @return string package containing this element */\r
142     function getPackage()\r
143     {\r
144         if ($this->docblock)\r
145         {\r
146             return $this->docblock->package;\r
147         } else return $GLOBALS['phpDocumentor_DefaultPackageName'];\r
148     }\r
149     \r
150     /** @param string */\r
151     function setFile($file)\r
152     {\r
153         $this->file = $file;\r
154     }\r
155     \r
156     /** @param string */\r
157     function setPath($file)\r
158     {\r
159         // look for special windows case\r
160         if(SMART_PATH_DELIMITER === '\\')\r
161             $this->path = strtr($file,'/','\\');\r
162         else\r
163             $this->path = $file;\r
164         $this->path = $file;\r
165     }\r
166     \r
167     /**\r
168      * @return string\r
169      */\r
170     function getName()\r
171     {\r
172         if (!isset($this->name)) return false;\r
173         return $this->name;\r
174     }\r
175     \r
176     /**\r
177      * @return string\r
178      */\r
179     function getFile()\r
180     {\r
181         if (!isset($this->file)) return false;\r
182         return $this->file;\r
183     }\r
184     \r
185     /**\r
186      * @return string\r
187      */\r
188     function getPath()\r
189     {\r
190         if (!isset($this->path)) return false;\r
191         return $this->path;\r
192     }\r
193 }\r
194 \r
195 /**\r
196  * @package phpDocumentor\r
197  * @subpackage ParserElements\r
198  * @author Greg Beaver <cellog@php.net>\r
199  * @since 1.0rc1\r
200  * @version $Id: ParserElements.inc,v 1.19 2007/04/24 21:30:50 ashnazg Exp $\r
201  */\r
202 class parserInclude extends parserElement\r
203 {\r
204     /**\r
205      * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'\r
206      * @var string always 'include'\r
207      */\r
208     var $type = 'include';\r
209 }\r
210 \r
211 /**\r
212  * @package phpDocumentor\r
213  * @subpackage ParserElements\r
214  * @author Greg Beaver <cellog@php.net>\r
215  * @since 1.1\r
216  * @version $Id: ParserElements.inc,v 1.19 2007/04/24 21:30:50 ashnazg Exp $\r
217  */\r
218 class parserGlobal extends parserElement\r
219 {\r
220     /**\r
221      * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'\r
222      * @var string always 'global'\r
223      */\r
224     var $type = 'global';\r
225     \r
226     /**\r
227      * Name of the global's data type\r
228      * @var string\r
229      */\r
230     var $datatype = 'mixed';\r
231 \r
232     /**\r
233      * quick way to link to this element\r
234      * @return mixed converter-specific link to this global variable\r
235      * @param Converter\r
236      * @param string text to display for the link or false for default text\r
237      */\r
238     function getLink(&$c, $text = false, $returnobj = false)\r
239     {\r
240         if ($returnobj)\r
241         {\r
242             return $c->getLink('global ' . $this->name, $this->docblock->package);\r
243         }\r
244         return $c->getGlobalLink($this->name, $this->docblock->package, $this->path, $text);\r
245     }\r
246 \r
247     /**\r
248      * Returns all global variables in other packages that have the same name as this global variable\r
249      * @return mixed false or an array Format: (package => {@link parserGlobal} of conflicting global variable)\r
250      * @param Converter\r
251      */\r
252     function getConflicts(&$c)\r
253     {\r
254         $a = $c->proceduralpages->getGlobalConflicts($this->name);\r
255         unset($a[$this->docblock->package]);\r
256         return $a;\r
257     }\r
258     \r
259     /**\r
260      * Sets the name of the global variable's type\r
261      * @param string\r
262      */\r
263     function setDataType($type)\r
264     {\r
265         $this->datatype = $type;\r
266     }\r
267     \r
268     /**\r
269      * Retrieve converter-specific representation of the data type\r
270      *\r
271      * If the data type is a documented class name, then this function will\r
272      * return a Converter-specific link to that class's documentation, so users\r
273      * can click/browse to the documentation directly from the global variable\r
274      * declaration\r
275      * @return string\r
276      * @param Converter\r
277      */\r
278     function getDataType(&$converter)\r
279     {\r
280         $converted_datatype = $this->datatype;\r
281         if (strpos($this->datatype,'|'))\r
282         {\r
283             $my_types = '';\r
284             $types = explode('|',$this->datatype);\r
285             foreach($types as $returntype)\r
286             {\r
287                 $a = $converter->getLink($returntype);\r
288                 if (is_object($a) && phpDocumentor_get_class($a) == 'classlink')\r
289                 {\r
290                     if (!empty($my_types)) $my_types .= '|';\r
291                     $my_types .= $converter->returnSee($a,$converter->type_adjust($returntype));\r
292                 } else\r
293                 {\r
294                     if (!empty($my_types)) $my_types .= '|';\r
295                     $my_types .= $converter->type_adjust($returntype);\r
296                 }\r
297             }\r
298             $converted_datatype = $my_types;\r
299         } else\r
300         {\r
301             $a = $converter->getLink($this->datatype);\r
302             if (is_object($a) && phpDocumentor_get_class($a) == 'classlink')\r
303             {\r
304                 $converted_datatype = $converter->returnSee($a,$converter->type_adjust($this->datatype));\r
305             } else\r
306             {\r
307                 $converted_dataype = $converter->type_adjust($this->datatype);\r
308             }\r
309         }\r
310         return $converted_datatype;\r
311     }\r
312 \r
313 }\r
314 \r
315 /**\r
316  * @package phpDocumentor\r
317  * @subpackage ParserElements\r
318  * @author Greg Beaver <cellog@php.net>\r
319  * @since 1.0rc1\r
320  * @version $Id: ParserElements.inc,v 1.19 2007/04/24 21:30:50 ashnazg Exp $\r
321  */\r
322 class parserFunction extends parserElement\r
323 {\r
324     /**\r
325      * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'\r
326      * @var string always 'function'\r
327      */\r
328     var $type = 'function';\r
329     /**\r
330      * parameters parsed from function definition.\r
331      *\r
332      * param name may be null, in which case, updateParams() must be called from the Converter\r
333      * @var array Format: array(param name => default value parsed from function definition)\r
334      * @see updateParams()\r
335      */\r
336     var $params = false;\r
337     /**\r
338      * Function returns a reference to an element, instead of a value\r
339      *\r
340      * set to true if function is declared as:\r
341      * <code>\r
342      * function &func(...\r
343      * </code>\r
344      * @var boolean\r
345      */\r
346     var $returnsreference = false;\r
347     /**\r
348      * global declarations parsed from function definition\r
349      *\r
350      * @var array Format: array(globalname1, globalname2,....)\r
351      */\r
352     var $globals = false;\r
353     /**\r
354      * static variable declarations parsed from function definition\r
355      * @var array Format: array(array('name' => staticvar1,'val' => '' or default val of staticvar1),...)\r
356      */\r
357     var $statics = false;\r
358     \r
359     var $source = '';\r
360     \r
361     /**\r
362      * @param string\r
363      * @param string default value parsed from function definition\r
364      * @param boolean indicates whether this parameter has a default value\r
365      * @param null|string class type hint\r
366      */\r
367     function addParam($name, $value, $has_default = true, $typehint = null)\r
368     {\r
369         $this->params[$name] = array($value, $has_default);\r
370         if (isset($typehint))\r
371         {\r
372             $this->params[$name][2] = $typehint;\r
373         }\r
374     }\r
375     \r
376     /**\r
377      * Set the source code.  Always array in PHP 4.3.0+\r
378      * @param string|array\r
379      */\r
380     function addSource($source)\r
381     {\r
382         $this->source = $source;\r
383     }\r
384     \r
385     /**\r
386      * Determine whether the source code has been requested via {@}source}\r
387      * @return boolean\r
388      */\r
389     function hasSource()\r
390     {\r
391         if (is_array($this->source)) return true;\r
392         return strlen($this->source);\r
393     }\r
394     \r
395     /**\r
396      * @return string|array source code ready for highlighting\r
397      */\r
398     function getSource()\r
399     {\r
400         return $this->source;\r
401     }\r
402     \r
403     /**\r
404      * quick way to link to this element\r
405      * @return mixed converter-specific link to this function\r
406      * @param Converter\r
407      * @param string text to display for the link or false for default text\r
408      */\r
409     function getLink($c, $text = false, $returnobj = false)\r
410     {\r
411         if ($returnobj)\r
412         {\r
413             return $c->getLink('function ' . $this->name, $this->docblock->package);\r
414         }\r
415         return $c->getFunctionLink($this->name, $this->docblock->package, $this->path, $text);\r
416     }\r
417 \r
418     /**\r
419      * Returns all functions in other packages that have the same name as this function\r
420      * @return mixed false or an array Format: (package => {@link parserFunction} of conflicting functions)\r
421      * @param Converter\r
422      */\r
423     function getConflicts(&$c)\r
424     {\r
425         $a = $c->proceduralpages->getFuncConflicts($this->name);\r
426         unset($a[$this->docblock->package]);\r
427         return $a;\r
428     }\r
429     \r
430     /**\r
431      * Add all "global $var, $var2" declarations to this function\r
432      * @param array $globals Format: array(globalname1, globalname2,....)\r
433      */\r
434     function addGlobals($globals)\r
435     {\r
436         $this->globals = $globals;\r
437     }\r
438 \r
439     /**\r
440      * Add all "static $var, $var2 = 6" declarations to this function\r
441      * @param array Format: array(varname1, varname2,...)\r
442      * @param array Format: array(default val of var 1, default val of var 2,...) if var 1 has no default, array(default val of var 2,...)\r
443      */\r
444     function addStatics($static,$vals)\r
445     {\r
446         if (count($static))\r
447         {\r
448             $this->statics = array();\r
449             for($i=0;$i<count($static);$i++)\r
450             {\r
451                 if (isset($static[$i]))\r
452                 {\r
453                     $a = '';\r
454                     if (isset($vals[$i])) $a = $vals[$i];\r
455                     $this->statics[] = array('name' => $static[$i],'val' => $a);\r
456                 }\r
457             }\r
458         }\r
459     }\r
460 \r
461     /**\r
462      * @return string default value of param $name\r
463      * @param string\r
464      */\r
465     function getParam ($name)\r
466     {\r
467         if (!isset($this->params[$name])) return false;\r
468         $test = $this->params[$name];\r
469         if ($test[1])\r
470         {\r
471             return $this->params[$name];\r
472         } else\r
473         {\r
474             return false;\r
475         }\r
476     }\r
477 \r
478     /**\r
479      * @return array format: array(array(paramname, default value),...)\r
480      */\r
481     function listParams ()\r
482     {\r
483         if (isset($this->params))\r
484         {\r
485             $ret = array();\r
486             if ($this->params)\r
487             foreach($this->params as $key => $val)\r
488             {\r
489                 if ($val[1])\r
490                 {\r
491                     $arr = array($key,$val[0]);\r
492                     if (isset($val[2]))\r
493                     {\r
494                         $arr[2] = $val[2];\r
495                     }\r
496                     $ret[$key] = $arr;\r
497                 } else\r
498                 {\r
499                     $arr = array($key,false);\r
500                     if (isset($val[2]))\r
501                     {\r
502                         $arr[2] = $val[2];\r
503                     }\r
504                     $ret[$key] = $arr;\r
505                 }\r
506             }\r
507             return $ret;\r
508         } else {\r
509             return array();\r
510         }\r
511     }\r
512     \r
513     /**\r
514      * @return array format: array(array(index, globalname),...)\r
515      */\r
516     function listGlobals ()\r
517     {\r
518         if (isset($this->globals))\r
519         {\r
520             $ret = array();\r
521             if ($this->globals)\r
522             foreach($this->globals as $key => $val)\r
523             {\r
524                 $ret[] = array($key,$val);\r
525             }\r
526             return $ret;\r
527         } else {\r
528             return array();\r
529         }\r
530     }\r
531     \r
532     /**\r
533      * @return array format: array(array(static var name, static var default value),...)\r
534      */\r
535     function listStatics ()\r
536     {\r
537         if (isset($this->statics))\r
538         {\r
539             $ret = array();\r
540             if ($this->statics)\r
541             foreach($this->statics as $key => $val)\r
542             {\r
543                 $ret[] = array($val['name'],$val['val']);\r
544             }\r
545             return $ret;\r
546         } else {\r
547             return array();\r
548         }\r
549     }\r
550     \r
551     /**\r
552      * sets {@link $returnsreference} to true\r
553      */\r
554     function setReturnsReference()\r
555     {\r
556         $this->returnsreference = true;\r
557     }\r
558     \r
559     /**\r
560      * @return boolean returns value of {@link $returnsreference}\r
561      */\r
562     function getReturnsReference()\r
563     {\r
564         return $this->returnsreference;\r
565     }\r
566     \r
567     /**\r
568      * Get a human-friendly description of the function call\r
569      *\r
570      * takes declaration like:\r
571      * <code>\r
572      * /** @returns string ... {rest of docblock}\r
573      * function &func($param1, $param2 = 6,\r
574      *                $param3 = array('20',9 => "heroo"))\r
575      * {...}\r
576      * </code>\r
577      * and returns:\r
578      * string &func( $param1, [$param2 = 6], [$param3 = array('20',9 => "heroo")] )\r
579      * @return string stylized function declaration\r
580      */\r
581     function getFunctionCall()\r
582     {\r
583         $a = '';\r
584         if ($this->getReturnsReference()) $a = '&';\r
585         $function_call = $a.$this->getName() . " ( ";\r
586         $tmp = 0;\r
587         foreach($this->listParams() as $param)\r
588         {\r
589             if ($tmp == 0)\r
590             {\r
591                 $tmp = 1;\r
592             } else {\r
593                 $function_call .= ", ";\r
594             }\r
595             if ($param[1] !== false)\r
596             {\r
597                 $function_call .= "[$param[0] = $param[1]]";\r
598             } else {\r
599                 $function_call .= $param[0];\r
600             }\r
601             $update_params[] = $param[0];\r
602         }\r
603         $function_call .= " )";\r
604         return $function_call;\r
605     }\r
606     \r
607     /**\r
608      * Like getFunctionCall(), but has no English or pre-determined formatting.\r
609      *\r
610      * Much more flexible.\r
611      * @return array Format:\r
612      * <code>\r
613      * array('name' => function name,\r
614      *       'returnsref' => boolean if declared as "function &name()"\r
615      *       'params' => array('type' => data type of parameter,\r
616      *                         'description' => from @param tag,\r
617      *                         'name' => variable name,\r
618      *                         'default' => default value if any))\r
619      * </code>\r
620      * @see getFunctionCall()\r
621      */\r
622     function getIntricateFunctionCall($converter,$paramtags)\r
623     {\r
624         $a = array();\r
625         if ($this->getReturnsReference()) $a['returnsref'] = true;\r
626         $a['name'] = $converter->type_adjust($this->getName());\r
627         $c = $this->listParams();\r
628         foreach($c as $param)\r
629         {\r
630             $b = array();\r
631             $b['type'] = 'mixed';\r
632             if (isset($paramtags[$param[0]]))\r
633             {\r
634                 $b['type'] = $paramtags[$param[0]]['datatype'];\r
635                 $b['description'] = $paramtags[$param[0]]['data'];\r
636                 unset($paramtags[$param[0]]);\r
637             } elseif(isset($paramtags[substr($param[0],1)]))\r
638             {\r
639                 $b['type'] = $paramtags[substr($param[0],1)]['datatype'];\r
640                 $b['description'] = $paramtags[substr($param[0],1)]['data'];\r
641                 unset($paramtags[substr($param[0],1)]);\r
642             }\r
643             if (isset($param[2]))\r
644             {\r
645                 $link = $converter->getLink('object ' . $param[2]);\r
646                 if ($link) {\r
647                     $link = $converter->returnSee($link, $param[2], true);\r
648                     $b['type'] = $link;\r
649                 } else {\r
650                     $b['type'] = $param[2];\r
651                 }\r
652             }\r
653             $b['name'] = $param[0];\r
654             $b['default'] = $converter->postProcess($param[1]);\r
655             $b['hasdefault'] = ($param[1] !== false);\r
656             $a['params'][] = $b;\r
657         }\r
658         // @param tags that don't correspond to actual parameters (like extra function values)\r
659         if (count($paramtags))\r
660         {\r
661             foreach($paramtags as $param)\r
662             {\r
663                 $b = array();\r
664                 $b['type'] = $param['datatype'];\r
665                 $b['description'] = $param['data'];\r
666                 $b['name'] = $param['var'];\r
667                 $b['default'] = '';\r
668                 $b['hasdefault'] = false;\r
669                 $a['params'][] = $b;\r
670             }\r
671         }\r
672         return $a;\r
673     }\r
674 }\r
675 \r
676 /**\r
677  * @package phpDocumentor\r
678  * @subpackage ParserElements\r
679  * @author Greg Beaver <cellog@php.net>\r
680  * @since 1.0rc1\r
681  * @version $Id: ParserElements.inc,v 1.19 2007/04/24 21:30:50 ashnazg Exp $\r
682  */\r
683 class parserClass extends parserElement\r
684 {\r
685     /**\r
686      * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'\r
687      * @var string always 'class'\r
688      */\r
689     var $type = 'class';\r
690     /** @var string\r
691      * @see parserPage::$sourceLocation */\r
692     var $sourceLocation = '';\r
693     /**\r
694      * @var mixed false or contents of extends clause in class declaration\r
695      */\r
696     var $extends = false;\r
697     /**\r
698      * @var array a list of interfaces this class implements\r
699      */\r
700     var $_implements = array();\r
701     /**\r
702      * @var array a list of interfaces this class implements\r
703      * @access private\r
704      */\r
705     var $_modifiers = false;\r
706     /**\r
707      * @var boolean determines whether a class is considered to be an interface\r
708      * @access private\r
709      */\r
710     var $_isInterface = false;\r
711     /**\r
712      * Format: array(file, parent) where parent class is found or false if no parent\r
713      * @var mixed\r
714      */\r
715     var $parent = false;\r
716     /**\r
717      * Used to determine whether a class should be ignored or not.  Helps maintain integrity of parsing\r
718      * @var boolean\r
719      * @see Classes::getParentClass()\r
720      */\r
721     var $ignore = false;\r
722 \r
723     /**\r
724      * @var string same as {@link parserElement::$path}\r
725      */\r
726     var $curfile = false;\r
727     /**\r
728      * @var tutorialLink|false either a link to the tutorial associated with this class, or false\r
729      */\r
730     var $tutorial = false;\r
731     \r
732     /**\r
733      * Get the PHP5+ modifiers for this class\r
734      * (abstract/final/static/private/protected/public)\r
735      * @return array|false\r
736      */\r
737     function getModifiers()\r
738     {\r
739         return $this->_modifiers;\r
740     }\r
741 \r
742     /**\r
743      * Set the PHP5+ modifiers for this class\r
744      * (abstract/final/static/private/protected/public)\r
745      * @param string $m\r
746      */\r
747     function setModifiers($m)\r
748     {\r
749         $this->_modifiers = $m;\r
750     }\r
751     \r
752     /**\r
753      * @param parserTutorial\r
754      * @param Converter\r
755      */\r
756     function addTutorial($t,&$c)\r
757     {\r
758         $this->tutorial = new tutorialLink;\r
759         $this->tutorial->addLink('',$t->path,$t->name,$t->package,$t->subpackage,$t->getTitle($c));\r
760     }\r
761     \r
762     /**\r
763      * Get the associated tutorial for this class, if any\r
764      * @tutorial tutorials.pkg\r
765      * @return parserTutorial\r
766      */\r
767     function getTutorial()\r
768     {\r
769         return $this->tutorial;\r
770     }\r
771     \r
772     /**\r
773      * Returns all classes in other packages that have the same name as this class\r
774      * @return mixed false or an array Format: (package => {@link parserClass} of conflicting classes)\r
775      * @param Converter\r
776      */\r
777     function getConflicts(&$c)\r
778     {\r
779         $a = $c->classes->getConflicts($this->name);\r
780         unset($a[$this->docblock->package]);\r
781         return $a;\r
782     }\r
783     \r
784     /**\r
785      * quick way to link to this element\r
786      * @return mixed converter-specific link to this class\r
787      * @param Converter\r
788      * @param string text to display for the link or false for default text\r
789      */\r
790     function getLink($c, $text = false, $returnobj = false)\r
791     {\r
792         if ($returnobj)\r
793         {\r
794             return $c->getLink('object ' . $this->name, $this->docblock->package);\r
795         }\r
796         return $c->getClassLink($this->name, $this->docblock->package, $this->curfile, $text);\r
797     }\r
798 \r
799     /**\r
800      * @param string parent class name\r
801      * @param string parent class file\r
802      * @param Classes {@link Classes} object currently calling setParent\r
803      * @see Classes::setClassParent()\r
804      */\r
805     \r
806     function setParent($p,$f, &$c)\r
807     {\r
808         $this->parent = array($f, $p);\r
809         $p = $c->getClass($p, $f);\r
810         // inherit package if no @package tag is in the docblock, fixes 591396\r
811         if (!$this->docblock->getExplicitPackage())\r
812         {\r
813             $this->docblock->package = $p->docblock->package;\r
814         }\r
815         if ($this->docblock->package == $p->docblock->package)\r
816         {\r
817             if ($this->docblock->subpackage == '')\r
818             $this->docblock->subpackage = $p->docblock->subpackage;\r
819         }\r
820         $author = $p->docblock->getKeyword('author');\r
821         $version = $p->docblock->getKeyword('version');\r
822         $copyright = $p->docblock->getKeyword('copyright');\r
823         // inherit tags\r
824         if (!$this->docblock->getKeyword('author'))\r
825         {\r
826             if ($author && !is_array($author)) $author = array($author);\r
827             if ($author) $this->docblock->tags['author'] = $author;\r
828         }\r
829         if (!$this->docblock->getKeyword('version'))\r
830         {\r
831             if ($version && !is_array($version)) $version = array($version);\r
832             if ($version) $this->docblock->tags['version'] = $version;\r
833         }\r
834         if (!$this->docblock->getKeyword('copyright'))\r
835         {\r
836             if ($copyright && !is_array($copyright)) $copyright = array($copyright);\r
837             if ($copyright) $this->docblock->tags['copyright'] = $copyright;\r
838         }\r
839         if (!$this->docblock->sdesc)\r
840         {\r
841             $this->docblock->setShortDesc($p->docblock);\r
842             $this->docblock->setDesc($p->docblock);\r
843         } else\r
844         {\r
845             if ($this->docblock->hasInheritDoc())\r
846             {\r
847                 $this->docblock->replaceInheritDoc($p->docblock);\r
848             }\r
849         }\r
850     }\r
851     \r
852     /**\r
853      * @param string $par parent class name (used by {@link Classes::setClassParent()} if parent class not found\r
854      */\r
855     function setParentNoClass($par)\r
856     {\r
857         $this->parent = $par;\r
858     }\r
859     \r
860     /**\r
861      * Use this method to set the type of class to be an interface\r
862      */\r
863     function setInterface()\r
864     {\r
865         $this->_isInterface = true;\r
866     }\r
867     \r
868     /**\r
869      * @return boolean true if this is an interface class\r
870      */\r
871     function isInterface()\r
872     {\r
873         return $this->_isInterface;\r
874     }\r
875     \r
876     /**\r
877      * Use this method to set access modifiers for a class\r
878      * @param array \r
879      */\r
880     function setAccessModifiers($modifiers)\r
881     {\r
882         $this->_modifiers = $modifiers;\r
883     }\r
884     \r
885     /**\r
886      * retrieve object that represents the parent class\r
887      * @param Converter this function will not work before the Conversion stage of parsing\r
888      * @return mixed returns the {@link parserClass} representation of the parent class, or false if no parent class\r
889      */\r
890     function &getParent(&$c)\r
891     {\r
892         $a = false;\r
893         if (!$this->parent) return $a;\r
894         if (is_array($this->parent))\r
895         {\r
896             return $c->classes->getClass($this->parent[1],$this->parent[0]);\r
897         } else return $this->parent;\r
898     }\r
899     \r
900     /**\r
901      * @param Converter this function will not work before the Conversion stage of parsing\r
902      * @return array returns a simple array of method objects\r
903      */\r
904     function getMethods(&$c)\r
905     {\r
906         return $c->classes->getMethods($this->name,$this->curfile);\r
907     }\r
908     \r
909     /**\r
910      * @return mixed {@link parserMethod} or false if not found\r
911      * @param Converter this function will not work before the Conversion stage of parsing\r
912      * @param string method name in this class\r
913      * @param boolean determines whether to search inherited methods as well\r
914      */\r
915     function getMethod(&$c, $name, $inherited = false)\r
916     {\r
917         $ret = $c->classes->getMethod($this->name, $this->curfile, $name);\r
918         if ($ret) return $ret;\r
919         if ($inherited) {\r
920             $x = $this;\r
921             while ($x->parent && is_array($x->parent)) {\r
922                 $par = $x->getParent($c);\r
923                 $x = $par;\r
924                 if ($meth = $x->getMethod($c, $name)) return $meth;\r
925             }\r
926         }\r
927         return false;\r
928     }\r
929     \r
930     /**\r
931      * @return mixed {@link parserVar} or false if not found\r
932      * @param Converter this function will not work before the Conversion stage of parsing\r
933      * @param string var name in this class\r
934      */\r
935     function getVar(&$c, $name)\r
936     {\r
937         return $c->classes->getVar($this->name,$this->curfile,$name);\r
938     }\r
939     \r
940     /**\r
941      * @param Converter this function will not work before the Conversion stage of parsing\r
942      * @return array returns a simple array of method name strings\r
943      */\r
944     function getMethodNames(&$c)\r
945     {\r
946         if (!$c->classes->hasMethods($this->curfile, $this->name)) return array();\r
947         $arr = array();\r
948         $arr1 = $this->getMethods($c);\r
949         for($i=0; $i < count($arr1); $i++)\r
950         {\r
951             $arr[] = $arr1[$i]->name;\r
952         }\r
953         return $arr;\r
954     }\r
955     \r
956     /**\r
957      * @param Converter this function will not work before the Conversion stage of parsing\r
958      * @param string method name\r
959      * @param boolean determines whether to search inherited methods as well\r
960      * @return boolean whether this class has a method of name $name\r
961      */\r
962     function hasMethod(&$c, $name, $inherited = false)\r
963     {\r
964         $ret = $c->classes->hasMethod($this->name, $this->curfile, $name);\r
965         if ($ret) return $ret;\r
966         if ($inherited) {\r
967             $x = $this;\r
968             while ($x->parent && is_array($x->parent)) {\r
969                 $par = $x->getParent($c);\r
970                 $x = $par;\r
971                 if ($x->hasMethod($c, $name)) return true;\r
972             }\r
973         }\r
974         return false;\r
975     }\r
976     \r
977     /**\r
978      * @param Converter this function will not work before the Conversion stage of parsing\r
979      * @param string var name\r
980      * @return boolean whether this class has a var of name $name\r
981      */\r
982     function hasVar(&$c,$name)\r
983     {\r
984         return $c->classes->hasVar($this->name, $this->curfile, $name);\r
985     }\r
986     \r
987     /**\r
988      * @param Converter this function will not work before the Conversion stage of parsing\r
989      * @param string class constant name\r
990      * @return boolean whether this class has a constant of name $name\r
991      */\r
992     function hasConst(&$c,$name)\r
993     {\r
994         return $c->classes->hasConst($this->name, $this->curfile, $name);\r
995     }\r
996     \r
997     /**\r
998      * @param Converter this function will not work before the Conversion stage of parsing\r
999      * @return array returns a simple array of var objects\r
1000      */\r
1001     function getVars(&$c)\r
1002     {\r
1003         return $c->classes->getVars($this->name,$this->curfile);\r
1004     }\r
1005     \r
1006     /**\r
1007      * @param Converter this function will not work before the Conversion stage of parsing\r
1008      * @return array returns a simple array of const objects\r
1009      */\r
1010     function getConsts(&$c)\r
1011     {\r
1012         return $c->classes->getConsts($this->name,$this->curfile);\r
1013     }\r
1014     \r
1015     /**\r
1016      * @param Converter this function will not work before the Conversion stage of parsing\r
1017      * @return array returns a simple array of var name strings\r
1018      */\r
1019     function getVarNames(&$c)\r
1020     {\r
1021         if (!$c->classes->hasVars($this->curfile, $this->name)) return array();\r
1022         $arr = array();\r
1023         $arr1 = $this->getVars($c);\r
1024         for($i=0; $i < count($arr1); $i++)\r
1025         {\r
1026             $arr[] = $arr1[$i]->name;\r
1027         }\r
1028         return $arr;\r
1029     }\r
1030     \r
1031     /**\r
1032      * @param Converter this function will not work before the Conversion stage of parsing\r
1033      * @return array returns a simple array of const name strings\r
1034      */\r
1035     function getConstNames(&$c)\r
1036     {\r
1037         if (!$c->classes->hasConsts($this->curfile, $this->name)) return array();\r
1038         $arr = array();\r
1039         $arr1 = $this->getConsts($c);\r
1040         for($i=0; $i < count($arr1); $i++)\r
1041         {\r
1042             $arr[] = $arr1[$i]->name;\r
1043         }\r
1044         return $arr;\r
1045     }\r
1046     \r
1047     /**\r
1048      * @param Converter this function will not work before the Conversion stage of parsing\r
1049      * @param boolean determines whether overriden methods should be included in the list of inherited methods\r
1050      * @return array returns an array of methods by parent classname array(name => array(method1,method2..),name2 => array(method1....))\r
1051      */\r
1052     function getInheritedMethods(&$c,$override = false)\r
1053     {\r
1054         $x = $oldx = $this;\r
1055         $methods = array();\r
1056         $arr = array();\r
1057         while ($x->parent && is_array($x->parent))\r
1058         {\r
1059             $methods = array_merge($methods,$x->getMethodNames($c));\r
1060             $par = $x->getParent($c);\r
1061             $parmethodnames = $par->getMethodNames($c);\r
1062             $parmethods = $par->getMethods($c);\r
1063             for($i=0; $i<count($parmethodnames); $i++)\r
1064             {\r
1065                 if ($override)\r
1066                 {\r
1067                     if (!in_array($parmethodnames[$i],$methods))\r
1068                     {\r
1069                         // fix for bug 587733\r
1070                         if ($parmethods[$i]->docblock && $parmethods[$i]->docblock->hasaccess && !$c->parseprivate && $parmethods[$i]->docblock->tags['access'][0]->value == 'private')\r
1071                         {\r
1072                             continue;\r
1073                         }\r
1074                         $methods[] = $parmethodnames[$i];\r
1075                         $arr[$par->getName()]['methods'][] = $parmethods[$i];\r
1076                         $arr[$par->getName()]['file'] = $par->curfile;\r
1077                     }\r
1078                 } else\r
1079                 {\r
1080                     // fix for bug 587733\r
1081                     if ($parmethods[$i]->docblock && $parmethods[$i]->docblock->hasaccess && !$c->parseprivate && $parmethods[$i]->docblock->tags['access'][0]->value == 'private')\r
1082                     {\r
1083                         continue;\r
1084                     }\r
1085                     $arr[$par->getName()]['methods'][] = $parmethods[$i];\r
1086                     $arr[$par->getName()]['file'] = $par->curfile;\r
1087                 }\r
1088             }\r
1089             $oldx = $x;\r
1090             $x = &$par;\r
1091         }\r
1092         if (is_a($oldx, 'parserClass') && is_a($oldx->getExtends(true), 'ReflectionClass')) {\r
1093             $extends = $oldx->getExtends(true);\r
1094             foreach ($extends->getMethods() as $method) {\r
1095                 $var = new parserMethod($oldx->getExtends());\r
1096                 if ($method->returnsReference()) {\r
1097                     $var->setReturnsReference();\r
1098                 }\r
1099                 $doc = new parserDocBlock;\r
1100                 foreach ($method->getParameters() as $param) {\r
1101                     $value = $param->isDefaultValueAvailable() ? var_export($param->getDefaultValue(), true) : null;\r
1102                     if ($param->isPassedByReference()) {\r
1103                         $var->addParam('&$' . $param->getName(), $value, $param->isOptional(),\r
1104                             $param->getClass());\r
1105                     } else {\r
1106                         $var->addParam('$' . $param->getName(), $value, $param->isOptional(),\r
1107                             $param->getClass());\r
1108                     }\r
1109                 }\r
1110                 $var->setName($method->getName());\r
1111                 $doc->addPackage('package', $oldx->getPackage());\r
1112                 $var->setDocBlock($doc);\r
1113                 $par = $method->getDeclaringClass();\r
1114                 $var->setLineNumber($par->getStartLine());\r
1115                 $modifiers = array();\r
1116                 if ($method->isPrivate()) {\r
1117                     $modifiers[] = 'private';\r
1118                 }\r
1119                 if ($method->isAbstract()) {\r
1120                     $modifiers[] = 'abstract';\r
1121                 }\r
1122                 if ($method->isFinal()) {\r
1123                     $modifiers[] = 'final';\r
1124                 }\r
1125                 if ($method->isProtected()) {\r
1126                     $modifiers[] = 'protected';\r
1127                 }\r
1128                 if ($method->isPublic()) {\r
1129                     $modifiers[] = 'public';\r
1130                 }\r
1131                 if ($method->isStatic()) {\r
1132                     $modifiers[] = 'static';\r
1133                 }\r
1134                 if ($method->isConstructor()) {\r
1135                     $var->setConstructor();\r
1136                 }\r
1137                 $var->setModifiers($modifiers);\r
1138                 $arr[$oldx->getExtends()]['methods'][] = $var;\r
1139                 $arr[$oldx->getExtends()]['file'] = '(internal)';\r
1140             }\r
1141         }\r
1142         return $arr;\r
1143     }\r
1144     \r
1145     /**\r
1146      * @param Converter this function will not work before the Conversion stage of parsing\r
1147      * @param boolean determines whether overriden vars should be included in the list of inherited vars\r
1148      * @return array returns an array of vars by parent classname array(name => array(var1,var1..),name2 => array(var1....))\r
1149      */\r
1150     function getInheritedVars(&$c,$override = true, $vars = false)\r
1151     {\r
1152         $x = $oldx = $this;\r
1153         $vars = array();\r
1154         $arr = array();\r
1155         while ($x->parent && is_array($x->parent))\r
1156         {\r
1157             $vars = array_merge($vars,$x->getVarNames($c));\r
1158             $par = $x->getParent($c);\r
1159             $parvarnames = $par->getVarNames($c);\r
1160             $parvars = $par->getVars($c);\r
1161             for($i=0; $i<count($parvarnames); $i++)\r
1162             {\r
1163                 if ($override)\r
1164                 {\r
1165                     if (!in_array($parvarnames[$i],$vars))\r
1166                     {\r
1167                         // fix for bug 587733\r
1168                         if ($parvars[$i]->docblock && $parvars[$i]->docblock->hasaccess && !$c->parseprivate && $parvars[$i]->docblock->tags['access'][0]->value == 'private')\r
1169                         {\r
1170                             continue;\r
1171                         }\r
1172                         $vars[] = $parvarnames[$i];\r
1173                         $arr[$par->getName()]['vars'][] = $parvars[$i];\r
1174                         $arr[$par->getName()]['file'] = $par->curfile;\r
1175                     }\r
1176                 } else\r
1177                 {\r
1178                     // fix for bug 587733\r
1179                     if ($parvars[$i]->docblock && $parvars[$i]->docblock->hasaccess && !$c->parseprivate && $parvars[$i]->docblock->tags['access'][0]->value == 'private')\r
1180                     {\r
1181                         continue;\r
1182                     }\r
1183                     $arr[$par->getName()]['vars'][] = $parvars[$i];\r
1184                     $arr[$par->getName()]['file'] = $par->curfile;\r
1185                 }\r
1186             }\r
1187             $oldx = $x;\r
1188             $x = &$par;\r
1189         }\r
1190         if (is_a($oldx, 'parserClass') && is_a($oldx->getExtends(true), 'ReflectionClass')) {\r
1191             $extends = $oldx->getExtends(true);\r
1192             foreach ($extends->getProperties() as $property) {\r
1193                 $var = new parserVar($oldx->getExtends());\r
1194                 $doc = new parserDocBlock;\r
1195                 $var->setName('$' . $property->getName());\r
1196                 $doc->addPackage('package', $oldx->getPackage());\r
1197                 $par = $property->getDeclaringClass();\r
1198                 $var->setLineNumber($par->getStartLine());\r
1199                 $modifiers = array();\r
1200                 if ($property->isPrivate()) {\r
1201                     $modifiers[] = 'private';\r
1202                     $doc->addAccess('private');\r
1203                 }\r
1204                 if ($property->isProtected()) {\r
1205                     $modifiers[] = 'protected';\r
1206                     $doc->addAccess('protected');\r
1207                 }\r
1208                 if ($property->isPublic()) {\r
1209                     $modifiers[] = 'public';\r
1210                     $doc->addAccess('public');\r
1211                 }\r
1212                 $var->setDocBlock($doc);\r
1213                 $var->setModifiers($modifiers);\r
1214                 $arr[$oldx->getExtends()]['vars'][] = $var;\r
1215                 $arr[$oldx->getExtends()]['file'] = '(internal)';\r
1216             }\r
1217         }\r
1218         return $arr;\r
1219     }\r
1220     \r
1221     /**\r
1222      * @param Converter this function will not work before the Conversion stage of parsing\r
1223      * @param boolean determines whether overriden vars should be included in the list of inherited vars\r
1224      * @return array returns an array of consts by parent classname array(name => array(const1,const2..),name2 => array(const1....))\r
1225      */\r
1226     function getInheritedConsts(&$c,$override = false, $consts = false)\r
1227     {\r
1228         $x = $oldx = $this;\r
1229         $consts = array();\r
1230         $arr = array();\r
1231         while ($x->parent && is_array($x->parent))\r
1232         {\r
1233             $consts = array_merge($consts,$x->getConstNames($c));\r
1234             $par = $x->getParent($c);\r
1235             $parvarnames = $par->getConstNames($c);\r
1236             $parvars = $par->getConsts($c);\r
1237             for($i=0; $i<count($parvarnames); $i++)\r
1238             {\r
1239                 if ($override)\r
1240                 {\r
1241                     if (!in_array($parvarnames[$i],$consts))\r
1242                     {\r
1243                         // fix for bug 587733\r
1244                         if ($parvars[$i]->docblock && $parvars[$i]->docblock->hasaccess && !$c->parseprivate && $parvars[$i]->docblock->tags['access'][0]->value == 'private')\r
1245                         {\r
1246                             continue;\r
1247                         }\r
1248                         $consts[] = $parvarnames[$i];\r
1249                         $arr[$par->getName()]['consts'][] = $parvars[$i];\r
1250                         $arr[$par->getName()]['file'] = $par->curfile;\r
1251                     }\r
1252                 } else\r
1253                 {\r
1254                     // fix for bug 587733\r
1255                     if ($parvars[$i]->docblock && $parvars[$i]->docblock->hasaccess && !$c->parseprivate && $parvars[$i]->docblock->tags['access'][0]->value == 'private')\r
1256                     {\r
1257                         continue;\r
1258                     }\r
1259                     $arr[$par->getName()]['consts'][] = $parvars[$i];\r
1260                     $arr[$par->getName()]['file'] = $par->curfile;\r
1261                 }\r
1262             }\r
1263             $oldx = $x;\r
1264             $x = &$par;\r
1265         }\r
1266         if (is_a($oldx, 'parserClass') && is_a($oldx->getExtends(true), 'ReflectionClass')) {\r
1267             $extends = $oldx->getExtends(true);\r
1268             if (!$extends->getConstants()) {\r
1269                 return $arr;\r
1270             }\r
1271             foreach ($extends->getConstants() as $property => $value) {\r
1272                 $var = new parserConst($oldx->getExtends());\r
1273                 $doc = new parserDocBlock;\r
1274                 $var->setName($property);\r
1275                 $var->setValue(var_export($value, true));\r
1276                 $doc->addPackage('package', $oldx->getPackage());\r
1277                 $var->setLineNumber($extends->getStartLine());\r
1278                 $var->setDocBlock($doc);\r
1279                 $arr[$oldx->getExtends()]['consts'][] = $var;\r
1280                 $arr[$oldx->getExtends()]['file'] = '(internal)';\r
1281             }\r
1282         }\r
1283         return $arr;\r
1284     }\r
1285     \r
1286     /**\r
1287      * @param Converter this function will not work before the Conversion stage of parsing\r
1288      * @return array Format: array(parentclassname => parserClass/false if no parent, parentclassname2 => ...)\r
1289      */\r
1290     function getParentClassTree(&$c)\r
1291     {\r
1292         $result = array();\r
1293         $result[$this->name] = $arr = $this->getParent($c);\r
1294         if (is_string($arr)) $result[$arr] = false;\r
1295         while ($arr && is_object($arr))\r
1296         {\r
1297             $result[$arr->name] = $arr->getParent($c);\r
1298             $arr = $arr->getParent($c);\r
1299             if (is_string($arr)) $result[$arr] = false;\r
1300         }\r
1301         return $result;\r
1302     }\r
1303     \r
1304     /**\r
1305      * returns a list of all child classes of this class\r
1306      * @param Converter this function will not work before the Conversion stage of parsing\r
1307      * @return array Format: array(parserClass child1,parserClass child2,...)\r
1308      */\r
1309     function getChildClassList(&$c)\r
1310     {\r
1311         $list = array();\r
1312         $kids = $c->classes->getDefiniteChildren($this->name,$this->curfile);\r
1313         if ($kids)\r
1314         {\r
1315             foreach($kids as $chile => $file)\r
1316             {\r
1317                 $list[] = $c->classes->getClass($chile,$file);\r
1318             }\r
1319         }\r
1320         return $list;\r
1321     }\r
1322     \r
1323     /**\r
1324      * @param string\r
1325      * @see $sourceLocation\r
1326      */\r
1327     function setSourceLocation($sl)\r
1328     {\r
1329         $this->sourceLocation = $sl;\r
1330     }\r
1331     \r
1332     /**\r
1333      * @param Converter\r
1334      * @param boolean\r
1335      * @return string\r
1336      * @see $sourceLocation\r
1337      */\r
1338     function getSourceLocation($c,$pearize = false)\r
1339     {\r
1340         global $_phpDocumentor_options;\r
1341         if (!isset($this->sourceLocation)) \r
1342         {\r
1343             $sl = false;   \r
1344         }\r
1345         else \r
1346         {\r
1347             $sl = $this->sourceLocation;\r
1348             if ($pearize)\r
1349             {\r
1350                 if (strpos($sl,'pear/'))\r
1351                 {\r
1352                     $sl = substr($sl,strpos($sl,'pear/') + 5);\r
1353                 }   \r
1354             }\r
1355         }        \r
1356         return $sl;\r
1357     }\r
1358     \r
1359     /**\r
1360      * @param string\r
1361      * @see $extends\r
1362      */\r
1363     function setExtends($extends)\r
1364     {\r
1365         $this->extends = $extends;\r
1366         if (!class_exists('ReflectionClass') || !class_exists($extends)) {\r
1367             return;\r
1368         }\r
1369         // this may throw an exception.  Hopefully it won't if the class exists\r
1370         $parent = new ReflectionClass($extends);\r
1371         if (!$parent->isInternal()) {\r
1372             return;\r
1373         }\r
1374         $this->extends = $parent;\r
1375     }\r
1376     \r
1377     /**\r
1378      * @param string\r
1379      */\r
1380     function addImplements($implements)\r
1381     {\r
1382         $this->_implements[] = $implements;\r
1383     }\r
1384     \r
1385     /**\r
1386      * @return array\r
1387      */\r
1388     function getImplements()\r
1389     {\r
1390         return $this->_implements;\r
1391     }\r
1392     \r
1393     /**\r
1394      * @return boolean\r
1395      * @see $extends\r
1396      */\r
1397     function getExtends($raw = false)\r
1398     {\r
1399         if (!isset($this->extends)) return false;\r
1400         if (!$raw) {\r
1401             if (is_a($this->extends, 'ReflectionClass')) {\r
1402                 return $this->extends->getName();\r
1403             }\r
1404         }\r
1405         return $this->extends;\r
1406     }\r
1407 }\r
1408 \r
1409 /**\r
1410  * @package phpDocumentor\r
1411  * @subpackage ParserElements\r
1412  * @author Greg Beaver <cellog@php.net>\r
1413  * @since 1.0rc1\r
1414  * @version $Id: ParserElements.inc,v 1.19 2007/04/24 21:30:50 ashnazg Exp $\r
1415  */\r
1416 class parserVar extends parserElement\r
1417 {\r
1418     /**\r
1419      * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'\r
1420      * @var string always 'var'\r
1421      */\r
1422     var $type = 'var';\r
1423     /** @var string class that contains this var */\r
1424     var $class = '';\r
1425     /** @var array */\r
1426     var $_modifiers;\r
1427     \r
1428     /**\r
1429      * @param string\r
1430      */\r
1431     function parserVar($class)\r
1432     {\r
1433         $this->class = $class;\r
1434     }\r
1435     \r
1436     /**\r
1437      * Retrieve the class name\r
1438      * @return string Class name that this var belongs to\r
1439      */\r
1440     function getClass()\r
1441     {\r
1442         return $this->class;\r
1443     }\r
1444     \r
1445     /**\r
1446      * Return a list of access modifiers (static/private/etc.)\r
1447      * @return array\r
1448      */\r
1449     function getModifiers()\r
1450     {\r
1451         return $this->_modifiers;\r
1452     }\r
1453     \r
1454     /**\r
1455      * Return name of the class that contains this method\r
1456      * @return string\r
1457      */\r
1458     function setModifiers($m)\r
1459     {\r
1460         $this->_modifiers = $m;\r
1461     }\r
1462 \r
1463     /**\r
1464      * quick way to link to this element\r
1465      * @return mixed converter-specific link to this var\r
1466      * @param Converter $c\r
1467      * @param string $text text to display for the link or false for default text\r
1468      */\r
1469     function getLink($c, $text = false, $returnobj = false)\r
1470     {\r
1471         if ($returnobj)\r
1472         {\r
1473             return $c->getLink($this->class . '::' . $this->name, $this->docblock->package);\r
1474         }\r
1475         return $c->getVarLink($this->name, $this->class, $this->docblock->package, false, $text);\r
1476     }\r
1477 \r
1478     /**\r
1479      * @param Converter\r
1480      * @return mixed {@link parserVar} representing var this var overrides from the parent class, or false if none\r
1481      */\r
1482     function getOverrides(&$c)\r
1483     {\r
1484         $class = $c->classes->getClass($this->class,$this->path);\r
1485         $par = $class->getParent($c);\r
1486         \r
1487         if (!is_object($par)) {\r
1488             if (is_a($class->getExtends(true), 'ReflectionClass')) {\r
1489                 $pare = $class->getExtends(true);\r
1490                 if (method_exists($pare, 'hasProperty') &&\r
1491                       $pare->hasProperty(substr($this->name, 1))) {\r
1492                     $par = $pare;\r
1493                     $property = $par->getProperty(substr($this->name, 1));\r
1494                     $ret = new parserVar($par->getName());\r
1495                     $doc = new parserDocBlock;\r
1496                     $ret->setName('$' . $property->getName());\r
1497                     $doc->addPackage('package', $class->getPackage());\r
1498                     $ret->setLineNumber($par->getStartLine());\r
1499                     $modifiers = array();\r
1500                     if ($property->isPrivate()) {\r
1501                         if ($c->parseprivate) {\r
1502                             return false;\r
1503                         }\r
1504                         $modifiers[] = 'private';\r
1505                         $doc->addAccess('private');\r
1506                     }\r
1507                     if ($property->isProtected()) {\r
1508                         $modifiers[] = 'protected';\r
1509                         $doc->addAccess('protected');\r
1510                     }\r
1511                     if ($property->isPublic()) {\r
1512                         $modifiers[] = 'public';\r
1513                         $doc->addAccess('public');\r
1514                     }\r
1515                     $ret->setDocBlock($doc);\r
1516                     $ret->setModifiers($modifiers);\r
1517                     return $ret;\r
1518                 }\r
1519             }\r
1520         }\r
1521         while (is_object($par))\r
1522         {\r
1523             if ($par->hasVar($c,$this->name))\r
1524             {\r
1525                 $var = $par->getVar($c,$this->name);\r
1526                 if (!($var->docblock && $var->docblock->hasaccess &&\r
1527                       !$c->parseprivate && $var->docblock->tags['access'][0]->value == 'private')) {\r
1528                     return $var;\r
1529                 }\r
1530             }\r
1531             $par = $par->getParent($c);\r
1532         }\r
1533         \r
1534         return false;\r
1535     }\r
1536 \r
1537     /**\r
1538      * @param Converter\r
1539      * @return array an array of parserVars from ALL child classes that override this var\r
1540      */\r
1541     function getOverridingVars(&$c)\r
1542     {\r
1543         $class = $c->classes->getClass($this->class,$this->path);\r
1544 \r
1545                                 return $this->getOverridingVarsForClass($c, $class);\r
1546     }\r
1547 \r
1548     /**\r
1549      * @param Converter\r
1550                  * @param parserClass\r
1551      * @return array an array of parserVars from ALL child classes that override this var in the given class\r
1552      */\r
1553                 function getOverridingVarsForClass(&$c, &$class)\r
1554                 {\r
1555                         $vars = array();\r
1556                         if (!$class) return $meths;\r
1557                         $kids = $class->getChildClassList($c);\r
1558                         for($i=0; $i<count($kids); $i++)\r
1559                         {\r
1560                                         if ($kids[$i]->hasVar($c, $this->name))\r
1561                                         {\r
1562                                                 $var = $kids[$i]->getVar($c,$this->name);\r
1563                                                 if (!($var->docblock && $var->docblock->hasaccess && !$c->parseprivate && $var->docblock->tags['access'][0]->value == 'private'))\r
1564                                                         $vars[] = $var;\r
1565                                         }\r
1566 \r
1567                                         $vars = array_merge($vars, $this->getOverridingVarsForClass($c, $kids[$i]));\r
1568                         }\r
1569                         return $vars;\r
1570                 }\r
1571 }\r
1572 \r
1573 /**\r
1574  * @package phpDocumentor\r
1575  * @subpackage ParserElements\r
1576  * @author Greg Beaver <cellog@php.net>\r
1577  * @since 1.2.4\r
1578  */\r
1579 class parserConst extends parserElement\r
1580 {\r
1581     /**\r
1582      * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'\r
1583      * @var string always 'const'\r
1584      */\r
1585     var $type = 'const';\r
1586     /** @var string class that contains this var */\r
1587     var $class = '';\r
1588     \r
1589     /**\r
1590      * @param string\r
1591      */\r
1592     function parserConst($class)\r
1593     {\r
1594         $this->class = $class;\r
1595     }\r
1596     \r
1597     /**\r
1598      * Retrieve the class name\r
1599      * @return string Class name that this var belongs to\r
1600      */\r
1601     function getClass()\r
1602     {\r
1603         return $this->class;\r
1604     }\r
1605 \r
1606     /**\r
1607      * quick way to link to this element\r
1608      * @return mixed converter-specific link to this var\r
1609      * @param Converter $c\r
1610      * @param string $text text to display for the link or false for default text\r
1611      */\r
1612     function getLink($c, $text = false, $returnobj = false)\r
1613     {\r
1614         if ($returnobj)\r
1615         {\r
1616             return $c->getLink($this->class . '::'. $this->name, $this->docblock->package);\r
1617         }\r
1618         return $c->getConstLink($this->name, $this->class, $this->docblock->package, false, $text);\r
1619     }\r
1620 }\r
1621 \r
1622 /**\r
1623  * @package phpDocumentor\r
1624  * @subpackage ParserElements\r
1625  * @author Greg Beaver <cellog@php.net>\r
1626  * @since 1.0rc1\r
1627  * @version $Id: ParserElements.inc,v 1.19 2007/04/24 21:30:50 ashnazg Exp $\r
1628  */\r
1629 class parserMethod extends parserFunction\r
1630 {\r
1631     /**\r
1632      * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'\r
1633      * @var string always 'method'\r
1634      */\r
1635     var $type = 'method';\r
1636     /** @var boolean whether this method is a constructor */\r
1637     var $isConstructor = false;\r
1638     /** @var boolean whether this method is a destructor by PEAR standards */\r
1639     var $isDestructor = false;\r
1640     /** @var string class that contains this method */\r
1641     var $class = '';\r
1642     var $_modifiers = array();\r
1643     \r
1644     /**\r
1645      * @param string\r
1646      */\r
1647     function parserMethod($class)\r
1648     {\r
1649         $this->class = $class;\r
1650     }\r
1651     \r
1652     /**\r
1653      * @param string\r
1654      * @param string default value parsed from function definition\r
1655      * @param boolean indicates whether this parameter has a default value\r
1656      * @param null|string class type hint\r
1657      */\r
1658     function addParam($name, $value, $has_default = true, $typehint = null)\r
1659     {\r
1660         $this->params[$name] = array($value, $has_default);\r
1661         if (isset($typehint))\r
1662         {\r
1663             $this->params[$name][2] = $typehint;\r
1664         }\r
1665     }\r
1666     \r
1667     /**\r
1668      * adds "constructor " to start of function call if {@link $isConstructor} is true\r
1669      * @return string\r
1670      * @see parent::getFunctionCall()\r
1671      */\r
1672     function getFunctionCall()\r
1673     {\r
1674         $a = parserFunction::getFunctionCall();\r
1675         if ($this->isConstructor) $a = "constructor $a";\r
1676         return $a;\r
1677     }\r
1678     \r
1679     function getIntricateFunctionCall($converter,$paramtags)\r
1680     {\r
1681         $a = parserFunction::getIntricateFunctionCall($converter,$paramtags);\r
1682         if ($this->isConstructor) $a['constructor'] = true;\r
1683         if ($this->isDestructor) $a['destructor'] = true;\r
1684         return $a;\r
1685     }\r
1686     \r
1687     /**\r
1688      * Return name of the class that contains this method\r
1689      * @return string\r
1690      */\r
1691     function getClass()\r
1692     {\r
1693         return $this->class;\r
1694     }\r
1695     \r
1696     /**\r
1697      * Return name of the class that contains this method\r
1698      * @return string\r
1699      */\r
1700     function getModifiers()\r
1701     {\r
1702         return $this->_modifiers;\r
1703     }\r
1704     \r
1705     /**\r
1706      * Return name of the class that contains this method\r
1707      * @return string\r
1708      */\r
1709     function setModifiers($m)\r
1710     {\r
1711         $this->_modifiers = $m;\r
1712     }\r
1713     \r
1714     /**\r
1715      * @param Converter\r
1716      * @return mixed {@link parserMethod} representing method this method\r
1717      * overrides from the parent class, or false if none\r
1718      */\r
1719     function getOverrides(&$c)\r
1720     {\r
1721         $class = $c->classes->getClass($this->class,$this->path);\r
1722         \r
1723         $par = $class->getParent($c);\r
1724         if (!is_object($par)) {\r
1725             if (is_a($class->getExtends(true), 'ReflectionClass')) {\r
1726                 $pare = $class->getExtends(true);\r
1727                 if (method_exists($pare, 'hasMethod') && $pare->hasMethod($this->name)) {\r
1728                     $par = $pare;\r
1729                     $method = $par->getMethod($this->name);\r
1730                     $var = new parserMethod($par->getName());\r
1731                     if ($method->returnsReference()) {\r
1732                         $var->setReturnsReference();\r
1733                     }\r
1734                     $doc = new parserDocBlock;\r
1735                     foreach ($method->getParameters() as $param) {\r
1736                         $value = ($param->isOptional() && !$method->isInternal()) ? var_export($param->getDefaultValue(), true) : null;\r
1737                         if ($param->isPassedByReference()) {\r
1738                             $var->addParam('&$' . $param->getName(), $value, $param->isOptional(),\r
1739                                 $param->getClass());\r
1740                         } else {\r
1741                             $var->addParam('$' . $param->getName(), $value, $param->isOptional(),\r
1742                                 $param->getClass());\r
1743                         }\r
1744                     }\r
1745                     $var->setName($method->getName());\r
1746                     $doc->addPackage('package', $this->getPackage());\r
1747                     $par = $method->getDeclaringClass();\r
1748                     $var->setLineNumber($par->getStartLine());\r
1749                     $modifiers = array();\r
1750                     if ($method->isPrivate()) {\r
1751                         $modifiers[] = 'private';\r
1752                         $doc->addAccess('private');\r
1753                     }\r
1754                     $blank = new parserStringWithInlineTags;\r
1755                     if ($method->isAbstract()) {\r
1756                         $modifiers[] = 'abstract';\r
1757                         $doc->addKeyword('abstract', $blank);\r
1758                     }\r
1759                     if ($method->isFinal()) {\r
1760                         $modifiers[] = 'final';\r
1761                         $doc->addKeyword('final', $blank);\r
1762                     }\r
1763                     if ($method->isProtected()) {\r
1764                         $modifiers[] = 'protected';\r
1765                         $doc->addAccess('protected');\r
1766                     }\r
1767                     if ($method->isPublic()) {\r
1768                         $modifiers[] = 'public';\r
1769                         $doc->addAccess('public');\r
1770                     }\r
1771                     if ($method->isStatic()) {\r
1772                         $modifiers[] = 'static';\r
1773                         $doc->addKeyword('static', $blank);\r
1774                     }\r
1775                     if ($method->isConstructor()) {\r
1776                         $var->setConstructor();\r
1777                     }\r
1778                     $var->setDocBlock($doc);\r
1779                     $var->setModifiers($modifiers);\r
1780                     return $var;\r
1781                 }\r
1782             }\r
1783         }\r
1784 \r
1785         while (is_object($par))\r
1786         {\r
1787             if ($par->hasMethod($c,$this->name))\r
1788             {\r
1789                 $meth = $par->getMethod($c,$this->name);\r
1790                 if (!($meth->docblock && $meth->docblock->hasaccess &&\r
1791                       !$c->parseprivate && $meth->docblock->tags['access'][0]->value == 'private')) {\r
1792                     return $meth;\r
1793                 }\r
1794             }\r
1795             \r
1796             $par = $par->getParent($c);\r
1797         }\r
1798         \r
1799         return false;\r
1800     }\r
1801     /**\r
1802      * @param Converter\r
1803      * @return mixed {@link parserMethod} representing method this method implements\r
1804      * from an interface, or false if none\r
1805      */\r
1806     function getImplements(&$c)\r
1807     {\r
1808         $class = $c->classes->getClass($this->class,$this->path);\r
1809         \r
1810         $implements = $class->getImplements();\r
1811         if (!count($implements)) {\r
1812             return false;\r
1813         }\r
1814         $ret = array();\r
1815         $haveAlready = array();\r
1816         foreach ($implements as $interface) {\r
1817             $interface_link = $c->getLink('object ' . $interface);\r
1818             if (is_a($interface_link, 'classlink')) {\r
1819                 $par = $c->classes->getClass($interface_link->name,\r
1820                     $interface_link->path);\r
1821                 if (is_object($par)) {\r
1822                     if ($par->hasMethod($c, $this->name, true))\r
1823                     {\r
1824                         $meth = $par->getMethod($c, $this->name);\r
1825                         if (!$meth) {\r
1826                             $meth = $par->getMethod($c, $this->name, true);\r
1827                         }\r
1828                         if (!($meth->docblock && $meth->docblock->hasaccess &&\r
1829                               !$c->parseprivate && $meth->docblock->tags['access'][0]->value == 'private')) {\r
1830                             if (isset($haveAlready[$meth->getClass()])) {\r
1831                                 // this ensures extended interfaces don't cause\r
1832                                 // 2 links to the same method\r
1833                                 if ($haveAlready[$meth->getClass()] == $this->name) {\r
1834                                     continue;\r
1835                                 }\r
1836                             }\r
1837                             $ret[] = $meth;\r
1838                             $haveAlready = array($meth->getClass() => $this->name);\r
1839                         }\r
1840                     }\r
1841                 }\r
1842                 continue;\r
1843             }\r
1844             if (class_exists('ReflectionClass')) {\r
1845                 if (interface_exists($interface)) {\r
1846                     $info = new ReflectionClass($interface);\r
1847                     if (method_exists($info, 'hasMethod') && $info->hasMethod($this->name)) {\r
1848                         $par = $info;\r
1849                         $method = $par->getMethod($this->name);\r
1850                         $var = new parserMethod($par->getName());\r
1851                         if ($method->returnsReference()) {\r
1852                             $var->setReturnsReference();\r
1853                         }\r
1854                         $doc = new parserDocBlock;\r
1855                         foreach ($method->getParameters() as $param) {\r
1856                             $value = $param->isOptional() ? var_export($param->getDefaultValue(), true) : null;\r
1857                             if ($param->isPassedByReference()) {\r
1858                                 $var->addParam('&$' . $param->getName(), $value, $param->isOptional(),\r
1859                                     $param->getClass());\r
1860                             } else {\r
1861                                 $var->addParam('$' . $param->getName(), $value, $param->isOptional(),\r
1862                                     $param->getClass());\r
1863                             }\r
1864                         }\r
1865                         $var->setName($method->getName());\r
1866                         $doc->addPackage('package', $this->getPackage());\r
1867                         $par = $method->getDeclaringClass();\r
1868                         $var->setLineNumber($par->getStartLine());\r
1869                         $modifiers = array();\r
1870                         if ($method->isPrivate()) {\r
1871                             $modifiers[] = 'private';\r
1872                             $doc->addAccess('private');\r
1873                         }\r
1874                         $blank = new parserStringWithInlineTags;\r
1875                         if ($method->isAbstract()) {\r
1876                             $modifiers[] = 'abstract';\r
1877                             $doc->addKeyword('abstract', $blank);\r
1878                         }\r
1879                         if ($method->isFinal()) {\r
1880                             $modifiers[] = 'final';\r
1881                             $doc->addKeyword('final', $blank);\r
1882                         }\r
1883                         if ($method->isProtected()) {\r
1884                             $modifiers[] = 'protected';\r
1885                             $doc->addAccess('protected');\r
1886                         }\r
1887                         if ($method->isPublic()) {\r
1888                             $modifiers[] = 'public';\r
1889                             $doc->addAccess('public');\r
1890                         }\r
1891                         if ($method->isStatic()) {\r
1892                             $modifiers[] = 'static';\r
1893                             $doc->addKeyword('static', $blank);\r
1894                         }\r
1895                         if ($method->isConstructor()) {\r
1896                             $var->setConstructor();\r
1897                         }\r
1898                         $var->setDocBlock($doc);\r
1899                         $var->setModifiers($modifiers);\r
1900                         $ret[] = $var;\r
1901                         continue;\r
1902                     }\r
1903                 }\r
1904             }\r
1905         }\r
1906         \r
1907         return $ret;\r
1908     }\r
1909     \r
1910     /**\r
1911      * quick way to link to this element\r
1912      * @return mixed converter-specific link to this method\r
1913      * @param Converter $c\r
1914      * @param string $text text to display for the link or false for default text\r
1915      */\r
1916     function getLink($c, $text = false, $returnobj = false)\r
1917     {\r
1918         if ($returnobj)\r
1919         {\r
1920             return $c->getLink($this->class . '::' . $this->name . '()', $this->docblock->package);\r
1921         }\r
1922         return $c->getMethodLink($this->name, $this->class, $this->docblock->package, false, $text);\r
1923     }\r
1924 \r
1925     /**\r
1926      * Use this method to tell the parser that this method is the class constructor\r
1927      */\r
1928     function setConstructor()\r
1929     {\r
1930         $this->isConstructor = true;\r
1931     }\r
1932     \r
1933     /**\r
1934      * Use this method to tell the parser that this method is the class constructor\r
1935      */\r
1936     function setDestructor()\r
1937     {\r
1938         $this->isDestructor = true;\r
1939     }\r
1940     \r
1941     /**\r
1942      * @param Converter\r
1943      * @return array an array of parserMethods from child classes that override this method\r
1944      */\r
1945     function getOverridingMethods(&$c)\r
1946     {\r
1947         $class = $c->classes->getClass($this->class,$this->path);\r
1948 \r
1949                                 return $this->getOverridingMethodsForClass($c, $class);\r
1950     }\r
1951 \r
1952     /**\r
1953      * @param Converter\r
1954                  * @param parserClass\r
1955      * @return array an array of parserMethods from ALL child classes that override this method in the given class\r
1956      */\r
1957                 function getOverridingMethodsForClass(&$c, &$class)\r
1958                 {\r
1959                         $meths = array();\r
1960                         if (!$class) return $meths;\r
1961                         $kids = $class->getChildClassList($c);\r
1962                         for($i=0; $i<count($kids); $i++)\r
1963                         {\r
1964                                         if ($kids[$i]->hasMethod($c, $this->name))\r
1965                                         {\r
1966                                                 $meth = $kids[$i]->getMethod($c,$this->name);\r
1967                                                 if (!($meth->docblock && $meth->docblock->hasaccess && !$c->parseprivate && $meth->docblock->tags['access'][0]->value == 'private'))\r
1968                                                         $meths[] = $meth;\r
1969                                         }\r
1970 \r
1971                                         $meths = array_merge($meths, $this->getOverridingMethodsForClass($c, $kids[$i]));\r
1972                         }\r
1973                         return $meths;\r
1974                 }\r
1975 }\r
1976 \r
1977 /**\r
1978  * @package phpDocumentor\r
1979  * @subpackage ParserElements\r
1980  * @author Greg Beaver <cellog@php.net>\r
1981  * @since 1.0rc1\r
1982  * @version $Id: ParserElements.inc,v 1.19 2007/04/24 21:30:50 ashnazg Exp $\r
1983  */\r
1984 class parserDefine extends parserElement\r
1985 {\r
1986     /**\r
1987      * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'\r
1988      * @var string always 'define'\r
1989      */\r
1990     var $type = 'define';\r
1991 \r
1992     /**\r
1993      * quick way to link to this element\r
1994      * @return mixed converter-specific link to this define\r
1995      * @param Converter $c\r
1996      * @param string $text text to display for the link or false for default text\r
1997      */\r
1998     function getLink($c, $text = false, $returnobj = false)\r
1999     {\r
2000         if ($returnobj)\r
2001         {\r
2002             return $c->getLink('constant ' . $this->name, $this->docblock->package);\r
2003         }\r
2004         return $c->getDefineLink($this->name, $this->docblock->package, false, $text);\r
2005     }\r
2006 \r
2007     /**\r
2008      * Returns all defines in other packages that have the same name as this define\r
2009      * @return mixed false or an array Format: (package => {@link parserDefine} of conflicting defines)\r
2010      * @param Converter\r
2011      */\r
2012     function getConflicts(&$c)\r
2013     {\r
2014         $a = $c->proceduralpages->getDefineConflicts($this->name);\r
2015         unset($a[$this->docblock->package]);\r
2016         return $a;\r
2017     }\r
2018     \r
2019 }\r
2020 \r
2021 /**\r
2022  * @package phpDocumentor\r
2023  * @subpackage ParserElements\r
2024  * @author Greg Beaver <cellog@php.net>\r
2025  * @since 1.0rc1\r
2026  * @version $Id: ParserElements.inc,v 1.19 2007/04/24 21:30:50 ashnazg Exp $\r
2027  */\r
2028 class parserPackagePage extends parserStringWithInlineTags\r
2029 {\r
2030     /**\r
2031      * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'\r
2032      * @var string always 'packagepage'\r
2033      */\r
2034     var $type = 'packagepage';\r
2035     /** @var string */\r
2036     var $package = 'default';\r
2037     \r
2038     /**\r
2039      * @param string\r
2040      */\r
2041     function parserPackagePage($package)\r
2042     {\r
2043         $this->package = $package;\r
2044     }\r
2045     \r
2046     /**\r
2047      * @param Converter\r
2048      */\r
2049     function Convert(&$c)\r
2050     {\r
2051         return parent::Convert($c,false);\r
2052     }\r
2053 }\r
2054 \r
2055 /**\r
2056  * @package phpDocumentor\r
2057  * @subpackage ParserElements\r
2058  * @since 1.2\r
2059  */\r
2060 class parserTutorial extends parserPackagePage\r
2061 {\r
2062     /**\r
2063      * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'\r
2064      * @var string always 'tutorial'\r
2065      */\r
2066     var $type = 'tutorial';\r
2067     /** @var string */\r
2068     var $package = 'default';\r
2069     /**\r
2070      * Either cls, pkg, or proc\r
2071      * @var string\r
2072      */\r
2073     var $tutorial_type;\r
2074     /**\r
2075      * The documentable element this tutorial is linked to\r
2076      *\r
2077      * Can be a parserData, parserClass, or nothing for package/subpackage docs\r
2078      */\r
2079     var $linked_element;\r
2080     /**\r
2081      * path to the tutorial page\r
2082      * @var string\r
2083      */\r
2084     var $path;\r
2085     /**\r
2086      * filename minus extension of this tutorial (used for @tutorial tag)\r
2087      * @var string\r
2088      */\r
2089     var $name;\r
2090     /** @var boolean */\r
2091     var $_xml = true;\r
2092     /**\r
2093      * output from tutorialname.ext.ini\r
2094      *\r
2095      * an array generated by {@link phpDocumentor_parse_ini_file()} containing\r
2096      * an index 'Linked Tutorials' with an array of tutorial names in the order\r
2097      * they should appear.  This is used to generate a linked list of tutorials like\r
2098      * {@tutorial phpDocumentor/tags.pkg}\r
2099      * @var array\r
2100      */\r
2101     var $ini = false;\r
2102     /**\r
2103      * link to the next tutorial in a document series, or false if none\r
2104      * @var tutorialLink\r
2105      */\r
2106     var $next = false;\r
2107     /**\r
2108      * link to the previous tutorial in a document series, or false if none\r
2109      * @var tutorialLink\r
2110      */\r
2111     var $prev = false;\r
2112     /**\r
2113      * link to the parent tutorial in a document series, or false if none\r
2114      *\r
2115      * This is used to generate an "Up" or "Home" link like the php manual.\r
2116      * The parent is defined as a tutorial that has a parenttutorialname.ext.ini\r
2117      * file and is not contained by any other tutorial's tutorialname.ext.ini\r
2118      * @var tutorialLink\r
2119      */\r
2120     var $parent = false;\r
2121     /**\r
2122      * links to the child tutorials, or false if none\r
2123      * @var array\r
2124      */\r
2125     var $children = false;\r
2126     \r
2127     /**\r
2128      * @param parserXMLDocBookTag top-level tag (<refentry> for 1.2.0)\r
2129      * @param information about the tutorial file.  Format:\r
2130      *\r
2131      * <pre>\r
2132      * array('tutename' => tutorial name,\r
2133      *       'path' => relative path of tutorial to tutorials/ directory\r
2134      *       'ini' => contents of the tutorial .ini file, if any)\r
2135      * </pre>\r
2136      */\r
2137     function parserTutorial($data, $info)\r
2138     {\r
2139         $this->value = $data;\r
2140         $this->package = $info['package'];\r
2141         $this->subpackage = $info['subpackage'];\r
2142         $this->tutorial_type = $info['tutetype'];\r
2143         $this->name = $info['tutename'];\r
2144         $this->path = $info['path'];\r
2145         $this->ini = $info['ini'];\r
2146     }\r
2147     \r
2148     /**\r
2149      * Retrieve the title of the tutorial, or of any subsection\r
2150      * @param Converter\r
2151      * @param string which subsection to retrieve the title from, if any\r
2152      * @uses parserXMLDocBookTag::getSubSection() retrieve the subsection to\r
2153      *       to get a title from\r
2154      */\r
2155     function getTitle(&$c,$subsection = '')\r
2156     {\r
2157         if (!empty($subsection))\r
2158         {\r
2159             $z = $this->value->getSubSection($c,$subsection);\r
2160             if (!$z)\r
2161             {\r
2162                 addWarning(PDERROR_TUTORIAL_SUBSECTION_NOT_FOUND,$this->name,$subsection);\r
2163                 return $subsection;\r
2164             }\r
2165             return $z->getTitle($c);\r
2166         }\r
2167         return $this->value->getTitle($c);\r
2168     }\r
2169     \r
2170     /**\r
2171      * @param Converter\r
2172      * @param boolean determines whether character data is postprocessed to be\r
2173      *                Converter-friendly or not.\r
2174      */\r
2175     function Convert(&$c, $postprocess = true)\r
2176     {\r
2177         return $this->value->Convert($c, $postprocess);\r
2178     }\r
2179     \r
2180     /**\r
2181      * @uses $parent creates a link to the documentation for the parent tutorial\r
2182      * @param parserTutorial\r
2183      * @param Converter\r
2184      */\r
2185     function setParent($parent,&$c)\r
2186     {\r
2187         $this->parent = new tutorialLink;\r
2188         $this->parent->addLink('', $parent->path, $parent->name, $parent->package, $parent->subpackage, $parent->getTitle($c));\r
2189     }\r
2190     \r
2191     /**\r
2192      * Determine if this parserTutorial object is a child of another\r
2193      * \r
2194      * WARNING:  This method can enter an infinite loop when run on PHP v5.2.1...\r
2195      * see {@link http://bugs.php.net/bug.php?id=40608 PHP Bug #40608}\r
2196      * and {@link http://pear.php.net/bugs/bug.php?id=10289 PEAR Bug #10289}\r
2197      * @param array $parents array of parserTutorials that have child tutorials\r
2198      * @return boolean whether or not this tutorial is a child of the any of the parents\r
2199      */\r
2200     function isChildOf($parents)\r
2201     {\r
2202         // avoid infinite loop PHP bug #40608 in PHP v5.2.1, see PEAR #10289\r
2203         checkForBugCondition('5.2.1', '40608', '10289');\r
2204 \r
2205         foreach($parents as $i => $parent)\r
2206         {\r
2207             if ($parent->path == $this->path) continue;\r
2208             if ($parent->ini && ($parent->package == $this->package) && ($parent->subpackage == $this->subpackage) && ($parent->tutorial_type == $this->tutorial_type))\r
2209             {\r
2210                 foreach($parent->ini['Linked Tutorials'] as $child)\r
2211                 {\r
2212                     if ($child . '.' . $this->tutorial_type == $this->name) return true;\r
2213                 }\r
2214             }\r
2215         }\r
2216     }\r
2217     \r
2218     /**\r
2219      * Retrieve converter-specific link to the parent tutorial's documentation\r
2220      * @param Converter\r
2221      */\r
2222     function getParent(&$c)\r
2223     {\r
2224         if (!$this->parent) return false;\r
2225         return $c->returnSee($this->parent);\r
2226     }\r
2227     \r
2228     /**\r
2229      * @uses $next creates a link to the documentation for the next tutorial\r
2230      * @param parserTutorial\r
2231      * @param Converter\r
2232      */\r
2233     function setNext($next,&$c)\r
2234     {\r
2235         if (phpDocumentor_get_class($next) == 'tutoriallink') return $this->next = $next;\r
2236         $this->next = new tutorialLink;\r
2237         $this->next->addLink('', $next->path, $next->name, $next->package, $next->subpackage, $next->getTitle($c));\r
2238     }\r
2239     \r
2240     /**\r
2241      * Retrieve converter-specific link to the next tutorial's documentation\r
2242      * @param Converter\r
2243      */\r
2244     function getNext(&$c)\r
2245     {\r
2246         if (!$this->next) return false;\r
2247         return $c->returnSee($this->next);\r
2248     }\r
2249     \r
2250     /**\r
2251      * @uses $prev creates a link to the documentation for the previous tutorial\r
2252      * @param parserTutorial\r
2253      * @param Converter\r
2254      */\r
2255     function setPrev($prev,&$c)\r
2256     {\r
2257         if (phpDocumentor_get_class($prev) == 'tutoriallink') return $this->prev = $prev;\r
2258         $this->prev = new tutorialLink;\r
2259         $this->prev->addLink('', $prev->path, $prev->name, $prev->package, $prev->subpackage, $prev->getTitle($c));\r
2260     }\r
2261     \r
2262     /**\r
2263      * Retrieve converter-specific link to the previous tutorial's documentation\r
2264      * @param Converter\r
2265      */\r
2266     function getPrev(&$c)\r
2267     {\r
2268         if (!$this->prev) return false;\r
2269         return $c->returnSee($this->prev);\r
2270     }\r
2271     \r
2272     /**\r
2273      * Get a link to this tutorial, or to any subsection of this tutorial\r
2274      * @param Converter\r
2275      * @param boolean if true, returns a {@link tutorialLink} instead of a string\r
2276      * @param string section name to link to\r
2277      * @return string|tutorialLink\r
2278      */\r
2279     function getLink(&$c,$pure = false,$section = '')\r
2280     {\r
2281         $link = new tutorialLink;\r
2282         $link->addLink($section, $this->path, $this->name, $this->package, $this->subpackage, $this->getTitle($c), $this->category);\r
2283         if ($pure) return $link;\r
2284         return $c->returnSee($link);\r
2285     }\r
2286 }\r
2287 \r
2288 ?>