Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * Outputs documentation in XML DocBook format, in the version expected by
4
 * pear.php.net's documentation team
5
 *
6
 * phpDocumentor :: automatic documentation generator
7
 *
8
 * PHP versions 4 and 5
9
 *
10
 * Copyright (c) 2002-2006 Gregory Beaver
11
 *
12
 * LICENSE:
13
 *
14
 * This library is free software; you can redistribute it
15
 * and/or modify it under the terms of the GNU Lesser General
16
 * Public License as published by the Free Software Foundation;
17
 * either version 2.1 of the License, or (at your option) any
18
 * later version.
19
 *
20
 * This library is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23
 * Lesser General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU Lesser General Public
26
 * License along with this library; if not, write to the Free Software
27
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28
 *
29
 * @package    Converters
30
 * @subpackage XMLDocBook
31
 * @author     Greg Beaver <cellog@php.net>
32
 * @copyright  2002-2006 Gregory Beaver
33
 * @license    http://www.opensource.org/licenses/lgpl-license.php LGPL
34
 * @version    CVS: $Id: XMLDocBookpeardoc2Converter.inc 234423 2007-04-24 21:32:15Z ashnazg $
35
 * @filesource
36
 * @link       http://www.phpdoc.org
37
 * @link       http://pear.php.net/PhpDocumentor
38
 * @since      1.2
39
 */
40
/**
41
 * XML DocBook converter.
42
 * This Converter takes output from the {@link Parser} and converts it to DocBook
43
 * output for PEAR documentation.
44
 *
45
 * This Converter differs from the parent DocBook Converter in that it does not
46
 * recognize the possibility of procedural pages or of functions!  All functions
47
 * must be defined as static methods for namespace purposes.  In addition, all
48
 * constants and global variables for a package are grouped together as per
49
 * peardoc2 requirements.  Include statements are not documented.  If you want
50
 * to document a normal project, don't use the peardoc2 converter, use the
51
 * DocBook converter.
52
 * @package Converters
53
 * @subpackage XMLDocBook
54
 * @author Greg Beaver <cellog@php.net>
55
 * @since 1.2
56
 * @version $Id: XMLDocBookpeardoc2Converter.inc 234423 2007-04-24 21:32:15Z ashnazg $
57
 */
58
class XMLDocBookpeardoc2Converter extends Converter
59
{
60
    /**
61
     * This converter knows about the new root tree processing
62
     * In order to fix PEAR Bug #6389
63
     * @var boolean
64
     */
65
    var $processSpecialRoots = true;
66
    /**
67
     * XMLDocBookConverter wants elements sorted by type as well as alphabetically
68
     * @see Converter::$sort_page_contents_by_type
69
     * @var boolean
70
     */
71
    var $sort_page_contents_by_type = true;
72
    /** @var string */
73
    var $outputformat = 'XML';
74
    /** @var string */
75
    var $name = 'DocBook/peardoc2';
76
    /**
77
     * indexes of elements by package that need to be generated
78
     * @var array
79
     */
80
    var $leftindex = array('classes' => true, 'pages' => false, 'functions' => false, 'defines' => true, 'globals' => true);
81
    /**
82
     * whether a @see is going to be in the {@link $base_dir}, or in a package/subpackage subdirectory of $base_dir
83
     * @var boolean
84
     */
85
    var $local = true;
86
 
87
    /**
88
     * name of current page being converted
89
     * @var string
90
     */
91
    var $page;
92
 
93
    /**
94
     * path of current page being converted
95
     * @var string
96
     */
97
    var $path;
98
 
99
    /**
100
     * name of current class being converted
101
     * @var string
102
     */
103
    var $class;
104
 
105
    /**
106
     * template for the procedural page currently being processed
107
     * @var Template
108
     */
109
    var $page_data;
110
 
111
    /**
112
     * output directory for the current procedural page being processed
113
     * @var string
114
     */
115
    var $page_dir;
116
 
117
    /**
118
     * Constants, used for constants.tpl
119
     * @var array
120
     */
121
    var $_peardoc2_constants = false;
122
 
123
    /**
124
     * Global Variables, used for globals.tpl
125
     * @var array
126
     */
127
    var $_peardoc2_globals = false;
128
 
129
    /**
130
     * target directory passed on the command-line.
131
     * {@link $targetDir} is malleable, always adding package/ and package/subpackage/ subdirectories onto it.
132
     * @var string
133
     */
134
    var $base_dir;
135
 
136
    /**
137
     * output directory for the current class being processed
138
     * @var string
139
     */
140
    var $class_dir;
141
 
142
    /**
143
     * template for the class currently being processed
144
     * @var Template
145
     */
146
    var $class_data;
147
 
148
    /**
149
     * array of converted package page names.
150
     * Used to link to the package page in the left index
151
     * @var array Format: array(package => 1)
152
     */
153
    var $package_pages = array();
154
 
155
    /**
156
     * Contents of the packagename.xml file are stored in this template variable
157
     * @var Smarty
158
     */
159
    var $packagexml;
160
    /**
161
     * controls formatting of parser informative output
162
     *
163
     * Converter prints:
164
     * "Converting /path/to/file.php... Procedural Page Elements... Classes..."
165
     * Since HTMLdefaultConverter outputs files while converting, it needs to send a \n to start a new line.  However, if there
166
     * is more than one class, output is messy, with multiple \n's just between class file output.  This variable prevents that
167
     * and is purely cosmetic
168
     * @var boolean
169
     */
170
    var $juststarted = false;
171
 
172
    /**
173
     * contains all of the template procedural page element loop data needed for the current template
174
     * @var array
175
     */
176
    var $current;
177
 
178
    /**
179
     * contains all of the template class element loop data needed for the current template
180
     * @var array
181
     */
182
    var $currentclass;
183
 
184
    /**
185
     * Pass elements by package, simplifies generation of package.xml/category.xml
186
     */
187
    var $sort_absolutely_everything = true;
188
    /**
189
     * template options.  Currently only 1 recognized option usepear
190
     *
191
     * usepear tells the getLink() function to return a package link to PEAR and PEAR_ERROR if possible, and to link directly
192
     * to the fully-delimited link package#class.method or package#file.method in PEAR style, if possible, even if the
193
     * package is not parsed.  This will allow parsing of separate PEAR packages without parsing the entire thing at once!
194
     * @var array
195
     */
196
    var $template_options = array('usepear' => false);
197
 
198
    var $function_data = array();
199
    var $method_data = array();
200
    var $_write_constants_xml = array();
201
    var $_write_globals_xml = array();
202
    var $sourceloc = '';
203
    /**
204
     * peardoc2 Category
205
     * @var string
206
     */
207
    var $category;
208
    /**
209
     * Used to re-format output so that it's easy for translators to handle
210
     *
211
     * @var XML_Beautifier|false
212
     * @access private
213
     */
214
    var $_beautifier = false;
215
 
216
    /**
217
     * sets {@link $base_dir} to $targetDir
218
     * @see Converter()
219
     */
220
    function XMLDocBookpeardoc2Converter(&$allp, &$packp, &$classes, &$procpages, $po, $pp, $qm, $targetDir, $templateDir, $title)
221
    {
222
        if (!class_exists('XML_Beautifier')) {
223
            @include_once 'XML/Beautifier.php';
224
        }
225
        Converter::Converter($allp, $packp, $classes, $procpages,$po, $pp, $qm, $targetDir, $templateDir, $title);
226
        if (class_exists('XML_Beautifier')) {
227
            require_once 'phpDocumentor/Converters/XML/DocBook/peardoc2/Beautifier.php';
228
            $this->_beautifier = new phpDocumentor_peardoc2_XML_Beautifier;
229
            $this->_beautifier->setOption('indent', ' ');
230
        }
231
        $this->base_dir = $targetDir;
232
    }
233
 
234
    /**
235
     * do that stuff in $template_options
236
     */
237
    function &getLink($expr, $package = false, $packages = false)
238
    {
239
        return Converter::getLink($expr, $package, $packages);
240
    }
241
 
242
    function unmangle($s,$sourcecode)
243
    {
244
        return '<programlisting role="php"><![CDATA[
245
'.$sourcecode.']]></programlisting>';
246
    }
247
 
248
    /**
249
     * Writes a file to target dir, beautify any .xml files first
250
     * @param string filename
251
     * @param string file contents
252
     * @param boolean true if the data is binary and not text
253
     */
254
    function writeFile($file,$data,$binary = false)
