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