Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

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