255
    {
256
        if ($this->_beautifier && substr($file, -4) == '.xml') {
257
            $ret = $this->_beautifier->formatString($data);
258
            if (PEAR::isError($ret)) {
259
                addWarning(PDERROR_BEAUTIFYING_FAILED, $ret->getMessage());
260
                $ret = $data;
261
            }
262
            $data = $ret;
263
        }
264
        return parent::writeFile($file, $data, $binary);
265
    }
266
 
267
    /**
268
     * Used to convert the {@}example} inline tag in a docblock.
269
     *
270
     * By default, this just wraps ProgramExample
271
     * @see XMLDocBookpeardoc2Converter::exampleProgramExample
272
     * @param string
273
     * @param boolean true if this is to highlight a tutorial <programlisting>
274
     * @return string
275
     */
276
    function exampleProgramExample($example, $tutorial = false, $inlinesourceparse = null/*false*/,
277
                            $class = null/*false*/, $linenum = null/*false*/, $filesourcepath = null/*false*/)
278
    {
279
        return '<example><title>Example</title><programlisting role="php"><![CDATA[' .
280
         $example . ']]></programlisting></example>';
281
        $this->ProgramExample($example, $tutorial, $inlinesourceparse, $class, $linenum, $filesourcepath)
282
        . '</example>';
283
    }
284
 
285
    function writeExample($title, $path, $source)
286
    {
287
        $this->_save_example = array($title, $source);
288
    }
289
 
290
    function getExampleLink($unused, $title)
291
    {
292
        $source = $this->_save_example[1];
293
        return '<para><example><title>' . $title . '</title>' . $source . '</example></para>';
294
    }
295
 
296
    function type_adjust($typename)
297
    {
298
        if (isset($this->template_options['typechanging'][trim($typename)]))
299
        return $this->template_options['typechanging'][trim($typename)];
300
        $a = $this->getLink($typename);
301
        if (is_object($a))
302
        {
303
            if (phpDocumentor_get_class($a) == 'classlink')
304
            return '<classname>'.$typename.'</classname>';
305
            if (phpDocumentor_get_class($a) == 'functionlink' || phpDocumentor_get_class($a) == 'methodlink')
306
            return '<function>'.$typename.'</function>';
307
            if (phpDocumentor_get_class($a) == 'definelink')
308
            return '<constant>'.$typename.'</constant>';
309
            if (phpDocumentor_get_class($a) == 'varlink')
310
            return '<varname>'.$typename.'</varname>';
311
        }
312
        return $typename;
313
    }
314
 
315
    /**
316
     * Writes out the template file of {@link $class_data} and unsets the template to save memory
317
     * @see registerCurrentClass()
318
     * @see parent::endClass()
319
     * @todo move class summary into an array to be written out at the end
320
     *       of parsing each package
321
     */
322
    function endClass()
323
    {
324
        $a = '../';
325
        if (!empty($this->subpackage)) $a .= '../';
326
        if ($this->juststarted)
327
        {
328
            $this->juststarted = false;
329
            phpDocumentor_out("\n");
330
            flush();
331
        }
332
        foreach($this->method_data as $func)
333
        {
334
            $func[0]->assign("phpdocversion",PHPDOCUMENTOR_VER);
335
            $func[0]->assign("phpdocwebsite",PHPDOCUMENTOR_WEBSITE);
336
            $this->setTargetDir($this->base_dir . PATH_DELIMITER . strtolower($this->category) . PATH_DELIMITER . strtolower($this->class_dir . PATH_DELIMITER . str_replace(array('_','.'),array('-','--'),$this->class)));
337
            $this->writefile(strtolower($func[1] ). '.xml','<!-- $' . "Revision$ -->\n" . $func[0]->fetch('method.tpl'));
338
        }
339
        // code below is in packagename.xml handling, see Output()
340
/*        $this->setTargetDir($this->base_dir . PATH_DELIMITER . strtolower($this->category) . PATH_DELIMITER . strtolower($this->class_dir));
341
        $this->writefile(str_replace(array('_','.'),array('-','--'),strtolower($this->class)) . '.xml',$this->class_data->fetch('class.tpl'));*/
342
        unset($this->class_data);
343
    }
344
 
345
    function addSummaryToPackageXml($template_output)
346
    {
347
        $this->packagexml->append('ids',$template_output);
348
    }
349
 
350
    /**
351
     * @param parserClass|false $element is false if this is the end of all conversion
352
     */
353
    function flushPackageXml($element)
354
    {
355
        if (isset($this->packagexml))
356
        {
357
            if (!$element || $element->docblock->package != $this->package) // finished with package
358
            {
359
                if (isset($this->_write_constants_xml[$this->category][$this->package]) &&
360
                    $this->_write_constants_xml[$this->category][$this->package])
361
                {
362
                    $this->packagexml->append('ids',
363
                        '&package.' .
364
                         strtolower($this->category.'.' .
365
                         str_replace(array('_','.'),array('-','--'),$this->package).'.constants;'));
366
                    $this->_write_constants_xml[$this->category][$this->package] = false;
367
                }
368
                if (isset($this->_write_globals_xml[$this->category][$this->package]) &&
369
                    $this->_write_globals_xml[$this->category][$this->package])
370
                {
371
                    $this->packagexml->append('ids',
372
                            '&package.'.strtolower($this->category.'.' .
373
                             str_replace(array('_','.'),array('-','--'),$this->package).'.globals;'));
374
                    $this->_write_globals_xml[$this->category][$this->package] = false;
375
                }
376
                $this->setTargetDir($this->base_dir . PATH_DELIMITER . strtolower($this->category));
377
                $this->writefile(str_replace('_','-',strtolower($this->package)).'.xml',
378
                    '<!-- $' . "Revision$ -->\n" . $this->packagexml->fetch('package.tpl'));
379
                $this->packagexml->clear_all_assign();
380
                if ($element) {
381
                    $this->packagexml->assign('package',$element->docblock->package);
382
                    $this->packagexml->assign('ids',array());
383
                    $this->packagexml->assign('id',$this->getId($element, true));
384
                }
385
            }
386
        } else
387
        {
388
            $this->packagexml = $this->newSmarty();
389
            $this->packagexml->assign('package',$element->docblock->package);
390
            $this->packagexml->assign('ids',array());
391
            $this->packagexml->assign('id',$this->getId($element, true));
392
        }
393
    }
394
 
395
    /**
396
     * @param string
397
     * @param string
398
     * @return string <ulink url="'.$link.'">'.$text.'</ulink>
399
     */
400
    function returnLink($link,$text)
401
    {
402
        return '<ulink url="'.$link.'">'.$text.'</ulink>';
403
    }
404
 
405
    function makeLeft()
406
    {
407
    }
408
 
409
    /**
410
     * Does nothing
411
     */
412
    function formatPkgIndex()
413
    {
414
    }
415
 
416
    /**
417
     * Does nothing
418
     */
419
    function formatIndex()
420
    {
421
    }
422
 
423
    /**
424
     * Does nothing
425
     */
426
    function writeNewPPage($key)
427
    {
428
    }
429
 
430
    /**
431
     * Does nothing
432
     */
433
    function writeSource()
434
    {
435
    }
436
 
437
    /**
438
     * Creates package/lang/categoryname/packagename.xml for each package
439
     */
440
    function formatLeftIndex()
441
    {
442
        $this->makeLeft();
443
    }
444
 
445
    /**
446
     * This function takes an {@link abstractLink} descendant and returns an html link
447
     *
448
     * @param abstractLink a descendant of abstractlink should be passed, and never text
449
     * @param string text to display in the link
450
     * @param boolean this parameter is not used, and is deprecated
451
     * @param boolean determines whether the returned text is enclosed in an <link> tag
452
     */
453
    function returnSee(&$element, $eltext = false, $local = true, $with_a = true)
454
    {
455
        if (!$element) return false;
456
        if (!$eltext)
457
        {
458
            $eltext = '';
459
            switch($element->type)
460
            {
461
                case 'tutorial' :
462
                $eltext = $element->title;
463
                break;
464
                case 'class' :
465
                $eltext = '<classname>'.$element->name.'</classname>';
466
                break;
467
                case 'method' :
468
                $eltext .= '<function>';
469
                case 'var' :
470
                if ($element->type == 'var') $eltext .= '<varname>';
471
                $eltext .= $element->class.'::';
472
                case 'page' :
473
                case 'define' :
474
                if ($element->type == 'define')
475
                $eltext .= '<constant>';
476
                case 'function' :
477
                if ($element->type == 'function')
478
                $eltext .= '<function>';
479
                case 'global' :
480
                default :
481
                $eltext .= $element->name;
482
                if ($element->type == 'function' || $element->type == 'method') $eltext .= '</function>';
483
                if ($element->type == 'var') $eltext .= '</varname>';
484
                if ($element->type == 'define') $eltext .= '</constant>';
485
                break;
486
            }
487
        } elseif (!is_object($element)) {
488
            return false;
489
        } elseif ($element->type == 'method')
490
        {
491
            $eltext = str_replace($element->name . '()', $element->name, $eltext);
492
        }
493
 
494
        if ($element->type == 'page' || $element->type == 'function' || $element->type == 'var')
495
        { // we ignore all procedural pages, instead, constant, function and
496
          // global variable pages are output
497
            return $eltext;
498
        }
499
        if ($element->type == 'class')
500
        {
501
            return '<link linkend="'.$this->getId($element).'-summary">'.$eltext.'</link>';
502
        }
503
        return '<link linkend="'.$this->getId($element).'">'.$eltext.'</link>';
504
    }
