home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / PEAR / PhpDocumentor / phpDocumentor / ProceduralPages.inc < prev    next >
Encoding:
Text File  |  2008-07-02  |  35.4 KB  |  1,068 lines

  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,v 1.9 2008/02/24 02:35:44 ashnazg Exp $
  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.2
  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. ?>
  1068.