Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * Intermediate procedural page parsing structure.
4
 * This structure parses defines, functions, and global variables by file,
5
 * and then iterates over the elements to document conflicts.
6
 *
7
 * phpDocumentor :: automatic documentation generator
8
 *
9
 * PHP versions 4 and 5
10
 *
11
 * Copyright (c) 2002-2008 Gregory Beaver
12
 *
13
 * LICENSE:
14
 *
15
 * This library is free software; you can redistribute it
16
 * and/or modify it under the terms of the GNU Lesser General
17
 * Public License as published by the Free Software Foundation;
18
 * either version 2.1 of the License, or (at your option) any
19
 * later version.
20
 *
21
 * This library is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24
 * Lesser General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU Lesser General Public
27
 * License along with this library; if not, write to the Free Software
28
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29
 *
30
 * @category  ToolsAndUtilities
31
 * @package   phpDocumentor
32
 * @author    Gregory Beaver <cellog@php.net>
33
 * @copyright 2002-2008 Gregory Beaver
34
 * @license   http://www.opensource.org/licenses/lgpl-license.php LGPL
35
 * @version   CVS: $Id: ProceduralPages.inc 253641 2008-02-24 02:35:44Z ashnazg $
36
 * @link      http://www.phpdoc.org
37
 * @link      http://pear.php.net/PhpDocumentor
38
 * @since     1.1
39
 * @todo      CS cleanup - change package to PhpDocumentor
40
 */
41
 
42
/**
43
 * Intermediate procedural page parsing structure.
44
 * This structure parses defines, functions, and global variables by file,
45
 * and then iterates over the elements to document conflicts.
46
 *
47
 * @category  ToolsAndUtilities
48
 * @package   phpDocumentor
49
 * @author    Greg Beaver <cellog@php.net>
50
 * @copyright 2002-2008 Gregory Beaver
51
 * @license   http://www.opensource.org/licenses/lgpl-license.php LGPL
52
 * @version   Release: 1.4.3
53
 * @link      http://www.phpdoc.org
54
 * @link      http://pear.php.net/PhpDocumentor
55
 * @since     1.1
56
 * @todo      CS cleanup - change package to PhpDocumentor
57
 */