505
 
506
    /**
507
     * Get the id value needed to allow linking
508
     * @param mixed descendant of parserElement or parserData/parserPage
509
     * @param boolean true to return the id for the package page
510
     * @see parserElement, parserData, parserPage
511
     * @return string the id value for this element type
512
     */
513
    function getId(&$el, $returnpackage = false)
514
    {
515
        if (phpDocumentor_get_class($el) == 'parserdata')
516
        {
517
            $element = $this->addLink($el->parent);
518
            $elp = $el->parent;
519
        } elseif (!is_a($el,'abstractlink'))
520
        {
521
            $elp = $el;
522
            $element = $this->addLink($el);
523
        } else $element = $el;
524
        $a = '';
525
        if (!empty($element->subpackage))
526
        {
527
            $a = str_replace(array('_','.'),array('-','--'),$element->subpackage).'.';
528
        }
529
        if ($returnpackage) return 'package.'.strtolower($element->category.'.'.str_replace(array('_','.'),array('-','--'),$element->package));
530
        switch ($element->type)
531
        {
532
            case 'page' :
533
            return 'package.'.strtolower($element->category.'.'.str_replace(array('_','.'),array('-','--'),$element->package).'.'.$a.$element->fileAlias);
534
            break;
535
            case 'define' :
536
            return 'package.'.strtolower($element->category.'.'.str_replace(array('_','.'),array('-','--'),$element->package).'.constants.details.'.$element->fileAlias);
537
            break;
538
            case 'global' :
539
            return 'package.'.strtolower($element->category.'.'.str_replace(array('_','.'),array('-','--'),$element->package).'.globals.details.'.$element->fileAlias);
540
            break;
541
            case 'class' :
542
            return 'package.'.strtolower($element->category.'.'.str_replace(array('_','.'),array('-','--'),$element->package).'.'.$a.str_replace(array('_','.'),array('-','--'),$element->name));
543
            break;
544
            case 'function' :
545
            return 'package.'.strtolower($element->category.'.'.str_replace(array('_','.'),array('-','--'),$element->package).'.'.$a.$element->fileAlias.'.'.str_replace('_','-',$element->name));
546
            break;
547
            case 'method' :
548
            return 'package.'.strtolower($element->category.'.'.str_replace(array('_','.'),array('-','--'),$element->package).'.'.$a.str_replace(array('_','.'),array('-','--'),$element->class).'.'.str_replace('_','-',$element->name));
549
            break;
550
            case 'var' :
551
            return 'package.'.strtolower($element->category.'.'.str_replace(array('_','.'),array('-','--'),$element->package).'.'.$a.str_replace(array('_','.'),array('-','--'),$element->class).'-summary.vars.'.str_replace(array('$','_'),array('var--','-'),$element->name));
552
            break;
553
            case 'tutorial' :
554
            return 'package.'.strtolower($element->category.'.'.str_replace(array('_','.'),array('-','--'),$element->package).'.'.$a.str_replace(array('_','.'),array('-','--'),$element->name)).'-tutorial';
555
            break;
556
        }
557
    }
558
 
559
    /**
560
     * Create errors.html template file output
561
     *
562
     * This method takes all parsing errors and warnings and spits them out ordered by file and line number.
563
     * @global ErrorTracker We'll be using it's output facility
564
     */
565
    function ConvertErrorLog()
566
    {
567
        global $phpDocumentor_errors;
568
        $allfiles = array();
569
        $files = array();
570
        $warnings = $phpDocumentor_errors->returnWarnings();
571
        $errors = $phpDocumentor_errors->returnErrors();
572
        $template = &$this->newSmarty();
573
        foreach($warnings as $warning)
574
        {
575
            $file = '##none';
576
            $linenum = 'Warning';
577
            if ($warning->file)
578
            {
579
                $file = $warning->file;
580
                $allfiles[$file] = 1;
581
                $linenum .= ' on line '.$warning->linenum;
582
            }
583
            $files[$file]['warnings'][] = array('name' => $linenum, 'listing' => $warning->data);
584
        }
585
        foreach($errors as $error)
586
        {
587
            $file = '##none';
588
            $linenum = 'Error';
589
            if ($error->file)
590
            {
591
                $file = $error->file;
592
                $allfiles[$file] = 1;
593
                $linenum .= ' on line '.$error->linenum;
594
            }
595
            $files[$file]['errors'][] = array('name' => $linenum, 'listing' => $error->data);
596
        }
597
        $i=1;
598
        $af = array();
599
        foreach($allfiles as $file => $num)
600
        {
601
            $af[$i++] = $file;
602
        }
603
        $allfiles = $af;
604
        usort($allfiles,'strnatcasecmp');
605
        $allfiles[0] = "Post-parsing";
606
        foreach($allfiles as $i => $a)
607
        {
608
            $allfiles[$i] = array('file' => $a);
609
        }
610
        $out = array();
611
        foreach($files as $file => $data)
612
        {
613
            if ($file == '##none') $file = 'Post-parsing';
614
            $out[$file] = $data;
615
        }
616
        $template->assign("files",$allfiles);
617
        $template->assign("all",$out);
618
        $template->assign("title","phpDocumentor Parser Errors and Warnings");
619
        $this->setTargetDir($this->base_dir);
620
        $this->writefile("errors.html",$template->fetch('errors.tpl'));
621
        unset($template);
622
        phpDocumentor_out("\n\nTo view errors and warnings, look at ".$this->base_dir. PATH_DELIMITER . "errors.html\n");
623
        flush();
624
    }
625
 
626
    function postProcess($text)
627
    {
628
        return str_replace("'", '&apos;', htmlentities($text));
629
    }
630
 
631
    function prepareDocBlock(&$element, $nopackage = true)
632
    {
633
        $a = new parserStringWithInlineTags;
634
        $a->add('no exceptions thrown');
635
        if (!$element->docblock->getKeyword('throws')) $element->docblock->addKeyword('throws',$a);
636
        $tags = parent::prepareDocBlock($element,
637
                array('staticvar' => 'note','deprec' => 'deprecated',
638
                      'abstract' => 'abstract','TODO' => 'note', 'link' => 'see',
639
                      'uses' => 'see', 'usedby' => 'see', 'tutorial' => 'see',
640
                      'return' => 'returns', 'access' => false), $nopackage);
641
        $ret = array();
642
        foreach($tags['tags'] as $tag)
643
        {
644
            if ($tag['keyword'] == 'return')
645
            {
646
                // hack because stupid Converter isn't doing its job
647
                $tag['keyword'] = 'returns';
648
            }
649
            $ret[$tag['keyword']][] = $tag;
650
        }
651
        $tags['tags'] = $ret;
652
        $tags['sdesc'] = $this->wordwrap($tags['sdesc']);
653
        return $tags;
654
    }
655
 
656
    function getTutorialId($package,$subpackage,$tutorial,$id,$category)
657
    {
658
        $subpackage = (empty($subpackage) ? '' : '.'.$subpackage);
659
        $id = (empty($id) ? '' : '.'.$id);
660
        return 'package.'.strtolower($category.'.'.$package.$subpackage.str_replace(array('_','.'),array('-','--'),$tutorial).$id);
661
    }
662
 
663
 
664
    /**
665
     * Retrieve a Converter-specific anchor to a segment of a source code file
666
     * parsed via a {@tutorial tags.filesource.pkg} tag.
667
     *
668
     * NOTE: unused
669
     * @param string full path to source file
670
     * @param string name of anchor
671
     * @param string link text, if this is a link
672
     * @param boolean returns either a link or a destination based on this
673
     *                parameter
674
     * @return string link to an anchor, or the anchor
675
     */
676
    function getSourceAnchor($sourcefile,$anchor,$text = '',$link = false)
677
    {
678
        return '';
679
    }
680
 
681
    function Br($input)
682
    {
683
        return "$input\n";
684
    }
685
 
686
    function getCData($value)
