Source for file Converter.inc
Documentation is available at
Converter.inc
<?php
/**
* Base class for all Converters
*
* phpDocumentor :: automatic documentation generator
*
* PHP versions 4 and 5
*
* Copyright (c) 2001-2006 Gregory Beaver
*
* LICENSE:
*
* This library is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser General
* Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any
* later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
@package
Converters
*
@author
Greg Beaver <
[email protected]
>
*
@copyright
2001-2006 Gregory Beaver
*
@license
http://www.opensource.org/licenses/lgpl-license.php LGPL
*
@version
CVS: $Id: Converter.inc 291278 2009-11-24 17:43:20Z ashnazg $
*
@filesource
*
@link
http://www.phpdoc.org
*
@link
http://pear.php.net/PhpDocumentor
*
@see
parserDocBlock, parserInclude, parserPage, parserClass
*
@see
parserDefine, parserFunction, parserMethod, parserVar
*
@since
1.0rc1
*/
/**
* Smarty template files
*/
include_once
(
"phpDocumentor/Smarty-2.6.0/libs/Smarty.class.php"
)
;
/**
* Base class for all output converters.
*
* The Converter marks the final stage in phpDocumentor. phpDocumentor works
* in this order:
*
* <pre>Parsing => Intermediate Parsing organization => Conversion to output</pre>
*
* A Converter takes output from the
{@link phpDocumentor_IntermediateParser}
and
* converts it to output. With version 1.2, phpDocumentor includes a variety
* of output converters:
* <ul>
* <li>
{@link HTMLframesConverter}
</li>
* <li>
{@link HTMLSmartyConverter}
</li>
* <li>
{@link PDFdefaultConverter}
</li>
* <li>
{@link CHMdefaultConverter}
</li>
* <li>
{@link CSVdia2codeConverter}
</li>
* <li>
{@link XMLDocBookConverter}
</li>
* </ul>
*
{@internal
* The converter takes output directly from {@link phpDocumentor_IntermediateParser}
* and using {@link walk()} or {@link walk_everything} (depending on the value of
* {@link $sort_absolutely_everything}) it "walks" over an array of phpDocumentor elements.}}
}
*
*
@package
Converters
*
@abstract
*
@author
Greg Beaver <
[email protected]
>
*
@since
1.0rc1
*
@version
$Id: Converter.inc 291278 2009-11-24 17:43:20Z ashnazg $
*/
class
Converter
{
/**
* This converter knows about the new root tree processing
* In order to fix PEAR Bug #6389
*
@var
boolean
*/
var
$processSpecialRoots
= false
;
/**
* output format of this converter
*
* in Child converters, this will match the first part of the -o command-line
* as in -o HTML:frames:default "HTML"
*
@tutorial
phpDocumentor.howto.pkg#using.command-line.output
*
@var
string
*/
var
$outputformat
=
'Generic'
;
/**
* package name currently being converted
*
@var
string
*/
var
$package
=
'default'
;
/**
* subpackage name currently being converted
*
@var
string
*/
var
$subpackage
=
''
;
/**
* set to a classname if currently parsing a class, false if not
*
@var
string
|
false
*/
var
$class
= false
;
/**#@+
* @access private
*/
/**
* the workhorse of linking.
*
* This array is an array of link objects of format:
* [package][subpackage][eltype][elname] = descendant of
{@link abstractLink}
* eltype can be page|function|define|class|method|var
* if eltype is method or var, the array format is:
* [package][subpackage][eltype][class][elname]
*
@var
array
*
@see
functionLink, pageLink, classLink, defineLink, methodLink, varLink, globalLink
*/
var
$links
= array
(
)
;
/**
* the workhorse of linking, with allowance for support of multiple
* elements in different files.
*
* This array is an array of link objects of format:
* [package][subpackage][eltype][file][elname] = descendant of
{@link abstractLink}
* eltype can be function|define|class|method|var
* if eltype is method or var, the array format is:
* [package][subpackage][eltype][file][class][elname]
*
@var
array
*
@see
functionLink, pageLink, classLink, defineLink, methodLink, varLink, globalLink
*/
var
$linkswithfile
= array
(
)
;
/**#@-*/
/**
* set to value of -po commandline
*
@tutorial
phpDocumentor.howto.pkg#using.command-line.packageoutput
*
@var
mixed
*/
var
$package_output
;
/**
* name of current page being converted
*
@var
string
*/
var
$page
;
/**
* path of current page being converted
*
@var
string
*/
var
$path
;
/**
* template for the procedural page currently being processed
*
@var
Smarty
*/
var
$page_data
;
/**
* template for the class currently being processed
*
@var
Smarty
*/
var
$class_data
;
/**
* current procedural page being processed
*
@var
parserPage
*/
var
$curpage
;
/**
* alphabetical index of all elements sorted by package, subpackage, page,
* and class.
*
@var
array
Format: array(package => array(subpackage => array('page'|'class' => array(path|classname => array(element, element,...)))))
*
@uses
$sort_absolutely_everything if true, then $package_elements is used,
* otherwise, the
{@link ParserData::$classelements}
and
*
{@link ParserData::$pageelements}
variables are used
*/
var
$package_elements
= array
(
)
;
/**
* alphabetical index of all elements
*
*
@var
array
Format: array(first letter of element name => array(
{@link parserElement}
or
{@link parserPage}
,...))
*
@see
formatIndex(), HTMLframesConverter::formatIndex()
*/
var
$elements
= array
(
)
;
/**
* alphabetized index of procedural pages by package
*
*
@see
$leftindex
*
@var
array
Format: array(package => array(subpackage => array(
{@link pageLink}
1,
{@link pageLink}
2,...)
*/
var
$page_elements
= array
(
)
;
/**
* alphabetized index of defines by package
*
*
@see
$leftindex
*
@var
array
Format: array(package => array(subpackage => array(
{@link defineLink}
1,
{@link defineLink}
2,...)
*/
var
$define_elements
= array
(
)
;
/**
* alphabetized index of classes by package
*
*
@see
$leftindex
*
@var
array
Format: array(package => array(subpackage => array(
{@link classLink}
1,
{@link classLink}
2,...)
*/
var
$class_elements
= array
(
)
;
/**
* alphabetized index of global variables by package
*
*
@see
$leftindex
*
@var
array
Format: array(package => array(subpackage => array(
{@link globalLink}
1,
{@link globalLink}
2,...)
*/
var
$global_elements
= array
(
)
;
/**
* alphabetized index of functions by package
*
*
@see
$leftindex
*
@var
array
Format: array(package => array(subpackage => array(
{@link functionLink}
1,
{@link functionLink}
2,...)
*/
var
$function_elements
= array
(
)
;
/**
* alphabetical index of all elements, indexed by package/subpackage
*
*
@var
array
Format: array(first letter of element name => array(
{@link parserElement}
or
{@link parserPage}
,...))
*
@see
formatPkgIndex(), HTMLframesConverter::formatPkgIndex()
*/
var
$pkg_elements
= array
(
)
;
/**
* alphabetical index of all elements on a page by package/subpackage
*
* The page itself has a link under ###main
*
@var
array
Format: array(package => array(subpackage => array(path => array(
{@link abstractLink}
descendant 1, ...)))
*
@see
formatLeftIndex()
*/
var
$page_contents
= array
(
)
;
/**
* This determines whether the
{@link $page_contents}
array should be sorted by element type as well as alphabetically by name
*
@see
sortPageContentsByElementType()
*
@var
boolean
*/
var
$sort_page_contents_by_type
= false
;
/**
* This is used if the content must be passed in the order it should be read, i.e. by package, procedural then classes
*
* This fixes bug 637921, and is used by
{@link PDFdefaultConverter}
*/
var
$sort_absolutely_everything
= false
;
/**
* alphabetical index of all methods and vars in a class by package/subpackage
*
* The class itself has a link under ###main
*
@var
array
*
Format:<pre>
* array(package =>
* array(subpackage =>
* array(path =>
* array(class =>
* array(
{@link abstractLink}
descendant 1, ...
* )
* )
* )
* )</pre>
*
@see
formatLeftIndex()
*/
var
$class_contents
= array
(
)
;
/**
* controls processing of elements marked private with @access private
*
* defaults to false. Set with command-line --parseprivate or -pp
*
@var
bool
*/
var
$parseprivate
;
/**
* controls display of progress information while parsing.
*
* defaults to false. Set to true for cron jobs or other situations where no visual output is necessary
*
@var
bool
*/
var
$quietmode
;
/**
* directory that output is sent to. -t command-line sets this.
*
@tutorial
phpDocumentor.howto.pkg#using.command-line.target
*/
var
$targetDir
=
''
;
/**
* Directory that the template is in, relative to phpDocumentor root directory
*
@var
string
*/
var
$templateDir
=
''
;
/**
* Directory that the smarty templates are in
*
@var
string
*/
var
$smarty_dir
=
''
;
/**
* Name of the template, from last part of -o
*
@tutorial
phpDocumentor.howto.pkg#using.command-line.output
*
@var
string
*/
var
$templateName
=
''
;
/**
* full path of the current file being converted
*/
var
$curfile
;
/**
* All class information, organized by path, and by package
*
@var
Classes
*/
var
$classes
;
/**
* Flag used to help converters determine whether to do special source highlighting
*
@var
boolean
*/
var
$highlightingSource
= false
;
/**
* Hierarchy of packages
*
* Every package that contains classes may have parent or child classes
* in other packages. In other words, this code is legal:
*
* <code>
* /**
* * @package one
* * /
* class one {}
*
* /**
* * @package two
* * /
* class two extends one {}
* </code>
*
* In this case, package one is a parent of package two
*
@var
array
*
@see
phpDocumentor_IntermediateParser::$package_parents
*/
var
$package_parents
;
/**
* Packages associated with categories
*
* Used by the XML:DocBook/peardoc2 converter, and available to others, to
* group many packages into categories
*
@see
phpDocumentor_IntermediateParser::$packagecategories
*
@var
array
*/
var
$packagecategories
;
/**
* All packages encountered in parsing
*
@var
array
*
@see
phpDocumentor_IntermediateParser::$all_packages
*/
var
$all_packages
;
/**
* A list of files that have had source code generated
*
@var
array
*/
var
$sourcePaths
= array
(
)
;
/**
* Controls which of the one-element-only indexes are generated.
*
* Generation of these indexes for large packages is time-consuming. This is an optimization feature. An
* example of how to use this is in
{@link HTMLframesConverter::$leftindex}
, and in
{@link HTMLframesConverter::formatLeftIndex()}
.
* These indexes are intended for use as navigational aids through documentation, but can be used for anything by converters.
*
@see
$class_elements, $page_elements, $function_elements, $define_elements, $global_elements
*
@see
formatLeftIndex()
*
@var
array
*/
var
$leftindex
= array
(
'classes'
=> true
,
'pages'
=> true
,
'functions'
=> true
,
'defines'
=> true
,
'globals'
=> true
)
;
/**
@access
private */
var
$killclass
= false
;
/**
*
@var
string
*
@see
phpDocumentor_IntermediateParser::$title
*/
var
$title
=
'Generated Documentation'
;
/**
* Options for each template, parsed from the options.ini file in the template base directory
*
@tutorial
phpDocumentor/tutorials.pkg#conversion.ppage
*
@var
array
*/
var
$template_options
;
/**
* Tutorials and Extended Documentation parsed from a tutorials/package[/subpackage] directory
*
@tutorial
tutorials.pkg
*
@access
private
*/
var
$tutorials
= array
(
)
;
/**
* tree-format structure of tutorials and their child tutorials, if any
*
@var
array
*
@access
private
*/
var
$tutorial_tree
= false
;
/**
* list of tutorials that have already been processed. Used by @link _setupTutorialTree()
*
@var
array
*
@access
private
*/
var
$processed_tutorials
;
/**
* List of all @todo tags and a link to the element with the @todo
*
* Format: array(package => array(link to element, array(todo
{@link parserTag}
,...)),...)
*
@tutorial
tags.todo.pkg
*
@var
array
*/
var
$todoList
= array
(
)
;
/**
* Directory where compiled templates go - will be deleted on exit
*
*
@var
string
*
@access
private
*/
var
$_compiledDir
= array
(
)
;
/**
* Initialize Converter data structures
*
@param
array
{@link $all_packages}
value
*
@param
array
{@link $package_parents}
value
*
@param
Classes
{@link $classes}
value
*
@param
ProceduralPages
{@link $proceduralpages}
value
*
@param
array
{@link $package_output}
value
*
@param
boolean
{@link $parseprivate}
value
*
@param
boolean
{@link $quietmode}
value
*
@param
string
{@link $targetDir}
value
*
@param
string
{@link $templateDir}
value
*
@param
string
(@link $title} value
*/
function
Converter
(
&
$allp
,
&
$packp
,
&
$classes
,
&
$procpages
,
$po
,
$pp
,
$qm
,
$targetDir
,
$template
,
$title
)
{
$this
->
all_packages
=
$allp
;
$this
->
package_parents
=
$packp
;
$this
->
package
=
$GLOBALS
[
'phpDocumentor_DefaultPackageName'
]
;
$this
->
proceduralpages
=
&
$procpages
;
$this
->
package_output
=
$po
;
if
(
is_array
(
$po
))
{
$a
=
$po
[
0
]
;
$this
->
all_packages
=
array_flip
(
$po
)
;
$this
->
all_packages
[
$a
]
= 1
;
}
$this
->
parseprivate
=
$pp
;
$this
->
quietmode
=
$qm
;
$this
->
classes
=
&
$classes
;
$this
->
roots
=
$classes
->
getRoots
(
$this
->
processSpecialRoots
)
;
$this
->
title
=
$title
;
$this
->
setTemplateDir
(
$template
)
;
$this
->
setTargetdir
(
$targetDir
)
;
}
/**
* Called by IntermediateParser after creation
*
@access
private
*/
function
setTutorials
(
$tutorials
)
{
$this
->
tutorials
=
$tutorials
;
}
/**
*
@param
pkg
|
cls
|
proc
the tutorial type to search for
*
@param
tutorial
name
*
@param
string
package name
*
@param
string
subpackage name, if any
*
@return
false
|
parserTutorial
if the tutorial exists, return it
*/
function
hasTutorial
(
$type
,
$name
,
$package
,
$subpackage
=
''
)
{
if
(
isset
(
$this
->
tutorials
[
$package
]
[
$subpackage
]
[
$type
]
[
$name
.
'.'
.
$type
]
))
return
$this
->
tutorials
[
$package
]
[
$subpackage
]
[
$type
]
[
$name
.
'.'
.
$type
]
;
return
false
;
}
/**
* Called by
{@link walk()}
while converting, when the last class element
* has been parsed.
*
* A Converter can use this method in any way it pleases. HTMLframesConverter
* uses it to complete the template for the class and to output its
* documentation
*
@see
HTMLframesConverter::endClass()
*
@abstract
*/
function
endClass
(
)
{
}
/**
* Called by
{@link walk()}
while converting, when the last procedural page
* element has been parsed.
*
* A Converter can use this method in any way it pleases. HTMLframesConverter
* uses it to complete the template for the procedural page and to output its
* documentation
*
@see
HTMLframesConverter::endClass()
*
@abstract
*/
function
endPage
(
)
{
}
/**
* Called by
{@link walk()}
while converting.
*
* This method is intended to be the place that
{@link $pkg_elements}
is
* formatted for output.
*
@see
HTMLframesConverter::formatPkgIndex()
*
@abstract
*/
function
formatPkgIndex
(
)
{
}
/**
* Called by
{@link walk()}
while converting.
*
* This method is intended to be the place that
{@link $elements}
is
* formatted for output.
*
@see
HTMLframesConverter::formatIndex()
*
@abstract
*/
function
formatIndex
(
)
{
}
/**
* Called by
{@link walk()}
while converting.
*
* This method is intended to be the place that any of
*
{@link $class_elements, $function_elements, $page_elements}
,
*
{@link $define_elements}
, and
{@link $global_elements}
is formatted for
* output, depending on the value of
{@link $leftindex}
*
@see
HTMLframesConverter::formatLeftIndex()
*
@abstract
*/
function
formatLeftIndex
(
)
{
}
/**
* Called by
{@link parserSourceInlineTag::stringConvert()}
to allow
* converters to format the source code the way they'd like.
*
* default returns it unchanged (html with xhtml tags)
*
@param
string
output from highlight_string() - use this function to
* reformat the returned data for Converter-specific output
*
@return
string
*
@deprecated
in favor of tokenizer-based highlighting. This will be
* removed for 2.0
*/
function
unmangle
(
$sourcecode
)
{
return
$sourcecode
;
}
/**
* Initialize highlight caching
*/
function
startHighlight
(
)
{
$this
->
_highlightCache
= array
(
false
,
false
)
;
$this
->
_appendHighlight
=
''
;
}
function
getHighlightState
(
)
{
return
$this
->
_highlightCache
;
}
function
_setHighlightCache
(
$type
,
$token
)
{
$test
=
(
$this
->
_highlightCache
[
0
]
===
$type
&&
$this
->
_highlightCache
[
1
]
==
$token
)
;
if
(
!
$test
)
{
$this
->
_appendHighlight
=
$this
->
flushHighlightCache
(
)
;
}
else
{
$this
->
_appendHighlight
=
''
;
}
$this
->
_highlightCache
= array
(
$type
,
$token
)
;
return
$test
;
}
/**
* Return the close text for the current token
*
@return
string
*/
function
flushHighlightCache
(
)
{
$hc
=
$this
->
_highlightCache
;
$this
->
_highlightCache
= array
(
false
,
false
)
;
if
(
$hc
[
0
]
)
{
if
(
!
isset
(
$this
->
template_options
[
$hc
[
0
]]
[
'/'
.
$hc
[
1
]]
))
{
return
''
;
}
return
$this
->
template_options
[
$hc
[
0
]]
[
'/'
.
$hc
[
1
]]
;
}
return
''
;
}
/**
* Used to allow converters to format the source code the way they'd like.
*
* default returns it unchanged. Mainly used by the
{@link HighlightParser}
*
{@internal
* The method takes information from options.ini, the template options
* file, specifically the [highlightSourceTokens] and [highlightSource]
* sections, and uses them to enclose tokens.
*
* {@source }
}
*
@param
integer
token value from
{@link PHP_MANUAL#tokenizer tokenizer constants}
*
@param
string
contents of token
*
@param
boolean
whether the contents are preformatted or need modification
*
@return
string
*/
function
highlightSource
(
$token
,
$word
,
$preformatted
= false
)
{
if
(
$token
!== false
)
{
if
(
!
$preformatted
)
$word
=
$this
->
postProcess
(
$word
)
;
if
(
isset
(
$this
->
template_options
[
'highlightSourceTokens'
]
[
token_name
(
$token
)
]
))
{
if
(
$this
->
_setHighlightCache
(
'highlightSourceTokens'
,
token_name
(
$token
)))
{
return
$word
;
}
$e
=
$this
->
_appendHighlight
;
return
$e
.
$this
->
template_options
[
'highlightSourceTokens'
]
[
token_name
(
$token
)
]
.
$word
;
}
else
{
$this
->
_setHighlightCache
(
false
,
false
)
;
$e
=
$this
->
_appendHighlight
;
return
$e
.
$word
;
}
}
else
{
if
(
isset
(
$this
->
template_options
[
'highlightSource'
]
[
$word
]
))
{
$newword
=
(
$preformatted
?
$word
:
$this
->
postProcess
(
$word
))
;
if
(
$this
->
_setHighlightCache
(
'highlightSource'
,
$word
))
{
return
$newword
;
}
$e
=
$this
->
_appendHighlight
;
return
$e
.
$this
->
template_options
[
'highlightSource'
]
[
$word
]
.
$newword
;
}
else
{
$this
->
_setHighlightCache
(
false
,
false
)
;
$e
=
$this
->
_appendHighlight
;
return
$e
.
(
$preformatted
?
$word
:
$this
->
postProcess
(
$word
))
;
}
}
}
/**
* Used to allow converters to format the source code of DocBlocks the way
* they'd like.
*
* default returns it unchanged. Mainly used by the
{@link HighlightParser}
*
{@internal
* The method takes information from options.ini, the template options
* file, specifically the [highlightDocBlockSourceTokens] section, and uses
* it to enclose tokens.
*
* {@source }
}
*
@param
string
name of docblock token type
*
@param
string
contents of token
*
@param
boolean
whether the contents are preformatted or need modification
*
@return
string
*/
function
highlightDocBlockSource
(
$token
,
$word
,
$preformatted
= false
)
{
if
(
empty
(
$word
))
{
$this
->
_setHighlightCache
(
false
,
false
)
;
$e
=
$this
->
_appendHighlight
;
return
$e
.
$word
;
}
if
(
isset
(
$this
->
template_options
[
'highlightDocBlockSourceTokens'
]
[
$token
]
))
{
if
(
!
$preformatted
)
$word
=
$this
->
postProcess
(
$word
)
;
if
(
$this
->
_setHighlightCache
(
'highlightDocBlockSourceTokens'
,
$token
))
{
return
$word
;
}
$e
=
$this
->
_appendHighlight
;
return
$e
.
$this
->
template_options
[
'highlightDocBlockSourceTokens'
]
[
$token
]
.
$word
;
}
else
{
$this
->
_setHighlightCache
(
false
,
false
)
;
$e
=
$this
->
_appendHighlight
;
return
$e
.
(
$preformatted
?
$word
:
$this
->
postProcess
(
$word
))
;
}
}
/**
* Used to allow converters to format the source code of Tutorial XML the way
* they'd like.
*
* default returns it unchanged. Mainly used by the
{@link HighlightParser}
*
{@internal
* The method takes information from options.ini, the template options
* file, specifically the [highlightDocBlockSourceTokens] section, and uses
* it to enclose tokens.
*
* {@source }
}
*
@param
string
name of docblock token type
*
@param
string
contents of token
*
@param
boolean
whether the contents are preformatted or need modification
*
@return
string
*/
function
highlightTutorialSource
(
$token
,
$word
,
$preformatted
= false
)
{
if
(
empty
(
$word
))
{
$this
->
_setHighlightCache
(
false
,
false
)
;
$e
=
$this
->
_appendHighlight
;
return
$e
.
$word
;
}
if
(
isset
(
$this
->
template_options
[
'highlightTutorialSourceTokens'
]
[
$token
]
))
{
if
(
!
$preformatted
)
$word
=
$this
->
postProcess
(
$word
)
;
if
(
$this
->
_setHighlightCache
(
'highlightTutorialSourceTokens'
,
$token
))
{
return
$word
;
}
$e
=
$this
->
_appendHighlight
;
return
$e
.
$this
->
template_options
[
'highlightTutorialSourceTokens'
]
[
$token
]
.
$word
;
}
else
{
$this
->
_setHighlightCache
(
false
,
false
)
;
$e
=
$this
->
_appendHighlight
;
return
$e
.
(
$preformatted
?
$word
:
$this
->
postProcess
(
$word
))
;
}
}
/**
* Called by
{@link parserReturnTag::Convert()}
to allow converters to
* change type names to desired formatting
*
* Used by
{@link XMLDocBookConverter::type_adjust()}
to change true and
* false to the peardoc2 values
*
@param
string
*
@return
string
*/
function
type_adjust
(
$typename
)
{
return
$typename
;
}
/**
* Used to convert the {@}example} inline tag in a docblock.
*
* By default, this just wraps ProgramExample
*
@see
XMLDocBookpeardoc2Converter::exampleProgramExample
*
@param
string
*
@param
boolean
true if this is to highlight a tutorial <programlisting>
*
@return
string
*/
function
exampleProgramExample
(
$example
,
$tutorial
= false
,
$inlinesourceparse
= null
/*false*/
,
$class
= null
/*false*/
,
$linenum
= null
/*false*/
,
$filesourcepath
= null
/*false*/
)
{
return
$this
->
ProgramExample
(
$example
,
$tutorial
,
$inlinesourceparse
,
$class
,
$linenum
,
$filesourcepath
)
;
}
/**
* Used to convert the <<code>> tag in a docblock
*
@param
string
*
@param
boolean
true if this is to highlight a tutorial <programlisting>
*
@return
string
*/
function
ProgramExample
(
$example
,
$tutorial
= false
,
$inlinesourceparse
= null
/*false*/
,
$class
= null
/*false*/
,
$linenum
= null
/*false*/
,
$filesourcepath
= null
/*false*/
)
{
$this
->
highlightingSource
= true
;
if
(
tokenizer_ext
)
{
$e
=
$example
;
if
(
!
is_array
(
$example
))
{
$obj
= new
phpDocumentorTWordParser
;
$obj
->
setup
(
$example
)
;
$e
=
$obj
->
getFileSource
(
)
;
$bOpenTagFound
= false
;
foreach
(
$e
as
$ke
=>
$ee
)
{
foreach
(
$ee
as
$kee
=>
$eee
)
{
if
(
(int)
$e
[
$ke
]
[
$kee
]
[
0
]
== T_OPEN_TAG
)
{
$bOpenTagFound
= true
;
}
}
}
if
(
!
$bOpenTagFound
)
{
$example
=
"<?php\n"
.
$example
;
$obj
->
setup
(
$example
)
;
$e
=
$obj
->
getFileSource
(
)
;
unset
(
$e
[
0
]
)
;
$e
=
array_values
(
$e
)
;
}
unset
(
$obj
)
;
}
$saveclass
=
$this
->
class
;
$parser
= new
phpDocumentor_HighlightParser
;
if
(
!
isset
(
$inlinesourceparse
))
{
$example
=
$parser
->
parse
(
$e
,
$this
,
true
)
;
// force php mode
}
else
{
if
(
isset
(
$filesourcepath
))
{
$example
=
$parser
->
parse
(
$e
,
$this
,
$inlinesourceparse
,
$class
,
$linenum
,
$filesourcepath
)
;
}
elseif
(
isset
(
$linenum
))
{
$example
=
$parser
->
parse
(
$e
,
$this
,
$inlinesourceparse
,
$class
,
$linenum
)
;
}
elseif
(
isset
(
$class
))
{
$example
=
$parser
->
parse
(
$e
,
$this
,
$inlinesourceparse
,
$class
)
;
}
else
{
$example
=
$parser
->
parse
(
$e
,
$this
,
$inlinesourceparse
)
;
}
}
$this
->
class
=
$saveclass
;
}
else
{
$example
=
$this
->
postProcess
(
$example
)
;
}
$this
->
highlightingSource
= false
;
if
(
$tutorial
)
{
return
$example
;
}
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
))
return
$example
;
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
[
'code'
]
))
return
$example
;
$example
=
$this
->
template_options
[
'desctranslate'
]
[
'code'
]
.
$example
;
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
[
'/code'
]
))
return
$example
;
return
$example
.
$this
->
template_options
[
'desctranslate'
]
[
'/code'
]
;
}
/**
*
@param
string
*/
function
TutorialExample
(
$example
)
{
$this
->
highlightingSource
= true
;
$parse
= new
phpDocumentor_TutorialHighlightParser
;
$x
=
$parse
->
parse
(
$example
,
$this
)
;
$this
->
highlightingSource
= false
;
return
$x
;
}
/**
* Used to convert the contents of <<li>> in a docblock
*
@param
string
*
@return
string
*/
function
ListItem
(
$item
)
{
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
))
return
$item
;
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
[
'li'
]
))
return
$item
;
$item
=
$this
->
template_options
[
'desctranslate'
]
[
'li'
]
.
$item
;
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
[
'/li'
]
))
return
$item
;
return
$item
.
$this
->
template_options
[
'desctranslate'
]
[
'/li'
]
;
}
/**
* Used to convert the contents of <<ol>> or <<ul>> in a docblock
*
@param
string
*
@return
string
*/
function
EncloseList
(
$list
,
$ordered
)
{
$listname
=
(
$ordered
?
'ol'
:
'ul'
)
;
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
))
return
$list
;
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
[
$listname
]
))
return
$list
;
$list
=
$this
->
template_options
[
'desctranslate'
]
[
$listname
]
.
$list
;
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
[
'/'
.
$listname
]
))
return
$list
;
return
$list
.
$this
->
template_options
[
'desctranslate'
]
[
'/'
.
$listname
]
;
}
/**
* Used to convert the contents of <<pre>> in a docblock
*
@param
string
*
@return
string
*/
function
PreserveWhiteSpace
(
$string
)
{
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
))
return
$string
;
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
[
'pre'
]
))
return
$string
;
$string
=
$this
->
template_options
[
'desctranslate'
]
[
'pre'
]
.
$string
;
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
[
'/pre'
]
))
return
$string
;
return
$string
.
$this
->
template_options
[
'desctranslate'
]
[
'/pre'
]
;
}
/**
* Used to enclose a paragraph in a docblock
*
@param
string
*
@return
string
*/
function
EncloseParagraph
(
$para
)
{
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
))
return
$para
;
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
[
'p'
]
))
return
$para
;
$para
=
$this
->
template_options
[
'desctranslate'
]
[
'p'
]
.
$para
;
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
[
'/p'
]
))
return
$para
;
return
$para
.
$this
->
template_options
[
'desctranslate'
]
[
'/p'
]
;
}
/**
* Used to convert the contents of <<b>> in a docblock
*
@param
string
*
@return
string
*/
function
Bolden
(
$para
)
{
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
))
return
$para
;
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
[
'b'
]
))
return
$para
;
$para
=
$this
->
template_options
[
'desctranslate'
]
[
'b'
]
.
$para
;
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
[
'/b'
]
))
return
$para
;
return
$para
.
$this
->
template_options
[
'desctranslate'
]
[
'/b'
]
;
}
/**
* Used to convert the contents of <<i>> in a docblock
*
@param
string
*
@return
string
*/
function
Italicize
(
$para
)
{
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
))
return
$para
;
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
[
'i'
]
))
return
$para
;
$para
=
$this
->
template_options
[
'desctranslate'
]
[
'i'
]
.
$para
;
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
[
'/i'
]
))
return
$para
;
return
$para
.
$this
->
template_options
[
'desctranslate'
]
[
'/i'
]
;
}
/**
* Used to convert the contents of <<var>> in a docblock
*
@param
string
*
@return
string
*/
function
Varize
(
$para
)
{
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
))
return
$para
;
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
[
'var'
]
))
return
$para
;
$para
=
$this
->
template_options
[
'desctranslate'
]
[
'var'
]
.
$para
;
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
[
'/var'
]
))
return
$para
;
return
$para
.
$this
->
template_options
[
'desctranslate'
]
[
'/var'
]
;
}
/**
* Used to convert the contents of <<kbd>> in a docblock
*
@param
string
*
@return
string
*/
function
Kbdize
(
$para
)
{
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
))
return
$para
;
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
[
'kbd'
]
))
return
$para
;
$para
=
$this
->
template_options
[
'desctranslate'
]
[
'kbd'
]
.
$para
;
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
[
'/kbd'
]
))
return
$para
;
return
$para
.
$this
->
template_options
[
'desctranslate'
]
[
'/kbd'
]
;
}
/**
* Used to convert the contents of <<samp>> in a docblock
*
@param
string
*
@return
string
*/
function
Sampize
(
$para
)
{
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
))
return
$para
;
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
[
'samp'
]
))
return
$para
;
$para
=
$this
->
template_options
[
'desctranslate'
]
[
'samp'
]
.
$para
;
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
[
'/samp'
]
))
return
$para
;
return
$para
.
$this
->
template_options
[
'desctranslate'
]
[
'/samp'
]
;
}
/**
* Used to convert <<br>> in a docblock
*
@param
string
*
@return
string
*/
function
Br
(
$para
)
{
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
))
return
$para
;
if
(
!
isset
(
$this
->
template_options
[
'desctranslate'
]
[
'br'
]
))
return
$para
;
$para
=
$this
->
template_options
[
'desctranslate'
]
[
'br'
]
.
$para
;
return
$para
;
}
/**
* This version does nothing
*
* Perform necessary post-processing of string data. For example, the HTML
* Converters should escape < and > to become < and >
*
@return
string
*/
function
postProcess
(
$text
)
{
return
$text
;
}
/**
* Creates a table of contents for a {@}toc} inline tag in a tutorial
*
* This function should return a formatted table of contents. By default, it
* does nothing, it is up to the converter to format the TOC
*
@abstract
*
@return
string
table of contents formatted for use in the current output format
*
@param
array
format: array(array('tagname' => section, 'link' => returnsee link, 'id' => anchor name, 'title' => from title tag),...)
*/
function
formatTutorialTOC
(
$toc
)
{
return
''
;
}
/**
* Write out the formatted source code for a php file
*
* This function provides the primary functionality for the
*
{@tutorial tags.filesource.pkg}
tag.
*
@param
string
full path to the file
*
@param
string
fully highlighted/linked source code of the file
*
@abstract
*/
function
writeSource
(
$filepath
,
$source
)
{
debug
(
$source
)
;
return
;
}
/**
* Write out the formatted source code for an example php file
*
* This function provides the primary functionality for the
*
{@tutorial tags.example.pkg}
tag.
*
@param
string
example title
*
@param
string
example filename (no path)
*
@param
string
fully highlighted/linked source code of the file
*
@abstract
*/
function
writeExample
(
$title
,
$path
,
$source
)
{
return
;
}
/** Translate the path info into a unique file name for the highlighted
* source code.
*
@param
string
$pathinfo
*
@return
string
*/
function
getFileSourceName
(
$path
)
{
global
$_phpDocumentor_options
;
$pathinfo
=
$this
->
proceduralpages
->
getPathInfo
(
$path
,
$this
)
;
$pathinfo
[
'source_loc'
]
=
str_replace
(
$_phpDocumentor_options
[
'Program_Root'
]
.
'/'
,
''
,
$pathinfo
[
'source_loc'
]
)
;
$pathinfo
[
'source_loc'
]
=
str_replace
(
'/'
,
'_'
,
$pathinfo
[
'source_loc'
]
)
;
return
"
fsource_{
$pathinfo
[
'package'
]
}
_{
$pathinfo
[
'subpackage'
]
}
_{
$pathinfo
[
'source_loc'
]
}
"
;
}
/** Return the fixed path to the source-code file folder.
*
@param
string
$base
Path is relative to this folder
*
@return
string
*/
function
getFileSourcePath
(
$base
)
{
if
(
substr
(
$base
,
strlen
(
$base
)
- 1
)
!=
PATH_DELIMITER
)
{
$base
.=
PATH_DELIMITER
;
}
return
$base
.
'__filesource'
;
}
/** Return the path to the current
*
@param
string
$pathinfo
*
@return
string
*/
function
getCurrentPageURL
(
)
{
return
'{$srcdir}'
.
PATH_DELIMITER
.
$this
->
page_dir
;
}
/**
*
@return
string
an output-format dependent link to phpxref-style highlighted
* source code
*
@abstract
*/
function
getSourceLink
(
$path
)
{
return
''
;
}
/**
*
@return
string
Link to the current page being parsed.
* Should return
{@link $curname}
and a converter-specific extension.
*
@abstract
*/
function
getCurrentPageLink
(
)
{
}
/**
* Return a line of highlighted source code with formatted line number
*
* If the $path is a full path, then an anchor to the line number will be
* added as well
*
@param
integer
line number
*
@param
string
highlighted source code line
*
@param
false
|
string
full path to @filesource file this line is a part of,
* if this is a single line from a complete file.
*
@return
string
formatted source code line with line number
*/
function
sourceLine
(
$linenumber
,
$line
,
$path
= false
)
{
if
(
$path
)
{
return
$this
->
getSourceAnchor
(
$path
,
$linenumber
)
.
$this
->
Br
(
sprintf
(
'%-6u'
,
$linenumber
)
.
str_replace
(
"\n"
,
''
,
$line
))
;
}
else
{
return
$this
->
Br
(
sprintf
(
'%-6u'
,
$linenumber
)
.
str_replace
(
"\n"
,
''
,
$line
))
;
}
}
/**
* Determine whether an element's file has generated source code, used for
* linking to line numbers of source.
*
* Wrapper for
{@link $sourcePaths}
in this version
*
*
{@internal since file paths get stored with most/all slashes
* set to forward slash '/', we need to doublecheck that
* we're not given a backslashed path to search for...
* if we are, it's likely that it was originally stored
* with a forward slash. Further, I'm not convinced it's safe
* to just check the {@link PHPDOCUMENTOR_WINDOWS} flag, so I'm checking
* specifically for backslashes intead.}}
}
*
*
@param
string
full path to the source code file
*
@return
boolean
*/
function
hasSourceCode
(
$path
)
{
return
isset
(
$this
->
sourcePaths
[
$path
]
)
;
if
(
strpos
(
$path
,
'\\'
)
> -1
)
{
$modifiedPath
=
str_replace
(
'\\'
,
'/'
,
$path
)
;
return
isset
(
$this
->
sourcePaths
[
$modifiedPath
]
)
;
}
else
{
return
isset
(
$this
->
sourcePaths
[
$path
]
)
;
}
}
/**
* Mark a file as having had source code highlighted
*
@param
string
full path of source file
*/
function
setSourcePaths
(
$path
)
{
$this
->
sourcePaths
[
$path
]
= true
;
}
/**
* Used to translate an XML DocBook entity like ” from a tutorial by
* reading the options.ini file for the template.
*
@param
string
entity name
*/
function
TranslateEntity
(
$name
)
{
if
(
!
isset
(
$this
->
template_options
[
'ppage'
]
))
{
if
(
!
$this
->
template_options
[
'preservedocbooktags'
]
)
return
''
;
else
return
'&'
.
$name
.
';'
;
}
if
(
isset
(
$this
->
template_options
[
'ppage'
]
[
'&'
.
$name
.
';'
]
))
{
return
$this
->
template_options
[
'ppage'
]
[
'&'
.
$name
.
';'
]
;
}
else
{
if
(
!
$this
->
template_options
[
'preservedocbooktags'
]
)
return
''
;
else
return
'&'
.
$name
.
';'
;
}
}
/**
* Used to translate an XML DocBook tag from a tutorial by reading the
* options.ini file for the template.
*
@param
string
tag name
*
@param
string
any attributes Format: array(name => value)
*
@param
string
the tag contents, if any
*
@param
string
the tag contents, if any, unpost-processed
*
@return
string
*/
function
TranslateTag
(
$name
,
$attr
,
$cdata
,
$unconvertedcdata
)
{
if
(
!
isset
(
$this
->
template_options
[
'ppage'
]
))
{
if
(
!
$this
->
template_options
[
'preservedocbooktags'
]
)
return
$cdata
;
else
return
'<'
.
$name
.
$this
->
AttrToString
(
$name
,
$attr
,
true
)
.
'>'
.
$cdata
.
'</'
.
$name
.
'>'
.
"\n"
;
}
// make sure this template transforms the tag into something
if
(
isset
(
$this
->
template_options
[
'ppage'
]
[
$name
]
))
{
// test for global attribute transforms like $attr$role = class, changing
// all role="*" attributes to class="*" in html, for example
foreach
(
$attr
as
$att
=>
$val
)
{
if
(
isset
(
$this
->
template_options
[
'$attr$'
.
$att
]
))
{
$new
=
''
;
if
(
!
isset
(
$this
->
template_options
[
'$attr$'
.
$att
]
[
'close'
]
))
{
$new
.=
'<'
.
$this
->
template_options
[
'$attr$'
.
$att
]
[
'open'
]
;
if
(
isset
(
$this
->
template_options
[
'$attr$'
.
$att
]
[
'cdata!'
]
))
{
if
(
isset
(
$this
->
template_options
[
'$attr$'
.
$att
]
[
'separateall'
]
))
$new
.=
$this
->
template_options
[
'$attr$'
.
$att
]
[
'separator'
]
;
else
$new
.=
' '
;
$new
.=
$this
->
template_options
[
'$attr$'
.
$att
]
[
'$'
.
$att
]
;
$new
.=
$this
->
template_options
[
'$attr$'
.
$att
]
[
'separator'
]
;
if
(
$this
->
template_options
[
'$attr$'
.
$att
]
[
'quotevalues'
]
)
$val
=
'"'
.
$val
.
'"'
;
$new
.=
$val
.
'>'
;
}
else
{
$new
.=
'>'
.
$val
;
}
$new
.=
'</'
.
$this
->
template_options
[
'$attr$'
.
$att
]
[
'open'
]
.
'>'
;
}
else
{
$new
.=
$this
->
template_options
[
'$attr$'
.
$att
]
[
'open'
]
.
$val
.
$this
->
template_options
[
'$attr$'
.
$att
]
[
'close'
]
;
}
unset
(
$attr
[
$att
]
)
;
$cdata
=
$new
.
$cdata
;
}
}
if
(
!
isset
(
$this
->
template_options
[
'ppage'
]
[
'/'
.
$name
]
))
{
// if the close tag isn't specified, we put opening and closing tags around it, with translated attributes
if
(
isset
(
$this
->
template_options
[
'ppage'
]
[
$name
.
'/'
]
))
$cdata
=
'<'
.
$this
->
template_options
[
'ppage'
]
[
$name
]
.
$this
->
AttrToString
(
$name
,
$attr
)
.
'/>'
.
$cdata
;
else
$cdata
=
'<'
.
$this
->
template_options
[
'ppage'
]
[
$name
]
.
$this
->
AttrToString
(
$name
,
$attr
)
.
'>'
.
$cdata
.
'</'
.
$this
->
template_options
[
'ppage'
]
[
$name
]
.
'>'
;
}
else
{
// if close tag is specified, use the open and close as literal
if
(
$name
==
'programlisting'
&& isset
(
$attr
[
'role'
]
)
&&
(
$attr
[
'role'
]
==
'php'
||
$attr
[
'role'
]
==
'tutorial'
||
$attr
[
'role'
]
==
'html'
))
{
// highlight PHP source
// var_dump($unconvertedcdata, $cdata);exit;
if
(
$attr
[
'role'
]
==
'php'
)
{
$cdata
=
$this
->
ProgramExample
(
$unconvertedcdata
,
true
)
;
}
elseif
(
$attr
[
'role'
]
==
'tutorial'
)
{
$cdata
=
$this
->
TutorialExample
(
$unconvertedcdata
)
;
}
elseif
(
$attr
[
'role'
]
==
'html'
)
{
$cdata
=
$unconvertedcdata
;
}
}
else
{
// normal case below
$cdata
=
$this
->
template_options
[
'ppage'
]
[
$name
]
.
$this
->
AttrToString
(
$name
,
$attr
)
.
$cdata
.
$this
->
template_options
[
'ppage'
]
[
'/'
.
$name
]
;
}
}
return
$cdata
;
}
else
{
if
(
$this
->
template_options
[
'preservedocbooktags'
]
)
{
return
'<'
.
$name
.
$this
->
AttrToString
(
$name
,
$attr
,
true
)
.
'>'
.
$cdata
.
'</'
.
$name
.
'>'
.
"\n"
;
}
else
{
return
$cdata
;
}
}
}
/**
* Convert the attribute of a Tutorial docbook tag's attribute list
* to a string based on the template options.ini
*
@param
string
tag name
*
@param
attribute
array
*
@param
boolean
if true, returns attrname="value"...
*
@return
string
*/
function
AttrToString
(
$tag
,
$attr
,
$unmodified
= false
)
{
$ret
=
''
;
if
(
$unmodified
)
{
$ret
=
' '
;
foreach
(
$attr
as
$n
=>
$v
)
{
$ret
.=
$n
.
' = "'
.
$v
.
'"'
;
}
return
$ret
;
}
// no_attr tells us to ignore all attributes
if
(
isset
(
$this
->
template_options
[
'no_attr'
]
))
return
$ret
;
// tagname! tells us to ignore all attributes for this tag
if
(
isset
(
$this
->
template_options
[
'ppage'
]
[
$tag
.
'!'
]
))
return
$ret
;
if
(
count
(
$attr
))
$ret
=
' '
;
// pass 1, check to see if any attributes add together
$same
= array
(
)
;
foreach
(
$attr
as
$n
=>
$v
)
{
if
(
isset
(
$this
->
template_options
[
'ppage'
]
[
$tag
.
'->'
.
$n
]
))
{
$same
[
$this
->
template_options
[
'ppage'
]
[
$tag
.
'->'
.
$n
]]
[
]
=
$n
;
}
}
foreach
(
$attr
as
$n
=>
$v
)
{
if
(
isset
(
$this
->
template_options
[
'ppage'
]
[
$tag
.
'->'
.
$n
]
))
{
if
(
count
(
$same
[
$this
->
template_options
[
'ppage'
]
[
$tag
.
'->'
.
$n
]]
)
== 1
)
{
// only 1 attribute translated for this one
// this is useful for equivalent value names
if
(
isset
(
$this
->
template_options
[
'ppage'
]
[
$tag
.
'->'
.
$n
.
'+'
.
$v
]
))
$v
=
$this
->
template_options
[
'ppage'
]
[
$tag
.
'->'
.
$n
.
'+'
.
$v
]
;
}
else
{
// more than 1 attribute combines to make the new attribute
$teststrtemp
= array
(
)
;
foreach
(
$same
[
$this
->
template_options
[
'ppage'
]
[
$tag
.
'->'
.
$n
]]
as
$oldattr
)
{
$teststrtemp
[
]
=
$oldattr
.
'+'
.
$attr
[
$oldattr
]
;
}
$teststrs
= array
(
)
;
$num
=
count
(
$same
[
$this
->
template_options
[
'ppage'
]
[
$tag
.
'->'
.
$n
]]
)
;
for
(
$i
=0
;
$i
<
$num
;
$i
++
)
{
$started
= false
;
$a
=
''
;
for
(
$j
=
$i
;
!
$started
||
$j
!=
$i
;
$j
=
(
$j
+
$i
)
%
$num
)
{
if
(
!
empty
(
$a
))
$a
.=
'|'
;
$a
.=
$teststrtemp
[
$j
]
;
}
$teststrs
[
$i
]
=
$a
;
}
$done
= false
;
foreach
(
$teststrs
as
$test
)
{
if
(
$done
)
break
;
if
(
isset
(
$this
->
template_options
[
'ppage'
]
[
$tag
.
'->'
.
$test
]
))
{
$done
= true
;
$v
=
$this
->
template_options
[
'ppage'
]
[
$tag
.
'->'
.
$test
]
;
}
}
}
$ret
.=
$this
->
template_options
[
'ppage'
]
[
$tag
.
'->'
.
$n
]
.
' = "'
.
$v
.
'"'
;
}
else
{
if
(
!
isset
(
$this
->
template_options
[
'ppage'
]
[
$tag
.
'!'
.
$n
]
))
{
if
(
isset
(
$this
->
template_options
[
'ppage'
]
[
'$attr$'
.
$n
]
))
$ret
.=
$this
->
template_options
[
'ppage'
]
[
'$attr$'
.
$n
]
.
' = "'
.
$v
.
'"'
;
else
$ret
.=
$n
.
' = "'
.
$v
.
'"'
;
}
}
}
return
$ret
;
}
/**
* Convert the title of a Tutorial docbook tag section
* to a string based on the template options.ini
*
@param
string
tag name
*
@param
array
*
@param
string
title text
*
@param
string
*
@return
string
*/
function
ConvertTitle
(
$tag
,
$attr
,
$title
,
$cdata
)
{
if
(
!
isset
(
$this
->
template_options
[
$tag
.
'_title'
]
))
return
array
(
$attr
,
$cdata
)
;
if
(
isset
(
$this
->
template_options
[
$tag
.
'_title'
]
[
'tag_attr'
]
))
{
$attr
[
$this
->
template_options
[
$tag
.
'_title'
]
[
'tag_attr'
]]
=
urlencode
(
$cdata
)
;
$cdata
=
''
;
}
elseif
(
isset
(
$this
->
template_options
[
$tag
.
'_title'
]
[
'cdata_start'
]
))
{
$cdata
=
$this
->
template_options
[
$tag
.
'_title'
]
[
'open'
]
.
$title
.
$this
->
template_options
[
$tag
.
'_title'
]
[
'close'
]
.
$cdata
;
}
else
$cdata
=
$title
.
$cdata
;
return
array
(
$attr
,
$cdata
)
;
}
/**
* Return a converter-specific id to distinguish tutorials and their
* sections
*
* Used by {@}id}
*
@return
string
*/
function
getTutorialId
(
$package
,
$subpackage
,
$tutorial
,
$id
)
{
return
$package
.
$subpackage
.
$tutorial
.
$id
;
}
/**
* Create the
{@link $elements, $pkg_elements}
and
{@link $links}
arrays
*
@access
private
*
@todo
version 2.0 - faulty package_output logic should be removed
*
* in this version, if the parent file isn't in the package, all
* the procedural elements are simply shunted to another package!
*/
function
_createPkgElements
(
&
$pages
)
{
if
(
empty
(
$this
->
elements
))
{
$this
->
elements
= array
(
)
;
$this
->
pkg_elements
= array
(
)
;
$this
->
links
= array
(
)
;
phpDocumentor_out
(
'Building indexes...'
)
;
flush
(
)
;
foreach
(
$pages
as
$j
=>
$flub
)
{
$this
->
package
=
$pages
[
$j
]
->
parent
->
package
;
$this
->
subpackage
=
$pages
[
$j
]
->
parent
->
subpackage
;
$this
->
class
= false
;
$this
->
curfile
=
$pages
[
$j
]
->
parent
->
getFile
(
)
;
$this
->
curname
=
$this
->
getPageName
(
$pages
[
$j
]
->
parent
)
;
$this
->
curpath
=
$pages
[
$j
]
->
parent
->
getPath
(
)
;
$use
= true
;
if
(
$this
->
package_output
)
{
if
(
in_array
(
$this
->
package
,
$this
->
package_output
))
{
$this
->
addElement
(
$pages
[
$j
]
->
parent
,
$pages
[
$j
]
)
;
}
else
{
if
(
count
(
$pages
[
$j
]
->
classelements
))
{
list
(
,
$pages
[
$j
]
->
parent
->
package
)
=
each
(
$this
->
package_output
)
;
reset
(
$this
->
package_output
)
;
$pages
[
$j
]
->
parent
->
subpackage =
''
;
$this
->
addElement
(
$pages
[
$j
]
->
parent
,
$pages
[
$j
]
)
;
}
else
{
unset
(
$pages
[
$j
]
)
;
continue
;
}
}
}
else
{
$this
->
addElement
(
$pages
[
$j
]
->
parent
,
$pages
[
$j
]
)
;
}
if
(
$use
)
for
(
$i
=0
;
$i
<
count
(
$pages
[
$j
]
->
elements
)
;
$i
++
)
{
$pages
[
$j
]
->
elements
[
$i
]
->
docblock
->
package =
$this
->
package
;
$pages
[
$j
]
->
elements
[
$i
]
->
docblock
->
subpackage =
$this
->
subpackage
;
$this
->
proceduralpages
->
replaceElement
(
$pages
[
$j
]
->
elements
[
$i
]
)
;
$this
->
addElement
(
$pages
[
$j
]
->
elements
[
$i
]
)
;
}
for
(
$i
=0
;
$i
<
count
(
$pages
[
$j
]
->
classelements
)
;
$i
++
)
{
if
(
$this
->
class
)
{
if
(
$pages
[
$j
]
->
classelements
[
$i
]
->
type ==
'class'
)
{
if
(
$this
->
checkKillClass
(
$pages
[
$j
]
->
classelements
[
$i
]
->
getName
(
)
,
$pages
[
$j
]
->
classelements
[
$i
]
->
getPath
(
)))
continue
;
$this
->
package
=
$pages
[
$j
]
->
classelements
[
$i
]
->
docblock
->
package
;
if
(
$this
->
package_output
)
if
(
!
in_array
(
$this
->
package
,
$this
->
package_output
))
continue
;
$this
->
subpackage
=
$pages
[
$j
]
->
classelements
[
$i
]
->
docblock
->
subpackage
;
$this
->
class
=
$pages
[
$j
]
->
classelements
[
$i
]
->
name
;
}
else
{
if
(
$this
->
killclass
)
continue
;
// force all contained elements to have parent package/subpackage
$pages
[
$j
]
->
classelements
[
$i
]
->
docblock
->
package =
$this
->
package
;
$pages
[
$j
]
->
classelements
[
$i
]
->
docblock
->
subpackage =
$this
->
subpackage
;
}
}
if
(
$pages
[
$j
]
->
classelements
[
$i
]
->
type ==
'class'
)
{
if
(
$this
->
checkKillClass
(
$pages
[
$j
]
->
classelements
[
$i
]
->
getName
(
)
,
$pages
[
$j
]
->
classelements
[
$i
]
->
getPath
(
)))
continue
;
$this
->
package
=
$pages
[
$j
]
->
classelements
[
$i
]
->
docblock
->
package
;
if
(
$this
->
package_output
)
if
(
!
in_array
(
$this
->
package
,
$this
->
package_output
))
continue
;
$this
->
subpackage
=
$pages
[
$j
]
->
classelements
[
$i
]
->
docblock
->
subpackage
;
$this
->
class
=
$pages
[
$j
]
->
classelements
[
$i
]
->
name
;
}
if
(
!
$this
->
killclass
)
$this
->
addElement
(
$pages
[
$j
]
->
classelements
[
$i
]
)
;
}
}
phpDocumentor_out
(
"done\n"
)
;
flush
(
)
;
}
$this
->
sortIndexes
(
)
;
$this
->
sortTodos
(
)
;
if
(
$this
->
sort_page_contents_by_type
)
$this
->
sortPageContentsByElementType
(
$pages
)
;
}
/**
* Process the
{@link $tutorials}
array
*
* Using the tutorialname.ext.ini files, this method sets up tutorial
* hierarchy. There is some minimal error checking to make sure that no
* tutorial links to itself, even two levels deep as in tute->next->tute.
*
* If all tests pass, it creates the hierarchy
*
@uses
generateTutorialOrder()
*
@uses
_setupTutorialTree()
*
@access
private
*/
function
_processTutorials
(
)
{
$parents
=
$all
= array
(
)
;
foreach
(
$this
->
tutorials
as
$package
=>
$els
)
{
if
(
$this
->
package_output
)
{
if
(
!
in_array
(
$package
,
$this
->
package_output
))
{
unset
(
$this
->
tutorials
[
$package
]
)
;
continue
;
}
}
if
(
!
isset
(
$this
->
pkg_elements
[
$package
]
))
{
unset
(
$this
->
tutorials
[
$package
]
)
;
continue
;
}
foreach
(
$els
as
$subpackage
=>
$els2
)
{
foreach
(
$els2
as
$type
=>
$tutorials
)
{
foreach
(
$tutorials
as
$tutorial
)
{
if
(
$tutorial
->
ini
)
{
if
(
isset
(
$tutorial
->
ini
[
'Linked Tutorials'
]
))
{
foreach
(
$tutorial
->
ini
[
'Linked Tutorials'
]
as
$child
)
{
$sub
=
(
empty
(
$tutorial
->
subpackage
)
?
''
:
$tutorial
->
subpackage .
'/'
)
;
$kid
=
$tutorial
->
package .
'/'
.
$sub
.
$child
.
'.'
.
$tutorial
->
tutorial_type
;
// parent includes self as a linked tutorial?
$kidlink
=
$this
->
getTutorialLink
(
$kid
,
false
,
false
,
array
(
$tutorial
->
package
))
;
if
(
is_object
(
$kidlink
)
&&
$this
->
returnSee
(
$kidlink
)
==
$tutorial
->
getLink
(
$this
))
{
// bad!
addErrorDie
(
PDERROR_TUTORIAL_IS_OWN_CHILD
,
$tutorial
->
name
,
$tutorial
->
name.
'.ini'
)
;
}
}
$parents
[
]
=
$tutorial
;
}
}
$all
[
$package
]
[
$subpackage
]
[
$type
]
[
]
=
$tutorial
;
}
}
}
}
// loop error-checking, use this to eliminate possibility of accidentally linking to a parent as a child
$testlinks
= array
(
)
;
foreach
(
$parents
as
$parent
)
{
$testlinks
[
$parent
->
name
]
[
'links'
]
[
]
=
$parent
->
getLink
(
$this
)
;
$testlinks
[
$parent
->
name
]
[
'name'
]
[
$parent
->
getLink
(
$this
)
]
=
$parent
->
name
;
}
// generate the order of tutorials, and link them together
foreach
(
$parents
as
$parent
)
{
foreach
(
$parent
->
ini
[
'Linked Tutorials'
]
as
$child
)
{
$sub
=
(
empty
(
$parent
->
subpackage
)
?
''
:
$parent
->
subpackage .
'/'
)
;
$kid
=
$parent
->
package .
'/'
.
$sub
.
$child
.
'.'
.
$parent
->
tutorial_type
;
// child tutorials must be in the same package AND subpackage
// AND have the same extension as the parent, makes things clearer for both ends
if
(
in_array
(
$this
->
returnSee
(
$this
->
getTutorialLink
(
$kid
,
false
,
false
,
array
(
$parent
->
package
)))
,
$testlinks
[
$parent
->
name
]
[
'links'
]
))
addErrorDie
(
PDERROR_TUTORIAL_IS_OWN_GRANDPA
,
$testlinks
[
$parent
->
name
]
[
$this
->
returnSee
(
$this
->
getTutorialLink
(
$kid
,
false
,
false
,
array
(
$parent
->
package
)))
]
,
$kid
->
name
,
$testlinks
[
$parent
->
name
]
[
$this
->
returnSee
(
$this
->
getTutorialLink
(
$kid
,
false
,
false
,
array
(
$parent
->
package
)))
]
,
$kid
->
name.
'.ini'
)
;
if
(
$this
->
returnSee
(
$this
->
getTutorialLink
(
$kid
,
false
,
false
,
array
(
$parent
->
package
)))
==
$kid
)
{
addWarning
(
PDERROR_CHILD_TUTORIAL_NOT_FOUND
,
$child
.
'.'
.
$parent
->
tutorial_type
,
$parent
->
name .
'.ini'
,
$parent
->
package
,
$parent
->
subpackage
)
;
}
}
}
$new
=
$tree
=
$roots
= array
(
)
;
// build a list of all 'root' tutorials (tutorials without parents).
foreach
(
$parents
as
$i
=>
$parent
)
{
if
(
!
$parent
->
isChildOf
(
$parents
))
{
$roots
[
]
=
$parent
;
}
}
$parents
=
$roots
;
// add the parents and all child tutorials in order to the list of tutorials to process
foreach
(
$parents
as
$parent
)
{
$this
->
generateTutorialOrder
(
$parent
,
$all
,
$new
)
;
}
if
(
count
(
$all
))
{
// add the leftover tutorials
foreach
(
$all
as
$package
=>
$els
)
{
foreach
(
$els
as
$subpackage
=>
$els2
)
{
foreach
(
$els2
as
$type
=>
$tutorials
)
{
foreach
(
$tutorials
as
$tutorial
)
{
$new
[
$package
]
[
$subpackage
]
[
$type
]
[
]
=
$tutorial
;
}
}
}
}
}
// remove the old, unprocessed tutorials, and set it up with the next code
$this
->
tutorials
= array
(
)
;
// reset integrity of the tutorial list
$prev
= false
;
uksort
(
$new
,
'tutorialcmp'
)
;
// debug($this->vardump_tree($new));exit;
foreach
(
$new
as
$package
=>
$els
)
{
foreach
(
$els
as
$subpackage
=>
$els2
)
{
foreach
(
$els2
as
$type
=>
$tutorials
)
{
foreach
(
$tutorials
as
$tutorial
)
{
if
(
$prev
)
{
$this
->
tutorials
[
$prevpackage
]
[
$prevsubpackage
]
[
$prevtype
]
[
$prevname
]
->
setNext
(
$tutorial
,
$this
)
;
$tutorial
->
setPrev
(
$prev
,
$this
)
;
}
$this
->
tutorials
[
$package
]
[
$subpackage
]
[
$type
]
[
$tutorial
->
name
]
=
$tutorial
;
$prev
=
$tutorial
->
getLink
(
$this
,
true
)
;
$prevpackage
=
$package
;
$prevsubpackage
=
$subpackage
;
$prevtype
=
$type
;
$prevname
=
$tutorial
->
name
;
}
}
}
}
$this
->
tutorial_tree
=
$this
->
_setupTutorialTree
(
)
;
return
$new
;
}
/**
* called by
{@link phpDocumentor_IntermediateParser::Convert()}
to traverse
* the array of pages and their elements, converting them to the output format
*
* The walk() method should be flexible enough such that it never needs
* modification. walk() sets up all of the indexes, and sorts everything in
* logical alphabetical order. It then passes each element individually to
*
{@link Convert()}
, which then passes to the Convert*() methods. A child
* Converter need not override any of these unless special functionality must
* be added. see
{@tutorial Converters/template.vars.cls}
for details.
*
{@internal
* walk() first creates all of the indexes {@link $elements, $pkg_elements}
* and the left indexes specified by {@link $leftindexes},
* and then sorts them by calling {@link sortIndexes()}.
*
* Next, it converts all README/CHANGELOG/INSTALL-style files, using
* {@link Convert_RIC}.
*
* After this, it
* passes all package-level docs to Convert(). Then, it calls the index
* sorting functions {@link formatPkgIndex(), formatIndex()} and
* {@link formatLeftIndex()}.
*
* Finally, it converts each procedural page in alphabetical order. This
* stage passes elements from the physical file to Convert() in alphabetical
* order. First, procedural page elements {@link parserDefine, parserInclude}
* {@link parserGlobal}, and {@link parserFunction} are passed to Convert().
*
* Then, class elements are passed in this order: {@link parserClass}, then
* all of the {@link parserVar}s in the class and all of the
* {@link parserMethod}s in the class. Classes are in alphabetical order,
* and both vars and methods are in alphabetical order.
*
* Finally, {@link ConvertErrorLog()} is called and the data walk is complete.}}
}
*
@param
array
Format: array(fullpath =>
{@link parserData}
structure with full
{@link parserData::$elements}
* and
{@link parserData::$class_elements}
.
*
@param
array
Format: array(
{@link parserPackagePage}
1,
{@link parserPackagePage}
2,...)
*
@uses
Converter::_createPkgElements() sets up
{@link $elements}
and
*
{@link $pkg_elements}
array, as well as
{@link $links}
*/
function
walk
(
&
$pages
,
&
$package_pages
)
{
if
(
empty
(
$pages
))
{
die
(
"<b>ERROR</b>: nothing parsed"
)
;
}
$this
->
_createPkgElements
(
$pages
)
;
if
(
count
(
$this
->
ric
))
{
phpDocumentor_out
(
"Converting README/INSTALL/CHANGELOG contents...\n"
)
;
flush
(
)
;
foreach
(
$this
->
ric
as
$name
=>
$contents
)
{
phpDocumentor_out
(
"
$name
...
"
)
;
flush
(
)
;
$this
->
Convert_RIC
(
$name
,
$contents
)
;
}
phpDocumentor_out
(
"\ndone\n"
)
;
flush
(
)
;
}
foreach
(
$package_pages
as
$i
=>
$perp
)
{
if
(
$this
->
package_output
)
{
if
(
!
in_array
(
$package_pages
[
$i
]
->
package
,
$this
->
package_output
))
continue
;
}
phpDocumentor_out
(
'Converting package page for package '
.
$package_pages
[
$i
]
->
package.
'... '
)
;
flush
(
)
;
$this
->
package
=
$package_pages
[
$i
]
->
package
;
$this
->
subpackage
=
''
;
$this
->
class
= false
;
$this
->
Convert
(
$package_pages
[
$i
]
)
;
phpDocumentor_out
(
"done\n"
)
;
flush
(
)
;
}
phpDocumentor_out
(
"Converting tutorials/extended docs\n"
)
;
flush
(
)
;
// get tutorials into the order they will display, and set next/prev links
$new
=
$this
->
_processTutorials
(
)
;
foreach
(
$this
->
tutorials
as
$package
=>
$els
)
{
foreach
(
$els
as
$subpackage
=>
$els2
)
{
foreach
(
$els2
as
$type
=>
$tutorials
)
{
foreach
(
$tutorials
as
$tutorial
)
{
switch
(
$type
)
{
case
'pkg'
:
$a
=
''
;
if
(
$tutorial
->
ini
)
$a
.=
'Top-level '
;
if
(
!
empty
(
$tutorial
->
subpackage
))
$a
.=
'Sub-'
;
$ptext
=
"
Converting ${a
}
Package-level tutorial
"
.
$tutorial
->
name.
'...'
;
break
;
case
'cls'
:
$a
=
''
;
if
(
$tutorial
->
ini
)
$a
.=
'Top-level '
;
$ptext
=
"
Converting ${a
}
Class-level tutorial
"
.
$tutorial
->
name .
" and associating..."
;
$link
=
Converter
::
getClassLink
(
str_replace
(
'.cls'
,
''
,
$tutorial
->
name
)
,
$tutorial
->
package
)
;
if
(
is_object
(
$link
))
{
if
(
$this
->
sort_absolutely_everything
)
{
$addend
=
'unsuccessful '
;
if
(
isset
(
$this
->
package_elements
[
$tutorial
->
package
]
[
$tutorial
->
subpackage
]
[
'class'
]
[
$link
->
name
]
))
{
$this
->
package_elements
[
$tutorial
->
package
]
[
$tutorial
->
subpackage
]
[
'class'
]
[
$link
->
name
]
[
0
]
->
addTutorial
(
$tutorial
,
$this
)
;
$addend
=
'success '
;
}
}
else
{
$addend
=
'unsuccessful '
;
if
(
!
isset
(
$this
->
classes
->
killclass
[
str_replace
(
'.cls'
,
''
,
$tutorial
->
name
)
]
)
&&
!
isset
(
$this
->
classes
->
killclass
[
str_replace
(
'.cls'
,
''
,
$tutorial
->
name
)
]
[
$tutorial
->
path
]
))
{
foreach
(
$pages
as
$j
=>
$inf
)
{
foreach
(
$inf
->
classelements as
$i
=>
$class
)
{
if
(
$class
->
type ==
'class'
&&
$class
->
name ==
str_replace
(
'.cls'
,
''
,
$tutorial
->
name
)
&&
$class
->
path ==
$link
->
path
)
{
$pages
[
$j
]
->
classelements
[
$i
]
->
addTutorial
(
$tutorial
,
$this
)
;
$addend
=
'success '
;
}
}
}
}
}
$ptext
.=
$addend
;
}
else
$ptext
.=
"unsuccessful "
;
break
;
case
'proc'
:
$a
=
''
;
if
(
$tutorial
->
ini
)
$a
.=
'Top-level '
;
$ptext
=
"
Converting ${a
}
Procedural-level tutorial
"
.
$tutorial
->
name.
" and associating..."
;
$link
=
Converter
::
getPageLink
(
str_replace
(
'.proc'
,
''
,
$tutorial
->
name
)
,
$tutorial
->
package
)
;
if
(
is_object
(
$link
))
{
$addend
=
'unsuccessful '
;
if
(
$this
->
sort_absolutely_everything
)
{
if
(
isset
(
$this
->
package_elements
[
$tutorial
->
package
]
[
$tutorial
->
subpackage
]
[
'page'
]
[
$link
->
path
]
))
{
$this
->
package_elements
[
$tutorial
->
package
]
[
$tutorial
->
subpackage
]
[
'page'
]
[
$link
->
path
]
[
0
]
->
addTutorial
(
$tutorial
,
$this
)
;
$addend
=
"success "
;
}
}
else
{
foreach
(
$pages
as
$j
=>
$info
)
{
if
(
$j
==
$link
->
path
)
{
$pages
[
$j
]
->
addTutorial
(
$tutorial
,
$this
)
;
$addend
=
"success "
;
}
}
}
$ptext
.=
$addend
;
}
else
$ptext
.=
"unsuccessful "
;
break
;
}
phpDocumentor_out
(
$ptext
)
;
flush
(
)
;
$this
->
package
=
$tutorial
->
package
;
$this
->
subpackage
=
$tutorial
->
subpackage
;
$this
->
Convert
(
$tutorial
)
;
phpDocumentor_out
(
"done\n"
)
;
flush
(
)
;
}
}
}
}
phpDocumentor_out
(
"Formatting Package Indexes..."
)
;
flush
(
)
;
$this
->
formatPkgIndex
(
)
;
phpDocumentor_out
(
"done\n"
)
;
flush
(
)
;
phpDocumentor_out
(
"Formatting Index..."
)
;
flush
(
)
;
$this
->
formatIndex
(
)
;
phpDocumentor_out
(
"done\n\n"
)
;
flush
(
)
;
phpDocumentor_out
(
"Formatting Left Quick Index..."
)
;
flush
(
)
;
$this
->
formatLeftIndex
(
)
;
phpDocumentor_out
(
"done\n\n"
)
;
flush
(
)
;
if
(
$this
->
sort_absolutely_everything
)
return
$this
->
walk_everything
(
)
;
foreach
(
$pages
as
$j
=>
$flub
)
{
phpDocumentor_out
(
'Converting '
.
$pages
[
$j
]
->
parent
->
getPath
(
))
;
flush
(
)
;
$this
->
package
=
$pages
[
$j
]
->
parent
->
package
;
$this
->
subpackage
=
$pages
[
$j
]
->
parent
->
subpackage
;
$this
->
class
= false
;
$this
->
curfile
=
$pages
[
$j
]
->
parent
->
getFile
(
)
;
$this
->
curname
=
$this
->
getPageName
(
$pages
[
$j
]
->
parent
)
;
$this
->
curpath
=
$pages
[
$j
]
->
parent
->
getPath
(
)
;
$use
= true
;
if
(
$this
->
package_output
)
{
if
(
in_array
(
$this
->
package
,
$this
->
package_output
))
{
$this
->
Convert
(
$pages
[
$j
]
)
;
}
else
{
$use
= false
;
}
}
else
{
$this
->
Convert
(
$pages
[
$j
]
)
;
}
phpDocumentor_out
(
" Procedural Page Elements..."
)
;
flush
(
)
;
if
(
$use
)
for
(
$i
=0
;
$i
<
count
(
$pages
[
$j
]
->
elements
)
;
$i
++
)
{
$a
=
$pages
[
$j
]
->
elements
[
$i
]
->
docblock
->
getKeyword
(
'access'
)
;
if
(
is_object
(
$a
))
$a
=
$a
->
getString
(
)
;
if
(
!
$this
->
parseprivate
&&
(
$a
==
'private'
))
continue
;
// phpDocumentor_out(" ".$pages[$j]->elements[$i]->name."\n");
$pages
[
$j
]
->
elements
[
$i
]
->
docblock
->
package =
$this
->
package
;
$pages
[
$j
]
->
elements
[
$i
]
->
docblock
->
subpackage =
$this
->
subpackage
;
$this
->
Convert
(
$pages
[
$j
]
->
elements
[
$i
]
)
;
}
phpDocumentor_out
(
" Classes..."
)
;
$this
->
class
= false
;
flush
(
)
;
for
(
$i
=0
;
$i
<
count
(
$pages
[
$j
]
->
classelements
)
;
$i
++
)
{
if
(
$this
->
class
)
{
if
(
$pages
[
$j
]
->
classelements
[
$i
]
->
type ==
'class'
)
{
if
(
!
$this
->
killclass
)
$this
->
endClass
(
)
;
$this
->
killclass
= false
;
if
(
$this
->
checkKillClass
(
$pages
[
$j
]
->
classelements
[
$i
]
->
getName
(
)
,
$pages
[
$j
]
->
classelements
[
$i
]
->
getPath
(
)))
continue
;
$this
->
package
=
$pages
[
$j
]
->
classelements
[
$i
]
->
docblock
->
package
;
if
(
$this
->
package_output
)
if
(
!
in_array
(
$this
->
package
,
$this
->
package_output
))
continue
;
$this
->
subpackage
=
$pages
[
$j
]
->
classelements
[
$i
]
->
docblock
->
subpackage
;
$this
->
class
=
$pages
[
$j
]
->
classelements
[
$i
]
->
name
;
}
else
{
$a
=
$pages
[
$j
]
->
classelements
[
$i
]
->
docblock
->
getKeyword
(
'access'
)
;
if
(
is_object
(
$a
))
$a
=
$a
->
getString
(
)
;
if
(
!
$this
->
parseprivate
&&
(
$a
==
'private'
))
continue
;
if
(
$this
->
killclass
)
continue
;
// force all contained elements to have parent package/subpackage
$pages
[
$j
]
->
classelements
[
$i
]
->
docblock
->
package =
$this
->
package
;
$pages
[
$j
]
->
classelements
[
$i
]
->
docblock
->
subpackage =
$this
->
subpackage
;
}
}
if
(
$pages
[
$j
]
->
classelements
[
$i
]
->
type ==
'class'
)
{
$this
->
killclass
= false
;
if
(
$this
->
checkKillClass
(
$pages
[
$j
]
->
classelements
[
$i
]
->
getName
(
)
,
$pages
[
$j
]
->
classelements
[
$i
]
->
getPath
(
)))
continue
;
$this
->
package
=
$pages
[
$j
]
->
classelements
[
$i
]
->
docblock
->
package
;
if
(
$this
->
package_output
)
if
(
!
in_array
(
$this
->
package
,
$this
->
package_output
))
continue
;
$this
->
subpackage
=
$pages
[
$j
]
->
classelements
[
$i
]
->
docblock
->
subpackage
;
$this
->
class
=
$pages
[
$j
]
->
classelements
[
$i
]
->
name
;
}
if
(
$this
->
killclass
)
continue
;
// phpDocumentor_out(" ".$pages[$j]->classelements[$i]->name."\n");
$this
->
Convert
(
$pages
[
$j
]
->
classelements
[
$i
]
)
;
}
if
(
count
(
$pages
[
$j
]
->
classelements
)
&&
!
$this
->
killclass
)
$this
->
endClass
(
)
;
phpDocumentor_out
(
" done\n"
)
;
flush
(
)
;
$this
->
endPage
(
)
;
}
phpDocumentor_out
(
"\nConverting @todo List..."
)
;
flush
(
)
;
if
(
count
(
$this
->
todoList
))
{
$this
->
ConvertTodoList
(
)
;
}
phpDocumentor_out
(
"done\n"
)
;
flush
(
)
;
phpDocumentor_out
(
"\nConverting Error Log..."
)
;
flush
(
)
;
$this
->
ConvertErrorLog
(
)
;
phpDocumentor_out
(
"done\n"
)
;
flush
(
)
;
}
/**
* Get a tree structure representing the hierarchy of tutorials
*
* Returns an array in format:
* <pre>
* array('tutorial' =>
{@link parserTutorial}
,
* 'kids' => array( // child tutorials
* array('tutorial' => child
{@link parserTutorial}
,
* 'kids' => array(...)
* )
* )
* )
* </pre>
*
@param
parserTutorial
|
array
*
@tutorial
tutorials.pkg
*
@return
array
*/
function
getTutorialTree
(
$tutorial
)
{
if
(
is_object
(
$tutorial
))
{
$path
=
$this
->
_tutorial_path
(
$tutorial
,
$tutorial
,
$tutorial
)
;
if
(
isset
(
$this
->
tutorial_tree
[
$path
]
))
{
$tutorial
=
$this
->
tutorial_tree
[
$path
]
;
}
else
{
return
false
;
}
}
$tree
= array
(
)
;
if
(
isset
(
$tutorial
[
'tutorial'
]
))
{
$tree
[
'tutorial'
]
=
$tutorial
[
'tutorial'
]
;
if
(
isset
(
$tutorial
[
'child'
]
))
{
foreach
(
$tutorial
[
'child'
]
as
$a
=>
$b
)
{
$btut
=
$b
[
'tutorial'
]
;
$res
= array
(
'tutorial'
=>
$this
->
tutorials
[
$btut
->
package
]
[
$btut
->
subpackage
]
[
$btut
->
tutorial_type
]
[
$btut
->
name
]
)
;
if
(
isset
(
$b
[
'child'
]
))
{
$tempres
=
Converter
::
getTutorialTree
(
$b
)
;
$res
[
'kids'
]
=
$tempres
[
'kids'
]
;
}
$tree
[
'kids'
]
[
]
=
$res
;
}
}
}
return
$tree
;
}
/**
* Remove tutorials one by one from $all, and transfer them into $new in the
* order they should be parsed
*
@param
parserTutorial
*
@param
array
*
@param
array
*
@access
private
*/
function
generateTutorialOrder
(
$parent
,
&
$all
,
&
$new
)
{
// remove from the list of tutorials to process
foreach
(
$all
[
$parent
->
package
]
[
$parent
->
subpackage
]
[
$parent
->
tutorial_type
]
as
$ind
=>
$t
)
{
if
(
$t
->
name ==
$parent
->
name
)
{
unset
(
$all
[
$parent
->
package
]
[
$parent
->
subpackage
]
[
$parent
->
tutorial_type
]
[
$ind
]
)
;
}
}
// add to the new ordered list of tutorials
$x
=
&
$new
[
$parent
->
package
]
[
$parent
->
subpackage
]
[
$parent
->
tutorial_type
]
;
if
(
!
is_object
(
$x
[
count
(
$x
)
- 1
]
)
||
$x
[
count
(
$x
)
- 1
]
->
name !=
$parent
->
name
)
{
// only add if the parent isn't also a child
$new
[
$parent
->
package
]
[
$parent
->
subpackage
]
[
$parent
->
tutorial_type
]
[
]
=
$parent
;
// add a new branch to the tree
}
// process all child tutorials, and insert them in order
// debug("processing parent ".$parent->name);
if
(
$parent
->
ini
)
{
foreach
(
$parent
->
ini
[
'Linked Tutorials'
]
as
$child
)
{
$sub
=
(
empty
(
$parent
->
subpackage
)
?
''
:
$parent
->
subpackage .
'/'
)
;
$kid
=
$parent
->
package .
'/'
.
$sub
.
$child
.
'.'
.
$parent
->
tutorial_type
;
$_klink
=
$this
->
getTutorialLink
(
$kid
,
false
,
false
,
array
(
$parent
->
package
))
;
if
(
is_object
(
$_klink
))
{
$klink
=
$this
->
returnSee
(
$_klink
)
;
}
else
{
$klink
= false
;
}
// remove the child from the list of remaining tutorials
foreach
(
$all
[
$parent
->
package
]
[
$parent
->
subpackage
]
[
$parent
->
tutorial_type
]
as
$ind
=>
$tute
)
{
if
(
$klink
&&
$tute
->
getLink
(
$this
)
==
$klink
)
{
// set up parent, next and prev links
$tute
->
setParent
(
$parent
,
$this
)
;
// remove the child from the list of tutorials to process
foreach
(
$all
[
$parent
->
package
]
[
$parent
->
subpackage
]
[
$parent
->
tutorial_type
]
as
$ind
=>
$t
)
{
if
(
$t
->
name ==
$tute
->
name
)
unset
(
$all
[
$parent
->
package
]
[
$parent
->
subpackage
]
[
$parent
->
tutorial_type
]
[
$ind
]
)
;
}
// add to the new ordered list of tutorials
$new
[
$parent
->
package
]
[
$parent
->
subpackage
]
[
$parent
->
tutorial_type
]
[
]
=
$tute
;
if
(
$tute
->
ini
)
{
// add all the child's child tutorials to the list
$this
->
generateTutorialOrder
(
$tute
,
$all
,
$new
)
;
}
}
}
}
}
return
;
}
/** Returns the path to this tutorial as a string
*
@param
parserTutorial
$pkg
*
@param
parserTutorial
$subpkg
*
@param
parserTutorial
$namepkg
*
@return
string
*/
function
_tutorial_path
(
$pkg
,
$subpkg
= 0
,
$namepkg
= 0
)
{
if
(
!
$subpkg
)
{
$subpkg
=
$pkg
;
}
if
(
!
$namepkg
)
{
$namepkg
=
$pkg
;
}
$subpackagename
=
(
$subpkg
->
subpackage ?
'/'
.
$subpkg
->
subpackage :
''
)
;
return
$pkg
->
package .
$subpackagename
.
'/'
.
$namepkg
->
name
;
}
/**
* Creates a tree structure of tutorials
*
* Format:
* <pre>
* array('package/subpackage/tutorial1.ext' =>
* array('tutorial' =>
{@link parserTutorial}
,
* 'child' =>
* array('package/subpackage/child1tutorial.ext' => ...,
* 'package/subpackage/child2tutorial.ext' => ...,
* ...
* )
* 'package/subpackage/tutorial2.ext' => ...,
* ...
* )
* </pre>
*
@return
array
the tutorial tree
*
@access
private
*/
function
_setupTutorialTree
(
$parent
= false
)
{
if
(
!
isset
(
$this
->
processed_tutorials
))
{
$this
->
processed_tutorials
= array
(
)
;
}
$tree
= array
(
)
;
if
(
!
$parent
)
{
foreach
(
$this
->
tutorials
as
$package
=>
$s
)
{
foreach
(
$s
as
$subpackage
=>
$t
)
{
foreach
(
$t
as
$type
=>
$n
)
{
foreach
(
$n
as
$name
=>
$tutorial
)
{
if
(
$tutorial
->
parent
)
{
continue
;
}
$child_path
=
$this
->
_tutorial_path
(
$tutorial
,
$tutorial
,
$tutorial
)
;
if
(
isset
(
$this
->
processed_tutorials
[
$child_path
]
))
{
continue
;
}
$this
->
processed_tutorials
[
$child_path
]
=
$tutorial
;
//debug("parent ".$tutorial->name);
$ret
=
$this
->
_setupTutorialTree
(
$tutorial
)
;
if
(
!
count
(
$tree
))
{
$tree
=
$ret
;
}
else
{
$tree
=
array_merge
(
$tree
,
$ret
)
;
}
}
}
}
}
return
$tree
;
}
$parent_path
=
$this
->
_tutorial_path
(
$parent
)
;
$tree
[
$parent_path
]
[
'tutorial'
]
=
$parent
;
// process all child tutorials, and insert them in order
if
(
$parent
->
ini
)
{
foreach
(
$parent
->
ini
[
'Linked Tutorials'
]
as
$child
)
{
if
(
isset
(
$this
->
tutorials
[
$parent
->
package
]
[
$parent
->
subpackage
]
[
$parent
->
tutorial_type
]
[
$child
.
'.'
.
$parent
->
tutorial_type
]
))
{
// remove the child from the list of remaining tutorials
$tute
=
$this
->
tutorials
[
$parent
->
package
]
[
$parent
->
subpackage
]
[
$parent
->
tutorial_type
]
[
$child
.
'.'
.
$parent
->
tutorial_type
]
;
}
else
{
$tute
= false
;
}
if
(
!
$tute
)
{
continue
;
}
$child_path
=
$this
->
_tutorial_path
(
$parent
,
$parent
,
$tute
)
;
if
(
isset
(
$this
->
processed_tutorials
[
$child_path
]
))
{
continue
;
}
$this
->
processed_tutorials
[
$child_path
]
=
$tute
;
if
(
$tute
->
name !=
$child
.
'.'
.
$parent
->
tutorial_type
)
{
continue
;
}
//echo "Adding [$child_path] to [$parent_path]<br>";
$tree
[
$parent_path
]
[
'child'
]
[
$this
->
_tutorial_path
(
$parent
,
$parent
,
$tute
)
]
[
'tutorial'
]
=
$tute
;
if
(
!
$tute
->
ini
)
{
continue
;
}
// add all the child's child tutorials to the list
if
(
!
isset
(
$tree
[
$parent_path
]
[
'child'
]
))
{
$tree
[
$parent_path
]
[
'child'
]
=
$this
->
_setupTutorialTree
(
$tute
)
;
}
else
{
$tree
[
$parent_path
]
[
'child'
]
=
array_merge
(
$tree
[
$parent_path
]
[
'child'
]
,
$this
->
_setupTutorialTree
(
$tute
))
;
}
}
}
return
$tree
;
}
/**
* Debugging function for dumping
{@link $tutorial_tree}
*
@return
string
*/
function
vardump_tree
(
$tree
,
$indent
=
''
)
{
if
(
phpDocumentor_get_class
(
$tree
)
==
'parsertutorial'
)
return
$tree
->
name.
' extends '
.
(
$tree
->
parent?
$tree
->
parent
->
name :
'nothing'
)
;
$a
=
''
;
foreach
(
$tree
as
$ind
=>
$stuff
)
{
$x
=
$this
->
vardump_tree
(
$stuff
,
"
$indent
"
)
;
$a
.=
$indent
.
'['
.
$ind
.
" => \n "
.
$indent
.
$x
.
"]\n"
;
}
return
substr
(
$a
,
0
,
strlen
(
$a
)
- 1
)
;
}
/**
*
@access
private
*/
function
sort_package_elements
(
$a
,
$b
)
{
if
((
$a
->
type ==
$b
->
type
)
&&
(
isset
(
$a
->
isConstructor
)
&&
$a
->
isConstructor
))
return
-1
;
if
((
$a
->
type ==
$b
->
type
)
&&
(
isset
(
$b
->
isConstructor
)
&&
$b
->
isConstructor
))
return
1
;
if
(
$a
->
type ==
$b
->
type
)
return
strnatcasecmp
(
$a
->
name
,
$b
->
name
)
;
if
(
$a
->
type ==
'class'
)
return
-1
;
if
(
$b
->
type ==
'class'
)
return
1
;
if
(
$a
->
type ==
'const'
)
return
-1
;
if
(
$b
->
type ==
'const'
)
return
1
;
if
(
$a
->
type ==
'var'
)
return
-1
;
if
(
$b
->
type ==
'var'
)
return
1
;
if
(
$a
->
type ==
'page'
)
return
-1
;
if
(
$b
->
type ==
'page'
)
return
1
;
if
(
$a
->
type ==
'include'
)
return
-1
;
if
(
$b
->
type ==
'include'
)
return
1
;
if
(
$a
->
type ==
'define'
)
return
-1
;
if
(
$b
->
type ==
'define'
)
return
1
;
if
(
$a
->
type ==
'global'
)
return
-1
;
if
(
$b
->
type ==
'global'
)
return
1
;
if
(
$a
->
type ==
'function'
)
return
-1
;
if
(
$b
->
type ==
'function'
)
return
1
;
}
/**
*
@access
private
*/
function
defpackagesort
(
$a
,
$b
)
{
if
(
$a
==
$GLOBALS
[
'phpDocumentor_DefaultPackageName'
]
)
return
-1
;
if
(
$b
==
$GLOBALS
[
'phpDocumentor_DefaultPackageName'
]
)
return
0
;
return
strnatcasecmp
(
$a
,
$b
)
;
}
/**
*
@access
private
*/
function
Pc_sort
(
$a
,
$b
)
{
return
strnatcasecmp
(
key
(
$a
)
,
key
(
$b
))
;
}
/**
* walk over elements by package rather than page
*
* This method is designed for converters like the PDF converter that need
* everything passed in alphabetical order by package/subpackage and by
* procedural and then class information
*
@see
PDFdefaultConverter
*
@see
walk()
*/
function
walk_everything
(
)
{
global
$hooser
;
$hooser
= false
;
uksort
(
$this
->
package_elements
,
array
(
$this
,
'defpackagesort'
))
;
foreach
(
$this
->
package_elements
as
$package
=>
$r
)
{
if
(
$this
->
package_output
)
{
if
(
!
in_array
(
$this
->
package
,
$this
->
package_output
))
{
unset
(
$this
->
package_elements
[
$package
]
)
;
continue
;
}
}
uksort
(
$this
->
package_elements
[
$package
]
,
'strnatcasecmp'
)
;
}
foreach
(
$this
->
package_elements
as
$package
=>
$r
)
{
foreach
(
$this
->
package_elements
[
$package
]
as
$subpackage
=>
$r
)
{
if
(
isset
(
$r
[
'page'
]
))
{
uksort
(
$r
[
'page'
]
,
'strnatcasecmp'
)
;
foreach
(
$r
[
'page'
]
as
$page
=>
$oo
)
{
usort
(
$this
->
package_elements
[
$package
]
[
$subpackage
]
[
'page'
]
[
$page
]
,
array
(
$this
,
'sort_package_elements'
))
;
}
}
if
(
isset
(
$r
[
'class'
]
))
{
uksort
(
$r
[
'class'
]
,
'strnatcasecmp'
)
;
foreach
(
$r
[
'class'
]
as
$page
=>
$oo
)
{
usort
(
$r
[
'class'
]
[
$page
]
,
array
(
$this
,
'sort_package_elements'
))
;
}
}
$this
->
package_elements
[
$package
]
[
$subpackage
]
=
$r
;
}
}
foreach
(
$this
->
package_elements
as
$package
=>
$s
)
{
$notyet
= false
;
foreach
(
$s
as
$subpackage
=>
$r
)
{
$this
->
package
=
$package
;
$this
->
subpackage
=
$subpackage
;
if
(
isset
(
$r
[
'page'
]
))
{
$this
->
class
= false
;
foreach
(
$r
[
'page'
]
as
$page
=>
$elements
)
{
if
(
is_array
(
$elements
))
{
foreach
(
$elements
as
$element
)
{
if
(
$element
->
type ==
'page'
)
{
phpDocumentor_out
(
'Converting '
.
$element
->
parent
->
getPath
(
))
;
flush
(
)
;
$this
->
curfile
=
$element
->
parent
->
getFile
(
)
;
$this
->
curname
=
$this
->
getPageName
(
$element
->
parent
)
;
$this
->
curpath
=
$element
->
parent
->
getPath
(
)
;
$notyet
= true
;
}
else
{
// force all contained elements to have parent package/subpackage
$element
->
docblock
->
package =
$this
->
package
;
$element
->
docblock
->
subpackage =
$this
->
subpackage
;
$a
=
$element
->
docblock
->
getKeyword
(
'access'
)
;
if
(
is_object
(
$a
))
$a
=
$a
->
getString
(
)
;
if
(
!
$this
->
parseprivate
&&
(
$a
==
'private'
))
continue
;
}
if
(
$notyet
)
{
phpDocumentor_out
(
" Procedural Page Elements..."
)
;
flush
(
)
;
$notyet
= false
;
}
$this
->
Convert
(
$element
)
;
}
}
$this
->
endPage
(
)
;
phpDocumentor_out
(
"done\n"
)
;
flush
(
)
;
}
}
$start_classes
= true
;
if
(
isset
(
$r
[
'class'
]
))
{
foreach
(
$r
[
'class'
]
as
$class
=>
$elements
)
{
foreach
(
$elements
as
$element
)
{
if
(
$element
->
type ==
'class'
)
{
if
(
!
$start_classes
)
{
if
(
count
(
$elements
)
&&
!
$this
->
killclass
)
$this
->
endClass
(
)
;
phpDocumentor_out
(
"done\n"
)
;
flush
(
)
;
}
$start_classes
= false
;
$this
->
class
=
$element
->
getName
(
)
;
$this
->
killclass
= false
;
if
(
$this
->
checkKillClass
(
$element
->
getName
(
)
,
$element
->
getPath
(
)))
continue
;
if
(
!
$this
->
killclass
)
{
phpDocumentor_out
(
'Converting '
.
$this
->
class
.
"..."
)
;
flush
(
)
;
$notyet
= true
;
}
}
else
{
if
(
$notyet
)
{
phpDocumentor_out
(
"Variables/methods/Class constants...\n"
)
;
flush
(
)
;
$notyet
= false
;
}
$a
=
$element
->
docblock
->
getKeyword
(
'access'
)
;
if
(
is_object
(
$a
))
$a
=
$a
->
getString
(
)
;
if
(
!
$this
->
parseprivate
&&
(
$a
==
'private'
))
continue
;
if
(
$this
->
killclass
)
continue
;
// force all contained elements to have parent package/subpackage
$element
->
docblock
->
package =
$this
->
package
;
$element
->
docblock
->
subpackage =
$this
->
subpackage
;
}
if
(
$this
->
killclass
)
continue
;
$this
->
Convert
(
$element
)
;
}
}
if
(
count
(
$elements
)
&&
!
$this
->
killclass
)
$this
->
endClass
(
)
;
phpDocumentor_out
(
"done\n"
)
;
flush
(
)
;
}
// if isset($r['class'])
}
// foreach($s
}
// foreach($this->package_elements)
phpDocumentor_out
(
"\nConverting @todo List..."
)
;
flush
(
)
;
if
(
count
(
$this
->
todoList
))
{
$this
->
ConvertTodoList
(
)
;
}
phpDocumentor_out
(
"done\n"
)
;
flush
(
)
;
phpDocumentor_out
(
"\nConverting Error Log..."
)
;
flush
(
)
;
$this
->
ConvertErrorLog
(
)
;
phpDocumentor_out
(
"done\n"
)
;
flush
(
)
;
}
/**
* Convert the phpDocumentor parsing/conversion error log
*
@abstract
*/
function
ConvertErrorLog
(
)
{
}
/**
* Convert the list of all @todo tags
*
@abstract
*/
function
ConvertTodoList
(
)
{
}
/**
* Sorts the @todo list - do not override or modify this function
*
@access
private
*
@uses
_sortTodos passed to
{@link usort()}
to sort the todo list
*/
function
sortTodos
(
)
{
phpDocumentor_out
(
"\nSorting @todo list..."
)
;
flush
(
)
;
foreach
(
$this
->
todoList
as
$package
=>
$r
)
{
usort
(
$this
->
todoList
[
$package
]
,
array
(
'Converter'
,
'_sortTodoPackage'
))
;
foreach
(
$r
as
$a
=>
$sub
)
{
if
(
is_array
(
$this
->
todoList
[
$package
]
[
$a
]
[
1
]
))
{
usort
(
$this
->
todoList
[
$package
]
[
$a
]
[
1
]
,
array
(
'Converter'
,
'_sortTodos'
))
;
}
}
}
phpDocumentor_out
(
"done\n"
)
;
}
/**
@access
private */
function
_sortTodoPackage
(
$a
,
$b
)
{
return
strnatcasecmp
(
$a
[
0
]
->
name
,
$b
[
0
]
->
name
)
;
}
/**
@access
private */
function
_sortTodos
(
$a
,
$b
)
{
if
(
!
is_object
(
$a
))
{
var_dump
(
$a
)
;
}
return
strnatcasecmp
(
$a
->
getString
(
)
,
$b
->
getString
(
))
;
}
/**
* Sorts all indexes - do not override or modify this function
*
@uses
$leftindex based on the value of leftindex, sorts link arrays
*
@uses
$class_elements sorts with
{@link compareLink}
*
@uses
$page_elements sorts with
{@link compareLink}
*
@uses
$define_elements sorts with
{@link compareLink}
*
@uses
$global_elements sorts with
{@link compareLink}
*
@uses
$function_elements sorts with
{@link compareLink}
*
@uses
$elements sorts with
{@link elementCmp}
*
@uses
$pkg_elements sorts with
{@link elementCmp}
after sorting by
* package/subpackage alphabetically
*
@access
private
*/
function
sortIndexes
(
)
{
phpDocumentor_out
(
"\nSorting Indexes..."
)
;
flush
(
)
;
uksort
(
$this
->
elements
,
'strnatcasecmp'
)
;
if
(
$this
->
leftindex
[
'classes'
]
)
{
foreach
(
$this
->
class_elements
as
$package
=>
$o1
)
{
foreach
(
$o1
as
$subpackage
=>
$links
)
{
usort
(
$this
->
class_elements
[
$package
]
[
$subpackage
]
,
array
(
$this
,
'compareLink'
))
;
}
}
}
if
(
$this
->
leftindex
[
'pages'
]
)
{
foreach
(
$this
->
page_elements
as
$package
=>
$o1
)
{
uksort
(
$this
->
page_elements
[
$package
]
,
'strnatcasecmp'
)
;
foreach
(
$o1
as
$subpackage
=>
$links
)
{
usort
(
$this
->
page_elements
[
$package
]
[
$subpackage
]
,
array
(
$this
,
'compareLink'
))
;
}
}
}
if
(
$this
->
leftindex
[
'defines'
]
)
{
foreach
(
$this
->
define_elements
as
$package
=>
$o1
)
{
uksort
(
$this
->
define_elements
[
$package
]
,
'strnatcasecmp'
)
;
foreach
(
$o1
as
$subpackage
=>
$links
)
{
usort
(
$this
->
define_elements
[
$package
]
[
$subpackage
]
,
array
(
$this
,
'compareLink'
))
;
}
}
}
if
(
$this
->
leftindex
[
'globals'
]
)
{
foreach
(
$this
->
global_elements
as
$package
=>
$o1
)
{
uksort
(
$this
->
global_elements
[
$package
]
,
'strnatcasecmp'
)
;
foreach
(
$o1
as
$subpackage
=>
$links
)
{
usort
(
$this
->
global_elements
[
$package
]
[
$subpackage
]
,
array
(
$this
,
'compareLink'
))
;
}
}
}
if
(
$this
->
leftindex
[
'functions'
]
)
{
foreach
(
$this
->
function_elements
as
$package
=>
$o1
)
{
uksort
(
$this
->
function_elements
[
$package
]
,
'strnatcasecmp'
)
;
foreach
(
$o1
as
$subpackage
=>
$links
)
{
usort
(
$this
->
function_elements
[
$package
]
[
$subpackage
]
,
array
(
$this
,
'compareLink'
))
;
}
}
}
foreach
(
$this
->
elements
as
$letter
=>
$nothuing
)
{
uasort
(
$this
->
elements
[
$letter
]
,
array
(
$this
,
"elementCmp"
))
;
}
foreach
(
$this
->
pkg_elements
as
$package
=>
$els
)
{
uksort
(
$this
->
pkg_elements
[
$package
]
,
'strnatcasecmp'
)
;
foreach
(
$this
->
pkg_elements
[
$package
]
as
$subpackage
=>
$els
)
{
if
(
empty
(
$els
))
continue
;
uksort
(
$this
->
pkg_elements
[
$package
]
[
$subpackage
]
,
'strnatcasecmp'
)
;
foreach
(
$els
as
$letter
=>
$yuh
)
{
usort
(
$this
->
pkg_elements
[
$package
]
[
$subpackage
]
[
$letter
]
,
array
(
$this
,
"elementCmp"
))
;
}
}
}
phpDocumentor_out
(
"done\n"
)
;
flush
(
)
;
}
/**
* sorts
{@link $page_contents}
by element type as well as alphabetically
*
@see
$sort_page_contents_by_element_type
*/
function
sortPageContentsByElementType
(
&
$pages
)
{
foreach
(
$this
->
page_contents
as
$package
=>
$els
)
{
foreach
(
$this
->
page_contents
[
$package
]
as
$subpackage
=>
$els
)
{
if
(
empty
(
$els
))
continue
;
foreach
(
$this
->
page_contents
[
$package
]
[
$subpackage
]
as
$path
=>
$stuff
)
{
if
(
!
count
(
$pages
[
$path
]
->
elements
))
continue
;
usort
(
$pages
[
$path
]
->
elements
,
array
(
$this
,
'eltypecmp'
))
;
usort
(
$this
->
page_contents
[
$package
]
[
$subpackage
]
[
$path
]
,
array
(
$this
,
'eltypecmp'
))
;
if
(
isset
(
$this
->
page_contents
[
$package
]
[
$subpackage
]
[
$path
]
[
0
]
))
$this
->
page_contents
[
$package
]
[
$subpackage
]
[
$path
]
[
'###main'
]
=
$this
->
page_contents
[
$package
]
[
$subpackage
]
[
$path
]
[
0
]
;
unset
(
$this
->
page_contents
[
$package
]
[
$subpackage
]
[
$path
]
[
0
]
)
;
}
}
}
}
/**
*
@access
private
*
@see
Converter::sortIndexes()
*/
function
compareLink
(
$a
,
$b
)
{
return
strnatcasecmp
(
$a
->
name
,
$b
->
name
)
;
}
/**
*
@access
private
*
@see
Converter::sortPageContentsByElementType()
*/
function
eltypecmp
(
$a
,
$b
)
{
if
(
$a
->
type ==
'page'
)
return
-1
;
if
(
$b
->
type ==
'page'
)
return
1
;
return
strnatcasecmp
(
$a
->
type.
$a
->
name
,
$b
->
type.
$b
->
name
)
;
}
/**
* does a nat case sort on the specified second level value of the array
*
*
@param
mixed
$a
*
@param
mixed
$b
*
@return
int
*
@access
private
*/
function
elementCmp
(
$a
,
$b
)
{
return
strnatcasecmp
(
$a
->
getName
(
)
,
$b
->
getName
(
))
;
}
/**
* Used to stop conversion of @ignored or private @access classes
*
@uses
$killclass sets killclass based on the value of
{@link Classes::$killclass}
* and
{@link $package_output}
*
@access
private
*/
function
checkKillClass
(
$class
,
$path
)
{
$this
->
killclass
= false
;
if
(
isset
(
$this
->
classes
->
killclass
[
$class
]
)
&& isset
(
$this
->
classes
->
killclass
[
$class
]
[
$path
]
))
$this
->
killclass
= true
;
if
(
$this
->
package_output
)
{
$a
=
$this
->
classes
->
getClass
(
$class
,
$path
)
;
if
(
!
in_array
(
$a
->
docblock
->
package
,
$this
->
package_output
))
$this
->
killclass
= true
;
}
if
(
PHPDOCUMENTOR_DEBUG &&
$this
->
killclass
)
debug
(
"
$class
$path
killed
"
)
;
return
$this
->
killclass
;
}
/**
*
@param
abstractLink
descendant of abstractLink
*
@param
array
|
parserTag
list of @todos|@todo tag
*
@access
private
*/
function
addTodoLink
(
$link
,
$todos
)
{
$this
->
todoList
[
$link
->
package
]
[
]
= array
(
$link
,
$todos
)
;
}
/**
* Adds all elements to the
{@link $elements, $pkg_elements, $links}
,
*
{@link $linkswithfile}
and left indexes - Do not modify or override
*
@access
private
*
@param
parserBase
any documentable element descendant of parserBase
* except parserTutorial
*
@param
false
|
parserPage
only used to add a
{@link parserPage}
if the
* $element passed is a parserPage
*
@staticvar
string
path of current page, used for
{@link $page_contents}
setup
*/
function
addElement
(
&
$element
,
$pageel
=false
)
{
static
$curpath
=
''
;
if
(
$this
->
package_output
)
{
if
(
!
in_array
(
$this
->
package
,
$this
->
package_output
))
return
;
}
if
(
$pageel
&& phpDocumentor_get_class
(
$pageel
)
==
'parserdata'
)
{
if
(
isset
(
$pageel
->
docblock
)
&& phpDocumentor_get_class
(
$pageel
->
docblock
)
==
'parserdocblock'
)
{
$a
=
$pageel
->
docblock
->
getKeyword
(
'todo'
)
;
if
(
$a
&&
!
empty
(
$a
->
value
[
0
]
))
{
$this
->
addTodoLink
(
$this
->
addLink
(
$element
)
,
$a
)
;
}
}
}
if
(
isset
(
$element
->
docblock
))
{
$a
=
$element
->
docblock
->
getKeyword
(
'access'
)
;
if
(
is_object
(
$a
))
$a
=
$a
->
getString
(
)
;
if
(
!
$this
->
parseprivate
&&
(
$a
==
'private'
))
return
;
$a
=
$element
->
docblock
->
getKeyword
(
'todo'
)
;
if
(
$a
&&
!
empty
(
$a
->
value
[
0
]
))
{
if
(
$element
->
type !=
'include'
)
{
$this
->
addTodoLink
(
$this
->
addLink
(
$element
)
,
$a
)
;
}
else
{
addWarning
(
PDERROR_NOTODO_INCLUDE
,
$element
->
getLineNumber
(
)
,
$element
->
getPath
(
))
;
}
}
}
$startPositionOfElementName
= 0
;
// which character of the element name actually starts its textual name
switch
(
$element
->
type
)
{
case
'page'
:
if
(
$this
->
sort_absolutely_everything
)
{
$this
->
package_elements
[
$element
->
package
]
[
$element
->
subpackage
]
[
'page'
]
[
$element
->
getPath
(
)
]
[
]
=
$pageel
;
}
$link
=
$this
->
addLink
(
$element
)
;
$curpath
=
$element
->
getPath
(
)
;
if
(
$this
->
leftindex
[
'pages'
]
)
$this
->
page_elements
[
$element
->
package
]
[
$element
->
subpackage
]
[
]
=
$link
;
$this
->
page_contents
[
$element
->
package
]
[
$element
->
subpackage
]
[
$curpath
]
[
'###main'
]
=
$link
;
break
;
case
'class'
:
if
(
$this
->
sort_absolutely_everything
)
{
$this
->
package_elements
[
$element
->
docblock
->
package
]
[
$element
->
docblock
->
subpackage
]
[
'class'
]
[
$this
->
class
]
[
]
=
$element
;
}
$link
=
$this
->
addLink
(
$element
)
;
if
(
$this
->
leftindex
[
'classes'
]
)
$this
->
class_elements
[
$element
->
docblock
->
package
]
[
$element
->
docblock
->
subpackage
]
[
]
=
$link
;
$this
->
class_contents
[
$element
->
docblock
->
package
]
[
$element
->
docblock
->
subpackage
]
[
$this
->
class
]
[
'###main'
]
=
$link
;
break
;
case
'include'
:
if
(
$this
->
sort_absolutely_everything
)
{
$this
->
package_elements
[
$element
->
docblock
->
package
]
[
$element
->
docblock
->
subpackage
]
[
'page'
]
[
$curpath
]
[
]
=
$element
;
}
$link
=
$this
->
addLink
(
$element
)
;
break
;
case
'define'
:
if
(
$this
->
sort_absolutely_everything
)
{
$this
->
package_elements
[
$element
->
docblock
->
package
]
[
$element
->
docblock
->
subpackage
]
[
'page'
]
[
$curpath
]
[
]
=
$element
;
}
$link
=
$this
->
addLink
(
$element
)
;
if
(
$this
->
leftindex
[
'defines'
]
)
$this
->
define_elements
[
$element
->
docblock
->
package
]
[
$element
->
docblock
->
subpackage
]
[
]
=
$link
;
$this
->
page_contents
[
$element
->
docblock
->
package
]
[
$element
->
docblock
->
subpackage
]
[
$curpath
]
[
]
=
$link
;
break
;
case
'global'
:
if
(
$this
->
sort_absolutely_everything
)
{
$this
->
package_elements
[
$element
->
docblock
->
package
]
[
$element
->
docblock
->
subpackage
]
[
'page'
]
[
$curpath
]
[
]
=
$element
;
}
$link
=
$this
->
addLink
(
$element
)
;
$startPositionOfElementName
= 1
;
// lose the leading "$" character
if
(
$this
->
leftindex
[
'globals'
]
)
$this
->
global_elements
[
$element
->
docblock
->
package
]
[
$element
->
docblock
->
subpackage
]
[
]
=
$link
;
$this
->
page_contents
[
$element
->
docblock
->
package
]
[
$element
->
docblock
->
subpackage
]
[
$curpath
]
[
]
=
$link
;
break
;
case
'var'
:
if
(
$this
->
sort_absolutely_everything
)
{
$this
->
package_elements
[
$element
->
docblock
->
package
]
[
$element
->
docblock
->
subpackage
]
[
'class'
]
[
$this
->
class
]
[
]
=
$element
;
}
$link
=
$this
->
addLink
(
$element
)
;
$startPositionOfElementName
= 1
;
// lose the leading "$" character
$this
->
class_contents
[
$element
->
docblock
->
package
]
[
$element
->
docblock
->
subpackage
]
[
$this
->
class
]
[
]
=
$link
;
break
;
case
'const'
:
if
(
$this
->
sort_absolutely_everything
)
{
$this
->
package_elements
[
$element
->
docblock
->
package
]
[
$element
->
docblock
->
subpackage
]
[
'class'
]
[
$this
->
class
]
[
]
=
$element
;
}
$link
=
$this
->
addLink
(
$element
)
;
$this
->
class_contents
[
$element
->
docblock
->
package
]
[
$element
->
docblock
->
subpackage
]
[
$this
->
class
]
[
]
=
$link
;
break
;
case
'method'
:
if
(
$this
->
sort_absolutely_everything
)
{
$this
->
package_elements
[
$element
->
docblock
->
package
]
[
$element
->
docblock
->
subpackage
]
[
'class'
]
[
$this
->
class
]
[
]
=
$element
;
}
$link
=
$this
->
addLink
(
$element
)
;
$this
->
class_contents
[
$element
->
docblock
->
package
]
[
$element
->
docblock
->
subpackage
]
[
$this
->
class
]
[
]
=
$link
;
break
;
case
'function'
:
if
(
$this
->
sort_absolutely_everything
)
{
$this
->
package_elements
[
$element
->
docblock
->
package
]
[
$element
->
docblock
->
subpackage
]
[
'page'
]
[
$curpath
]
[
]
=
$element
;
}
$link
=
$this
->
addLink
(
$element
)
;
if
(
$this
->
leftindex
[
'functions'
]
)
$this
->
function_elements
[
$element
->
docblock
->
package
]
[
$element
->
docblock
->
subpackage
]
[
]
=
$link
;
$this
->
page_contents
[
$element
->
docblock
->
package
]
[
$element
->
docblock
->
subpackage
]
[
$curpath
]
[
]
=
$link
;
break
;
default :
break
;
}
if
(
$element
->
getType
(
)
!=
'include'
)
{
if
(
$element
->
getType
(
)
==
'var'
||
$element
->
getType
(
)
==
'method'
||
$element
->
getType
(
)
==
'const'
)
{
$this
->
links
[
$this
->
package
]
[
$this
->
subpackage
]
[
$element
->
getType
(
)
]
[
$element
->
class
]
[
$element
->
getName
(
)
]
=
$link
;
$this
->
linkswithfile
[
$this
->
package
]
[
$this
->
subpackage
]
[
$element
->
getType
(
)
]
[
$element
->
getPath
(
)
]
[
$element
->
class
]
[
$element
->
getName
(
)
]
=
$link
;
}
else
{
if
(
$element
->
type ==
'page'
)
{
$this
->
links
[
$this
->
package
]
[
$this
->
subpackage
]
[
$element
->
getType
(
)
]
[
$element
->
getFile
(
)
]
=
$link
;
$this
->
linkswithfile
[
$this
->
package
]
[
$this
->
subpackage
]
[
$element
->
getType
(
)
]
[
$element
->
getPath
(
)
]
[
$element
->
getFile
(
)
]
=
$link
;
}
else
{
$this
->
links
[
$this
->
package
]
[
$this
->
subpackage
]
[
$element
->
getType
(
)
]
[
$element
->
getName
(
)
]
=
$link
;
$this
->
linkswithfile
[
$this
->
package
]
[
$this
->
subpackage
]
[
$element
->
getType
(
)
]
[
$element
->
getPath
(
)
]
[
$element
->
getName
(
)
]
=
$link
;
}
}
}
if
(
$element
->
type ==
'page'
)
{
$this
->
elements
[
substr
(
strtolower
(
$element
->
getFile
(
))
,
$startPositionOfElementName
,
1
)
]
[
]
=
$element
;
$this
->
pkg_elements
[
$this
->
package
]
[
$this
->
subpackage
]
[
substr
(
strtolower
(
$element
->
getFile
(
))
,
$startPositionOfElementName
,
1
)
]
[
]
=
$element
;
}
else
{
$this
->
elements
[
substr
(
strtolower
(
$element
->
getName
(
))
,
$startPositionOfElementName
,
1
)
]
[
]
=
$element
;
$this
->
pkg_elements
[
$this
->
package
]
[
$this
->
subpackage
]
[
substr
(
strtolower
(
$element
->
getName
(
))
,
$startPositionOfElementName
,
1
)
]
[
]
=
$element
;
}
}
/**
* returns an abstract link to element. Do not modify or override
*
* This method should only be called in process of Conversion, unless
* $element is a parserPage, or $page is set to true, and $element is
* not a parserPage
*
@return
abstractLink
abstractLink descendant
*
@access
private
*
@param
parserElement
element to add a new link (descended from
*
{@link abstractLink}
)to the
{@link $links}
array
*
@param
string
classname for elements that are class-based (this may be
* deprecated in the future, as the classname
* should be contained within the element. if $element is a
* page, this parameter is a package name
*
@param
string
subpackage name for page elements
*/
function
addLink
(
&
$element
,
$page
= false
)
{
if
(
$page
)
{
// create a fake parserPage to extract the fileAlias for this link
$fakepage
= new
parserPage
;
$fakepage
->
setPath
(
$element
->
getPath
(
))
;
$fakepage
->
setFile
(
basename
(
$element
->
getPath
(
)))
;
$this
->
curname =
$this
->
getPageName
(
$fakepage
)
;
}
switch
(
$element
->
type
)
{
case
'function'
:
$x
= new
functionLink
;
$x
->
addLink
(
$element
->
getPath
(
)
,
$this
->
curname
,
$element
->
name
,
$element
->
docblock
->
package
,
$element
->
docblock
->
subpackage
,
$element
->
docblock
->
category
)
;
return
$x
;
break
;
case
'define'
:
$x
= new
defineLink
;
$x
->
addLink
(
$element
->
getPath
(
)
,
$this
->
curname
,
$element
->
name
,
$element
->
docblock
->
package
,
$element
->
docblock
->
subpackage
,
$element
->
docblock
->
category
)
;
return
$x
;
break
;
case
'global'
:
$x
= new
globalLink
;
$x
->
addLink
(
$element
->
getPath
(
)
,
$this
->
curname
,
$element
->
name
,
$element
->
docblock
->
package
,
$element
->
docblock
->
subpackage
,
$element
->
docblock
->
category
)
;
return
$x
;
break
;
case
'class'
:
$x
= new
classLink
;
$x
->
addLink
(
$element
->
getPath
(
)
,
$this
->
curname
,
$element
->
name
,
$element
->
docblock
->
package
,
$element
->
docblock
->
subpackage
,
$element
->
docblock
->
category
)
;
return
$x
;
break
;
case
'method'
:
$x
= new
methodLink
;
$x
->
addLink
(
$this
->
class
,
$element
->
getPath
(
)
,
$this
->
curname
,
$element
->
name
,
$element
->
docblock
->
package
,
$element
->
docblock
->
subpackage
,
$element
->
docblock
->
category
)
;
return
$x
;
break
;
case
'var'
:
$x
= new
varLink
;
$x
->
addLink
(
$this
->
class
,
$element
->
getPath
(
)
,
$this
->
curname
,
$element
->
name
,
$element
->
docblock
->
package
,
$element
->
docblock
->
subpackage
,
$element
->
docblock
->
category
)
;
return
$x
;
break
;
case
'const'
:
$x
= new
constLink
;
$x
->
addLink
(
$this
->
class
,
$element
->
getPath
(
)
,
$this
->
curname
,
$element
->
name
,
$element
->
docblock
->
package
,
$element
->
docblock
->
subpackage
,
$element
->
docblock
->
category
)
;
return
$x
;
break
;
case
'page'
:
$x
= new
pageLink
;
$x
->
addLink
(
$element
->
getPath
(
)
,
$this
->
getPageName
(
$element
)
,
$element
->
file
,
$element
->
package
,
$element
->
subpackage
,
$element
->
category
)
;
return
$x
;
break
;
}
}
/**
* Return a tree of all classes that extend this class
*
* The data structure returned is designed for a non-recursive algorithm,
* and is somewhat complex.
* In most cases, the array returned is:
*
* <pre>
* array('#root' =>
* array('link' =>
{@link classLink}
to $class,
* 'parent' => false,
* 'children' => array(array('class' => 'childclass1',
* 'package' => 'child1package'),
* array('class' => 'childclass2',
* 'package' => 'child2package'),...
* )
* ),
* 'child1package#childclass1' =>
* array('link' =>
{@link classLink}
to childclass1,
* 'parent' => '#root',
* 'children' => array(array('class' => 'kidclass',
* 'package' => 'kidpackage'),...
* )
* ),
* 'kidpackage#kidclass' =>
* array('link' =>
{@link classLink}
to kidclass,
* 'parent' => 'child1package#childclass1',
* 'children' => array() // no children
* ),
* ....
* )
*</pre>
*
* To describe this format using language, every class in the tree has an
* entry in the first level of the array. The index for all child
* classes that extend the root class is childpackage#childclassname.
* Each entry in the array has 3 elements: link, parent, and children.
* <ul>
* <li>link - a
{@link classLink}
to the current class</li>
* <li>parent - a
{@link classLink}
to the class's parent, or false (except for one special case described below)</li>
* <li>children - an array of arrays, each entry has a 'class' and 'package' index to the child class,
* used to find the entry in the big array</li>
* </ul>
*
* special cases are when the #root class has a parent in another package,
* or when the #root class extends a class not found
* by phpDocumentor. In the first case, parent will be a
* classLink to the parent class. In the second, parent will be the
* extends clause, as in:
* <code>
* class X extends Y
* {
* ...
* }
* </code>
* in this case, the #root entry will be array('link' => classLink to X, 'parent' => 'Y', children => array(...))
*
* The fastest way to design a method to process the array returned
* is to copy HTMLframesConverter::getRootTree() into
* your converter and to modify the html to whatever output format you are going to use
*
@see
HTMLframesConverter::getRootTree()
*
@param
string
class name
*
@param
string
*
@param
string
*
@return
array
Format: see docs
*/
function
getSortedClassTreeFromClass
(
$class
,
$package
,
$subpackage
)
{
$my_tree
= array
(
)
;
$root
=
$this
->
classes
->
getClassByPackage
(
$class
,
$package
)
;
if
(
!
$root
)
return
false
;
$class_children
=
$this
->
classes
->
getDefiniteChildren
(
$class
,
$root
->
curfile
)
;
if
(
!
$class_children
)
{
// special case: parent class is found, but is not part of this package, class has no children
if
(
is_array
(
$root
->
parent
))
{
$x
=
$root
->
getParent
(
$this
)
;
if
(
$x
->
docblock
->
package
!=
$package
)
{
$v
=
Converter
::
getClassLink
(
$root
->
getName
(
)
,
$package
,
$root
->
getPath
(
))
;
return
array
(
'#root'
=> array
(
'link'
=>
$v
,
'parent'
=>
Converter
::
getClassLink
(
$x
->
getName
(
)
,
$x
->
docblock
->
package
,
$x
->
getPath
(
))
,
'children'
=> array
(
)))
;
}
}
else
{
// class has normal situation, no children
if
(
is_string
(
$root
->
getParent
(
$this
)))
return
array
(
'#root'
=> array
(
'link'
=>
Converter
::
getClassLink
(
$root
->
getName
(
)
,
$package
,
$root
->
getPath
(
))
,
'parent'
=>
$root
->
getExtends
(
)
,
'children'
=> array
(
)))
;
else
return
array
(
'#root'
=> array
(
'link'
=>
Converter
::
getClassLink
(
$root
->
getName
(
)
,
$package
,
$root
->
getPath
(
))
,
'parent'
=> false
,
'children'
=> array
(
)))
;
}
}
// special case: parent class is found, but is not part of this package, class has children
if
(
is_array
(
$root
->
parent
))
{
$x
=
$root
->
getParent
(
$this
)
;
if
(
$x
->
docblock
->
package
!=
$package
)
{
$v
=
Converter
::
getClassLink
(
$root
->
getName
(
)
,
$package
,
$root
->
getPath
(
))
;
$my_tree
= array
(
'#root'
=> array
(
'link'
=>
$v
,
'parent'
=>
Converter
::
getClassLink
(
$x
->
getName
(
)
,
$x
->
docblock
->
package
,
$x
->
getPath
(
))
,
'children'
=> array
(
)))
;
}
else
{
}
}
else
$my_tree
= array
(
'#root'
=> array
(
'link'
=>
Converter
::
getClassLink
(
$root
->
getName
(
)
,
$package
,
$root
->
getPath
(
))
,
'parent'
=> false
,
'children'
=> array
(
)))
;
// location of tree walker
$cur
=
'#root'
;
$lastcur
= array
(
array
(
false
,
0
))
;
$childpos
= 0
;
if
(
isset
(
$class_children
))
{
do
{
if
(
!
$class_children
)
{
list
(
$cur
,
$childpos
)
=
array_pop
(
$lastcur
)
;
if
(
isset
(
$my_tree
[
$cur
]
[
'children'
]
[
$childpos
+ 1
]
))
{
array_push
(
$lastcur
,
array
(
$cur
,
$childpos
+ 1
))
;
$par
=
$cur
;
$cur
=
$my_tree
[
$cur
]
[
'children'
]
[
$childpos
+ 1
]
;
$x
=
$this
->
classes
->
getClassByPackage
(
$cur
[
'class'
]
,
$cur
[
'package'
]
)
;
$childpos
= 0
;
$cur
=
$cur
[
'package'
]
.
'#'
.
$cur
[
'class'
]
;
$my_tree
[
$cur
]
[
'link'
]
=
Converter
::
getClassLink
(
$x
->
getName
(
)
,
$x
->
docblock
->
package
,
$x
->
getPath
(
))
;
$my_tree
[
$cur
]
[
'parent'
]
=
$par
;
$my_tree
[
$cur
]
[
'children'
]
= array
(
)
;
$class_children
=
$this
->
classes
->
getDefiniteChildren
(
$x
->
getName
(
)
,
$x
->
curfile
)
;
continue
;
}
else
{
$class_children
= false
;
continue
;
}
}
foreach
(
$class_children
as
$chileclass
=>
$chilefile
)
{
$ch
=
$this
->
classes
->
getClass
(
$chileclass
,
$chilefile
)
;
$my_tree
[
$cur
]
[
'children'
]
[
]
= array
(
'class'
=>
$ch
->
getName
(
)
,
'package'
=>
$ch
->
docblock
->
package
)
;
}
usort
(
$my_tree
[
$cur
]
[
'children'
]
,
'rootcmp'
)
;
if
(
isset
(
$my_tree
[
$cur
]
[
'children'
]
[
$childpos
]
))
{
array_push
(
$lastcur
,
array
(
$cur
,
$childpos
))
;
$par
=
$cur
;
$cur
=
$my_tree
[
$cur
]
[
'children'
]
[
$childpos
]
;
$x
=
$this
->
classes
->
getClassByPackage
(
$cur
[
'class'
]
,
$cur
[
'package'
]
)
;
$cur
=
$cur
[
'package'
]
.
'#'
.
$cur
[
'class'
]
;
$my_tree
[
$cur
]
[
'link'
]
=
Converter
::
getClassLink
(
$x
->
getName
(
)
,
$x
->
docblock
->
package
,
$x
->
getPath
(
))
;
$my_tree
[
$cur
]
[
'parent'
]
=
$par
;
$my_tree
[
$cur
]
[
'children'
]
= array
(
)
;
$childpos
= 0
;
$class_children
=
$this
->
classes
->
getDefiniteChildren
(
$x
->
getName
(
)
,
$x
->
curfile
)
;
}
else
{
list
(
$cur
,
$childpos
)
=
array_pop
(
$lastcur
)
;
}
}
while
(
$cur
)
;
}
return
$my_tree
;
}
/**
* do not override
*
@return
bool
true if a link to this class exists in package $package and subpackage $subpackage
*
@param
string
$expr
class name
*
@param
string
$package
package to search in
*
@param
string
$subpackage
subpackage to search in
*
@access
private
*/
function
isLinkedClass
(
$expr
,
$package
,
$subpackage
,
$file
=false
)
{
if
(
$file
)
return
isset
(
$this
->
linkswithfile
[
$package
]
[
$subpackage
]
[
'class'
]
[
$file
]
[
$expr
]
)
;
return
isset
(
$this
->
links
[
$package
]
[
$subpackage
]
[
'class'
]
[
$expr
]
)
;
}
/**
* do not override
*
@return
bool
true if a link to this function exists in package $package and subpackage $subpackage
*
@param
string
$expr
function name
*
@param
string
$package
package to search in
*
@param
string
$subpackage
subpackage to search in
*
@access
private
*/
function
isLinkedFunction
(
$expr
,
$package
,
$subpackage
,
$file
=false
)
{
if
(
$file
)
return
isset
(
$this
->
linkswithfile
[
$package
]
[
$subpackage
]
[
'function'
]
[
$file
]
[
$expr
]
)
;
return
isset
(
$this
->
links
[
$package
]
[
$subpackage
]
[
'function'
]
[
$expr
]
)
;
}
/**
* do not override
*
@return
bool
true if a link to this define exists in package $package and subpackage $subpackage
*
@param
string
$expr
define name
*
@param
string
$package
package to search in
*
@param
string
$subpackage
subpackage to search in
*
@access
private
*/
function
isLinkedDefine
(
$expr
,
$package
,
$subpackage
,
$file
=false
)
{
if
(
$file
)
return
isset
(
$this
->
linkswithfile
[
$package
]
[
$subpackage
]
[
'define'
]
[
$file
]
[
$expr
]
)
;
return
isset
(
$this
->
links
[
$package
]
[
$subpackage
]
[
'define'
]
[
$expr
]
)
;
}
/**
* do not override
*
@return
bool
true if a link to this define exists in package $package and subpackage $subpackage
*
@param
string
$expr
define name
*
@param
string
$package
package to search in
*
@param
string
$subpackage
subpackage to search in
*
@access
private
*/
function
isLinkedGlobal
(
$expr
,
$package
,
$subpackage
,
$file
=false
)
{
if
(
$file
)
return
isset
(
$this
->
linkswithfile
[
$package
]
[
$subpackage
]
[
'global'
]
[
$file
]
[
$expr
]
)
;
return
isset
(
$this
->
links
[
$package
]
[
$subpackage
]
[
'global'
]
[
$expr
]
)
;
}
/**
* do not override
*
@return
bool
true if a link to this procedural page exists in package $package and subpackage $subpackage
*
@param
string
$expr
procedural page name
*
@param
string
$package
package to search in
*
@param
string
$subpackage
subpackage to search in
*
@access
private
*/
function
isLinkedPage
(
$expr
,
$package
,
$subpackage
,
$path
=false
)
{
if
(
$path
)
return
isset
(
$this
->
linkswithfile
[
$package
]
[
$subpackage
]
[
'page'
]
[
$path
]
[
$expr
]
)
;
return
isset
(
$this
->
links
[
$package
]
[
$subpackage
]
[
'page'
]
[
$expr
]
)
;
}
/**
* do not override
*
@return
bool
true if a link to this method exists in package $package, subpackage $subpackage and class $class
*
@param
string
$expr
method name
*
@param
string
$class
class name
*
@param
string
$package
package to search in
*
@param
string
$subpackage
subpackage to search in
*
@access
private
*/
function
isLinkedMethod
(
$expr
,
$package
,
$subpackage
,
$class
,
$file
=false
)
{
if
(
$file
)
return
isset
(
$this
->
linkswithfile
[
$package
]
[
$subpackage
]
[
'method'
]
[
$file
]
[
$class
]
[
$expr
]
)
;
return
isset
(
$this
->
links
[
$package
]
[
$subpackage
]
[
'method'
]
[
$class
]
[
$expr
]
)
;
}
/**
* do not override
*
@return
bool
true if a link to this method exists in package $package, subpackage $subpackage and class $class
*
@param
string
$expr
var name
*
@param
string
$class
class name
*
@param
string
$package
package to search in
*
@param
string
$subpackage
subpackage to search in
*
@access
private
*/
function
isLinkedVar
(
$expr
,
$package
,
$subpackage
,
$class
,
$file
=false
)
{
if
(
$file
)
return
isset
(
$this
->
linkswithfile
[
$package
]
[
$subpackage
]
[
'var'
]
[
$file
]
[
$class
]
[
$expr
]
)
;
return
isset
(
$this
->
links
[
$package
]
[
$subpackage
]
[
'var'
]
[
$class
]
[
$expr
]
)
;
}
/**
* do not override
*
@return
bool
true if a link to this method exists in package $package, subpackage $subpackage and class $class
*
@param
string
$expr
constant name
*
@param
string
$class
class name
*
@param
string
$package
package to search in
*
@param
string
$subpackage
subpackage to search in
*
@access
private
*/
function
isLinkedConst
(
$expr
,
$package
,
$subpackage
,
$class
,
$file
=false
)
{
if
(
$file
)
return
isset
(
$this
->
linkswithfile
[
$package
]
[
$subpackage
]
[
'const'
]
[
$file
]
[
$class
]
[
$expr
]
)
;
return
isset
(
$this
->
links
[
$package
]
[
$subpackage
]
[
'const'
]
[
$class
]
[
$expr
]
)
;
}
/**
* return false or a
{@link classLink}
to $expr
*
@param
string
$expr
class name
*
@param
string
$package
package name
*
@return
mixed
returns a
{@link classLink}
or false if the element is not found in package $package
*
@see
classLink
*/
function
getClassLink
(
$expr
,
$package
,
$file
=false
,
$text
= false
)
{
if
(
!
isset
(
$this
->
links
[
$package
]
))
return
false
;
foreach
(
$this
->
links
[
$package
]
as
$subpackage
=>
$notused
)
{
if
(
$this
->
isLinkedClass
(
$expr
,
$package
,
$subpackage
,
$file
))
{
if
(
$file
)
{
return
$this
->
linkswithfile
[
$package
]
[
$subpackage
]
[
'class'
]
[
$file
]
[
$expr
]
;
}
return
$this
->
links
[
$package
]
[
$subpackage
]
[
'class'
]
[
$expr
]
;
}
}
return
false
;
}
/**
* return false or a
{@link functionLink}
to $expr
*
@param
string
$expr
function name
*
@param
string
$package
package name
*
@return
mixed
returns a
{@link functionLink}
or false if the element is not found in package $package
*
@see
functionLink
*/
function
getFunctionLink
(
$expr
,
$package
,
$file
=false
,
$text
= false
)
{
if
(
!
isset
(
$this
->
links
[
$package
]
))
return
false
;
foreach
(
$this
->
links
[
$package
]
as
$subpackage
=>
$notused
)
{
if
(
$this
->
isLinkedFunction
(
$expr
,
$package
,
$subpackage
,
$file
))
{
if
(
$file
)
{
return
$this
->
linkswithfile
[
$package
]
[
$subpackage
]
[
'function'
]
[
$file
]
[
$expr
]
;
}
return
$this
->
links
[
$package
]
[
$subpackage
]
[
'function'
]
[
$expr
]
;
}
}
return
false
;
}
/**
* return false or a
{@link defineLink}
to $expr
*
@param
string
$expr
constant name
*
@param
string
$package
package name
*
@return
mixed
returns a
{@link defineLink}
or false if the element is not found in package $package
*
@see
defineLink
*/
function
getDefineLink
(
$expr
,
$package
,
$file
=false
,
$text
= false
)
{
if
(
!
isset
(
$this
->
links
[
$package
]
))
return
false
;
foreach
(
$this
->
links
[
$package
]
as
$subpackage
=>
$notused
)
{
if
(
$this
->
isLinkedDefine
(
$expr
,
$package
,
$subpackage
,
$file
))
{
if
(
$file
)
{
return
$this
->
linkswithfile
[
$package
]
[
$subpackage
]
[
'define'
]
[
$file
]
[
$expr
]
;
}
return
$this
->
links
[
$package
]
[
$subpackage
]
[
'define'
]
[
$expr
]
;
}
}
return
false
;
}
/**
* return false or a
{@link globalLink}
to $expr
*
@param
string
$expr
global variable name (with leading $)
*
@param
string
$package
package name
*
@return
mixed
returns a
{@link defineLink}
or false if the element is not found in package $package
*
@see
defineLink
*/
function
getGlobalLink
(
$expr
,
$package
,
$file
=false
,
$text
= false
)
{
if
(
!
isset
(
$this
->
links
[
$package
]
))
return
false
;
foreach
(
$this
->
links
[
$package
]
as
$subpackage
=>
$notused
)
{
if
(
$this
->
isLinkedGlobal
(
$expr
,
$package
,
$subpackage
,
$file
))
{
if
(
$file
)
{
return
$this
->
linkswithfile
[
$package
]
[
$subpackage
]
[
'global'
]
[
$file
]
[
$expr
]
;
}
return
$this
->
links
[
$package
]
[
$subpackage
]
[
'global'
]
[
$expr
]
;
}
}
return
false
;
}
/**
* return false or a
{@link pageLink}
to $expr
*
@param
string
$expr
procedural page name
*
@param
string
$package
package name
*
@return
mixed
returns a
{@link pageLink}
or false if the element is not found in package $package
*
@see
pageLink
*/
function
getPageLink
(
$expr
,
$package
,
$path
= false
,
$text
= false
,
$packages
= false
)
{
if
(
!
isset
(
$this
->
links
[
$package
]
))
return
false
;
foreach
(
$this
->
links
[
$package
]
as
$subpackage
=>
$notused
)
{
if
(
$this
->
isLinkedPage
(
$expr
,
$package
,
$subpackage
,
$path
))
{
if
(
$path
)
{
return
$this
->
linkswithfile
[
$package
]
[
$subpackage
]
[
'page'
]
[
$path
]
[
$expr
]
;
}
return
$this
->
links
[
$package
]
[
$subpackage
]
[
'page'
]
[
$expr
]
;
}
}
return
false
;
}
/**
* return false or a
{@link methodLink}
to $expr in $class
*
@param
string
$expr
method name
*
@param
string
$class
class name
*
@param
string
$package
package name
*
@return
mixed
returns a
{@link methodLink}
or false if the element is not found in package $package, class $class
*
@see
methodLink
*/
function
getMethodLink
(
$expr
,
$class
,
$package
,
$file
=false
,
$text
= false
)
{
$expr
=
trim
(
$expr
)
;
$class
=
trim
(
$class
)
;
if
(
!
isset
(
$this
->
links
[
$package
]
))
return
false
;
foreach
(
$this
->
links
[
$package
]
as
$subpackage
=>
$notused
)
{
if
(
$this
->
isLinkedMethod
(
$expr
,
$package
,
$subpackage
,
$class
,
$file
))
{
if
(
$file
)
{
return
$this
->
linkswithfile
[
$package
]
[
$subpackage
]
[
'method'
]
[
$file
]
[
$class
]
[
$expr
]
;
}
return
$this
->
links
[
$package
]
[
$subpackage
]
[
'method'
]
[
$class
]
[
$expr
]
;
}
}
return
false
;
}
/**
* return false or a
{@link varLink}
to $expr in $class
*
@param
string
$expr
var name
*
@param
string
$class
class name
*
@param
string
$package
package name
*
@return
mixed
returns a
{@link varLink}
or false if the element is not found in package $package, class $class
*
@see
varLink
*/
function
getVarLink
(
$expr
,
$class
,
$package
,
$file
=false
,
$text
= false
)
{
$expr
=
trim
(
$expr
)
;
$class
=
trim
(
$class
)
;
if
(
!
isset
(
$this
->
links
[
$package
]
))
return
false
;
foreach
(
$this
->
links
[
$package
]
as
$subpackage
=>
$notused
)
{
if
(
$this
->
isLinkedVar
(
$expr
,
$package
,
$subpackage
,
$class
,
$file
))
{
if
(
$file
)
{
return
$this
->
linkswithfile
[
$package
]
[
$subpackage
]
[
'var'
]
[
$file
]
[
$class
]
[
$expr
]
;
}
return
$this
->
links
[
$package
]
[
$subpackage
]
[
'var'
]
[
$class
]
[
$expr
]
;
}
}
return
false
;
}
/**
* return false or a
{@link constLink}
to $expr in $class
*
@param
string
$expr
constant name
*
@param
string
$class
class name
*
@param
string
$package
package name
*
@return
mixed
returns a
{@link varLink}
or false if the element is not found in package $package, class $class
*
@see
constLink
*/
function
getConstLink
(
$expr
,
$class
,
$package
,
$file
=false
,
$text
= false
)
{
$expr
=
trim
(
$expr
)
;
$class
=
trim
(
$class
)
;
if
(
!
isset
(
$this
->
links
[
$package
]
))
return
false
;
foreach
(
$this
->
links
[
$package
]
as
$subpackage
=>
$notused
)
{
if
(
$this
->
isLinkedConst
(
$expr
,
$package
,
$subpackage
,
$class
,
$file
))
{
if
(
$file
)
{
return
$this
->
linkswithfile
[
$package
]
[
$subpackage
]
[
'const'
]
[
$file
]
[
$class
]
[
$expr
]
;
}
return
$this
->
links
[
$package
]
[
$subpackage
]
[
'const'
]
[
$class
]
[
$expr
]
;
}
}
return
false
;
}
/**
* The meat of the @tutorial tag and inline {@}tutorial} tag
*
* Take a string and return an abstract link to the tutorial it represents.
* Since tutorial naming literally works like the underlying filesystem, the
* way to reference the tutorial is similar. Tutorials are located in a
* subdirectory of any directory parsed, which is named 'tutorials/' (we
* try to make things simple when we can :). They are further organized by
* package and subpackage as:
*
* tutorials/package/subpackage
*
* and the files are named *.cls, *.pkg, or *.proc, and so a link to a tutorial
* named file.cls can be referenced (depending on context) as any of:
*
* <code>
* * @tutorial package/subpackage/file.cls
* * @tutorial package/file.cls
* * @tutorial file.cls
* </code>
*
* The first case will only be needed if file.cls exists in both the current
* package, in anotherpackage/file.cls and in anotherpackage/subpackage/file.cls
* and you wish to reference the one in anotherpackage/subpackage.
* The second case is only needed if you wish to reference file.cls in another
* package and it is unique in that package. the third will link to the first
* file.cls it finds using this search method:
*
* <ol>
* <li>current package/subpackage</li>
* <li>all other subpackages of current package</li>
* <li>parent package, if this package has classes that extend classes in
* another package</li>
* <li>all other packages</li>
* </ol>
*
@return
tutorialLink
|
string
returns either a link, or the original text, if not found
*
@param
string
the original expression
*
@param
string
package to look in first
*
@param
string
subpackage to look in first
*
@param
array
array of package names to search in if not found in parent packages.
* This is used to limit the search, phpDocumentor automatically searches
* all packages
*
@since
1.2
*/
function
getTutorialLink
(
$expr
,
$package
= false
,
$subpackage
= false
,
$packages
= false
)
{
// is $expr a comma-delimited list?
if
(
strpos
(
$expr
,
','
))
{
$a
=
explode
(
','
,
$expr
)
;
$b
= array
(
)
;
for
(
$i
=0
;
$i
<
count
(
$a
)
;
$i
++
)
{
// if so return each component with a link
$b
[
]
=
Converter
::
getTutorialLink
(
trim
(
$a
[
$i
]
))
;
}
return
$b
;
}
$subsection
=
''
;
if
(
strpos
(
$expr
,
'#'
))
{
$a
=
explode
(
'#'
,
$expr
)
;
$org
=
$expr
;
$expr
=
$a
[
0
]
;
$subsection
=
$a
[
1
]
;
}
if
(
strpos
(
$expr
,
'/'
))
{
$a
=
explode
(
'/'
,
$expr
)
;
if
(
count
(
$a
)
== 3
)
{
return
Converter
::
getTutorialLink
(
$a
[
2
]
,
$a
[
0
]
,
$a
[
1
]
,
array
(
))
;
}
if
(
count
(
$a
)
== 2
)
{
return
Converter
::
getTutorialLink
(
$a
[
1
]
,
$a
[
0
]
,
false
,
array
(
))
;
}
}
if
(
!
$package
)
$package
=
$this
->
package
;
if
(
!
$subpackage
)
$subpackage
=
$this
->
subpackage
;
if
(
!
isset
(
$this
->
all_packages
[
$package
]
))
return
$expr
;
elseif
(
isset
(
$packages
[
$package
]
))
unset
(
$packages
[
$package
]
)
;
$ext
=
pathinfo
(
$expr
,
PATHINFO_EXTENSION
)
;
if
(
isset
(
$this
->
tutorials
[
$package
]
[
$subpackage
]
[
$ext
]
[
$expr
]
))
{
$a
=
$this
->
tutorials
[
$package
]
[
$subpackage
]
[
$ext
]
[
$expr
]
;
$link
= new
tutorialLink
;
$link
->
addLink
(
$subsection
,
$a
->
path
,
$a
->
name
,
$a
->
package
,
$a
->
subpackage
,
$a
->
getTitle
(
$this
,
$subsection
))
;
return
$link
;
}
do
{
if
(
!
is_array
(
$packages
))
{
$packages
=
$this
->
all_packages
;
if
(
isset
(
$packages
[
$package
]
))
unset
(
$packages
[
$package
]
)
;
}
if
(
isset
(
$this
->
tutorials
[
$package
]
))
{
if
(
isset
(
$this
->
tutorials
[
$package
]
[
$subpackage
]
[
$ext
]
[
$expr
]
))
{
$a
=
$this
->
tutorials
[
$package
]
[
$subpackage
]
[
$ext
]
[
$expr
]
;
$link
= new
tutorialLink
;
$link
->
addLink
(
$subsection
,
$a
->
path
,
$a
->
name
,
$a
->
package
,
$a
->
subpackage
,
$a
->
getTitle
(
$this
))
;
return
$link
;
}
else
{
foreach
(
$this
->
tutorials
[
$package
]
as
$subpackage
=>
$stuff
)
{
if
(
isset
(
$stuff
[
$ext
]
[
$expr
]
))
{
$a
=
$stuff
[
$ext
]
[
$expr
]
;
$link
= new
tutorialLink
;
$link
->
addLink
(
$subsection
,
$a
->
path
,
$a
->
name
,
$a
->
package
,
$a
->
subpackage
,
$a
->
getTitle
(
$this
))
;
return
$link
;
}
}
}
}
// try other packages
// look in parent package first, if found
if
(
isset
(
$this
->
package_parents
[
$package
]
))
{
$p1
=
$package
;
$package
=
$this
->
package_parents
[
$package
]
;
}
else
{
// no parent package, so start with the first one that's left
list
(
$package
,
)
=
@
each
(
$packages
)
;
}
if
(
$package
)
{
if
(
isset
(
$packages
[
$package
]
))
unset
(
$packages
[
$package
]
)
;
}
}
while
(
count
(
$packages
)
||
$package
)
;
addWarning
(
PDERROR_TUTORIAL_NOT_FOUND
,
$expr
)
;
return
$expr
;
}
/**
* The meat of the @see tag and inline {@}link} tag
*
* $expr is a string with many allowable formats:
* <ol>
* <li>proceduralpagename.ext</li>
* <li>constant_name</li>
* <li>classname::function()</li>
* <li>classname::constantname</li> (new 1.2.4)
* <li>classname::$variablename</li>
* <li>classname</li>
* <li>object classname</li>
* <li>function functionname()</li>
* <li>global $globalvarname</li>
* <li>packagename#expr where expr is any of the above</li>
* </ol>
*
* New in version 1.1, you can explicitly specify a package to link to that
* is different from the current package. Use the # operator
* to specify a new package, as in tests#bug-540368.php (which should appear
* as a link like: "
{@link tests#bug-540368.php}
"). This
* example links to the procedural page bug-540368.php in package
* tests. Also, the "function" operator is now used to specifically
* link to a function instead of a method in the current class.
*
* <code>
* class myclass
* {
* // from inside the class definition, use "function conflict()" to refer to procedural function "conflict()"
* function conflict()
* {
* }
* }
*
* function conflict()
* {
* }
* </code>
*
* If classname:: is not present, and the see tag is in a documentation
* block within a class, then the function uses the classname to
* search for $expr as a function or variable within classname, or any of its parent classes.
* given an $expr without '$', '::' or '()' getLink first searches for
* classes, procedural pages, constants, global variables, and then searches for
* methods and variables within the default class, and finally for any function
*
*
@param
string
$expr
expression to search for a link
*
@param
string
$package
package to start searching in
*
@param
array
$packages
list of all packages to search in
*
@return
mixed
getLink returns a descendant of
{@link abstractLink}
if it finds a link, otherwise it returns a string
*
@see
getPageLink(), getDefineLink(), getVarLink(), getFunctionLink(), getClassLink()
*
@see
pageLink, functionLink, defineLink, classLink, methodLink, varLink
*/
function
&
getLink
(
$expr
,
$package
= false
,
$packages
= false
)
{
// is $expr a comma-delimited list?
if
(
strpos
(
$expr
,
','
))
{
$a
=
explode
(
','
,
$expr
)
;
$b
= array
(
)
;
for
(
$i
=0
;
$i
<
count
(
$a
)
;
$i
++
)
{
// if so return each component with a link
$b
[
]
=
Converter
::
getLink
(
trim
(
$a
[
$i
]
))
;
}
return
$b
;
}
if
(
strpos
(
$expr
,
'#'
))
{
$a
=
explode
(
'#'
,
$expr
)
;
if
(
count
(
$a
)
== 2
)
{
// can have exactly 1 package override, otherwise it's ignored
// feature 564991, link to php manual
if
(
$a
[
0
]
==
'PHP_MANUAL'
)
{
$s
=
'http://www.php.net/'
.
$a
[
1
]
;
return
$s
;
}
$s
=
&
Converter
::
getLink
(
$a
[
1
]
,
$a
[
0
]
,
array
(
))
;
return
$s
;
}
}
$a
=
&
$this
->
_getLink
(
$expr
,
$package
,
$packages
)
;
return
$a
;
}
/**
*
@access
private
*/
function
&
_getLink
(
$expr
,
$package
= false
,
$packages
= false
)
{
if
(
!
$package
)
$package
=
$this
->
package
;
//
if
(
!
isset
(
$this
->
all_packages
[
$package
]
))
return
$expr
;
elseif
(
isset
(
$packages
[
$package
]
))
unset
(
$packages
[
$package
]
)
;
$links
=
&
$this
->
links
;
$class
=
$this
->
class
;
if
(
strpos
(
$expr
,
'function '
)
=== 0
)
{
// asking for a function, not a method
if
(
$test
=
Converter
::
getFunctionLink
(
str_replace
(
'function '
,
''
,
str_replace
(
'()'
,
''
,
$expr
))
,
$package
))
return
$test
;
else
return
$expr
;
}
if
(
strpos
(
$expr
,
'global '
)
=== 0
)
{
// asking for a global variable
if
(
$test
=
Converter
::
getGlobalLink
(
str_replace
(
'global '
,
''
,
$expr
)
,
$package
))
return
$test
;
else
return
$expr
;
}
if
(
strpos
(
$expr
,
'object '
)
=== 0
)
{
// asking for a class
if
(
$test
=
Converter
::
getClassLink
(
str_replace
(
'object '
,
''
,
$expr
)
,
$package
))
return
$test
;
else
return
$expr
;
}
if
(
strpos
(
$expr
,
'constant '
)
=== 0
)
{
// asking for a class
if
(
$test
=
Converter
::
getDefineLink
(
str_replace
(
'constant '
,
''
,
$expr
)
,
$package
))
return
$test
;
else
return
$expr
;
}
// are we in a class?
if
(
$class
)
{
// is $expr simply a word? see if it is the class
if
(
trim
(
$expr
)
==
$class
)
{
if
(
$test
=
Converter
::
getClassLink
(
trim
(
str_replace
(
'object '
,
''
,
$expr
))
,
$package
))
return
$test
;
}
// if not, check to see if it is a method or variable of this class tree
if
(
!
strpos
(
$expr
,
'::'
))
{
// if get is neither get() nor $get, assume get is a function, add () to make get()
if
(
strpos
(
$expr
,
'$'
)
!== 0 &&
!
strpos
(
$expr
,
'()'
))
//$get = $get.'()';
{
if
(
$a
=
$this
->
getLinkMethod
(
$expr
,
$class
,
$package
))
return
$a
;
if
(
$a
=
$this
->
getLinkConst
(
$expr
,
$class
,
$package
))
return
$a
;
if
(
$a
=
$this
->
getLinkVar
(
'$'
.
$expr
,
$class
,
$package
))
return
$a
;
}
if
(
strpos
(
$expr
,
'()'
))
if
(
$a
=
$this
->
getLinkMethod
(
$expr
,
$class
,
$package
))
return
$a
;
if
(
is_numeric
(
strpos
(
$expr
,
'$'
)))
if
(
$a
=
$this
->
getLinkVar
(
$expr
,
$class
,
$package
))
return
$a
;
}
}
if
(
$test
=
Converter
::
getClassLink
(
trim
(
str_replace
(
'object '
,
''
,
$expr
))
,
$package
))
return
$test
;
if
(
$test
=
Converter
::
getPageLink
(
trim
(
$expr
)
,
$package
))
return
$test
;
if
(
$test
=
Converter
::
getDefineLink
(
trim
(
$expr
)
,
$package
))
return
$test
;
if
(
$test
=
Converter
::
getGlobalLink
(
trim
(
$expr
)
,
$package
))
return
$test
;
// if (strpos($expr,'.'))
// package specified
if
(
!
is_array
(
$packages
))
{
$packages
=
$this
->
all_packages
;
}
do
{
if
(
isset
(
$packages
[
$package
]
))
unset
(
$packages
[
$package
]
)
;
if
(
$test
=
Converter
::
getClassLink
(
str_replace
(
'object '
,
''
,
$expr
)
,
$package
))
return
$test
;
if
(
$test
=
Converter
::
getPageLink
(
$expr
,
$package
))
return
$test
;
if
(
$test
=
Converter
::
getDefineLink
(
$expr
,
$package
))
return
$test
;
if
(
$test
=
Converter
::
getGlobalLink
(
$expr
,
$package
))
return
$test
;
// is $expr in class::method() or class::$variable format?
if
(
strpos
(
$expr
,
'function '
)
=== 0
)
{
// asking for a function, not a method
if
(
$test
=
Converter
::
getFunctionLink
(
str_replace
(
'function'
,
''
,
str_replace
(
'()'
,
''
,
$expr
))
,
$package
))
return
$test
;
else
return
$expr
;
}
$test
=
$this
->
_getDoubleColon
(
$expr
,
$package
,
$packages
,
$class
,
$links
)
;
if
(
!
is_string
(
$test
))
return
$test
;
if
(
strpos
(
$test
,
'parent::'
)
=== 0
)
return
$test
;
// $expr does not have ::
if
(
is_numeric
(
@
strpos
(
'$'
,
$expr
)))
{
// default to current class, whose name is contained in $this->render->parent
if
(
$test
=
Converter
::
getVarLink
(
$expr
,
$class
,
$package
))
return
$test
;
}
// $expr is a function? (non-method)
if
(
@
strpos
(
$expr
,
'()'
))
{
// otherwise, see if it is a method
if
(
$class
)
{
if
(
$test
=
Converter
::
getMethodLink
(
str_replace
(
'()'
,
''
,
$expr
)
,
$class
,
$package
))
return
$test
;
}
// extract the function name, use it to retrieve the file that the function is in
// $page = $this->func_page[str_replace('function ','',str_replace('()','',$expr))];
// return the link
if
(
$test
=
Converter
::
getFunctionLink
(
str_replace
(
'function '
,
''
,
str_replace
(
'()'
,
''
,
$expr
))
,
$package
))
return
$test
;
}
// $expr is just a word. First, test to see if it is a function of the current package
if
(
$test
=
Converter
::
getFunctionLink
(
str_replace
(
'function '
,
''
,
str_replace
(
'()'
,
''
,
$expr
))
,
$package
))
return
$test
;
// try other packages
// look in parent package first, if found
if
(
isset
(
$this
->
package_parents
[
$package
]
)
&&
in_array
(
$this
->
package_parents
[
$package
]
,
$packages
))
{
$p1
=
$package
;
$package
=
$this
->
package_parents
[
$package
]
;
if
(
$package
)
{
if
(
isset
(
$packages
[
$package
]
))
unset
(
$packages
[
$package
]
)
;
}
continue
;
}
// no parent package, so start with the first one that's left
$package
=
@
array_shift
(
@
array_keys
(
$packages
))
;
if
(
$package
&& isset
(
$packages
[
$package
]
))
{
unset
(
$packages
[
$package
]
)
;
}
}
while
(
count
(
$packages
)
||
$package
)
;
$funcs
=
get_defined_functions
(
)
;
// feature 564991, link to php manual
if
(
in_array
(
str_replace
(
array
(
'('
,
')'
)
,
array
(
''
,
''
)
,
$expr
)
,
$funcs
[
'internal'
]
))
{
$return
=
'http://www.php.net/'
.
str_replace
(
array
(
'('
,
')'
)
,
array
(
''
,
''
)
,
$expr
)
;
return
$return
;
}
// no links found
return
$expr
;
}
/**
* Split up getLink to make it easier to debug
*
@access
private
*/
function
_getDoubleColon
(
&
$expr
,
&
$package
,
&
$packages
,
$class
,
$links
)
{
if
(
@
strpos
(
$expr
,
'::'
))
{
$class_method
=
explode
(
'::'
,
$expr
)
;
if
(
$class_method
[
0
]
==
'parent'
)
{
// can only have parent in the same package as the class! subtle bug
$package
=
$this
->
package
;
$packages
= array
(
)
;
$cl
=
$this
->
classes
->
getClassByPackage
(
$class
,
$package
)
;
if
(
!
$cl
)
{
// this is possible if an example file has parent::method()
return
$expr
;
}
$par
=
$cl
->
getParent
(
$this
)
;
$phpparent
= false
;
if
(
is_object
(
$par
))
{
$package
=
$par
->
docblock
->
package
;
$phpparent
=
$par
->
getName
(
)
;
}
else
{
addWarning
(
PDERROR_CLASS_PARENT_NOT_FOUND
,
$class
,
$package
,
$class_method
[
1
]
)
;
return
$expr
;
}
if
(
$phpparent
)
$class_method
[
0
]
=
$phpparent
;
}
if
(
strpos
(
$class_method
[
1
]
,
'()'
))
{
// strip everything but the function name, return a link
if
(
$test
=
Converter
::
getMethodLink
(
str_replace
(
'()'
,
''
,
$class_method
[
1
]
)
,
$class_method
[
0
]
,
$package
))
return
$test
;
}
if
(
$test
=
Converter
::
getVarLink
(
$class_method
[
1
]
,
$class_method
[
0
]
,
$package
))
return
$test
;
if
(
$test
=
Converter
::
getConstLink
(
$class_method
[
1
]
,
$class_method
[
0
]
,
$package
))
return
$test
;
}
return
$expr
;
}
/**
* cycle through parent classes to retrieve a link to a method
* do not use or override, used by getLink
*
@access
private
*/
function
&
getLinkMethod
(
$expr
,
$class
,
$package
)
{
$links
=
&
$this
->
links
;
do
{
// is $expr in class::method() or class::$variable format?
if
(
@
strpos
(
$expr
,
'::'
))
{
$class_method
=
explode
(
'::'
,
$expr
)
;
if
(
$class_method
[
0
]
==
'parent'
)
{
$cl
=
$this
->
classes
->
getClassByPackage
(
$class
,
$package
)
;
$par
=
$cl
->
getParent
(
$this
)
;
$phpparent
= false
;
if
(
is_object
(
$par
))
{
$package
=
$par
->
docblock
->
package
;
$phpparent
=
$par
->
getName
(
)
;
}
else
addWarning
(
PDERROR_CLASSPARENT_NOTFOUND
,
$class
,
$package
,
$class_method
[
1
]
)
;
if
(
$phpparent
)
$class_method
[
0
]
=
$phpparent
;
}
else
{
$cl
=
$this
->
classes
->
getClassByPackage
(
$class
,
$package
)
;
}
if
(
strpos
(
$class_method
[
1
]
,
'()'
))
{
// strip everything but the function name, return a link
if
(
$test
=
Converter
::
getMethodLink
(
str_replace
(
'function '
,
''
,
str_replace
(
'()'
,
''
,
$class_method
[
1
]
))
,
$class_method
[
0
]
,
$package
))
return
$test
;
}
}
if
(
$test
=
Converter
::
getMethodLink
(
str_replace
(
'()'
,
''
,
$expr
)
,
$class
,
$package
))
return
$test
;
$cl
=
$this
->
classes
->
getClassByPackage
(
$class
,
$package
)
;
if
(
$cl
)
{
$par
=
$cl
->
getParent
(
$this
)
;
if
(
is_object
(
$par
))
{
$package
=
$par
->
docblock
->
package
;
$class
=
$par
->
getName
(
)
;
}
else
$class
=
$par
;
}
else
$class
= false
;
}
while
(
$class
)
;
// no links found
$flag
= false
;
return
$flag
;
}
/**
* cycle through parent classes to retrieve a link to a var
* do not use or override, used by getLink
*
@access
private
*/
function
&
getLinkVar
(
$expr
,
$class
,
$package
)
{
$links
=
&
$this
->
links
;
do
{
// is $expr in class::method() or class::$variable format?
if
(
@
strpos
(
$expr
,
'::'
))
{
$class_method
=
explode
(
'::'
,
$expr
)
;
if
(
$class_method
[
0
]
==
'parent'
)
{
$cl
=
$this
->
classes
->
getClassByPackage
(
$class
,
$package
)
;
$phpparent
= false
;
$par
=
$cl
->
getParent
(
$this
)
;
if
(
is_object
(
$par
))
{
$package
=
$par
->
docblock
->
package
;
$phpparent
=
$par
->
getName
(
)
;
}
else
addWarning
(
PDERROR_CLASSPARENT_NOTFOUND
,
$class
,
$package
,
$class_method
[
1
]
)
;
if
(
$phpparent
)
$class_method
[
0
]
=
$phpparent
;
}
else
{
$cl
=
$this
->
classes
->
getClassByPackage
(
$class
,
$package
)
;
}
if
(
$test
=
Converter
::
getVarLink
(
$class_method
[
1
]
,
$class_method
[
0
]
,
$package
))
return
$test
;
if
(
$test
=
Converter
::
getVarLink
(
'$'
.
$class_method
[
1
]
,
$class_method
[
0
]
,
$package
))
return
$test
;
}
if
(
$test
=
Converter
::
getVarLink
(
$expr
,
$class
,
$package
))
return
$test
;
if
(
$test
=
Converter
::
getVarLink
(
'$'
.
$expr
,
$class
,
$package
))
return
$test
;
$cl
=
$this
->
classes
->
getClassByPackage
(
$class
,
$package
)
;
if
(
$cl
)
{
$par
=
$cl
->
getParent
(
$this
)
;
if
(
is_object
(
$par
))
{
$package
=
$par
->
docblock
->
package
;
$class
=
$par
->
getName
(
)
;
}
else
$class
=
$par
;
}
else
$class
= false
;
}
while
(
$class
)
;
// no links found
$class
= false
;
return
$class
;
}
/**
* cycle through parent classes to retrieve a link to a class constant
* do not use or override, used by getLink
*
@access
private
*
@since
1.2.4
*/
function
&
getLinkConst
(
$expr
,
$class
,
$package
)
{
$links
=
&
$this
->
links
;
do
{
// is $expr in class::method() or class::$variable format?
if
(
@
strpos
(
$expr
,
'::'
))
{
$class_method
=
explode
(
'::'
,
$expr
)
;
if
(
$class_method
[
0
]
==
'parent'
)
{
$cl
=
$this
->
classes
->
getClassByPackage
(
$class
,
$package
)
;
$phpparent
= false
;
$par
=
$cl
->
getParent
(
$this
)
;
if
(
is_object
(
$par
))
{
$package
=
$par
->
docblock
->
package
;
$phpparent
=
$par
->
getName
(
)
;
}
else
addWarning
(
PDERROR_CLASSPARENT_NOTFOUND
,
$class
,
$package
,
$class_method
[
1
]
)
;
if
(
$phpparent
)
$class_method
[
0
]
=
$phpparent
;
}
else
{
$cl
=
$this
->
classes
->
getClassByPackage
(
$class
,
$package
)
;
}
if
(
$test
=
Converter
::
getConstLink
(
$class_method
[
1
]
,
$class_method
[
0
]
,
$package
))
return
$test
;
}
if
(
$test
=
Converter
::
getConstLink
(
$expr
,
$class
,
$package
))
return
$test
;
$cl
=
$this
->
classes
->
getClassByPackage
(
$class
,
$package
)
;
if
(
$cl
)
{
$par
=
$cl
->
getParent
(
$this
)
;
if
(
is_object
(
$par
))
{
$package
=
$par
->
docblock
->
package
;
$class