58
class ProceduralPages
59
{
60
    /**
61
     * file being parsed, used in every add function
62
     * to match up elements with the file that contains them
63
     *
64
     * @see addClass(), addMethod(), addVar(), nextFile()
65
     * @var string
66
     */
67
    var $curfile;
68
    /**
69
     * array of all procedural pages ordered by name
70
     * Format:
71
     * <pre>
72
     *     array(
73
     *         name => array(
74
     *             fullpath => parserPage,
75
     *             fullpath => parserPage2 [if there are name conflicts],
76
     *             ...
77
     *         )
78
     *     )
79
     * </pre>
80
     *
81
     * @var array
82
     */
83
    var $pages = array();
84
    /**
85
     * array of all procedural pages ordered by name
86
     * that have been ignored via -po or @access private or @ignore
87
     * Format:
88
     * <pre>
89
     *     array(
90
     *         name => array(
91
     *             fullpath => parserPage,
92
     *             fullpath => parserPage2 [if there are name conflicts],
93
     *             ...
94
     *         )
95
     *     )
96
     * </pre>
97
     *
98
     * @var array
99
     */
100
    var $ignorepages = array();
101
    /**
102
     * array of all procedural page names ordered by full path to the file
103
     * Format:
104
     * <pre>
105
     *     array(
106
     *         fullpath => name
107
     *     )
108
     * </pre>
109
     *
110
     * @var array
111
     */
112
    var $pathpages = array();
113
    /**
114
     * array of parsed includes organized by the full path
115
     * of the file that contains the include.
116
     * Format:
117
     * <pre>
118
     *     array(
119
     *         full path => array(
120
     *             includename => {@link parserInclude}
121
     *         )
122
     *     )
123
     * </pre>
124
     *
125
     * @var array
126
     */
127
    var $includesbyfile = array();
128
    /**
129
     * array of parsed functions organized by the full path
130
     * of the file that contains the function.
131
     * Format:
132
     * <pre>
133
     *     array(
134
     *         full path => array(
135
     *             functionname => {@link parserFunction}
136
     *         )
137
     *     )
138
     * </pre>
139
     *
140
     * @var array
141
     */
142
    var $functionsbyfile = array();
143
    /**
144
     * array of parsed defines organized by the full path
145
     * of the file that contains the define.
146
     * Format:
147
     * <pre>
148
     *     array(
149
     *         full path => array(
150
     *             definename => {@link parserDefine}
151
     *         )
152
     *     )
153
     * </pre>
154
     *
155
     * @var array
156
     */
157
    var $definesbyfile = array();
158
    /**
159
     * array of parsed global variables organized by the full path
160
     * of the file that contains the global variable definition.
161
     * Format:
162
     * <pre>
163
     *     array(
164
     *         full path => array(
165
     *             globalname => {@link parserGlobal}
166
     *         )
167
     *     )
168
     * </pre>
169
     *
170
     * @var array
171
     */
172
    var $globalsbyfile = array();
173
    /**
174
     * array of file names organized by functions that are in the file.
175
     *
176
     * This structure is designed to handle name conflicts.  Two files can contain
177
     * functions with the same name, and this array will record both filenames to
178
     * help control namespace errors
179
     * Format:
180
     * <pre>
181
     *     array(
182
     *         functionname => array(
183
     *             full path of file containing functionname,
184
     *             full path of file 2 containing functionname,
185
     *             ...
186
     *         )
187
     *     )
188
     * </pre>
189
     *
190
     * @var array
191
     */
192
    var $functionsbynamefile = array();
193
    /**
194
     * array of file names organized by defines that are in the file.
195
     * This structure is designed to handle name conflicts.  Two files
196
     * can contain defines with the same name, and this array will
197
     * record both filenames to help control namespace errors
198
     * Format:
199
     * <pre>
200
     *     array(
201
     *         definename => array(
202
     *             full path of file containing definename,
203
     *             full path of file 2 containing definename,
204
     *             ...
205
     *         )
206
     *     )
207
     * </pre>
208
     *
209
     * @var array
210
     */
211
    var $definesbynamefile = array();
212
    /**
213
     * array of file names organized by global variables that are in the file.
214
     *
215
     * This structure is designed to handle name conflicts.  Two files can
216
     * contain global variables with the same name, and this array will
217
     * record both filenames to help control namespace errors
218
     * Format:
219
     * <pre>
220
     *     array(
221
     *         global variablename => array(
222
     *             full path of file containing global variablename,
223
     *             full path of file 2 containing global variablename,
224
     *             ...
225
     *         )
226
     *     )
227
     * </pre>
228
     *
229
     * @var array
230
     */
231
    var $globalsbynamefile = array();
232
    /**
233
     * array of packages ordered by full path
234
     * Format:
235
     * <pre>
236
     *     array(
237
     *         fullpath => array(
238
     *             packagename,
239
     *             subpackagename
240
     *         )
241
     *     )
242
     * </pre>
243
     *
244
     * @var array
245
     */
246
    var $pagepackages = array();
247
    /**
248
     * array of packages assigned to classes in a file, ordered by fullpath
249
     * Format:
250
     * <pre>
251
     *     array(
252
     *         fullpath => array(
253
     *             packagename => array(
254
     *                 subpackagename => 1,
255
     *                 subpackagename => 1,
256
     *                 ..
257
     *             ),
258
     *             packagename2 => array(...
259
     *             )
260
     *         )
261
     *     )
262
     * </pre>
263
     *
264
     * @var array
265
     */
266
    var $pageclasspackages = array();
267
    /**
268
     * Namespace conflicts within all documented packages of functions
269
     * Format:
270
     * <pre>
271
     *     array(
272
     *         functionname => array(
273
     *             full path,
274
     *             full path,
275
     *             ...
276
     *         )
277
     *     )
278
     * </pre>
279
     *
280
     * @var array
281
     */
282
    var $functionconflicts = array();
283
    /**
284
     * Namespace conflicts within all documented pages
285
     * Format:
286
     * <pre>
287
     *     array(
288
     *         pagename => array(
289
     *             fullpath,
290
     *             fullpath,
291
     *             ...
292
     *         )
293
     *     )
294
     * </pre>
295
     *
296
     * @var array
297
     */
298
    var $pageconflicts = array();
299
    /**
300
     * Namespace conflicts within all documented packages of functions
301
     * Format:
302
     * <pre>
303
     *     array(
304
     *         functionname => array(
305
     *             full path,
306
     *             full path,
307
     *             ...
308
     *         )
309
     *     )
310
     * </pre>
311
     *
312
     * @var array
313
     */
314
    var $defineconflicts = array();
315
    /**
316
     * Namespace conflicts within all documented packages of functions
317
     * Format:
318
     * <pre>
319
     *     array(
320
     *         functionname => array(
321
     *             full path,
322
     *             full path,
323
     *             ...
324
     *         )
325
     *     )
326
     * </pre>
327
     *
328
     * @var array
329
     */
330
    var $globalconflicts = array();
331
    /**
332
     * @access private
333
     * @var array
334
     */
335
    var $revcpbf = array();
336
    /**
337
     * @access private
338
     * @var boolean
339
     */
340
    var $packagesetup = false;
341
 
342
    /**
343
     * sets up the {@link $pages} array
344
     *
345
     * @param parserPage &$element the parser page element
346
     *
347
     * @return void
348
     */
349
    function addPage(&$element)
350
    {
351
        $this->curfile
352
            = $element->getPath();
353
        $this->pages[$element->getFile()][$element->getPath()]
354
            = $element;
355
        $this->pathpages[$this->curfile]
356
            = $element->getFile();
357
        $this->addPagePackage($this->curfile,
358
            $element->package, $element->subpackage);
359
    }
360
 
361
    /**
362
     * moves a page from the {@link $pages} array to the {@link $ignorepages} array
363
     *
364
     * @param parserPage &$element the parser page element
365
     *
366
     * @return void
367
     */
368
    function ignorePage(&$element)
369
    {
370
        $this->ignorepages[$element->getFile()][$element->getPath()]
371
            = $this->pages[$element->getFile()][$element->getPath()];
372
        unset($this->pages[$element->getFile()][$element->getPath()]);
373
    }
374
 
375
    /**
376
     * gathers path-related info about a given element
377
     *
378
     * @param string $path path to the element
379
     * @param mixed  &$c   ???
380
     *
381
     * @return array|bool an array of path info,
382
     *                    or FALSE
383
     * @todo figure out what &$c is and update the param tag
384
     */
385
    function getPathInfo($path, &$c)
386
    {
387
        $path = str_replace('/', SMART_PATH_DELIMITER, $path);
388
        $info = array();
389
        if (!isset($this->pathpages[$path])) {
390
            return false;
391
        }
392
 
393
        $p = $this->pages[$this->pathpages[$path]][$path];
394
        // fixes [ 1391432 ] Too many underscores in include links.
395
        $p->name = $p->origName;
396
        $p->name = $c->getPageName($p);
397
 
398
        $info['package']    = $p->package;
399
        $info['subpackage'] = $p->subpackage;
400
        $info['name']       = $p->getFile();
401
        $info['source_loc'] = $p->getSourceLocation($c);
402
 
403
        $x = new pageLink;
404
        $x->addLink($p->path, $p->name, $p->file, $p->package, $p->subpackage);
405
 
406
        $info['docs'] = $c->returnSee($x);
407
        $p->name      = $p->origName;
408
 
409
        return $info;
410
    }
411
 
412
    /**
413
     * Change a page's name from its file to alias $name
414
     *
415
     * This function is used to handle a @name tag in a page-level DocBlock
416
     *
417
     * @param string $name the alias
418
     *
419
     * @return void
420
     */
421
    function setName($name)
422
    {
423
        if ($this->pages[$name][$this->curfile]->file == $name) {
424
            addWarning(PDERROR_NAME_ALIAS_SAME_AS_TARGET,'');
425
 
426
        } else {
427
            $this->pages[$name][$this->curfile]
428
                = $this->pages[$this->pathpages[$this->curfile]][$this->curfile];
429
            $this->pages[$name][$this->curfile]->file
430
                = $name;
431
 
432
            unset($this->pages[$this->pathpages[$this->curfile]][$this->curfile]);
433
 
434
            $this->pathpages[$this->curfile] = $name;
435
        }
436
    }
437
 
438
    /**
439
     * Changes the package of the page represented by $path
440
     *
441
     * changes package in both the {@link $pages} array
442
     * and the {@link pagepackages} array
443
     *
444
     * @param string $path       full path
445
     * @param string $package    the package name
446
     * @param string $subpackage the subpackage name
447
     *
448
     * @return void
449
     */
450
    function addPagePackage($path, $package, $subpackage)
451
    {
452
        $this->pages[$this->pathpages[$path]][$path]->package
453
            = $package;
454
        $this->pages[$this->pathpages[$path]][$path]->subpackage
455
            = $subpackage;
456
        $this->pagepackages[$path]
457
            = array($package, $subpackage);
458
 
459
        if (isset($this->includesbyfile[$path])) {
460
            foreach ($this->includesbyfile[$path] as $i => $el) {
461
                $el->package                     = $package;
462
                $el->subpackage                  = $subpackage;
463
                $this->includesbyfile[$path][$i] = $el;
464
            }
465
        }
466
        if (isset($this->functionsbyfile[$path])) {
467
            foreach ($this->functionsbyfile[$path] as $i => $el) {
468
                $el->package                      = $package;
469
                $el->subpackage                   = $subpackage;
470
                $this->functionsbyfile[$path][$i] = $el;
471
            }
472
        }
473
        if (isset($this->definesbyfile[$path])) {
474
            foreach ($this->definesbyfile[$path] as $i => $el) {
475
                $el->package                    = $package;
476
                $el->subpackage                 = $subpackage;
477
                $this->definesbyfile[$path][$i] = $el;
478
            }
479
        }
480
        if (isset($this->globalsbyfile[$path])) {
481
            foreach ($this->globalsbyfile[$path] as $i => $el) {
482
                $el->package                    = $package;
483
                $el->subpackage                 = $subpackage;
484
                $this->globalsbyfile[$path][$i] = $el;
485
            }
486
        }
487
    }
488
 
489
    /**
490
     * sets up the {@link $includesbyfile} array using {@link $curfile}
491
     *
492
     * @param parserInclude &$element the "include" element object
493
     *
494
     * @return void
495
     */
496
    function addInclude(&$element)
497
    {
498
        $this->includesbyfile[$this->curfile][] = $element;
499
    }
500
 
501
    /**
502
     * sets up the {@link $functionsbyfile} array using {@link $curfile}
503
     *
504
     * @param parserFunction &$element the "function" object
505
     *
506
     * @return void
507
     */
508
    function addFunction(&$element)
509
    {
510
        if (isset($this->functionsbyfile[$this->curfile])) {
511
            foreach ($this->functionsbyfile[$this->curfile] as $i => $function) {
512
                if ($function->getName() == $element->getName()) {
513
                    addWarning(PDERROR_ELEMENT_IGNORED, 'function',
514
                        $element->getName(), $this->curfile);
515
                    return;
516
                }
517
            }
518
        }
519
        $this->functionsbyfile[$this->curfile][]          = $element;
520
        $this->functionsbynamefile[$element->getName()][] = $this->curfile;
521
    }
522
 
523
    /**
524
     * sets up the {@link $globalsbyfile} array using {@link $curfile}
525
     *
526
     * @param parserGlobal &$element the "global" element
527
     *
528
     * @return void
529
     */
530
    function addGlobal(&$element)
531
    {
532
        if (isset($this->globalsbyfile[$this->curfile])) {
533
            foreach ($this->globalsbyfile[$this->curfile] as $i => $global) {
534
                if ($global->getName() == $element->getName()) {
535
                    addWarning(PDERROR_ELEMENT_IGNORED, 'global variable',
536
                        $element->getName(), $this->curfile);
537
                    return;
538
                }
539
            }
540
        }
541
        $this->globalsbyfile[$this->curfile][]          = $element;
542
        $this->globalsbynamefile[$element->getName()][] = $this->curfile;
543
    }
544
 
545
    /**
546
     * sets up the {@link $definesbyfile} array using {@link $curfile}
547
     *
548
     * @param parserDefine &$element the "define" element
549
     *
550
     * @return void
551
     */
552
    function addDefine(&$element)
553
    {
554
        if (isset($this->definesbyfile[$this->curfile])) {
555
            foreach ($this->definesbyfile[$this->curfile] as $i => $define) {
556
                if ($define->getName() == $element->getName()) {
557
                    addWarning(PDERROR_ELEMENT_IGNORED, 'define',
558
                        $element->getName(), $this->curfile);
559
                    return;
560
                }
561
            }
562
        }
563
        $this->definesbyfile[$this->curfile][]          = $element;
564
        $this->definesbynamefile[$element->getName()][] = $this->curfile;
565
    }
566
 
567
    /**
568
     * Used to align an element with the package of its parent page
569
     * prior to Conversion.
570
     *
571
     * @param parserElement &$element the element to align
572
     *
573
     * @return void
574
     */
575
    function replaceElement(&$element)
576
    {
577
        if ($element->type == 'define') {
578
            foreach ($this->definesbyfile[$element->getPath()] as $i => $el) {
579
                if ($el->getName() == $element->getName()) {
580
                    $this->definesbyfile[$element->getPath()][$i] = &$element;
581
                }
582
            }
583
        } elseif ($element->type == 'global') {
584
            foreach ($this->globalsbyfile[$element->getPath()] as $i => $el) {
585
                if ($el->getName() == $element->getName()) {
586
                    $this->globalsbyfile[$element->getPath()][$i] = &$element;
587
                }
588
            }
589
        } elseif ($element->type == 'include') {
590
            foreach ($this->includesbyfile[$element->getPath()] as $i => $el) {
591
                if ($el->getName() == $element->getName()) {
592
                    $this->includesbyfile[$element->getPath()][$i] = &$element;
593
                }
594
            }
595
        } elseif ($element->type == 'function') {
596
            foreach ($this->functionsbyfile[$element->getPath()] as $i => $el) {
597
                if ($el->getName() == $element->getName()) {
598
                    $this->functionsbyfile[$element->getPath()][$i] = &$element;
599
                }
600
            }
601
        }
602
    }
603
 
604
    /**
605
     * adds a package from a class to the current file
606
     *
607
     * @param string $file       full path to the file that contains the class
608
     * @param string $package    package name
609
     * @param string $subpackage subpackage name
610
     *
611
     * @return void
612
     */
613
    function addClassPackageToFile($file, $package, $subpackage)
614
    {
615
        if (!isset($this->revcpbf[$file][$package][$subpackage])) {
616
            $this->pageclasspackages[$file][$package][$subpackage] = 1;
617
        }
618
        $this->revcpbf[$file][$package][$subpackage] = 1;
619
    }
620
 
621
    /**
622
     * if there is one class package in a file,
623
     * the parent path inherits the package if its package is default.
624
     * helps with -po to avoid dumb bugs
625
     *
626
     * @return void
627
     */
628
    function setupPagePackages()
629
    {
630
        if ($this->packagesetup) {
631
            return;
632
        }
633
        foreach ($this->pageclasspackages as $fullpath => $packages) {
634
            if (isset($this->pagepackages[$fullpath])) {
635
                if ($this->pagepackages[$fullpath][0]
636
                    == $GLOBALS['phpDocumentor_DefaultPackageName']
637
                ) {
638
                    if (count($packages) == 1) {
639
                        list($package, $subpackage) = each($packages);
640
                        if (count($subpackage) == 1) {
641
                            list($subpackage,) = each($subpackage);
642
                        } else {
643
                            $subpackage = '';
644
                        }
645
                        $this->addPagePackage($fullpath, $package, $subpackage);
646
                    }
647
                }
648
            }
649
        }
650
        $this->packagesetup = true;
651
    }
652
 
653
    /**
654
     * extracts function, define, and global variable name conflicts within the
655
     * same package and between different packages.  No two elements with the same
656
     * name are allowed in the same package, to keep automatic linking possible.
657
     *
658
     * @param mixed &$render the renderer object
659
     *
660
     * @return void
661
     * @access private
662
     * @todo functions, defines, and globals are coded,
663
     *       but pages section is empty... does it need to be coded?
664
     */
665
    function setupConflicts(&$render)
666
    {
667
        foreach ($this->functionsbynamefile as $function => $paths) {
668
            if (count($paths) - 1) {
669
                //conflict
670
                $package = array();
671
                foreach ($paths as $path) {
672
                    // create a list of conflicting functions in each package
673
                    $package[$this->pagepackages[$path][0]][] = $path;
674
                }
675
                foreach ($package as $pathpackages) {
676
                    // if at least 2 functions exist in the same package,
677
                    // delete all but the first one and add warnings
678
                    if (count($pathpackages) - 1) {
679
                        for ($i=1; $i < count($pathpackages); $i++) {
680
                            addWarning(PDERROR_ELEMENT_IGNORED, 'function',
681
                                $function, $pathpackages[$i]);
682
                            foreach ($this->functionsbyfile[$pathpackages[$i]]
683
                                as $j => $blah
684
                            ) {
685
                                if ($this->functionsbyfile[$pathpackages[$i]][$j]
686
                                    ->getName() == $function
687
                                ) {
688
                                    unset($this
689
                                        ->functionsbyfile[$pathpackages[$i]][$j]);
690
                                }
691
                            }
692
                            $oth = array_flip($paths);
693
                            unset($paths[$oth[$pathpackages[$i]]]);
694
                        }
695
                    }
696
                }
697
                $this->functionconflicts[$function] = $paths;
698
            }
699
        }
700
 
701
        foreach ($this->definesbynamefile as $define => $paths) {
702
            if (count($paths) - 1) {
703
                //conflict
704
                $package = array();
705
                foreach ($paths as $path) {
706
                    // create a list of conflicting functions in each package
707
                    $package[$this->pagepackages[$path][0]][] = $path;
708
                }
709
                foreach ($package as $pathpackages) {
710
                    // if at least 2 functions exist in the same package,
711
                    // delete all but the first one and add warnings
712
                    if (count($pathpackages) - 1) {
713
                        for ($i=1; $i < count($pathpackages); $i++) {
714
                            addWarning(PDERROR_ELEMENT_IGNORED, 'define',
715
                                $define, $pathpackages[$i]);
716
                            foreach ($this->definesbyfile[$pathpackages[$i]]
717
                                as $j => $blah
718
                            ) {
719
                                if ($this->definesbyfile[$pathpackages[$i]][$j]
720
                                    ->getName() == $define
721
                                ) {
722
                                    unset($this
723
                                        ->definesbyfile[$pathpackages[$i]][$j]);
724
                                }
725
                            }
726
                            $oth = array_flip($paths);
727
                            unset($paths[$oth[$pathpackages[$i]]]);
728
                        }
729
                    }
730
                }
731
                $this->defineconflicts[$define] = $paths;
732
            }
733
        }
734
 
735
        foreach ($this->globalsbynamefile as $global => $paths) {
736
            if (count($paths) - 1) {
737
                //conflict
738
                $package = array();
739
                foreach ($paths as $path) {
740
                    // create a list of conflicting functions in each package
741
                    $package[$this->pagepackages[$path][0]][] = $path;
742
                }
743
                foreach ($package as $pathpackages) {
744
                    // if at least 2 functions exist in the same package,
745
                    // delete all but the first one and add warnings
746
                    if (count($pathpackages) - 1) {
747
                        for ($i=1; $i < count($pathpackages); $i++) {
748
                            addWarning(PDERROR_ELEMENT_IGNORED, 'global variable',
749
                                $global, $pathpackages[$i]);
750
                            foreach ($this->globalsbyfile[$pathpackages[$i]]
751
                                as $j => $blah
752
                            ) {
753
                                if ($this->globalsbyfile[$pathpackages[$i]][$j]
754
                                    ->getName() == $global
755
                                ) {
756
                                    unset($this
757
                                        ->globalsbyfile[$pathpackages[$i]][$j]);
758
                                }
759
                            }
760
                            $oth = array_flip($paths);
761
                            unset($paths[$oth[$pathpackages[$i]]]);
762
                        }
763
                    }
764
                }
765
                $this->globalconflicts[$global] = $paths;
766
            }
767
        }
768
 
769
        /*
770
         * @todo does this section still need to be coded???
771
         */
772
        foreach ($this->pages as $name => $pages) {
773
            if (count($pages) - 1) {
774
                // possible conflict
775
            }
776
        }
777
    }
778
 
779
    /**
780
     * called by {@link parserFunction::getConflicts()} to get
781
     * inter-package conflicts, should not be called directly
782
     *
783
     * @param string $name the function name to check
784
     *
785
     * @access private
786
     * @return array|bool Format: (package => {@link parserFunction}
787
     *                    of conflicting function)
788
     *                    or FALSE if the function is not recorded as a conflict
789
     */
790
    function getFuncConflicts($name)
791
    {
792
        if (!isset($this->functionconflicts[$name])) {
793
            return false;
794
        }
795
        $a = array();
796
        foreach ($this->functionconflicts[$name] as $conflict) {
797
            foreach ($this->functionsbyfile[$conflict] as $i => $func) {
798
                if ($func->getName() == $name) {
799
                    $a[$this->functionsbyfile[$conflict][$i]->docblock->package]
800
                        = $this->functionsbyfile[$conflict][$i];
801
                }
802
            }
803
        }
804
        return $a;
805
    }
806
 
807
    /**
808
     * called by {@link parserGlobal::getConflicts()}
809
     * to get inter-package conflicts, should not be called directly
810
     *
811
     * @param string $name the global name to check
812
     *
813
     * @access private
814
     * @return array|bool Format: (package => {@link parserGlobal}
815
     *                    of conflicting global variable)
816
     *                    or FALSE if the global is not recorded as a conflict
817
     */
818
    function getGlobalConflicts($name)
819
    {
820
        if (!isset($this->globalconflicts[$name])) {
821
            return false;
822
        }
823
        $a = array();
824
        foreach ($this->globalconflicts[$name] as $conflict) {
825
            foreach ($this->globalsbyfile[$conflict] as $i => $func) {
826
                if ($func->getName() == $name) {
827
                    $a[$this->globalsbyfile[$conflict][$i]->docblock->package]
828
                        = $this->globalsbyfile[$conflict][$i];
829
                }
830
            }
831
        }
832
        return $a;
833
    }
834
 
835
    /**
836
     * called by {@link parserDefine::getConflicts()}
837
     * to get inter-package conflicts, should not be called directly
838
     *
839
     * @param string $name the define name to check
840
     *
841
     * @access private
842
     * @return array|bool Format: (package => {@link parserDefine}
843
     *                    of conflicting define)
844
     *                    or FALSE if the define is not recorded as a conflict
845
     */
846
    function getDefineConflicts($name)
847
    {
848
        if (!isset($this->defineconflicts[$name])) {
849
            return false;
850
        }
851
        $a = array();
852
        foreach ($this->defineconflicts[$name] as $conflict) {
853
            foreach ($this->definesbyfile[$conflict] as $i => $func) {
854
                if ($func->getName() == $name) {
855
                    $a[$this->definesbyfile[$conflict][$i]->docblock->package]
856
                        = $this->definesbyfile[$conflict][$i];
857
                }
858
            }
859
        }
860
        return $a;
861
    }
862
 
863
    /**
864
     * Adjusts packages of all pages and removes name conflicts within a package
865
     *
866
     * Automatic linking requires that each linkable name have exactly one element
867
     * associated with it.  In other words, there cannot be two functions named
868
     * foo() in the same package.
869
     *
870
     * This also adheres to php rules with one exception:
871
     *
872
     * <code>
873
     * if ($test == 3) {
874
     *    define('whatever', 'this thing');
875
     * } else {
876
     *    define('whatever', 'this other thing');
877
     * }
878
     * </code>
879
     *
880
     * phpDocumentor is not aware of conditional control structures because it
881
     * would slow things down considerably.  So, what phpDocumentor does is
882
     * automatically ignore the second define and raise a warning.  The warning can
883
     * be eliminated with an @ignore tag on the second element like so:
884
     *
885
     * <code>
886
     * if ($test == 3) {
887
     *    define('whatever', 'this thing');
888
     * } else {
889
     *    /**
890
     *     * @ignore
891
     *     {@*}
892
     *    define('whatever', 'this other thing');
893
     * }
894
     * </code>
895
     *
896
     * If there are two files that contain the same procedural elements in the
897
     * same package (for example, a common configuration file common.php), they
898
     * will also be ignored as if they were in the same file.  The reasoning
899
     * behind this is simple.  A package is an indivisible set of files and
900
     * classes that a user will include in their code.  Name conflicts must be
901
     * avoided to allow successful execution.
902
     *
903
     * This function also plays the all-important role of calling
904
     * {@link phpDocumentor_IntermediateParser::addElementToPage()} in order to add
905
     * processed elements to their pages for Conversion.
906
     *
907
     * @param phpDocumentor_IntermediateParser &$render the parser
908
     *
909
     * @return void
910
     */
911
    function setupPages(&$render)
912
    {
913
        global $_phpDocumentor_setting;
914
        phpDocumentor_out("\nProcessing Procedural Page Element Name Conflicts\n\n");
915
        flush();
916
        $this->setupPagePackages();
917
        $this->setupConflicts($render);
918
        // phpDocumentor_out("\nProcessing Procedural Pages\n\n");
919
        foreach ($this->pathpages as $path => $name) {
920
            // phpDocumentor_out("Processing $path\n");
921
            $a = $this->pagepackages[$path];
922
            $b = &$this->pages[$name][$path];
923
            $render->addPage($b, $path);
924
            $render->addUses($b, $path);
925
            if (isset($this->includesbyfile[$path])) {
926
                foreach ($this->includesbyfile[$path] as $include) {
927
                    $include->docblock->package    = $a[0];
928
                    $include->docblock->subpackage = $a[1];
929
                    $render->addElementToPage($include, $path);
930
                }
931
            }
932
 
933
            if (isset($this->functionsbyfile[$path])) {
934
                foreach ($this->functionsbyfile[$path] as $function) {
935
                    $function->docblock->package    = $a[0];
936
                    $function->docblock->subpackage = $a[1];
937
                    $render->addElementToPage($function, $path);
938
                    $render->addUses($function, $path);
939
                }
940
            }
941
 
942
            if (isset($this->definesbyfile[$path])) {
943
                foreach ($this->definesbyfile[$path] as $define) {
944
                    $define->docblock->package    = $a[0];
945
                    $define->docblock->subpackage = $a[1];
946
                    $render->addElementToPage($define, $path);
947
                    $render->addUses($define, $path);
948
                }
949
            }
950
 
951
            if (isset($this->globalsbyfile[$path])) {
952
                foreach ($this->globalsbyfile[$path] as $global) {
953
                    $global->docblock->package    = $a[0];
954
                    $global->docblock->subpackage = $a[1];
955
                    $render->addElementToPage($global, $path);
956
                    $render->addUses($global, $path);
957
                }
958
            }
959
        }
960
    }
961
 
962
    /**
963
     * sets the parser base
964
     *
965
     * @param mixed $pbase the parser base
966
     *
967
     * @return void
968
     */
969
    function setParseBase($pbase)
970
    {
971
        $this->_parsedbase = $pbase;
972
    }
973
 
974
    /**
975
     * checks to see if the parsed file matches the given path
976
     *
977
     * @param string $path   the path to look for
978
     * @param string $infile the file to check
979
     *
980
     * @return parserPage|bool matched parserPage if found,
981
     *                         or FALSE if not found
982
     */
983
    function pathMatchesParsedFile($path, $infile)
984
    {
985
        $test = $this->getRealPath($path, $infile);
986
        if (is_string($test)) {
987
            if (isset($this->pathpages[$test])) {
988
                return $this->pages[$this->pathpages[$test]][$test];
989
            }
990
            if (PHPDOCUMENTOR_WINDOWS) {
991
                $test = str_replace('/', '\\', $test);
992
            }
993
            if (isset($this->pathpages[$test])) {
994
                $a = $this->pages[$this->pathpages[$test]][$test];
995
                if (is_array($a->packageOutput)
996
                    && !in_array($a->package, $a->packageOutput)
997
                ) {
998
                    return false;
999
                }
1000
                return $this->pages[$this->pathpages[$test]][$test];
1001
            }
1002
        } else {
1003
            foreach ($test as $file) {
1004
                if (isset($this->pathpages[$file])) {
1005
                    return $this->pages[$this->pathpages[$file]][$file];
1006
                }
1007
                if (PHPDOCUMENTOR_WINDOWS) {
1008
                    $file = str_replace('/', '\\', $file);
1009
                }
1010
                if (isset($this->pathpages[$file])) {
1011
                    $a = $this->pages[$this->pathpages[$file]][$file];
1012
                    if (is_array($a->packageOutput)
1013
                        && !in_array($a->package, $a->packageOutput)
1014
                    ) {
1015
                        return false;
1016
                    }
1017
                    return $this->pages[$this->pathpages[$file]][$file];
1018
                }
1019
            }
1020
        }
1021
        return false;
1022
    }
1023
 
1024
    /**
1025
     * Ensures the path to the file is an absolute path
1026
     *
1027
     * @param string $path path to the file
1028
     * @param string $file the file name
1029
     *
1030
     * @return array|string returns an array of possible file locations or
1031
     *                      a string if there is an exact match
1032
     */
1033
    function getRealPath($path, $file)
1034
    {
1035
        $curdir = str_replace('\\', '/', dirname($file));
1036
        $path   = str_replace('\\', '/', $path);
1037
        if (strpos($path, ':') !== false) {
1038
            // windows, and we have a drive letter
1039
            return $path;
1040
        } elseif (strpos($path, '/') === 0) {
1041
            return $path;
1042
        }
1043
        // not an absolute path
1044
        $path = explode('/', $path);
1045
        if ($path[0] == '.') {
1046
            $path[0] = dirname($file);
1047
            return join($path, '/');
1048
        } elseif ($path[0] == '..') {
1049
            $dirfile = explode('/', dirname(str_replace('\\', '/', $file)));
1050
            // remove the current directory
1051
            array_pop($dirfile);
1052
            if (!count($dirfile)) {
1053
                // we were at a top-level dir!
1054
                return false;
1055
            }
1056
            // replace .. with parent dirname
1057
            $path[0] = join($dirfile, '/');
1058
            return join($path, '/');
1059
        } else {
1060
            $path = join($path, '/');
1061
            return array($curdir . PATH_DELIMITER . $path,
1062
                str_replace('\\', '/', PHPDOCUMENTOR_BASE)
1063
                . PATH_DELIMITER . $path);
1064
        }
1065
    }
1066
}
1067
?>