687
    {
688
        return '<![CDATA['.$value.']]>';
689
    }
690
 
691
    function ProgramExample($listing, $tutorial = false, $inlinesourceparse = null/*false*/,
692
                            $class = null/*false*/, $linenum = null/*false*/, $filesourcepath = null/*false*/, $origsource = null)
693
    {
694
        if ($origsource !== null) {
695
            $listing = $origsource;
696
        }
697
        if (!tokenizer_ext)
698
        {
699
            $listing = $this->getCData($listing);
700
        }
701
        return '<programlisting role="php">' . $this->getCData($listing) . '</programlisting>';
702
    }
703
 
704
    /**
705
     * Does nothing - use tutorials for DocBook
706
     * @param parserPackagePage
707
     */
708
    function convertPackagePage(&$element)
709
    {
710
    }
711
 
712
    /**
713
     * Convert tutorials for output
714
     * @param parserTutorial
715
     */
716
    function convertTutorial(&$element)
717
    {
718
        $template = &parent::convertTutorial($element);
719
        phpDocumentor_out("\n");
720
        flush();
721
        $x = $element->Convert($this,false);
722
        if ($element->ini)
723
        { // add child tutorial list to the tutorial through a slight hack :)
724
            $subtutorials = '';
725
            $b = '';
726
            if (!empty($element->subpackage)) $b = '.'.$element->subpackage;
727
            foreach($element->ini['Linked Tutorials'] as $child)
728
            {
729
                $subtutorials .= '      &'.$element->category.'.'.$element->package.$b.'.'.str_replace(array('_','.'),array('-','--'),$child).'-'.$element->tutorial_type."-tutorial;\n";
730
            }
731
            $x = str_replace('</refsect1></refentry>','</refsect1>
732
    <refsect1>
733
     <title>Related Docs</title>
734
     <para>
735
'.$subtutorials.
736
'     </para>
737
    </refsect1></refentry>',$x);
738
        }
739
        $template->assign('contents',$x);
740
        $contents = $template->fetch('tutorial.tpl');
741
        $a = '';
742
        if ($element->subpackage) $a = PATH_DELIMITER . $element->subpackage;
743
        phpDocumentor_out("\n");
744
        flush();
745
        $this->setTargetDir($this->base_dir . PATH_DELIMITER . str_replace(array('_','.'),array('-','--'),strtolower($element->category))
746
          . PATH_DELIMITER . strtolower(str_replace(array('_','.'),array('-','--'),$element->package) . $a));
747
        $this->writeFile(str_replace(array('_','.'),array('-','--'),strtolower($element->name)).'-tutorial.xml',
748
            '<!-- $' . "Revision$ -->\n" . $contents);
749
    }
750
 
751
    /**
752
     * Does nothing in this converter
753
     * @param parserVar
754
     */
755
    function convertVar(&$element)
756
    {
757
        return;
758
        $docblock = $this->prepareDocBlock($element);
759
        $b = 'mixed';
760
        if ($element->docblock->var)
761
        {
762
            $b = $element->docblock->var->converted_returnType;
763
        }
764
//        var_dump($this->getFormattedOverrides($element));
765
        if (isset($this->template_options['separatepage']) && $this->template_options['separatepage'])
766
        $this->class_summary->append('vars',array('sdesc' => $docblock['sdesc'],
767
                                               'desc' => $docblock['desc'],
768
                                               'tags' => $docblock['tags'],
769
                                               'var_name' => $this->type_adjust($element->getName()),
770
                                               'var_default' => htmlspecialchars($element->getValue()),
771
                                               'var_type' => $b,
772
                                               'var_overrides' => $this->getFormattedOverrides($element),
773
                                               'line_number' => $element->getLineNumber(),
774
                                               'id' => $this->getId($element)));
775
        else
776
        $this->class_data->append('vars',array('sdesc' => $docblock['sdesc'],
777
                                               'desc' => $docblock['desc'],
778
                                               'tags' => $docblock['tags'],
779
                                               'var_name' => $this->type_adjust($element->getName()),
780
                                               'var_default' => htmlspecialchars($element->getValue()),
781
                                               'var_type' => $b,
782
                                               'var_overrides' => $this->getFormattedOverrides($element),
783
                                               'line_number' => $element->getLineNumber(),
784
                                               'id' => $this->getId($element)));
785
    }
786
 
787
    /**
788
     * Converts class for template output
789
     * @param parserClass
790
     * @uses flushPackageXml() creates packagename.xml file when all classes in
791
     *       a package have been converted
792
     */
793
    function convertClass(&$element)
794
    {
795
        $this->flushPackageXml($element);
796
        parent::convertClass($element);
797
        $docblock = $this->prepareDocBlock($element);
798
        $this->method_data = array();
799
        $this->class_dir = str_replace(array('_','.'),array('-','--'),$element->docblock->package);
800
        $this->package = $element->docblock->package;
801
        $this->category = strtolower($element->docblock->category);
802
        if (!empty($element->docblock->subpackage)) $this->class_dir .= PATH_DELIMITER . $element->docblock->subpackage;
803
        $docblock = $this->prepareDocBlock($element,false);
804
        $this->class_data->assign("sdesc",$docblock['sdesc']);
805
        $this->class_data->assign("desc",$docblock['desc']);
806
        $this->class_data->assign("tags",$docblock['tags']);
807
 
808
        $this->class_data->assign("source_location",$element->getSourceLocation($this,$this->template_options['usepear']));
809
        $this->class_data->assign("id",$this->getId($element));
810
        $this->class_data->assign("method_ids",array());
811
        $this->left[$this->package][] = array('link' => $this->getId($element).'-summary');
812
        if ($t = $element->getTutorial())
813
        {
814
            $this->class_data->append("method_ids",$this->getId($t));
815
        }
816
 
817
        if (isset($this->template_options['separatepage']) && $this->template_options['separatepage'])
818
        {
819
            $this->class_summary = &$this->newSmarty(true);
820
            if ($t = $element->getTutorial())
821
            {
822
                $this->class_summary->assign("tutorial",$this->returnSee($t));
823
            }
824
 
825
            $this->class_summary->assign("class_name",$this->type_adjust($element->getName()));
826
            $this->class_summary->assign("sdesc",$docblock['sdesc']);
827
            $this->class_summary->assign("desc",$docblock['desc']);
828
            $this->class_summary->assign("tags",$docblock['tags']);
829
            $this->class_summary->assign("vars",array());
830
            $this->class_summary->assign("methods",array());
831
            $this->class_summary->assign("package",$element->docblock->package);
832
 
833
            $this->class_summary->assign("children", $this->generateChildClassList($element));
834
            $this->class_summary->assign("class_tree", $this->generateFormattedClassTree($element));
835
            $this->class_summary->assign("conflicts", $this->getFormattedConflicts($element,"classes"));
836
 
837
            $this->class_summary->assign("source_location",$element->getSourceLocation($this,$this->template_options['usepear']));
838
            $this->class_summary->assign("id",$this->getId($element).'-summary');
839
            $this->class_data->append("method_ids",$this->getId($element).'.'.strtolower(str_replace('_','-',$element->getName())).'-summary');
840
            $inherited_methods = $this->getFormattedInheritedMethods($element);
841
            if (!empty($inherited_methods))
842
            {
843
                $this->class_summary->assign("imethods",$inherited_methods);
844
            }
845
            $inherited_vars = $this->getFormattedInheritedVars($element);
846
            // variables are irrelevant in peardoc2
847
            if (false)//!empty($inherited_vars))
848
            {
849
                $this->class_summary->assign("ivars",$inherited_vars);
850
            }
851
            $this->addSummaryToPackageXml($this->class_summary->fetch('class_summary.tpl'));
852
        }
853
        $this->sourceloc = $element->getSourceLocation($this,$this->template_options['usepear']);
854
    }
855
 
856
    /**
857
     * Converts method for template output
858
     * @see prepareDocBlock(), parserMethod::getFunctionCall(), getFormattedDescMethods(), getFormattedOverrides()
859
     * @param parserMethod
860
     */
861
    function convertMethod(&$element)
862
    {
863
        $docblock = $this->prepareDocBlock($element);
864
        $returntype = 'void';
865
        if ($element->docblock->return)
866
        {
867
            $a = $element->docblock->return->Convert($this);
868
            $returntype = $element->docblock->return->converted_returnType;
869
            if ($returntype != $element->docblock->return->returnType)
870
            {
871
                $returntype = "<replaceable>$returntype</replaceable>";
872
            }
873
        }
874
        $params = array();
875
        if (count($element->docblock->params))
876
        foreach($element->docblock->params as $param => $val)
877
        {
878
            $a = $val->Convert($this);
879
            $b = explode(' ',$a);
880
            $c = '';
881
            foreach($b as $blah) {
882
                if (!empty($c)) {
883
                    $c .= ' ';
884
                }
885
                $c .= str_replace(array('true', 'false', 'null'), array('&true;', '&false;', '&null;'), $blah);
886
            }
887
            $params[$param] = array("var" => $param,"datatype" => str_replace(array('true', 'false', 'null'), array('&true;', '&false;', '&null;'),
888
                $val->returnType), "cdatatype" => $val->converted_returnType,"data" => $this->wordwrap($c));
889
        }
890
 
891
        $call = $element->getIntricateFunctionCall($this, $params);
892
        if (isset($call['params']))
893
        {
894
            foreach($call['params'] as $i => $param)
895
            {
896
                if (!is_string($call['params'][$i]['default']))
897
                {
898
                    continue;
899
                }
900
                $call['params'][$i]['default'] = str_replace(array('true', 'false', 'null'), array('&true;', '&false;', '&null;'), $param['default']);
901
            }
902
        }
903
        $this->packagexml->append('ids','&'.$this->getId($element).';');
904
        $this->class_data->append('method_ids',$this->getId($element));
905
        $this->class_summary->append('methods',array('id' => $this->getId($element),
906
                                                  'sdesc' => $docblock['sdesc'],
907
                                                  'desc' => $docblock['desc'],
908
                                                  'tags' => $docblock['tags'],
909
                                                  'is_constructor' => $element->isConstructor,
910
                                                  'function_name' => $element->getName(),
911
                                                  'function_return' => $returntype,
912
                                                  'function_call' => $call,
913
                                                  'descmethod' => $this->getFormattedDescMethods($element),
914
                                                  'method_overrides' => $this->getFormattedOverrides($element),
915
                                                  'line_number' => $element->getLineNumber(),
916
                                                  'params' => $params));
917
        $this->method_data[$i = count($this->method_data) - 1][0] = &$this->newSmarty(true);
918
        $this->method_data[$i][1] = str_replace(array('_','.'),array('-','--'),$element->getName());
919
        $this->method_data[$i][0]->assign('class',$this->class);
920
        $this->method_data[$i][0]->assign('source_location',$this->returnSee($this->getLink(basename($this->curpage->getFile())),$this->sourceloc));
921
        $this->method_data[$i][0]->assign('sdesc',$docblock['sdesc']);
922
        $this->method_data[$i][0]->assign('desc',$docblock['desc']);
923
        $this->method_data[$i][0]->assign('tags',$docblock['tags']);
924
        $this->method_data[$i][0]->assign('function_name',$element->getName());
925
        $this->method_data[$i][0]->assign('function_return',$returntype);
926
        $this->method_data[$i][0]->assign('function_call',$call);
927
        $this->method_data[$i][0]->assign('descmethod',$this->getFormattedDescMethods($element));
928
        $this->method_data[$i][0]->assign('method_overrides',$this->getFormattedOverrides($element));
929
        $this->method_data[$i][0]->assign('params',$params);
930
        $this->method_data[$i][0]->assign('id',$this->getId($element));
931
    }
932
 
933
    /**
934
     * Converts function for template output - does nothing in peardoc2!
935
     * @param parserFunction
936
     */
937
    function convertFunction(&$element)
938
    {
939
/*        parent::convertFunction($element);
940
        $docblock = $this->prepareDocBlock($element);
941
        $fname = $element->getName();
942
        $params = array();
943
        if (count($element->docblock->params))
944
        foreach($element->docblock->params as $param => $val)
945
        {
946
            $a = $val->Convert($this);
947
            $params[$param] = array("var" => $param,"datatype" => $val->converted_returnType,"data" => $a);
948
        }
949
        $returntype = 'void';
950
        if ($element->docblock->return)
951
        {
952
            $a = $element->docblock->return->Convert($this);
953
            $returntype = $element->docblock->return->converted_returnType;
954
        }
955
 
956
        $this->page_data->append("function_ids",$this->getId($element));
957
        $this->page_summary->append("function_ids",$this->getId($element));
958
        $this->page_summary->append('functions',array('id' => $this->getId($element),
959
                                                   'sdesc' => $docblock['sdesc'],
960
                                                   'desc' => $docblock['desc'],
961
                                                   'tags' => $docblock['tags'],
962
                                                   'function_name' => $element->getName(),
963
                                                   'line_number' => $element->getLineNumber(),
964
                                                   'function_return' => $returntype,
965
                                                   'function_call' => $element->getIntricateFunctionCall($this,$params),
966
                                                   'function_conflicts' => $this->getFormattedConflicts($element,'functions'),
967
                                                   'params' => $params));
968
        $this->function_data[$i = count($this->function_data) - 1][0] = $this->newSmarty(true);
969
        $this->function_data[$i][1] = $element->getName();
970
        $this->function_data[$i][0]->assign('sdesc',$docblock['sdesc']);
971
        $this->function_data[$i][0]->assign('desc',$docblock['desc']);
972
        $this->function_data[$i][0]->assign('tags',$docblock['tags']);
973
        $this->function_data[$i][0]->assign('function_name',$fname);
974
        $this->function_data[$i][0]->assign('line_number',$element->getLineNumber());
975
        $this->function_data[$i][0]->assign('function_return',$returntype);
976
        $this->function_data[$i][0]->assign('function_call',$element->getIntricateFunctionCall($this,$params));
977
        $this->function_data[$i][0]->assign('function_conflicts',$this->getFormattedConflicts($element,"functions"));
978
        $this->function_data[$i][0]->assign('params',$params);
979
        $this->function_data[$i][0]->assign('source_location',$this->returnSee($this->getLink(basename($this->curpage->getFile())),$this->sourceloc));
980
        $this->function_data[$i][0]->assign('id',$this->getId($element));*/
981
    }
982
 
983
    /**
984
     * Converts include elements for template output
985
     *
986
     * Completely ignored by this converter
987
     * @param parserInclude
988
     */
989
    function convertInclude(&$element)
990
    {
991
/*        parent::convertInclude($element, array('include_file'    => '-'.strtr($element->getValue(),array('"' => '', "'" => '','.' => '-'))));
992
        $docblock = $this->prepareDocBlock($element);
993
        $per = $this->getIncludeValue($element->getValue(), $element->getPath());
994
        $this->page_summary->append('includes',array('sdesc' => $docblock['sdesc'],
995
                                                   'desc' => $docblock['desc'],
996
                                                  'tags' => $docblock['tags'],
997
                                                  'utags' => $docblock['utags'],
998
                                                  'include_name'     => $element->getName(),
999
                                                  'include_value'    => $per,
1000
                                                  'line_number' => $element->getLineNumber(),
1001
                                                  'include_file'    => '-'.strtr($element->getValue(),array('"' => '', "'" => '','.' => '-'))));*/
1002
    }
1003
 
1004
    /**
1005
     * Converts defines for template output
1006
     * @see prepareDocBlock(), getFormattedConflicts()
1007
     * @param parserDefine
1008
     */
1009
    function convertDefine(&$element)
1010
    {
1011
        $docblock = $this->prepareDocBlock($element);
1012
        $this->_appendDefines(array('sdesc' => $docblock['sdesc'],
1013
                                   'desc' => $docblock['desc'],
1014
                                   'tags' => $docblock['tags'],
1015
                                   'name'     => $this->postProcess($element->getName()),
1016
                                   'value'    => $this->postProcess($element->getValue()),
1017
                                   'conflicts'    => $this->getFormattedConflicts($element,"defines"),
1018
                                   'line_number' => $element->getLineNumber(),
1019
                                   'id' => $this->getId($element)));
1020
    }
1021
 
1022
    /**
1023
     * Append the constant information to the Smarty information
1024
     *
1025
     * Uses category, package, and current file to organize constants defined
1026
     * in a package for the constants.xml output file
1027
     * @param array
1028
     * @uses $_peardoc2_constants appends $define to them
1029
     * @access private
1030
     */
1031
    function _appendDefines($define)
1032
    {
1033
        if (!isset($this->_peardoc2_constants[$this->category][$this->package][$this->sourceloc]))
1034
        {
1035
            $this->_peardoc2_constants[$this->category][$this->package][$this->sourceloc]['name'] =
1036
                $this->sourceloc;
1037
            $this->_peardoc2_constants[$this->category][$this->package][$this->sourceloc]['page'] =
1038
                $this->page;
1039
        }
1040
        $this->_write_constants_xml[$this->category][$this->package] = true;
1041
        $this->_peardoc2_constants[$this->category][$this->package][$this->sourceloc]['defines'][] = $define;
1042
    }
1043
 
1044
    /**
1045
     * Converts global variables for template output
1046
     * @param parserGlobal
1047
     * @see prepareDocBlock(), getFormattedConflicts()
1048
     */
1049
    function convertGlobal(&$element)
1050
    {
1051
        $docblock = $this->prepareDocBlock($element);
1052
        $value = $this->getGlobalValue($element->getValue());
1053
        if ($value == $element->getValue())
1054
        {
1055
            $value = $this->ProgramExample($value);
1056
        } else
1057
        {
1058
            $value = $this->getGlobalValue('<![CDATA[' .$element->getValue() . ']]>');
1059
        }
1060
        $this->_appendGlobals(array('sdesc' => $docblock['sdesc'],
1061
                                   'desc' => $docblock['desc'],
1062
                                   'tags' => $docblock['tags'],
1063
                                   'name'     => $this->postProcess($element->getName()),
1064
                                   'link'    => $element->getName(),
1065
                                   'value'    => $value,
1066
                                   'type' => $element->getDataType($this),
1067
                                   'line_number' => $element->getLineNumber(),
1068
                                   'conflicts'    => $this->getFormattedConflicts($element,"global variables"),
1069
                                   'id' => $this->getId($element)));
1070
    }
1071
 
1072
    /**
1073
     * Append the global variable information to the Smarty information
1074
     *
1075
     * Uses category, package, and current file to organize globals defined
1076
     * in a package for the globals.xml output file
1077
     * @param array
1078
     * @uses $_peardoc2_globals appends $global to them
1079
     * @access private
1080
     */
1081
    function _appendGlobals($global)
1082
    {
1083
        if (!isset($this->_peardoc2_globals[$this->category][$this->package][$this->sourceloc]))
1084
        {
1085
            $this->_peardoc2_globals[$this->category][$this->package][$this->sourceloc]['name'] =
1086
                $this->sourceloc;
1087
            $this->_peardoc2_globals[$this->category][$this->package][$this->sourceloc]['page'] =
1088
                $this->page;
1089
        }
1090
        $this->_write_globals_xml[$this->category][$this->package] = true;
1091
        $this->_peardoc2_globals[$this->category][$this->package][$this->sourceloc]['globals'][] = $global;
1092
    }
1093
 
1094
    /**
1095
     * converts procedural pages for template output
1096
     * @see prepareDocBlock(), getClassesOnPage()
1097
     * @param parserData
1098
     */
1099
    function convertPage(&$element)
1100
    {
1101
        parent::convertPage($element);
1102
        $this->juststarted = true;
1103
        $this->page_dir = $element->parent->package;
1104
        $this->page = $this->getPageName($element->parent);
1105
        $this->category = strtolower($element->parent->category);
1106
        $this->sourceloc = $element->parent->getSourceLocation($this,true);
1107
        if (!empty($element->parent->subpackage)) $this->page_dir .= PATH_DELIMITER . $element->parent->subpackage;
1108
        // registering stuff on the template
1109
    }
1110
 
1111
    function getPageName(&$element)
1112
    {
1113
        return str_replace(array('/','_','.'),array('-','-','---'),$element->getSourceLocation($this,true));
1114
    }
1115
 
1116
    /**
1117
     * returns an array containing the class inheritance tree from the root object to the class
1118
     *
1119
     * @param parserClass    class variable
1120
     * @return array Format: array(root,child,child,child,...,$class)
1121
     * @uses parserClass::getParentClassTree()
1122
     */
1123
 
1124
    function generateFormattedClassTree($class)
1125
    {
1126
        $tree = $class->getParentClassTree($this);
1127
        $out = '';
1128
        if (count($tree) - 1)
1129
        {
1130
            $result = array($class->getName());
1131
            $parent = $tree[$class->getName()];
1132
            while ($parent)
1133
            {
1134
                if (is_string($parent)) {
1135
                    $result[] = $parent;
1136
                    break;
1137
                }
1138
                $subpackage = $parent->docblock->subpackage;
1139
                $package = $parent->docblock->package;
1140
                $x = $parent;
1141
                if (is_object($parent))
1142
                $x = $parent->getLink($this);
1143
                if (!$x) $x = $parent->getName();
1144
                $result[] =
1145
                    $x;
1146
                if (is_object($parent))
1147
                $parent = $tree[$parent->getName()];
1148
                elseif (isset($tree[$parent]))
1149
                $parent = $tree[$parent];
1150
            }
1151
            return array_reverse($result);
1152
        } else
1153
        {
1154
            return array($class->getName());
1155
        }
1156
    }
1157
 
1158
    /**
1159
     * returns a list of child classes
1160
     *
1161
     * @param parserClass class variable
1162
     * @uses parserClass::getChildClassList()
1163
     */
1164
 
1165
    function generateChildClassList($class)
1166
    {
1167
        $kids = $class->getChildClassList($this);
1168
        $list = array();
1169
        if (count($kids))
1170
        {
1171
            for($i=0; $i<count($kids); $i++)
1172
            {
1173
                $lt['link'] = '<link linkend="'.$this->getId($kids[$i]) . '-summary">'. $kids[$i]->getName().'</link>';
1174
                $lt['sdesc'] = $kids[$i]->docblock->getSDesc($this);
1175
                $list[] = $lt;
1176
            }
1177
        } else return false;
1178
        return $list;
1179
    }
1180
 
1181
    /** @access private */
1182
    function sortVar($a, $b)
1183
    {
1184
        return strnatcasecmp($a->getName(),$b->getName());
1185
    }
1186
 
1187
    /** @access private */
1188
    function sortMethod($a, $b)
1189
    {
1190
        if ($a->isConstructor) return -1;
1191
        if ($b->isConstructor) return 1;
1192
        return strnatcasecmp($a->getName(),$b->getName());
1193
    }
1194
 
1195
    /**
1196
     * returns a template-enabled array of class trees
1197
     *
1198
     * @param    string    $package    package to generate a class tree for
1199
     * @see $roots, HTMLConverter::getRootTree()
1200
     */
1201
    function generateFormattedClassTrees($package)
1202
    {
1203
        if (!isset($this->roots['normal'][$package]) &&
1204
              !isset($this->roots['special'][$package])) {
1205
            return array();
1206
        }
1207
        $trees = array();
1208
        if (isset($this->roots['normal'][$package])) {
1209
            $roots = $this->roots['normal'][$package];
1210
            for($i=0;$i<count($roots);$i++)
1211
            {
1212
                $root = $this->classes->getClassByPackage($roots[$i], $package);
1213
                if ($root && $root->isInterface()) {
1214
                    continue;
1215
                }
1216
                $trees[] = array('class' => $roots[$i],'class_tree' => "<ul>\n".$this->getRootTree($this->getSortedClassTreeFromClass($roots[$i],$package,''),$package)."</ul>\n");
1217
            }
1218
        }
1219
        if (isset($this->roots['special'][$package])) {
1220
            $roots = $this->roots['special'][$package];
1221
            foreach ($roots as $parent => $classes) {
1222
                $thistree = '';
1223
                foreach ($classes as $classinfo) {
1224
                    $root = $this->classes->getClassByPackage($classinfo, $package);
1225
                    if ($root && $root->isInterface()) {
1226
                        continue;
1227
                    }
1228
                    $thistree .=
1229
                        $this->getRootTree(
1230
                            $this->getSortedClassTreeFromClass(
1231
                                $classinfo,
1232
                                $package,
1233
                                ''),
1234
                            $package,
1235
                            true);
1236
                }
1237
                if (!$thistree) {
1238
                    continue;
1239
                }
1240
                $trees[] = array(
1241
                    'class' => $parent,
1242
                    'class_tree' => "<ul>\n" . $thistree . "</ul>\n"
1243
                );
1244
            }
1245
        }
1246
        return $trees;
1247
    }
1248
 
1249
    /**
1250
     * returns a template-enabled array of interface inheritance trees
1251
     *
1252
     * @param    string    $package    package to generate a class tree for
1253
     * @see $roots, HTMLConverter::getRootTree()
1254
     */
1255
    function generateFormattedInterfaceTrees($package)
1256
    {
1257
        if (!isset($this->roots['normal'][$package]) &&
1258
              !isset($this->roots['special'][$package])) {
1259
            return array();
1260
        }
1261
        $trees = array();
1262
        if (isset($this->roots['normal'][$package])) {
1263
            $roots = $this->roots['normal'][$package];
1264
            for($i=0;$i<count($roots);$i++)
1265
            {
1266
                $root = $this->classes->getClassByPackage($roots[$i], $package);
1267
                if ($root && !$root->isInterface()) {
1268
                    continue;
1269
                }
1270
                $trees[] = array('class' => $roots[$i],'class_tree' => "<ul>\n".$this->getRootTree($this->getSortedClassTreeFromClass($roots[$i],$package,''),$package)."</ul>\n");
1271
            }
1272
        }
1273
        if (isset($this->roots['special'][$package])) {
1274
            $roots = $this->roots['special'][$package];
1275
            foreach ($roots as $parent => $classes) {
1276
                $thistree = '';
1277
                foreach ($classes as $classinfo) {
1278
                    $root = $this->classes->getClassByPackage($classinfo, $package);
1279
                    if ($root && !$root->isInterface()) {
1280
                        continue;
1281
                    }
1282
                    $thistree .=
1283
                        $this->getRootTree(
1284
                            $this->getSortedClassTreeFromClass(
1285
                                $classinfo,
1286
                                $package,
1287
                                ''),
1288
                            $package,
1289
                            true);
1290
                }
1291
                if (!$thistree) {
1292
                    continue;
1293
                }
1294
                $trees[] = array(
1295
                    'class' => $parent,
1296
                    'class_tree' => "<ul>\n" . $thistree . "</ul>\n"
1297
                );
1298
            }
1299
        }
1300
        return $trees;
1301
    }
1302
 
1303
    /**
1304
     * return formatted class tree for the Class Trees page
1305
     *
1306
     * @param array $tree output from {@link getSortedClassTreeFromClass()}
1307
     * @param string $package  package
1308
     * @param boolean $nounknownparent if true, an object's parent will not be checked
1309
     * @see Classes::$definitechild, generateFormattedClassTrees()
1310
     * @return string
1311
     */
1312
    function getRootTree($tree, $package, $noparent = false)
1313
    {
1314
        if (!$tree) return '';
1315
        $my_tree = '';
1316
        $cur = '#root';
1317
        $lastcur = array(false);
1318
        $kids = array();
1319
        $dopar = false;
1320
        if (!$noparent && $tree[$cur]['parent'])
1321
        {
1322
            $dopar = true;
1323
            if (!is_object($tree[$cur]['parent']))
1324
            {
1325
//                debug("parent ".$tree[$cur]['parent']." not found");
1326
                $my_tree .= '<listitem>' . $tree[$cur]['parent'] .'<itemizedlist>';
1327
            }
1328
            else
1329
            {
1330
//                        debug("parent ".$this->returnSee($tree[$cur]['parent'], false, false)." in other package");
1331
                $my_tree .= '<listitem>' . $this->returnSee($tree[$cur]['parent'], false, false);
1332
                if ($tree[$cur]['parent']->package != $package) $my_tree .= ' <emphasis>(Different package)</emphasis><itemizedlist>';
1333
            }
1334
        }
1335
        do
1336
        {
1337
//            fancy_debug($cur,$lastcur,$kids);
1338
            if (count($tree[$cur]['children']))
1339
            {
1340
//                debug("$cur has children");
1341
                if (!isset($kids[$cur]))
1342
                {
1343
//                    debug("set $cur kids");
1344
                    $kids[$cur] = 1;
1345
                    $my_tree .= '<listitem>'.$this->returnSee($tree[$cur]['link'], false, false);
1346
                    $my_tree .= '<itemizedlist>'."\n";
1347
                }
1348
                array_push($lastcur,$cur);
1349
                list(,$cur) = each($tree[$cur]['children']);
1350
//                var_dump('listed',$cur);
1351
                if ($cur)
1352
                {
1353
                    $cur = $cur['package'] . '#' . $cur['class'];
1354
//                    debug("set cur to child $cur");
1355
//                    $my_tree .= '<li>'.$this->returnSee($tree[$cur]['link'], false, false);
1356
                    continue;
1357
                } else
1358
                {
1359
//                    debug("end of children for $cur");
1360
                    $cur = array_pop($lastcur);
1361
                    $cur = array_pop($lastcur);
1362
                    $my_tree .= '</itemizedlist></listitem>'."\n";
1363
                    if ($dopar && ($cur == '#root' || !$cur)) $my_tree .= '</itemizedlist></listitem>';
1364
                }
1365
            } else
1366
            {
1367
//                debug("$cur has no children");
1368
                $my_tree .= '<listitem>'.$this->returnSee($tree[$cur]['link'], false, false)."</listitem>";
1369
                if ($dopar && $cur == '#root') $my_tree .= '</itemizedlist></listitem>';
1370
                $cur = array_pop($lastcur);
1371
            }
1372
        } while ($cur);
1373
        return $my_tree;
1374
    }
1375
    /**
1376
     * does nothing
1377
     */
1378
    function generateElementIndex()
1379
    {
1380
    }
1381
 
1382
    function setTemplateDir($dir)
1383
    {
1384
        Converter::setTemplateDir($dir);
1385
        $this->smarty_dir = $this->templateDir;
1386
    }
1387
 
1388
    /**
1389
     * Generate alphabetical index of all elements by package and subpackage
1390
     *
1391
     * @param string $package name of a package
1392
     * @see $pkg_elements, walk(), generatePkgElementIndexes()
1393
     */
1394
    function generatePkgElementIndex($package)
1395
    {
1396
    }
1397
 
1398
    /**
1399
     *
1400
     * @see generatePkgElementIndex()
1401
     */
1402
    function generatePkgElementIndexes()
1403
    {
1404
    }
1405
 
1406
    /**
1407
     * @param string name of class
1408
     * @param string package name
1409
     * @param string full path to look in (used in index generation)
1410
     * @param boolean deprecated
1411
     * @param boolean return just the URL, or enclose it in an html a tag
1412
     * @return mixed false if not found, or an html a link to the class's documentation
1413
     * @see parent::getClassLink()
1414
     */
1415
    function getClassLink($expr,$package, $file = false,$text = false, $local = true, $with_a = true)
1416
    {
1417
        $a = Converter::getClassLink($expr,$package,$file);
1418
        if (!$a) return false;
1419
        return $this->returnSee($a, $text, $local, $with_a);
1420
    }
1421
 
1422
    /**
1423
     * @param string name of function
1424
     * @param string package name
1425
     * @param string full path to look in (used in index generation)
1426
     * @param boolean deprecated
1427
     * @param boolean return just the URL, or enclose it in an html a tag
1428
     * @return mixed false if not found, or an html a link to the function's documentation
1429
     * @see parent::getFunctionLink()
1430
     */
1431
    function getFunctionLink($expr,$package, $file = false,$text = false, $local = true)
1432
    {
1433
        $a = Converter::getFunctionLink($expr,$package,$file);
1434
        if (!$a) return false;
1435
        return $this->returnSee($a, $text, $local);
1436
    }
1437
 
1438
    /**
1439
     * @param string name of define
1440
     * @param string package name
1441
     * @param string full path to look in (used in index generation)
1442
     * @param boolean deprecated
1443
     * @param boolean return just the URL, or enclose it in an html a tag
1444
     * @return mixed false if not found, or an html a link to the define's documentation
1445
     * @see parent::getDefineLink()
1446
     */
1447
    function getDefineLink($expr,$package, $file = false,$text = false, $local = true)
1448
    {
1449
        $a = Converter::getDefineLink($expr,$package,$file);
1450
        if (!$a) return false;
1451
        return $this->returnSee($a, $text, $local);
1452
    }
1453
 
1454
    /**
1455
     * @param string name of global variable
1456
     * @param string package name
1457
     * @param string full path to look in (used in index generation)
1458
     * @param boolean deprecated
1459
     * @param boolean return just the URL, or enclose it in an html a tag
1460
     * @return mixed false if not found, or an html a link to the global variable's documentation
1461
     * @see parent::getGlobalLink()
1462
     */
1463
    function getGlobalLink($expr,$package, $file = false,$text = false, $local = true)
1464
    {
1465
        $a = Converter::getGlobalLink($expr,$package,$file);
1466
        if (!$a) return false;
1467
        return $this->returnSee($a, $text, $local);
1468
    }
1469
 
1470
    /**
1471
     * @param string name of procedural page
1472
     * @param string package name
1473
     * @param string full path to look in (used in index generation)
1474
     * @param boolean deprecated
1475
     * @param boolean return just the URL, or enclose it in an html a tag
1476
     * @return mixed false if not found, or an html a link to the procedural page's documentation
1477
     * @see parent::getPageLink()
1478
     */
1479
    function getPageLink($expr,$package, $path = false,$text = false, $local = true)
1480
    {
1481
        $a = Converter::getPageLink($expr,$package,$path);
1482
        if (!$a) return false;
1483
        return $this->returnSee($a, $text, $local);
1484
    }
1485
 
1486
    /**
1487
     * @param string name of method
1488
     * @param string class containing method
1489
     * @param string package name
1490
     * @param string full path to look in (used in index generation)
1491
     * @param boolean deprecated
1492
     * @param boolean return just the URL, or enclose it in an html a tag
1493
     * @return mixed false if not found, or an html a link to the method's documentation
1494
     * @see parent::getMethodLink()
1495
     */
1496
    function getMethodLink($expr,$class,$package, $file = false,$text = false, $local = true)
1497
    {
1498
        $a = Converter::getMethodLink($expr,$class,$package,$file);
1499
        if (!$a) return false;
1500
        return $this->returnSee($a, $text, $local);
1501
    }
1502
 
1503
    /**
1504
     * @param string name of var
1505
     * @param string class containing var
1506
     * @param string package name
1507
     * @param string full path to look in (used in index generation)
1508
     * @param boolean deprecated
1509
     * @param boolean return just the URL, or enclose it in an html a tag
1510
     * @return mixed false if not found, or an html a link to the var's documentation
1511
     * @see parent::getVarLink()
1512
     */
1513
    function getVarLink($expr,$class,$package, $file = false,$text = false, $local = true)
1514
    {
1515
        $a = Converter::getVarLink($expr,$class,$package,$file);
1516
        if (!$a) return false;
1517
        return $this->returnSee($a, $text, $local);
1518
    }
1519
 
1520
    /**
1521
     * does a nat case sort on the specified second level value of the array
1522
     *
1523
     * @param    mixed    $a
1524
     * @param    mixed    $b
1525
     * @return    int
1526
     */
1527
    function rcNatCmp ($a, $b)
1528
    {
1529
        $aa = strtoupper($a[$this->rcnatcmpkey]);
1530
        $bb = strtoupper($b[$this->rcnatcmpkey]);
1531
 
1532
        return strnatcasecmp($aa, $bb);
1533
    }
1534
 
1535
    /**
1536
     * does a nat case sort on the specified second level value of the array.
1537
     * this one puts constructors first
1538
     *
1539
     * @param    mixed    $a
1540
     * @param    mixed    $b
1541
     * @return    int
1542
     */
1543
    function rcNatCmp1 ($a, $b)
1544
    {
1545
        $aa = strtoupper($a[$this->rcnatcmpkey]);
1546
        $bb = strtoupper($b[$this->rcnatcmpkey]);
1547
 
1548
        if (strpos($aa,'CONSTRUCTOR') === 0)
1549
        {
1550
            return -1;
1551
        }
1552
        if (strpos($bb,'CONSTRUCTOR') === 0)
1553
        {
1554
            return 1;
1555
        }
1556
        if (strpos($aa,strtoupper($this->class)) === 0)
1557
        {
1558
            return -1;
1559
        }
1560
        if (strpos($bb,strtoupper($this->class)) === 0)
1561
        {
1562
            return -1;
1563
        }
1564
        return strnatcasecmp($aa, $bb);
1565
    }
1566
 
1567
    function wordwrap($string)
1568
    {
1569
        return wordwrap($string);
1570
    }
1571
 
1572
    /**
1573
     * Generate the constants.xml, packagename.xml, and globals.xml files
1574
     */
1575
    function Output()
1576
    {
1577
        $this->flushPackageXml(false);
1578
        $templ = &$this->newSmarty();
1579
        $categories = array();
1580
        $packages = array_flip($this->all_packages);
1581
        foreach($this->packagecategories as $package => $category)
1582
        {
1583
            $categories[$category]['package.'.$category.'.'.str_replace('_','-',strtolower($package ))] = 1;
1584
            if (isset($packages[$package])) unset($packages[$package]);
1585
        }
1586
        $category = $GLOBALS['phpDocumentor_DefaultCategoryName'];
1587
        foreach($packages as $package)
1588
        {
1589
            $categories[$category]['package.'.$category.'.'.str_replace('_','-',strtolower($package ))] = 1;
1590
        }
1591
        foreach($categories as $category => $ids)
1592
        {
1593
            $templ->assign('id','package.'.$category);
1594
            $templ->assign('ids',array());
1595
            $templ->assign('category',$category);
1596
            $this->setTargetDir($this->base_dir);
1597
            if (file_exists($this->base_dir . PATH_DELIMITER . strtolower($category ) . '.xml'))
1598
            {
1599
                $contents = @file($this->base_dir . PATH_DELIMITER . strtolower($category ) . '.xml');
1600
                if (is_array($contents))
1601
                {
1602
                    $found = false;
1603
                    foreach($contents as $i => $line)
1604
                    {
1605
                        $line = trim($line);
1606
                        if (strlen($line) && $line{0} == '&')
1607
                        {
1608
                            $found = $i;
1609
                            if (in_array(str_replace(array ('&', ';'), array ('', ''), trim($line )), array_keys($ids )))
1610
                            {
1611
                                unset($ids[str_replace(array('&', ';'), array('', ''), trim($line))]);
1612
                            }
1613
                        }
1614
                        if ($found !== false && (!strlen($line) || $line{0} != '&'))
1615
                        {
1616
                            break;
1617
                        }
1618
                    }
1619
                    $newids = array();
1620
                    foreach($ids as $id => $unll)
1621
                    {
1622
                        $newids[] = ' &' . $id . ";\n";
1623
                    }
1624
                    $newcontents = array_merge(array_slice($contents, 0, $i), $newids);
1625
                    $newcontents = array_merge($newcontents, array_slice($contents, $i));
1626
                }
1627
                $categorycontents = implode($newcontents, '');
1628
            } else
1629
            {
1630
                foreach($ids as $id => $unll)
1631
                {
1632
                    if (!in_array($id, $templ->_tpl_vars['ids']))
1633
                    {
1634
                        $templ->append('ids',$id);
1635
                    }
1636
                }
1637
                $categorycontents = '<!-- $' . "Revision$ -->\n" . $templ->fetch('category.tpl');
1638
            }
1639
            $this->writefile(strtolower($category) . '.xml',
1640
                $categorycontents);
1641
            phpDocumentor_out("\n");
1642
            flush();
1643
        }
1644
        $my = &$this->newSmarty();
1645
        if ($this->_peardoc2_constants)
1646
        {
1647
            foreach($this->_peardoc2_constants as $category => $r)
1648
            {
1649
                foreach($r as $package => $s)
1650
                {
1651
                    $my->assign('id','package.'.strtolower($category.'.'.str_replace('_','-',strtolower($package ))).'.constants');
1652
                    $my->assign('package',$package);
1653
                    $defines = array();
1654
                    foreach($s as $file => $t)
1655
                    {
1656
                        $arr = array();
1657
                        $arr['name'] = $file;
1658
                        $arr['page'] = strtolower($t['page']);
1659
                        $arr['defines'] = $t['defines'];
1660
                        $defines[] = $arr;
1661
                    }
1662
                    $my->assign('defines',$defines);
1663
                    $this->setTargetDir($this->base_dir . PATH_DELIMITER . $category
1664
                       . PATH_DELIMITER . strtolower(str_replace('_','-',strtolower($package ))));
1665
                    $this->writefile('constants.xml',
1666
                        '<!-- $' . "Revision$ -->\n" . $my->fetch('constants.tpl'));
1667
                    $my->clear_all_assign();
1668
                }
1669
            }
1670
            $this->_peardoc2_constants = false;
1671
        }
1672
        if ($this->_peardoc2_globals)
1673
        {
1674
            foreach($this->_peardoc2_globals as $category => $r)
1675
            {
1676
                foreach($r as $package => $s)
1677
                {
1678
                    $my->assign('id','package.'.strtolower($category.'.'.str_replace('_','-',strtolower($package ))).'.globals');
1679
                    $my->assign('package',$package);
1680
                    $defines = array();
1681
                    foreach($s as $file => $t)
1682
                    {
1683
                        $arr = array();
1684
                        $arr['name'] = $file;
1685
                        $arr['page'] = strtolower($t['page']);
1686
                        $arr['globals'] = $t['globals'];
1687
                        $defines[] = $arr;
1688
                    }
1689
                    $my->assign('globals',$defines);
1690
                    $this->setTargetDir($this->base_dir . PATH_DELIMITER . $category
1691
                       . PATH_DELIMITER . strtolower(str_replace('_','-',strtolower($package ))));
1692
                    $this->writefile('globals.xml',
1693
                        '<!-- $' . "Revision$ -->\n" . $my->fetch('globals.tpl'));
1694
                    $my->clear_all_assign();
1695
                }
1696
            }
1697
            $this->_peardoc2_globals = false;
1698
        }
1699
    }
1700
}
1701
?>