summaryrefslogtreecommitdiff
path: root/buildscripts
diff options
context:
space:
mode:
Diffstat (limited to 'buildscripts')
-rw-r--r--buildscripts/Benchmark/Iterate.php167
-rw-r--r--buildscripts/Benchmark/LICENSE22
-rw-r--r--buildscripts/Benchmark/Profiler.php447
-rw-r--r--buildscripts/Benchmark/Timer.php319
-rw-r--r--buildscripts/Benchmark/doc/timer_example.php18
-rw-r--r--buildscripts/PHPUnit2/Extensions/ExceptionTestCase.php122
-rw-r--r--buildscripts/PHPUnit2/Extensions/PerformanceTestCase.php128
-rw-r--r--buildscripts/PHPUnit2/Extensions/RepeatedTest.php138
-rw-r--r--buildscripts/PHPUnit2/Extensions/TestDecorator.php174
-rw-r--r--buildscripts/PHPUnit2/Extensions/TestSetup.php154
-rw-r--r--buildscripts/PHPUnit2/Framework/Assert.php626
-rw-r--r--buildscripts/PHPUnit2/Framework/AssertionFailedError.php80
-rw-r--r--buildscripts/PHPUnit2/Framework/ComparisonFailure.php153
-rw-r--r--buildscripts/PHPUnit2/Framework/Error.php88
-rw-r--r--buildscripts/PHPUnit2/Framework/IncompleteTest.php72
-rw-r--r--buildscripts/PHPUnit2/Framework/IncompleteTestError.php75
-rw-r--r--buildscripts/PHPUnit2/Framework/Test.php87
-rw-r--r--buildscripts/PHPUnit2/Framework/TestCase.php292
-rw-r--r--buildscripts/PHPUnit2/Framework/TestFailure.php154
-rw-r--r--buildscripts/PHPUnit2/Framework/TestListener.php135
-rw-r--r--buildscripts/PHPUnit2/Framework/TestResult.php447
-rw-r--r--buildscripts/PHPUnit2/Framework/TestSuite.php554
-rw-r--r--buildscripts/PHPUnit2/Framework/Warning.php94
-rw-r--r--buildscripts/PHPUnit2/Runner/BaseTestRunner.php283
-rw-r--r--buildscripts/PHPUnit2/Runner/IncludePathTestCollector.php184
-rw-r--r--buildscripts/PHPUnit2/Runner/StandardTestSuiteLoader.php129
-rw-r--r--buildscripts/PHPUnit2/Runner/TestCollector.php77
-rw-r--r--buildscripts/PHPUnit2/Runner/TestSuiteLoader.php85
-rw-r--r--buildscripts/PHPUnit2/Runner/Version.php90
-rw-r--r--buildscripts/PHPUnit2/TextUI/ResultPrinter.php356
-rw-r--r--buildscripts/PHPUnit2/TextUI/TestRunner.php622
-rw-r--r--buildscripts/PHPUnit2/Util/CodeCoverage/Renderer.php225
-rw-r--r--buildscripts/PHPUnit2/Util/CodeCoverage/Renderer/HTML.php191
-rw-r--r--buildscripts/PHPUnit2/Util/CodeCoverage/Renderer/Text.php125
-rw-r--r--buildscripts/PHPUnit2/Util/ErrorHandler.php77
-rw-r--r--buildscripts/PHPUnit2/Util/Fileloader.php109
-rw-r--r--buildscripts/PHPUnit2/Util/Filter.php263
-rw-r--r--buildscripts/PHPUnit2/Util/Log/PEAR.php220
-rw-r--r--buildscripts/PHPUnit2/Util/Log/XML.php356
-rw-r--r--buildscripts/PHPUnit2/Util/Printer.php116
-rw-r--r--buildscripts/PHPUnit2/Util/Skeleton.php340
-rw-r--r--buildscripts/PHPUnit2/Util/TestDox/NamePrettifier.php165
-rw-r--r--buildscripts/PHPUnit2/Util/TestDox/ResultPrinter.php299
-rw-r--r--buildscripts/PHPUnit2/Util/TestDox/ResultPrinter/HTML.php120
-rw-r--r--buildscripts/PHPUnit2/Util/TestDox/ResultPrinter/Text.php102
-rw-r--r--buildscripts/PHPUnit2/pear-phpunit41
-rw-r--r--buildscripts/PHPUnit2/pear-phpunit.bat39
-rw-r--r--buildscripts/PhpDocumentor/PHPLICENSE.txt69
-rw-r--r--buildscripts/PhpDocumentor/new_phpdoc.php662
-rw-r--r--buildscripts/PhpDocumentor/pear-phpdoc38
-rw-r--r--buildscripts/PhpDocumentor/pear-phpdoc.bat145
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor.ini118
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Classes.inc1068
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converter.inc5189
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/CHMdefaultConverter.inc1753
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/options.ini507
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/basicindex.tpl21
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/blank.tpl13
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/class.tpl94
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/classleft.tpl8
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/classtrees.tpl12
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/const.tpl29
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/contents.hhc.tpl11
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/define.tpl33
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/docblock.tpl31
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/elementindex.tpl9
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/errors.tpl21
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/fileleft.tpl8
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/filesource.tpl6
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/footer.tpl8
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/function.tpl44
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/global.tpl32
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/header.tpl22
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/hhp.tpl17
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/include.tpl26
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/index.hhk.tpl8
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/index.tpl24
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/media/bg_left.pngbin0 -> 991 bytes
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/media/stylesheet.css129
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/method.tpl55
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/packages.tpl3
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/page.tpl34
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/pkgelementindex.tpl14
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/ric.tpl6
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/tocentry.tpl11
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/todolist.tpl14
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/tutorial.tpl32
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/tutorial_toc.tpl29
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/tutorial_tree.tpl5
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/var.tpl30
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/HTMLSmartyConverter.inc1779
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/options.ini577
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/__tags.tpl13
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_class_declaration.tpl38
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_class_description.tpl7
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_class_list.tpl1
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_constant_details.tpl33
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_constant_summary.tpl22
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_constructor_details.tpl55
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_constructor_summary.tpl25
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_destructor_details.tpl55
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_destructor_summary.tpl27
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_footer.tpl1
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_get_constant_type.tpl10
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_header.tpl4
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_inherited_constants.tpl34
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_inherited_methods.tpl42
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_inheritence_tree.tpl3
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_method_details.tpl101
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_method_summary.tpl61
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_sub_classes.tpl19
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_tags.tpl13
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/basicindex.tpl18
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/blank.tpl5
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/class.tpl29
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/classleft.tpl9
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/classtrees.tpl8
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/const.tpl14
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/define.tpl32
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/docblock.tpl15
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/elementindex.tpl5
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/errors.tpl21
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/examplesource.tpl6
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/fileleft.tpl10
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/filesource.tpl8
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/footer.tpl25
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/function.tpl48
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/global.tpl40
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/header.tpl121
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/include.tpl9
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/index.tpl7
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/media/background.pngbin0 -> 238 bytes
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/media/empty.pngbin0 -> 206 bytes
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/media/style.css197
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/method.tpl58
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/packages.tpl3
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/page.tpl31
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/pkgelementindex.tpl5
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/ric.tpl6
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/todolist.tpl14
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/tutorial.tpl32
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/tutorial_toc.tpl29
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/tutorial_tree.tpl5
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/var.tpl28
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/HTMLframesConverter.inc1747
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/options.ini577
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/basicindex.tpl47
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/blank.tpl13
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/class.tpl402
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/classtrees.tpl11
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/const.tpl18
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/define.tpl24
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/docblock.tpl14
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/elementindex.tpl12
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/errors.tpl21
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/examplesource.tpl6
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/filesource.tpl8
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/footer.tpl8
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/function.tpl44
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/global.tpl26
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/header.tpl12
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/include.tpl16
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/index.tpl24
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/left_frame.tpl149
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/media/banner.css32
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/media/stylesheet.css144
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/method.tpl61
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/page.tpl211
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/pkgelementindex.tpl17
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/ric.tpl6
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/todolist.tpl14
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/top_frame.tpl43
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/tutorial.tpl13
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/tutorial_nav.tpl41
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/tutorial_toc.tpl39
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/tutorial_tree.tpl6
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/var.tpl44
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/DescHTML.inc241
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/DocBlock/Lexer.inc701
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/DocBlockTags.inc984
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Errors.inc793
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/EventStack.inc78
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/HighlightParser.inc2354
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/InlineTags.inc854
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/IntermediateParser.inc1832
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Io.inc868
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/LinkClasses.inc206
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/PackagePageElements.inc387
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Parser.inc3185
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/ParserData.inc725
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/ParserDescCleanup.inc1456
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/ParserDocBlock.inc1165
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/ParserElements.inc1910
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/ProceduralPages.inc782
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Publisher.inc84
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Setup.inc.php785
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/BUGS7
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/COPYING.lib458
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/ChangeLog5421
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/FAQ284
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/INSTALL29
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/NEWS733
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/README80
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/RELEASE_NOTES423
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/TODO12
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/Config_File.class.php365
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/Smarty.class.php2010
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/Smarty_Compiler.class.php2123
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.assemble_plugin_filepath.php62
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.assign_smarty_interface.php43
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.create_dir_structure.php79
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.display_debug_console.php60
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.get_include_path.php44
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.get_microtime.php23
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.get_php_resource.php80
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.is_secure.php59
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.is_trusted.php50
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.load_plugins.php125
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.load_resource_plugin.php74
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.process_cached_inserts.php71
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.process_compiled_include.php32
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.read_cache_file.php111
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.rm_auto.php71
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.rmdir.php55
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.run_insert_handler.php71
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.smarty_include_php.php50
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.write_cache_file.php73
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.write_compiled_include.php59
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.write_compiled_resource.php37
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.write_file.php48
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/debug.tpl64
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/block.strip.php35
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/block.textformat.php83
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.assign.php38
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.assign_debug_info.php39
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.config_load.php130
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.counter.php88
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.cycle.php119
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.debug.php35
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.eval.php48
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.fetch.php217
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_checkboxes.php135
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_image.php143
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_options.php118
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_radios.php138
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_select_date.php243
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_select_time.php163
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_table.php113
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.mailto.php140
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.math.php82
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.popup.php87
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.popup_init.php39
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.var_dump.php20
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.capitalize.php25
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.cat.php33
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.count_characters.php31
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.count_paragraphs.php28
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.count_sentences.php28
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.count_words.php32
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.date_format.php43
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.debug_print_var.php57
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.default.php31
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.escape.php63
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.htmlentities.php18
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.indent.php27
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.lower.php25
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.nl2br.php35
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.rawurlencode.php18
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.regex_replace.php29
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.replace.php29
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.spacify.php29
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.string_format.php28
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.strip.php33
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.strip_tags.php31
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.truncate.php43
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.upper.php25
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.wordwrap.php28
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/outputfilter.trimwhitespace.php75
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/shared.escape_special_chars.php30
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/shared.make_timestamp.php43
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/misc/smarty_icon.README6
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/misc/smarty_icon.gifbin0 -> 1102 bytes
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/TutorialHighlightParser.inc491
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/WordParser.inc325
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/XMLpackagePageParser.inc554
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/clone.inc.php13
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/clone5.inc.php14
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/common.inc.php244
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/find_phpdoc.php32
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/phpDocumentorTParser.inc2615
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/phpDocumentorTWordParser.inc311
-rw-r--r--buildscripts/PhpDocumentor/phpDocumentor/phpdoc.inc45
-rw-r--r--buildscripts/PhpDocumentor/phpdoc52
-rw-r--r--buildscripts/PhpDocumentor/phpdoc.php469
-rw-r--r--buildscripts/PhpDocumentor/poweredbyphpdoc.gifbin0 -> 1363 bytes
-rw-r--r--buildscripts/PhpDocumentor/scripts/add_cvs.php153
-rw-r--r--buildscripts/PhpDocumentor/scripts/create_examples.php66
-rw-r--r--buildscripts/PhpDocumentor/scripts/create_package.xml.php204
-rw-r--r--buildscripts/PhpDocumentor/scripts/makedoc.sh94
-rw-r--r--buildscripts/PhpDocumentor/scripts/tokenizer_test.php59
-rw-r--r--buildscripts/PhpDocumentor/user/default.ini98
-rw-r--r--buildscripts/PhpDocumentor/user/demo.ini78
-rw-r--r--buildscripts/PhpDocumentor/user/error.ini82
-rw-r--r--buildscripts/PhpDocumentor/user/pear-makedocs.ini71
-rw-r--r--buildscripts/PhpDocumentor/user/prado.ini79
-rw-r--r--buildscripts/PhpDocumentor/user/testdocbook.ini74
-rw-r--r--buildscripts/index/api_index.php3
-rw-r--r--buildscripts/index/search.php36
-rw-r--r--buildscripts/phing/CREDITS45
-rw-r--r--buildscripts/phing/LICENSE1042
-rw-r--r--buildscripts/phing/README78
-rw-r--r--buildscripts/phing/bin/pear-phing22
-rw-r--r--buildscripts/phing/bin/pear-phing.bat44
-rw-r--r--buildscripts/phing/bin/phing75
-rw-r--r--buildscripts/phing/bin/phing.bat58
-rw-r--r--buildscripts/phing/bin/phing.php50
-rw-r--r--buildscripts/phing/classes/phing/BuildEvent.php205
-rw-r--r--buildscripts/phing/classes/phing/BuildException.php100
-rw-r--r--buildscripts/phing/classes/phing/BuildListener.php91
-rw-r--r--buildscripts/phing/classes/phing/IntrospectionHelper.php542
-rw-r--r--buildscripts/phing/classes/phing/Phing.php1161
-rw-r--r--buildscripts/phing/classes/phing/Project.php966
-rw-r--r--buildscripts/phing/classes/phing/ProjectComponent.php72
-rw-r--r--buildscripts/phing/classes/phing/RuntimeConfigurable.php118
-rw-r--r--buildscripts/phing/classes/phing/Target.php317
-rw-r--r--buildscripts/phing/classes/phing/Task.php266
-rw-r--r--buildscripts/phing/classes/phing/TaskAdapter.php84
-rw-r--r--buildscripts/phing/classes/phing/TaskContainer.php42
-rw-r--r--buildscripts/phing/classes/phing/UnknownElement.php211
-rw-r--r--buildscripts/phing/classes/phing/filters/BaseFilterReader.php157
-rw-r--r--buildscripts/phing/classes/phing/filters/BaseParamFilterReader.php69
-rw-r--r--buildscripts/phing/classes/phing/filters/ChainableReader.php42
-rw-r--r--buildscripts/phing/classes/phing/filters/ExpandProperties.php82
-rw-r--r--buildscripts/phing/classes/phing/filters/HeadFilter.php161
-rw-r--r--buildscripts/phing/classes/phing/filters/LineContains.php258
-rw-r--r--buildscripts/phing/classes/phing/filters/LineContainsRegexp.php179
-rw-r--r--buildscripts/phing/classes/phing/filters/PrefixLines.php142
-rw-r--r--buildscripts/phing/classes/phing/filters/ReplaceRegexp.php129
-rw-r--r--buildscripts/phing/classes/phing/filters/ReplaceTokens.php415
-rw-r--r--buildscripts/phing/classes/phing/filters/StripLineBreaks.php148
-rw-r--r--buildscripts/phing/classes/phing/filters/StripLineComments.php205
-rw-r--r--buildscripts/phing/classes/phing/filters/StripPhpComments.php190
-rw-r--r--buildscripts/phing/classes/phing/filters/TabToSpaces.php144
-rw-r--r--buildscripts/phing/classes/phing/filters/TailFilter.php157
-rw-r--r--buildscripts/phing/classes/phing/filters/TidyFilter.php162
-rw-r--r--buildscripts/phing/classes/phing/filters/TranslateGettext.php285
-rw-r--r--buildscripts/phing/classes/phing/filters/XsltFilter.php317
-rw-r--r--buildscripts/phing/classes/phing/filters/util/ChainReaderHelper.php184
-rw-r--r--buildscripts/phing/classes/phing/filters/util/IniFileTokenReader.php96
-rw-r--r--buildscripts/phing/classes/phing/input/DefaultInputHandler.php82
-rw-r--r--buildscripts/phing/classes/phing/input/InputHandler.php45
-rw-r--r--buildscripts/phing/classes/phing/input/InputRequest.php107
-rw-r--r--buildscripts/phing/classes/phing/input/MultipleChoiceInputRequest.php58
-rw-r--r--buildscripts/phing/classes/phing/input/PropertyFileInputHandler.php129
-rw-r--r--buildscripts/phing/classes/phing/input/YesNoInputRequest.php47
-rw-r--r--buildscripts/phing/classes/phing/lib/Capsule.php266
-rw-r--r--buildscripts/phing/classes/phing/lib/Zip.php3588
-rw-r--r--buildscripts/phing/classes/phing/listener/AnsiColorLogger.php231
-rw-r--r--buildscripts/phing/classes/phing/listener/BuildLogger.php42
-rw-r--r--buildscripts/phing/classes/phing/listener/DefaultLogger.php233
-rw-r--r--buildscripts/phing/classes/phing/listener/NoBannerLogger.php61
-rw-r--r--buildscripts/phing/classes/phing/listener/PearLogger.php246
-rw-r--r--buildscripts/phing/classes/phing/listener/XmlLogger.php265
-rw-r--r--buildscripts/phing/classes/phing/listener/defaults.properties43
-rw-r--r--buildscripts/phing/classes/phing/mappers/FileNameMapper.php59
-rw-r--r--buildscripts/phing/classes/phing/mappers/FlattenMapper.php55
-rw-r--r--buildscripts/phing/classes/phing/mappers/GlobMapper.php113
-rw-r--r--buildscripts/phing/classes/phing/mappers/IdentityMapper.php54
-rw-r--r--buildscripts/phing/classes/phing/mappers/MergeMapper.php69
-rw-r--r--buildscripts/phing/classes/phing/mappers/RegexpMapper.php97
-rw-r--r--buildscripts/phing/classes/phing/parser/AbstractHandler.php98
-rw-r--r--buildscripts/phing/classes/phing/parser/AbstractSAXParser.php140
-rw-r--r--buildscripts/phing/classes/phing/parser/DataTypeHandler.php144
-rw-r--r--buildscripts/phing/classes/phing/parser/ExpatParseException.php31
-rw-r--r--buildscripts/phing/classes/phing/parser/ExpatParser.php140
-rw-r--r--buildscripts/phing/classes/phing/parser/Location.php72
-rw-r--r--buildscripts/phing/classes/phing/parser/NestedElementHandler.php186
-rw-r--r--buildscripts/phing/classes/phing/parser/ProjectConfigurator.php246
-rw-r--r--buildscripts/phing/classes/phing/parser/ProjectHandler.php146
-rw-r--r--buildscripts/phing/classes/phing/parser/RootHandler.php82
-rw-r--r--buildscripts/phing/classes/phing/parser/TargetHandler.php149
-rw-r--r--buildscripts/phing/classes/phing/parser/TaskHandler.php229
-rw-r--r--buildscripts/phing/classes/phing/system/io/BufferedReader.php170
-rw-r--r--buildscripts/phing/classes/phing/system/io/BufferedWriter.php72
-rw-r--r--buildscripts/phing/classes/phing/system/io/ConsoleReader.php84
-rw-r--r--buildscripts/phing/classes/phing/system/io/FileReader.php179
-rw-r--r--buildscripts/phing/classes/phing/system/io/FileSystem.php657
-rw-r--r--buildscripts/phing/classes/phing/system/io/FileWriter.php139
-rw-r--r--buildscripts/phing/classes/phing/system/io/FilterReader.php72
-rw-r--r--buildscripts/phing/classes/phing/system/io/IOException.php28
-rw-r--r--buildscripts/phing/classes/phing/system/io/PhingFile.php866
-rw-r--r--buildscripts/phing/classes/phing/system/io/Reader.php88
-rw-r--r--buildscripts/phing/classes/phing/system/io/StringReader.php73
-rw-r--r--buildscripts/phing/classes/phing/system/io/TokenReader.php51
-rw-r--r--buildscripts/phing/classes/phing/system/io/UnixFileSystem.php266
-rw-r--r--buildscripts/phing/classes/phing/system/io/Win32FileSystem.php477
-rw-r--r--buildscripts/phing/classes/phing/system/io/WinNTFileSystem.php35
-rw-r--r--buildscripts/phing/classes/phing/system/io/Writer.php48
-rw-r--r--buildscripts/phing/classes/phing/system/lang/Character.php49
-rw-r--r--buildscripts/phing/classes/phing/system/lang/EventObject.php52
-rw-r--r--buildscripts/phing/classes/phing/system/lang/FileNotFoundException.php27
-rw-r--r--buildscripts/phing/classes/phing/system/lang/NullPointerException.php27
-rw-r--r--buildscripts/phing/classes/phing/system/lang/SecurityException.php27
-rw-r--r--buildscripts/phing/classes/phing/system/util/Message.php9
-rw-r--r--buildscripts/phing/classes/phing/system/util/Properties.php270
-rw-r--r--buildscripts/phing/classes/phing/system/util/Register.php115
-rw-r--r--buildscripts/phing/classes/phing/system/util/Timer.php96
-rw-r--r--buildscripts/phing/classes/phing/tasks/defaults.properties69
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/CapsuleTask.php478
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/CreoleSQLExecTask.php556
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/CreoleTask.php242
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/MailTask.php77
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/PackageAsPathTask.php65
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/PearPackageTask.php421
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/PhpLintTask.php82
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/SmartyTask.php610
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/TarTask.php380
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/XmlLintTask.php116
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/ZendCodeAnalyzerTask.php163
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/ZipTask.php176
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMerger.php127
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMergerTask.php92
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTask.php406
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTransformer.php121
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageSetupTask.php163
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeComment.php44
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeEncoderTask.php336
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeLicenseTask.php144
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/pearpackage/Fileset.php231
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/phpdoc/PHPDocumentorTask.php157
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/phpunit2/BatchTest.php171
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/phpunit2/FormatterElement.php120
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2ReportTask.php162
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2ResultFormatter.php154
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2Task.php239
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2TestRunner.php107
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2Util.php114
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/phpunit2/PlainPHPUnit2ResultFormatter.php117
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/phpunit2/SummaryPHPUnit2ResultFormatter.php58
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/phpunit2/XMLPHPUnit2ResultFormatter.php117
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestCountResultFormatter.php52
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestFormatterElement.php62
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestPlainResultFormatter.php95
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestResultFormatter.php162
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestSummaryResultFormatter.php54
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestTask.php238
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/svn/SvnBaseTask.php180
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/svn/SvnExportTask.php68
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/svn/SvnLastRevisionTask.php75
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/AdhocTask.php88
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/AdhocTaskdefTask.php90
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/AdhocTypedefTask.php71
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/AppendTask.php240
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/AvailableTask.php132
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/ChmodTask.php177
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/ConditionTask.php74
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/CopyTask.php401
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/CvsPassTask.php173
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/CvsTask.php540
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/DeleteTask.php277
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/EchoTask.php107
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/ExecTask.php248
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/ExitTask.php118
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/ForeachTask.php138
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/IfTask.php224
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/IncludePathTask.php115
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/InputTask.php146
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/MatchingTask.php361
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/MkdirTask.php64
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/MoveTask.php197
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/PhingCallTask.php139
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/PhingTask.php596
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/PhpEvalTask.php169
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/PropertyPromptTask.php201
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/PropertyTask.php438
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/ReflexiveTask.php155
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/ResolvePathTask.php122
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/SequentialTask.php57
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/TaskdefTask.php127
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/TouchTask.php170
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/TstampTask.php168
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/TypedefTask.php125
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/UpToDateTask.php217
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/WarnTask.php35
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/XsltTask.php81
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/condition/AndCondition.php46
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/condition/Condition.php39
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/condition/ConditionBase.php195
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/condition/ContainsCondition.php76
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/condition/EqualsCondition.php78
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/condition/IsFalseCondition.php60
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/condition/IsSetCondition.php53
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/condition/IsTrueCondition.php59
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/condition/NotCondition.php48
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/condition/OrCondition.php46
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/condition/OsCondition.php63
-rw-r--r--buildscripts/phing/classes/phing/tasks/system/condition/ReferenceExistsCondition.php52
-rw-r--r--buildscripts/phing/classes/phing/types/AbstractFileSet.php570
-rw-r--r--buildscripts/phing/classes/phing/types/Commandline.php467
-rw-r--r--buildscripts/phing/classes/phing/types/DataType.php182
-rw-r--r--buildscripts/phing/classes/phing/types/Description.php53
-rw-r--r--buildscripts/phing/classes/phing/types/DirSet.php49
-rw-r--r--buildscripts/phing/classes/phing/types/FileList.php223
-rw-r--r--buildscripts/phing/classes/phing/types/FileSet.php56
-rw-r--r--buildscripts/phing/classes/phing/types/FilterChain.php164
-rw-r--r--buildscripts/phing/classes/phing/types/Mapper.php207
-rw-r--r--buildscripts/phing/classes/phing/types/Parameter.php99
-rw-r--r--buildscripts/phing/classes/phing/types/Parameterizable.php32
-rw-r--r--buildscripts/phing/classes/phing/types/Path.php456
-rw-r--r--buildscripts/phing/classes/phing/types/PatternSet.php449
-rw-r--r--buildscripts/phing/classes/phing/types/PhingFilterReader.php136
-rw-r--r--buildscripts/phing/classes/phing/types/Reference.php56
-rw-r--r--buildscripts/phing/classes/phing/types/RegularExpression.php105
-rw-r--r--buildscripts/phing/classes/phing/types/TokenReader.php66
-rw-r--r--buildscripts/phing/classes/phing/types/TokenSource.php157
-rw-r--r--buildscripts/phing/classes/phing/types/defaults.properties13
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/AndSelector.php67
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/BaseExtendSelector.php62
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/BaseSelector.php84
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/BaseSelectorContainer.php270
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/ContainsRegexpSelector.php164
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/ContainsSelector.php151
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/DateSelector.php214
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/DependSelector.php151
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/DepthSelector.php158
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/ExtendFileSelector.php43
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/ExtendSelector.php127
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/FileSelector.php47
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/FilenameSelector.php157
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/MajoritySelector.php92
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/NoneSelector.php71
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/NotSelector.php59
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/OrSelector.php72
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/PresentSelector.php154
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/SelectSelector.php124
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/SelectorContainer.php141
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/SelectorScanner.php55
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/SelectorUtils.php440
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/SizeSelector.php228
-rw-r--r--buildscripts/phing/classes/phing/types/selectors/TypeSelector.php113
-rw-r--r--buildscripts/phing/classes/phing/util/DirectoryScanner.php710
-rw-r--r--buildscripts/phing/classes/phing/util/ExtendedFileStream.php133
-rw-r--r--buildscripts/phing/classes/phing/util/FileUtils.php294
-rw-r--r--buildscripts/phing/classes/phing/util/LogWriter.php96
-rw-r--r--buildscripts/phing/classes/phing/util/PathTokenizer.php245
-rw-r--r--buildscripts/phing/classes/phing/util/SourceFileScanner.php159
-rw-r--r--buildscripts/phing/classes/phing/util/StringHelper.php209
-rw-r--r--buildscripts/phing/classes/phing/util/regexp/PregEngine.php105
-rw-r--r--buildscripts/phing/classes/phing/util/regexp/Regexp.php168
-rw-r--r--buildscripts/phing/classes/phing/util/regexp/RegexpEngine.php74
-rw-r--r--buildscripts/phing/etc/VERSION.TXT1
-rw-r--r--buildscripts/phing/etc/coverage-frames.xsl669
-rw-r--r--buildscripts/phing/etc/log.xsl216
-rw-r--r--buildscripts/phing/etc/phpunit2-frames.xsl677
-rw-r--r--buildscripts/phing/etc/phpunit2-noframes.xsl436
-rw-r--r--buildscripts/phing/etc/str.replace.function.xsl105
-rw-r--r--buildscripts/phing/pear/BuildPhingPEARPackageTask.php270
-rw-r--r--buildscripts/phing/pear/build.xml156
-rw-r--r--buildscripts/phing/tasks/ManualIndexTask.php38
-rw-r--r--buildscripts/phing/tasks/PradoDocTask.php137
-rw-r--r--buildscripts/phing/tasks/PradoPearTask.php133
-rw-r--r--buildscripts/phing/tasks/PradoTestTask.php18
-rw-r--r--buildscripts/phing/tasks/PradoVersionTask.php56
-rw-r--r--buildscripts/phing/tasks/QuickstartIndexTask.php32
-rw-r--r--buildscripts/texbuilder/quickstart.tex4
565 files changed, 117130 insertions, 3 deletions
diff --git a/buildscripts/Benchmark/Iterate.php b/buildscripts/Benchmark/Iterate.php
new file mode 100644
index 00000000..acf1ec08
--- /dev/null
+++ b/buildscripts/Benchmark/Iterate.php
@@ -0,0 +1,167 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | PEAR :: Benchmark |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2001-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>. |
+// +------------------------------------------------------------------------+
+// | This source file is subject to the New BSD license, That is bundled |
+// | with this package in the file LICENSE, and is available through |
+// | the world-wide-web at |
+// | http://www.opensource.org/licenses/bsd-license.php |
+// | If you did not receive a copy of the new BSDlicense and are unable |
+// | to obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+// $Id: Iterate.php,v 1.12 2006/02/17 16:29:44 toggg Exp $
+//
+
+require_once 'Benchmark/Timer.php';
+
+/**
+ * Provides timing and profiling information.
+ *
+ * Example 1
+ *
+ * <code>
+ * <?php
+ * require_once 'Benchmark/Iterate.php';
+ *
+ * $benchmark = new Benchmark_Iterate;
+ *
+ * function foo($string) {
+ * print $string . '<br>';
+ * }
+ *
+ * $benchmark->run(100, 'foo', 'test');
+ * $result = $benchmark->get();
+ * ?>
+ * </code>
+ *
+ * Example 2
+ *
+ * <code>
+ * <?php
+ * require_once 'Benchmark/Iterate.php';
+ *
+ * $benchmark = new Benchmark_Iterate;
+ *
+ * class MyClass {
+ * function foo($string) {
+ * print $string . '<br>';
+ * }
+ * }
+ *
+ * $benchmark->run(100, 'myclass::foo', 'test');
+ * $result = $benchmark->get();
+ * ?>
+ * </code>
+ *
+ * Example 3
+ *
+ * <code>
+ * <?php
+ * require_once 'Benchmark/Iterate.php';
+ *
+ * $benchmark = new Benchmark_Iterate;
+ *
+ * class MyClass {
+ * function foo($string) {
+ * print $string . '<br>';
+ * }
+ * }
+ *
+ * $o = new MyClass();
+ *
+ * $benchmark->run(100, 'o->foo', 'test');
+ * $result = $benchmark->get();
+ * ?>
+ * </code>
+ *
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright Copyright &copy; 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.php.net/license/3_0.txt The PHP License, Version 3.0
+ * @category Benchmarking
+ * @package Benchmark
+ */
+class Benchmark_Iterate extends Benchmark_Timer {
+ /**
+ * Benchmarks a function or method.
+ *
+ * @access public
+ */
+ function run() {
+ $arguments = func_get_args();
+ $iterations = array_shift($arguments);
+ $function_name = array_shift($arguments);
+
+ if (strstr($function_name, '::')) {
+ $function_name = explode('::', $function_name);
+ $objectmethod = $function_name[1];
+ }
+
+ if (strstr($function_name, '->')) {
+ $function_name = explode('->', $function_name);
+ $objectname = $function_name[0];
+
+ $object = $GLOBALS[$objectname];
+ $objectmethod = $function_name[1];
+
+ for ($i = 1; $i <= $iterations; $i++) {
+ $this->setMarker('start_' . $i);
+ call_user_func_array(array($object, $function_name[1]), $arguments);
+ $this->setMarker('end_' . $i);
+ }
+
+ return(0);
+ }
+
+ for ($i = 1; $i <= $iterations; $i++) {
+ $this->setMarker('start_' . $i);
+ call_user_func_array($function_name, $arguments);
+ $this->setMarker('end_' . $i);
+ }
+ }
+
+ /**
+ * Returns benchmark result.
+ *
+ * $result[x ] = execution time of iteration x
+ * $result['mean' ] = mean execution time
+ * $result['iterations'] = number of iterations
+ *
+ * @return array
+ * @access public
+ */
+ function get($simple_output = false) {
+ $result = array();
+ $total = 0;
+
+ $iterations = count($this->markers)/2;
+
+ for ($i = 1; $i <= $iterations; $i++) {
+ $time = $this->timeElapsed('start_'.$i , 'end_'.$i);
+
+ if (extension_loaded('bcmath')) {
+ $total = bcadd($total, $time, 6);
+ } else {
+ $total = $total + $time;
+ }
+
+ if (!$simple_output) {
+ $result[$i] = $time;
+ }
+ }
+
+ if (extension_loaded('bcmath')) {
+ $result['mean'] = bcdiv($total, $iterations, 6);
+ } else {
+ $result['mean'] = $total / $iterations;
+ }
+
+ $result['iterations'] = $iterations;
+
+ return $result;
+ }
+}
diff --git a/buildscripts/Benchmark/LICENSE b/buildscripts/Benchmark/LICENSE
new file mode 100644
index 00000000..db25e880
--- /dev/null
+++ b/buildscripts/Benchmark/LICENSE
@@ -0,0 +1,22 @@
+Redistribution and use in source and binary forms, with or without modification
+, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, th
+ is list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation and/
+ or other materials provided with the distribution.
+
+3. The name of the author may not be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WA
+RRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABIL
+ITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR C
+ONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOW
+EVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILI
+TY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE U
+SE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/buildscripts/Benchmark/Profiler.php b/buildscripts/Benchmark/Profiler.php
new file mode 100644
index 00000000..e9108a84
--- /dev/null
+++ b/buildscripts/Benchmark/Profiler.php
@@ -0,0 +1,447 @@
+<?php
+//
+// +----------------------------------------------------------------------+
+// | PEAR :: Benchmark |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 2002-2006 Matthias Englert <Matthias.Englert@gmx.de>. |
+// +----------------------------------------------------------------------+
+// | This source file is subject to the New BSD license, That is bundled |
+// | with this package in the file LICENSE, and is available through |
+// | the world-wide-web at |
+// | http://www.opensource.org/licenses/bsd-license.php |
+// | If you did not receive a copy of the new BSDlicense and are unable |
+// | to obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +----------------------------------------------------------------------+
+//
+// $Id: Profiler.php,v 1.19 2006/03/01 19:26:09 anant Exp $
+//
+
+require_once 'PEAR.php';
+
+/**
+ * Provides timing and profiling information.
+ *
+ * Example 1: Automatic profiling start, stop, and output.
+ *
+ * <code>
+ * <?php
+ * require_once 'Benchmark/Profiler.php';
+ *
+ * $profiler = new Benchmark_Profiler(TRUE);
+ *
+ * function myFunction() {
+ * global $profiler;
+ * $profiler->enterSection('myFunction');
+ * //do something
+ * $profiler->leaveSection('myFunction');
+ * return;
+ * }
+ *
+ * //do something
+ * myFunction();
+ * //do more
+ * ?>
+ * </code>
+ *
+ * Example 2: Manual profiling start, stop, and output.
+ *
+ * <code>
+ * <?php
+ * require_once 'Benchmark/Profiler.php';
+ *
+ * $profiler = new Benchmark_Profiler();
+ *
+ * function myFunction() {
+ * global $profiler;
+ * $profiler->enterSection('myFunction');
+ * //do something
+ * $profiler->leaveSection('myFunction');
+ * return;
+ * }
+ *
+ * $profiler->start();
+ * //do something
+ * myFunction();
+ * //do more
+ * $profiler->stop();
+ * $profiler->display();
+ * ?>
+ * </code>
+ *
+ * @author Matthias Englert <Matthias.Englert@gmx.de>
+ * @copyright Copyright &copy; 2002-2005 Matthias Englert <Matthias.Englert@gmx.de>
+ * @license http://www.php.net/license/3_0.txt The PHP License, Version 3.0
+ * @category Benchmarking
+ * @package Benchmark
+ * @since 1.2.0
+ */
+class Benchmark_Profiler extends PEAR {
+ /**
+ * Contains the total ex. time of each section
+ *
+ * @var array
+ * @access private
+ */
+ var $_sections = array();
+
+ /**
+ * Calling stack
+ *
+ * @var array
+ * @access private
+ */
+ var $_stack = array();
+
+ /**
+ * Notes how often a section was entered
+ *
+ * @var array
+ * @access private
+ */
+ var $_numberOfCalls = array();
+
+ /**
+ * Notes for each section how much time is spend in sub-sections
+ *
+ * @var array
+ * @access private
+ */
+ var $_subSectionsTime = array();
+
+ /**
+ * Notes for each section how often it calls which section
+ *
+ * @var array
+ * @access private
+ */
+ var $_calls = array();
+
+ /**
+ * Notes for each section how often it was called by which section
+ *
+ * @var array
+ * @access private
+ */
+ var $_callers = array();
+
+ /**
+ * Auto-starts and stops profiler
+ *
+ * @var boolean
+ * @access private
+ */
+ var $_auto = FALSE;
+
+ /**
+ * Max marker name length for non-html output
+ *
+ * @var integer
+ * @access private
+ */
+ var $_maxStringLength = 0;
+
+ /**
+ * Constructor, starts profiling recording
+ *
+ * @access public
+ */
+ function Benchmark_Profiler($auto = FALSE) {
+ $this->_auto = $auto;
+
+ if ($this->_auto) {
+ $this->start();
+ }
+
+ $this->PEAR();
+ }
+
+ /**
+ * Destructor, stops profiling recording
+ *
+ * @access private
+ */
+ function _Benchmark_Profiler() {
+ if (isset($this->_auto) && $this->_auto) {
+ $this->stop();
+ $this->display();
+ }
+ }
+
+ /**
+ * Returns profiling informations for a given section.
+ *
+ * @param string $section
+ * @return array
+ * @access public
+ */
+ function getSectionInformations($section = 'Global') {
+ if (isset($this->_sections[$section])) {
+ $calls = array();
+
+ if (isset($this->_calls[$section])) {
+ $calls = $this->_calls[$section];
+ }
+
+ $callers = array();
+
+ if (isset($this->_callers[$section])) {
+ $callers = $this->_callers[$section];
+ }
+
+ $informations = array();
+
+ $informations['time'] = $this->_sections[$section];
+ if (isset($this->_sections['Global'])) {
+ $informations['percentage'] = number_format(100 * $this->_sections[$section] / $this->_sections['Global'], 2, '.', '');
+ } else {
+ $informations['percentage'] = 'N/A';
+ }
+ $informations['calls'] = $calls;
+ $informations['num_calls'] = $this->_numberOfCalls[$section];
+ $informations['callers'] = $callers;
+
+ if (isset($this->_subSectionsTime[$section])) {
+ $informations['netto_time'] = $this->_sections[$section] - $this->_subSectionsTime[$section];
+ } else {
+ $informations['netto_time'] = $this->_sections[$section];
+ }
+
+ return $informations;
+ } else {
+ $this->raiseError("The section '$section' does not exists.\n", NULL, PEAR_ERROR_TRIGGER, E_USER_WARNING);
+ }
+ }
+
+ /**
+ * Returns profiling informations for all sections.
+ *
+ * @return array
+ * @access public
+ */
+ function getAllSectionsInformations() {
+ $informations = array();
+
+ foreach($this->_sections as $section => $time) {
+ $informations[$section] = $this->getSectionInformations($section);
+ }
+
+ return $informations;
+ }
+
+ /**
+ * Returns formatted profiling information.
+ *
+ * @param string output format (auto, plain or html), default auto
+ * @see display()
+ * @access private
+ */
+ function _getOutput($format) {
+
+ /* Quickly find out the maximun length: Ineffecient, but will do for now! */
+ $informations = $this->getAllSectionsInformations();
+ $names = array_keys($informations);
+
+ $maxLength = 0;
+ foreach ($names as $name)
+ {
+ if ($maxLength < strlen($name)) {
+ $maxLength = strlen($name);
+ }
+ }
+ $this->_maxStringLength = $maxLength;
+
+ if ($format == 'auto') {
+ if (function_exists('version_compare') &&
+ version_compare(phpversion(), '4.1', 'ge')) {
+ $format = isset($_SERVER['SERVER_PROTOCOL']) ? 'html' : 'plain';
+ } else {
+ global $HTTP_SERVER_VARS;
+ $format = isset($HTTP_SERVER_VARS['SERVER_PROTOCOL']) ? 'html' : 'plain';
+ }
+ }
+
+ if ($format == 'html') {
+ $out = '<table style="border: 1px solid #000000; ">'."\n";
+ $out .=
+ '<tr><td>&nbsp;</td><td align="center"><b>total ex. time</b></td>'.
+ '<td align="center"><b>netto ex. time</b></td>'.
+ '<td align="center"><b>#calls</b></td><td align="center"><b>%</b></td>'.
+ '<td align="center"><b>calls</b></td><td align="center"><b>callers</b></td></tr>'.
+ "\n";
+ } else {
+ $dashes = $out = str_pad("\n", ($this->_maxStringLength + 75), '-', STR_PAD_LEFT);
+ $out .= str_pad('Section', $this->_maxStringLength + 10);
+ $out .= str_pad("Total Ex Time", 22);
+ $out .= str_pad("Netto Ex Time", 22);
+ $out .= str_pad("#Calls", 10);
+ $out .= "Percentage\n";
+ $out .= $dashes;
+ }
+
+ foreach($informations as $name => $values) {
+ $percentage = $values['percentage'];
+ $calls_str = "";
+
+ foreach($values['calls'] as $key => $val) {
+ if ($calls_str) {
+ $calls_str .= ", ";
+ }
+
+ $calls_str .= "$key ($val)";
+ }
+
+ $callers_str = "";
+
+ foreach($values['callers'] as $key => $val) {
+ if ($callers_str) {
+ $callers_str .= ", ";
+ }
+
+ $callers_str .= "$key ($val)";
+ }
+
+ if ($format == 'html') {
+ $out .= "<tr><td><b>$name</b></td><td>{$values['time']}</td><td>{$values['netto_time']}</td><td>{$values['num_calls']}</td>";
+ if (is_numeric($values['percentage'])) {
+ $out .= "<td align=\"right\">{$values['percentage']}%</td>\n";
+ } else {
+ $out .= "<td align=\"right\">{$values['percentage']}</td>\n";
+ }
+ $out .= "<td>$calls_str</td><td>$callers_str</td></tr>";
+ } else {
+ $out .= str_pad($name, $this->_maxStringLength + 10);
+ $out .= str_pad($values['time'], 22);
+ $out .= str_pad($values['netto_time'], 22);
+ $out .= str_pad($values['num_calls'], 10);
+ if (is_numeric($values['percentage'])) {
+ $out .= str_pad($values['percentage']."%\n", 8, ' ', STR_PAD_LEFT);
+ } else {
+ $out .= str_pad($values['percentage']."\n", 8, ' ', STR_PAD_LEFT);
+ }
+ }
+ }
+
+ if ($format == 'html') {
+ return $out . '</table>';
+ } else {
+ return $out;
+ }
+ }
+
+ /**
+ * Returns formatted profiling information.
+ *
+ * @param string output format (auto, plain or html), default auto
+ * @access public
+ */
+ function display($format = 'auto') {
+ echo $this->_getOutput($format);
+ }
+
+ /**
+ * Enters "Global" section.
+ *
+ * @see enterSection(), stop()
+ * @access public
+ */
+ function start() {
+ $this->enterSection('Global');
+ }
+
+ /**
+ * Leaves "Global" section.
+ *
+ * @see leaveSection(), start()
+ * @access public
+ */
+ function stop() {
+ $this->leaveSection('Global');
+ }
+
+ /**
+ * Enters code section.
+ *
+ * @param string name of the code section
+ * @see start(), leaveSection()
+ * @access public
+ */
+ function enterSection($name) {
+ if (count($this->_stack)) {
+ if (isset($this->_callers[$name][$this->_stack[count($this->_stack) - 1]["name"]])) {
+ $this->_callers[$name][$this->_stack[count($this->_stack) - 1]["name"]]++;
+ } else {
+ $this->_callers[$name][$this->_stack[count($this->_stack) - 1]["name"]] = 1;
+ }
+
+ if (isset($this->_calls[$this->_stack[count($this->_stack) - 1]["name"]][$name])) {
+ $this->_calls[$this->_stack[count($this->_stack) - 1]["name"]][$name]++;
+ } else {
+ $this->_calls[$this->_stack[count($this->_stack) - 1]["name"]][$name] = 1;
+ }
+ } else {
+ if ($name != 'Global') {
+ $this->raiseError("tried to enter section ".$name." but profiling was not started\n", NULL, PEAR_ERROR_DIE);
+ }
+ }
+
+ if (isset($this->_numberOfCalls[$name])) {
+ $this->_numberOfCalls[$name]++;
+ } else {
+ $this->_numberOfCalls[$name] = 1;
+ }
+
+ array_push($this->_stack, array("name" => $name, "time" => $this->_getMicrotime()));
+ }
+
+ /**
+ * Leaves code section.
+ *
+ * @param string name of the marker to be set
+ * @see stop(), enterSection()
+ * @access public
+ */
+ function leaveSection($name) {
+ $microtime = $this->_getMicrotime();
+
+ if (!count($this->_stack)) {
+ $this->raiseError("tried to leave section ".$name." but profiling was not started\n", NULL, PEAR_ERROR_DIE);
+ }
+
+ $x = array_pop($this->_stack);
+
+ if ($x["name"] != $name) {
+ $this->raiseError("reached end of section $name but expecting end of " . $x["name"]."\n", NULL, PEAR_ERROR_DIE);
+ }
+
+ if (isset($this->_sections[$name])) {
+ $this->_sections[$name] += $microtime - $x["time"];
+ } else {
+ $this->_sections[$name] = $microtime - $x["time"];
+ }
+
+ $parent = array_pop($this->_stack);
+
+ if (isset($parent)) {
+ if (isset($this->_subSectionsTime[$parent['name']])) {
+ $this->_subSectionsTime[$parent['name']] += $microtime - $x['time'];
+ } else {
+ $this->_subSectionsTime[$parent['name']] = $microtime - $x['time'];
+ }
+
+ array_push($this->_stack, $parent);
+ }
+ }
+
+ /**
+ * Wrapper for microtime().
+ *
+ * @return float
+ * @access private
+ * @since 1.3.0
+ */
+ function _getMicrotime() {
+ $microtime = explode(' ', microtime());
+ return $microtime[1] . substr($microtime[0], 1);
+ }
+}
diff --git a/buildscripts/Benchmark/Timer.php b/buildscripts/Benchmark/Timer.php
new file mode 100644
index 00000000..d713e6b2
--- /dev/null
+++ b/buildscripts/Benchmark/Timer.php
@@ -0,0 +1,319 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | PEAR :: Benchmark |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2001-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>. |
+// +------------------------------------------------------------------------+
+// | This source file is subject to the New BSD license, That is bundled |
+// | with this package in the file LICENSE, and is available through |
+// | the world-wide-web at |
+// | http://www.opensource.org/licenses/bsd-license.php |
+// | If you did not receive a copy of the new BSDlicense and are unable |
+// | to obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+// $Id: Timer.php,v 1.16 2006/03/01 13:41:39 matthias Exp $
+//
+
+require_once 'PEAR.php';
+
+/**
+ * Provides timing and profiling information.
+ *
+ * Example 1: Automatic profiling start, stop, and output.
+ *
+ * <code>
+ * <?php
+ * require_once 'Benchmark/Timer.php';
+ *
+ * $timer = new Benchmark_Timer(TRUE);
+ * $timer->setMarker('Marker 1');
+ * ?>
+ * </code>
+ *
+ * Example 2: Manual profiling start, stop, and output.
+ *
+ * <code>
+ * <?php
+ * require_once 'Benchmark/Timer.php';
+ *
+ * $timer = new Benchmark_Timer();
+ * $timer->start();
+ * $timer->setMarker('Marker 1');
+ * $timer->stop();
+ *
+ * $timer->display(); // to output html formated
+ * // AND/OR :
+ * $profiling = $timer->getProfiling(); // get the profiler info as an associative array
+ * ?>
+ * </code>
+ *
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @author Ludovico Magnocavallo <ludo@sumatrasolutions.com>
+ * @copyright Copyright &copy; 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.php.net/license/3_0.txt The PHP License, Version 3.0
+ * @category Benchmarking
+ * @package Benchmark
+ */
+class Benchmark_Timer extends PEAR {
+ /**
+ * Contains the markers.
+ *
+ * @var array
+ * @access private
+ */
+ var $markers = array();
+
+ /**
+ * Auto-start and stop timer.
+ *
+ * @var boolean
+ * @access private
+ */
+ var $auto = FALSE;
+
+ /**
+ * Max marker name length for non-html output.
+ *
+ * @var integer
+ * @access private
+ */
+ var $maxStringLength = 0;
+
+ /**
+ * Constructor.
+ *
+ * @param boolean $auto
+ * @access public
+ */
+ function Benchmark_Timer($auto = FALSE) {
+ $this->auto = $auto;
+
+ if ($this->auto) {
+ $this->start();
+ }
+
+ $this->PEAR();
+ }
+
+ /**
+ * Destructor.
+ *
+ * @access private
+ */
+ function _Benchmark_Timer() {
+ if ($this->auto) {
+ $this->stop();
+ $this->display();
+ }
+ }
+
+ /**
+ * Set "Start" marker.
+ *
+ * @see setMarker(), stop()
+ * @access public
+ */
+ function start() {
+ $this->setMarker('Start');
+ }
+
+ /**
+ * Set "Stop" marker.
+ *
+ * @see setMarker(), start()
+ * @access public
+ */
+ function stop() {
+ $this->setMarker('Stop');
+ }
+
+ /**
+ * Set marker.
+ *
+ * @param string $name Name of the marker to be set.
+ * @see start(), stop()
+ * @access public
+ */
+ function setMarker($name) {
+ $this->markers[$name] = $this->_getMicrotime();
+ }
+
+ /**
+ * Returns the time elapsed betweens two markers.
+ *
+ * @param string $start start marker, defaults to "Start"
+ * @param string $end end marker, defaults to "Stop"
+ * @return double $time_elapsed time elapsed between $start and $end
+ * @access public
+ */
+ function timeElapsed($start = 'Start', $end = 'Stop') {
+ if ($end == 'Stop' && !isset($this->markers['Stop'])) {
+ $this->markers['Stop'] = $this->_getMicrotime();
+ }
+
+ if (extension_loaded('bcmath')) {
+ return bcsub($this->markers[$end], $this->markers[$start], 6);
+ } else {
+ return $this->markers[$end] - $this->markers[$start];
+ }
+ }
+
+ /**
+ * Returns profiling information.
+ *
+ * $profiling[x]['name'] = name of marker x
+ * $profiling[x]['time'] = time index of marker x
+ * $profiling[x]['diff'] = execution time from marker x-1 to this marker x
+ * $profiling[x]['total'] = total execution time up to marker x
+ *
+ * @return array
+ * @access public
+ */
+ function getProfiling() {
+ $i = $total = 0;
+ $result = array();
+ $temp = reset($this->markers);
+ $this->maxStringLength = 0;
+
+ foreach ($this->markers as $marker => $time) {
+ if (extension_loaded('bcmath')) {
+ $diff = bcsub($time, $temp, 6);
+ $total = bcadd($total, $diff, 6);
+ } else {
+ $diff = $time - $temp;
+ $total = $total + $diff;
+ }
+
+ $result[$i]['name'] = $marker;
+ $result[$i]['time'] = $time;
+ $result[$i]['diff'] = $diff;
+ $result[$i]['total'] = $total;
+
+ $this->maxStringLength = (strlen($marker) > $this->maxStringLength ? strlen($marker) + 1 : $this->maxStringLength);
+
+ $temp = $time;
+ $i++;
+ }
+
+ $result[0]['diff'] = '-';
+ $result[0]['total'] = '-';
+ $this->maxStringLength = (strlen('total') > $this->maxStringLength ? strlen('total') : $this->maxStringLength);
+ $this->maxStringLength += 2;
+
+ return $result;
+ }
+
+ /**
+ * Return formatted profiling information.
+ *
+ * @param boolean $showTotal Optionnaly includes total in output, default no
+ * @param string $format output format (auto, plain or html), default auto
+ * @return string
+ * @see getProfiling()
+ * @access public
+ */
+ function getOutput($showTotal = FALSE, $format = 'auto') {
+ if ($format == 'auto') {
+ if (function_exists('version_compare') &&
+ version_compare(phpversion(), '4.1', 'ge'))
+ {
+ $format = isset($_SERVER['SERVER_PROTOCOL']) ? 'html' : 'plain';
+ } else {
+ global $HTTP_SERVER_VARS;
+ $format = isset($HTTP_SERVER_VARS['SERVER_PROTOCOL']) ? 'html' : 'plain';
+ }
+ }
+
+ $total = $this->TimeElapsed();
+ $result = $this->getProfiling();
+ $dashes = '';
+
+ if ($format == 'html') {
+ $out = '<table border="1">'."\n";
+ $out .= '<tr><td>&nbsp;</td><td align="center"><b>time index</b></td><td align="center"><b>ex time</b></td><td align="center"><b>%</b></td>'.
+ ($showTotal ?
+ '<td align="center"><b>elapsed</b></td><td align="center"><b>%</b></td>'
+ : '')."</tr>\n";
+ } else {
+ $dashes = $out = str_pad("\n",
+ $this->maxStringLength + ($showTotal ? 70 : 45), '-', STR_PAD_LEFT);
+ $out .= str_pad('marker', $this->maxStringLength) .
+ str_pad("time index", 22) .
+ str_pad("ex time", 16) .
+ str_pad("perct ", 8) .
+ ($showTotal ? ' '.str_pad("elapsed", 16)."perct" : '')."\n" .
+ $dashes;
+ }
+
+ foreach ($result as $k => $v) {
+ $perc = (($v['diff'] * 100) / $total);
+ $tperc = (($v['total'] * 100) / $total);
+
+ if ($format == 'html') {
+ $out .= "<tr><td><b>" . $v['name'] .
+ "</b></td><td>" . $v['time'] .
+ "</td><td>" . $v['diff'] .
+ "</td><td align=\"right\">" . number_format($perc, 2, '.', '') .
+ "%</td>".
+ ($showTotal ?
+ "<td>" . $v['total'] .
+ "</td><td align=\"right\">" .
+ number_format($tperc, 2, '.', '') .
+ "%</td>" : '').
+ "</tr>\n";
+ } else {
+ $out .= str_pad($v['name'], $this->maxStringLength, ' ') .
+ str_pad($v['time'], 22) .
+ str_pad($v['diff'], 14) .
+ str_pad(number_format($perc, 2, '.', '')."%",8, ' ', STR_PAD_LEFT) .
+ ($showTotal ? ' '.
+ str_pad($v['total'], 14) .
+ str_pad(number_format($tperc, 2, '.', '')."%",
+ 8, ' ', STR_PAD_LEFT) : '').
+ "\n";
+ }
+
+ $out .= $dashes;
+ }
+
+ if ($format == 'html') {
+ $out .= "<tr style='background: silver;'><td><b>total</b></td><td>-</td><td>${total}</td><td>100.00%</td>".($showTotal ? "<td>-</td><td>-</td>" : "")."</tr>\n";
+ $out .= "</table>\n";
+ } else {
+ $out .= str_pad('total', $this->maxStringLength);
+ $out .= str_pad('-', 22);
+ $out .= str_pad($total, 15);
+ $out .= "100.00%\n";
+ $out .= $dashes;
+ }
+
+ return $out;
+ }
+
+ /**
+ * Prints the information returned by getOutput().
+ *
+ * @param boolean $showTotal Optionnaly includes total in output, default no
+ * @param string $format output format (auto, plain or html), default auto
+ * @see getOutput()
+ * @access public
+ */
+ function display($showTotal = FALSE, $format = 'auto') {
+ print $this->getOutput($showTotal, $format);
+ }
+
+ /**
+ * Wrapper for microtime().
+ *
+ * @return float
+ * @access private
+ * @since 1.3.0
+ */
+ function _getMicrotime() {
+ $microtime = explode(' ', microtime());
+ return $microtime[1] . substr($microtime[0], 1);
+ }
+}
diff --git a/buildscripts/Benchmark/doc/timer_example.php b/buildscripts/Benchmark/doc/timer_example.php
new file mode 100644
index 00000000..93dd05c6
--- /dev/null
+++ b/buildscripts/Benchmark/doc/timer_example.php
@@ -0,0 +1,18 @@
+<?php
+require '../Timer.php';
+
+function wait($amount) {
+ for ($i=0; $i < $amount; $i++) {
+ for ($i=0; $i < 100; $i++);
+ }
+}
+// Pass the param "true" to constructor to automatically display the results
+$timer = new Benchmark_Timer();
+$timer->start();
+wait(10);
+$timer->setMarker('Mark1');
+echo "Elapsed time between Start and Mark1: " .
+ $timer->timeElapsed('Start', 'Mark1') . "\n";
+wait(50);
+$timer->stop();
+$timer->display();
diff --git a/buildscripts/PHPUnit2/Extensions/ExceptionTestCase.php b/buildscripts/PHPUnit2/Extensions/ExceptionTestCase.php
new file mode 100644
index 00000000..80afd1b5
--- /dev/null
+++ b/buildscripts/PHPUnit2/Extensions/ExceptionTestCase.php
@@ -0,0 +1,122 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: ExceptionTestCase.php,v 1.15.2.6 2006/02/20 07:42:59 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+require_once 'PHPUnit2/Framework/TestCase.php';
+
+/**
+ * A TestCase that expects a specified Exception to be thrown.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.0.0
+ */
+class PHPUnit2_Extensions_ExceptionTestCase extends PHPUnit2_Framework_TestCase {
+ /**
+ * The name of the expected Exception.
+ *
+ * @var mixed
+ * @access private
+ */
+ private $expectedException = NULL;
+
+ /**
+ * @return string
+ * @access public
+ * @since Method available since Release 2.2.0
+ */
+ public function getExpectedException() {
+ return $this->expectedException;
+ }
+
+ /**
+ * @param mixed $exceptionName
+ * @access public
+ * @since Method available since Release 2.2.0
+ */
+ public function setExpectedException($exceptionName) {
+ if ((is_string($exceptionName) && class_exists($exceptionName)) || $exceptionName === NULL) {
+ $this->expectedException = $exceptionName;
+ }
+ }
+
+ /**
+ * @access protected
+ */
+ protected function runTest() {
+ try {
+ parent::runTest();
+ }
+
+ catch (Exception $e) {
+ if ($this->expectedException !== NULL &&
+ $e instanceof $this->expectedException) {
+ return;
+ } else {
+ throw $e;
+ }
+ }
+
+ if ($this->expectedException !== NULL) {
+ $this->fail('Expected exception ' . $this->expectedException);
+ }
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Extensions/PerformanceTestCase.php b/buildscripts/PHPUnit2/Extensions/PerformanceTestCase.php
new file mode 100644
index 00000000..38b249a6
--- /dev/null
+++ b/buildscripts/PHPUnit2/Extensions/PerformanceTestCase.php
@@ -0,0 +1,128 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: PerformanceTestCase.php,v 1.15.2.5 2005/12/17 16:04:56 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.1.0
+ */
+
+require_once 'PHPUnit2/Framework/TestCase.php';
+
+require_once 'Benchmark/Timer.php';
+
+/**
+ * A TestCase that expects a TestCase to be executed
+ * meeting a given time limit.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.1.0
+ */
+class PHPUnit2_Extensions_PerformanceTestCase extends PHPUnit2_Framework_TestCase {
+ /**
+ * @var integer
+ * @access private
+ */
+ private $maxRunningTime = 0;
+
+ /**
+ * @access protected
+ */
+ protected function runTest() {
+ $timer = new Benchmark_Timer;
+
+ $timer->start();
+ parent::runTest();
+ $timer->stop();
+
+ if ($this->maxRunningTime != 0 &&
+ $timer->timeElapsed() > $this->maxRunningTime) {
+ $this->fail(
+ sprintf(
+ 'expected running time: <= %s but was: %s',
+
+ $this->maxRunningTime,
+ $timer->timeElapsed()
+ )
+ );
+ }
+ }
+
+ /**
+ * @param integer $maxRunningTime
+ * @throws Exception
+ * @access public
+ * @since Method available since Release 2.3.0
+ */
+ public function setMaxRunningTime($maxRunningTime) {
+ if (is_integer($maxRunningTime) &&
+ $maxRunningTime >= 0) {
+ $this->maxRunningTime = $maxRunningTime;
+ } else {
+ throw new Exception;
+ }
+ }
+
+ /**
+ * @return integer
+ * @access public
+ * @since Method available since Release 2.3.0
+ */
+ public function getMaxRunningTime() {
+ return $this->maxRunningTime;
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Extensions/RepeatedTest.php b/buildscripts/PHPUnit2/Extensions/RepeatedTest.php
new file mode 100644
index 00000000..c23b0915
--- /dev/null
+++ b/buildscripts/PHPUnit2/Extensions/RepeatedTest.php
@@ -0,0 +1,138 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: RepeatedTest.php,v 1.15.2.4 2005/12/17 16:04:56 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+require_once 'PHPUnit2/Extensions/TestDecorator.php';
+
+/**
+ * A Decorator that runs a test repeatedly.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.0.0
+ */
+class PHPUnit2_Extensions_RepeatedTest extends PHPUnit2_Extensions_TestDecorator {
+ /**
+ * @var integer
+ * @access private
+ */
+ private $timesRepeat = 1;
+
+ /**
+ * Constructor.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @param integer $timesRepeat
+ * @throws Exception
+ * @access public
+ */
+ public function __construct(PHPUnit2_Framework_Test $test, $timesRepeat = 1) {
+ parent::__construct($test);
+
+ if (is_integer($timesRepeat) &&
+ $timesRepeat >= 0) {
+ $this->timesRepeat = $timesRepeat;
+ } else {
+ throw new Exception(
+ 'Argument 2 must be a positive integer.'
+ );
+ }
+ }
+
+ /**
+ * Counts the number of test cases that
+ * will be run by this test.
+ *
+ * @return integer
+ * @access public
+ */
+ public function countTestCases() {
+ return $this->timesRepeat * $this->test->countTestCases();
+ }
+
+ /**
+ * Runs the decorated test and collects the
+ * result in a TestResult.
+ *
+ * @param PHPUnit2_Framework_TestResult $result
+ * @return PHPUnit2_Framework_TestResult
+ * @throws Exception
+ * @access public
+ */
+ public function run($result = NULL) {
+ if ($result === NULL) {
+ $result = $this->createResult();
+ }
+
+ // XXX: Workaround for missing ability to declare type-hinted parameters as optional.
+ else if (!($result instanceof PHPUnit2_Framework_TestResult)) {
+ throw new Exception(
+ 'Argument 1 must be an instance of PHPUnit2_Framework_TestResult.'
+ );
+ }
+
+ for ($i = 0; $i < $this->timesRepeat && !$result->shouldStop(); $i++) {
+ $this->test->run($result);
+ }
+
+ return $result;
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Extensions/TestDecorator.php b/buildscripts/PHPUnit2/Extensions/TestDecorator.php
new file mode 100644
index 00000000..3557eeca
--- /dev/null
+++ b/buildscripts/PHPUnit2/Extensions/TestDecorator.php
@@ -0,0 +1,174 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: TestDecorator.php,v 1.14.2.4 2005/12/17 16:04:56 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+require_once 'PHPUnit2/Framework/Assert.php';
+require_once 'PHPUnit2/Framework/Test.php';
+require_once 'PHPUnit2/Framework/TestResult.php';
+
+/**
+ * A Decorator for Tests.
+ *
+ * Use TestDecorator as the base class for defining new
+ * test decorators. Test decorator subclasses can be introduced
+ * to add behaviour before or after a test is run.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.0.0
+ */
+class PHPUnit2_Extensions_TestDecorator extends PHPUnit2_Framework_Assert implements PHPUnit2_Framework_Test {
+ /**
+ * The Test to be decorated.
+ *
+ * @var object
+ * @access protected
+ */
+ protected $test = NULL;
+
+ /**
+ * Constructor.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @access public
+ */
+ public function __construct(PHPUnit2_Framework_Test $test) {
+ $this->test = $test;
+ }
+
+ /**
+ * Returns a string representation of the test.
+ *
+ * @return string
+ * @access public
+ */
+ public function toString() {
+ return $this->test->toString();
+ }
+
+ /**
+ * Runs the test and collects the
+ * result in a TestResult.
+ *
+ * @param PHPUnit2_Framework_TestResult $result
+ * @access public
+ */
+ public function basicRun(PHPUnit2_Framework_TestResult $result) {
+ $this->test->run($result);
+ }
+
+ /**
+ * Counts the number of test cases that
+ * will be run by this test.
+ *
+ * @return integer
+ * @access public
+ */
+ public function countTestCases() {
+ return $this->test->countTestCases();
+ }
+
+ /**
+ * Creates a default TestResult object.
+ *
+ * @return PHPUnit2_Framework_TestResult
+ * @access protected
+ */
+ protected function createResult() {
+ return new PHPUnit2_Framework_TestResult;
+ }
+
+ /**
+ * Returns the test to be run.
+ *
+ * @return PHPUnit2_Framework_Test
+ * @access public
+ */
+ public function getTest() {
+ return $this->test;
+ }
+
+ /**
+ * Runs the decorated test and collects the
+ * result in a TestResult.
+ *
+ * @param PHPUnit2_Framework_TestResult $result
+ * @return PHPUnit2_Framework_TestResult
+ * @throws Exception
+ * @access public
+ */
+ public function run($result = NULL) {
+ if ($result === NULL) {
+ $result = $this->createResult();
+ }
+
+ // XXX: Workaround for missing ability to declare type-hinted parameters as optional.
+ else if (!($result instanceof PHPUnit2_Framework_TestResult)) {
+ throw new Exception(
+ 'Argument 1 must be an instance of PHPUnit2_Framework_TestResult.'
+ );
+ }
+
+ $this->basicRun($result);
+
+ return $result;
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Extensions/TestSetup.php b/buildscripts/PHPUnit2/Extensions/TestSetup.php
new file mode 100644
index 00000000..4d28f931
--- /dev/null
+++ b/buildscripts/PHPUnit2/Extensions/TestSetup.php
@@ -0,0 +1,154 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: TestSetup.php,v 1.13.2.6 2005/12/17 16:04:56 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+require_once 'PHPUnit2/Framework/TestSuite.php';
+require_once 'PHPUnit2/Extensions/TestDecorator.php';
+
+/**
+ * A Decorator to set up and tear down additional fixture state.
+ * Subclass TestSetup and insert it into your tests when you want
+ * to set up additional state once before the tests are run.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.0.0
+ */
+class PHPUnit2_Extensions_TestSetup extends PHPUnit2_Extensions_TestDecorator {
+ /**
+ * Runs the decorated test and collects the
+ * result in a TestResult.
+ *
+ * @param PHPUnit2_Framework_TestResult $result
+ * @return PHPUnit2_Framework_TestResult
+ * @throws Exception
+ * @access public
+ */
+ public function run($result = NULL) {
+ if ($result === NULL) {
+ $result = $this->createResult();
+ }
+
+ // XXX: Workaround for missing ability to declare type-hinted parameters as optional.
+ else if (!($result instanceof PHPUnit2_Framework_TestResult)) {
+ throw new Exception(
+ 'Argument 1 must be an instance of PHPUnit2_Framework_TestResult.'
+ );
+ }
+
+ $this->setUp();
+ $this->copyFixtureToTest();
+ $this->basicRun($result);
+ $this->tearDown();
+
+ return $result;
+ }
+
+ /**
+ * Copies the fixture set up by setUp() to the test.
+ *
+ * @access private
+ * @since Method available since Release 2.3.0
+ */
+ private function copyFixtureToTest() {
+ $object = new ReflectionClass($this);
+
+ foreach ($object->getProperties() as $property) {
+ $name = $property->getName();
+
+ if ($name != 'test') {
+ $this->doCopyFixtureToTest($this->test, $name, $this->$name);
+ }
+ }
+ }
+
+ /**
+ * @access private
+ * @since Method available since Release 2.3.0
+ */
+ private function doCopyFixtureToTest($object, $name, &$value) {
+ if ($object instanceof PHPUnit2_Framework_TestSuite) {
+ foreach ($object->tests() as $test) {
+ $this->doCopyFixtureToTest($test, $name, $value);
+ }
+ } else {
+ $object->$name =& $value;
+ }
+ }
+
+ /**
+ * Sets up the fixture. Override to set up additional fixture
+ * state.
+ *
+ * @access protected
+ */
+ protected function setUp() {
+ }
+
+ /**
+ * Tears down the fixture. Override to tear down the additional
+ * fixture state.
+ *
+ * @access protected
+ */
+ protected function tearDown() {
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Framework/Assert.php b/buildscripts/PHPUnit2/Framework/Assert.php
new file mode 100644
index 00000000..3465afea
--- /dev/null
+++ b/buildscripts/PHPUnit2/Framework/Assert.php
@@ -0,0 +1,626 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: Assert.php,v 1.45.2.4 2005/12/17 16:04:56 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+require_once 'PHPUnit2/Framework/AssertionFailedError.php';
+require_once 'PHPUnit2/Framework/ComparisonFailure.php';
+
+/**
+ * A set of assert methods.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.0.0
+ * @static
+ */
+class PHPUnit2_Framework_Assert {
+ /**
+ * @var boolean
+ * @access private
+ * @static
+ */
+ private static $looselyTyped = FALSE;
+
+ /**
+ * Protect constructor since it is a static only class.
+ *
+ * @access protected
+ */
+ protected function __construct() {
+ }
+
+ /**
+ * Asserts that a haystack contains a needle.
+ *
+ * @param mixed $needle
+ * @param mixed $haystack
+ * @param string $message
+ * @access public
+ * @static
+ * @since Method available since Release 2.1.0
+ */
+ public static function assertContains($needle, $haystack, $message = '') {
+ self::doAssertContains($needle, $haystack, TRUE, $message);
+ }
+
+ /**
+ * Asserts that a haystack does not contain a needle.
+ *
+ * @param mixed $needle
+ * @param mixed $haystack
+ * @param string $message
+ * @access public
+ * @static
+ * @since Method available since Release 2.1.0
+ */
+ public static function assertNotContains($needle, $haystack, $message = '') {
+ self::doAssertContains($needle, $haystack, FALSE, $message);
+ }
+
+ /**
+ * @param mixed $needle
+ * @param mixed $haystack
+ * @param boolean $condition
+ * @param string $message
+ * @throws Exception
+ * @access private
+ * @static
+ * @since Method available since Release 2.2.0
+ */
+ private static function doAssertContains($needle, $haystack, $condition, $message) {
+ $found = FALSE;
+
+ if (is_array($haystack) ||
+ (is_object($haystack) && $haystack instanceof Iterator)) {
+ foreach ($haystack as $straw) {
+ if ($straw === $needle) {
+ $found = TRUE;
+ break;
+ }
+ }
+ }
+
+ else if (is_string($needle) && is_string($haystack)) {
+ if (strpos($haystack, $needle) !== FALSE) {
+ $found = TRUE;
+ }
+ }
+
+ else {
+ throw new Exception;
+ }
+
+ if ($condition && !$found) {
+ self::fail(
+ sprintf(
+ '%s%s"%s" does not contain "%s"',
+
+ $message,
+ ($message != '') ? ' ' : '',
+ self::objectToString($haystack),
+ self::objectToString($needle)
+ )
+ );
+ }
+
+ else if (!$condition && $found) {
+ self::fail(
+ sprintf(
+ '%s%s"%s" contains "%s"',
+
+ $message,
+ ($message != '') ? ' ' : '',
+ self::objectToString($haystack),
+ self::objectToString($needle)
+ )
+ );
+ }
+ }
+
+ /**
+ * Asserts that two variables are equal.
+ *
+ * @param mixed $expected
+ * @param mixed $actual
+ * @param string $message
+ * @param mixed $delta
+ * @access public
+ * @static
+ */
+ public static function assertEquals($expected, $actual, $message = '', $delta = 0) {
+ self::doAssertEquals($expected, $actual, $delta, TRUE, $message);
+ }
+
+ /**
+ * Asserts that two variables are not equal.
+ *
+ * @param mixed $expected
+ * @param mixed $actual
+ * @param string $message
+ * @param mixed $delta
+ * @access public
+ * @static
+ * @since Method available since Release 2.3.0
+ */
+ public static function assertNotEquals($expected, $actual, $message = '', $delta = 0) {
+ self::doAssertEquals($expected, $actual, $delta, FALSE, $message);
+ }
+
+ /**
+ * @param mixed $expected
+ * @param mixed $actual
+ * @param mixed $delta
+ * @param boolean $condition
+ * @param string $message
+ * @access private
+ * @static
+ * @since Method available since Release 2.3.0
+ */
+ private static function doAssertEquals($expected, $actual, $delta, $condition, $message) {
+ $equal = FALSE;
+
+ if (is_array($expected)) {
+ if (is_array($actual)) {
+ self::sortArrayRecursively($actual);
+ self::sortArrayRecursively($expected);
+
+ if (self::$looselyTyped) {
+ $actual = self::convertToString($actual);
+ $expected = self::convertToString($expected);
+ }
+
+ $equal = (serialize($expected) == serialize($actual));
+ }
+ }
+
+ else if (is_float($expected) && is_float($actual) && is_float($delta)) {
+ $equal = (abs($expected - $actual) <= $delta);
+ }
+
+ else {
+ $equal = (serialize($expected) == serialize($actual));
+ }
+
+ if ($condition && !$equal) {
+ self::failNotSame(
+ $expected,
+ $actual,
+ $message
+ );
+ }
+
+ else if (!$condition && $equal) {
+ self::failSame(
+ $expected,
+ $actual,
+ $message
+ );
+ }
+ }
+
+ /**
+ * Asserts that a condition is true.
+ *
+ * @param boolean $condition
+ * @param string $message
+ * @throws Exception
+ * @access public
+ * @static
+ */
+ public static function assertTrue($condition, $message = '') {
+ if (is_bool($condition)) {
+ if (!$condition) {
+ self::fail($message);
+ }
+ } else {
+ throw new Exception;
+ }
+ }
+
+ /**
+ * Asserts that a condition is false.
+ *
+ * @param boolean $condition
+ * @param string $message
+ * @throws Exception
+ * @access public
+ * @static
+ */
+ public static function assertFalse($condition, $message = '') {
+ if (is_bool($condition)) {
+ self::assertTrue(!$condition, $message);
+ } else {
+ throw new Exception;
+ }
+ }
+
+ /**
+ * Asserts that a variable is not NULL.
+ *
+ * @param mixed $actual
+ * @param string $message
+ * @access public
+ * @static
+ */
+ public static function assertNotNull($actual, $message = '') {
+ if (is_null($actual)) {
+ self::fail(self::format('NOT NULL', 'NULL', $message));
+ }
+ }
+
+ /**
+ * Asserts that a variable is NULL.
+ *
+ * @param mixed $actual
+ * @param string $message
+ * @access public
+ * @static
+ */
+ public static function assertNull($actual, $message = '') {
+ if (!is_null($actual)) {
+ self::fail(self::format('NULL', 'NOT NULL', $message));
+ }
+ }
+
+ /**
+ * Asserts that two variables have the same type and value.
+ * Used on objects, it asserts that two variables reference
+ * the same object.
+ *
+ * @param mixed $expected
+ * @param mixed $actual
+ * @param string $message
+ * @access public
+ * @static
+ */
+ public static function assertSame($expected, $actual, $message = '') {
+ if ($expected !== $actual) {
+ self::failNotSame($expected, $actual, $message);
+ }
+ }
+
+ /**
+ * Asserts that two variables do not have the same type and value.
+ * Used on objects, it asserts that two variables do not reference
+ * the same object.
+ *
+ * @param mixed $expected
+ * @param mixed $actual
+ * @param string $message
+ * @access public
+ * @static
+ */
+ public static function assertNotSame($expected, $actual, $message = '') {
+ if ($expected === $actual) {
+ self::failSame($expected, $actual, $message);
+ }
+ }
+
+ /**
+ * Asserts that a variable is of a given type.
+ *
+ * @param string $expected
+ * @param mixed $actual
+ * @param string $message
+ * @access public
+ * @static
+ */
+ public static function assertType($expected, $actual, $message = '') {
+ self::doAssertType($expected, $actual, TRUE, $message);
+ }
+
+ /**
+ * Asserts that a variable is not of a given type.
+ *
+ * @param string $expected
+ * @param mixed $actual
+ * @param string $message
+ * @access public
+ * @static
+ * @since Method available since Release 2.2.0
+ */
+ public static function assertNotType($expected, $actual, $message = '') {
+ self::doAssertType($expected, $actual, FALSE, $message);
+ }
+
+ /**
+ * @param string $expected
+ * @param mixed $actual
+ * @param boolean $condition
+ * @param string $message
+ * @access private
+ * @static
+ * @since Method available since Release 2.2.0
+ */
+ private static function doAssertType($expected, $actual, $condition, $message) {
+ if (!is_string($expected)) {
+ throw new Exception;
+ }
+
+ if (is_object($actual)) {
+ $result = $actual instanceof $expected;
+ } else {
+ $result = (gettype($actual) == $expected);
+ }
+
+ if ($condition && !$result) {
+ self::failNotSame(
+ $expected,
+ $actual,
+ $message
+ );
+ }
+
+ else if (!$condition && $result) {
+ self::failSame(
+ $expected,
+ $actual,
+ $message
+ );
+ }
+ }
+
+ /**
+ * Asserts that a string matches a given regular expression.
+ *
+ * @param string $pattern
+ * @param string $string
+ * @param string $message
+ * @access public
+ * @static
+ */
+ public static function assertRegExp($pattern, $string, $message = '') {
+ self::doAssertRegExp($pattern, $string, TRUE, $message);
+ }
+
+ /**
+ * Asserts that a string does not match a given regular expression.
+ *
+ * @param string $pattern
+ * @param string $string
+ * @param string $message
+ * @access public
+ * @static
+ * @since Method available since Release 2.1.0
+ */
+ public static function assertNotRegExp($pattern, $string, $message = '') {
+ self::doAssertRegExp($pattern, $string, FALSE, $message);
+ }
+
+ /**
+ * @param mixed $pattern
+ * @param mixed $string
+ * @param boolean $condition
+ * @param string $message
+ * @access private
+ * @static
+ * @since Method available since Release 2.2.0
+ */
+ private static function doAssertRegExp($pattern, $string, $condition, $message) {
+ if (!is_string($pattern) || !is_string($string)) {
+ throw new Exception;
+ }
+
+ $result = preg_match($pattern, $string);
+
+ if ($condition && !$result) {
+ self::fail(
+ sprintf(
+ '%s%s"%s" does not match pattern "%s"',
+
+ $message,
+ ($message != '') ? ' ' : '',
+ $string,
+ $pattern
+ )
+ );
+ }
+
+ else if (!$condition && $result) {
+ self::fail(
+ sprintf(
+ '%s%s"%s" matches pattern "%s"',
+
+ $message,
+ ($message != '') ? ' ' : '',
+ $string,
+ $pattern
+ )
+ );
+ }
+ }
+
+ /**
+ * Fails a test with the given message.
+ *
+ * @param string $message
+ * @throws PHPUnit2_Framework_AssertionFailedError
+ * @access public
+ * @static
+ */
+ public static function fail($message = '') {
+ throw new PHPUnit2_Framework_AssertionFailedError($message);
+ }
+
+ /**
+ * @param string $message
+ * @throws PHPUnit2_Framework_AssertionFailedError
+ * @access private
+ * @static
+ */
+ private static function failSame($message) {
+ self::fail(
+ sprintf(
+ '%s%sexpected not same',
+
+ $message,
+ ($message != '') ? ' ' : ''
+ )
+ );
+ }
+
+ /**
+ * @param mixed $expected
+ * @param mixed $actual
+ * @param string $message
+ * @throws PHPUnit2_Framework_AssertionFailedError
+ * @access private
+ * @static
+ */
+ private static function failNotSame($expected, $actual, $message) {
+ if (is_string($expected) && is_string($actual)) {
+ throw new PHPUnit2_Framework_ComparisonFailure($expected, $actual, $message);
+ }
+
+ self::fail(
+ sprintf(
+ '%s%sexpected same: <%s> was not: <%s>',
+
+ $message,
+ ($message != '') ? ' ' : '',
+ self::objectToString($expected),
+ self::objectToString($actual)
+ )
+ );
+ }
+
+ /**
+ * @param mixed $expected
+ * @param mixed $actual
+ * @param string $message
+ * @access public
+ * @static
+ */
+ public static function format($expected, $actual, $message) {
+ return sprintf(
+ '%s%sexpected: <%s> but was: <%s>',
+
+ $message,
+ ($message != '') ? ' ' : '',
+ self::objectToString($expected),
+ self::objectToString($actual)
+ );
+ }
+
+ /**
+ * @param boolean $looselyTyped
+ * @access public
+ * @static
+ */
+ public static function setLooselyTyped($looselyTyped) {
+ if (is_bool($looselyTyped)) {
+ self::$looselyTyped = $looselyTyped;
+ }
+ }
+
+ /**
+ * Converts a value to a string.
+ *
+ * @param mixed $value
+ * @access private
+ * @static
+ */
+ private static function convertToString($value) {
+ foreach ($value as $k => $v) {
+ if (is_array($v)) {
+ $value[$k] = self::convertToString($value[$k]);
+ } else if (is_object($v)) {
+ $value[$k] = self::objectToString($value[$k]);
+ } else {
+ settype($value[$k], 'string');
+ }
+ }
+
+ return $value;
+ }
+
+ /**
+ * @param mixed $object
+ * @return string
+ * @access private
+ * @static
+ */
+ private static function objectToString($object) {
+ if (is_array($object) || is_object($object)) {
+ $object = serialize($object);
+ }
+
+ return $object;
+ }
+
+ /**
+ * Sorts an array recursively by its keys.
+ *
+ * @param array $array
+ * @access private
+ * @static
+ * @author Adam Maccabee Trachtenberg <adam@trachtenberg.com>
+ */
+ private static function sortArrayRecursively(&$array) {
+ ksort($array);
+
+ foreach($array as $k => $v) {
+ if (is_array($v)) {
+ self::sortArrayRecursively($array[$k]);
+ }
+ }
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Framework/AssertionFailedError.php b/buildscripts/PHPUnit2/Framework/AssertionFailedError.php
new file mode 100644
index 00000000..d3db50ed
--- /dev/null
+++ b/buildscripts/PHPUnit2/Framework/AssertionFailedError.php
@@ -0,0 +1,80 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: AssertionFailedError.php,v 1.9.2.2 2005/12/17 16:04:56 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+/**
+ * Thrown when an assertion failed.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.0.0
+ */
+class PHPUnit2_Framework_AssertionFailedError extends Exception {
+ /**
+ * Wrapper for getMessage() which is declared as final.
+ *
+ * @return string
+ * @access public
+ */
+ public function toString() {
+ return $this->getMessage();
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Framework/ComparisonFailure.php b/buildscripts/PHPUnit2/Framework/ComparisonFailure.php
new file mode 100644
index 00000000..cc8e26e6
--- /dev/null
+++ b/buildscripts/PHPUnit2/Framework/ComparisonFailure.php
@@ -0,0 +1,153 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: ComparisonFailure.php,v 1.13.2.3 2005/12/17 16:04:56 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+require_once 'PHPUnit2/Framework/Assert.php';
+require_once 'PHPUnit2/Framework/AssertionFailedError.php';
+
+/**
+ * Thrown when an assertion for string equality failed.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.0.0
+ */
+class PHPUnit2_Framework_ComparisonFailure extends PHPUnit2_Framework_AssertionFailedError {
+ /**
+ * @var string
+ * @access private
+ */
+ private $expected = '';
+
+ /**
+ * @var string
+ * @access private
+ */
+ private $actual = '';
+
+ /**
+ * Constructs a comparison failure.
+ *
+ * @param string $expected
+ * @param string $actual
+ * @param string $message
+ * @access public
+ */
+ public function __construct($expected, $actual, $message = '') {
+ parent::__construct($message);
+
+ $this->expected = ($expected === NULL) ? 'NULL' : $expected;
+ $this->actual = ($actual === NULL) ? 'NULL' : $actual;
+ }
+
+ /**
+ * Returns "..." in place of common prefix and "..." in
+ * place of common suffix between expected and actual.
+ *
+ * @return string
+ * @access public
+ */
+ public function toString() {
+ $end = min(strlen($this->expected), strlen($this->actual));
+ $i = 0;
+ $j = strlen($this->expected) - 1;
+ $k = strlen($this->actual) - 1;
+
+ for (; $i < $end; $i++) {
+ if ($this->expected[$i] != $this->actual[$i]) {
+ break;
+ }
+ }
+
+ for (; $k >= $i && $j >= $i; $k--,$j--) {
+ if ($this->expected[$j] != $this->actual[$k]) {
+ break;
+ }
+ }
+
+ if ($j < $i && $k < $i) {
+ $expected = $this->expected;
+ $actual = $this->actual;
+ } else {
+ $expected = substr($this->expected, $i, ($j + 1 - $i));
+ $actual = substr($this->actual, $i, ($k + 1 - $i));;
+
+ if ($i <= $end && $i > 0) {
+ $expected = '...' . $expected;
+ $actual = '...' . $actual;
+ }
+
+ if ($j < strlen($this->expected) - 1) {
+ $expected .= '...';
+ }
+
+ if ($k < strlen($this->actual) - 1) {
+ $actual .= '...';
+ }
+ }
+
+ return PHPUnit2_Framework_Assert::format(
+ $expected,
+ $actual,
+ parent::getMessage()
+ );
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Framework/Error.php b/buildscripts/PHPUnit2/Framework/Error.php
new file mode 100644
index 00000000..a4bd4fd2
--- /dev/null
+++ b/buildscripts/PHPUnit2/Framework/Error.php
@@ -0,0 +1,88 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: Error.php,v 1.4.2.2 2005/12/17 16:04:56 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.2.0
+ */
+
+/**
+ * Wrapper for PHP errors.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.2.0
+ */
+class PHPUnit2_Framework_Error extends Exception {
+ /**
+ * Constructor.
+ *
+ * @param string $message
+ * @param integer $code
+ * @param string $file
+ * @param integer $line
+ * @param array $trace
+ * @access public
+ */
+ public function __construct($message, $code, $file, $line, $trace) {
+ parent::__construct($message, $code);
+
+ $this->file = $file;
+ $this->line = $line;
+ $this->trace = $trace;
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Framework/IncompleteTest.php b/buildscripts/PHPUnit2/Framework/IncompleteTest.php
new file mode 100644
index 00000000..325e6411
--- /dev/null
+++ b/buildscripts/PHPUnit2/Framework/IncompleteTest.php
@@ -0,0 +1,72 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: IncompleteTest.php,v 1.6.2.2 2005/12/17 16:04:56 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+/**
+ * A marker interface for marking any exception/error as result of an unit
+ * test as incomplete implementation or currently not implemented.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Interface available since Release 2.0.0
+ */
+interface PHPUnit2_Framework_IncompleteTest {
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Framework/IncompleteTestError.php b/buildscripts/PHPUnit2/Framework/IncompleteTestError.php
new file mode 100644
index 00000000..6c2a0660
--- /dev/null
+++ b/buildscripts/PHPUnit2/Framework/IncompleteTestError.php
@@ -0,0 +1,75 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: IncompleteTestError.php,v 1.5.2.3 2005/12/17 16:04:56 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+require_once 'PHPUnit2/Framework/AssertionFailedError.php';
+require_once 'PHPUnit2/Framework/IncompleteTest.php';
+
+/**
+ * Extension to PHPUnit2_Framework_AssertionFailedError to mark the special
+ * case of an incomplete test.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.0.0
+ */
+class PHPUnit2_Framework_IncompleteTestError extends PHPUnit2_Framework_AssertionFailedError implements PHPUnit2_Framework_IncompleteTest {
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Framework/Test.php b/buildscripts/PHPUnit2/Framework/Test.php
new file mode 100644
index 00000000..1d198f1a
--- /dev/null
+++ b/buildscripts/PHPUnit2/Framework/Test.php
@@ -0,0 +1,87 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: Test.php,v 1.12.2.3 2005/12/17 16:04:56 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+/**
+ * A Test can be run and collect its results.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Interface available since Release 2.0.0
+ */
+interface PHPUnit2_Framework_Test {
+ /**
+ * Counts the number of test cases that will be run by this test.
+ *
+ * @return integer
+ * @access public
+ */
+ public function countTestCases();
+
+ /**
+ * Runs a test and collects its result in a TestResult instance.
+ *
+ * @param PHPUnit2_Framework_TestResult $result
+ * @return PHPUnit2_Framework_TestResult
+ * @access public
+ */
+ public function run($result = NULL);
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Framework/TestCase.php b/buildscripts/PHPUnit2/Framework/TestCase.php
new file mode 100644
index 00000000..80f56932
--- /dev/null
+++ b/buildscripts/PHPUnit2/Framework/TestCase.php
@@ -0,0 +1,292 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: TestCase.php,v 1.32.2.5 2005/12/17 16:04:56 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+require_once 'PHPUnit2/Framework/Assert.php';
+require_once 'PHPUnit2/Framework/Error.php';
+require_once 'PHPUnit2/Framework/Test.php';
+require_once 'PHPUnit2/Framework/TestResult.php';
+
+/**
+ * A TestCase defines the fixture to run multiple tests.
+ *
+ * To define a TestCase
+ *
+ * 1) Implement a subclass of PHPUnit2_Framework_TestCase.
+ * 2) Define instance variables that store the state of the fixture.
+ * 3) Initialize the fixture state by overriding setUp().
+ * 4) Clean-up after a test by overriding tearDown().
+ *
+ * Each test runs in its own fixture so there can be no side effects
+ * among test runs.
+ *
+ * Here is an example:
+ *
+ * <code>
+ * <?php
+ * require_once 'PHPUnit2/Framework/TestCase.php';
+ *
+ * class MathTest extends PHPUnit2_Framework_TestCase {
+ * public $value1;
+ * public $value2;
+ *
+ * public function __construct($name) {
+ * parent::__construct($name);
+ * }
+ *
+ * public function setUp() {
+ * $this->value1 = 2;
+ * $this->value2 = 3;
+ * }
+ * }
+ * ?>
+ * </code>
+ *
+ * For each test implement a method which interacts with the fixture.
+ * Verify the expected results with assertions specified by calling
+ * assert with a boolean.
+ *
+ * <code>
+ * <?php
+ * public function testPass() {
+ * $this->assertTrue($this->value1 + $this->value2 == 5);
+ * }
+ * ?>
+ * </code>
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.0.0
+ * @abstract
+ */
+abstract class PHPUnit2_Framework_TestCase extends PHPUnit2_Framework_Assert implements PHPUnit2_Framework_Test {
+ /**
+ * The name of the test case.
+ *
+ * @var string
+ * @access private
+ */
+ private $name = NULL;
+
+ /**
+ * Constructs a test case with the given name.
+ *
+ * @param string
+ * @access public
+ */
+ public function __construct($name = NULL) {
+ if ($name !== NULL) {
+ $this->setName($name);
+ }
+ }
+
+ /**
+ * Returns a string representation of the test case.
+ *
+ * @return string
+ * @access public
+ */
+ public function toString() {
+ $class = new ReflectionClass($this);
+
+ return sprintf(
+ '%s(%s)',
+
+ $this->getName(),
+ $class->name
+ );
+ }
+
+ /**
+ * Counts the number of test cases executed by run(TestResult result).
+ *
+ * @return integer
+ * @access public
+ */
+ public function countTestCases() {
+ return 1;
+ }
+
+ /**
+ * Gets the name of a TestCase.
+ *
+ * @return string
+ * @access public
+ */
+ public function getName() {
+ return $this->name;
+ }
+
+ /**
+ * Runs the test case and collects the results in a TestResult object.
+ * If no TestResult object is passed a new one will be created.
+ *
+ * @param PHPUnit2_Framework_TestResult $result
+ * @return PHPUnit2_Framework_TestResult
+ * @throws Exception
+ * @access public
+ */
+ public function run($result = NULL) {
+ if ($result === NULL) {
+ $result = $this->createResult();
+ }
+
+ // XXX: Workaround for missing ability to declare type-hinted parameters as optional.
+ else if (!($result instanceof PHPUnit2_Framework_TestResult)) {
+ throw new Exception(
+ 'Argument 1 must be an instance of PHPUnit2_Framework_TestResult.'
+ );
+ }
+
+ $result->run($this);
+
+ return $result;
+ }
+
+ /**
+ * Runs the bare test sequence.
+ *
+ * @access public
+ */
+ public function runBare() {
+ $catchedException = NULL;
+
+ $this->setUp();
+
+ try {
+ $this->runTest();
+ }
+
+ catch (Exception $e) {
+ $catchedException = $e;
+ }
+
+ $this->tearDown();
+
+ // Workaround for missing "finally".
+ if ($catchedException !== NULL) {
+ throw $catchedException;
+ }
+ }
+
+ /**
+ * Override to run the test and assert its state.
+ *
+ * @throws PHPUnit2_Framework_Error
+ * @access protected
+ */
+ protected function runTest() {
+ if ($this->name === NULL) {
+ throw new PHPUnit2_Framework_Error(
+ 'PHPUnit2_Framework_TestCase::$name must not be NULL.'
+ );
+ }
+
+ try {
+ $class = new ReflectionClass($this);
+ $method = $class->getMethod($this->name);
+ }
+
+ catch (ReflectionException $e) {
+ $this->fail($e->getMessage());
+ }
+
+ $method->invoke($this);
+ }
+
+ /**
+ * Sets the name of a TestCase.
+ *
+ * @param string
+ * @access public
+ */
+ public function setName($name) {
+ $this->name = $name;
+ }
+
+ /**
+ * Creates a default TestResult object.
+ *
+ * @return PHPUnit2_Framework_TestResult
+ * @access protected
+ */
+ protected function createResult() {
+ return new PHPUnit2_Framework_TestResult;
+ }
+
+ /**
+ * Sets up the fixture, for example, open a network connection.
+ * This method is called before a test is executed.
+ *
+ * @access protected
+ */
+ protected function setUp() {
+ }
+
+ /**
+ * Tears down the fixture, for example, close a network connection.
+ * This method is called after a test is executed.
+ *
+ * @access protected
+ */
+ protected function tearDown() {
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Framework/TestFailure.php b/buildscripts/PHPUnit2/Framework/TestFailure.php
new file mode 100644
index 00000000..4957e4e6
--- /dev/null
+++ b/buildscripts/PHPUnit2/Framework/TestFailure.php
@@ -0,0 +1,154 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: TestFailure.php,v 1.10.2.3 2005/12/17 16:04:56 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+require_once 'PHPUnit2/Framework/AssertionFailedError.php';
+require_once 'PHPUnit2/Framework/Test.php';
+
+/**
+ * A TestFailure collects a failed test together with the caught exception.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.0.0
+ */
+class PHPUnit2_Framework_TestFailure {
+ /**
+ * @var PHPUnit2_Framework_Test
+ * @access protected
+ */
+ protected $failedTest;
+
+ /**
+ * @var Exception
+ * @access protected
+ */
+ protected $thrownException;
+
+ /**
+ * Constructs a TestFailure with the given test and exception.
+ *
+ * @param PHPUnit2_Framework_Test $failedTest
+ * @param Exception $thrownException
+ * @access public
+ */
+ public function __construct(PHPUnit2_Framework_Test $failedTest, Exception $thrownException) {
+ $this->failedTest = $failedTest;
+ $this->thrownException = $thrownException;
+ }
+
+ /**
+ * Returns a short description of the failure.
+ *
+ * @return string
+ * @access public
+ */
+ public function toString() {
+ return sprintf(
+ '%s: %s',
+
+ $this->failedTest,
+ $this->thrownException->getMessage()
+ );
+ }
+
+ /**
+ * Gets the failed test.
+ *
+ * @return Test
+ * @access public
+ */
+ public function failedTest() {
+ return $this->failedTest;
+ }
+
+ /**
+ * Gets the thrown exception.
+ *
+ * @return Exception
+ * @access public
+ */
+ public function thrownException() {
+ return $this->thrownException;
+ }
+
+ /**
+ * Returns the exception's message.
+ *
+ * @return string
+ * @access public
+ */
+ public function exceptionMessage() {
+ return $this->thrownException()->getMessage();
+ }
+
+ /**
+ * Returns TRUE if the thrown exception
+ * is of type AssertionFailedError.
+ *
+ * @return boolean
+ * @access public
+ */
+ public function isFailure() {
+ return ($this->thrownException() instanceof PHPUnit2_Framework_AssertionFailedError);
+ }
+}
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Framework/TestListener.php b/buildscripts/PHPUnit2/Framework/TestListener.php
new file mode 100644
index 00000000..79f11ffb
--- /dev/null
+++ b/buildscripts/PHPUnit2/Framework/TestListener.php
@@ -0,0 +1,135 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: TestListener.php,v 1.11.2.3 2005/12/17 16:04:56 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+require_once 'PHPUnit2/Framework/AssertionFailedError.php';
+require_once 'PHPUnit2/Framework/TestSuite.php';
+
+/**
+ * A Listener for test progress.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Interface available since Release 2.0.0
+ */
+interface PHPUnit2_Framework_TestListener {
+ /**
+ * An error occurred.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @param Exception $e
+ * @access public
+ */
+ public function addError(PHPUnit2_Framework_Test $test, Exception $e);
+
+ /**
+ * A failure occurred.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @param PHPUnit2_Framework_AssertionFailedError $e
+ * @access public
+ */
+ public function addFailure(PHPUnit2_Framework_Test $test, PHPUnit2_Framework_AssertionFailedError $e);
+
+ /**
+ * Incomplete test.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @param Exception $e
+ * @access public
+ */
+ public function addIncompleteTest(PHPUnit2_Framework_Test $test, Exception $e);
+
+ /**
+ * A test suite started.
+ *
+ * @param PHPUnit2_Framework_TestSuite $suite
+ * @access public
+ * @since Method available since Release 2.2.0
+ */
+ public function startTestSuite(PHPUnit2_Framework_TestSuite $suite);
+
+ /**
+ * A test suite ended.
+ *
+ * @param PHPUnit2_Framework_TestSuite $suite
+ * @access public
+ * @since Method available since Release 2.2.0
+ */
+ public function endTestSuite(PHPUnit2_Framework_TestSuite $suite);
+
+ /**
+ * A test started.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @access public
+ */
+ public function startTest(PHPUnit2_Framework_Test $test);
+
+ /**
+ * A test ended.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @access public
+ */
+ public function endTest(PHPUnit2_Framework_Test $test);
+}
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Framework/TestResult.php b/buildscripts/PHPUnit2/Framework/TestResult.php
new file mode 100644
index 00000000..17adb529
--- /dev/null
+++ b/buildscripts/PHPUnit2/Framework/TestResult.php
@@ -0,0 +1,447 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: TestResult.php,v 1.32.2.7 2006/02/25 09:44:23 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+require_once 'PHPUnit2/Framework/AssertionFailedError.php';
+require_once 'PHPUnit2/Framework/IncompleteTest.php';
+require_once 'PHPUnit2/Framework/TestFailure.php';
+require_once 'PHPUnit2/Framework/TestListener.php';
+require_once 'PHPUnit2/Util/ErrorHandler.php';
+require_once 'PHPUnit2/Util/Filter.php';
+
+/**
+ * A TestResult collects the results of executing a test case.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.0.0
+ */
+class PHPUnit2_Framework_TestResult {
+ /**
+ * @var array
+ * @access protected
+ */
+ protected $errors = array();
+
+ /**
+ * @var array
+ * @access protected
+ */
+ protected $failures = array();
+
+ /**
+ * @var array
+ * @access protected
+ */
+ protected $notImplemented = array();
+
+ /**
+ * @var array
+ * @access protected
+ */
+ protected $listeners = array();
+
+ /**
+ * @var integer
+ * @access protected
+ */
+ protected $runTests = 0;
+
+ /**
+ * Code Coverage information provided by Xdebug.
+ *
+ * @var array
+ * @access protected
+ */
+ protected $codeCoverageInformation = array();
+
+ /**
+ * @var boolean
+ * @access protected
+ */
+ protected $collectCodeCoverageInformation = FALSE;
+
+ /**
+ * @var boolean
+ * @access private
+ */
+ private $stop = FALSE;
+
+ /**
+ * Registers a TestListener.
+ *
+ * @param PHPUnit2_Framework_TestListener
+ * @access public
+ */
+ public function addListener(PHPUnit2_Framework_TestListener $listener) {
+ $this->listeners[] = $listener;
+ }
+
+ /**
+ * Unregisters a TestListener.
+ *
+ * @param PHPUnit2_Framework_TestListener $listener
+ * @access public
+ */
+ public function removeListener(PHPUnit2_Framework_TestListener $listener) {
+ for ($i = 0; $i < sizeof($this->listeners); $i++) {
+ if ($this->listeners[$i] === $listener) {
+ unset($this->listeners[$i]);
+ }
+ }
+ }
+
+ /**
+ * Adds an error to the list of errors.
+ * The passed in exception caused the error.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @param Exception $e
+ * @access public
+ */
+ public function addError(PHPUnit2_Framework_Test $test, Exception $e) {
+ if ($e instanceof PHPUnit2_Framework_IncompleteTest) {
+ $this->notImplemented[] = new PHPUnit2_Framework_TestFailure($test, $e);
+
+ foreach ($this->listeners as $listener) {
+ $listener->addIncompleteTest($test, $e);
+ }
+ } else {
+ $this->errors[] = new PHPUnit2_Framework_TestFailure($test, $e);
+
+ foreach ($this->listeners as $listener) {
+ $listener->addError($test, $e);
+ }
+ }
+ }
+
+ /**
+ * Adds a failure to the list of failures.
+ * The passed in exception caused the failure.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @param PHPUnit2_Framework_AssertionFailedError $e
+ * @access public
+ */
+ public function addFailure(PHPUnit2_Framework_Test $test, PHPUnit2_Framework_AssertionFailedError $e) {
+ if ($e instanceof PHPUnit2_Framework_IncompleteTest) {
+ $this->notImplemented[] = new PHPUnit2_Framework_TestFailure($test, $e);
+
+ foreach ($this->listeners as $listener) {
+ $listener->addIncompleteTest($test, $e);
+ }
+ } else {
+ $this->failures[] = new PHPUnit2_Framework_TestFailure($test, $e);
+
+ foreach ($this->listeners as $listener) {
+ $listener->addFailure($test, $e);
+ }
+ }
+ }
+
+ /**
+ * Informs the result that a testsuite will be started.
+ *
+ * @param PHPUnit2_Framework_TestSuite $suite
+ * @access public
+ * @since Method available since Release 2.2.0
+ */
+ public function startTestSuite(PHPUnit2_Framework_TestSuite $suite) {
+ foreach ($this->listeners as $listener) {
+ $listener->startTestSuite($suite);
+ }
+ }
+
+ /**
+ * Informs the result that a testsuite was completed.
+ *
+ * @param PHPUnit2_Framework_TestSuite $suite
+ * @access public
+ * @since Method available since Release 2.2.0
+ */
+ public function endTestSuite(PHPUnit2_Framework_TestSuite $suite) {
+ foreach ($this->listeners as $listener) {
+ $listener->endTestSuite($suite);
+ }
+ }
+
+ /**
+ * Informs the result that a test will be started.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @access public
+ */
+ public function startTest(PHPUnit2_Framework_Test $test) {
+ $this->runTests += $test->countTestCases();
+
+ foreach ($this->listeners as $listener) {
+ $listener->startTest($test);
+ }
+ }
+
+ /**
+ * Informs the result that a test was completed.
+ *
+ * @param PHPUnit2_Framework_Test
+ * @access public
+ */
+ public function endTest(PHPUnit2_Framework_Test $test) {
+ foreach ($this->listeners as $listener) {
+ $listener->endTest($test);
+ }
+ }
+
+ /**
+ * Returns TRUE if no incomplete test occured.
+ *
+ * @return boolean
+ * @access public
+ */
+ public function allCompletlyImplemented() {
+ return $this->notImplementedCount() == 0;
+ }
+
+ /**
+ * Gets the number of incomplete tests.
+ *
+ * @return integer
+ * @access public
+ */
+ public function notImplementedCount() {
+ return sizeof($this->notImplemented);
+ }
+
+ /**
+ * Returns an Enumeration for the incomplete tests.
+ *
+ * @return array
+ * @access public
+ */
+ public function notImplemented() {
+ return $this->notImplemented;
+ }
+
+ /**
+ * Gets the number of detected errors.
+ *
+ * @return integer
+ * @access public
+ */
+ public function errorCount() {
+ return sizeof($this->errors);
+ }
+
+ /**
+ * Returns an Enumeration for the errors.
+ *
+ * @return array
+ * @access public
+ */
+ public function errors() {
+ return $this->errors;
+ }
+
+ /**
+ * Gets the number of detected failures.
+ *
+ * @return integer
+ * @access public
+ */
+ public function failureCount() {
+ return sizeof($this->failures);
+ }
+
+ /**
+ * Returns an Enumeration for the failures.
+ *
+ * @return array
+ * @access public
+ */
+ public function failures() {
+ return $this->failures;
+ }
+
+ /**
+ * Enables or disables the collection of Code Coverage information.
+ *
+ * @param boolean $flag
+ * @throws Exception
+ * @access public
+ * @since Method available since Release 2.3.0
+ */
+ public function collectCodeCoverageInformation($flag) {
+ if (is_bool($flag)) {
+ $this->collectCodeCoverageInformation = $flag;
+ } else {
+ throw new Exception;
+ }
+ }
+
+ /**
+ * Returns Code Coverage data per test case.
+ *
+ * Format of the result array:
+ *
+ * <code>
+ * array(
+ * "testCase" => array(
+ * "/tested/code.php" => array(
+ * linenumber => flag
+ * )
+ * )
+ * )
+ * </code>
+ *
+ * flag < 0: Line is executable but was not executed.
+ * flag > 0: Line was executed.
+ *
+ * @return array
+ * @access public
+ */
+ public function getCodeCoverageInformation() {
+ return $this->codeCoverageInformation;
+ }
+
+ /**
+ * Runs a TestCase.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @access public
+ */
+ public function run(PHPUnit2_Framework_Test $test) {
+ $this->startTest($test);
+
+ set_error_handler('PHPUnit2_Util_ErrorHandler', E_USER_ERROR);
+
+ $useXdebug = (extension_loaded('xdebug') && $this->collectCodeCoverageInformation);
+
+ if ($useXdebug) {
+ xdebug_start_code_coverage(XDEBUG_CC_UNUSED);
+ }
+
+ $globalsBackup = $GLOBALS;
+
+ try {
+ $test->runBare();
+ }
+
+ catch (PHPUnit2_Framework_AssertionFailedError $e) {
+ $this->addFailure($test, $e);
+ }
+
+ catch (Exception $e) {
+ $this->addError($test, $e);
+ }
+
+ $GLOBALS = $globalsBackup;
+
+ if ($useXdebug) {
+ $this->codeCoverageInformation[$test->getName()] = PHPUnit2_Util_Filter::getFilteredCodeCoverage(
+ xdebug_get_code_coverage()
+ );
+
+ xdebug_stop_code_coverage();
+ }
+
+ restore_error_handler();
+
+ $this->endTest($test);
+ }
+
+ /**
+ * Gets the number of run tests.
+ *
+ * @return integer
+ * @access public
+ */
+ public function runCount() {
+ return $this->runTests;
+ }
+
+ /**
+ * Checks whether the test run should stop.
+ *
+ * @return boolean
+ * @access public
+ */
+ public function shouldStop() {
+ return $this->stop;
+ }
+
+ /**
+ * Marks that the test run should stop.
+ *
+ * @access public
+ */
+ public function stop() {
+ $this->stop = TRUE;
+ }
+
+ /**
+ * Returns whether the entire test was successful or not.
+ *
+ * @return boolean
+ * @access public
+ */
+ public function wasSuccessful() {
+ return empty($this->errors) && empty($this->failures);
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Framework/TestSuite.php b/buildscripts/PHPUnit2/Framework/TestSuite.php
new file mode 100644
index 00000000..3d5d670e
--- /dev/null
+++ b/buildscripts/PHPUnit2/Framework/TestSuite.php
@@ -0,0 +1,554 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: TestSuite.php,v 1.26.2.11 2005/12/17 16:04:56 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+require_once 'PHPUnit2/Framework/Test.php';
+require_once 'PHPUnit2/Framework/TestCase.php';
+require_once 'PHPUnit2/Framework/TestResult.php';
+require_once 'PHPUnit2/Runner/BaseTestRunner.php';
+require_once 'PHPUnit2/Util/Fileloader.php';
+
+/**
+ * A TestSuite is a composite of Tests. It runs a collection of test cases.
+ *
+ * Here is an example using the dynamic test definition.
+ *
+ * <code>
+ * <?php
+ * $suite = new PHPUnit2_Framework_TestSuite;
+ * $suite->addTest(new MathTest('testPass'));
+ * ?>
+ * </code>
+ *
+ * Alternatively, a TestSuite can extract the tests to be run automatically.
+ * To do so you pass a ReflectionClass instance for your
+ * PHPUnit2_Framework_TestCase class to the PHPUnit2_Framework_TestSuite
+ * constructor.
+ *
+ * <code>
+ * <?php
+ * $suite = new PHPUnit2_Framework_TestSuite(
+ * new ReflectionClass('MathTest')
+ * );
+ * ?>
+ * </code>
+ *
+ * This constructor creates a suite with all the methods starting with
+ * "test" that take no arguments.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.0.0
+ */
+class PHPUnit2_Framework_TestSuite implements PHPUnit2_Framework_Test {
+ /**
+ * The name of the test suite.
+ *
+ * @var string
+ * @access private
+ */
+ private $name = '';
+
+ /**
+ * The tests in the test suite.
+ *
+ * @var array
+ * @access private
+ */
+ private $tests = array();
+
+ /**
+ * Constructs a new TestSuite:
+ *
+ * - PHPUnit2_Framework_TestSuite() constructs an empty TestSuite.
+ *
+ * - PHPUnit2_Framework_TestSuite(ReflectionClass) constructs a
+ * TestSuite from the given class.
+ *
+ * - PHPUnit2_Framework_TestSuite(ReflectionClass, String)
+ * constructs a TestSuite from the given class with the given
+ * name.
+ *
+ * - PHPUnit2_Framework_TestSuite(String) either constructs a
+ * TestSuite from the given class (if the passed string is the
+ * name of an existing class) or constructs an empty TestSuite
+ * with the given name.
+ *
+ * @param mixed $theClass
+ * @param string $name
+ * @throws Exception
+ * @access public
+ */
+ public function __construct($theClass = '', $name = '') {
+ $argumentsValid = FALSE;
+
+ if (is_object($theClass) &&
+ $theClass instanceof ReflectionClass) {
+ $argumentsValid = TRUE;
+ }
+
+ else if (is_string($theClass) && $theClass !== '' && class_exists($theClass)) {
+ $argumentsValid = TRUE;
+
+ if ($name == '') {
+ $name = $theClass;
+ }
+
+ $theClass = new ReflectionClass($theClass);
+ }
+
+ else if (is_string($theClass)) {
+ $this->setName($theClass);
+ return;
+ }
+
+ if (!$argumentsValid) {
+ throw new Exception;
+ }
+
+ if ($name != '') {
+ $this->setName($name);
+ } else {
+ $this->setName($theClass->getName());
+ }
+
+ $constructor = $theClass->getConstructor();
+
+ if ($constructor === NULL ||
+ !$constructor->isPublic()) {
+ $this->addTest(
+ self::warning(
+ sprintf(
+ 'Class %s has no public constructor',
+
+ $theClass->getName()
+ )
+ )
+ );
+
+ return;
+ }
+
+ $methods = $theClass->getMethods();
+ $names = array();
+
+ foreach ($methods as $method) {
+ $this->addTestMethod($method, $names, $theClass);
+ }
+
+ if (empty($this->tests)) {
+ $this->addTest(
+ self::warning(
+ sprintf(
+ 'No tests found in %s',
+
+ $theClass->getName()
+ )
+ )
+ );
+ }
+ }
+
+ /**
+ * Returns a string representation of the test suite.
+ *
+ * @return string
+ * @access public
+ */
+ public function toString() {
+ return $this->getName();
+ }
+
+ /**
+ * Adds a test to the suite.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @access public
+ */
+ public function addTest(PHPUnit2_Framework_Test $test) {
+ $this->tests[] = $test;
+ }
+
+ /**
+ * Adds the tests from the given class to the suite.
+ *
+ * @param mixed $testClass
+ * @access public
+ */
+ public function addTestSuite($testClass) {
+ if (is_string($testClass) &&
+ class_exists($testClass)) {
+ $testClass = new ReflectionClass($testClass);
+ }
+
+ if (is_object($testClass) &&
+ $testClass instanceof ReflectionClass) {
+ $this->addTest(new PHPUnit2_Framework_TestSuite($testClass));
+ }
+ }
+
+ /**
+ * Wraps both <code>addTest()</code> and <code>addTestSuite</code>
+ * as well as the separate import statements for the user's convenience.
+ *
+ * If the named file cannot be read or there are no new tests that can be
+ * added, a <code>PHPUnit2_Framework_Warning</code> will be created instead,
+ * leaving the current test run untouched.
+ *
+ * @param string $filename
+ * @throws Exception
+ * @access public
+ * @since Method available since Release 2.3.0
+ * @author Stefano F. Rausch <stefano@rausch-e.net>
+ */
+ public function addTestFile($filename) {
+ if (!is_string($filename) || !file_exists($filename)) {
+ throw new Exception;
+ }
+
+ $declaredClasses = get_declared_classes();
+
+ PHPUnit2_Util_Fileloader::checkAndLoad($filename);
+
+ $newClasses = array_values(
+ array_diff(get_declared_classes(), $declaredClasses)
+ );
+
+ $testsFound = 0;
+
+ foreach ($newClasses as $class) {
+ if (preg_match('"Tests?$"', $class)) {
+ try {
+ $suiteMethod = new ReflectionMethod(
+ $class, PHPUnit2_Runner_BaseTestRunner::SUITE_METHODNAME
+ );
+
+ $this->addTest($suiteMethod->invoke(NULL));
+ } catch (ReflectionException $e) {
+ $this->addTestSuite(new ReflectionClass($class));
+ }
+
+ $testsFound++;
+ }
+ }
+
+ if ($testsFound == 0) {
+ $this->addTest(
+ new PHPUnit2_Framework_Warning('No tests found in file ' . $filename)
+ );
+ }
+ }
+
+ /**
+ * Wrapper for addTestFile() that adds multiple test files.
+ *
+ * @param Array $filenames
+ * @throws Exception
+ * @access public
+ * @since Method available since Release 2.3.0
+ */
+ public function addTestFiles($filenames) {
+ foreach ($filenames as $filename) {
+ $this->addTestFile($filename);
+ }
+ }
+
+ /**
+ * Counts the number of test cases that will be run by this test.
+ *
+ * @return integer
+ * @access public
+ */
+ public function countTestCases() {
+ $count = 0;
+
+ foreach ($this->tests as $test) {
+ $count += $test->countTestCases();
+ }
+
+ return $count;
+ }
+
+ /**
+ * @param ReflectionClass $theClass
+ * @param string $name
+ * @return PHPUnit2_Framework_Test
+ * @access public
+ * @static
+ */
+ public static function createTest(ReflectionClass $theClass, $name) {
+ if (!$theClass->isInstantiable()) {
+ return self::warning(
+ sprintf(
+ 'Cannot instantiate test case %s.',
+ $theClass->getName()
+ )
+ );
+ }
+
+ $constructor = $theClass->getConstructor();
+
+ if ($constructor !== NULL) {
+ $parameters = $constructor->getParameters();
+
+ if (sizeof($parameters) == 0) {
+ $test = $theClass->newInstance();
+
+ if ($test instanceof PHPUnit2_Framework_TestCase) {
+ $test->setName($name);
+ }
+ }
+
+ else if (sizeof($parameters) == 1 &&
+ $parameters[0]->getClass() === NULL) {
+ $test = $theClass->newInstance($name);
+ }
+
+ else {
+ return self::warning(
+ sprintf(
+ 'Constructor of class %s is not TestCase($name) or TestCase().',
+ $theClass->getName()
+ )
+ );
+ }
+ }
+
+ return $test;
+ }
+
+ /**
+ * Creates a default TestResult object.
+ *
+ * @return PHPUnit2_Framework_TestResult
+ * @access protected
+ */
+ protected function createResult() {
+ return new PHPUnit2_Framework_TestResult;
+ }
+
+ /**
+ * Returns the name of the suite.
+ *
+ * @return string
+ * @access public
+ */
+ public function getName() {
+ return $this->name;
+ }
+
+ /**
+ * Runs the tests and collects their result in a TestResult.
+ *
+ * @param PHPUnit2_Framework_TestResult $result
+ * @return PHPUnit2_Framework_TestResult
+ * @throws Exception
+ * @access public
+ */
+ public function run($result = NULL) {
+ if ($result === NULL) {
+ $result = $this->createResult();
+ }
+
+ // XXX: Workaround for missing ability to declare type-hinted parameters as optional.
+ else if (!($result instanceof PHPUnit2_Framework_TestResult)) {
+ throw new Exception(
+ 'Argument 1 must be an instance of PHPUnit2_Framework_TestResult.'
+ );
+ }
+
+ $result->startTestSuite($this);
+
+ foreach ($this->tests as $test) {
+ if ($result->shouldStop()) {
+ break;
+ }
+
+ $this->runTest($test, $result);
+ }
+
+ $result->endTestSuite($this);
+
+ return $result;
+ }
+
+ /**
+ * Runs a test.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @param PHPUnit2_Framework_TestResult $testResult
+ * @access public
+ */
+ public function runTest(PHPUnit2_Framework_Test $test, PHPUnit2_Framework_TestResult $result) {
+ $test->run($result);
+ }
+
+ /**
+ * Sets the name of the suite.
+ *
+ * @param string
+ * @access public
+ */
+ public function setName($name) {
+ $this->name = $name;
+ }
+
+ /**
+ * Returns the test at the given index.
+ *
+ * @param integer
+ * @return PHPUnit2_Framework_Test
+ * @access public
+ */
+ public function testAt($index) {
+ if (isset($this->tests[$index])) {
+ return $this->tests[$index];
+ } else {
+ return FALSE;
+ }
+ }
+
+ /**
+ * Returns the number of tests in this suite.
+ *
+ * @return integer
+ * @access public
+ */
+ public function testCount() {
+ return sizeof($this->tests);
+ }
+
+ /**
+ * Returns the tests as an enumeration.
+ *
+ * @return array
+ * @access public
+ */
+ public function tests() {
+ return $this->tests;
+ }
+
+ /**
+ * @param ReflectionMethod $method
+ * @param array $names
+ * @param ReflectionClass $theClass
+ * @access private
+ */
+ private function addTestMethod(ReflectionMethod $method, &$names, ReflectionClass $theClass) {
+ $name = $method->getName();
+
+ if (in_array($name, $names)) {
+ return;
+ }
+
+ if ($this->isPublicTestMethod($method)) {
+ $names[] = $name;
+
+ $this->addTest(
+ self::createTest(
+ $theClass,
+ $name
+ )
+ );
+ }
+
+ else if ($this->isTestMethod($method)) {
+ $this->addTest(
+ self::warning(
+ sprintf(
+ 'Test method is not public: %s',
+
+ $name
+ )
+ )
+ );
+ }
+ }
+
+ /**
+ * @param ReflectionMethod $method
+ * @return boolean
+ * @access private
+ */
+ private function isPublicTestMethod(ReflectionMethod $method) {
+ return ($this->isTestMethod($method) &&
+ $method->isPublic());
+ }
+
+ /**
+ * @param ReflectionMethod $method
+ * @return boolean
+ * @access private
+ */
+ private function isTestMethod(ReflectionMethod $method) {
+ return (substr($method->name, 0, 4) == 'test');
+ }
+
+ /**
+ * @param string $message
+ * @return PHPUnit2_Framework_Warning
+ * @access private
+ */
+ private static function warning($message) {
+ require_once 'PHPUnit2/Framework/Warning.php';
+ return new PHPUnit2_Framework_Warning($message);
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Framework/Warning.php b/buildscripts/PHPUnit2/Framework/Warning.php
new file mode 100644
index 00000000..0ae885a4
--- /dev/null
+++ b/buildscripts/PHPUnit2/Framework/Warning.php
@@ -0,0 +1,94 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: Warning.php,v 1.11.2.3 2005/12/17 16:04:56 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+require_once 'PHPUnit2/Framework/TestCase.php';
+
+/**
+ * A warning.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.0.0
+ */
+class PHPUnit2_Framework_Warning extends PHPUnit2_Framework_TestCase {
+ /**
+ * @var string
+ * @access private
+ */
+ private $message = '';
+
+ /**
+ * @param string $message
+ * @access public
+ */
+ public function __construct($message = '') {
+ $this->message = $message;
+ parent::__construct('Warning');
+ }
+
+ /**
+ * @access protected
+ */
+ protected function runTest() {
+ $this->fail($this->message);
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Runner/BaseTestRunner.php b/buildscripts/PHPUnit2/Runner/BaseTestRunner.php
new file mode 100644
index 00000000..b9517e5a
--- /dev/null
+++ b/buildscripts/PHPUnit2/Runner/BaseTestRunner.php
@@ -0,0 +1,283 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: BaseTestRunner.php,v 1.18.2.3 2005/12/17 16:04:56 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+require_once 'PHPUnit2/Framework/AssertionFailedError.php';
+require_once 'PHPUnit2/Framework/TestListener.php';
+require_once 'PHPUnit2/Runner/StandardTestSuiteLoader.php';
+
+/**
+ * Base class for all test runners.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.0.0
+ * @abstract
+ */
+abstract class PHPUnit2_Runner_BaseTestRunner implements PHPUnit2_Framework_TestListener {
+ const STATUS_ERROR = 1;
+ const STATUS_FAILURE = 2;
+ const STATUS_INCOMPLETE = 3;
+ const SUITE_METHODNAME = 'suite';
+
+ /**
+ * An error occurred.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @param Exception $e
+ * @access public
+ */
+ public function addError(PHPUnit2_Framework_Test $test, Exception $e) {
+ $this->testFailed(self::STATUS_ERROR, $test, $e);
+ }
+
+ /**
+ * A failure occurred.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @param PHPUnit2_Framework_AssertionFailedError $e
+ * @access public
+ */
+ public function addFailure(PHPUnit2_Framework_Test $test, PHPUnit2_Framework_AssertionFailedError $e) {
+ $this->testFailed(self::STATUS_FAILURE, $test, $e);
+ }
+
+ /**
+ * Incomplete test.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @param Exception $e
+ * @access public
+ */
+ public function addIncompleteTest(PHPUnit2_Framework_Test $test, Exception $e) {
+ $this->testFailed(self::STATUS_INCOMPLETE, $test, $e);
+ }
+
+ /**
+ * A testsuite started.
+ *
+ * @param PHPUnit2_Framework_TestSuite $suite
+ * @access public
+ * @since Method available since Release 2.2.0
+ */
+ public function startTestSuite(PHPUnit2_Framework_TestSuite $suite) {
+ }
+
+ /**
+ * A testsuite ended.
+ *
+ * @param PHPUnit2_Framework_TestSuite $suite
+ * @access public
+ * @since Method available since Release 2.2.0
+ */
+ public function endTestSuite(PHPUnit2_Framework_TestSuite $suite) {
+ }
+
+ /**
+ * A test started.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @access public
+ */
+ public function startTest(PHPUnit2_Framework_Test $test) {
+ $this->testStarted($test->getName());
+ }
+
+ /**
+ * A test ended.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @access public
+ */
+ public function endTest(PHPUnit2_Framework_Test $test) {
+ $this->testEnded($test->getName());
+ }
+
+ /**
+ * Returns the loader to be used.
+ *
+ * @return PHPUnit2_Runner_TestSuiteLoader
+ * @access public
+ */
+ public function getLoader() {
+ return new PHPUnit2_Runner_StandardTestSuiteLoader;
+ }
+
+ /**
+ * Returns the Test corresponding to the given suite.
+ * This is a template method, subclasses override
+ * the runFailed() and clearStatus() methods.
+ *
+ * @param string $suiteClassName
+ * @param string $suiteClassFile
+ * @return PHPUnit2_Framework_Test
+ * @access public
+ */
+ public function getTest($suiteClassName, $suiteClassFile = '') {
+ if ($suiteClassFile == $suiteClassName . '.php') {
+ $suiteClassFile = '';
+ }
+
+ try {
+ $testClass = $this->loadSuiteClass($suiteClassName, $suiteClassFile);
+ }
+
+ catch (Exception $e) {
+ $this->runFailed($e->getMessage());
+ return NULL;
+ }
+
+ try {
+ $suiteMethod = $testClass->getMethod(self::SUITE_METHODNAME);
+
+ if (!$suiteMethod->isStatic()) {
+ $this->runFailed(
+ 'suite() method must be static.'
+ );
+
+ return NULL;
+ }
+
+ try {
+ $test = $suiteMethod->invoke(NULL);
+ }
+
+ catch (ReflectionException $e) {
+ $this->runFailed(
+ sprintf(
+ "Failed to invoke suite() method.\n%s",
+
+ $e->getMessage()
+ )
+ );
+
+ return NULL;
+ }
+ }
+
+ catch (ReflectionException $e) {
+ $test = new PHPUnit2_Framework_TestSuite($testClass);
+ }
+
+ $this->clearStatus();
+
+ return $test;
+ }
+
+ /**
+ * Override to define how to handle a failed loading of
+ * a test suite.
+ *
+ * @param string $message
+ * @access protected
+ * @abstract
+ */
+ protected abstract function runFailed($message);
+
+ /**
+ * Returns the loaded ReflectionClass for a suite name.
+ *
+ * @param string $suiteClassName
+ * @param string $suiteClassFile
+ * @return ReflectionClass
+ * @access protected
+ */
+ protected function loadSuiteClass($suiteClassName, $suiteClassFile = '') {
+ return $this->getLoader()->load($suiteClassName, $suiteClassFile);
+ }
+
+ /**
+ * Clears the status message.
+ *
+ * @access protected
+ */
+ protected function clearStatus() {
+ }
+
+ /**
+ * A test started.
+ *
+ * @param string $testName
+ * @access public
+ * @abstract
+ */
+ public abstract function testStarted($testName);
+
+ /**
+ * A test ended.
+ *
+ * @param string $testName
+ * @access public
+ * @abstract
+ */
+ public abstract function testEnded($testName);
+
+ /**
+ * A test failed.
+ *
+ * @param integer $status
+ * @param PHPUnit2_Framework_Test $test
+ * @param PHPUnit2_Framework_AssertionFailedError $e
+ * @access public
+ * @abstract
+ */
+ public abstract function testFailed($status, PHPUnit2_Framework_Test $test, PHPUnit2_Framework_AssertionFailedError $e);
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Runner/IncludePathTestCollector.php b/buildscripts/PHPUnit2/Runner/IncludePathTestCollector.php
new file mode 100644
index 00000000..116b20ed
--- /dev/null
+++ b/buildscripts/PHPUnit2/Runner/IncludePathTestCollector.php
@@ -0,0 +1,184 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: IncludePathTestCollector.php,v 1.13.2.5 2005/12/17 16:04:56 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.1.0
+ */
+
+if (!class_exists('AppendIterator')) {
+ class AppendIterator implements Iterator {
+ private $iterators;
+
+ public function __construct() {
+ $this->iterators = new ArrayIterator();
+ }
+
+ public function __call($func, $params) {
+ return call_user_func_array(array($this->getInnerIterator(), $func), $params);
+ }
+
+ public function append(Iterator $it) {
+ $this->iterators->append($it);
+ }
+
+ public function getInnerIterator() {
+ return $this->iterators->current();
+ }
+
+ public function rewind() {
+ $this->iterators->rewind();
+
+ if ($this->iterators->valid()) {
+ $this->getInnerIterator()->rewind();
+ }
+ }
+
+ public function valid() {
+ return $this->iterators->valid() && $this->getInnerIterator()->valid();
+ }
+
+ public function current() {
+ return $this->iterators->valid() ? $this->getInnerIterator()->current() : NULL;
+ }
+
+ public function key() {
+ return $this->iterators->valid() ? $this->getInnerIterator()->key() : NULL;
+ }
+
+ public function next() {
+ if (!$this->iterators->valid()) return;
+ $this->getInnerIterator()->next();
+
+ if ($this->getInnerIterator()->valid()) return;
+ $this->iterators->next();
+
+ while ($this->iterators->valid()) {
+ $this->getInnerIterator()->rewind();
+
+ if ($this->getInnerIterator()->valid()) return;
+ $this->iterators->next();
+ }
+ }
+ }
+}
+
+require_once 'PHPUnit2/Runner/TestCollector.php';
+
+require_once 'PEAR/Config.php';
+
+/**
+ * An implementation of a TestCollector that consults the
+ * include path set in the php.ini.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.1.0
+ */
+
+class PHPUnit2_Runner_IncludePathTestCollector implements PHPUnit2_Runner_TestCollector {
+ /**
+ * @return array
+ * @access public
+ */
+ public function collectTests() {
+ $config = new PEAR_Config;
+ $iterator = new AppendIterator;
+ $result = array();
+
+ if (substr(PHP_OS, 0, 3) == 'WIN') {
+ $delimiter = ';';
+ } else {
+ $delimiter = ':';
+ }
+
+ $paths = explode($delimiter, ini_get('include_path'));
+ $paths[] = $config->get('test_dir');
+
+ foreach ($paths as $path) {
+ $iterator->append(
+ new RecursiveIteratorIterator(
+ new RecursiveDirectoryIterator($path)
+ )
+ );
+ }
+
+ foreach ($iterator as $path => $file) {
+ if ($this->isTestClass($file)) {
+ if (substr(PHP_OS, 0, 3) == 'WIN') {
+ $path = str_replace('/', '\\', $path);
+ }
+
+ $result[] = $path;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Considers a file to contain a test class when it contains the
+ * pattern "Test" in its name and its name ends with ".php".
+ *
+ * @param string $classFileName
+ * @return boolean
+ * @access protected
+ */
+ protected function isTestClass($classFileName) {
+ return (strpos($classFileName, 'Test') !== FALSE && substr($classFileName, -4) == '.php') ? TRUE : FALSE;
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Runner/StandardTestSuiteLoader.php b/buildscripts/PHPUnit2/Runner/StandardTestSuiteLoader.php
new file mode 100644
index 00000000..b0c359a0
--- /dev/null
+++ b/buildscripts/PHPUnit2/Runner/StandardTestSuiteLoader.php
@@ -0,0 +1,129 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: StandardTestSuiteLoader.php,v 1.19.2.8 2005/12/17 16:04:56 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+require_once 'PHPUnit2/Runner/TestSuiteLoader.php';
+require_once 'PHPUnit2/Util/Fileloader.php';
+
+require_once 'PEAR/Config.php';
+
+/**
+ * The standard test suite loader.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.0.0
+ */
+class PHPUnit2_Runner_StandardTestSuiteLoader implements PHPUnit2_Runner_TestSuiteLoader {
+ /**
+ * @param string $suiteClassName
+ * @param string $suiteClassFile
+ * @return ReflectionClass
+ * @throws Exception
+ * @access public
+ */
+ public function load($suiteClassName, $suiteClassFile = '') {
+ $suiteClassName = str_replace('.php', '', $suiteClassName);
+ $suiteClassFile = !empty($suiteClassFile) ? $suiteClassFile : str_replace('_', '/', $suiteClassName) . '.php';
+
+ if (!class_exists($suiteClassName)) {
+ if(!file_exists($suiteClassFile)) {
+ $config = new PEAR_Config;
+
+ $includePaths = explode(PATH_SEPARATOR, get_include_path());
+ $includePaths[] = $config->get('test_dir');
+
+ foreach ($includePaths as $includePath) {
+ $file = $includePath . DIRECTORY_SEPARATOR . $suiteClassFile;
+
+ if (file_exists($file)) {
+ $suiteClassFile = $file;
+ break;
+ }
+ }
+ }
+
+ PHPUnit2_Util_Fileloader::checkAndLoad($suiteClassFile);
+ }
+
+ if (class_exists($suiteClassName)) {
+ return new ReflectionClass($suiteClassName);
+ } else {
+ throw new Exception(
+ sprintf(
+ 'Class %s could not be found in %s.',
+
+ $suiteClassName,
+ $suiteClassFile
+ )
+ );
+ }
+ }
+
+ /**
+ * @param ReflectionClass $aClass
+ * @return ReflectionClass
+ * @access public
+ */
+ public function reload(ReflectionClass $aClass) {
+ return $aClass;
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Runner/TestCollector.php b/buildscripts/PHPUnit2/Runner/TestCollector.php
new file mode 100644
index 00000000..38a9ce81
--- /dev/null
+++ b/buildscripts/PHPUnit2/Runner/TestCollector.php
@@ -0,0 +1,77 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: TestCollector.php,v 1.7.2.2 2005/12/17 16:04:56 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+/**
+ * Collects Test class names to be presented
+ * by the TestSelector.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Interface available since Release 2.0.0
+ */
+interface PHPUnit2_Runner_TestCollector {
+ /**
+ * @return array
+ * @access public
+ */
+ public function collectTests();
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Runner/TestSuiteLoader.php b/buildscripts/PHPUnit2/Runner/TestSuiteLoader.php
new file mode 100644
index 00000000..711a03d2
--- /dev/null
+++ b/buildscripts/PHPUnit2/Runner/TestSuiteLoader.php
@@ -0,0 +1,85 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: TestSuiteLoader.php,v 1.11.2.2 2005/12/17 16:04:56 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+/**
+ * An interface to define how a test suite should be loaded.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Interface available since Release 2.0.0
+ */
+interface PHPUnit2_Runner_TestSuiteLoader {
+ /**
+ * @param string $suiteClassName
+ * @param string $suiteClassFile
+ * @return ReflectionClass
+ * @access public
+ */
+ public function load($suiteClassName, $suiteClassFile = '');
+
+ /**
+ * @param ReflectionClass $aClass
+ * @return ReflectionClass
+ * @access public
+ */
+ public function reload(ReflectionClass $aClass);
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Runner/Version.php b/buildscripts/PHPUnit2/Runner/Version.php
new file mode 100644
index 00000000..5a0f7785
--- /dev/null
+++ b/buildscripts/PHPUnit2/Runner/Version.php
@@ -0,0 +1,90 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: Version.php,v 1.7.2.2 2005/12/17 16:04:56 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+/**
+ * This class defines the current version of PHPUnit.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.0.0
+ */
+class PHPUnit2_Runner_Version {
+ /**
+ * Returns the current version of PHPUnit.
+ *
+ * @return string
+ * @access public
+ * @static
+ */
+ public static function id() {
+ return '@package_version@';
+ }
+
+ /**
+ * @return string
+ * @access public
+ * @static
+ */
+ public static function getVersionString() {
+ return 'PHPUnit @package_version@ by Sebastian Bergmann.';
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/TextUI/ResultPrinter.php b/buildscripts/PHPUnit2/TextUI/ResultPrinter.php
new file mode 100644
index 00000000..32d3e667
--- /dev/null
+++ b/buildscripts/PHPUnit2/TextUI/ResultPrinter.php
@@ -0,0 +1,356 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: ResultPrinter.php,v 1.20.2.5 2005/12/17 16:04:57 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+require_once 'PHPUnit2/Framework/TestListener.php';
+require_once 'PHPUnit2/Framework/TestFailure.php';
+require_once 'PHPUnit2/Util/Filter.php';
+require_once 'PHPUnit2/Util/Printer.php';
+
+/**
+ * Prints the result of a TextUI TestRunner run.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.0.0
+ */
+class PHPUnit2_TextUI_ResultPrinter extends PHPUnit2_Util_Printer implements PHPUnit2_Framework_TestListener {
+ /**
+ * @var integer
+ * @access private
+ */
+ private $column = 0;
+
+ /**
+ * @var boolean
+ * @access private
+ */
+ private $lastTestFailed = FALSE;
+
+ /**
+ * @param PHPUnit2_Framework_TestResult $result
+ * @param float $runTime
+ * @access public
+ */
+ public function printResult(PHPUnit2_Framework_TestResult $result, $timeElapsed) {
+ $this->printHeader($timeElapsed);
+ $this->printErrors($result);
+ $this->printFailures($result);
+ $this->printIncompletes($result);
+ $this->printFooter($result);
+ }
+
+ /**
+ * @param array $defects
+ * @param integer $count
+ * @param string $type
+ * @access protected
+ */
+ protected function printDefects($defects, $count, $type) {
+ if ($count == 0) {
+ return;
+ }
+
+ $this->write(
+ sprintf(
+ "There %s %d %s%s:\n",
+
+ ($count == 1) ? 'was' : 'were',
+ $count,
+ $type,
+ ($count == 1) ? '' : 's'
+ )
+ );
+
+ $i = 1;
+
+ foreach ($defects as $defect) {
+ $this->printDefect($defect, $i++);
+ }
+ }
+
+ /**
+ * @param PHPUnit2_Framework_TestFailure $defect
+ * @param integer $count
+ * @access protected
+ */
+ protected function printDefect(PHPUnit2_Framework_TestFailure $defect, $count) {
+ $this->printDefectHeader($defect, $count);
+ $this->printDefectTrace($defect);
+ }
+
+ /**
+ * @param PHPUnit2_Framework_TestFailure $defect
+ * @param integer $count
+ * @access protected
+ */
+ protected function printDefectHeader(PHPUnit2_Framework_TestFailure $defect, $count) {
+ $this->write(
+ sprintf(
+ "%d) %s\n",
+
+ $count,
+ $defect->failedTest()->toString()
+ )
+ );
+ }
+
+ /**
+ * @param PHPUnit2_Framework_TestFailure $defect
+ * @access protected
+ */
+ protected function printDefectTrace(PHPUnit2_Framework_TestFailure $defect) {
+ $e = $defect->thrownException();
+ $message = method_exists($e, 'toString') ? $e->toString() : $e->getMessage();
+
+ $this->write($message . "\n");
+
+ $this->write(
+ PHPUnit2_Util_Filter::getFilteredStacktrace(
+ $defect->thrownException()
+ )
+ );
+ }
+
+ /**
+ * @param PHPUnit2_Framework_TestResult $result
+ * @access protected
+ */
+ protected function printErrors(PHPUnit2_Framework_TestResult $result) {
+ $this->printDefects($result->errors(), $result->errorCount(), 'error');
+ }
+
+ /**
+ * @param PHPUnit2_Framework_TestResult $result
+ * @access protected
+ */
+ protected function printFailures(PHPUnit2_Framework_TestResult $result) {
+ $this->printDefects($result->failures(), $result->failureCount(), 'failure');
+ }
+
+ /**
+ * @param PHPUnit2_Framework_TestResult $result
+ * @access protected
+ */
+ protected function printIncompletes(PHPUnit2_Framework_TestResult $result) {
+ $this->printDefects($result->notImplemented(), $result->notImplementedCount(), 'incomplete test case');
+ }
+
+ /**
+ * @param float $timeElapsed
+ * @access protected
+ */
+ protected function printHeader($timeElapsed) {
+ $this->write(
+ sprintf(
+ "\n\nTime: %s\n",
+
+ $timeElapsed
+ )
+ );
+ }
+
+ /**
+ * @param PHPUnit2_Framework_TestResult $result
+ * @access protected
+ */
+ protected function printFooter(PHPUnit2_Framework_TestResult $result) {
+ if ($result->allCompletlyImplemented() &&
+ $result->wasSuccessful()) {
+ $this->write(
+ sprintf(
+ "\nOK (%d test%s)\n",
+
+ $result->runCount(),
+ ($result->runCount() == 1) ? '' : 's'
+ )
+ );
+ }
+
+ else if (!$result->allCompletlyImplemented() &&
+ $result->wasSuccessful()) {
+ $this->write(
+ sprintf(
+ "\nOK, but incomplete test cases!!!\nTests run: %d, Incomplete Tests: %d.\n",
+
+ $result->runCount(),
+ $result->notImplementedCount()
+ )
+ );
+ }
+
+ else {
+ $this->write(
+ sprintf(
+ "\nFAILURES!!!\nTests run: %d, Failures: %d, Errors: %d, Incomplete Tests: %d.\n",
+
+ $result->runCount(),
+ $result->failureCount(),
+ $result->errorCount(),
+ $result->notImplementedCount()
+ )
+ );
+ }
+ }
+
+ /**
+ * @access public
+ */
+ public function printWaitPrompt() {
+ $this->write("\n<RETURN> to continue\n");
+ }
+
+ /**
+ * An error occurred.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @param Exception $e
+ * @access public
+ */
+ public function addError(PHPUnit2_Framework_Test $test, Exception $e) {
+ $this->write('E');
+ $this->nextColumn();
+
+ $this->lastTestFailed = TRUE;
+ }
+
+ /**
+ * A failure occurred.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @param PHPUnit2_Framework_AssertionFailedError $e
+ * @access public
+ */
+ public function addFailure(PHPUnit2_Framework_Test $test, PHPUnit2_Framework_AssertionFailedError $e) {
+ $this->write('F');
+ $this->nextColumn();
+
+ $this->lastTestFailed = TRUE;
+ }
+
+ /**
+ * Incomplete test.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @param Exception $e
+ * @access public
+ */
+ public function addIncompleteTest(PHPUnit2_Framework_Test $test, Exception $e) {
+ $this->write('I');
+ $this->nextColumn();
+
+ $this->lastTestFailed = TRUE;
+ }
+
+ /**
+ * A testsuite started.
+ *
+ * @param PHPUnit2_Framework_TestSuite $suite
+ * @access public
+ * @since Method available since Release 2.2.0
+ */
+ public function startTestSuite(PHPUnit2_Framework_TestSuite $suite) {
+ }
+
+ /**
+ * A testsuite ended.
+ *
+ * @param PHPUnit2_Framework_TestSuite $suite
+ * @access public
+ * @since Method available since Release 2.2.0
+ */
+ public function endTestSuite(PHPUnit2_Framework_TestSuite $suite) {
+ }
+
+ /**
+ * A test started.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @access public
+ */
+ public function startTest(PHPUnit2_Framework_Test $test) {
+ }
+
+ /**
+ * A test ended.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @access public
+ */
+ public function endTest(PHPUnit2_Framework_Test $test) {
+ if (!$this->lastTestFailed) {
+ $this->write('.');
+ $this->nextColumn();
+ }
+
+ $this->lastTestFailed = FALSE;
+ }
+
+ /**
+ * @access protected
+ */
+ protected function nextColumn() {
+ if ($this->column++ >= 40) {
+ $this->column = 0;
+ $this->write("\n");
+ }
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/TextUI/TestRunner.php b/buildscripts/PHPUnit2/TextUI/TestRunner.php
new file mode 100644
index 00000000..63639a24
--- /dev/null
+++ b/buildscripts/PHPUnit2/TextUI/TestRunner.php
@@ -0,0 +1,622 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: TestRunner.php,v 1.64.2.5 2005/12/17 16:04:58 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+if (!defined('PHPUnit2_MAIN_METHOD')) {
+ define('PHPUnit2_MAIN_METHOD', 'PHPUnit2_TextUI_TestRunner::main');
+}
+
+require_once 'PHPUnit2/Framework/TestSuite.php';
+require_once 'PHPUnit2/Runner/Version.php';
+require_once 'PHPUnit2/Runner/BaseTestRunner.php';
+require_once 'PHPUnit2/TextUI/ResultPrinter.php';
+require_once 'PHPUnit2/Util/Fileloader.php';
+
+require_once 'Console/Getopt.php';
+require_once 'Benchmark/Timer.php';
+
+/**
+ * A TestRunner for the Command Line Interface (CLI)
+ * PHP SAPI Module.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.0.0
+ */
+class PHPUnit2_TextUI_TestRunner extends PHPUnit2_Runner_BaseTestRunner {
+ const SUCCESS_EXIT = 0;
+ const FAILURE_EXIT = 1;
+ const EXCEPTION_EXIT = 2;
+
+ /**
+ * @var PHPUnit2_Runner_TestSuiteLoader
+ * @access private
+ */
+ private $loader = NULL;
+
+ /**
+ * @var PHPUnit2_TextUI_ResultPrinter
+ * @access private
+ */
+ private $printer = NULL;
+
+ /**
+ * @var boolean
+ * @access private
+ * @static
+ */
+ private static $versionStringPrinted = FALSE;
+
+ /**
+ * @access public
+ * @static
+ */
+ public static function main() {
+ $aTestRunner = new PHPUnit2_TextUI_TestRunner;
+
+ try {
+ $result = $aTestRunner->start($_SERVER['argv']);
+
+ if (!$result->wasSuccessful()) {
+ exit(self::FAILURE_EXIT);
+ }
+
+ exit(self::SUCCESS_EXIT);
+ }
+
+ catch (Exception $e) {
+ self::printVersionString();
+ print $e->getMessage();
+ exit(self::EXCEPTION_EXIT);
+ }
+ }
+
+ /**
+ * @param array $arguments
+ * @throws Exception
+ * @access protected
+ */
+ protected function start($arguments) {
+ $coverageDataFile = FALSE;
+ $coverageHTMLFile = FALSE;
+ $coverageTextFile = FALSE;
+ $testdoxHTMLFile = FALSE;
+ $testdoxTextFile = FALSE;
+ $xmlLogfile = FALSE;
+ $wait = FALSE;
+
+ $possibleOptions = array(
+ 'help',
+ 'loader=',
+ 'log-xml=',
+ 'skeleton',
+ 'testdox-html=',
+ 'testdox-text=',
+ 'version',
+ 'wait'
+ );
+
+ if (extension_loaded('xdebug')) {
+ $possibleOptions[] = 'coverage-data=';
+ $possibleOptions[] = 'coverage-html=';
+ $possibleOptions[] = 'coverage-text=';
+ }
+
+ $options = Console_Getopt::getopt(
+ $arguments,
+ '',
+ $possibleOptions
+ );
+
+ if (PEAR::isError($options)) {
+ $this->showError($options->getMessage());
+ }
+
+ $test = isset($options[1][0]) ? $options[1][0] : FALSE;
+ $testFile = isset($options[1][1]) ? $options[1][1] : $test . '.php';
+
+ foreach ($options[0] as $option) {
+ switch ($option[0]) {
+ case '--coverage-data': {
+ $coverageDataFile = $option[1];
+ }
+ break;
+
+ case '--coverage-html': {
+ $coverageHTMLFile = $option[1];
+ }
+ break;
+
+ case '--coverage-text': {
+ $coverageTextFile = $option[1];
+ }
+ break;
+
+ case '--help': {
+ $this->showHelp();
+ exit(self::SUCCESS_EXIT);
+ }
+ break;
+
+ case '--testdox-html': {
+ $testdoxHTMLFile = $option[1];
+ }
+ break;
+
+ case '--testdox-text': {
+ $testdoxTextFile = $option[1];
+ }
+ break;
+
+ case '--loader': {
+ if (!class_exists($option[1])) {
+ PHPUnit2_Util_Fileloader::checkAndLoad(
+ str_replace('_', '/', $option[1]) . '.php'
+ );
+ }
+
+ if (class_exists($option[1])) {
+ $class = new ReflectionClass($option[1]);
+
+ if ($class->implementsInterface('PHPUnit2_Runner_TestSuiteLoader') &&
+ $class->isInstantiable()) {
+ $this->loader = $class->newInstance();
+ }
+ }
+
+ if ($this->loader === NULL) {
+ $this->showError(
+ sprintf(
+ 'Could not use "%s" as loader.',
+
+ $option[1]
+ )
+ );
+ }
+ }
+ break;
+
+ case '--log-xml': {
+ $xmlLogfile = $option[1];
+ }
+ break;
+
+ case '--skeleton': {
+ if ($test !== FALSE) {
+ self::printVersionString();
+
+ try {
+ require_once 'PHPUnit2/Util/Skeleton.php';
+
+ $skeleton = new PHPUnit2_Util_Skeleton($test, $testFile);
+ $skeleton->write();
+ }
+
+ catch (Exception $e) {
+ print $e->getMessage() . "\n";
+
+ printf(
+ "Could not write test class skeleton for %s to %s.\n",
+ $test,
+ $test . 'Test.php'
+ );
+
+ exit(self::FAILURE_EXIT);
+ }
+
+ printf(
+ "Wrote test class skeleton for %s to %s.\n",
+ $test,
+ $test . 'Test.php'
+ );
+
+ exit(self::SUCCESS_EXIT);
+ }
+ }
+ break;
+
+ case '--version': {
+ self::printVersionString();
+ exit(self::SUCCESS_EXIT);
+ }
+ break;
+
+ case '--wait': {
+ $wait = TRUE;
+ }
+ break;
+ }
+ }
+
+ if ($test === FALSE) {
+ $this->showHelp();
+
+ exit(self::SUCCESS_EXIT);
+ }
+
+ try {
+ return $this->doRun(
+ $this->getTest($test, $testFile),
+ $coverageDataFile,
+ $coverageHTMLFile,
+ $coverageTextFile,
+ $testdoxHTMLFile,
+ $testdoxTextFile,
+ $xmlLogfile,
+ $wait
+ );
+ }
+
+ catch (Exception $e) {
+ throw new Exception(
+ 'Could not create and run test suite: ' . $e->getMessage()
+ );
+ }
+ }
+
+ /**
+ * @param mixed $test
+ * @param mixed $coverageDataFile
+ * @param mixed $testdoxHTMLFile
+ * @param mixed $testdoxTextFile
+ * @param mixed $xmlLogfile
+ * @param boolean $wait
+ * @access public
+ * @static
+ */
+ public static function run($test, $coverageDataFile = FALSE, $coverageHTMLFile = FALSE, $coverageTextFile = FALSE, $testdoxHTMLFile = FALSE, $testdoxTextFile = FALSE, $xmlLogfile = FALSE, $wait = FALSE) {
+ if ($test instanceof ReflectionClass) {
+ $test = new PHPUnit2_Framework_TestSuite($test);
+ }
+
+ if ($test instanceof PHPUnit2_Framework_Test) {
+ $aTestRunner = new PHPUnit2_TextUI_TestRunner;
+
+ return $aTestRunner->doRun(
+ $test,
+ $coverageDataFile,
+ $coverageHTMLFile,
+ $coverageTextFile,
+ $testdoxHTMLFile,
+ $testdoxTextFile,
+ $xmlLogfile,
+ $wait
+ );
+ }
+ }
+
+ /**
+ * Runs a single test and waits until the user types RETURN.
+ *
+ * @param PHPUnit2_Framework_Test $suite
+ * @access public
+ * @static
+ */
+ public static function runAndWait(PHPUnit2_Framework_Test $suite) {
+ $aTestRunner = new PHPUnit2_TextUI_TestRunner;
+
+ $aTestRunner->doRun(
+ $suite,
+ FALSE,
+ FALSE,
+ FALSE,
+ FALSE,
+ FALSE,
+ FALSE,
+ TRUE
+ );
+ }
+
+ /**
+ * @return PHPUnit2_Framework_TestResult
+ * @access protected
+ */
+ protected function createTestResult() {
+ return new PHPUnit2_Framework_TestResult;
+ }
+
+ /**
+ * @param PHPUnit2_Framework_Test $suite
+ * @param mixed $coverageDataFile
+ * @param mixed $coverageHTMLFile
+ * @param mixed $coverageTextFile
+ * @param mixed $testdoxHTMLFile
+ * @param mixed $testdoxTextFile
+ * @param mixed $xmlLogfile
+ * @param boolean $wait
+ * @return PHPUnit2_Framework_TestResult
+ * @access public
+ */
+ public function doRun(PHPUnit2_Framework_Test $suite, $coverageDataFile = FALSE, $coverageHTMLFile = FALSE, $coverageTextFile = FALSE, $testdoxHTMLFile = FALSE, $testdoxTextFile = FALSE, $xmlLogfile = FALSE, $wait = FALSE) {
+ $result = $this->createTestResult();
+ $timer = new Benchmark_Timer;
+
+ if ($this->printer === NULL) {
+ $this->printer = new PHPUnit2_TextUI_ResultPrinter;
+ }
+
+ $this->printer->write(
+ PHPUnit2_Runner_Version::getVersionString() . "\n\n"
+ );
+
+ $result->addListener($this->printer);
+
+ if ($testdoxHTMLFile !== FALSE || $testdoxTextFile !== FALSE) {
+ require_once 'PHPUnit2/Util/TestDox/ResultPrinter.php';
+
+ if ($testdoxHTMLFile !== FALSE) {
+ $result->addListener(
+ PHPUnit2_Util_TestDox_ResultPrinter::factory(
+ 'HTML',
+ $testdoxHTMLFile
+ )
+ );
+ }
+
+ if ($testdoxTextFile !== FALSE) {
+ $result->addListener(
+ PHPUnit2_Util_TestDox_ResultPrinter::factory(
+ 'Text',
+ $testdoxTextFile
+ )
+ );
+ }
+ }
+
+ if ($xmlLogfile !== FALSE) {
+ require_once 'PHPUnit2/Util/Log/XML.php';
+
+ $result->addListener(
+ new PHPUnit2_Util_Log_XML($xmlLogfile)
+ );
+ }
+
+ if ($coverageDataFile !== FALSE ||
+ $coverageHTMLFile !== FALSE ||
+ $coverageTextFile !== FALSE) {
+ $result->collectCodeCoverageInformation(TRUE);
+ }
+
+ $timer->start();
+ $suite->run($result);
+ $timer->stop();
+ $timeElapsed = $timer->timeElapsed();
+
+ $this->pause($wait);
+
+ $this->printer->printResult($result, $timeElapsed);
+
+ $this->handleCodeCoverageInformation(
+ $result,
+ $coverageDataFile,
+ $coverageHTMLFile,
+ $coverageTextFile
+ );
+
+ return $result;
+ }
+
+ /**
+ * Returns the loader to be used.
+ *
+ * @return PHPUnit2_Runner_TestSuiteLoader
+ * @access public
+ * @since Method available since Release 2.2.0
+ */
+ public function getLoader() {
+ if ($this->loader === NULL) {
+ $this->loader = new PHPUnit2_Runner_StandardTestSuiteLoader;
+ }
+
+ return $this->loader;
+ }
+
+ /**
+ * @param PHPUnit2_Framework_TestResult $result
+ * @param mixed $coverageDataFile
+ * @param mixed $coverageHTMLFile
+ * @param mixed $coverageTextFile
+ * @access protected
+ * @since Method available since Release 2.1.0
+ */
+ protected function handleCodeCoverageInformation(PHPUnit2_Framework_TestResult $result, $coverageDataFile, $coverageHTMLFile, $coverageTextFile) {
+ if ($coverageDataFile !== FALSE &&
+ $fp = fopen($coverageDataFile, 'w')) {
+ fputs($fp, serialize($result->getCodeCoverageInformation()));
+ fclose($fp);
+ }
+
+ if ($coverageHTMLFile !== FALSE || $coverageTextFile !== FALSE) {
+ require_once 'PHPUnit2/Util/CodeCoverage/Renderer.php';
+
+ if ($coverageHTMLFile !== FALSE) {
+ $renderer = PHPUnit2_Util_CodeCoverage_Renderer::factory(
+ 'HTML',
+ $result->getCodeCoverageInformation()
+ );
+
+ $renderer->renderToFile($coverageHTMLFile);
+ }
+
+ if ($coverageTextFile !== FALSE) {
+ $renderer = PHPUnit2_Util_CodeCoverage_Renderer::factory(
+ 'Text',
+ $result->getCodeCoverageInformation()
+ );
+
+ $renderer->renderToFile($coverageTextFile);
+ }
+ }
+ }
+
+ /**
+ * @access public
+ */
+ public function showError($message) {
+ self::printVersionString();
+ print $message . "\n";
+
+ exit(self::FAILURE_EXIT);
+ }
+
+ /**
+ * @access public
+ */
+ public function showHelp() {
+ self::printVersionString();
+ print "Usage: phpunit [switches] UnitTest [UnitTest.php]\n";
+
+ if (extension_loaded('xdebug')) {
+ print " --coverage-data <file> Write Code Coverage data in raw format to file.\n" .
+ " --coverage-html <file> Write Code Coverage data in HTML format to file.\n" .
+ " --coverage-text <file> Write Code Coverage data in text format to file.\n\n";
+ }
+
+ print " --testdox-html <file> Write agile documentation in HTML format to file.\n" .
+ " --testdox-text <file> Write agile documentation in Text format to file.\n" .
+ " --log-xml <file> Log test progress in XML format to file.\n\n";
+
+ print " --loader <loader> TestSuiteLoader implementation to use.\n\n" .
+ " --skeleton Generate skeleton UnitTest class for Unit in Unit.php.\n\n" .
+ " --wait Waits for a keystroke after each test.\n\n" .
+ " --help Prints this usage information.\n" .
+ " --version Prints the version and exits.\n";
+ }
+
+ /**
+ * @param boolean $wait
+ * @access protected
+ */
+ protected function pause($wait) {
+ if (!$wait) {
+ return;
+ }
+
+ $this->printer->printWaitPrompt();
+
+ fgets(STDIN);
+ }
+
+ /**
+ * @param PHPUnit2_TextUI_ResultPrinter $resultPrinter
+ * @access public
+ */
+ public function setPrinter(PHPUnit2_TextUI_ResultPrinter $resultPrinter) {
+ $this->printer = $resultPrinter;
+ }
+
+ /**
+ * A test started.
+ *
+ * @param string $testName
+ * @access public
+ */
+ public function testStarted($testName) {
+ }
+
+ /**
+ * A test ended.
+ *
+ * @param string $testName
+ * @access public
+ */
+ public function testEnded($testName) {
+ }
+
+ /**
+ * A test failed.
+ *
+ * @param integer $status
+ * @param PHPUnit2_Framework_Test $test
+ * @param PHPUnit2_Framework_AssertionFailedError $e
+ * @access public
+ */
+ public function testFailed($status, PHPUnit2_Framework_Test $test, PHPUnit2_Framework_AssertionFailedError $e) {
+ }
+
+ /**
+ * Override to define how to handle a failed loading of
+ * a test suite.
+ *
+ * @param string $message
+ * @access protected
+ */
+ protected function runFailed($message) {
+ self::printVersionString();
+ print $message;
+ exit(self::FAILURE_EXIT);
+ }
+
+ /**
+ * @access private
+ * @since Method available since Release 2.2.0
+ */
+ private static function printVersionString() {
+ if (!self::$versionStringPrinted) {
+ print PHPUnit2_Runner_Version::getVersionString() . "\n\n";
+ self::$versionStringPrinted = TRUE;
+ }
+ }
+}
+
+if (PHPUnit2_MAIN_METHOD == 'PHPUnit2_TextUI_TestRunner::main') {
+ PHPUnit2_TextUI_TestRunner::main();
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Util/CodeCoverage/Renderer.php b/buildscripts/PHPUnit2/Util/CodeCoverage/Renderer.php
new file mode 100644
index 00000000..cbcdda51
--- /dev/null
+++ b/buildscripts/PHPUnit2/Util/CodeCoverage/Renderer.php
@@ -0,0 +1,225 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: Renderer.php,v 1.8.2.7 2006/02/25 17:02:23 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.3.0
+ */
+
+/**
+ * Abstract base class for Code Coverage renderers.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.1.0
+ * @abstract
+ */
+abstract class PHPUnit2_Util_CodeCoverage_Renderer {
+ /**
+ * @var array
+ * @access protected
+ */
+ protected $codeCoverageInformation;
+
+ /**
+ * Constructor.
+ *
+ * @param array $codeCoverageInformation
+ * @access protected
+ */
+ protected function __construct($codeCoverageInformation) {
+ $this->codeCoverageInformation = $codeCoverageInformation;
+ }
+
+ /**
+ * Abstract Factory.
+ *
+ * @param string $rendererName
+ * @param array $codeCoverageInformation
+ * @throws Exception
+ * @access public
+ */
+ public function factory($rendererName, $codeCoverageInformation) {
+ require_once 'PHPUnit2/Util/CodeCoverage/Renderer/' . $rendererName . '.php';
+
+ $class = 'PHPUnit2_Util_CodeCoverage_Renderer_' . $rendererName;
+ return new $class($codeCoverageInformation);
+ }
+
+ /**
+ * Visualizes the result array of
+ * PHPUnit2_Framework_TestResult::getCodeCoverageInformation().
+ *
+ * @return string
+ * @access public
+ * @final
+ */
+ public final function render() {
+ $buffer = $this->header();
+
+ foreach ($this->getSummary() as $sourceFile => $executedLines) {
+ if (file_exists($sourceFile)) {
+ $buffer .= $this->startSourceFile($sourceFile);
+ $buffer .= $this->renderSourceFile(file($sourceFile), $executedLines);
+ $buffer .= $this->endSourceFile($sourceFile);
+ }
+ }
+
+ return $buffer . $this->footer();
+ }
+
+ /**
+ * Visualizes the result array of
+ * PHPUnit2_Framework_TestResult::getCodeCoverageInformation()
+ * and writes it to a file.
+ *
+ * @param string $filename
+ * @access public
+ * @since Method available since Release 2.2.0
+ */
+ public function renderToFile($filename) {
+ if ($fp = fopen($filename, 'w')) {
+ fputs(
+ $fp,
+ $this->render()
+ );
+
+ fclose($fp);
+ }
+ }
+
+ /**
+ * Returns summarized Code Coverage data.
+ *
+ * Format of the result array:
+ *
+ * <code>
+ * array(
+ * "/tested/code.php" => array(
+ * linenumber => flag
+ * )
+ * )
+ * </code>
+ *
+ * flag > 0: line was executed.
+ * flag < 0: line is executable but was not executed.
+ *
+ * @return array
+ * @access protected
+ * @since Method available since Release 2.2.0
+ */
+ protected function getSummary() {
+ $summary = array();
+
+ foreach ($this->codeCoverageInformation as $testCaseName => $sourceFiles) {
+ foreach ($sourceFiles as $sourceFile => $executedLines) {
+ foreach ($executedLines as $lineNumber => $flag) {
+ if (!isset($summary[$sourceFile][$lineNumber])) {
+ $summary[$sourceFile][$lineNumber] = $flag;
+ }
+
+ else if ($flag > 0) {
+ $summary[$sourceFile][$lineNumber] = $flag;
+ }
+ }
+ }
+ }
+
+ return $summary;
+ }
+
+ /**
+ * @return string
+ * @access protected
+ * @since Method available since Release 2.1.1
+ */
+ protected function header() {
+ }
+
+ /**
+ * @return string
+ * @access protected
+ * @since Method available since Release 2.1.1
+ */
+ protected function footer() {
+ }
+
+ /**
+ * @param string $sourceFile
+ * @return string
+ * @access protected
+ */
+ protected function startSourceFile($sourceFile) {
+ }
+
+ /**
+ * @param string $sourceFile
+ * @return string
+ * @access protected
+ */
+ protected function endSourceFile($sourceFile) {
+ }
+
+ /**
+ * @param array $codeLines
+ * @param array $executedLines
+ * @return string
+ * @access protected
+ * @abstract
+ */
+ abstract protected function renderSourceFile($codeLines, $executedLines);
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Util/CodeCoverage/Renderer/HTML.php b/buildscripts/PHPUnit2/Util/CodeCoverage/Renderer/HTML.php
new file mode 100644
index 00000000..66fc4d13
--- /dev/null
+++ b/buildscripts/PHPUnit2/Util/CodeCoverage/Renderer/HTML.php
@@ -0,0 +1,191 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: HTML.php,v 1.7.2.3 2005/12/17 16:04:58 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.3.0
+ */
+
+require_once 'PHPUnit2/Util/CodeCoverage/Renderer.php';
+
+/**
+ * Renders Code Coverage information in HTML format.
+ *
+ * Formatting of the generated HTML can be achieved through
+ * CSS (codecoverage.css).
+ *
+ * Example
+ *
+ * <code>
+ * td.ccLineNumber, td.ccCoveredLine, td.ccUncoveredLine, td.ccNotExecutableLine {
+ * font-family: monospace;
+ * white-space: pre;
+ * }
+ *
+ * td.ccLineNumber, td.ccCoveredLine {
+ * background-color: #aaaaaa;
+ * }
+ *
+ * td.ccNotExecutableLine {
+ * color: #aaaaaa;
+ * }
+ * </code>
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.1.0
+ */
+class PHPUnit2_Util_CodeCoverage_Renderer_HTML extends PHPUnit2_Util_CodeCoverage_Renderer {
+ const pageHeader =
+'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <link href="codecoverage.css" type="text/css" rel="stylesheet" />
+ </head>
+ <body>
+';
+
+ const pageFooter =
+' </body>
+</html>
+';
+
+ const sourceFileHeader =
+' <table style="border: 1px solid black" cellspacing="0" cellpadding="0" width="100%">
+';
+
+ const sourceFileFooter =
+' </table>
+';
+
+ const codeLine =
+' <tr><td class="ccLineNumber">%s</td><td class="%s">%s</td></tr>
+';
+
+ /**
+ * @return string
+ * @access protected
+ * @since Method available since Release 2.1.1
+ */
+ protected function header() {
+ return self::pageHeader;
+ }
+
+ /**
+ * @return string
+ * @access protected
+ * @since Method available since Release 2.1.1
+ */
+ protected function footer() {
+ return self::pageFooter;
+ }
+
+ /**
+ * @param string $sourceFile
+ * @return string
+ * @access protected
+ */
+ protected function startSourceFile($sourceFile) {
+ return self::sourceFileHeader;
+ }
+
+ /**
+ * @param string $sourceFile
+ * @return string
+ * @access protected
+ */
+ protected function endSourceFile($sourceFile) {
+ return self::sourceFileFooter;
+ }
+
+ /**
+ * @param array $codeLines
+ * @param array $executedLines
+ * @return string
+ * @access protected
+ */
+ protected function renderSourceFile($codeLines, $executedLines) {
+ $buffer = '';
+ $line = 1;
+
+ foreach ($codeLines as $codeLine) {
+ $lineStyle = 'ccNotExecutableLine';
+
+ if (isset($executedLines[$line])) {
+ if ($executedLines[$line] > 0) {
+ $lineStyle = 'ccCoveredLine';
+ } else {
+ $lineStyle = 'ccUncoveredLine';
+ }
+ }
+
+ $buffer .= sprintf(
+ self::codeLine,
+
+ $line,
+ $lineStyle,
+ htmlspecialchars(rtrim($codeLine))
+ );
+
+ $line++;
+ }
+
+ return $buffer;
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Util/CodeCoverage/Renderer/Text.php b/buildscripts/PHPUnit2/Util/CodeCoverage/Renderer/Text.php
new file mode 100644
index 00000000..6b083692
--- /dev/null
+++ b/buildscripts/PHPUnit2/Util/CodeCoverage/Renderer/Text.php
@@ -0,0 +1,125 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: Text.php,v 1.6.2.3 2005/12/17 16:04:58 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.3.0
+ */
+
+require_once 'PHPUnit2/Util/CodeCoverage/Renderer.php';
+
+/**
+ * Renders Code Coverage information in text format.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.1.0
+ */
+class PHPUnit2_Util_CodeCoverage_Renderer_Text extends PHPUnit2_Util_CodeCoverage_Renderer {
+ /**
+ * @param string $sourceFile
+ * @return string
+ * @access protected
+ */
+ protected function startSourceFile($sourceFile) {
+ return ' ' . $sourceFile . "\n\n";
+ }
+
+ /**
+ * @param string $sourceFile
+ * @return string
+ * @access protected
+ */
+ protected function endSourceFile($sourceFile) {
+ return "\n";
+ }
+
+ /**
+ * @param array $codeLines
+ * @param array $executedLines
+ * @return string
+ * @access protected
+ */
+ protected function renderSourceFile($codeLines, $executedLines) {
+ $buffer = '';
+ $line = 1;
+
+ foreach ($codeLines as $codeLine) {
+ $flag = '-';
+
+ if (isset($executedLines[$line])) {
+ if ($executedLines[$line] > 0) {
+ $flag = '+';
+ } else {
+ $flag = '#';
+ }
+ }
+
+ $buffer .= sprintf(
+ ' %4u|%s| %s',
+
+ $line,
+ $flag,
+ $codeLine
+ );
+
+ $line++;
+ }
+
+ return $buffer;
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Util/ErrorHandler.php b/buildscripts/PHPUnit2/Util/ErrorHandler.php
new file mode 100644
index 00000000..ee724ffe
--- /dev/null
+++ b/buildscripts/PHPUnit2/Util/ErrorHandler.php
@@ -0,0 +1,77 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: ErrorHandler.php,v 1.1.2.2 2005/12/17 16:04:58 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.3.0
+ */
+
+/**
+ * @param integer $errno
+ * @param string $errstr
+ * @param string $errfile
+ * @param integer $errline
+ * @throws PHPUnit2_Framework_Error
+ * @since Function available since Release 2.3.0
+ */
+function PHPUnit2_Util_ErrorHandler($errno, $errstr, $errfile, $errline) {
+ $trace = debug_backtrace();
+ array_shift($trace);
+
+ throw new PHPUnit2_Framework_Error(
+ $errstr,
+ $errno,
+ $errfile,
+ $errline,
+ $trace
+ );
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Util/Fileloader.php b/buildscripts/PHPUnit2/Util/Fileloader.php
new file mode 100644
index 00000000..bdcd49ed
--- /dev/null
+++ b/buildscripts/PHPUnit2/Util/Fileloader.php
@@ -0,0 +1,109 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: Fileloader.php,v 1.1.2.6 2005/12/19 05:43:56 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.3.0
+ */
+
+/**
+ *
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.3.0
+ */
+class PHPUnit2_Util_Fileloader {
+ /**
+ * Checks if a PHP sourcefile is readable and contains no syntax errors.
+ * If that is the case, the sourcefile is loaded through include_once().
+ *
+ * @param string $filename
+ * @throws Exception
+ * @access public
+ * @static
+ */
+ public static function checkAndLoad($filename) {
+ if (!is_readable($filename)) {
+ $filename = './' . $filename;
+ }
+
+ if (!is_readable($filename)) {
+ throw new Exception(
+ sprintf(
+ '%s could not be found or is not readable.',
+
+ str_replace('./', '', $filename)
+ )
+ );
+ }
+
+ $output = shell_exec('php -l ' . escapeshellarg($filename));
+
+ if (strpos($output, 'No syntax errors detected in') === FALSE) {
+ throw new Exception(
+ sprintf(
+ 'Syntax error in %s.',
+
+ str_replace('./', '', $filename)
+ )
+ );
+ }
+
+ include_once $filename;
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Util/Filter.php b/buildscripts/PHPUnit2/Util/Filter.php
new file mode 100644
index 00000000..70d055fd
--- /dev/null
+++ b/buildscripts/PHPUnit2/Util/Filter.php
@@ -0,0 +1,263 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: Filter.php,v 1.32.2.5 2005/12/17 16:04:58 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+/**
+ * Utility class for code filtering.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.0.0
+ */
+class PHPUnit2_Util_Filter {
+ /**
+ * Source files that are to be filtered.
+ *
+ * @var array
+ * @access protected
+ * @static
+ */
+ protected static $filteredFiles = array(
+ 'PHPUnit2/Extensions/ExceptionTestCase.php',
+ 'PHPUnit2/Extensions/PerformanceTestCase.php',
+ 'PHPUnit2/Extensions/RepeatedTest.php',
+ 'PHPUnit2/Extensions/TestDecorator.php',
+ 'PHPUnit2/Extensions/TestSetup.php',
+ 'PHPUnit2/Framework/Assert.php',
+ 'PHPUnit2/Framework/AssertionFailedError.php',
+ 'PHPUnit2/Framework/ComparisonFailure.php',
+ 'PHPUnit2/Framework/Error.php',
+ 'PHPUnit2/Framework/IncompleteTest.php',
+ 'PHPUnit2/Framework/IncompleteTestError.php',
+ 'PHPUnit2/Framework/Test.php',
+ 'PHPUnit2/Framework/TestCase.php',
+ 'PHPUnit2/Framework/TestFailure.php',
+ 'PHPUnit2/Framework/TestListener.php',
+ 'PHPUnit2/Framework/TestResult.php',
+ 'PHPUnit2/Framework/TestSuite.php',
+ 'PHPUnit2/Framework/Warning.php',
+ 'PHPUnit2/Runner/BaseTestRunner.php',
+ 'PHPUnit2/Runner/IncludePathTestCollector.php',
+ 'PHPUnit2/Runner/StandardTestSuiteLoader.php',
+ 'PHPUnit2/Runner/TestCollector.php',
+ 'PHPUnit2/Runner/TestSuiteLoader.php',
+ 'PHPUnit2/Runner/Version.php',
+ 'PHPUnit2/TextUI/ResultPrinter.php',
+ 'PHPUnit2/TextUI/TestRunner.php',
+ 'PHPUnit2/Util/CodeCoverage/Renderer/HTML.php',
+ 'PHPUnit2/Util/CodeCoverage/Renderer/Text.php',
+ 'PHPUnit2/Util/CodeCoverage/Renderer.php',
+ 'PHPUnit2/Util/Log/PEAR.php',
+ 'PHPUnit2/Util/Log/XML.php',
+ 'PHPUnit2/Util/TestDox/ResultPrinter/HTML.php',
+ 'PHPUnit2/Util/TestDox/ResultPrinter/Text.php',
+ 'PHPUnit2/Util/TestDox/NamePrettifier.php',
+ 'PHPUnit2/Util/TestDox/ResultPrinter.php',
+ 'PHPUnit2/Util/ErrorHandler.php',
+ 'PHPUnit2/Util/Fileloader.php',
+ 'PHPUnit2/Util/Filter.php',
+ 'PHPUnit2/Util/Printer.php',
+ 'PHPUnit2/Util/Skeleton.php',
+ 'Benchmark/Timer.php',
+ 'Console/Getopt.php',
+ 'Log/composite.php',
+ 'Log/console.php',
+ 'Log/display.php',
+ 'Log/error.php',
+ 'Log/file.php',
+ 'Log/mail.php',
+ 'Log/mcal.php',
+ 'Log/null.php',
+ 'Log/observer.php',
+ 'Log/sql.php',
+ 'Log/sqlite.php',
+ 'Log/syslog.php',
+ 'Log/win.php',
+ 'Log.php',
+ 'PEAR/Config.php',
+ 'PEAR.php'
+ );
+
+ /**
+ * Adds a new file to be filtered.
+ *
+ * @param string
+ * @access public
+ * @static
+ * @since Method available since Release 2.1.0
+ */
+ public static function addFileToFilter($filename) {
+ $filename = self::getCanonicalFilename($filename);
+
+ if (!self::isFiltered($filename)) {
+ self::$filteredFiles[] = $filename;
+ }
+ }
+
+ /**
+ * Removes a file from the filter.
+ *
+ * @param string
+ * @access public
+ * @static
+ * @since Method available since Release 2.1.0
+ */
+ public static function removeFileFromFilter($filename) {
+ $filename = self::getCanonicalFilename($filename);
+ $keys = array_keys(self::$filteredFiles);
+
+ for ($i = 0; $i < sizeof($keys); $i++) {
+ if (self::$filteredFiles[$keys[$i]] == $filename) {
+ unset(self::$filteredFiles[$keys[$i]]);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Filters source lines from PHPUnit classes.
+ *
+ * @param array
+ * @return array
+ * @access public
+ * @static
+ */
+ public static function getFilteredCodeCoverage($codeCoverageInformation) {
+ $files = array_keys($codeCoverageInformation);
+
+ foreach ($files as $file) {
+ if (self::isFiltered($file)) {
+ unset($codeCoverageInformation[$file]);
+ }
+ }
+
+ return $codeCoverageInformation;
+ }
+
+ /**
+ * Filters stack frames from PHPUnit classes.
+ *
+ * @param Exception $e
+ * @return string
+ * @access public
+ * @static
+ */
+ public static function getFilteredStacktrace(Exception $e) {
+ $filteredStacktrace = '';
+ $stacktrace = $e->getTrace();
+
+ foreach ($stacktrace as $frame) {
+ $filtered = FALSE;
+
+ if (isset($frame['file']) && !self::isFiltered($frame['file'])) {
+ $filteredStacktrace .= sprintf(
+ "%s:%s\n",
+
+ $frame['file'],
+ isset($frame['line']) ? $frame['line'] : '?'
+ );
+ }
+ }
+
+ return $filteredStacktrace;
+ }
+
+ /**
+ * Canonicalizes a source file name.
+ *
+ * @param string $filename
+ * @return string
+ * @access protected
+ * @static
+ */
+ protected static function getCanonicalFilename($filename) {
+ foreach (array('PHPUnit2', 'Benchmark', 'Console', 'PEAR') as $package) {
+ $pos = strpos($filename, $package);
+
+ if ($pos !== FALSE) {
+ $filename = substr($filename, $pos);
+ break;
+ }
+ }
+
+ return str_replace(
+ '\\',
+ '/',
+ $filename
+ );
+ }
+
+ /**
+ * @param string $filename
+ * @return boolean
+ * @access protected
+ * @static
+ * @since Method available since Release 2.1.3
+ */
+ protected static function isFiltered($filename) {
+ if (substr($filename, -7) == 'phpunit' ||
+ in_array(self::getCanonicalFilename($filename), self::$filteredFiles)) {
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Util/Log/PEAR.php b/buildscripts/PHPUnit2/Util/Log/PEAR.php
new file mode 100644
index 00000000..368c4f54
--- /dev/null
+++ b/buildscripts/PHPUnit2/Util/Log/PEAR.php
@@ -0,0 +1,220 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: PEAR.php,v 1.2.2.3 2005/12/17 16:04:58 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.3.0
+ */
+
+require_once 'PHPUnit2/Framework/TestListener.php';
+
+@include_once 'Log.php';
+
+/**
+ * A TestListener that logs to a PEAR_Log sink.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.1.0
+ */
+class PHPUnit2_Util_Log_PEAR implements PHPUnit2_Framework_TestListener {
+ /**
+ * Log.
+ *
+ * @var Log
+ * @access private
+ */
+ private $log;
+
+ /**
+ * @param string $type The type of concrete Log subclass to use.
+ * Currently, valid values are 'console',
+ * 'syslog', 'sql', 'file', and 'mcal'.
+ * @param string $name The name of the actually log file, table, or
+ * other specific store to use. Defaults to an
+ * empty string, with which the subclass will
+ * attempt to do something intelligent.
+ * @param string $ident The identity reported to the log system.
+ * @param array $conf A hash containing any additional configuration
+ * information that a subclass might need.
+ * @param int $maxLevel Maximum priority level at which to log.
+ * @access public
+ */
+ public function __construct($type, $name = '', $ident = '', $conf = array(), $maxLevel = PEAR_LOG_DEBUG) {
+ $this->log = Log::factory($type, $name, $ident, $conf, $maxLevel);
+ }
+
+ /**
+ * An error occurred.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @param Exception $e
+ * @access public
+ */
+ public function addError(PHPUnit2_Framework_Test $test, Exception $e) {
+ $this->log->crit(
+ sprintf(
+ 'Test "%s" failed: %s',
+
+ $test->getName(),
+ $e->getMessage()
+ )
+ );
+ }
+
+ /**
+ * A failure occurred.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @param PHPUnit2_Framework_AssertionFailedError $e
+ * @access public
+ */
+ public function addFailure(PHPUnit2_Framework_Test $test, PHPUnit2_Framework_AssertionFailedError $e) {
+ $this->log->err(
+ sprintf(
+ 'Test "%s" failed: %s',
+
+ $test->getName(),
+ $e->getMessage()
+ )
+ );
+ }
+
+ /**
+ * Incomplete test.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @param Exception $e
+ * @access public
+ */
+ public function addIncompleteTest(PHPUnit2_Framework_Test $test, Exception $e) {
+ $this->log->info(
+ sprintf(
+ 'Test "%s" incomplete: %s',
+
+ $test->getName(),
+ $e->getMessage()
+ )
+ );
+ }
+
+ /**
+ * A test suite started.
+ *
+ * @param PHPUnit2_Framework_TestSuite $suite
+ * @access public
+ * @since Method available since Release 2.2.0
+ */
+ public function startTestSuite(PHPUnit2_Framework_TestSuite $suite) {
+ $this->log->info(
+ sprintf(
+ 'TestSuite "%s" started.',
+
+ $suite->getName()
+ )
+ );
+ }
+
+ /**
+ * A test suite ended.
+ *
+ * @param PHPUnit2_Framework_TestSuite $suite
+ * @access public
+ * @since Method available since Release 2.2.0
+ */
+ public function endTestSuite(PHPUnit2_Framework_TestSuite $suite) {
+ $this->log->info(
+ sprintf(
+ 'TestSuite "%s" ended.',
+
+ $suite->getName()
+ )
+ );
+ }
+
+ /**
+ * A test started.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @access public
+ */
+ public function startTest(PHPUnit2_Framework_Test $test) {
+ $this->log->info(
+ sprintf(
+ 'Test "%s" started.',
+
+ $test->getName()
+ )
+ );
+ }
+
+ /**
+ * A test ended.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @access public
+ */
+ public function endTest(PHPUnit2_Framework_Test $test) {
+ $this->log->info(
+ sprintf(
+ 'Test "%s" ended.',
+
+ $test->getName()
+ )
+ );
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Util/Log/XML.php b/buildscripts/PHPUnit2/Util/Log/XML.php
new file mode 100644
index 00000000..ce528753
--- /dev/null
+++ b/buildscripts/PHPUnit2/Util/Log/XML.php
@@ -0,0 +1,356 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: XML.php,v 1.2.2.3 2005/12/17 16:04:58 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.3.0
+ */
+
+require_once 'PHPUnit2/Framework/TestListener.php';
+require_once 'PHPUnit2/Util/Filter.php';
+require_once 'PHPUnit2/Util/Printer.php';
+
+require_once 'Benchmark/Timer.php';
+
+/**
+ * A TestListener that generates an XML-based logfile
+ * of the test execution.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.1.0
+ */
+class PHPUnit2_Util_Log_XML extends PHPUnit2_Util_Printer implements PHPUnit2_Framework_TestListener {
+ /**
+ * @var DOMDocument
+ * @access private
+ */
+ private $document;
+
+ /**
+ * @var DOMElement
+ * @access private
+ */
+ private $root;
+
+ /**
+ * @var boolean
+ * @access private
+ */
+ private $writeDocument = TRUE;
+
+ /**
+ * @var DOMElement[]
+ * @access private
+ */
+ private $testSuites = array();
+
+ /**
+ * @var integer[]
+ * @access private
+ */
+ private $testSuiteTests = array(0);
+
+ /**
+ * @var integer[]
+ * @access private
+ */
+ private $testSuiteErrors = array(0);
+
+ /**
+ * @var integer[]
+ * @access private
+ */
+ private $testSuiteFailures = array(0);
+
+ /**
+ * @var integer[]
+ * @access private
+ */
+ private $testSuiteTimes = array(0);
+
+ /**
+ * @var integer
+ * @access private
+ */
+ private $testSuiteLevel = 0;
+
+ /**
+ * @var DOMElement
+ * @access private
+ */
+ private $currentTestCase = NULL;
+
+ /**
+ * @var Benchmark_Timer
+ * @access private
+ */
+ private $timer;
+
+ /**
+ * Constructor.
+ *
+ * @param mixed $out
+ * @access public
+ */
+ public function __construct($out = NULL) {
+ $this->document = new DOMDocument('1.0', 'UTF-8');
+ $this->document->formatOutput = TRUE;
+
+ $this->root = $this->document->createElement('testsuites');
+ $this->document->appendChild($this->root);
+
+ $this->timer = new Benchmark_Timer;
+
+ parent::__construct($out);
+ }
+
+ /**
+ * Destructor.
+ *
+ * @access public
+ */
+ public function __destruct() {
+ if ($this->writeDocument === TRUE) {
+ $this->write($this->getXML());
+ }
+
+ parent::__destruct();
+ }
+
+ /**
+ * An error occurred.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @param Exception $e
+ * @access public
+ */
+ public function addError(PHPUnit2_Framework_Test $test, Exception $e) {
+ $error = $this->document->createElement('error', PHPUnit2_Util_Filter::getFilteredStacktrace($e));
+ $error->setAttribute('message', $e->getMessage());
+ $error->setAttribute('type', get_class($e));
+
+ $this->currentTestCase->appendChild($error);
+
+ $this->testSuiteErrors[$this->testSuiteLevel]++;
+ }
+
+ /**
+ * A failure occurred.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @param PHPUnit2_Framework_AssertionFailedError $e
+ * @access public
+ */
+ public function addFailure(PHPUnit2_Framework_Test $test, PHPUnit2_Framework_AssertionFailedError $e) {
+ $failure = $this->document->createElement('failure', PHPUnit2_Util_Filter::getFilteredStacktrace($e));
+ $failure->setAttribute('message', $e->getMessage());
+ $failure->setAttribute('type', get_class($e));
+
+ $this->currentTestCase->appendChild($failure);
+
+ $this->testSuiteFailures[$this->testSuiteLevel]++;
+ }
+
+ /**
+ * Incomplete test.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @param Exception $e
+ * @access public
+ */
+ public function addIncompleteTest(PHPUnit2_Framework_Test $test, Exception $e) {
+ $error = $this->document->createElement('error', PHPUnit2_Util_Filter::getFilteredStacktrace($e));
+ $error->setAttribute('message', 'Incomplete Test');
+ $error->setAttribute('type', get_class($e));
+
+ $this->currentTestCase->appendChild($error);
+
+ $this->testSuiteErrors[$this->testSuiteLevel]++;
+ }
+
+ /**
+ * A testsuite started.
+ *
+ * @param PHPUnit2_Framework_TestSuite $suite
+ * @access public
+ * @since Method available since Release 2.2.0
+ */
+ public function startTestSuite(PHPUnit2_Framework_TestSuite $suite) {
+ $testSuite = $this->document->createElement('testsuite');
+ $testSuite->setAttribute('name', $suite->getName());
+
+ try {
+ $class = new ReflectionClass($suite->getName());
+ $docComment = $class->getDocComment();
+
+ if (preg_match('/@category[\s]+([\.\w]+)/', $docComment, $matches)) {
+ $testSuite->setAttribute('category', $matches[1]);
+ }
+
+ if (preg_match('/@package[\s]+([\.\w]+)/', $docComment, $matches)) {
+ $testSuite->setAttribute('package', $matches[1]);
+ }
+
+ if (preg_match('/@subpackage[\s]+([\.\w]+)/', $docComment, $matches)) {
+ $testSuite->setAttribute('subpackage', $matches[1]);
+ }
+ }
+
+ catch (ReflectionException $e) {
+ }
+
+ if ($this->testSuiteLevel > 0) {
+ $this->testSuites[$this->testSuiteLevel]->appendChild($testSuite);
+ } else {
+ $this->root->appendChild($testSuite);
+ }
+
+ $this->testSuiteLevel++;
+ $this->testSuites[$this->testSuiteLevel] = $testSuite;
+ $this->testSuiteTests[$this->testSuiteLevel] = 0;
+ $this->testSuiteErrors[$this->testSuiteLevel] = 0;
+ $this->testSuiteFailures[$this->testSuiteLevel] = 0;
+ $this->testSuiteTimes[$this->testSuiteLevel] = 0;
+ }
+
+ /**
+ * A testsuite ended.
+ *
+ * @param PHPUnit2_Framework_TestSuite $suite
+ * @access public
+ * @since Method available since Release 2.2.0
+ */
+ public function endTestSuite(PHPUnit2_Framework_TestSuite $suite) {
+ $this->testSuites[$this->testSuiteLevel]->setAttribute('tests', $this->testSuiteTests[$this->testSuiteLevel]);
+ $this->testSuites[$this->testSuiteLevel]->setAttribute('failures', $this->testSuiteFailures[$this->testSuiteLevel]);
+ $this->testSuites[$this->testSuiteLevel]->setAttribute('errors', $this->testSuiteErrors[$this->testSuiteLevel]);
+ $this->testSuites[$this->testSuiteLevel]->setAttribute('time', $this->testSuiteTimes[$this->testSuiteLevel]);
+
+ if ($this->testSuiteLevel > 1) {
+ $this->testSuiteTests[$this->testSuiteLevel - 1] += $this->testSuiteTests[$this->testSuiteLevel];
+ $this->testSuiteErrors[$this->testSuiteLevel - 1] += $this->testSuiteErrors[$this->testSuiteLevel];
+ $this->testSuiteFailures[$this->testSuiteLevel - 1] += $this->testSuiteFailures[$this->testSuiteLevel];
+ $this->testSuiteTimes[$this->testSuiteLevel - 1] += $this->testSuiteTimes[$this->testSuiteLevel];
+ }
+
+ $this->testSuiteLevel--;
+ }
+
+ /**
+ * A test started.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @access public
+ */
+ public function startTest(PHPUnit2_Framework_Test $test) {
+ $testCase = $this->document->createElement('testcase');
+ $testCase->setAttribute('name', $test->getName());
+ $testCase->setAttribute('class', get_class($test));
+
+ $this->testSuites[$this->testSuiteLevel]->appendChild($testCase);
+ $this->currentTestCase = $testCase;
+
+ $this->testSuiteTests[$this->testSuiteLevel]++;
+
+ $this->timer->start();
+ }
+
+ /**
+ * A test ended.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @access public
+ */
+ public function endTest(PHPUnit2_Framework_Test $test) {
+ $this->timer->stop();
+ $time = $this->timer->timeElapsed();
+
+ $this->currentTestCase->setAttribute('time', $time);
+ $this->testSuiteTimes[$this->testSuiteLevel] += $time;
+
+ $this->currentTestCase = NULL;
+ }
+
+ /**
+ * Returns the XML as a string.
+ *
+ * @return string
+ * @access public
+ * @since Method available since Release 2.2.0
+ */
+ public function getXML() {
+ return $this->document->saveXML();
+ }
+
+ /**
+ * Enables or disables the writing of the document
+ * in __destruct().
+ *
+ * This is a "hack" needed for the integration of
+ * PHPUnit with Phing.
+ *
+ * @return string
+ * @access public
+ * @since Method available since Release 2.2.0
+ */
+ public function setWriteDocument($flag) {
+ if (is_bool($flag)) {
+ $this->writeDocument = $flag;
+ }
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Util/Printer.php b/buildscripts/PHPUnit2/Util/Printer.php
new file mode 100644
index 00000000..13dc46a9
--- /dev/null
+++ b/buildscripts/PHPUnit2/Util/Printer.php
@@ -0,0 +1,116 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: Printer.php,v 1.10.2.3 2005/12/17 16:04:58 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.0.0
+ */
+
+/**
+ * Utility class that can print to STDOUT or write to a file.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.0.0
+ * @abstract
+ */
+abstract class PHPUnit2_Util_Printer {
+ /**
+ * @var resource
+ * @access private
+ */
+ private $out = NULL;
+
+ /**
+ * Constructor.
+ *
+ * @param mixed $out
+ * @access public
+ */
+ public function __construct($out = NULL) {
+ if ($out !== NULL) {
+ if (is_string($out)) {
+ $this->out = fopen($out, 'w');
+ } else {
+ $this->out = $out;
+ }
+ }
+ }
+
+ /**
+ * Destructor.
+ *
+ * @access public
+ */
+ public function __destruct() {
+ if ($this->out !== NULL) {
+ fclose($this->out);
+ }
+ }
+
+ /**
+ * @param string $buffer
+ * @access public
+ */
+ public function write($buffer) {
+ if ($this->out !== NULL) {
+ fputs($this->out, $buffer);
+ } else {
+ print $buffer;
+ }
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Util/Skeleton.php b/buildscripts/PHPUnit2/Util/Skeleton.php
new file mode 100644
index 00000000..39717557
--- /dev/null
+++ b/buildscripts/PHPUnit2/Util/Skeleton.php
@@ -0,0 +1,340 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: Skeleton.php,v 1.24.2.3 2005/12/17 16:04:58 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.1.0
+ */
+
+/**
+ * Class for creating a PHPUnit2_Framework_TestCase skeleton file.
+ *
+ * This class will take a classname as a parameter on construction and will
+ * create a PHP file that contains the skeleton of a PHPUnit2_Framework_TestCase
+ * subclass.
+ *
+ * <code>
+ * <?php
+ * require_once 'PHPUnit2/Util/Skeleton.php';
+ *
+ * $skeleton = new PHPUnit2_Util_Skeleton(
+ * 'PHPUnit2_Util_Skeleton',
+ * 'PHPUnit2/Util/Skeleton.php'
+ * );
+ *
+ * $skeleton->write();
+ * ?>
+ * </code>
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.1.0
+ */
+class PHPUnit2_Util_Skeleton {
+ protected $templateClassHeader =
+'<?php
+// Call {className}Test::main() if this source file is executed directly.
+if (!defined("PHPUnit2_MAIN_METHOD")) {
+ define("PHPUnit2_MAIN_METHOD", "{className}Test::main");
+}
+
+require_once "PHPUnit2/Framework/TestCase.php";
+require_once "PHPUnit2/Framework/TestSuite.php";
+
+// You may remove the following line when all tests have been implemented.
+require_once "PHPUnit2/Framework/IncompleteTestError.php";
+
+require_once "{classFile}";
+
+/**
+ * Test class for {className}.
+ * Generated by PHPUnit2_Util_Skeleton on {date} at {time}.
+ */
+class {className}Test extends PHPUnit2_Framework_TestCase {
+ /**
+ * Runs the test methods of this class.
+ *
+ * @access public
+ * @static
+ */
+ public static function main() {
+ require_once "PHPUnit2/TextUI/TestRunner.php";
+
+ $suite = new PHPUnit2_Framework_TestSuite("{className}Test");
+ $result = PHPUnit2_TextUI_TestRunner::run($suite);
+ }
+
+ /**
+ * Sets up the fixture, for example, open a network connection.
+ * This method is called before a test is executed.
+ *
+ * @access protected
+ */
+ protected function setUp() {
+ }
+
+ /**
+ * Tears down the fixture, for example, close a network connection.
+ * This method is called after a test is executed.
+ *
+ * @access protected
+ */
+ protected function tearDown() {
+ }
+';
+
+ protected $templateClassFooter =
+'}
+
+// Call {className}Test::main() if this source file is executed directly.
+if (PHPUnit2_MAIN_METHOD == "{className}Test::main") {
+ {className}Test::main();
+}
+?>
+';
+
+ protected $templateMethod =
+'
+ /**
+ * @todo Implement test{methodName}().
+ */
+ public function test{methodName}() {
+ // Remove the following line when you implement this test.
+ throw new PHPUnit2_Framework_IncompleteTestError;
+ }
+';
+
+ /**
+ * @var string
+ * @access protected
+ */
+ protected $className;
+
+ /**
+ * @var string
+ * @access protected
+ */
+ protected $classSourceFile;
+
+ /**
+ * Constructor.
+ *
+ * @param string $className
+ * @param string $classSourceFile
+ * @throws Exception
+ * @access public
+ */
+ public function __construct($className, $classSourceFile = '') {
+ if ($classSourceFile == '') {
+ $classSourceFile = $className . '.php';
+ }
+
+ if (file_exists($classSourceFile)) {
+ $this->classSourceFile = $classSourceFile;
+ } else {
+ throw new Exception(
+ sprintf(
+ 'Could not open %s.',
+
+ $classSourceFile
+ )
+ );
+ }
+
+ @include_once $this->classSourceFile;
+
+ if (class_exists($className)) {
+ $this->className = $className;
+ } else {
+ throw new Exception(
+ sprintf(
+ 'Could not find class "%s" in %s.',
+
+ $className,
+ $classSourceFile
+ )
+ );
+ }
+ }
+
+ /**
+ * Generates the test class' source.
+ *
+ * @return string
+ * @access public
+ */
+ public function generate() {
+ $testClassSource = $this->testClassHeader($this->className, $this->classSourceFile);
+
+ $class = new ReflectionClass($this->className);
+
+ foreach ($class->getMethods() as $method) {
+ if (!$method->isConstructor() &&
+ !$method->isAbstract() &&
+ $method->isUserDefined() &&
+ $method->isPublic() &&
+ $method->getDeclaringClass()->getName() == $this->className) {
+ $testClassSource .= $this->testMethod($method->getName());
+ }
+ }
+
+ $testClassSource .= $this->testClassFooter($this->className);
+
+ return $testClassSource;
+ }
+
+ /**
+ * Generates the test class and writes it to a source file.
+ *
+ * @param string $file
+ * @access public
+ */
+ public function write($file = '') {
+ if ($file == '') {
+ $file = $this->className . 'Test.php';
+ }
+
+ if ($fp = @fopen($file, 'w')) {
+ @fputs($fp, $this->generate());
+ @fclose($fp);
+ }
+ }
+
+ /**
+ * Sets the templates for class header, class footer, and method.
+ *
+ * @param string $classHeader
+ * @param string $classFooter
+ * @param string $method
+ * @access public
+ * @since Method available since Release 2.2.0
+ */
+ public function setTemplates($classHeader, $classFooter, $method) {
+ if (is_file($classHeader)) {
+ $this->templateClassHeader = file_get_contents($classHeader);
+ } else {
+ $this->templateClassHeader = $classHeader;
+ }
+
+ if (is_file($classFooter)) {
+ $this->templateClassFooter = file_get_contents($classFooter);
+ } else {
+ $this->templateClassFooter = $classFooter;
+ }
+
+ if (is_file($method)) {
+ $this->templateMethod = file_get_contents($method);
+ } else {
+ $this->templateMethod = $method;
+ }
+ }
+
+ /**
+ * @param string $className
+ * @param string $classSourceFile
+ * @access protected
+ */
+ protected function testClassHeader($className, $classSourceFile) {
+ return str_replace(
+ array(
+ '{className}',
+ '{classFile}',
+ '{date}',
+ '{time}'
+ ),
+ array(
+ $className,
+ $classSourceFile,
+ date('Y-m-d'),
+ date('H:i:s')
+ ),
+ $this->templateClassHeader
+ );
+ }
+
+ /**
+ * @param string $className
+ * @access protected
+ */
+ protected function testClassFooter($className) {
+ return str_replace(
+ array(
+ '{className}'
+ ),
+ array(
+ $className
+ ),
+ $this->templateClassFooter
+ );
+ }
+
+ /**
+ * @param string $methodName
+ * @access protected
+ */
+ protected function testMethod($methodName) {
+ return str_replace(
+ array(
+ '{methodName}'
+ ),
+ array(
+ ucfirst($methodName)
+ ),
+ $this->templateMethod
+ );
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Util/TestDox/NamePrettifier.php b/buildscripts/PHPUnit2/Util/TestDox/NamePrettifier.php
new file mode 100644
index 00000000..1d686dc8
--- /dev/null
+++ b/buildscripts/PHPUnit2/Util/TestDox/NamePrettifier.php
@@ -0,0 +1,165 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: NamePrettifier.php,v 1.2.2.2 2005/12/17 16:04:58 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.3.0
+ */
+
+/**
+ * Prettifies class and method names for use in TestDox documentation.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.1.0
+ */
+class PHPUnit2_Util_TestDox_NamePrettifier {
+ /**
+ * @var string
+ * @access protected
+ */
+ protected $prefix = 'Test';
+
+ /**
+ * @var string
+ * @access protected
+ */
+ protected $suffix = 'Test';
+
+ /**
+ * Tests if a method is a test method.
+ *
+ * @param string $testMethodName
+ * @return boolean
+ * @access public
+ */
+ public function isATestMethod($testMethodName) {
+ if (substr($testMethodName, 0, 4) == 'test') {
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ /**
+ * Prettifies the name of a test class.
+ *
+ * @param string $testClassName
+ * @return string
+ * @access public
+ */
+ public function prettifyTestClass($testClassName) {
+ $title = $testClassName;
+
+ if ($this->suffix !== NULL &&
+ $this->suffix == substr($testClassName, -1 * strlen($this->suffix))) {
+ $title = substr($title, 0, strripos($title, $this->suffix));
+ }
+
+ if ($this->prefix !== NULL &&
+ $this->prefix == substr($testClassName, 0, strlen($this->prefix))) {
+ $title = substr($title, strlen($this->prefix));
+ }
+
+ return $title;
+ }
+
+ /**
+ * Prettifies the name of a test method.
+ *
+ * @param string $testMethodName
+ * @return string
+ * @access public
+ */
+ public function prettifyTestMethod($testMethodName) {
+ $buffer = '';
+
+ $testMethodName = preg_replace('#\d+$#', '', $testMethodName);
+
+ for ($i = 4; $i < strlen($testMethodName); $i++) {
+ if ($i > 4 &&
+ ord($testMethodName[$i]) >= 65 &&
+ ord($testMethodName[$i]) <= 90) {
+ $buffer .= ' ' . strtolower($testMethodName[$i]);
+ } else {
+ $buffer .= $testMethodName[$i];
+ }
+ }
+
+ return $buffer;
+ }
+
+ /**
+ * Sets the prefix of test names.
+ *
+ * @param string $prefix
+ * @access public
+ */
+ public function setPrefix($prefix) {
+ $this->prefix = $prefix;
+ }
+
+ /**
+ * Sets the suffix of test names.
+ *
+ * @param string $prefix
+ * @access public
+ */
+ public function setSuffix($suffix) {
+ $this->suffix = $suffix;
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Util/TestDox/ResultPrinter.php b/buildscripts/PHPUnit2/Util/TestDox/ResultPrinter.php
new file mode 100644
index 00000000..274c7309
--- /dev/null
+++ b/buildscripts/PHPUnit2/Util/TestDox/ResultPrinter.php
@@ -0,0 +1,299 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: ResultPrinter.php,v 1.2.2.6 2005/12/17 16:04:58 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.3.0
+ */
+
+require_once 'PHPUnit2/Framework/TestListener.php';
+require_once 'PHPUnit2/Util/TestDox/NamePrettifier.php';
+require_once 'PHPUnit2/Util/Printer.php';
+
+/**
+ * Base class for printers of TestDox documentation.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.1.0
+ * @abstract
+ */
+abstract class PHPUnit2_Util_TestDox_ResultPrinter extends PHPUnit2_Util_Printer implements PHPUnit2_Framework_TestListener {
+ /**
+ * @var PHPUnit2_Util_TestDox_NamePrettifier
+ * @access protected
+ */
+ protected $prettifier;
+
+ /**
+ * @var string
+ * @access protected
+ */
+ protected $testClass = '';
+
+ /**
+ * @var boolean
+ * @access protected
+ */
+ protected $testFailed = FALSE;
+
+ /**
+ * @var array
+ * @access protected
+ */
+ protected $tests = array();
+
+ /**
+ * Constructor.
+ *
+ * @param resource $out
+ * @access public
+ */
+ public function __construct($out = NULL) {
+ parent::__construct($out);
+
+ $this->prettifier = new PHPUnit2_Util_TestDox_NamePrettifier;
+ $this->startRun();
+ }
+
+ /**
+ * Destructor.
+ *
+ * @access public
+ */
+ public function __destruct() {
+ $this->doEndClass();
+ $this->endRun();
+
+ parent::__destruct();
+ }
+
+ /**
+ * Abstract Factory.
+ *
+ * @param string $type
+ * @param resource $out
+ * @throws Exception
+ * @access public
+ * @static
+ */
+ public static function factory($type, $out = NULL) {
+ require_once 'PHPUnit2/Util/TestDox/ResultPrinter/' . $type . '.php';
+
+ $class = 'PHPUnit2_Util_TestDox_ResultPrinter_' . $type;
+ return new $class($out);
+ }
+
+ /**
+ * An error occurred.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @param Exception $e
+ * @access public
+ */
+ public function addError(PHPUnit2_Framework_Test $test, Exception $e) {
+ $this->testFailed = TRUE;
+ }
+
+ /**
+ * A failure occurred.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @param PHPUnit2_Framework_AssertionFailedError $e
+ * @access public
+ */
+ public function addFailure(PHPUnit2_Framework_Test $test, PHPUnit2_Framework_AssertionFailedError $e) {
+ $this->testFailed = TRUE;
+ }
+
+ /**
+ * Incomplete test.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @param Exception $e
+ * @access public
+ */
+ public function addIncompleteTest(PHPUnit2_Framework_Test $test, Exception $e) {
+ $this->testFailed = TRUE;
+ }
+
+ /**
+ * A testsuite started.
+ *
+ * @param PHPUnit2_Framework_TestSuite $suite
+ * @access public
+ * @since Method available since Release 2.2.0
+ */
+ public function startTestSuite(PHPUnit2_Framework_TestSuite $suite) {
+ }
+
+ /**
+ * A testsuite ended.
+ *
+ * @param PHPUnit2_Framework_TestSuite $suite
+ * @access public
+ * @since Method available since Release 2.2.0
+ */
+ public function endTestSuite(PHPUnit2_Framework_TestSuite $suite) {
+ }
+
+ /**
+ * A test started.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @access public
+ */
+ public function startTest(PHPUnit2_Framework_Test $test) {
+ $class = get_class($test);
+
+ if ($this->testClass != $class) {
+ if ($this->testClass != '') {
+ $this->doEndClass();
+ }
+
+ $this->startClass($this->prettifier->prettifyTestClass($class));
+
+ $this->testClass = $class;
+ $this->tests = array();
+ }
+
+ $this->testFailed = FALSE;
+ }
+
+ /**
+ * A test ended.
+ *
+ * @param PHPUnit2_Framework_Test $test
+ * @access public
+ */
+ public function endTest(PHPUnit2_Framework_Test $test) {
+ $prettifiedName = $this->prettifier->prettifyTestMethod($test->getName());
+
+ if (!isset($this->tests[$prettifiedName])) {
+ if (!$this->testFailed) {
+ $this->tests[$prettifiedName]['success'] = 1;
+ $this->tests[$prettifiedName]['failure'] = 0;
+ } else {
+ $this->tests[$prettifiedName]['success'] = 0;
+ $this->tests[$prettifiedName]['failure'] = 1;
+ }
+ } else {
+ if (!$this->testFailed) {
+ $this->tests[$prettifiedName]['success']++;
+ } else {
+ $this->tests[$prettifiedName]['failure']++;
+ }
+ }
+ }
+
+ /**
+ * @access private
+ * @since Method available since Release 2.3.0
+ */
+ private function doEndClass() {
+ foreach ($this->tests as $name => $data) {
+ if ($data['failure'] == 0) {
+ $this->onTest($name);
+ }
+ }
+
+ $this->endClass($this->prettifier->prettifyTestClass($this->testClass));
+ }
+
+ /**
+ * Handler for 'start run' event.
+ *
+ * @access protected
+ */
+ protected function startRun() {
+ }
+
+ /**
+ * Handler for 'start class' event.
+ *
+ * @param string $name
+ * @access protected
+ * @abstract
+ */
+ abstract protected function startClass($name);
+
+ /**
+ * Handler for 'on test' event.
+ *
+ * @param string $name
+ * @access protected
+ * @abstract
+ */
+ abstract protected function onTest($name);
+
+ /**
+ * Handler for 'end class' event.
+ *
+ * @param string $name
+ * @access protected
+ * @abstract
+ */
+ abstract protected function endClass($name);
+
+ /**
+ * Handler for 'end run' event.
+ *
+ * @access protected
+ */
+ protected function endRun() {
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Util/TestDox/ResultPrinter/HTML.php b/buildscripts/PHPUnit2/Util/TestDox/ResultPrinter/HTML.php
new file mode 100644
index 00000000..505ec60d
--- /dev/null
+++ b/buildscripts/PHPUnit2/Util/TestDox/ResultPrinter/HTML.php
@@ -0,0 +1,120 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: HTML.php,v 1.2.2.3 2005/12/17 16:04:58 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.3.0
+ */
+
+require_once 'PHPUnit2/Util/TestDox/ResultPrinter.php';
+
+/**
+ * Prints TestDox documentation in HTML format.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.1.0
+ */
+class PHPUnit2_Util_TestDox_ResultPrinter_HTML extends PHPUnit2_Util_TestDox_ResultPrinter {
+ /**
+ * Handler for 'start run' event.
+ *
+ * @access protected
+ */
+ protected function startRun() {
+ $this->write('<html><body>');
+ }
+
+ /**
+ * Handler for 'start class' event.
+ *
+ * @param string $name
+ * @access protected
+ */
+ protected function startClass($name) {
+ $this->write('<h2>' . $name . '</h2><ul>');
+ }
+
+ /**
+ * Handler for 'on test' event.
+ *
+ * @param string $name
+ * @access protected
+ */
+ protected function onTest($name) {
+ $this->write('<li>' . $name . '</li>');
+ }
+
+ /**
+ * Handler for 'end class' event.
+ *
+ * @param string $name
+ * @access protected
+ */
+ protected function endClass($name) {
+ $this->write('</ul>');
+ }
+
+ /**
+ * Handler for 'end run' event.
+ *
+ * @access protected
+ */
+ protected function endRun() {
+ $this->write('</body></html>');
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/Util/TestDox/ResultPrinter/Text.php b/buildscripts/PHPUnit2/Util/TestDox/ResultPrinter/Text.php
new file mode 100644
index 00000000..cd12e525
--- /dev/null
+++ b/buildscripts/PHPUnit2/Util/TestDox/ResultPrinter/Text.php
@@ -0,0 +1,102 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version CVS: $Id: Text.php,v 1.2.2.3 2005/12/17 16:04:58 sebastian Exp $
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since File available since Release 2.3.0
+ */
+
+require_once 'PHPUnit2/Util/TestDox/ResultPrinter.php';
+
+/**
+ * Prints TestDox documentation in text format.
+ *
+ * @category Testing
+ * @package PHPUnit2
+ * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @copyright 2002-2006 Sebastian Bergmann <sb@sebastian-bergmann.de>
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PHPUnit2
+ * @since Class available since Release 2.1.0
+ */
+class PHPUnit2_Util_TestDox_ResultPrinter_Text extends PHPUnit2_Util_TestDox_ResultPrinter {
+ /**
+ * Handler for 'start class' event.
+ *
+ * @param string $name
+ * @access protected
+ */
+ protected function startClass($name) {
+ $this->write($name . "\n");
+ }
+
+ /**
+ * Handler for 'on test' event.
+ *
+ * @param string $name
+ * @access protected
+ */
+ protected function onTest($name) {
+ $this->write(' - ' . $name . "\n");
+ }
+
+ /**
+ * Handler for 'end class' event.
+ *
+ * @param string $name
+ * @access protected
+ */
+ protected function endClass($name) {
+ $this->write("\n");
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/buildscripts/PHPUnit2/pear-phpunit b/buildscripts/PHPUnit2/pear-phpunit
new file mode 100644
index 00000000..25e8944d
--- /dev/null
+++ b/buildscripts/PHPUnit2/pear-phpunit
@@ -0,0 +1,41 @@
+#!@php_bin@
+<?php
+/* PHP Version 5
+ *
+ * Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * Neither the name of Sebastian Bergmann nor the names of his
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: pear-phpunit,v 1.2.8.2 2005/12/17 16:04:56 sebastian Exp $
+ */
+
+require 'PHPUnit2/TextUI/TestRunner.php';
+?>
diff --git a/buildscripts/PHPUnit2/pear-phpunit.bat b/buildscripts/PHPUnit2/pear-phpunit.bat
new file mode 100644
index 00000000..d7aadb5c
--- /dev/null
+++ b/buildscripts/PHPUnit2/pear-phpunit.bat
@@ -0,0 +1,39 @@
+@echo off
+REM PHP Version 5
+REM
+REM Copyright (c) 2002-2006, Sebastian Bergmann <sb@sebastian-bergmann.de>.
+REM All rights reserved.
+REM
+REM Redistribution and use in source and binary forms, with or without
+REM modification, are permitted provided that the following conditions
+REM are met:
+REM
+REM * Redistributions of source code must retain the above copyright
+REM notice, this list of conditions and the following disclaimer.
+REM
+REM * Redistributions in binary form must reproduce the above copyright
+REM notice, this list of conditions and the following disclaimer in
+REM the documentation and/or other materials provided with the
+REM distribution.
+REM
+REM * Neither the name of Sebastian Bergmann nor the names of his
+REM contributors may be used to endorse or promote products derived
+REM from this software without specific prior written permission.
+REM
+REM THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+REM "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+REM LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+REM FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+REM COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+REM INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+REM BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+REM LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+REM CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
+REM LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+REM ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+REM POSSIBILITY OF SUCH DAMAGE.
+REM
+REM $Id: pear-phpunit.bat,v 1.3.2.2 2005/12/17 16:04:56 sebastian Exp $
+REM
+
+"@php_bin@" "@php_dir@/PHPUnit2/TextUI/TestRunner.php" %*
diff --git a/buildscripts/PhpDocumentor/PHPLICENSE.txt b/buildscripts/PhpDocumentor/PHPLICENSE.txt
new file mode 100644
index 00000000..c88b3873
--- /dev/null
+++ b/buildscripts/PhpDocumentor/PHPLICENSE.txt
@@ -0,0 +1,69 @@
+--------------------------------------------------------------------
+ The PHP License, version 3.0
+Copyright (c) 1999 - 2002 The PHP Group. All rights reserved.
+--------------------------------------------------------------------
+
+Redistribution and use in source and binary forms, with or without
+modification, is permitted provided that the following conditions
+are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ 3. The name "PHP" must not be used to endorse or promote products
+ derived from this software without prior written permission. For
+ written permission, please contact group@php.net.
+
+ 4. Products derived from this software may not be called "PHP", nor
+ may "PHP" appear in their name, without prior written permission
+ from group@php.net. You may indicate that your software works in
+ conjunction with PHP by saying "Foo for PHP" instead of calling
+ it "PHP Foo" or "phpfoo"
+
+ 5. The PHP Group may publish revised and/or new versions of the
+ license from time to time. Each version will be given a
+ distinguishing version number.
+ Once covered code has been published under a particular version
+ of the license, you may always continue to use it under the terms
+ of that version. You may also choose to use such covered code
+ under the terms of any subsequent version of the license
+ published by the PHP Group. No one other than the PHP Group has
+ the right to modify the terms applicable to covered code created
+ under this License.
+
+ 6. Redistributions of any form whatsoever must retain the following
+ acknowledgment:
+ "This product includes PHP, freely available from
+ <http://www.php.net/>".
+
+THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
+ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
+DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
+
+--------------------------------------------------------------------
+
+This software consists of voluntary contributions made by many
+individuals on behalf of the PHP Group.
+
+The PHP Group can be contacted via Email at group@php.net.
+
+For more information on the PHP Group and the PHP project,
+please see <http://www.php.net>.
+
+This product includes the Zend Engine, freely available at
+<http://www.zend.com>.
+
diff --git a/buildscripts/PhpDocumentor/new_phpdoc.php b/buildscripts/PhpDocumentor/new_phpdoc.php
new file mode 100644
index 00000000..e4adea90
--- /dev/null
+++ b/buildscripts/PhpDocumentor/new_phpdoc.php
@@ -0,0 +1,662 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<?php
+/**
+ * Advanced Web Interface to phpDocumentor
+ * @see phpdoc.php
+ * @package phpDocumentor
+ * @deprecated in favor of docbuilder (see {@link docbuilder/config.php})
+ * @filesource
+ */
+//
+//
+// An HTML interface for Joshua Eichorn's phpDocumentor
+// Author: Juan Pablo Morales <ju-moral@uniandes.edu.co>
+// Joshua Eichorn <jeichorn@phpdoc.org>
+// Gregory Beaver <cellog@users.sourceforge.net>
+//
+// phpDocumentor, a program for creating javadoc style documentation from php code
+// Copyright (C) 2000-2002 Joshua Eichorn
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+//
+// Copyleft 2001 Juan Pablo Morales
+
+if (!function_exists('version_compare'))
+{
+ print "phpDocumentor requires PHP version 4.1.0 or greater to function";
+ exit;
+}
+
+// set up include path so we can find all files, no matter what
+$GLOBALS['_phpDocumentor_install_dir'] = dirname(realpath(__FILE__));
+// add my directory to the include path, and make it first, should fix any errors
+if (substr(PHP_OS, 0, 3) == 'WIN')
+ini_set('include_path',$GLOBALS['_phpDocumentor_install_dir'].';'.ini_get('include_path'));
+else
+ini_set('include_path',$GLOBALS['_phpDocumentor_install_dir'].':'.ini_get('include_path'));
+
+/**
+* common file information
+*/
+include_once("phpDocumentor/common.inc.php");
+
+// find the .ini directory by parsing phpDocumentor.ini and extracting _phpDocumentor_options[userdir]
+$ini = phpDocumentor_parse_ini_file($_phpDocumentor_install_dir . PATH_DELIMITER . 'phpDocumentor.ini', true);
+if (isset($ini['_phpDocumentor_options']['userdir']))
+ $configdir = $ini['_phpDocumentor_options']['userdir'];
+else
+ $configdir = $_phpDocumentor_install_dir . '/user';
+
+// allow the user to change this at runtime
+if (!empty($_REQUEST['altuserdir'])) $configdir = $_REQUEST['altuserdir'];
+?>
+<html>
+ <head>
+ <title>
+ Form to submit to phpDocumentor v<?php print PHPDOCUMENTOR_VER; ?>
+ </title>
+ <?php
+ if(!isset($_GET['submit']) || !empty($_REQUEST['altuserdir'])) {
+?>
+<script src="HTML_TreeMenu-1.1.2/TreeMenu.js" language="JavaScript" type="text/javascript"></script>
+ <?php
+ include_once('HTML_TreeMenu-1.1.2/TreeMenu.php');
+ set_time_limit(0); // six minute timeout
+ ini_set("memory_limit","256M");
+ /**
+ * Directory Node
+ * @package HTML_TreeMenu
+ */
+ class DirNode extends HTML_TreeNode
+ {
+ /**
+ * full path to this node
+ * @var string
+ */
+ var $path;
+
+ function DirNode($text = false, $link = false, $icon = false, $path, $events = array())
+ {
+ $this->path = $path;
+ $options = array();
+ if ($text) $options['text'] = $text;
+ if ($link) $options['link'] = $link;
+ if ($icon) $options['icon'] = $icon;
+ HTML_TreeNode::HTML_TreeNode($options,$events);
+ }
+ }
+
+ function getDir($path,&$node)
+ {
+ global $pd;
+ if (!$dir = opendir($path)) return;
+
+ $node = new HTML_TreeNode(array('text' => basename(realpath($path)), 'link' => "", 'icon' => 'folder.gif'));
+ while (($file = readdir($dir)) !== false)
+ {
+ if ($file != '.' && $file != '..')
+ {
+ if (is_dir("$path$pd$file") && !is_link("$path$pd$file"))
+ {
+ $entry[] = "$path$pd$file";
+ }
+ }
+ }
+ closedir($dir);
+ for($i = 0; $i < count($entry); $i++)
+ {
+ $node->addItem(new HTML_TreeNode(array('text'=>basename(realpath($entry[$i])), 'link' => "javascript:setHelp('".addslashes(realpath($entry[$i]))."');", 'icon' => 'folder.gif')));
+ }
+ }
+
+ function recurseDir($path, &$node) {
+ global $pd;
+ if (!$dir = opendir($path)) {
+ return false;
+ }
+ $anode = new HTML_TreeNode(array('text' => basename($path), 'link' => "javascript:setHelpVal('".$path."');", 'icon' => 'folder.gif'));
+ $result = addslashes(realpath(stripslashes($path).$pd.".."));
+ if (!$node) $anode->addItem(new DirNode('..',"javascript:setHelp('".$result."');",'folder.gif'),'..');
+ while (($file = readdir($dir)) !== false) {
+ if ($file != '.' && $file != '..') {
+ if (is_dir("$path$pd$file")) {
+ recurseDir("$path$pd$file",$anode);
+ }
+ }
+ }
+ rewinddir($dir);//
+ while (false){//($file = readdir($dir)) !== false) {
+ if ($file != '.' && $file != '..') {
+ if (is_file("$path$pd$file")) {
+ $anode->addItem(new DirNode($file,"javascript:setHelpVal('$path$pd$file');",'branchtop.gif',"$path$pd$file"));
+ }
+ }
+ }
+ if (!$node) $node = $anode;
+ else
+ $node->addItem($anode);
+ closedir($dir);
+ }
+
+ function switchDirTree($path, &$node)
+ {
+ global $pd;
+
+ // initialize recursion simulation values
+ // array format: path => &parent in $node itemlist
+ $parent = array();
+ $parent_indexes = array();
+ $parenti = 1;
+
+ $node = new DirNode(basename($path),"javascript:setHelpVal('".$path."');",'folder.gif',$path);
+ $result = addslashes(realpath($path.$pd.".."));
+ $node->addItem(new DirNode('..',"javascript:setHelp('".$result."');",'folder.gif','..'));
+ $rnode = &$node;
+ $parent[realpath($path)] = false;
+ $recur = 0;
+ do
+ {
+ if ($recur++ > 120) return;
+ if (!$dir = @opendir($path)) {
+ // no child files or directories
+// echo "$path no child files or directories return to ";
+ $rnode = &$parent[realpath($path)];
+ $path = $rnode->path;
+ if (isset($parent_indexes[realpath($path)])) $parenti = $parent_indexes[realpath($path)];
+// echo "$path parenti $parenti<br>";
+ }
+// fancy_debug($path,$parent_indexes);
+// vdump_par($parent);
+ if (!isset($parent_indexes[realpath($path)]))
+ {
+ $file = readdir($dir);
+ while ($file !== false) {
+ if ($file != '.' && $file != '..') {
+ if (@is_dir(realpath("$path$pd$file"))) {
+ if (!isset($parent_indexes[realpath($path)])) $parent_indexes[realpath($path)] = true;
+ $parent[realpath("$path$pd$file")] = &$rnode;
+// echo "<br>adding new ".addslashes(realpath($path.$pd.$file))." to $path<br>";
+ $rnode->addItem(new DirNode(addslashes(realpath("$path$pd$file")),"javascript:setHelpVal('".addslashes(realpath($path.$pd.$file))."');",'folder.gif',addslashes(realpath($path.$pd.$file))));
+ }
+ }
+ $file = readdir($dir);
+ }
+ }
+ // go down the tree if possible
+ if (isset($parent_indexes[realpath($path)]))
+ {
+ if ($parenti + 1 > (count($rnode->items)))
+ {
+ // no more children, go back up to parent
+// echo "$path no more children, go back up to parent ";
+ $rnode = &$parent[realpath($path)];
+ $path = $rnode->path;
+ if (isset($parent_indexes[realpath($path)])) $parenti = $parent_indexes[realpath($path)];
+// echo $path." parenti $parenti<br>";
+ } else
+ {
+ // go to next child
+// echo "$path go to next child ";
+ $parent_indexes[realpath($path)] = $parenti+1;
+// debug("set parent ".$rnode->items[$parenti]->path." = ".$rnode->path.'<br>');
+ $parent[realpath($rnode->items[$parenti]->path)] = &$rnode;
+ $rnode = &$rnode->items[$parenti];
+ $path = $rnode->path;
+// echo "$path<br>";
+ $parenti = 0;
+ }
+ } else
+ {
+ // no children, go back up the tree to the next child
+// echo "$path no children, go back up to parent ";
+ $rnode = &$parent[realpath($path)];
+ $path = $rnode->path;
+ if (isset($parent_indexes[realpath($path)])) $parenti = $parent_indexes[realpath($path)];
+// echo "$path parenti $parenti<br>";
+ }
+ @closedir($dir);
+ } while ($path && (($parenti < (count($rnode->items))) || ($parent[realpath($path)] !== false)));
+ }
+
+ function vdump_par($tree)
+ {
+ foreach($tree as $key => $val)
+ {
+ if ($val === false)
+ debug($key.' -> false<br>');
+ else
+ debug($key.' -> ' .$val->path.'<br>');
+ }
+ debug('<br>');
+ }
+
+ $menu = new HTML_TreeMenu();
+ $filename = '';
+ if (isset($_GET) && isset($_GET['fileName'])) $filename = $_GET['fileName'];
+ $filename = realpath($filename);
+ $pd = (substr(PHP_OS, 0, 3) == 'WIN') ? '\\' : '/';
+ $test = ($pd == '/') ? '/' : 'C:\\';
+ if (empty($filename) || ($filename == $test))
+ {
+ $filename = ($pd == '/') ? '/' : 'C:\\';
+ $node = false;
+ getDir($filename,$node);
+ } else
+ {
+ flush();
+// if ($pd != '/') $pd = $pd.$pd;
+ $anode = false;
+ switchDirTree($filename,$anode);
+// recurseDir($filename,$anode);
+ $node = new HTML_TreeNode(array('text' => "Click to view $filename",'link' => "",'icon' => 'branchtop.gif'));
+ $node->addItem($anode);
+ };
+ $menu->addItem($node);
+ $DHTMLmenu = &new HTML_TreeMenu_DHTML($menu, array('images' => 'HTML_TreeMenu-1.1.2/images'));
+ ?>
+<script type="text/javascript" language="Javascript">
+/**
+ Creates some global variables
+*/
+function initializate() {
+ //
+ //The "platform independent" newLine
+ //
+ //Taken from http://developer.netscape.com/docs/manuals/communicator/jsref/brow1.htm#1010426
+if (navigator.appVersion.lastIndexOf('Win') != -1)
+ {
+ $pathdelim="\\";
+ $newLine="\r\n";
+ } else
+ {
+ $newLine="\n";
+ $pathdelim="/";
+ }
+/* for($a=0;$a<document.dataForm.elements.length;$a++) {
+ alert("The name is '"+document.dataForm.elements[$a].name+"' "+$a);
+ }
+*/
+}
+/** Sets the contents of the help box, and submits the form
+*/
+function setHelp($str)
+{
+ document.helpForm.fileName.value = $str;
+ document.helpForm.helpdata.click();
+}
+
+/** Sets the contents of the help box only
+*/
+function setHelpVal($str)
+{
+ document.helpForm.fileName.value = $str;
+}
+/**Adds the contents of the help box as a directory
+*/
+function addDirectory($object) {
+ $a = document.helpForm.fileName.value;
+ $a = myReplace($a,'\\\\','\\');
+ if ($a[$a.length - 1] == $pathdelim) $a = $a.substring(0, $a.length - 1);
+ if ($a.lastIndexOf('.') > 0)
+ {
+ $a = $a.substring(0,$a.lastIndexOf($pathdelim));
+ }
+ $object.value = prepareString($object.value)+$a;
+}
+/**Adds the contents of the converter box to the converters list
+*/
+function addConverter($object) {
+ $object.value = prepareString($object.value)+document.dataForm.ConverterSetting.value;
+}
+/**Replaces the converters list with the contents of the converter box
+*/
+function replaceConverter($object) {
+ $object.value = document.dataForm.ConverterSetting.value;
+}
+/**Adds the contents of the help box as a file to the given control
+*/
+function addFile($object) {
+ $a = document.helpForm.fileName.value;
+ $a = myReplace($a,'\\\\','\\');
+ $object.value = prepareString($object.value)+$a;
+}
+/**Takes a given string and leaves it ready to add a new string
+ That is, puts the comma and the new line if needed
+*/
+function prepareString($myString) {
+ //First verify that a comma is not at the end
+ if($myString.lastIndexOf(",") >= $myString.length-2) {
+ //We have a comma at the end
+ return $myString;
+ }
+ if($myString.length > 0) {
+ $myString+=","+$newLine;
+ }
+ return $myString;
+}
+/**Do the validation needed before sending the from and return a truth value indicating if the form can be sent
+*/
+ function validate() {
+ //Take out all newLines and change them by nothing
+ //This could be done by using javascript function's replacebut that was implemented only until Navigator 4.0 and so it is better to use more backward compatible functions like substr
+ document.dataForm.elements[0].value= stripNewLines(document.dataForm.elements[0].value);
+ document.dataForm.elements[1].value= stripNewLines(document.dataForm.elements[1].value);
+ document.dataForm.elements[2].value= stripNewLines(document.dataForm.elements[2].value);
+ document.dataForm.elements[3].value= stripNewLines(document.dataForm.elements[3].value);
+ document.dataForm.elements[4].value= stripNewLines(document.dataForm.elements[4].value);
+ document.dataForm.elements[5].value= stripNewLines(document.dataForm.elements[5].value);
+ document.dataForm.elements[6].value= stripNewLines(document.dataForm.elements[6].value);
+ document.dataForm.elements[7].value= stripNewLines(document.dataForm.elements[7].value);
+ //By returning true we are allowing the form to be submitted
+ return true;
+ }
+/**Takes a string and removes all the ocurrences of new lines
+Could have been implemented a lot easier with replace but it's not very backwards compatible
+*/
+ function stripNewLines($myString) {
+ return myReplace($myString,$newLine,'');
+ }
+ function myReplace($string,$text,$by) {
+ // Replaces text with by in string
+ var $strLength = $string.length, $txtLength = $text.length;
+ if (($strLength == 0) || ($txtLength == 0)) return $string;
+
+ var $i = $string.indexOf($text);
+ if ((!$i) && ($text != $string.substring(0,$txtLength))) return $string;
+ if ($i == -1) return $string;
+
+ var $newstr = $string.substring(0,$i) + $by;
+
+ if ($i+$txtLength < $strLength)
+ $newstr += myReplace($string.substring($i+$txtLength,$strLength),$text,$by);
+
+ return $newstr;
+ }
+</script><?php } ?>
+ </head>
+ <?php
+ //Find out if we are submitting and if we are, send it
+ // This code originally by Joshua Eichorn on phpdoc.php
+ //
+ if(isset($_GET['submit']) && empty($_REQUEST['altuserdir'])) {
+ echo "<body bgcolor=\"#ffffff\">";
+ echo "<h1>Parsing Files ...</h1>";
+ flush();
+ echo "<pre>\n";
+ /** phpdoc.inc */
+ include("phpDocumentor/phpdoc.inc");
+ echo "</pre>\n";
+ echo "<h1>Operation Completed!!</h1>";
+ } else
+ {
+ ?>
+ <body bgcolor="#ffffff" onload="javascript:initializate()">
+ <h1>
+ phpDocumentor v<?php print PHPDOCUMENTOR_VER; ?> Web Interface
+ </h1>
+ phpDocumentor written by Joshua Eichorn<br>
+ Web Interface written by Juan Pablo Morales and enhanced by Greg Beaver<br>
+ <img src="poweredbyphpdoc.gif" alt="" width="88" height="31" border="0">
+ <table cellpadding="1" cellspacing="1" border="0" width="60%" bgcolor=
+ "#000000">
+ <tr>
+ <td bgcolor="#ffff66">
+ <b>Help</b>
+ </td>
+ <td bgcolor="#ffff99">
+ use this to find directories and files which can be used below
+ <form name="helpForm" action="<?php print $_SERVER['PHP_SELF']; ?>" method="get"
+ enctype="multipart/form-data">
+ <input size="80" type="text" name="fileName" value="<?php print $filename;?>">
+ <input type="submit" name="helpdata" value="browse tree">
+ </form>
+<div id='menuLayer'></div>
+<?php
+ $DHTMLmenu->printMenu();
+?>
+ </td>
+ </tr>
+ </table>
+
+ <form name="dataForm" action="<?php print $_SERVER['PHP_SELF']; ?>" method="GET" onsubmit=
+ "return validate()">
+ <table cellpadding="3" cellspacing="3" border="0" width="80%"
+ bgcolor="#000000">
+ <tr>
+ <td bgcolor="#3399ff">
+ <b>Use a pre-created config file for form values.</b>
+ </td>
+ <td bgcolor="#CCCCCC">
+ Normally, phpDocumentor uses the form values from this form to set up parsing. In version 1.2,
+ phpDocumentor allows you to "save" form values in configuration files so that you can replicate
+ common complicated documentation tasks with only one time. Just choose a config file below or create a
+ new one and refresh this page to choose it.<hr /><b>change config directory:</b><input size="20" type="text" name="altuserdir" value=""><?php if (!empty($_REQUEST['altuserdir'])) print '<br><i>changed to <b>"'.$_REQUEST['altuserdir'].'"</b></i>'; ?>
+ <b>Choose a config:</b> <select name="setting[useconfig]">
+ <option value="" <?php if (empty($_REQUEST['altuserdir'])) print 'selected'; ?>>don't use config file</option>
+ <?php
+ $dirs = array();
+ $dirs = phpDocumentor_ConfigFileList($configdir);
+ $path = '';
+ $sel = ' selected';
+ if (!empty($_REQUEST['altuserdir'])) $path = $configdir . PATH_DELIMITER;
+ else $sel = '';
+ foreach($dirs as $configfile)
+ {
+ print '<option value="'.$path.$configfile.'"'.$sel.'>'.$configfile.".ini</option>\n";
+ $sel = '';
+ }
+ ?>
+ </select><input type="SUBMIT" value=
+ "Go" name="submitButton"><br>
+ </td>
+ </tr>
+ </tr>
+ <td bgcolor="#66cc66">
+ <b>Target</b>
+ </td>
+ <td bgcolor="#eeeeee">
+ Target is the directory where
+ the output produced by phpDocumentor will reside<br>
+ <input type="TEXT" name="setting[target]" size=
+ "80"><br>
+ <a href=
+ "javascript:addDirectory(document.dataForm.elements[3])">
+ Add the directory in the help box</a>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#3399ff">
+ <b>Files to parse</b>
+ </td>
+ <td bgcolor="#CCCCCC">
+ This is a group of comma-separated names of php files
+ or tutorials that will be processed by phpDocumentor.<br>
+<textarea rows="6" cols="80" name=
+"setting[filename]"></textarea> <br>
+ <a href=
+ "javascript:addFile(document.dataForm.elements[4])">
+ Add the file in the help box</a>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#66cc66">
+ <b>Directory to parse</b>
+ </td>
+ <td bgcolor="#eeeeee">
+ This is a group of comma-separated directories where php files
+ or tutorials are found that will be processed by phpDocumentor.
+ phpDocumentor automatically parses subdirectories<br>
+<textarea rows="6" cols="80" name="setting[directory]"></textarea> <br>
+ <a href=
+ "javascript:addDirectory(document.dataForm.elements[5])">
+ Add the directory in the help box</a>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#66cc66">
+ <b>Files to ignore</b>
+ </td>
+ <td bgcolor="#eeeeee">
+ A list of files (full path or filename), and patterns
+ to ignore. Patterns may use wildcards * and ?. To
+ ignore all subdirectories named "test" for example,
+ using "test/" To ignore all files and directories
+ with test in their name use "*test*"
+<textarea rows="6" cols="80" name="setting[ignore]"></textarea> <br>
+ <a href=
+ "javascript:addDirectory(document.dataForm.elements[6])">
+ Add the directory in the help box</a>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#66cc66">
+ <b>Generated Documentation Title</b>
+ </td>
+ <td bgcolor="#eeeeee">
+ Choose a title for the generated documentation<br>
+ <input type="TEXT" name="setting[title]" size=
+ "80" value="Generated Documentation"><br>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#3399ff">
+ <b>Default Package Name</b>
+ </td>
+ <td bgcolor="#cccccc">
+ Choose a name for the default package<br>
+ <input type="TEXT" name="setting[defaultpackagename]" size=
+ "80" value="default"><br>
+ </td>
+ <tr>
+ <tr>
+ <td bgcolor="#3399ff">
+ <b>Custom Tags</b>
+ </td>
+ <td bgcolor="#CCCCCC">
+ Custom Tags is a comma-separated list of tags
+ you want phpDocumentor to include as valid tags
+ in this parse. An example would be "value, size"
+ to allow @value and @size tags.
+ <input type="TEXT" name="setting[customtags]" size=
+ "80"><br>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#66cc66">
+ <b>Packages to parse</b>
+ </td>
+ <td bgcolor="#eeeeee">
+ The parameter packages is a group of comma
+ separated names of abstract packages that will
+ be processed by phpDocumentor. All package names must be
+ separated by commas.<br>
+<textarea rows="3" cols="80" name=
+"setting[packageoutput]"></textarea> <br>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#3399ff">
+ <b>Output Information</b>
+ </td>
+ <td bgcolor="#CCCCCC">
+ <br>
+ Outputformat
+ may be HTML, XML, PDF, or CHM (case-sensitive) in version 1.2. There is only one Converter
+ for both CHM and PDF, <b>default</b>. There are 2 HTML Converters,
+ <b>frames</b> and <b>Smarty</b>. <b>frames templates</b> may be any of:<br><br>
+ <b>default, l0l33t, phpdoc.de, phphtmllib, phpedit, DOM/default, DOM/l0l33t, or DOM/phpdoc.de</b>.
+ <b>Smarty templates</b> may be any of:<br><br>
+ <b>default or PHP</b>.<br>
+<br>
+There is only 1 template for all other Converters, <b>default</b>
+<br>Output type:Converter name:template name <input type=
+ "TEXT" name="setting[output]" value=
+ "HTML:Smarty:default" size="80"><br>
+<select name="ConverterSetting">
+<option value="HTML:frames:default">HTML:frames:default</option>
+<option value="HTML:frames:l0l33t">HTML:frames:l0l33t</option>
+<option value="HTML:frames:phpdoc.de">HTML:frames:phpdoc.de</option>
+<option value="HTML:frames:phphtmllib">HTML:frames:phphtmllib</option>
+<option value="HTML:frames:phpedit">HTML:frames:phpedit</option>
+<option value="HTML:frames:DOM/default">HTML:frames:DOM/default</option>
+<option value="HTML:frames:DOM/l0l33t">HTML:frames:DOM/l0l33t</option>
+<option value="HTML:frames:DOM/phpdoc.de">HTML:frames:DOM/phpdoc.de</option>
+<option value="HTML:Smarty:default" SELECTED>HTML:Smarty:default</option>
+<option value="PDF:default:default">PDF:default:default</option>
+<option value="CHM:default:default">CHM:default:default</option>
+<option value="XML:DocBook/peardoc2:default">XML:DocBook/peardoc2:default</option>
+</select><br>
+<a href=
+ "javascript:addConverter(document.dataForm.elements[11])">
+ Add the converter in the help box</a> <br>
+<a href=
+ "javascript:replaceConverter(document.dataForm.elements[11])">
+ Use ONLY the converter in the help box</a>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#3399ff">
+ <b>Parse @access private</b>
+ </td>
+ <td bgcolor="#CCCCCC">
+ The parameter Parse @access private tells phpDocumentor
+ whether to parse elements with an "@access private" tag in their docblock<br>
+ <input type="checkbox" name="setting[parseprivate]" value="on">Parse private <br>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#66cc66">
+ <b>JavaDoc-compliant Description parsing.</b>
+ </td>
+ <td bgcolor="#eeeeee">
+ Normally, phpDocumentor uses several rules to determine the short description. This switch
+ asks phpDocumentor to simply search for the first period (.) and use it to delineate the short
+ description. In addition, the short description will not be separated from the long description<br>
+ <input type="checkbox" name="setting[javadocdesc]" value="on">JavaDoc-compliant Description <br>
+ </td>
+ </tr>
+ </table>
+ <input type="HIDDEN" name="interface" value="web"> <input type=
+ "HIDDEN" name="submit" value="true"> <input type="SUBMIT" value=
+ "Create Documentation" name="submitButton">
+ </form>
+ <br>
+ <br>
+ <br>
+ <p>
+ Joshua Eichorn <a href="mailto:jeichorn@phpdoc.org">jeichorn@phpdoc.org</a><br>
+ Juan Pablo Morales <a href=
+ "mailto:ju-moral@uniandes.edu.co">ju-moral@uniandes.edu.co</a><br>
+ Gregory Beaver <a href=
+ "mailto:cellog@users.sourceforge.net">cellog@users.sourceforge.net</a>
+ </p>
+ <p>
+ If you have any problems with phpDocumentor, please visit the website: <a
+ href='http://phpdocu.sourceforge.net'>phpdocu.sourceforge.net</a> and
+ submit a bug
+ </p>
+ <!-- Created: Tue Jun 26 18:52:40 MEST 2001 -->
+ <!-- hhmts start -->
+<pre>
+Last modified: $Date: 2005/10/17 18:15:16 $
+Revision: $Revision: 1.1 $
+</pre>
+ <!-- hhmts end -->
+ <?php } //End the else that prints all code
+ ?>
+ </body>
+</html>
+
diff --git a/buildscripts/PhpDocumentor/pear-phpdoc b/buildscripts/PhpDocumentor/pear-phpdoc
new file mode 100644
index 00000000..258af7c8
--- /dev/null
+++ b/buildscripts/PhpDocumentor/pear-phpdoc
@@ -0,0 +1,38 @@
+#!@PHP-BIN@
+<?php
+//
+// PhpDoc, a program for creating javadoc style documentation from php code
+// Copyright (C) 2000-2001 Joshua Eichorn
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+//
+// Copyright 2000-2001 Joshua Eichorn
+// Email jeichorn@phpdoc.org
+// Web http://phpdoc.org/
+// Mirror http://phpdocu.sourceforge.net/
+// Project http://sourceforge.net/projects/phpdocu/
+//
+
+/**
+ * PHP auto documentor, like javadoc
+ * If you get an error uses this as a shell script then its been dosified
+ * @author Joshua Eichorn
+ * @version 1.3.0
+ * @copyright Joshua Eichorn
+ */
+include("PhpDocumentor/phpDocumentor/phpdoc.inc");
+?>
diff --git a/buildscripts/PhpDocumentor/pear-phpdoc.bat b/buildscripts/PhpDocumentor/pear-phpdoc.bat
new file mode 100644
index 00000000..04e3bcc3
--- /dev/null
+++ b/buildscripts/PhpDocumentor/pear-phpdoc.bat
@@ -0,0 +1,145 @@
+@ECHO OFF
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::
+:: Batch file to start phpDocumentor with PHP's CLI
+::
+:: This SW was contributed by BlueShoes www.blueshoes.org "The PHP Framework"
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+::----------------------------------------------------------------------------------
+:: Please set following to PHP's CLI
+:: NOTE: In PHP 4.2.x the PHP-CLI used to be named php-cli.exe.
+:: PHP 4.3.x names it php.exe but stores it in a subdir called /cli/php.exe
+:: E.g. for PHP 4.2 C:\phpdev\php-4.2-Win32\php-cli.exe
+:: for PHP 4.3 C:\phpdev\php-4.3-Win32\cli\php.exe
+
+ SET phpCli=@PHP-BIN@
+
+
+
+::---------------------------------------------------------------------------------
+::---------------------------------------------------------------------------------
+:: Do not modify below this line!! (Unless you know what your doing :)
+::---------------------------------------------------------------------------------
+::---------------------------------------------------------------------------------
+
+:: Only show this intro when no options are passed
+IF '%1'=='' (
+ ECHO ******************************************************************************
+ ECHO * PhpDocument Command-Line Starter
+ ECHO *
+ ECHO * phpDocumentor is a JavaDoc-like automatic documentation generator for PHP
+ ECHO * written in PHP. It is the most versatile tool for documenting PHP.
+ ECHO *
+ ECHO * This batch-file will try to run the phpDocumentor using the command-line
+ ECHO * version of PHP4. NOTE: It will not run with the PHP ISAPI module!
+ ECHO * Please update the path in this batch-file to your PHP-CLI.
+ ECHO *
+ ECHO * Tip: o Grab a copy of one of the ini-files in the user/ dir of the
+ ECHO * phpDocumentor and modify the settings there.
+ ECHO * o To see the command line options type phpdoc -h
+ ECHO *
+ ECHO * @version 1.3 2003-06-28
+ ECHO * @author Sam Blum sam@blueshoes.org
+ ECHO * @Copyright Free Software released under the GNU/GPL license
+ ECHO *
+ ECHO * This SW was contributed by BlueShoes www.blueshoes.org "The PHP Framework"
+ ECHO ******************************************************************************
+)
+
+:: Check existence of php.exe
+IF EXIST "%phpCli%" (
+ SET doNothing=
+) ELSE GOTO :NoPhpCli
+
+:: If called using options, just call phpdoc and end after without pausing.
+:: This will allow use where pausing is not wanted.
+IF '%1'=='' (
+ SET doNothing=
+) ELSE (
+ "%phpCli%" "@BIN-DIR@\phpdoc" %*
+ GOTO :EOF
+)
+
+
+SET iniFile=
+
+ECHO ------------------------------------------------------------------------------
+ECHO Select Ini-File [default is phpDocumentor.ini]
+ECHO ------------------------------------------------------------------------------
+ECHO # 0: phpDocumentor.ini
+SET count=0
+FOR /R "@DATA-DIR@\PhpDocumentor\user" %%I IN (*.ini) DO (
+ SET /a count+=1
+ CALL :exec ECHO # %%count%%: %%~nI%%~xI
+)
+
+:LOOP_1
+:: SET /P prompts for input and sets the variable
+:: to whatever the user types
+SET iniNr=
+SET /P iniNr=Type a number and press Enter[0]:
+
+:: Use default
+IF '%iniNr%'=='' (
+ SET iniNr=0
+)
+
+:: Check for default selection
+SET iniFile=phpDocumentor.ini
+IF %iniNr%==0 (
+ CALL :exec GOTO :run
+ GOTO :PAUSE_END
+)
+
+:: Check selected
+SET count=0
+SET found=
+FOR /R "@DATA-DIR@\PhpDocumentor\user" %%I IN (*.ini) DO (
+ SET /a count+=1
+ SET iniFile=%%~nI%%~xI
+ CALL :exec IF '%%iniNr%%'=='%%count%%' GOTO :run
+)
+
+:: Check if selected # was found
+IF '%found%'=='' (
+ ECHO Invalid input [%iniNr%]... try again
+ ECHO.
+ GOTO :LOOP_1
+)
+
+::
+:: php.exe not found error
+GOTO :PAUSE_END
+:NoPhpCli
+ECHO ** ERROR *****************************************************************
+ECHO * Sorry, can't find the php.exe file.
+ECHO * You must edit this file to point to your php.exe (CLI version!)
+ECHO * [Currently set to %phpCli%]
+ECHO *
+ECHO * NOTE: In PHP 4.2.x the PHP-CLI used to be named php-cli.exe.
+ECHO * PHP 4.3.x renamed it php.exe but stores it in a subdir
+ECHO * called /cli/php.exe
+ECHO * E.g. for PHP 4.2 C:\phpdev\php-4.2-Win32\php-cli.exe
+ECHO * for PHP 4.3 C:\phpdev\php-4.3-Win32\cli\php.exe
+ECHO **************************************************************************
+
+::
+:: Stupid MS-batch: Can't evaluate environment variable inside a FOR loop!!! :((
+GOTO :PAUSE_END
+:exec
+%*
+GOTO :EOF
+
+::
+:: Start the phpDocumentor
+GOTO :PAUSE_END
+:run
+SET found=1
+ECHO Starting: "%phpCli%" "@BIN-DIR@\phpdoc" -c "%iniFile%"
+ECHO.
+"%phpCli%" "@BIN-DIR@\phpdoc" -c "%iniFile%"
+GOTO :EOF
+
+:PAUSE_END
+PAUSE \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor.ini b/buildscripts/PhpDocumentor/phpDocumentor.ini
new file mode 100644
index 00000000..bbb01631
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor.ini
@@ -0,0 +1,118 @@
+;; phpDocumentor.ini
+;;
+;; contains all the runtime values that are configurable.
+;; This is moved from phpdoc.inc, to remove the necessity to edit the php code and
+;; simplify debugging
+[DEBUG]
+;; If you want to see the internals of the parser in action, set this to true
+PHPDOCUMENTOR_DEBUG = false
+;; set to true if you want to eliminate extra whitespace in doc comments (slows things down quite a bit)
+PHPDOCUMENTOR_KILL_WHITESPACE = false
+
+[_phpDocumentor_options]
+;; this is the value that will be displayed as the root directory
+Program_Root =
+;; uncomment this to set the path phpDocumentor looks in to find user files
+;userdir = user/
+
+;; Use useconfig if you want to be able to run phpdoc with no command-line options (!!)
+;; change the value of useconfig to an .ini file that is in users/ (like greg.ini)
+;[_phpDocumentor_setting]
+;useconfig = default
+
+[_phpDocumentor_phpfile_exts]
+php
+php3
+php4
+phtml
+inc
+
+;; deprecated in 1.2
+;; this list is informational only - the following tags will be parsed as
+;; having meaning, everything else will be treated as text by the output
+;; converter, meaning in the HTML converter, all other tags will be htmlentitied
+;[_phpDocumentor_html_allowed]
+;ul
+;ol
+;li
+;p
+;strong
+;pre
+;a
+;code
+;br
+;var
+;samp
+;kbd
+
+[_phpDocumentor_tags_allowed]
+abstract
+access
+author
+category
+copyright
+;; for Zend IDE support - minimal at best
+desc
+deprec
+deprecated
+example
+exception
+filesource
+final
+global
+ignore
+internal
+license
+link
+magic
+name
+package
+param
+parameter
+return
+;; alias for @return
+returns
+see
+since
+source
+static
+staticvar
+subpackage
+throws
+todo
+TODO
+tutorial
+uses
+var
+version
+;; compat tags, things wont parse right in incorrectly documented code without them
+;; hopefully better error handling in handleDockeyword allows these to go away
+;; this is a dumb tag included for pear compatability see bug# 558028
+extends
+private
+public
+
+[_phpDocumentor_inline_doc_tags_allowed]
+example
+inheritdoc
+internal
+link
+source
+tutorial
+
+[_phpDocumentor_inline_tutorial_tags_allowed]
+category
+example
+id
+link
+toc
+tutorial
+
+;; custom files to include in RIC
+;; these MUST be in upper-case
+[_phpDocumentor_RIC_files]
+README
+INSTALL
+CHANGELOG
+FAQ
+NEWS
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Classes.inc b/buildscripts/PhpDocumentor/phpDocumentor/Classes.inc
new file mode 100644
index 00000000..d4f29745
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Classes.inc
@@ -0,0 +1,1068 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * Intermediate class parsing structure.
+ * @package phpDocumentor
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: Classes.inc,v 1.1 2005/10/17 18:36:55 jeichorn Exp $
+ */
+/**
+ * Intermediate class parsing structure.
+ *
+ * The {@link phpDocumentor_IntermediateParser} class uses this class and its
+ * cousin, {@link ProceduralPages} to organize all parsed source code elements.
+ * Data is fed to each immediately after it is parsed, and at conversion time,
+ * everything is organized.
+ *
+ * The Classes class is responsible for all inheritance, including resolving
+ * name conflicts between classes, determining which classes extend other
+ * classes, and is responsible for all inheritance of documentation.
+ * {@internal
+ * This structure parses classes, vars and methods by file, and then iterates
+ * over the class tree to set up inheritance. The {@link Inherit()}
+ * method is the meat of the class, and processes the class trees from root to
+ * branch, ensuring that parsing order is unimportant.}}
+ * @package phpDocumentor
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: Classes.inc,v 1.1 2005/10/17 18:36:55 jeichorn Exp $
+ */
+class Classes
+{
+ /**#@+
+ * @access private
+ */
+ /**
+ * file being parsed, used in every add function to match up elements with
+ * the file that contains them
+ *
+ * This variable is used during parsing to associate class elements added
+ * to the data structures that contain them with the file they reside in
+ * @see addClass(), addMethod(), addVar(), nextFile()
+ * @var string
+ */
+ var $curfile;
+ /**
+ * class being parsed, used to match up methods and vars with their parent
+ * class
+ *
+ * This variable is used during parsing to associate class elements added
+ * to the data structures that contain them with the file they reside in
+ * @see addMethod(), addVar()
+ * @var string
+ */
+ var $curclass;
+
+ /**
+ * Used when a definite match is made between a parent class and a child
+ * class
+ *
+ * This variable is used in post-parsing.
+ *
+ * Format: array(parent => array(parentfile => array(child => childfile)))
+ * @var array
+ */
+ var $definitechild;
+ /**
+ * array of parsed classes organized by the name of the file that contains
+ * the class.
+ *
+ * Format:
+ * array(filename => array(classname => {@link parserClass}))
+ * @var array
+ */
+ var $classesbyfile = array();
+ /**
+ * array of file names organized by classes that are in the file.
+ *
+ * This structure is designed to handle name conflicts. Two files can
+ * contain classes with the same name, and this array will record both
+ * filenames to help control linking and inheritance errors
+ *
+ * Format:<pre>
+ * array(classname => array(name of file containing classname,
+ * name of file 2 containing classname...)</pre>
+ * @var array
+ */
+ var $classesbynamefile = array();
+ /**
+ * array of parsed methods organized by the file that contains them.
+ *
+ * Format:<pre>
+ * array(filename => array(classname => array({@link parserMethod} 1,
+ * {@link parserMethod} 2,...))</pre>
+ * @var array
+ */
+ var $methodsbyfile = array();
+ /**
+ * array of parsed vars organized by the file that contains them.
+ *
+ * Format:
+ * array(filename => array(classname => array({@link parserVar} 1, {@link parserVar} 2,...))
+ * @var array
+ */
+ var $varsbyfile = array();
+ /**
+ * array of parsed class constants organized by the file that contains them.
+ *
+ * Format:
+ * array(filename => array(classname => array({@link parserConst} 1, {@link parserConst} 2,...))
+ * @var array
+ */
+ var $constsbyfile = array();
+ /**
+ * keeps track of extend declarations by file, used to find inheritance
+ *
+ * Format:
+ * array(filename => array(classname => parentclassname))
+ * @var array
+ */
+ var $extendsbyfile = array();
+ /**
+ * Keeps track of child classes by file.
+ * Since phpDocumentor can document collections of files that contain name
+ * conflicts (PHP would give a fatal error), it
+ * is impossible to assume a class that declares "extends foo" necessarily
+ * extends the class foo in file X. It could be an
+ * extended class of class foo in file Y. Because of this, phpDocumentor
+ * relies on packaging to resolve the name conflict
+ * This array keeps track of the packages of a child class
+ *
+ * Format:
+ * array(parentclassname => array(filename => array(childclassname =>
+ * array(packagename, packagename)))
+ * @var array
+ */
+ var $classchildrenbyfile = array();
+ /**
+ * Keeps track of class packages found in a file.
+ * This is used in {@link getParentClass()} to determine the number of
+ * packages in a file, in order to resolve inheritance issues
+ * Format: array(filename => array(packagename1, packagename2,...))
+ * @var array
+ */
+ var $classpackagebyfile = array();
+ /**
+ * a tree of class inheritance by name.
+ *
+ * format:<pre>
+ * array(childname => parentname,
+ * childname1 => parentname1,
+ * rootname => 0, ...
+ * )</pre>
+ * @var array
+ * @see Converter::generateSortedClassTreeFromClass()
+ */
+ var $classparents = array();
+ /**
+ * Keeps track of package and subpackage for each class name, organized
+ * by package
+ *
+ * Format:<pre>
+ * array(classname => array(path => array(package,subpackage),
+ * path2 => array(package,subpackage),...))</pre>
+ * @var array
+ */
+ var $classpathpackages = array();
+ /**
+ * used to delete duplicates in the same package to avoid documentation errors
+ *
+ * Specifically used in {@link Converter::checkKillClass()}
+ */
+ var $killclass = array();
+ /**
+ * array of methods by package and class
+ *
+ * format:<pre>
+ * array(packagename =>
+ * array(classname =>
+ * array(methodname1 => {@link parserMethod} class,
+ * methodname2 => {@link parserMethod} class,...)
+ * )
+ * )
+ * )</pre>
+ * @var array
+ * @see Converter
+ */
+ var $methods = array();
+
+ /**
+ * array of class variables by package and class
+ *
+ * format:<pre>
+ * array(packagename =>
+ * array(classname =>
+ * array(variablename1 => {@link parserVar} class,
+ * variablename2 => {@link parserVar} class,...
+ * )
+ * )
+ * )</pre>
+ * @var array
+ * @see Converter
+ */
+ var $vars = array();
+
+ /**
+ * array of class variables by package and class
+ *
+ * format:<pre>
+ * array(packagename =>
+ * array(classname =>
+ * array(constname1 => {@link parserConst} class,
+ * constname2 => {@link parserConst} class,...
+ * )
+ * )
+ * )</pre>
+ * @var array
+ * @see Converter
+ */
+ var $consts = array();
+ /**
+ * Reverse class_packages_by_file, used to prevent duplicates
+ * @var array Format: array(packagename => 1)
+ */
+ var $revcpbf = array();
+ /**
+ * All classes with no parents (no extends clause) are tracked in this array
+ * by the file that contains them.
+ *
+ * Format:<pre>
+ * array(classname => array(name of file1 that contains root classname,
+ * name of file2 that contains root classname,...))</pre>
+ * @var array
+ */
+ var $roots = array();
+
+ /**
+ * array of all files that contain classes with the same name
+ * @var array Format: (classname => array(path1, path2,...))
+ */
+ var $potentialclassconflicts = array();
+
+ /**
+ * array of all inter-package name conflicts of classes
+ *
+ * This array allows documentation of PHP namespace conflicts that would
+ * occur should a user try to include these files in the same file
+ * @var array Format: (classname => array(path1, path2,...))
+ */
+ var $classconflicts = array();
+ /**#@-*/
+ /**
+ * While parsing, add a class to the list of parsed classes
+ *
+ * sets up the {@link $classesbyfile, $classesbynamefile, $extendsbyfile},
+ * {@link $classchildrenbyfile, $roots} arrays, and sets {@link $curclass}
+ * @param parserClass &$element element is a {@link parserClass}
+ * @uses addPackageToFile() marks the current class's package as being
+ * present in a file
+ */
+ function addClass(&$element)
+ {
+ $this->curclass = $element->getName();
+ $element->curfile = $this->curfile;
+ if (isset($this->classesbyfile[$this->curfile][$this->curclass]))
+ {
+ addWarning(PDERROR_ELEMENT_IGNORED,'class',$this->curclass,$this->curfile);
+ $this->curclass = false;
+ return;
+ }
+ $this->classesbyfile[$this->curfile][$this->curclass] = $element;
+ $this->classesbynamefile[$this->curclass][] = $this->curfile;
+ $this->extendsbyfile[$this->curfile][$this->curclass] = $element->getExtends();
+ $this->classchildrenbyfile[$element->getExtends()][$this->curfile][$this->curclass][] = $element->docblock->package;
+ if ($element->docblock->getExplicitPackage())
+ $this->addPackageToFile($element->docblock->package);
+ if (!$element->getExtends())
+ {
+ $this->roots[$this->curclass][] = $this->curfile;
+ }
+ }
+
+ /**
+ * While parsing, add a method to the list of parsed methods
+ *
+ * sets up the {@link $methodsbyfile} array using {@link $curfile} and
+ * {@link $curclass}
+ * @param parserMethod &$element element is a {@link parserMethod}
+ */
+ function addMethod(&$element)
+ {
+ if (!$this->curclass) return;
+ $this->methodsbyfile[$this->curfile][$this->curclass][] = $element;
+ }
+
+ /**
+ * While parsing, add a variable to the list of parsed variables
+ *
+ * sets up the {@link $varsbyfile} array using {@link $curfile} and {@link $curclass}
+ * @param parserVar &$element element is a {@link parserVar}
+ */
+ function addVar(&$element)
+ {
+ if (!$this->curclass) return;
+ $this->varsbyfile[$this->curfile][$this->curclass][] = $element;
+ }
+
+ /**
+ * While parsing, add a variable to the list of parsed variables
+ *
+ * sets up the {@link $constsbyfile} array using {@link $curfile} and {@link $curclass}
+ * @param parserConst &$element element is a {@link parserConst}
+ */
+ function addConst(&$element)
+ {
+ if (!$this->curclass) return;
+ $this->constsbyfile[$this->curfile][$this->curclass][] = $element;
+ }
+
+ /**
+ * Prepare to parse a new file
+ *
+ * sets {@link $curfile} to $file and {@link $curclass} to false (no class being parsed)
+ * @param string $file file currently being parsed
+ */
+ function nextFile($file)
+ {
+ $this->curfile = $file;
+ $this->curclass = false;
+ }
+
+ /**
+ * Mark a package as being used in a class
+ *
+ * {@source}
+ * @param string $package package name
+ */
+ function addPackageToFile($package)
+ {
+ if (!isset($this->revcpbf[$this->curfile][$package]))
+ $this->classpackagebyfile[$this->curfile][] = $package;
+ $this->revcpbf[$this->curfile][$package] = 1;
+ }
+
+ /**
+ * Find the parent class of $class, and set up structures to note this fact
+ *
+ * Modifies the {@link parserClass} element in {@link $classesbyfile} to use
+ * the parent's package, and inherit methods/vars
+ * @param string $class child class to find parent class
+ * @param string $file file child class is located in
+ * @uses $definitechild if a match is made between a parent class and parameter
+ * $class in file $file, then definitechild is set here
+ * @uses getParentClass() to find the parent class
+ */
+ function setClassParent($class,$file)
+ {
+ if (is_array($par = $this->getParentClass($class,$file)))
+ {
+// phpDocumentor_out("$file class $class extends ".$par[1]." file ".$par[0]."\n");
+ $this->classesbyfile[$file][$class]->setParent($par[1],$par[0],$this);
+ $this->definitechild[$par[1]][$par[0]][$class] = $file;
+ } else
+ {
+ $this->classesbyfile[$file][$class]->setParentNoClass($par);
+ }
+ }
+
+ /**
+ * Main processing engine for setting up class inheritance.
+ *
+ * This function uses {@link $roots} to traverse the inheritance tree via
+ * {@link processChild()} and returns the data structures
+ * phpDocumentor_IntermediateParser needs to convert parsed data
+ * to output using {@link phpDocumentor_IntermediateParser::Convert()}
+ * @param phpDocumentor_IntermediateParser
+ * @uses processChild() set up inheritance
+ */
+ function Inherit(&$render)
+ {
+ phpDocumentor_out("\nProcessing Class Inheritance\n\n");
+ flush();
+ phpDocumentor_out("\nProcessing Root Trees\n\n");
+ flush();
+ foreach($this->roots as $class => $files)
+ {
+ for ($i=0; $i<count($files); $i++)
+ {
+ $this->processChild($render,$class,$files[$i]);
+ }
+ }
+ if (0)
+ foreach($this->classesbyfile as $i => $j)
+ {
+ foreach($j as $k => $m)
+ {
+ var_dump($i,$k);
+ if ($i == 'iConverter')
+ {
+ var_dump($j);
+ }
+ }
+ }
+ phpDocumentor_out("\nProcessing leftover classes (classes that extend root classes not found in the same package)\n");
+ flush();
+ foreach($this->classesbyfile as $i => $j)
+ {
+ foreach($j as $k => $m)
+ {
+ $this->processChild($render,$k,$i,true);
+ }
+ }
+ phpDocumentor_out("done processing leftover classes\n");
+ flush();
+ $this->setupClassConflicts();
+ }
+
+ /**
+ * Transfers actual conflicts from {@link $potentialClassconflicts} to
+ * {@link $classconflicts}
+ * @access private
+ * @uses $potentialclassconflicts transfers values to {@link $classconflicts}
+ */
+ function setupClassConflicts()
+ {
+ foreach($this->potentialclassconflicts as $class => $paths)
+ {
+ if (count($paths) - 1)
+ { //conflict
+ $package = array();
+ foreach($paths as $path)
+ {
+ // create a list of conflicting classes in each package
+ if (isset($this->classpathpackages[$class][$path]))
+ $package[$this->classpathpackages[$class][$path][0]][] = $path;
+ }
+ foreach($package as $pathpackages)
+ {
+ // if at least 2 functions exist in the same package, delete all but the first one and add warnings
+ if (count($pathpackages) - 1)
+ {
+ for($i=1; $i < count($pathpackages); $i++)
+ {
+ if (isset($this->classesbyfile[$pathpackages[$i]]))
+ {
+ addWarning(PDERROR_ELEMENT_IGNORED,'class',$class,$pathpackages[$i]);
+ $this->killClass($class,$pathpackages[$i]);
+ $oth = array_flip($paths);
+ unset($paths[$oth[$pathpackages[$i]]]);
+ }
+ }
+ }
+ }
+ $this->classconflicts[$class] = $paths;
+ }
+ }
+ }
+
+ /**
+ * If a package contains two classes with the same name, this function finds
+ * that conflict
+ *
+ * Returns the {@link $classconflicts} entry for class $class, minus its own path
+ * @return mixed returns false if no conflicts, or an array of paths containing conflicts
+ */
+ function getConflicts($class)
+ {
+ if (!isset($this->classconflicts[$class])) return false;
+ $a = array();
+ foreach($this->classconflicts[$class] as $conflict)
+ {
+ $a[$this->classesbyfile[$conflict][$class]->docblock->package] = $this->classesbyfile[$conflict][$class];
+ }
+ return $a;
+ }
+
+ /**
+ * sets up {@link $killclass} for use by Converter::checkKillClass()
+ * @access private
+ */
+ function killClass($class,$path)
+ {
+ $this->killclass[$class][$path] = true;
+ }
+
+ /**
+ * This function recursively climbs up the class tree, setting inherited
+ * information like package and adds the elements to phpDocumentor_IntermediateParser.
+ *
+ * Using structures defined in {@link Classes}, the function first sets package information,
+ * and then seeks out child classes.
+ * It uses 3 tests to determine whether a class is a child class.
+ * <ol>
+ * <li>child class is in the same file as the parent class and extends parent class</li>
+ * <li>child class is in a different file and specifies the parent's @package in its docblock</li>
+ * <li>child class is in a different file and is in a different @package, with one possible parent class</li>
+ * </ol>
+ * @param phpDocumentor_IntermediateParser &$render
+ * @param string $class class to process
+ * @param string $file name of file $class is located in
+ * @param boolean $furb flag used privately to control informational output while parsing
+ * (used when processing leftover classes in {@link Inherit()}
+ * @global string default package, usually "default"
+ */
+ function processChild(&$render,$class,$file,$furb = false)
+ {
+ global $phpDocumentor_DefaultPackageName;
+ if (isset($this->classesbyfile[$file][$class]->processed)) return;
+ $this->potentialclassconflicts[$class][] = $file;
+ if ($furb) phpDocumentor_out("Processing $class in file $file\n");
+ flush();
+ $this->classesbyfile[$file][$class]->processed = true;
+ $db = $this->classesbyfile[$file][$class];
+ $render->addUses($db,$file);
+ if (!$render->parsePrivate)
+ {
+ // if this class has an @access private, and parse private is disabled, remove it
+ if ($db->docblock->hasaccess)
+ {
+ $aaa = $db->docblock->getKeyword('access');
+ if (is_object($aaa) && $aaa->getString() == 'private')
+ {
+ if (isset($this->varsbyfile[$file]) && isset($this->varsbyfile[$file][$class]))
+ {
+ unset($this->varsbyfile[$file][$class]);
+ }
+ if (isset($this->methodsbyfile[$file]) && isset($this->methodsbyfile[$file][$class]))
+ {
+ unset($this->methodsbyfile[$file][$class]);
+ }
+ if (isset($this->constsbyfile[$file]) && isset($this->constsbyfile[$file][$class]))
+ {
+ unset($this->constsbyfile[$file][$class]);
+ }
+ $this->classesbyfile[$file][$class]->ignore = true;
+ // if this is a root class, remove it from the roots array
+ if (isset($this->roots[$class]))
+ foreach($this->roots[$class] as $i => $files)
+ {
+ // find the file kkey and unset
+ if ($files == $file) unset($this->roots[$class][$i]);
+ }
+ // if this is a child, remove it from the list of child classes of its parent
+ if ($db->getExtends()) unset($this->classchildrenbyfile[$db->getExtends()][$file]);
+ return;
+ }
+ }
+ }
+ if ($render->packageoutput)
+ {
+ if (!in_array($db->docblock->package,$render->packageoutput))
+ {
+ if (isset($this->varsbyfile[$file]) && isset($this->varsbyfile[$file][$class]))
+ {
+ unset($this->varsbyfile[$file][$class]);
+ }
+ if (isset($this->methodsbyfile[$file]) && isset($this->methodsbyfile[$file][$class]))
+ {
+ unset($this->methodsbyfile[$file][$class]);
+ }
+ if (isset($this->constsbyfile[$file]) && isset($this->constsbyfile[$file][$class]))
+ {
+ unset($this->constsbyfile[$file][$class]);
+ }
+ $this->classesbyfile[$file][$class]->ignore = true;
+ if (isset($this->roots[$class]))
+ foreach($this->roots[$class] as $i => $files)
+ {
+ if ($files == $file) unset($this->roots[$class][$i]);
+ }
+ if ($db->getExtends()) unset($this->classchildrenbyfile[$db->getExtends()][$file]);
+ return;
+ }
+ }
+ $this->setClassParent($class,$file);
+ $db = $this->classesbyfile[$file][$class];
+ if ($furb && !is_array($db->parent))
+ {
+// debug("furb adding $class $file to roots");
+ $this->roots[$class][] = $file;
+ }
+ // fix for 591396
+ if (!$db->docblock->getExplicitPackage())
+ {
+ $a = $render->proceduralpages->pagepackages[$file];
+ if ($a[0] != $phpDocumentor_DefaultPackageName)
+ {
+ // inherit page package
+ $this->classesbyfile[$file][$class]->docblock->package = $a[0];
+ }
+ }
+ if ($this->classesbyfile[$file][$class]->docblock->package == $render->proceduralpages->pagepackages[$file][0])
+ {
+ if ($this->classesbyfile[$file][$class]->docblock->subpackage == '')
+ $this->classesbyfile[$file][$class]->docblock->subpackage = $render->proceduralpages->pagepackages[$file][1];
+ }
+ $db = $this->classesbyfile[$file][$class];
+ $render->addPackageParent($db);
+ $render->addPageIfNecessary($file, $db);
+ if ($access = $db->docblock->getKeyword('access'))
+ {
+ if (!is_string($access) && is_object($access)) $access = $access->getString();
+ if (!is_string($access)) $access = 'public';
+ if (($access == 'private') && (!$render->parsePrivate))
+ {
+ if (isset($this->varsbyfile[$file]) && isset($this->varsbyfile[$file][$class]))
+ foreach($this->varsbyfile[$file][$class] as $i => $vr)
+ {
+ $vr->docblock->addKeyword('access','private');
+ $this->varsbyfile[$file][$class][$i] = $vr;
+ }
+ if (isset($this->methodsbyfile[$file]) && isset($this->methodsbyfile[$file][$class]))
+ foreach($this->methodsbyfile[$file][$class] as $i => $vr)
+ {
+ $vr->docblock->addKeyword('access','private');
+ $this->methodsbyfile[$file][$class][$i] = $vr;
+ }
+ if (isset($this->constsbyfile[$file]) && isset($this->constsbyfile[$file][$class]))
+ foreach($this->constsbyfile[$file][$class] as $i => $vr)
+ {
+ $vr->docblock->addKeyword('access','private');
+ $this->constsbyfile[$file][$class][$i] = $vr;
+ }
+ }
+ }
+ $this->classpathpackages[$class][$file] = array($db->docblock->package,$db->docblock->subpackage);
+ if ($db->docblock->getExplicitPackage())
+ $render->proceduralpages->addClassPackageToFile($file,$db->docblock->package,$db->docblock->subpackage);
+ $render->addElementToPage($db,$file);
+ if (isset($this->varsbyfile[$file]) && isset($this->varsbyfile[$file][$class]))
+ foreach($this->varsbyfile[$file][$class] as $i => $vr)
+ {
+ $vr->docblock->package = $db->docblock->package;
+ $vr->docblock->subpackage = $db->docblock->subpackage;
+ $render->addElementToPage($vr,$file);
+ $render->addUses($vr,$file);
+ $this->varsbyfile[$file][$class][$i] = $vr;
+ $this->vars[$db->docblock->package][$class][$vr->getName()] = $vr;
+ }
+ if (isset($this->methodsbyfile[$file]) && isset($this->methodsbyfile[$file][$class]))
+ foreach($this->methodsbyfile[$file][$class] as $i => $vr)
+ {
+ $vr->docblock->package = $db->docblock->package;
+ $vr->docblock->subpackage = $db->docblock->subpackage;
+ $render->addElementToPage($vr,$file);
+ $render->addUses($vr,$file);
+ $this->methodsbyfile[$file][$class][$i] = $vr;
+ $this->methods[$db->docblock->package][$class][$vr->getName()] = $vr;
+ }
+ if (isset($this->constsbyfile[$file]) && isset($this->constsbyfile[$file][$class]))
+ foreach($this->constsbyfile[$file][$class] as $i => $vr)
+ {
+ $vr->docblock->package = $db->docblock->package;
+ $vr->docblock->subpackage = $db->docblock->subpackage;
+ $render->addElementToPage($vr,$file);
+ $render->addUses($vr,$file);
+ $this->constsbyfile[$file][$class][$i] = $vr;
+ $this->methods[$db->docblock->package][$class][$vr->getName()] = $vr;
+ }
+ $this->classpackages[$class][] = array($db->docblock->package,$db->docblock->subpackage);
+ if (is_array($db->parent))
+ $this->classparents[$db->docblock->package][$class] = $db->parent[1];
+ else
+ $this->classparents[$db->docblock->package][$class] = $db->getExtends();
+ if (is_array($db->parent))
+ {
+ $z = $this->getClass($db->parent[1],$db->parent[0]);
+ $this->classchildren[$z->docblock->package][$db->parent[1]][] = $db;
+ }
+ if (isset($this->classchildrenbyfile[$class]))
+ {
+ foreach($this->classchildrenbyfile[$class] as $childfile => $other)
+ {
+ // test 1, inherits in same file (must be same package)
+ if ($childfile == $file)
+ {
+ foreach($other as $child => $packages)
+ {
+// debug("parent $class same file $child");
+ $this->processChild($render,$child,$childfile);
+ $x = $this->getClass($child,$childfile);
+ if ($x->docblock->package != $GLOBALS['phpDocumentor_DefaultPackageName'])
+ {
+ // child package need root for class trees
+ if ($x->docblock->package != $db->docblock->package)
+ {
+// debug("adding $child in $childfile 1");
+ $this->roots[$child][] = $childfile;
+ }
+ }
+ }
+ } else
+ {
+ // test 2, different file, same package
+ foreach($other as $child => $packages)
+ {
+ for($j=0; $j<count($packages); $j++)
+ {
+ if ($this->classesbyfile[$file][$class]->docblock->package == $packages[$j])
+ {
+ $this->processChild($render,$child,$childfile);
+// debug("$childfile diff file $child, parent $class, same package ".$packages[$j]);
+ } else
+ {
+ // test 3, different file, different package, only 1 parent is possible
+ if (isset($this->classesbynamefile[$child]))
+ {
+ // 1 possible parent
+ if (count($this->classesbynamefile[$class]) == 1)
+ {
+// debug("$childfile diff file $child, diff package, 1 possible parent root $class");
+ $this->processChild($render,$child,$childfile);
+ $x = $this->getClass($child,$childfile);
+ if ($x->docblock->package != $GLOBALS['phpDocumentor_DefaultPackageName'])
+ {
+ // child package need root for class trees
+ if ($x->docblock->package != $db->docblock->package)
+ {
+// debug("adding roots $child in $childfile 2");
+ $this->roots[$child][] = $childfile;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Get the parserClass representation of a class from its name and file
+ * @return parserClass
+ * @param string $class classname
+ * @param string $file file classname is located in
+ */
+ function &getClass($class, $file)
+ {
+// debug("getClass called with class $class file $file");
+ return $this->classesbyfile[$file][$class];
+ }
+
+ /**
+ * Used by {@link parserData::getClasses()} to retrieve classes defined in file $path
+ *
+ * retrieves the array entry from {@link $classesbyfile} for $path
+ * @param string $path full path to filename
+ * @return mixed returns false if no classes defined in the file, otherwise returns an array of {@link parserClass}es
+ */
+ function getClassesInPath($path)
+ {
+ if (!isset($this->classesbyfile[$path])) return false;
+ return $this->classesbyfile[$path];
+ }
+
+ /**
+ * called by {@link parserClass::hasMethods()}. Should not be directly called
+ * @access private
+ * @param string $file
+ * @param string $class
+ */
+ function hasMethods($file,$class)
+ {
+ return isset($this->methodsbyfile[$file][$class]);
+ }
+
+ /**
+ * called by {@link parserClass::hasConsts()}. Should not be directly called
+ * @access private
+ * @param string $file
+ * @param string $class
+ */
+ function hasConsts($file,$class)
+ {
+ return isset($this->constsbyfile[$file][$class]);
+ }
+
+ /**
+ * called by {@link parserClass::hasVars()}. Should not be directly called
+ * @access private
+ * @param string $file
+ * @param string $class
+ */
+ function hasVars($file, $class)
+ {
+ return isset($this->varsbyfile[$file][$class]);
+ }
+
+ /**
+ * called by {@link parserClass::hasMethod()}. Should not be directly called
+ * @param string $file
+ * @param string $class
+ * @param string $name method name
+ * @access private
+ */
+ function hasMethod($class, $file, $name)
+ {
+ if (!$this->hasMethods($file, $class)) return false;
+ for($i=0; $i<count($this->methodsbyfile[$file][$class]); $i++)
+ {
+ if ($this->methodsbyfile[$file][$class][$i]->getName() == $name) return true;
+ }
+ return false;
+ }
+
+ /**
+ * called by {@link parserClass::hasVar()}. Should not be directly called
+ * @param string $file
+ * @param string $class
+ * @param string $name var name
+ * @access private
+ */
+ function hasVar($class, $file, $name)
+ {
+ if (!$this->hasVars($file, $class)) return false;
+ for($i=0; $i<count($this->varsbyfile[$file][$class]); $i++)
+ {
+ if ($this->varsbyfile[$file][$class][$i]->getName() == $name) return true;
+ }
+ return false;
+ }
+
+ /**
+ * called by {@link parserClass::hasConst()}. Should not be directly called
+ * @param string $file
+ * @param string $class
+ * @param string $name var name
+ * @access private
+ */
+ function hasConst($class, $file, $name)
+ {
+ if (!$this->hasConsts($file, $class)) return false;
+ for($i=0; $i<count($this->constsbyfile[$file][$class]); $i++)
+ {
+ if ($this->constsbyfile[$file][$class][$i]->getName() == $name) return true;
+ }
+ return false;
+ }
+
+ /**
+ * called by {@link parserClass::getMethods()}. Should not be directly called
+ * @access private
+ * @param string $class
+ * @param string $file
+ */
+ function &getMethods($class, $file)
+ {
+ if (!isset($this->methodsbyfile[$file][$class])) return false;
+ return $this->methodsbyfile[$file][$class];
+ }
+
+ /**
+ * called by {@link parserClass::getVars()}. Should not be directly called
+ * @access private
+ * @param string $class
+ * @param string $file
+ */
+ function &getVars($class, $file)
+ {
+ if (!isset($this->varsbyfile[$file][$class])) return false;
+ return $this->varsbyfile[$file][$class];
+ }
+
+ /**
+ * called by {@link parserClass::getConsts()}. Should not be directly called
+ * @access private
+ * @param string $class
+ * @param string $file
+ */
+ function &getConsts($class, $file)
+ {
+ if (!isset($this->constsbyfile[$file][$class])) return false;
+ return $this->constsbyfile[$file][$class];
+ }
+
+ /**
+ * called by {@link parserClass::getMethod()}. Should not be directly called
+ * @param string $class
+ * @param string $file
+ * @param string $name method name
+ * @access private
+ */
+ function getMethod($class, $file, $name)
+ {
+ if (!$this->hasMethod($class, $file, $name)) return false;
+ for($i=0; $i<count($this->methodsbyfile[$file][$class]); $i++)
+ {
+ if ($this->methodsbyfile[$file][$class][$i]->getName() == $name) return $this->methodsbyfile[$file][$class][$i];
+ }
+ }
+
+ /**
+ * called by {@link parserClass::getVar()}. Should not be directly called
+ * @param string $class
+ * @param string $file
+ * @param string $name var name
+ * @access private
+ */
+ function getVar($class, $file, $name)
+ {
+ if (!$this->hasVar($class, $file, $name)) return false;
+ for($i=0; $i<count($this->varsbyfile[$file][$class]); $i++)
+ {
+ if ($this->varsbyfile[$file][$class][$i]->getName() == $name) return $this->varsbyfile[$file][$class][$i];
+ }
+ }
+
+ /**
+ * called by {@link parserClass::getConst()}. Should not be directly called
+ * @param string $class
+ * @param string $file
+ * @param string $name var name
+ * @access private
+ */
+ function getConst($class, $file, $name)
+ {
+ if (!$this->hasConst($class, $file, $name)) return false;
+ for($i=0; $i<count($this->constsbyfile[$file][$class]); $i++)
+ {
+ if ($this->constsbyfile[$file][$class][$i]->getName() == $name) return $this->constsbyfile[$file][$class][$i];
+ }
+ }
+
+ /**
+ * Search for a class in a package
+ * @return mixed returns false if no class in $package, otherwise returns a {@link parserClass}
+ * @param string $class classname
+ * @param string $package package classname is in
+ */
+ function &getClassByPackage($class,$package)
+ {
+ if (!isset($this->classesbynamefile[$class]))
+ {
+// addWarning(PDERROR_CLASS_NOT_IN_PACKAGE,$class,$package); // removed, too many warnings, not very useful
+ return false;
+ }
+ for($i=0; $i < count($this->classesbynamefile[$class]); $i++)
+ {
+ $cls = $this->classesbyfile[$this->classesbynamefile[$class][$i]][$class];
+ $pkg = $cls->getPackage();
+ if ($pkg == $package)
+ return $cls;
+ }
+// addWarning(PDERROR_CLASS_NOT_IN_PACKAGE,$class,$package);
+ return false;
+ }
+
+ /**
+ * Find the parent class of a class in file $file
+ * uses 3 tests to find the parent classname:
+ * <ol>
+ * <li>only one class with the parent classname</li>
+ * <li>more than one class, but only one in the same file as the child</li>
+ * <li>only one parent class in the same package as the child</li>
+ * </ol>
+ * @return mixed false if no parent class, a string if no parent class found by that name,
+ * and an array(file parentclass is in,parentclassname)
+ */
+ function getParentClass($class,$file)
+ {
+ if (!isset($this->classesbyfile[$file][$class]))
+ {
+ return false;
+ }
+ $element = $this->classesbyfile[$file][$class];
+ if (!($ex = $element->getExtends())) return false;
+ // first check to see if there is one and only one class with the parent class's name
+ if (isset($this->classesbynamefile[$ex]))
+ {
+ if (count($this->classesbynamefile[$ex]) == 1)
+ {
+ if ($this->classesbyfile[$this->classesbynamefile[$ex][0]][$ex]->ignore) return $ex;
+ return array($this->classesbynamefile[$ex][0],$ex);
+ } else
+ {
+ // next check to see if there is a parent class in the same file
+ if (isset($this->classesbyfile[$file][$ex]))
+ {
+ if ($this->classesbyfile[$file][$ex]->ignore) return $ex;
+ return array($file,$ex);
+ }
+ // next check to see if there is only one package used in the file, try to resolve it that way
+ if (isset($this->classpackagebyfile[$file]))
+ {
+ if (count($this->classpackagebyfile[$file]) == 1)
+ {
+ for($i=0;$i<count($this->classesbynamefile[$ex]);$i++)
+ {
+ if ($this->classesbyfile[$this->classesbynamefile[$ex][$i]][$ex]->getPackage() == $this->classpackagebyfile[$file][0])
+ {
+ if ($this->classesbyfile[$this->classesbynamefile[$ex][$i]][$ex]->ignore) return $ex;
+ return array($this->classesbynamefile[$ex][$i],$ex);
+ }
+ }
+ }
+ }
+ // name conflict
+ addWarning(PDERROR_INHERITANCE_CONFLICT, $class, $file, $ex);
+ return $ex;
+ }
+ } else
+ {
+ addWarning(PDERROR_PARENT_NOT_FOUND, $class, $ex);
+ return $ex;
+ }
+ }
+
+ /**
+ * Get a list of all root classes indexed by package. Used to generate
+ * class trees by {@link Converter}
+ * @return array array(package => array(rootclassname, rootclassname,...),...)
+ */
+ function getRoots()
+ {
+ $roots = array();
+ foreach($this->roots as $class => $files)
+ {
+ if (count($files))
+ {
+ foreach($files as $i => $boofou)
+ {
+ $x = $this->getClass($class,$files[$i]);
+ $roots[$x->getPackage()][] = $class;
+ }
+ }
+ }
+ foreach($roots as $package => $root)
+ {
+ usort($roots[$package],"strnatcasecmp");
+ }
+ return $roots;
+ }
+
+ /**
+ * Get all classes confirmed in parsing to be descended class $parclass in file $file
+ * @return mixed either false if no children, or array of format
+ * array(childname => childfile,childname2 => childfile2,...)
+ * @param string $parclass name of parent class
+ * @param string $file file parent class is found in
+ * @see parserClass::getChildClassList()
+ * @uses $definitechild
+ */
+ function getDefiniteChildren($parclass,$file)
+ {
+ if (isset($this->definitechild[$parclass][$file])) return $this->definitechild[$parclass][$file];
+ return false;
+ }
+}
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converter.inc b/buildscripts/PhpDocumentor/phpDocumentor/Converter.inc
new file mode 100644
index 00000000..5b499d65
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converter.inc
@@ -0,0 +1,5189 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * Base class for all output converters.
+ * @package Converters
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: Converter.inc,v 1.5 2005/11/28 07:27:59 cellog Exp $
+ */
+/**
+ * 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 <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: Converter.inc,v 1.5 2005/11/28 07:27:59 cellog Exp $
+ */
+class Converter
+{
+ /**
+ * 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;
+
+ /**
+ * 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();
+
+ /**
+ * 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->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 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 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*/)
+ {
+ if (tokenizer_ext)
+ {
+ $e = $example;
+ if (!is_array($example))
+ {
+ $obj = new phpDocumentorTWordParser;
+ $obj->setup($example);
+ $e = $obj->getFileSource();
+ if (!isset($e[0]) || !is_array($e[0][0]) || $e[0][0][0] != T_OPEN_TAG)
+ {
+ $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);
+ }
+
+ 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)
+ {
+ $parse = new phpDocumentor_TutorialHighlightParser;
+ return $parse->parse($example, $this);
+ }
+
+ /**
+ * 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 &lt; and &gt;
+ * @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, -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
+ * @param string full path to the source code file
+ * @return boolean
+ */
+ function hasSourceCode($path)
+ {
+ 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 &rdquo; 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,$title.$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 = $tutorial->package . '/' . $tutorial->subpackage . '/' . $tutorial->name;
+ 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['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;
+ return $pkg->package.'/'.$subpkg->subpackage.'/'.$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)
+ {
+ $child_path = $this->_tutorial_path($tutorial,$tutorial,$tutorial);
+ if (! isset($this->processed_tutorials[$child_path]))
+ {
+ $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)
+ {
+ $child_path = $this->_tutorial_path($parent,$parent,$tute);
+ if (! isset($this->processed_tutorials[$child_path]))
+ {
+ $this->processed_tutorials[$child_path] = $tute;
+ if ($tute->name == $child . '.' . $parent->tutorial_type)
+ {
+// echo "Adding [$child_path] to [$parent_path]<br>";
+ $tree[$parent_path]['child'][$this->_tutorial_path($parent,$parent,$tute)]['tutorial'] = $tute;
+ if ($tute->ini)
+ {
+ // 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($this, '_sortTodos'));
+ phpDocumentor_out("done\n");
+ }
+
+ /** @access private */
+ function _sortTodos($a, $b)
+ {
+ return strnatcasecmp($a[0]->name, $b[0]->name);
+ }
+
+ /**
+ * 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)
+ {
+ $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)
+ {
+ $this->addTodoLink($this->addLink($element),$a);
+ }
+ }
+ $i = 0;
+ 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);
+ $i++;
+ 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);
+ $i++;
+ $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);
+ $i++;
+ $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()),$i,1)][] = $element;
+ $this->pkg_elements[$this->package][$this->subpackage][substr(strtolower($element->getFile()),$i,1)][] = $element;
+ } else
+ {
+ $this->elements[substr(strtolower($element->getName()),$i,1)][] = $element;
+ $this->pkg_elements[$this->package][$this->subpackage][substr(strtolower($element->getName()),$i,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>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')
+ return 'http://www.php.net/'.$a[1];
+ return Converter::getLink($a[1],$a[0],array());
+ }
+ }
+ $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);
+ }
+ // 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
+ return false;
+ }
+
+ /**
+ * 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 = $par->getName();
+ } else $class = $par;
+ } else $class = false;
+ } while ($class);
+ // no links found
+ return false;
+ }
+
+ /**
+ * take URL $link and text $text and return a link in the format needed for the Converter
+ * @param string URL
+ * @param string text to display
+ * @return string link to $link
+ * @abstract
+ */
+ function returnLink($link,$text)
+ {
+ }
+
+ /**
+ * take {@link abstractLink} descendant and text $eltext and return a link
+ * in the format needed for the Converter
+ * @param abstractLink
+ * @param string
+ * @return string link to $element
+ * @abstract
+ */
+ function returnSee(&$link, $eltext = false)
+ {
+ }
+
+ /**
+ * take {@link abstractLink} descendant and text $eltext and return a
+ * unique ID in the format needed for the Converter
+ * @param abstractLink
+ * @return string unique identifier of $element
+ * @abstract
+ */
+ function getId(&$link)
+ {
+ }
+
+ /**
+ * Convert README/INSTALL/CHANGELOG file contents to output format
+ * @param README|INSTALL|CHANGELOG
+ * @param string contents of the file
+ * @abstract
+ */
+ function Convert_RIC($name, $contents)
+ {
+ }
+
+ /**
+ * Convert all elements to output format
+ *
+ * This will call ConvertXxx where Xxx is {@link ucfirst}($element->type).
+ * It is expected that a child converter defines a handler for every
+ * element type, even if that handler does nothing. phpDocumentor will
+ * terminate with an error if a handler doesn't exist.
+ * {@internal
+ * Since 1.2.0 beta 3, this function has been moved from child converters
+ * to the parent, because it doesn't really make sense to put it in the
+ * child converter, and we can add error handling.
+ *
+ * {@source}}}
+ * @throws {@link PDERROR_NO_CONVERT_HANDLER}
+ * @param mixed {@link parserElement} descendant or {@link parserPackagePage} or {@link parserData}
+ */
+ function Convert(&$element)
+ {
+ $handler = 'convert'.ucfirst($element->type);
+ if (method_exists($this,$handler))
+ {
+ $this->$handler($element);
+ } else
+ {
+ addErrorDie(PDERROR_NO_CONVERTER_HANDLER,$element->type,$handler,phpDocumentor_get_class($this));
+ }
+ }
+ /**#@+
+ * Conversion Handlers
+ *
+ * All of the convert* handlers set up template variables for the Smarty
+ * template.{@internal In addition, the {@link newSmarty()} method is
+ * called to retrieve the global Smarty template}}
+ */
+ /**
+ * Default Tutorial Handler
+ *
+ * Sets up the tutorial template, and its prev/next/parent links
+ * {@internal
+ * Retrieves the title using {@link parserTutorial::getTitle()} and uses the
+ * {@link parserTutorial::prev, parserTutorial::next, parserTutorial::parent}
+ * links to set up those links.}}
+ * @param parserTutorial
+ */
+ function &convertTutorial(&$element)
+ {
+ $this->package = $element->package;
+ $this->subpackage = $element->subpackage;
+ $x = $element->Convert($this);
+ $template = &$this->newSmarty();
+ $template->assign('contents',$x);
+ $template->assign('title',$element->getTitle($this));
+ $template->assign('nav',$element->parent || $element->prev || $element->next);
+ if ($element->parent)
+ {
+ $template->assign('up',$this->getId($element->parent));
+ $template->assign('uptitle',$element->parent->title);
+ }
+ if ($element->prev)
+ {
+ $template->assign('prev',$this->getId($element->prev));
+ $template->assign('prevtitle',$element->prev->title);
+ }
+ if ($element->next)
+ {
+ $template->assign('next',$this->getId($element->next));
+ $template->assign('nexttitle',$element->next->title);
+ }
+ return $template;
+ }
+ /**
+ * Default Class Handler
+ *
+ * Sets up the class template.
+ * {@internal special methods
+ * {@link generateChildClassList(), generateFormattedClassTree()},
+ * {@link getFormattedConflicts, getFormattedInheritedMethods},
+ * and {@link getFormattedInheritedVars} are called to complete vital
+ * template setup.}}
+ */
+ function convertClass(&$element)
+ {
+ $this->class = $element->getName();
+ $this->class_data = &$this->newSmarty();
+ $this->class_data->assign("class_name",$element->getName());
+ $this->class_data->assign("vars",array());
+ $this->class_data->assign("methods",array());
+ $this->class_data->assign("consts",array());
+ $this->class_data->assign("is_interface", $element->isInterface());
+ $this->class_data->assign("implements", $this->getFormattedImplements($element));
+ $this->class_data->assign("package",$element->docblock->package);
+ $this->class_data->assign("line_number",$element->getLineNumber());
+ $this->class_data->assign("source_location",$element->getSourceLocation($this));
+ $this->class_data->assign("page_link",$this->getCurrentPageLink());
+ $docblock = $this->prepareDocBlock($element, false);
+ $this->class_data->assign("sdesc",$docblock['sdesc']);
+ $this->class_data->assign("desc",$docblock['desc']);
+ $this->class_data->assign("access", $docblock['access']);
+ $this->class_data->assign("abstract", $docblock['abstract']);
+ $this->class_data->assign("tags",$docblock['tags']);
+ $this->class_data->assign("api_tags",$docblock['api_tags']);
+ $this->class_data->assign("info_tags",$docblock['info_tags']);
+ $this->class_data->assign("utags",$docblock['utags']);
+ if ($this->hasSourceCode($element->getPath())) {
+ $this->class_data->assign("class_slink",$this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true));
+ }
+
+ else
+ $this->class_data->assign("class_slink",false);
+ $this->class_data->assign("children", $this->generateChildClassList($element));
+ $this->class_data->assign("class_tree", $this->generateFormattedClassTree($element));
+ $this->class_data->assign("conflicts", $this->getFormattedConflicts($element,"classes"));
+ $inherited_methods = $this->getFormattedInheritedMethods($element);
+ if (!empty($inherited_methods))
+ {
+ $this->class_data->assign("imethods",$inherited_methods);
+ } else
+ {
+ $this->class_data->assign("imethods",false);
+ }
+ $inherited_vars = $this->getFormattedInheritedVars($element);
+ if (!empty($inherited_vars))
+ {
+ $this->class_data->assign("ivars",$inherited_vars);
+ } else
+ {
+ $this->class_data->assign("ivars",false);
+ }
+ $inherited_consts = $this->getFormattedInheritedConsts($element);
+ if (!empty($inherited_consts))
+ {
+ $this->class_data->assign("iconsts",$inherited_consts);
+ } else
+ {
+ $this->class_data->assign("iconsts",false);
+ }
+ }
+
+
+ /**
+ * Converts method for template output
+ *
+ * This function must be called by a child converter with any extra
+ * template variables needed in the parameter $addition
+ * @param parserMethod
+ */
+ function convertMethod(&$element, $additions = array())
+ {
+ $fname = $element->getName();
+ $docblock = $this->prepareDocBlock($element);
+ $returntype = 'void';
+ if ($element->isConstructor) $returntype = $element->class;
+ if ($element->docblock->return)
+ {
+ $a = $element->docblock->return->Convert($this);
+ $returntype = $element->docblock->return->converted_returnType;
+ }
+ $params = $param_i = array();
+ if (count($element->docblock->params))
+ foreach($element->docblock->params as $param => $val)
+ {
+ $a = $val->Convert($this);
+ $params[] = $param_i[$param] = array("var" => $param,"datatype" => $val->converted_returnType,"data" => $a);
+ }
+
+ if ($element->docblock->hasaccess)
+ $acc = $element->docblock->tags['access'][0]->value;
+ else
+ $acc = 'public';
+
+
+ if ($this->hasSourceCode($element->getPath()))
+ $additions["slink"] = $this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true);
+ $this->class_data->append('methods',array_merge(
+ array('sdesc' => $docblock['sdesc'],
+ 'desc' => $docblock['desc'],
+ 'access' => $docblock['access'],
+ 'abstract' => $docblock['abstract'],
+ 'tags' => $docblock['tags'],
+ 'api_tags' => $docblock['api_tags'],
+ 'info_tags' => $docblock['info_tags'],
+ 'utags' => $docblock['utags'],
+ 'constructor' => $element->isConstructor,
+ 'access' => $acc,
+ 'function_name' => $fname,
+ 'function_return' => $returntype,
+ 'function_call' => $element->getFunctionCall(),
+ 'ifunction_call' => $element->getIntricateFunctionCall($this, $param_i),
+ 'descmethod' => $this->getFormattedDescMethods($element),
+ 'method_overrides' => $this->getFormattedOverrides($element),
+ 'line_number' => $element->getLineNumber(),
+ 'id' => $this->getId($element),
+ 'params' => $params),
+ $additions));
+ }
+
+ /**
+ * Converts class variables for template output.
+ *
+ * This function must be called by a child converter with any extra
+ * template variables needed in the parameter $addition
+ * @param parserVar
+ */
+ function convertVar(&$element, $additions = array())
+ {
+ $docblock = $this->prepareDocBlock($element);
+ $b = 'mixed';
+
+ if ($element->docblock->hasaccess)
+ $acc = $element->docblock->tags['access'][0]->value;
+ else
+ $acc = 'public';
+
+ if ($element->docblock->var)
+ {
+ $b = $element->docblock->var->converted_returnType;
+ }
+ if ($this->hasSourceCode($element->getPath()))
+ $additions["slink"] = $this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true);
+ $this->class_data->append('vars',array_merge(
+ array('sdesc' => $docblock['sdesc'],
+ 'desc' => $docblock['desc'],
+ 'abstract' => $docblock['abstract'],
+ 'utags' => $docblock['utags'],
+ 'tags' => $docblock['tags'],
+ 'api_tags' => $docblock['api_tags'],
+ 'info_tags' => $docblock['info_tags'],
+ 'var_name' => $element->getName(),
+ 'var_default' => $this->postProcess($element->getValue()),
+ 'var_type' => $b,
+ 'access' => $acc,
+ 'line_number' => $element->getLineNumber(),
+ 'descvar' => $this->getFormattedDescVars($element),
+ 'var_overrides' => $this->getFormattedOverrides($element),
+ 'id' => $this->getId($element)),
+ $additions));
+ }
+
+ /**
+ * Converts class constants for template output.
+ *
+ * This function must be called by a child converter with any extra
+ * template variables needed in the parameter $addition
+ * @param parserConst
+ */
+ function convertConst(&$element, $additions = array())
+ {
+ $docblock = $this->prepareDocBlock($element);
+
+ if ($element->docblock->hasaccess)
+ $acc = $element->docblock->tags['access'][0]->value;
+ else
+ $acc = 'public';
+
+ if ($this->hasSourceCode($element->getPath()))
+ $additions["slink"] = $this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true);
+ $this->class_data->append('consts',array_merge(
+ array('sdesc' => $docblock['sdesc'],
+ 'desc' => $docblock['desc'],
+ 'access' => $docblock['access'],
+ 'abstract' => $docblock['abstract'],
+ 'utags' => $docblock['utags'],
+ 'tags' => $docblock['tags'],
+ 'api_tags' => $docblock['api_tags'],
+ 'info_tags' => $docblock['info_tags'],
+ 'const_name' => $element->getName(),
+ 'const_value' => $this->postProcess($element->getValue()),
+ 'access' => $acc,
+ 'line_number' => $element->getLineNumber(),
+ 'id' => $this->getId($element)),
+ $additions));
+ }
+
+ /**
+ * Default Page Handler
+ *
+ * {@internal In addition to setting up the smarty template with {@link newSmarty()},
+ * this class uses {@link getSourceLocation()} and {@link getClassesOnPage()}
+ * to set template variables. Also used is {@link getPageName()}, to get
+ * a Converter-specific name for the page.}}
+ * @param parserPage
+ */
+ function convertPage(&$element)
+ {
+ $this->page_data = &$this->newSmarty(true);
+ $this->page = $this->getPageName($element->parent);
+ $this->path = $element->parent->getPath();
+ $this->curpage = &$element->parent;
+ $this->page_data->assign("source_location",$element->parent->getSourceLocation($this));
+ $this->page_data->assign("functions",array());
+ $this->page_data->assign("includes",array());
+ $this->page_data->assign("defines",array());
+ $this->page_data->assign("globals",array());
+ $this->page_data->assign("classes",$this->getClassesOnPage($element));
+ $this->page_data->assign("name", $element->parent->getFile());
+ if ($t = $element->getTutorial())
+ {
+ $this->page_data->assign("tutorial",$this->returnSee($t));
+ } else
+ {
+ $this->page_data->assign("tutorial",false);
+ }
+ if ($element->docblock)
+ {
+ $docblock = $this->prepareDocBlock($element, false);
+ $this->page_data->assign("sdesc",$docblock['sdesc']);
+ $this->page_data->assign("desc",$docblock['desc']);
+ $this->page_data->assign("tags",$docblock['tags']);
+ $this->page_data->assign("api_tags",$docblock['api_tags']);
+ $this->page_data->assign("info_tags",$docblock['info_tags']);
+ $this->page_data->assign("utags",$docblock['utags']);
+ }
+ }
+
+ /**
+ * Converts global variables for template output
+ *
+ * This function must be called by a child converter with any extra
+ * template variables needed in the parameter $addition
+ * {@internal
+ * In addition to using {@link prepareDocBlock()}, this method also
+ * uses utility functions {@link getGlobalValue(), getFormattedConflicts()}}}
+ * @param parserGlobal
+ * @uses postProcess() on global_value template value, makes it displayable
+ * @param array any additional template variables should be in this array
+ */
+ function convertGlobal(&$element, $addition = array())
+ {
+ $docblock = $this->prepareDocBlock($element);
+ $value = $this->getGlobalValue($element->getValue());
+ if ($this->hasSourceCode($element->getPath()))
+ $addition["slink"] = $this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true);
+ $this->page_data->append('globals',array_merge(
+ array('sdesc' => $docblock['sdesc'],
+ 'desc' => $docblock['desc'],
+ 'tags' => $docblock['tags'],
+ 'api_tags' => $docblock['api_tags'],
+ 'info_tags' => $docblock['info_tags'],
+ 'utags' => $docblock['utags'],
+ 'global_name' => $element->getName(),
+ 'global_type' => $element->getDataType($this),
+ 'global_value' => $this->postProcess($value),
+ 'line_number' => $element->getLineNumber(),
+ 'global_conflicts' => $this->getFormattedConflicts($element,"global variables"),
+ 'id' => $this->getId($element)),
+ $addition));
+ }
+
+ /**
+ * Converts defines for template output
+ *
+ * This function must be called by a child converter with any extra
+ * template variables needed in the parameter $addition
+ * {@internal
+ * In addition to using {@link prepareDocBlock()}, this method also
+ * uses utility functions {@link getGlobalValue(), getFormattedConflicts()}}}
+ * @param parserDefine
+ * @uses postProcess() on define_value template value, makes it displayable
+ * @param array any additional template variables should be in this array
+ */
+ function convertDefine(&$element, $addition = array())
+ {
+ $docblock = $this->prepareDocBlock($element);
+ if ($this->hasSourceCode($element->getPath()))
+ $addition["slink"] = $this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true);
+ $this->page_data->append('defines',array_merge(
+ array('sdesc' => $docblock['sdesc'],
+ 'desc' => $docblock['desc'],
+ 'tags' => $docblock['tags'],
+ 'api_tags' => $docblock['api_tags'],
+ 'info_tags' => $docblock['info_tags'],
+ 'utags' => $docblock['utags'],
+ 'define_name' => $element->getName(),
+ 'line_number' => $element->getLineNumber(),
+ 'define_value' => $this->postProcess($element->getValue()),
+ 'define_conflicts' => $this->getFormattedConflicts($element,"defines"),
+ 'id' => $this->getId($element)),
+ $addition));
+ }
+
+
+ /**
+ * Converts includes for template output
+ *
+ * This function must be called by a child converter with any extra
+ * template variables needed in the parameter $addition
+ * @see prepareDocBlock()
+ * @param parserInclude
+ */
+ function convertInclude(&$element, $addition = array())
+ {
+ $docblock = $this->prepareDocBlock($element);
+ $per = $this->getIncludeValue($element->getValue(), $element->getPath());
+
+ if ($this->hasSourceCode($element->getPath()))
+ $addition["slink"] = $this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true);
+ $this->page_data->append('includes',array_merge(
+ array('sdesc' => $docblock['sdesc'],
+ 'desc' => $docblock['desc'],
+ 'tags' => $docblock['tags'],
+ 'api_tags' => $docblock['api_tags'],
+ 'info_tags' => $docblock['info_tags'],
+ 'utags' => $docblock['utags'],
+ 'include_name' => $element->getName(),
+ 'line_number' => $element->getLineNumber(),
+ 'include_value' => $per),
+ $addition));
+ }
+
+ /**
+ * Converts function for template output
+ *
+ * This function must be called by a child converter with any extra
+ * template variables needed in the parameter $addition
+ * @see prepareDocBlock()
+ * @param parserFunction
+ */
+ function convertFunction(&$element, $addition = array())
+ {
+ $docblock = $this->prepareDocBlock($element);
+ $fname = $element->getName();
+ $params = $param_i = array();
+ if (count($element->docblock->params))
+ foreach($element->docblock->params as $param => $val)
+ {
+ $a = $val->Convert($this);
+ $params[] = $param_i[$param] = array("var" => $param,"datatype" => $val->converted_returnType,"data" => $a);
+ }
+ $returntype = 'void';
+ if ($element->docblock->return)
+ {
+ $a = $element->docblock->return->Convert($this);
+ $returntype = $element->docblock->return->converted_returnType;
+ }
+
+ if ($this->hasSourceCode($element->getPath()))
+ $addition["slink"] = $this->getSourceAnchor($element->getPath(),$element->getLineNumber(),$element->getLineNumber(),true);
+ $this->page_data->append('functions',array_merge(
+ array('sdesc' => $docblock['sdesc'],
+ 'desc' => $docblock['desc'],
+ 'tags' => $docblock['tags'],
+ 'api_tags' => $docblock['api_tags'],
+ 'info_tags' => $docblock['info_tags'],
+ 'utags' => $docblock['utags'],
+ 'function_name' => $fname,
+ 'function_return' => $returntype,
+ 'function_conflicts' => $this->getFormattedConflicts($element,"functions"),
+ 'ifunction_call' => $element->getIntricateFunctionCall($this, $param_i),
+ 'function_call' => $element->getFunctionCall(),
+ 'line_number' => $element->getLineNumber(),
+ 'id' => $this->getId($element),
+ 'params' => $params),
+ $addition));
+ }
+ /**#@-*/
+
+ /**
+ * convert the element's DocBlock for output
+ *
+ * This function converts all tags and descriptions for output
+ * @param mixed any descendant of {@link parserElement}, or {@link parserData}
+ * @param array used to translate tagnames into other tags
+ * @param boolean set to false for pages and classes, the only elements allowed to specify @package
+ * @return array
+ *
+ * Format:
+ * <pre>
+ * array('sdesc' => DocBlock summary
+ * 'desc' => DocBlock detailed description
+ * 'tags' => array('keyword' => tagname, 'data' => tag description)
+ * known tags
+ * 'api_tags' => array('keyword' => tagname, 'data' => tag description)
+ * known api documentation tags
+ * 'info_tags' => array('keyword' => tagname, 'data' => tag description)
+ * known informational tags
+ * [ 'utags' => array('keyword' => tagname, 'data' => tag description
+ * unknown tags ]
+ * [ 'vartype' => type from @var/@return tag ]
+ * [ 'var_descrip' => description from @var/@return tag ]
+ * )
+ * </pre>
+ */
+ function prepareDocBlock(&$element, $names = array(),$nopackage = true)
+ {
+ $tagses = $element->docblock->listTags();
+ $tags = $ret = $api_tags = $info_tags = array();
+ $api_tags_arr = array("abstract", "access", "deprecated", "example", "filesource",
+ "global", "internal", "name", "return", "see", "static",
+ "staticvar", "uses", "var");
+ if (!$nopackage)
+ {
+ $tags[] = array('keyword' => 'package','data' => $element->docblock->package);
+ if (!empty($element->docblock->subpackage)) $tags[] = array('keyword' => 'subpackage','data' => $element->docblock->subpackage);
+ }
+ if ($element->docblock->var)
+ {
+ $a = $element->docblock->var->Convert($this);
+ $ret['vartype'] = $element->docblock->var->converted_returnType;
+ if (!empty($a))
+ {
+ $tags[] = array('keyword' => 'var', 'data' => $a);
+ $ret["var_descrip"] = $a;
+ }
+ }
+ if ($element->docblock->return)
+ {
+ $a = $element->docblock->return->Convert($this);
+ $ret['vartype'] = $element->docblock->return->converted_returnType;
+ if (!empty($a))
+ {
+ $tags[] = $api_tags[] = array('keyword' => 'return', 'data' => $a);
+ $ret["var_descrip"] = $a;
+ }
+ }
+ if ($element->docblock->funcglobals)
+ foreach($element->docblock->funcglobals as $global => $val)
+ {
+ if ($a = $this->getGlobalLink($global,$element->docblock->package))
+ {
+ $global = $a;
+ }
+ $b = Converter::getLink($val[0]);
+ if (is_object($b) && phpDocumentor_get_class($b) == 'classlink')
+ {
+ $val[0] = $this->returnSee($b);
+ }
+ $tags[] = $api_tags[] = array('keyword' => 'global','data' => $val[0].' '.$global.': '.$val[1]->Convert($this));
+ }
+ if ($element->docblock->statics)
+ foreach($element->docblock->statics as $static => $val)
+ {
+ $a = $val->Convert($this);
+ $tags[] = $api_tags[] = array('keyword' => 'staticvar','data' => $val->converted_returnType.' '.$static.': '.$a);
+ }
+ foreach($tagses as $tag)
+ {
+ if (isset($names[$tag->keyword])) $tag->keyword = $names[$tag->keyword];
+ if ($tag->keyword)
+ $tags[] = array("keyword" => $tag->keyword,"data" => $tag->Convert($this));
+ if (in_array($tag->keyword, $api_tags_arr))
+ $api_tags[] = array("keyword" => $tag->keyword,"data" => $tag->Convert($this));
+ else
+ $info_tags[] = array("keyword" => $tag->keyword,"data" => $tag->Convert($this));
+ }
+ $utags = array();
+ foreach($element->docblock->unknown_tags as $keyword => $tag)
+ {
+ foreach($tag as $t)
+ $utags[] = array('keyword' => $keyword, 'data' => $t->Convert($this));
+ }
+ $ret['abstract'] = FALSE;
+ $ret['access'] = 'public';
+ foreach($tags as $tag)
+ {
+ if ($tag['keyword'] == 'access')
+ $ret['access'] = $tag['data'];
+ if ($tag['keyword'] == 'abstract')
+ $ret['abstract'] = TRUE;
+ }
+ $ret['sdesc'] = $element->docblock->getSDesc($this);
+ $ret['desc'] = $element->docblock->getDesc($this);
+ $ret['tags'] = $tags;
+ $ret['api_tags'] = $api_tags;
+ $ret['info_tags'] = $info_tags;
+ $ret['utags'] = $utags;
+ return $ret;
+ }
+
+ /**
+ * gets a list of all classes declared on a procedural page represented by
+ * $element, a {@link parserData} class
+ * @param parserData &$element
+ * @return array links to each classes documentation
+ *
+ * Format:
+ * <pre>
+ * array('name' => class name,
+ * 'sdesc' => summary of the class
+ * 'link' => link to the class's documentation)
+ * </pre>
+ */
+ function getClassesOnPage(&$element)
+ {
+ global $_phpDocumentor_setting;
+ $a = $element->getClasses($this);
+ $classes = array();
+ foreach($a as $package => $clas)
+ {
+ if (isset($_phpDocumentor_setting['packageoutput']))
+ {
+ $packages = explode(',',$_phpDocumentor_setting['packageoutput']);
+ if (!in_array($package, $packages)) continue;
+ }
+ for($i=0; $i<count($clas); $i++)
+ {
+ if ($this->parseprivate || ! ($clas[$i]->docblock && $clas[$i]->docblock->hasaccess && $clas[$i]->docblock->tags['access'][0]->value == 'private'))
+ {
+ $sdesc = '';
+ $r = array();
+ $sdesc = $clas[$i]->docblock->getSDesc($this);
+ if ($clas[$i]->docblock->hasaccess)
+ $r['access'] = $clas[$i]->docblock->tags['access'][0]->value;
+ else
+ $r['access'] = 'public';
+ if (isset ($clas[$i]->docblock->tags['abstract']))
+ $r['abstract'] = TRUE;
+ else
+ $r['abstract'] = FALSE;
+ $r['name'] = $clas[$i]->getName();
+ $r['sdesc'] = $sdesc;
+ $r['link'] = $this->getClassLink($clas[$i]->getName(),$package,$clas[$i]->getPath());
+ $classes[] = $r;
+ }
+ }
+ }
+ return $classes;
+ }
+
+ /**
+ * returns an array containing the class inheritance tree from the root
+ * object to the class.
+ *
+ * This method must be overridden, or phpDocumentor will halt with a fatal
+ * error
+ * @return string Converter-specific class tree for an individual class
+ * @param parserClass class variable
+ * @abstract
+ */
+
+ function generateFormattedClassTree($class)
+ {
+ addErrorDie(PDERROR_CONVERTER_OVR_GFCT,phpDocumentor_get_class($this));
+ }
+
+ /**
+ * returns an array containing the class inheritance tree from the root
+ * object to the class.
+ *
+ * This method must be overridden, or phpDocumentor will halt with a fatal
+ * error
+ * @return string Converter-specific class tree for an individual class
+ * @param parserClass class variable
+ * @abstract
+ */
+
+ function getFormattedImplements($el)
+ {
+ $ret = array();
+ foreach ($el->getImplements() as $interface)
+ {
+ $ret[] = $this->returnSee($this->getLink($interface));
+ }
+ return $ret;
+ }
+
+ /**
+ * @param mixed {@link parserClass, parserFunction, parserDefine} or
+ * {@link parserGlobal}
+ * @param string type to display. either 'class','function','define'
+ * or 'global variable'
+ * @return array links to conflicting elements, or empty array
+ * @uses parserClass::getConflicts()
+ * @uses parserFunction::getConflicts()
+ * @uses parserDefine::getConflicts()
+ * @uses parserGlobal::getConflicts()
+ */
+ function getFormattedConflicts(&$element,$type)
+ {
+ $conflicts = $element->getConflicts($this);
+ $r = array();
+ if (!$conflicts) return false;
+ foreach($conflicts as $package => $class)
+ {
+ $r[] = $class->getLink($this,$class->docblock->package);
+ }
+ if (!empty($r)) $r = array('conflicttype' => $type, 'conflicts' => $r);
+ return $r;
+ }
+
+ /**
+ * Get a list of methods in child classes that override this method
+ * @return array empty array or array(array('link'=>link to method,
+ * 'sdesc'=>short description of the method),...)
+ * @uses parserMethod::getOverridingMethods()
+ * @param parserMethod
+ */
+ function getFormattedDescMethods(&$element)
+ {
+ $meths = $element->getOverridingMethods($this);
+ $r = array();
+ for($i=0; $i<count($meths); $i++)
+ {
+ $ms = array();
+ $ms['link'] = $meths[$i]->getLink($this);
+ $ms['sdesc'] = $meths[$i]->docblock->getSDesc($this);
+ $r[] = $ms;
+ }
+ return $r;
+ }
+
+ /**
+ * Get a list of vars in child classes that override this var
+ * @return array empty array or array('link'=>link to var,
+ * 'sdesc'=>short description of the method
+ * @uses parserVar::getOverridingVars()
+ * @param parserVar
+ */
+ function getFormattedDescVars(&$element)
+ {
+ $vars = $element->getOverridingVars($this);
+ $r = array();
+ for($i=0; $i<count($vars); $i++)
+ {
+ $vs = array();
+ $vs['link'] = $vars[$i]->getLink($this);
+ $vs['sdesc'] = $vars[$i]->docblock->getSDesc($this);
+ $r[] = $vs;
+ }
+ return $r;
+ }
+
+ /**
+ * Get the method this method overrides, if any
+ * @return array|false array('link'=>link to overridden method,
+ * 'sdesc'=>short description
+ * @see parserMethod::getOverrides()
+ * @param parserMethod
+ */
+ function getFormattedOverrides(&$element)
+ {
+ $ovr = $element->getOverrides($this);
+ if (!$ovr) return false;
+ $sdesc = $ovr->docblock->getSDesc($this);
+ return array('link' => $ovr->getLink($this),'sdesc' => $sdesc);
+ }
+
+ /**
+ * returns a list of child classes
+ *
+ * @param parserClass class variable
+ * @uses parserClass::getChildClassList()
+ */
+
+ function generateChildClassList($class)
+ {
+ $kids = $class->getChildClassList($this);
+ $list = array();
+ if (count($kids))
+ {
+ for($i=0; $i<count($kids); $i++)
+ {
+ $lt['link'] = $kids[$i]->getLink($this);
+ $lt['sdesc'] = $kids[$i]->docblock->getSDesc($this);
+
+ if ($kids[$i]->docblock->hasaccess)
+ $lt['access'] = $kids[$i]->docblock->tags['access'][0]->value;
+ else
+ $lt['access'] = 'public';
+
+ $lt['abstract'] = isset ($kids[$i]->docblock->tags['abstract'][0]);
+
+ $list[] = $lt;
+ }
+ } else return false;
+ return $list;
+ }
+
+ /**
+ * Return template-enabled list of inherited variables
+ *
+ * uses parserVar helper function getInheritedVars and generates a
+ * template-enabled list using getClassLink()
+ * @param parserVar $child class method
+ * @see getClassLink(), parserVar::getInheritedVars()
+ * @return array Format:
+ * <pre>
+ * array(
+ * array('parent_class' => link to parent class's documentation,
+ * 'ivars' =>
+ * array(
+ * array('name' => inherited variable name,
+ * 'link' => link to inherited variable's documentation,
+ * 'default' => default value of inherited variable,
+ * 'sdesc' => summary of inherited variable),
+ * ...),
+ * ...)
+ * </pre>
+ */
+
+ function getFormattedInheritedVars($child)
+ {
+ $package = $child->docblock->package;
+ $subpackage = $child->docblock->subpackage;
+ $ivars = $child->getInheritedVars($this);
+ $results = array();
+ if (!count($ivars)) return $results;
+ foreach($ivars as $parent => $vars)
+ {
+ $file = $vars['file'];
+ $vars = $vars['vars'];
+ $par = $this->classes->getClass($parent,$file);
+ $package = $par->docblock->package;
+ usort($vars,array($this,"sortVar"));
+ $result['parent_class'] = $this->getClassLink($parent,$package);
+ foreach($vars as $var)
+ {
+ $info = array();
+
+ if ($var->docblock->hasaccess)
+ $info['access'] = $var->docblock->tags['access'][0]->value;
+ else
+ $info['access'] = 'public';
+
+ $info['abstract'] = isset ($var->docblock->tags['abstract'][0]);
+
+ $info['name'] = $var->getName();
+ $info['link'] = $var->getLink($this);
+ $info['default'] = $this->postProcess($var->getValue());
+ if ($var->docblock)
+ $info['sdesc'] = $var->docblock->getSDesc($this);
+ $result["ivars"][] = $info;
+ }
+ $results[] = $result;
+ $result = array();
+ }
+ return $results;
+ }
+
+ /**
+ * Return template-enabled list of inherited methods
+ *
+ * uses parserMethod helper function getInheritedMethods and generates a
+ * template-enabled list using getClassLink()
+ * @param parserMethod $child class method
+ * @see getClassLink(), parserMethod::getInheritedMethods()
+ * @return array Format:
+ * <pre>
+ * array(
+ * array('parent_class' => link to parent class's documentation,
+ * 'ivars' =>
+ * array(
+ * array('name' => inherited variable name,
+ * 'link' => link to inherited variable's documentation,
+ * 'function_call' => {@link parserMethod::getIntricateFunctionCall()}
+ * returned array,
+ * 'sdesc' => summary of inherited variable),
+ * ...),
+ * ...)
+ * </pre>
+ */
+
+ function getFormattedInheritedMethods($child)
+ {
+ $package = $child->docblock->package;
+ $subpackage = $child->docblock->subpackage;
+ $imethods = $child->getInheritedMethods($this);
+ $results = array();
+ if (!count($imethods)) return $results;
+ foreach($imethods as $parent => $methods)
+ {
+ $file = $methods['file'];
+ $methods = $methods['methods'];
+ $par = $this->classes->getClass($parent,$file);
+ $package = $par->docblock->package;
+ usort($methods,array($this,"sortMethod"));
+ $result['parent_class'] = $this->getClassLink($parent,$package);
+ foreach($methods as $method)
+ {
+ $info = array();
+
+ if ($method->docblock->hasaccess)
+ $info['access'] = $method->docblock->tags['access'][0]->value;
+ else
+ $info['access'] = 'public';
+
+ $info['abstract'] = isset ($method->docblock->tags['abstract'][0]);
+
+ if ($method->isConstructor) $info['constructor'] = 1;
+ $info['link'] = $method->getLink($this);
+ $info['name'] = $method->getName();
+ if ($method->docblock)
+ $info['sdesc'] = $method->docblock->getSDesc($this);
+ $params = array();
+ if (count($method->docblock->params))
+ foreach($method->docblock->params as $param => $val)
+ {
+ $a = $val->Convert($this);
+ $params[$param] = array("var" => $param,"datatype" => $val->converted_returnType,"data" => $a);
+ }
+
+ $info['function_call'] = $method->getIntricateFunctionCall($this,$params);
+ $result["imethods"][] = $info;
+ }
+ $results[] = $result;
+ $result = array();
+ }
+ return $results;
+ }
+
+ /**
+ * Return template-enabled list of inherited class constants
+ *
+ * uses parserConst helper function getInheritedConsts and generates a
+ * template-enabled list using getClassLink()
+ * @param parserConst $child class constant
+ * @see getClassLink(), parserMethod::getInheritedConsts()
+ * @return array Format:
+ * <pre>
+ * array(
+ * array('parent_class' => link to parent class's documentation,
+ * 'ivars' =>
+ * array(
+ * array('name' => inherited constant name,
+ * 'link' => link to inherited constant's documentation,
+ * 'value' => constant value,
+ * 'sdesc' => summary of inherited constant),
+ * ...),
+ * ...)
+ * </pre>
+ */
+
+ function getFormattedInheritedConsts($child)
+ {
+ $package = $child->docblock->package;
+ $subpackage = $child->docblock->subpackage;
+ $ivars = $child->getInheritedConsts($this);
+ $results = array();
+ if (!count($ivars)) return $results;
+ foreach($ivars as $parent => $vars)
+ {
+ $file = $vars['file'];
+ $vars = $vars['consts'];
+ $par = $this->classes->getClass($parent,$file);
+ $package = $par->docblock->package;
+ usort($vars,array($this,"sortVar"));
+ $result['parent_class'] = $this->getClassLink($parent,$package);
+ foreach($vars as $var)
+ {
+ $info = array();
+
+ if ($var->docblock->hasaccess)
+ $info['access'] = $var->docblock->tags['access'][0]->value;
+ else
+ $info['access'] = 'public';
+
+ $info['name'] = $var->getName();
+ $info['link'] = $var->getLink($this);
+ $info['value'] = $this->postProcess($var->getValue());
+ if ($var->docblock)
+ $info['sdesc'] = $var->docblock->getSDesc($this);
+ $result["iconsts"][] = $info;
+ }
+ $results[] = $result;
+ $result = array();
+ }
+ return $results;
+ }
+
+ /**
+ * Return a Smarty template object to operate with
+ *
+ * This returns a Smarty template with pre-initialized variables for use.
+ * If the method "SmartyInit()" exists, it is called.
+ * @return Smarty
+ */
+ function &newSmarty()
+ {
+ $templ = new Smarty;
+ $templ->use_sub_dirs = false;
+ $templ->template_dir = realpath($this->smarty_dir . PATH_DELIMITER . 'templates');
+ $templ->compile_dir = realpath($this->smarty_dir . PATH_DELIMITER . 'templates_c');
+ $templ->config_dir = realpath($this->smarty_dir . PATH_DELIMITER . 'configs');
+ $templ->assign("date",date("r",time()));
+ $templ->assign("maintitle",$this->title);
+ $templ->assign("package",$this->package);
+ $templ->assign("phpdocversion",PHPDOCUMENTOR_VER);
+ $templ->assign("phpdocwebsite",PHPDOCUMENTOR_WEBSITE);
+ $templ->assign("subpackage",$this->subpackage);
+ if (method_exists($this,'SmartyInit')) return $this->SmartyInit($templ);
+ return $templ;
+ }
+
+ /**
+ * do all necessary output
+ * @see Converter
+ * @abstract
+ */
+ function Output($title)
+ {
+ phpDocumentor_out("WARNING: Generic Converter::Output was used, no output will be generated");
+ }
+
+ /**
+ * Set the template directory with a different template base directory
+ * @tutorial phpDocumentor.howto.pkg#using.command-line.templatebase
+ * @param string template base directory
+ * @param string template name
+ */
+ function setTemplateBase($base, $dir)
+ {
+ // remove trailing /'s from the base path, if any
+ $base = str_replace('\\','/',$base);
+ while ($base{strlen($base) - 1} == '/') $base = substr($base,0,strlen($base) - 1);
+ $this->templateName = substr($dir,0,strlen($dir) - 1);
+ $this->templateDir = $base . "/Converters/" . $this->outputformat . "/" . $this->name . "/templates/" . $dir;
+ if (!is_dir($this->templateDir))
+ {
+ addErrorDie(PDERROR_TEMPLATEDIR_DOESNT_EXIST, $this->templateDir);
+ }
+
+ $this->smarty_dir = $this->templateDir;
+ if (file_exists($this->templateDir . PATH_DELIMITER . 'options.ini'))
+ {
+ // retrieve template options, allow array creation
+ $this->template_options = phpDocumentor_parse_ini_file($this->templateDir . PATH_DELIMITER . 'options.ini',true);
+ }
+ }
+
+ /**
+ * sets the template directory based on the {@link $outputformat} and {@link $name}
+ * Also sets {@link $templateName} to the $dir parameter
+ * @param string subdirectory
+ */
+ function setTemplateDir($dir)
+ {
+ if ('@DATA-DIR@' != '@'.'DATA-DIR@') {
+ $templateBase = str_replace('\\', '/', '@DATA-DIR@/PhpDocumentor/phpDocumentor');
+ } else {
+ $templateBase = str_replace('\\','/',$GLOBALS['_phpDocumentor_install_dir']) . '/phpDocumentor';
+ }
+ $this->setTemplateBase($templateBase, $dir);
+ }
+
+ /**
+ * Get the absolute path to the converter's base directory
+ * @return string
+ */
+ function getConverterDir()
+ {
+ if (/*@donotremove*/0) {
+ return str_replace('\\', '/', "@DATA-DIR@/PhpDocumentor/phpDocumentor/Converters/") . $this->outputformat . "/" . $this->name;
+ } else {
+ return str_replace('\\','/',$GLOBALS['_phpDocumentor_install_dir']) ."/phpDocumentor/Converters/" . $this->outputformat . "/" . $this->name;
+ }
+ }
+
+ /**
+ * Parse a global variable's default value for class initialization.
+ *
+ * If a global variable's default value is "new class" as in:
+ * <code>
+ * $globalvar = new Parser
+ * </code>
+ * This method will document it not as "new Parser" but instead as
+ * "new {@link Parser}". For examples, see {@link phpdoc.inc}.
+ * Many global variables are classes, and phpDocumentor links to their
+ * documentation
+ * @return string default global variable value with link to class if
+ * it's "new Class"
+ * @param string default value of a global variable.
+ */
+ function getGlobalValue($value)
+ {
+ if (strpos($value,'new') === 0)
+ {
+ preg_match('/new([^(]*)(.*)/',$value,$newval);
+ if (isset($newval[1]))
+ {
+ $a = Converter::getLink(trim($newval[1]));
+ if (!isset($newval[2])) $newval[2] = '';
+ if ($a && phpDocumentor_get_class($a) == 'classlink') $value = 'new '.$this->returnSee($a).$newval[2];
+ }
+ }
+ return $value;
+ }
+
+ /**
+ * Parse an include's file to see if it is a file documented in this project
+ *
+ * Although not very smart yet, this method will try to look for the
+ * included file file.ext:
+ *
+ * <code>
+ * include ("file.ext");
+ * </code>
+ *
+ * If it finds it, it will return a link to the file's documentation. As of
+ * 1.2.0rc1, phpDocumentor is smarty enough to find these cases:
+ * <ul>
+ * <li>absolute path to file</li>
+ * <li>./file.ext or ../file.ext</li>
+ * <li>relpath/to/file.ext if relpath is a subdirectory of the base parse
+ * directory</li>
+ * </ul>
+ * For examples, see {@link Setup.inc.php} includes.
+ * Every include auto-links to the documentation for the file that is included
+ * @return string included file with link to docs for file, if found
+ * @param string file included by include statement.
+ * @param string path of file that has the include statement
+ */
+ function getIncludeValue($value, $ipath)
+ {
+ preg_match('/"([^"\']*\.[^"\']*)"/',$value,$match);
+ if (!isset($match[1]))
+ preg_match('/\'([^"\']*\.[^"\']*)\'/',$value,$match);
+ if (isset($match[1]))
+ {
+ $fancy_per = $this->proceduralpages->pathMatchesParsedFile($match[1],$ipath);
+ if ($fancy_per)
+ {
+ $link = $this->addLink($fancy_per);
+ if (is_object($link) && phpDocumentor_get_class($link) == 'pagelink' &&
+ isset($this->all_packages[$link->package]))
+ {
+ $value = $this->returnSee($link,$value);
+ }
+ } else
+ {
+ $per = Converter::getLink($match[1]);
+ if (is_object($per) && phpDocumentor_get_class($per) == 'pagelink')
+ $value = $this->returnSee($per);
+ }
+ }
+ return $value;
+ }
+
+ /**
+ * Recursively creates all subdirectories that don't exist in the $dir path
+ * @param string $dir
+ */
+ function createParentDir($dir)
+ {
+ if (empty($dir)) return;
+ $tmp = explode(SMART_PATH_DELIMITER,$dir);
+ array_pop($tmp);
+ $parent = implode(SMART_PATH_DELIMITER,$tmp);
+ if ($parent != '' && !file_exists($parent))
+ {
+ $test = @mkdir($parent,0775);
+ if (!$test)
+ {
+ $this->createParentDir($parent);
+ $test = @mkdir($parent,0775);
+ phpDocumentor_out("Creating Parent Directory $parent\n");
+ } else
+ {
+ phpDocumentor_out("Creating Parent Directory $parent\n");
+ }
+ }
+ }
+
+ /**
+ * Sets the output directory for generated documentation
+ * @param string $dir the output directory
+ */
+ function setTargetDir($dir)
+ {
+ if (strlen($dir) > 0)
+ {
+ $this->targetDir = $dir;
+ // if directory does exist create it, this should have more error checking in the future
+ if (!file_exists($dir))
+ {
+ $tmp = str_replace(array("/","\\"),SMART_PATH_DELIMITER,$dir);
+ if (substr($tmp,-1) == SMART_PATH_DELIMITER)
+ {
+ $tmp = substr($tmp,0,(strlen($tmp)-1));
+ }
+ $this->createParentDir($tmp);
+ phpDocumentor_out("Creating Directory $dir\n");
+ mkdir($dir,0775);
+ }
+ else if (!is_dir($dir))
+ {
+ echo "Output path: '$dir' is not a directory\n";
+ die();
+ }
+ } else {
+ echo "a target directory must be specified\n try phpdoc -h\n";
+ die();
+ }
+ }
+
+ /**
+ * Writes a file to target dir
+ * @param string
+ * @param string
+ * @param boolean true if the data is binary and not text
+ */
+ function writeFile($file,$data,$binary = false)
+ {
+ if (!file_exists($this->targetDir))
+ {
+ mkdir($this->targetDir,0775);
+ }
+ $string = '';
+ if ($binary) $string = 'binary file ';
+ phpDocumentor_out(" Writing $string".$this->targetDir . PATH_DELIMITER . $file . "\n");
+ flush();
+ $write = 'w';
+ if ($binary) $write = 'wb';
+ $fp = fopen($this->targetDir . PATH_DELIMITER . $file,$write);
+ set_file_buffer( $fp, 0 );
+ fwrite($fp,$data,strlen($data));
+ fclose($fp);
+ }
+
+ /**
+ * Copies a file from the template directory to the target directory
+ * thanks to Robert Hoffmann for this fix
+ * @param string
+ */
+ function copyFile($file, $subdir = '')
+ {
+ if (!file_exists($this->targetDir))
+ {
+ mkdir($this->targetDir,0775);
+ }
+ copy($this->templateDir . $subdir . PATH_DELIMITER . $file, $this->targetDir . PATH_DELIMITER . $file);
+ }
+
+ /**
+ * Return parserStringWithInlineTags::Convert() cache state
+ * @see parserStringWithInlineTags::Convert()
+ * @abstract
+ */
+ function getState()
+ {
+ return true;
+ }
+
+ /**
+ * Compare parserStringWithInlineTags::Convert() cache state to $state
+ * @param mixed
+ * @see parserStringWithInlineTags::Convert()
+ * @abstract
+ */
+ function checkState($state)
+ {
+ return true;
+ }
+
+}
+
+/**
+ * @access private
+ * @see Converter::getSortedClassTreeFromClass()
+ */
+function rootcmp($a, $b)
+{
+ return strnatcasecmp($a['class'],$b['class']);
+}
+
+/**
+ * @access private
+ * @global string used to make the first tutorials converted the default package tutorials
+ */
+function tutorialcmp($a, $b)
+{
+ global $phpDocumentor_DefaultPackageName;
+ if ($a == $phpDocumentor_DefaultPackageName) return -1;
+ if ($b == $phpDocumentor_DefaultPackageName) return 1;
+ return strnatcasecmp($a, $b);
+}
+
+/**
+ * smart htmlentities, doesn't entity the allowed tags list
+ * Since version 1.1, this function uses htmlspecialchars instead of
+ * htmlentities, for international support
+ * This function has been replaced by functionality in {@link ParserDescCleanup.inc}
+ * @param string $s
+ * @return string browser-displayable page
+ * @deprecated As of v1.2, No longer needed, as valid tags are parsed out of the source,
+ * and everything else is {@link Converter::postProcess()} handled
+ */
+function adv_htmlentities($s)
+{
+ return;
+ global $phpDocumentor___html,$_phpDocumentor_html_allowed;
+ $result = htmlspecialchars($s);
+ $entities = array_flip(get_html_translation_table(HTML_SPECIALCHARS));
+ $result = strtr($result,$phpDocumentor___html);
+ $matches = array();
+ preg_match_all('/(&lt;img.*&gt;)/U',$result,$matches);
+ for($i=0;$i<count($matches[1]);$i++)
+ {
+ $result = str_replace($matches[1][$i],strtr($matches[1][$i],array_flip(get_html_translation_table(HTML_SPECIALCHARS))),$result);
+ }
+ preg_match_all('/(&lt;font.*&gt;)/U',$result,$matches);
+ for($i=0;$i<count($matches[1]);$i++)
+ {
+ $result = str_replace($matches[1][$i],strtr($matches[1][$i],array_flip(get_html_translation_table(HTML_SPECIALCHARS))),$result);
+ }
+ preg_match_all('/(&lt;ol.*&gt;)/U',$result,$matches);
+ for($i=0;$i<count($matches[1]);$i++)
+ {
+ $result = str_replace($matches[1][$i],strtr($matches[1][$i],array_flip(get_html_translation_table(HTML_SPECIALCHARS))),$result);
+ }
+ preg_match_all('/(&lt;ul.*&gt;)/U',$result,$matches);
+ for($i=0;$i<count($matches[1]);$i++)
+ {
+ $result = str_replace($matches[1][$i],strtr($matches[1][$i],array_flip(get_html_translation_table(HTML_SPECIALCHARS))),$result);
+ }
+ preg_match_all('/(&lt;li.*&gt;)/U',$result,$matches);
+ for($i=0;$i<count($matches[1]);$i++)
+ {
+ $result = str_replace($matches[1][$i],strtr($matches[1][$i],array_flip(get_html_translation_table(HTML_SPECIALCHARS))),$result);
+ }
+ preg_match_all('/(&lt;a .*&gt;)/U',$result,$matches);
+ for($i=0;$i<count($matches[1]);$i++)
+ {
+ $result = str_replace($matches[1][$i],strtr($matches[1][$i],array_flip(get_html_translation_table(HTML_SPECIALCHARS))),$result);
+ }
+ return $result;
+}
+
+/**
+ * Used solely for setting up the @uses list
+ * @package ignore
+ * @ignore
+ */
+class __dummyConverter extends Converter
+{
+ function setTemplateDir(){}
+ function setTargetDir(){}
+ function getPageName(&$element)
+ {
+ if (phpDocumentor_get_class($element) == 'parserpage') return '_'.$element->getName();
+ return '_'.$element->parent->getName();
+ }
+}
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/CHMdefaultConverter.inc b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/CHMdefaultConverter.inc
new file mode 100644
index 00000000..ac38031b
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/CHMdefaultConverter.inc
@@ -0,0 +1,1753 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+/**
+ * CHM (Compiled Help Manual) output converter for Smarty Template.
+ *
+ * @package Converters
+ * @subpackage CHMdefault
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: CHMdefaultConverter.inc,v 1.1 2005/10/17 18:36:57 jeichorn Exp $
+ */
+/**
+ * Generates files that MS HTML Help Worshop can use to create a MS Windows
+ * compiled help file (CHM)
+ *
+ * The free MS HTML Help compiler takes the project file (phpdoc.hhp) and reads
+ * the table of contents file specified in the project (which is always contents.hhc
+ * in phpDocumentor). When the converter reaches stable state, it will also
+ * output an index file index.hhk. The free download for MS HTML Help Workshop
+ * is available below
+ * @link http://www.microsoft.com/downloads/release.asp?releaseid=33071 MS HTML Help Workshop download
+ * @package Converters
+ * @subpackage CHMdefault
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Revision: 1.1 $
+ */
+class CHMdefaultConverter extends Converter
+{
+ /**
+ * CHMdefaultConverter wants elements sorted by type as well as alphabetically
+ * @see Converter::$sort_page_contents_by_type
+ * @var boolean
+ */
+ var $sort_page_contents_by_type = true;
+ /** @var string */
+ var $outputformat = 'CHM';
+ /** @var string */
+ var $name = 'default';
+ /**
+ * indexes of elements by package that need to be generated
+ * @var array
+ */
+ var $leftindex = array('classes' => true, 'pages' => true, 'functions' => true, 'defines' => false, 'globals' => false);
+
+ /**
+ * output directory for the current procedural page being processed
+ * @var string
+ */
+ var $page_dir;
+
+ /**
+ * target directory passed on the command-line.
+ * {@link $targetDir} is malleable, always adding package/ and package/subpackage/ subdirectories onto it.
+ * @var string
+ */
+ var $base_dir;
+
+ /**
+ * output directory for the current class being processed
+ * @var string
+ */
+ var $class_dir;
+
+ /**
+ * array of converted package page names.
+ * Used to link to the package page in the left index
+ * @var array Format: array(package => 1)
+ */
+ var $package_pages = array();
+
+ /**
+ * controls formatting of parser informative output
+ *
+ * Converter prints:
+ * "Converting /path/to/file.php... Procedural Page Elements... Classes..."
+ * Since CHMdefaultConverter outputs files while converting, it needs to send a \n to start a new line. However, if there
+ * is more than one class, output is messy, with multiple \n's just between class file output. This variable prevents that
+ * and is purely cosmetic
+ * @var boolean
+ */
+ var $juststarted = false;
+
+ /**
+ * contains all of the template procedural page element loop data needed for the current template
+ * @var array
+ */
+ var $current;
+
+ /**
+ * contains all of the template class element loop data needed for the current template
+ * @var array
+ */
+ var $currentclass;
+ var $wrote = false;
+ var $ric_set = array();
+ /**
+ * Table of Contents entry for index.hhk
+ * @var array
+ */
+ var $KLinks = array();
+
+ /**
+ * sets {@link $base_dir} to $targetDir
+ * @see Converter()
+ */
+ function CHMdefaultConverter(&$allp, &$packp, &$classes, &$procpages, $po, $pp, $qm, $targetDir, $templateDir, $title)
+ {
+ Converter::Converter($allp, $packp, $classes, $procpages,$po, $pp, $qm, $targetDir, $templateDir, $title);
+ $this->base_dir = $targetDir;
+ }
+
+ /**
+ * @deprecated in favor of PHP 4.3.0+ tokenizer-based source highlighting
+ */
+ function unmangle($sourcecode)
+ {
+ $sourcecode = str_replace('<code>','<pre>',$sourcecode);
+ $sourcecode = str_replace('</code>','</pre>',$sourcecode);
+ $sourcecode = str_replace('<br />',"\n",$sourcecode);
+ $sourcecode = str_replace('&nbsp;',' ',$sourcecode);
+ $sourcecode = str_replace('&lt;','<',$sourcecode);
+ $sourcecode = str_replace('&gt;','>',$sourcecode);
+ $sourcecode = str_replace('&amp;','&',$sourcecode);
+ return $sourcecode;
+ }
+
+ /**
+ * @param string full path to the source file
+ * @param string fully highlighted source code
+ */
+ function writeSource($path, $value)
+ {
+ $templ = &$this->newSmarty();
+ $pathinfo = $this->proceduralpages->getPathInfo($path, $this);
+ $templ->assign('source',$value);
+ $templ->assign('package',$pathinfo['package']);
+ $templ->assign('subpackage',$pathinfo['subpackage']);
+ $templ->assign('name',$pathinfo['name']);
+ $templ->assign('source_loc',$pathinfo['source_loc']);
+ $templ->assign('docs',$pathinfo['docs']);
+ $templ->assign("subdir",'../');
+ $templ->register_outputfilter('CHMdefault_outputfilter');
+ $this->setTargetDir($this->getFileSourcePath($this->base_dir));
+ $this->addSourceTOC($pathinfo['name'],$this->getFileSourceName($path),$pathinfo['package'],$pathinfo['subpackage'], true);
+ phpDocumentor_out("\n");
+ $this->setSourcePaths($path);
+ $this->writefile($this->getFileSourceName($path).'.html',$templ->fetch('filesource.tpl'));
+ }
+
+ function writeExample($title, $path, $source)
+ {
+ $templ = &$this->newSmarty();
+ $templ->assign('source',$source);
+ if (empty($title))
+ {
+ $title = 'example';
+ addWarning(PDERROR_EMPTY_EXAMPLE_TITLE, $path, $title);
+ }
+ $templ->assign('title',$title);
+ $templ->assign('file',$path);
+ $templ->assign("subdir",'../');
+ $templ->register_outputfilter('CHMdefault_outputfilter');
+ $pathinfo = $this->proceduralpages->getPathInfo($path, $this);
+ $this->setTargetDir($this->base_dir . PATH_DELIMITER . '__examplesource');
+ $this->addSourceTOC($title,'exsource_'.$path,$pathinfo['package'],$pathinfo['subpackage'], false);
+ phpDocumentor_out("\n");
+ $this->writefile('exsource_'.$path.'.html',$templ->fetch('examplesource.tpl'));
+ }
+
+ function getExampleLink($path, $title)
+ {
+ return $this->returnLink('{$subdir}__examplesource' . PATH_DELIMITER . 'exsource_'.$path.'.html',$title);
+ }
+
+ function getSourceLink($path)
+ {
+ // fix 1171583
+ $x = str_replace(PATH_DELIMITER, '', $this->getFileSourcePath('{$subdir}')) .
+ PATH_DELIMITER;
+ return $this->returnLink($x .
+ $this->getFileSourceName($path).'.html','Source Code for this file');
+ }
+
+ /**
+ * Used to convert the <<code>> tag in a docblock
+ * @param string
+ * @param boolean
+ * @return string
+ */
+ function ProgramExample($example, $tutorial = false, $inlinesourceparse = null/*false*/,
+ $class = null/*false*/, $linenum = null/*false*/, $filesourcepath = null/*false*/)
+ {
+ return $this->PreserveWhiteSpace(parent::ProgramExample($example, $tutorial, $inlinesourceparse, $class, $linenum, $filesourcepath));
+ }
+
+ /**
+ * @param string
+ */
+ function TutorialExample($example)
+ {
+ $trans = $this->template_options['desctranslate'];
+ $this->template_options['desctranslate'] = array();
+ $example = '<ol>' . parent::TutorialExample($example)
+ .'</ol>';
+ $this->template_options['desctranslate'] = $trans;
+ 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'];
+ }
+
+ /**
+ * Retrieve a Converter-specific anchor to a segment of a source code file
+ * parsed via a {@tutorial tags.filesource.pkg} tag.
+ * @param string full path to source file
+ * @param string name of anchor
+ * @param string link text, if this is a link
+ * @param boolean returns either a link or a destination based on this
+ * parameter
+ * @return string link to an anchor, or the anchor
+ */
+ function getSourceAnchor($sourcefile,$anchor,$text = '',$link = false)
+ {
+ if ($link) {
+ $x = str_replace(PATH_DELIMITER, '', $this->getFileSourcePath('{$subdir}')) .
+ PATH_DELIMITER;
+ return $this->returnLink($x .
+ $this->getFileSourceName($sourcefile).'.html#a'.$anchor, $text);
+ } else
+ return '<a name="a'.$anchor.'"></a>';
+ }
+
+ function getCurrentPageLink()
+ {
+ return $this->curname . '.html';
+ }
+
+ /**
+ * Uses htmlspecialchars() on the input
+ */
+ function postProcess($text)
+ {
+ return htmlspecialchars($text);
+ }
+
+ /**
+ * Use the template tutorial_toc.tpl to generate a table of contents for HTML
+ * @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)
+ {
+ $template = &$this->newSmarty();
+ $template->assign('toc',$toc);
+ return $template->fetch('tutorial_toc.tpl');
+ }
+
+ function &SmartyInit(&$templ)
+ {
+ if (!isset($this->package_index))
+ foreach($this->all_packages as $key => $val)
+ {
+ if (isset($this->pkg_elements[$key]))
+ {
+ if (!isset($start)) $start = $key;
+ $this->package_index[] = array('link' => "li_$key.html", 'title' => $key);
+ }
+ }
+ $templ->assign("packageindex",$this->package_index);
+ $templ->assign("subdir",'');
+ return $templ;
+ }
+
+
+ /**
+ * Writes out the template file of {@link $class_data} and unsets the template to save memory
+ * @see registerCurrentClass()
+ * @see parent::endClass()
+ */
+ function endClass()
+ {
+ $a = '../';
+ if (!empty($this->subpackage)) $a .= '../';
+ if ($this->juststarted)
+ {
+ $this->juststarted = false;
+ phpDocumentor_out("\n");
+ flush();
+ }
+ $this->setTargetDir($this->base_dir . PATH_DELIMITER . $this->class_dir);
+ $this->class_data->assign("subdir",$a);
+ $this->class_data->register_outputfilter('CHMdefault_outputfilter');
+ $this->addTOC($this->class,$this->class,$this->package,$this->subpackage, true);
+ $this->writefile($this->class . '.html',$this->class_data->fetch('class.tpl'));
+ unset($this->class_data);
+ }
+
+ /**
+ * Writes out the template file of {@link $page_data} and unsets the template to save memory
+ * @see registerCurrent()
+ * @see parent::endPage()
+ */
+ function endPage()
+ {
+ $this->package = $this->curpage->package;
+ $this->subpackage = $this->curpage->subpackage;
+ $a = '../';
+ if (!empty($this->subpackage)) $a .= '../';
+ $this->setTargetDir($this->base_dir . PATH_DELIMITER . $this->page_dir);
+ $this->page_data->assign("package",$this->package);
+ $this->page_data->assign("subdir",$a);
+ $this->page_data->register_outputfilter('CHMdefault_outputfilter');
+ $this->addTOC($this->curpage->file,$this->page,$this->package,$this->subpackage);
+ $this->writefile($this->page . '.html',$this->page_data->fetch('page.tpl'));
+ unset($this->page_data);
+ }
+
+ /**
+ * @param string
+ * @param string
+ * @return string &lt;a href="'.$link.'">'.$text.'</a&gt;
+ */
+ function returnLink($link,$text)
+ {
+ return '<a href="'.$link.'">'.$text.'</a>';
+ }
+
+ /**
+ * CHMdefaultConverter chooses to format both package indexes and the complete index here
+ *
+ * This function formats output for the elementindex.html and pkgelementindex.html template files. It then
+ * writes them to the target directory
+ * @see generateElementIndex(), generatePkgElementIndex()
+ */
+ function formatPkgIndex()
+ {
+ list($package_indexes,$packages,$mletters) = $this->generatePkgElementIndexes();
+ for($i=0;$i<count($package_indexes);$i++)
+ {
+ $template = &$this->newSmarty();
+ $this->package = $package_indexes[$i]['package'];
+ $this->subpackage = '';
+ $template->assign("index",$package_indexes[$i]['pindex']);
+ $template->assign("package",$package_indexes[$i]['package']);
+ $template->assign("letters",$mletters[$package_indexes[$i]['package']]);
+ $template->assign("title","Package ".$package_indexes[$i]['package']." Element Index");
+ $template->assign("subdir",'../');
+ $template->register_outputfilter('CHMdefault_outputfilter');
+ $this->setTargetDir($this->base_dir . PATH_DELIMITER . $package_indexes[$i]['package']);
+ $this->addTOC($package_indexes[$i]['package']." Alphabetical Index",'elementindex_'.$package_indexes[$i]['package'],$package_indexes[$i]['package'],'');
+ $this->writefile('elementindex_'.$package_indexes[$i]['package'].'.html',$template->fetch('pkgelementindex.tpl'));
+ }
+ phpDocumentor_out("\n");
+ flush();
+ }
+
+ /**
+ * CHMdefaultConverter uses this function to format template index.html and packages.html
+ *
+ * This function generates the package list from {@link $all_packages}, eliminating any
+ * packages that don't have any entries in their package index (no files at all, due to @ignore
+ * or other factors). Then it uses the default package name as the first package index to display.
+ * It sets the right pane to be either a blank file with instructions on making package-level docs,
+ * or the package-level docs for the default package.
+ * @global string Used to set the starting package to display
+ */
+ function formatIndex()
+ {
+ global $phpDocumentor_DefaultPackageName;
+ list($elindex,$mletters) = $this->generateElementIndex();
+ $template = &$this->newSmarty();
+ $template->assign("index",$elindex);
+ $template->assign("letters",$mletters);
+ $template->assign("title","Element Index");
+ $template->assign("date",date("r",time()));
+ $template->register_outputfilter('CHMdefault_outputfilter');
+ phpDocumentor_out("\n");
+ flush();
+ $this->setTargetDir($this->base_dir);
+ $this->addTOC("Alphabetical Index Of All Elements",'elementindex',"Index",'');
+ $this->writefile('elementindex.html',$template->fetch('elementindex.tpl'));
+ usort($this->package_index,"CHMdefault_pindexcmp");
+ $index = &$this->newSmarty();
+ foreach($this->all_packages as $key => $val)
+ {
+ if (isset($this->pkg_elements[$key]))
+ {
+ if (!isset($start)) $start = $key;
+ if (!isset($this->package_pages[$key])) $this->writeNewPPage($key);
+ }
+ }
+ $this->setTargetDir($this->base_dir);
+ // Created index.html
+ if (isset($this->pkg_elements[$phpDocumentor_DefaultPackageName])) $start = $phpDocumentor_DefaultPackageName;
+ $this->package = $start;
+ $this->subpackage = '';
+ $setalready = false;
+ if (isset($this->tutorials[$start]['']['pkg']))
+ {
+ foreach($this->tutorials[$start]['']['pkg'] as $tute)
+ {
+ if ($tute->name == $start . '.pkg')
+ {
+ $setalready = true;
+ $this->addTOC("Start page",$start.'/tutorial_'.$tute->name,"Index",'');
+ }
+ }
+ }
+ if (!$setalready)
+ {
+ if (isset($this->package_pages[$start]))
+ {
+ $this->addTOC("Start page",'package_'.$start,"Index",'');
+ }
+ else
+ {
+ $index->assign("blank","blank");
+ $blank = &$this->newSmarty();
+ $blank->assign('package',$phpDocumentor_DefaultPackageName);
+ $this->addTOC("Start page",'blank',"Index",'');
+ $this->writefile("blank.html",$blank->fetch('blank.tpl'));
+ Converter::writefile('index.html',$blank->fetch('tutorial.tpl'));
+ }
+ }
+ phpDocumentor_out("\n");
+ flush();
+
+ unset($index);
+ }
+
+ function writeNewPPage($key)
+ {
+ return;
+ $template = &$this->newSmarty();
+ $this->package = $key;
+ $this->subpackage = '';
+ $template->assign("date",date("r",time()));
+ $template->assign("title",$this->title);
+ $template->assign("package",$key);
+ $template->register_outputfilter('CHMdefault_outputfilter');
+ phpDocumentor_out("\n");
+ flush();
+ $this->setTargetDir($this->base_dir);
+
+ $this->addTOC("$key Index","li_$key",$key,'');
+ $this->writefile("li_$key.html",$template->fetch('index.tpl'));
+ unset($template);
+ }
+
+ /**
+ * Generate indexes for li_package.html and classtree output files
+ *
+ * This function generates the li_package.html files from the template file left.html. It does this by
+ * iterating through each of the $page_elements, $class_elements and $function_elements arrays to retrieve
+ * the pre-sorted {@link abstractLink} descendants needed for index generation. Conversion of these links to
+ * text is done by {@link returnSee()}. The {@link $local} parameter is set to false to ensure that paths are correct.
+ *
+ * Then it uses {@link generateFormattedClassTrees()} to create class trees from the template file classtrees.html. Output
+ * filename is classtrees_packagename.html. This function also unsets {@link $elements} and {@link $pkg_elements} to free
+ * up the considerable memory these two class vars use
+ * @see $page_elements, $class_elements, $function_elements
+ */
+ function formatLeftIndex()
+ {
+ phpDocumentor_out("\n");
+ flush();
+ $this->setTargetDir($this->base_dir);
+ if (0)//!isset($this->left))
+ {
+ debug("Nothing parsed, check the command-line");
+ die();
+ }
+ foreach($this->all_packages as $package => $rest)
+ {
+ if (!isset($this->pkg_elements[$package])) continue;
+
+ // Create class tree page
+ $template = &$this->newSmarty();
+ $template->assign("classtrees",$this->generateFormattedClassTrees($package));
+ $template->assign("package",$package);
+ $template->assign("date",date("r",time()));
+ $template->register_outputfilter('CHMdefault_outputfilter');
+ $this->addTOC("$package Class Trees","classtrees_$package",$package,'');
+ $this->writefile("classtrees_$package.html",$template->fetch('classtrees.tpl'));
+ phpDocumentor_out("\n");
+ flush();
+ }
+ // free up considerable memory
+ unset($this->elements);
+ unset($this->pkg_elements);
+ }
+
+ /**
+ * This function takes an {@link abstractLink} descendant and returns an html link
+ *
+ * @param abstractLink a descendant of abstractlink should be passed, and never text
+ * @param string text to display in the link
+ * @param boolean this parameter is not used, and is deprecated
+ * @param boolean determines whether the returned text is enclosed in an <a> tag
+ */
+ function returnSee(&$element, $eltext = false, $with_a = true)
+ {
+ if (!$element) return false;
+ if (!$with_a) return $this->getId($element, false);
+ if (!$eltext)
+ {
+ $eltext = '';
+ switch($element->type)
+ {
+ case 'tutorial' :
+ $eltext = strip_tags($element->title);
+ break;
+ case 'method' :
+ case 'var' :
+ case 'const' :
+ $eltext .= $element->class.'::';
+ case 'page' :
+ case 'define' :
+ case 'class' :
+ case 'function' :
+ case 'global' :
+ default :
+ $eltext .= $element->name;
+ if ($element->type == 'function' || $element->type == 'method') $eltext .= '()';
+ break;
+ }
+ }
+ return '<a href="'.$this->getId($element).'">'.$eltext.'</a>';
+ }
+
+ function getId($element, $fullpath = true)
+ {
+ if (phpDocumentor_get_class($element) == 'parserdata')
+ {
+ $element = $this->addLink($element->parent);
+ $elp = $element->parent;
+ } elseif (is_a($element, 'parserbase'))
+ {
+ $elp = $element;
+ $element = $this->addLink($element);
+ }
+ $c = '';
+ if (!empty($element->subpackage))
+ {
+ $c = '/'.$element->subpackage;
+ }
+ $b = '{$subdir}';
+ switch ($element->type)
+ {
+ case 'page' :
+ if ($fullpath)
+ return $b.$element->package.$c.'/'.$element->fileAlias.'.html';
+ return 'top';
+ break;
+ case 'define' :
+ case 'global' :
+ case 'function' :
+ if ($fullpath)
+ return $b.$element->package.$c.'/'.$element->fileAlias.'.html#'.$element->type.$element->name;
+ return $element->type.$element->name;
+ break;
+ case 'class' :
+ if ($fullpath)
+ return $b.$element->package.$c.'/'.$element->name.'.html';
+ return 'top';
+ break;
+ case 'method' :
+ case 'var' :
+ case 'const' :
+ if ($fullpath)
+ return $b.$element->package.$c.'/'.$element->class.'.html#'.$element->type.$element->name;
+ return $element->type.$element->name;
+ break;
+ case 'tutorial' :
+ $d = '';
+ if ($element->section)
+ {
+ $d = '#'.$element->section;
+ }
+ return $b.$element->package.$c.'/tutorial_'.$element->name.'.html'.$d;
+ }
+ }
+
+ function ConvertTodoList()
+ {
+ $todolist = array();
+ foreach($this->todoList as $package => $alltodos)
+ {
+ foreach($alltodos as $todos)
+ {
+ $converted = array();
+ $converted['link'] = $this->returnSee($todos[0]);
+ if (!is_array($todos[1]))
+ {
+ $converted['todos'][] = $todos[1]->Convert($this);
+ } else
+ {
+ foreach($todos[1] as $todo)
+ {
+ $converted['todos'][] = $todo->Convert($this);
+ }
+ }
+ $todolist[$package][] = $converted;
+ }
+ }
+ $templ = &$this->newSmarty();
+ $templ->assign('todos',$todolist);
+ $templ->register_outputfilter('CHMdefault_outputfilter');
+ $this->setTargetDir($this->base_dir);
+ $this->addTOC('Todo List','todolist','Index','',false,true);
+ $this->addKLink('Todo List', 'todolist', '', 'Development');
+ $this->writefile('todolist.html',$templ->fetch('todolist.tpl'));
+ }
+
+ /**
+ * Convert README/INSTALL/CHANGELOG file contents to output format
+ * @param README|INSTALL|CHANGELOG
+ * @param string contents of the file
+ */
+ function Convert_RIC($name, $contents)
+ {
+ $template = &$this->newSmarty();
+ $template->assign('contents',$contents);
+ $template->assign('name',$name);
+ $this->setTargetDir($this->base_dir);
+ $this->addTOC($name,'ric_'.$name,'Index','',false,true);
+ $this->addKLink($name, 'ric_'.$name, '', 'Development');
+ $this->writefile('ric_'.$name . '.html',$template->fetch('ric.tpl'));
+ $this->ric_set[$name] = true;
+ }
+
+ /**
+ * Create errors.html template file output
+ *
+ * This method takes all parsing errors and warnings and spits them out ordered by file and line number.
+ * @global ErrorTracker We'll be using it's output facility
+ */
+ function ConvertErrorLog()
+ {
+ global $phpDocumentor_errors;
+ $allfiles = array();
+ $files = array();
+ $warnings = $phpDocumentor_errors->returnWarnings();
+ $errors = $phpDocumentor_errors->returnErrors();
+ $template = &$this->newSmarty();
+ foreach($warnings as $warning)
+ {
+ $file = '##none';
+ $linenum = 'Warning';
+ if ($warning->file)
+ {
+ $file = $warning->file;
+ $allfiles[$file] = 1;
+ $linenum .= ' on line '.$warning->linenum;
+ }
+ $files[$file]['warnings'][] = array('name' => $linenum, 'listing' => $warning->data);
+ }
+ foreach($errors as $error)
+ {
+ $file = '##none';
+ $linenum = 'Error';
+ if ($error->file)
+ {
+ $file = $error->file;
+ $allfiles[$file] = 1;
+ $linenum .= ' on line '.$error->linenum;
+ }
+ $files[$file]['errors'][] = array('name' => $linenum, 'listing' => $error->data);
+ }
+ $i=1;
+ $af = array();
+ foreach($allfiles as $file => $num)
+ {
+ $af[$i++] = $file;
+ }
+ $allfiles = $af;
+ usort($allfiles,'strnatcasecmp');
+ $allfiles[0] = "Post-parsing";
+ foreach($allfiles as $i => $a)
+ {
+ $allfiles[$i] = array('file' => $a);
+ }
+ $out = array();
+ foreach($files as $file => $data)
+ {
+ if ($file == '##none') $file = 'Post-parsing';
+ $out[$file] = $data;
+ }
+ $template->assign("files",$allfiles);
+ $template->assign("all",$out);
+ $template->assign("title","phpDocumentor Parser Errors and Warnings");
+ $this->setTargetDir($this->base_dir);
+ $this->writefile("errors.html",$template->fetch('errors.tpl'));
+ unset($template);
+ phpDocumentor_out("\n\nTo view errors and warnings, look at ".$this->base_dir. PATH_DELIMITER . "errors.html\n");
+ flush();
+ }
+
+ function getCData($value)
+ {
+ return '<pre>'.htmlentities($value).'</pre>';
+ }
+
+ function getTutorialId($package,$subpackage,$tutorial,$id)
+ {
+ return $id;
+ }
+
+ /**
+ * Converts package page and sets its package as used in {@link $package_pages}
+ * @param parserPackagePage
+ */
+ function convertPackagepage(&$element)
+ {
+ phpDocumentor_out("\n");
+ flush();
+ $this->package = $element->package;
+ $this->subpackage = '';
+ $contents = $element->Convert($this);
+ $this->package_pages[$element->package] = str_replace('{$subdir}','../',$contents);
+ phpDocumentor_out("\n");
+ flush();
+ $this->setTargetDir($this->base_dir . PATH_DELIMITER . $element->package);
+ $this->addTOC($element->package." Tutorial",'package_'.$element->package,$element->package,'');
+ $this->writeFile('package_'.$element->package.'.html',str_replace('{$subdir}','../',$contents));
+ $this->setTargetDir($this->base_dir);
+ Converter::writefile('index.html',str_replace('{$subdir}','',$contents));
+ $this->addKLink($element->package." Tutorial", 'package_'.$element->package, '', 'Tutorials');
+ }
+
+ /**
+ * @param parserTutorial
+ */
+ function convertTutorial(&$element)
+ {
+ phpDocumentor_out("\n");
+ flush();
+ $template = &parent::convertTutorial($element);
+ $a = '../';
+ if ($element->subpackage) $a .= '../';
+ $template->assign('subdir',$a);
+ $template->register_outputfilter('CHMdefault_outputfilter');
+ $contents = $template->fetch('tutorial.tpl');
+ if ($element->package == $GLOBALS['phpDocumentor_DefaultPackageName'] && empty($element->subpackage) && ($element->name == $element->package . '.pkg'))
+ {
+ $template->assign('subdir','');
+ $this->setTargetDir($this->base_dir);
+ Converter::writefile('index.html',$template->fetch('tutorial.tpl'));
+ }
+ $a = '';
+ if ($element->subpackage) $a = PATH_DELIMITER . $element->subpackage;
+ phpDocumentor_out("\n");
+ flush();
+ $this->setTargetDir($this->base_dir . PATH_DELIMITER . $element->package . $a);
+ $this->addTOC($a = strip_tags($element->getTitle($this)), 'tutorial_'.$element->name,
+ $element->package, $element->subpackage, false, true);
+ $this->writeFile('tutorial_'.$element->name.'.html',$contents);
+ $this->addKLink($element->getTitle($this), $element->package . $a . PATH_DELIMITER . 'tutorial_'.$element->name,
+ '', 'Tutorials');
+ }
+
+ /**
+ * Converts class for template output
+ * @see prepareDocBlock(), generateChildClassList(), generateFormattedClassTree(), getFormattedConflicts()
+ * @see getFormattedInheritedMethods(), getFormattedInheritedVars()
+ * @param parserClass
+ */
+ function convertClass(&$element)
+ {
+ parent::convertClass($element);
+ $this->class_dir = $element->docblock->package;
+ if (!empty($element->docblock->subpackage)) $this->class_dir .= PATH_DELIMITER . $element->docblock->subpackage;
+ $a = '../';
+ if ($element->docblock->subpackage != '') $a = "../$a";
+
+ $this->class_data->assign('subdir',$a);
+ $this->class_data->assign("title","Docs For Class " . $element->getName());
+ $this->class_data->assign("page",$element->getName() . '.html');
+ $this->addKLink($element->name, $this->class_dir . PATH_DELIMITER . $this->class, '', 'Classes');
+ }
+
+
+ /**
+ * Converts class variables for template output
+ * @see prepareDocBlock(), getFormattedConflicts()
+ * @param parserDefine
+ */
+ function convertVar(&$element)
+ {
+ parent::convertVar($element, array('var_dest' => $this->getId($element,false)));
+ $this->setTargetDir($this->base_dir . PATH_DELIMITER . $this->class_dir);
+ $this->addKLink($element->name, $this->class_dir . PATH_DELIMITER .$this->class, $this->getId($element,false), $element->class.' Properties');
+ }
+
+ /**
+ * Converts class constants for template output
+ * @see prepareDocBlock(), getFormattedConflicts()
+ * @param parserDefine
+ */
+ function convertConst(&$element)
+ {
+ parent::convertConst($element, array('const_dest' => $this->getId($element,false)));
+ $this->setTargetDir($this->base_dir . PATH_DELIMITER . $this->class_dir);
+ $this->addKLink($element->name, $this->class_dir . PATH_DELIMITER .$this->class, $this->getId($element,false), $element->class.' Constants');
+ }
+
+ /**
+ * Converts class methods for template output
+ * @see prepareDocBlock(), getFormattedConflicts()
+ * @param parserDefine
+ */
+ function convertMethod(&$element)
+ {
+ parent::convertMethod($element, array('method_dest' => $this->getId($element,false)));
+ $this->setTargetDir($this->base_dir . PATH_DELIMITER . $this->class_dir);
+ $this->addKLink($element->name, $this->class_dir . PATH_DELIMITER .$this->class, $this->getId($element,false), $element->class.' Methods');
+ }
+
+ /**
+ * Converts function for template output
+ * @see prepareDocBlock(), parserFunction::getFunctionCall(), getFormattedConflicts()
+ * @param parserFunction
+ */
+ function convertFunction(&$element)
+ {
+ $funcloc = $this->getId($this->addLink($element));
+ parent::convertFunction($element,array('function_dest' => $this->getId($element,false)));
+ $this->setTargetDir($this->base_dir . PATH_DELIMITER . $this->page_dir);
+ $this->addKLink($element->name, $this->page_dir . PATH_DELIMITER . $this->page, $this->getId($element,false), 'Functions');
+ }
+
+ /**
+ * Converts include elements for template output
+ * @see prepareDocBlock()
+ * @param parserInclude
+ */
+ function convertInclude(&$element)
+ {
+ parent::convertInclude($element, array('include_file' => '_'.strtr($element->getValue(),array('"' => '', "'" => '','.' => '_'))));
+ $this->setTargetDir($this->base_dir . PATH_DELIMITER . $this->page_dir);
+ $this->addKLink(str_replace('"', '', $element->getValue()), $this->page_dir . PATH_DELIMITER . $this->page, '', ucfirst($element->name));
+ }
+
+ /**
+ * Converts defines for template output
+ * @see prepareDocBlock(), getFormattedConflicts()
+ * @param parserDefine
+ */
+ function convertDefine(&$element)
+ {
+ parent::convertDefine($element, array('define_link' => $this->getId($element,false)));
+ $this->setTargetDir($this->base_dir . PATH_DELIMITER . $this->page_dir);
+ $this->addKLink($element->name, $this->page_dir . PATH_DELIMITER . $this->page, $this->getId($element,false), 'Constants');
+ }
+
+ /**
+ * Converts global variables for template output
+ * @param parserGlobal
+ */
+ function convertGlobal(&$element)
+ {
+ parent::convertGlobal($element, array('global_link' => $this->getId($element,false)));
+ $this->setTargetDir($this->base_dir . PATH_DELIMITER . $this->page_dir);
+ $this->addKLink($element->name, $this->page_dir . PATH_DELIMITER . $this->page, $this->getId($element,false), 'Global Variables');
+ }
+
+ /**
+ * converts procedural pages for template output
+ * @see prepareDocBlock(), getClassesOnPage()
+ * @param parserData
+ */
+ function convertPage(&$element)
+ {
+ parent::convertPage($element);
+ $this->juststarted = true;
+ $this->page_dir = $element->parent->package;
+ if (!empty($element->parent->subpackage)) $this->page_dir .= PATH_DELIMITER . $element->parent->subpackage;
+ // registering stuff on the template
+ $this->page_data->assign("page",$this->getPageName($element) . '.html');
+ $this->page_data->assign("title","Docs for page ".$element->parent->getFile());
+ $this->setTargetDir($this->base_dir . PATH_DELIMITER . $this->page_dir);
+ $this->addKLink($element->parent->file, $this->page_dir . PATH_DELIMITER . $this->page, '', 'Files');
+ }
+
+ function getPageName(&$element)
+ {
+ if (phpDocumentor_get_class($element) == 'parserpage') return '_'.$element->getName();
+ return '_'.$element->parent->getName();
+ }
+
+ /**
+ * returns an array containing the class inheritance tree from the root object to the class
+ *
+ * @param parserClass class variable
+ * @return array Format: array(root,child,child,child,...,$class)
+ * @uses parserClass::getParentClassTree()
+ */
+
+ function generateFormattedClassTree($class)
+ {
+ $tree = $class->getParentClassTree($this);
+ $out = '';
+ if (count($tree) - 1)
+ {
+ $result = array($class->getName());
+ $parent = $tree[$class->getName()];
+ $distance[] = '';
+ while ($parent)
+ {
+ $x = $parent;
+ if (is_object($parent))
+ {
+ $subpackage = $parent->docblock->subpackage;
+ $package = $parent->docblock->package;
+ $x = $parent;
+ $x = $parent->getLink($this);
+ if (!$x) $x = $parent->getName();
+ }
+ $result[] =
+ $x;
+ $distance[] =
+ "\n%s|\n" .
+ "%s--";
+ if (is_object($parent))
+ $parent = $tree[$parent->getName()];
+ elseif (isset($tree[$parent]))
+ $parent = $tree[$parent];
+ }
+ $nbsp = ' ';
+ for($i=count($result) - 1;$i>=0;$i--)
+ {
+ $my_nbsp = '';
+ for($j=0;$j<count($result) - $i;$j++) $my_nbsp .= $nbsp;
+ $distance[$i] = sprintf($distance[$i],$my_nbsp,$my_nbsp);
+ }
+ return array('classes'=>array_reverse($result),'distance'=>array_reverse($distance));
+ } else
+ {
+ return array('classes'=>$class->getName(),'distance'=>array(''));
+ }
+ }
+
+ /** @access private */
+ function sortVar($a, $b)
+ {
+ return strnatcasecmp($a->getName(),$b->getName());
+ }
+
+ /** @access private */
+ function sortMethod($a, $b)
+ {
+ if ($a->isConstructor) return -1;
+ if ($b->isConstructor) return 1;
+ return strnatcasecmp($a->getName(),$b->getName());
+ }
+
+ /**
+ * returns a template-enabled array of class trees
+ *
+ * @param string $package package to generate a class tree for
+ * @see $roots, HTMLConverter::getRootTree()
+ */
+ function generateFormattedClassTrees($package)
+ {
+ if (!isset($this->roots[$package])) return array();
+ $roots = $trees = array();
+ $roots = $this->roots[$package];
+ for($i=0;$i<count($roots);$i++)
+ {
+ $trees[] = array('class' => $roots[$i],'class_tree' => "<ul>\n".$this->getRootTree($this->getSortedClassTreeFromClass($roots[$i],$package,''),$package)."</ul>\n");
+ }
+ return $trees;
+ }
+
+ /**
+ * return formatted class tree for the Class Trees page
+ *
+ * @param array $tree output from {@link getSortedClassTreeFromClass()}
+ * @see Classes::$definitechild, generateFormattedClassTrees()
+ * @return string
+ */
+ function getRootTree($tree,$package)
+ {
+ if (!$tree) return '';
+ $my_tree = '';
+ $cur = '#root';
+ $lastcur = array(false);
+ $kids = array();
+ $dopar = false;
+ if ($tree[$cur]['parent'])
+ {
+ $dopar = true;
+ if (!is_object($tree[$cur]['parent']))
+ {
+// debug("parent ".$tree[$cur]['parent']." not found");
+ $my_tree .= '<li>' . $tree[$cur]['parent'] .'<ul>';
+ }
+ else
+ {
+// debug("parent ".$this->returnSee($tree[$cur]['parent'])." in other package");
+ $my_tree .= '<li>' . $this->returnSee($tree[$cur]['parent']);
+ if ($tree[$cur]['parent']->package != $package) $my_tree .= ' <b>(Different package)</b><ul>';
+ }
+ }
+ do
+ {
+// fancy_debug($cur,$lastcur,$kids);
+ if (count($tree[$cur]['children']))
+ {
+// debug("$cur has children");
+ if (!isset($kids[$cur]))
+ {
+// debug("set $cur kids");
+ $kids[$cur] = 1;
+ $my_tree .= '<li>'.$this->returnSee($tree[$cur]['link']);
+ $my_tree .= '<ul>'."\n";
+ }
+ array_push($lastcur,$cur);
+ list(,$cur) = each($tree[$cur]['children']);
+// var_dump('listed',$cur);
+ if ($cur)
+ {
+ $cur = $cur['package'] . '#' . $cur['class'];
+// debug("set cur to child $cur");
+// $my_tree .= '<li>'.$this->returnSee($tree[$cur]['link']);
+ continue;
+ } else
+ {
+// debug("end of children for $cur");
+ $cur = array_pop($lastcur);
+ $cur = array_pop($lastcur);
+ $my_tree .= '</ul></li>'."\n";
+ if ($dopar && ($cur == '#root' || !$cur)) $my_tree .= '</ul></li>';
+ }
+ } else
+ {
+// debug("$cur has no children");
+ $my_tree .= '<li>'.$this->returnSee($tree[$cur]['link'])."</li>";
+ if ($dopar && $cur == '#root') $my_tree .= '</ul></li>';
+ $cur = array_pop($lastcur);
+ }
+ } while ($cur);
+ return $my_tree;
+ }
+ /**
+ * Generate indexing information for given element
+ *
+ * @param parserElement descendant of parserElement
+ * @see generateElementIndex()
+ * @return array
+ */
+ function getIndexInformation($elt)
+ {
+ $Result['type'] = $elt->type;
+ $Result['file_name'] = $elt->file;
+ $Result['path'] = $elt->getPath();
+
+ if (isset($elt->docblock))
+ {
+ $Result['description'] = $elt->docblock->getSDesc($this);
+
+ if ($elt->docblock->hasaccess)
+ $Result['access'] = $elt->docblock->tags['access'][0]->value;
+ else
+ $Result['access'] = 'public';
+
+ $Result['abstract'] = isset ($elt->docblock->tags['abstract'][0]);
+ }
+ else
+ $Result['description'] = '';
+
+ $aa = $Result['description'];
+ if (!empty($aa)) $aa = "<br>&nbsp;&nbsp;&nbsp;&nbsp;$aa";
+
+ switch($elt->type)
+ {
+ case 'class':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Class';
+ $Result['link'] = $this->getClassLink($elt->getName(),
+ $elt->docblock->package,
+ $elt->getPath(),
+ $elt->getName());
+ $Result['listing'] = 'in file '.$elt->file.', class '.$Result['link']."$aa";
+ break;
+ case 'define':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Constant';
+ $Result['link'] = $this->getDefineLink($elt->getName(),
+ $elt->docblock->package,
+ $elt->getPath(),
+ $elt->getName());
+ $Result['listing'] = 'in file '.$elt->file.', constant '.$Result['link']."$aa";
+ break;
+ case 'global':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Global';
+ $Result['link'] = $this->getGlobalLink($elt->getName(),
+ $elt->docblock->package,
+ $elt->getPath(),
+ $elt->getName());
+ $Result['listing'] = 'in file '.$elt->file.', global variable '.$Result['link']."$aa";
+ break;
+ case 'function':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Function';
+ $Result['link'] = $this->getFunctionLink($elt->getName(),
+ $elt->docblock->package,
+ $elt->getPath(),
+ $elt->getName().'()');
+ $Result['listing'] = 'in file '.$elt->file.', function '.$Result['link']."$aa";
+ break;
+ case 'method':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Method';
+ $Result['link'] = $this->getMethodLink($elt->getName(),
+ $elt->class,
+ $elt->docblock->package,
+ $elt->getPath(),
+ $elt->class.'::'.$elt->getName().'()'
+ );
+ if ($elt->isConstructor) $Result['constructor'] = 1;
+ $Result['listing'] = 'in file '.$elt->file.', method '.$Result['link']."$aa";
+ break;
+ case 'var':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Variable';
+ $Result['link'] = $this->getVarLink($elt->getName(),
+ $elt->class,
+ $elt->docblock->package,
+ $elt->getPath(),
+ $elt->class.'::'.$elt->getName());
+ $Result['listing'] = 'in file '.$elt->file.', variable '.$Result['link']."$aa";
+ break;
+ case 'const':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Variable';
+ $Result['link'] = $this->getConstLink($elt->getName(),
+ $elt->class,
+ $elt->docblock->package,
+ $elt->getPath(),
+ $elt->class.'::'.$elt->getName());
+ $Result['listing'] = 'in file '.$elt->file.', class constant '.$Result['link']."$aa";
+ break;
+ case 'page':
+ $Result['name'] = $elt->getFile();
+ $Result['title'] = 'Page';
+ $Result['link'] = $this->getPageLink($elt->getFile(),
+ $elt->package,
+ $elt->getPath(),
+ $elt->getFile());
+ $Result['listing'] = 'procedural page '.$Result['link'];
+ break;
+ case 'include':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Include';
+ $Result['link'] = $elt->getValue();
+ $Result['listing'] = 'include '.$Result['name'];
+ break;
+ }
+
+ return $Result;
+ }
+ /**
+ * Generate alphabetical index of all elements
+ *
+ * @see $elements, walk()
+ */
+ function generateElementIndex()
+ {
+ $elementindex = array();
+ $letters = array();
+ $used = array();
+ foreach($this->elements as $letter => $nutoh)
+ {
+ foreach($this->elements[$letter] as $i => $yuh)
+ {
+ if ($this->elements[$letter][$i]->type != 'include')
+ {
+ if (!isset($used[$letter]))
+ {
+ $letters[]['letter'] = $letter;
+ $elindex['letter'] = $letter;
+ $used[$letter] = 1;
+ }
+
+ $elindex['index'][] = $this->getIndexInformation($this->elements[$letter][$i]);
+ }
+ }
+ if (isset($elindex['index']))
+ {
+ $elementindex[] = $elindex;
+ } else
+ {
+ unset($letters[count($letters) - 1]);
+ }
+ $elindex = array();
+ }
+ return array($elementindex,$letters);
+ }
+
+ function setTemplateDir($dir)
+ {
+ Converter::setTemplateDir($dir);
+ $this->smarty_dir = $this->templateDir;
+ }
+
+ function copyMediaRecursively($media,$targetdir,$subdir = '')
+ {
+ if (!is_array($media)) {
+ return;
+ }
+ foreach($media as $dir => $files)
+ {
+ if ($dir === '/')
+ {
+ $this->copyMediaRecursively($files,$targetdir);
+ } else
+ {
+ if (!is_numeric($dir))
+ {
+ // create the subdir
+ phpDocumentor_out("creating $targetdir/$dir\n");
+ Converter::setTargetDir($targetdir . PATH_DELIMITER . $dir);
+ if (!empty($subdir)) $subdir .= PATH_DELIMITER;
+ $this->copyMediaRecursively($files,"$targetdir/$dir",$subdir . $dir);
+ } else
+ {
+ // copy the file
+ phpDocumentor_out("copying $targetdir/".$files['file']."\n");
+ $this->copyFile($files['file'],$subdir);
+ }
+ }
+ }
+ }
+
+ /**
+ * calls the converter setTargetDir, and then copies any template images and the stylesheet if they haven't been copied
+ * @see Converter::setTargetDir()
+ */
+ function setTargetDir($dir)
+ {
+ Converter::setTargetDir($dir);
+ if ($this->wrote) return;
+ $this->wrote = true;
+ $template_images = array();
+ $stylesheets = array();
+ $tdir = $dir;
+ $dir = $this->templateDir;
+ $this->templateDir = $this->templateDir.'templates/';
+ $info = new Io;
+ $this->copyMediaRecursively($info->getDirTree($this->templateDir.'media',$this->templateDir),$tdir);
+ }
+
+ /**
+ * Generate alphabetical index of all elements by package and subpackage
+ *
+ * @param string $package name of a package
+ * @see $pkg_elements, walk(), generatePkgElementIndexes()
+ */
+ function generatePkgElementIndex($package)
+ {
+// var_dump($this->pkg_elements[$package]);
+ $elementindex = array();
+ $letters = array();
+ $letterind = array();
+ $used = array();
+ $subp = '';
+ foreach($this->pkg_elements[$package] as $subpackage => $els)
+ {
+ if (empty($els)) continue;
+ if (!empty($subpackage)) $subp = " (<b>subpackage:</b> $subpackage)"; else $subp = '';
+ foreach($els as $letter => $yuh)
+ {
+ foreach($els[$letter] as $i => $yuh)
+ {
+ if ($els[$letter][$i]->type != 'include')
+ {
+ if (!isset($used[$letter]))
+ {
+ $letters[]['letter'] = $letter;
+ $letterind[$letter] = count($letters) - 1;
+ $used[$letter] = 1;
+ }
+ $elindex[$letter]['letter'] = $letter;
+
+ $elindex[$letter]['index'][] = $this->getIndexInformation($els[$letter][$i]);
+ }
+ }
+ }
+ }
+ ksort($elindex);
+ usort($letters,'CHMdefault_lettersort');
+ if (isset($elindex))
+ {
+ while(list($letter,$tempel) = each($elindex))
+ {
+ if (!isset($tempel))
+ {
+ unset($letters[$letterind[$tempel['letter']]]);
+ } else
+ $elementindex[] = $tempel;
+ }
+ } else $letters = array();
+ return array($elementindex,$letters);
+ }
+
+ /**
+ *
+ * @see generatePkgElementIndex()
+ */
+ function generatePkgElementIndexes()
+ {
+ $packages = array();
+ $package_names = array();
+ $pkg = array();
+ $letters = array();
+ foreach($this->pkg_elements as $package => $trash)
+ {
+ $pkgs['package'] = $package;
+ $pkg['package'] = $package;
+ list($pkg['pindex'],$letters[$package]) = $this->generatePkgElementIndex($package);
+ if (count($pkg['pindex']))
+ {
+ $packages[] = $pkg;
+ $package_names[] = $pkgs;
+ }
+ unset($pkgs);
+ unset($pkg);
+ }
+ foreach($packages as $i => $package)
+ {
+ $pnames = array();
+ for($j=0;$j<count($package_names);$j++)
+ {
+ if ($package_names[$j]['package'] != $package['package']) $pnames[] = $package_names[$j];
+ }
+ $packages[$i]['packageindexes'] = $pnames;
+ }
+ return array($packages,$package_names,$letters);
+ }
+
+ /**
+ * @param string name of class
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the class's documentation
+ * @see parent::getClassLink()
+ */
+ function getClassLink($expr,$package, $file = false,$text = false, $with_a = true)
+ {
+ $a = Converter::getClassLink($expr,$package,$file);
+ if (!$a) return false;
+ return $this->returnSee($a, $text, $with_a);
+ }
+
+ /**
+ * @param string name of function
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the function's documentation
+ * @see parent::getFunctionLink()
+ */
+ function getFunctionLink($expr,$package, $file = false,$text = false)
+ {
+ $a = Converter::getFunctionLink($expr,$package,$file);
+ if (!$a) return false;
+ return $this->returnSee($a, $text);
+ }
+
+ /**
+ * @param string name of define
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the define's documentation
+ * @see parent::getDefineLink()
+ */
+ function getDefineLink($expr,$package, $file = false,$text = false)
+ {
+ $a = Converter::getDefineLink($expr,$package,$file);
+ if (!$a) return false;
+ return $this->returnSee($a, $text);
+ }
+
+ /**
+ * @param string name of global variable
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the global variable's documentation
+ * @see parent::getGlobalLink()
+ */
+ function getGlobalLink($expr,$package, $file = false,$text = false)
+ {
+ $a = Converter::getGlobalLink($expr,$package,$file);
+ if (!$a) return false;
+ return $this->returnSee($a, $text);
+ }
+
+ /**
+ * @param string name of procedural page
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the procedural page's documentation
+ * @see parent::getPageLink()
+ */
+ function getPageLink($expr,$package, $path = false,$text = false)
+ {
+ $a = Converter::getPageLink($expr,$package,$path);
+ if (!$a) return false;
+ return $this->returnSee($a, $text);
+ }
+
+ /**
+ * @param string name of method
+ * @param string class containing method
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the method's documentation
+ * @see parent::getMethodLink()
+ */
+ function getMethodLink($expr,$class,$package, $file = false,$text = false)
+ {
+ $a = Converter::getMethodLink($expr,$class,$package,$file);
+ if (!$a) return false;
+ return $this->returnSee($a, $text);
+ }
+
+ /**
+ * @param string name of var
+ * @param string class containing var
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the var's documentation
+ * @see parent::getVarLink()
+ */
+ function getVarLink($expr,$class,$package, $file = false,$text = false)
+ {
+ $a = Converter::getVarLink($expr,$class,$package,$file);
+ if (!$a) return false;
+ return $this->returnSee($a, $text);
+ }
+
+ /**
+ * @param string name of class constant
+ * @param string class containing class constant
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the var's documentation
+ * @see parent::getVarLink()
+ */
+ function getConstLink($expr,$class,$package, $file = false,$text = false)
+ {
+ $a = Converter::getConstLink($expr,$class,$package,$file);
+ if (!$a) return false;
+ return $this->returnSee($a, $text);
+ }
+
+ /**
+ * does a nat case sort on the specified second level value of the array
+ *
+ * @param mixed $a
+ * @param mixed $b
+ * @return int
+ */
+ function rcNatCmp ($a, $b)
+ {
+ $aa = strtoupper($a[$this->rcnatcmpkey]);
+ $bb = strtoupper($b[$this->rcnatcmpkey]);
+
+ return strnatcasecmp($aa, $bb);
+ }
+
+ /**
+ * does a nat case sort on the specified second level value of the array.
+ * this one puts constructors first
+ *
+ * @param mixed $a
+ * @param mixed $b
+ * @return int
+ */
+ function rcNatCmp1 ($a, $b)
+ {
+ $aa = strtoupper($a[$this->rcnatcmpkey]);
+ $bb = strtoupper($b[$this->rcnatcmpkey]);
+
+ if (strpos($aa,'CONSTRUCTOR') === 0)
+ {
+ return -1;
+ }
+ if (strpos($bb,'CONSTRUCTOR') === 0)
+ {
+ return 1;
+ }
+ if (strpos($aa,strtoupper($this->class)) === 0)
+ {
+ return -1;
+ }
+ if (strpos($bb,strtoupper($this->class)) === 0)
+ {
+ return -1;
+ }
+ return strnatcasecmp($aa, $bb);
+ }
+
+ /**
+ * Write a file to disk, and add it to the {@link $hhp_files} list of files
+ * to include in the generated CHM
+ *
+ * {@source}
+ */
+ function writefile($file,$contents)
+ {
+ $this->addHHP($this->targetDir . PATH_DELIMITER . $file);
+ Converter::writefile($file,$contents);
+ }
+
+ /**
+ * @uses $hhp_files creates the array by adding parameter $file
+ */
+ function addHHP($file)
+ {
+ $file = str_replace($this->base_dir . PATH_DELIMITER, '', $file);
+ $file = str_replace('\\',PATH_DELIMITER,$file);
+ $file = str_replace('//',PATH_DELIMITER,$file);
+ $file = str_replace(PATH_DELIMITER,'\\',$file);
+ $this->hhp_files[]['name'] = $file;
+ }
+
+ function generateTOC()
+ {
+ $comppack = '';
+ $templ = &$this->newSmarty();
+ foreach($this->TOC as $package => $TOC1)
+ {
+ $comp_subs = '';
+ $comp_subs1 = false;
+ foreach($TOC1 as $subpackage => $types)
+ {
+ $comp_types = '';
+ foreach($types as $type => $files)
+ {
+ $comp = '';
+ $templ1 = &$this->newSmarty();
+ $templ1->assign('entry', array());
+ foreach($files as $file)
+ {
+ // use book icon for classes
+ if ($type == 'Classes') {
+ $templ1->append('entry', array('paramname' => $file[0],'outputfile' => $file[1],'isclass' => 1));
+ } else {
+ $templ1->append('entry', array('paramname' => $file[0],'outputfile' => $file[1]));
+ }
+ }
+ $templ = &$this->newSmarty();
+ $templ->assign('tocsubentries',$templ1->fetch('tocentry.tpl'));
+ $templ->assign('entry', array(array('paramname' => $type)));
+ $comp_types .= $templ->fetch('tocentry.tpl');
+ }
+ if (!empty($subpackage))
+ {
+ $templ = &$this->newSmarty();
+ $templ->assign('tocsubentries',$comp_types);
+ $templ->assign('entry', array(array('paramname' => $subpackage)));
+ $comp_subs .= $templ->fetch('tocentry.tpl');
+ } else
+ {
+ $comp_subs1 = $comp_types;
+ }
+ }
+ if ($comp_subs1)
+ $templ->assign('tocsubentries',$comp_subs1);
+ if (!empty($comp_subs))
+ $templ->assign('entry', array(array('paramname' => $package, 'tocsubentries' => $comp_subs)));
+ else
+ $templ->assign('entry', array(array('paramname' => $package)));
+ $comppack .= $templ->fetch('tocentry.tpl');
+ }
+ return $comppack;
+ }
+
+ function addSourceTOC($name, $file, $package, $subpackage, $source = false)
+ {
+ $file = str_replace($this->base_dir . PATH_DELIMITER, '', $this->targetDir)
+ . PATH_DELIMITER . $file . '.html';
+ $file = str_replace('\\',PATH_DELIMITER,$file);
+ $file = str_replace('//',PATH_DELIMITER,$file);
+ $file = str_replace(PATH_DELIMITER,'\\',$file);
+ $sub = $source ? 'Source Code' : 'Examples';
+ $this->TOC[$package][$subpackage][$sub][] = array($name, $file);
+ }
+
+ function addTOC($name,$file,$package,$subpackage,$class = false,$tutorial = false)
+ {
+ $file = str_replace($this->base_dir . PATH_DELIMITER, '', $this->targetDir)
+ . PATH_DELIMITER . $file . '.html';
+ $file = str_replace('\\',PATH_DELIMITER,$file);
+ $file = str_replace('//',PATH_DELIMITER,$file);
+ $file = str_replace(PATH_DELIMITER,'\\',$file);
+ $file = str_replace($this->base_dir . '\\', '', $file);
+ $sub = $class ? 'Classes' : 'Files';
+ if ($tutorial) $sub = 'Manual';
+ $this->TOC[$package][$subpackage][$sub][] = array($name,$file);
+ }
+
+ /**
+ * Add an item to the index.hhk file
+ * @param string $name index entry name
+ * @param string $file filename containing index
+ * @param string $bookmark html anchor of location in file, if any
+ * @param string $group group this entry with a string
+ * @uses $KLinks tracks the index
+ * @author Andrew Eddie <eddieajau@users.sourceforge.net>
+ */
+ function addKLink($name, $file, $bookmark='', $group='')
+ {
+ $file = $file . '.html';
+ $file = str_replace('\\',PATH_DELIMITER,$file);
+ $file = str_replace('//',PATH_DELIMITER,$file);
+ $file = str_replace(PATH_DELIMITER,'\\',$file);
+// debug("added $name, $file, $bookmark, $group ");
+ $link = $file;
+ $link .= $bookmark ? "#$bookmark" :'';
+ if ($group) {
+ $this->KLinks[$group]['grouplink'] = $file;
+ $this->KLinks[$group][] = array($name,$link);
+ }
+ $this->KLinks[] = array($name,$link);
+ }
+
+ /**
+ * Get the table of contents for index.hhk
+ * @return string contents of tocentry.tpl generated from $KLinks
+ * @author Andrew Eddie <eddieajau@users.sourceforge.net>
+ */
+ function generateKLinks()
+ {
+ $templ = &$this->newSmarty();
+ $templ->assign('entry', array());
+ foreach($this->KLinks as $group=>$link)
+ {
+ if (isset($link['grouplink'])) {
+ $templg = &$this->newSmarty();
+ $templg->assign('entry', array());
+ foreach($link as $k=>$sublink)
+ {
+ if ($k != 'grouplink') {
+ $templg->append('entry', array('paramname' => $sublink[0],'outputfile' => $sublink[1]));
+ }
+ }
+ $templ->append('entry', array('paramname' => $group, 'outputfile' => $link['grouplink'], 'tocsubentries' => $templg->fetch('tocentry.tpl') ));
+ } else {
+ $templ->append('entry', array('paramname' => $link[0],'outputfile' => $link[1]));
+ }
+ }
+ return $templ->fetch('tocentry.tpl');
+ }
+
+ /**
+ * Create the phpdoc.hhp, contents.hhc files needed by MS HTML Help Compiler
+ * to create a CHM file
+ *
+ * The output function generates the table of contents (contents.hhc)
+ * and file list (phpdoc.hhp) files used to create a .CHM by the
+ * free MS HTML Help compiler.
+ * {@internal
+ * Using {@link $hhp_files}, a list of all separate .html files
+ * is created in CHM format, and written to phpdoc.hhp. This list was
+ * generated by {@link writefile}.
+ *
+ * Next, a call to the table of contents:
+ *
+ * {@source 12 2}
+ *
+ * finishes things off}}
+ * @todo use to directly call html help compiler hhc.exe
+ * @link http://www.microsoft.com/downloads/release.asp?releaseid=33071
+ * @uses generateTOC() assigns to the toc template variable
+ */
+ function Output()
+ {
+ $templ = &$this->newSmarty();
+ $templ->assign('files',$this->hhp_files);
+ $this->setTargetDir($this->base_dir);
+ Converter::writefile('phpdoc.hhp',$templ->fetch('hhp.tpl'));
+ $templ = &$this->newSmarty();
+ $templ->assign('toc',$this->generateTOC());
+ Converter::writefile('contents.hhc',$templ->fetch('contents.hhc.tpl'));
+ $templ->assign('klinks',$this->generateKLinks());
+ Converter::writefile('index.hhk',$templ->fetch('index.hhk.tpl'));
+ phpDocumentor_out("NOTE: to create the documentation.chm file, you must now run Microsoft Help Workshop on phpdoc.hhp\n");
+ phpDocumentor_out("To get the free Microsoft Help Workshop, browse to: http://go.microsoft.com/fwlink/?LinkId=14188\n");
+ flush();
+ }
+}
+
+/**
+ * @access private
+ * @global string name of the package to set as the first package
+ */
+function CHMdefault_pindexcmp($a, $b)
+{
+ global $phpDocumentor_DefaultPackageName;
+ if ($a['title'] == $phpDocumentor_DefaultPackageName) return -1;
+ if ($b['title'] == $phpDocumentor_DefaultPackageName) return 1;
+ return strnatcasecmp($a['title'],$b['title']);
+}
+
+/** @access private */
+function CHMdefault_lettersort($a, $b)
+{
+ return strnatcasecmp($a['letter'],$b['letter']);
+}
+
+/** @access private */
+function CHMdefault_outputfilter($src, &$smarty)
+{
+ return str_replace('{$subdir}',$smarty->_tpl_vars['subdir'],$src);
+}
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/options.ini b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/options.ini
new file mode 100644
index 00000000..56474470
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/options.ini
@@ -0,0 +1,507 @@
+preservedocbooktags = false
+
+;; used to highlight the {@source} inline tag, @filesource tag, and @example tag
+[highlightSourceTokens]
+;; format:
+;; T_CONSTANTNAME = open
+;; /T_CONSTANTNAME = close
+T_ABSTRACT = <font color="blue">
+/T_ABSTRACT = </font>
+T_CLONE = <font color="blue">
+/T_CLONE = </font>
+T_HALT_COMPILER = <font color="red">
+/T_HALT_COMPILER = </font>
+T_PUBLIC = <font color="blue">
+/T_PUBLIC = </font>
+T_PRIVATE = <font color="blue">
+/T_PRIVATE = </font>
+T_PROTECTED = <font color="blue">
+/T_PROTECTED = </font>
+T_FINAL = <font color="blue">
+/T_FINAL = </font>
+T_IMPLEMENTS = <font color="blue">
+/T_IMPLEMENTS = </font>
+T_CLASS = <font color="blue">
+/T_CLASS = </font>
+T_INTERFACE = <font color="blue">
+/T_INTERFACE = </font>
+T_INCLUDE = <font color="blue">
+/T_INCLUDE = </font>
+T_INCLUDE_ONCE = <font color="blue">
+/T_INCLUDE_ONCE = </font>
+T_REQUIRE_ONCE = <font color="blue">
+/T_REQUIRE_ONCE = </font>
+T_FUNCTION = <font color="blue">
+/T_FUNCTION = </font>
+T_VARIABLE = <strong>
+/T_VARIABLE = </strong>
+T_CONSTANT_ENCAPSED_STRING = <font color="#66cccc">
+/T_CONSTANT_ENCAPSED_STRING = </font>
+T_COMMENT = <font color="green">
+/T_COMMENT = </font>
+T_OBJECT_OPERATOR = <strong>
+/T_OBJECT_OPERATOR = </strong>
+T_RETURN = <font color="blue">
+/T_RETURN = </font>
+T_STATIC = <font color="blue">
+/T_STATIC = </font>
+T_SWITCH = <font color="blue">
+/T_SWITCH = </font>
+T_IF = <font color="blue">
+/T_IF = </font>
+T_FOREACH = <font color="blue">
+/T_FOREACH = </font>
+T_FOR = <font color="blue">
+/T_FOR = </font>
+T_VAR = <font color="blue">
+/T_VAR = </font>
+T_EXTENDS = <font color="blue">
+/T_EXTENDS = </font>
+T_RETURN = <font color="blue">
+/T_RETURN = </font>
+T_GLOBAL = <font color="blue">
+/T_GLOBAL = </font>
+T_DOUBLE_COLON = <strong>
+/T_DOUBLE_COLON = </strong>
+T_OBJECT_OPERATOR = <strong>
+/T_OBJECT_OPERATOR = </strong>
+T_OPEN_TAG = <strong>
+/T_OPEN_TAG = </strong>
+T_CLOSE_TAG = <strong>
+/T_CLOSE_TAG = </strong>
+
+[highlightSource]
+;; this is for highlighting things that aren't tokens like "&"
+;; format:
+;; word = open
+;; /word = close
+@ = <strong>
+/@ = </strong>
+& = <strong>
+/& = </strong>
+[ = <strong>
+/[ = </strong>
+] = <strong>
+/] = </strong>
+! = <strong>
+/! = </strong>
+";" = <strong>
+/; = </strong>
+( = <strong>
+/( = </strong>
+) = <strong>
+/) = </strong>
+, = <strong>
+/, = </strong>
+{ = <strong>
+/{ = </strong>
+} = <strong>
+/} = </strong>
+""" = <font color="#66cccc">
+/" = </font>
+
+[highlightDocBlockSourceTokens]
+;; this is for docblock tokens, using by phpDocumentor_HighlightParser
+;; tagphptype is for "string" in @param string description, for example
+docblock = <font color="#009999">
+/docblock = </font>
+tagphptype = <em>
+/tagphptype = </em>
+tagvarname = <strong>
+/tagvarname = </strong>
+coretag = <strong><font color = "#0099FF">
+/coretag = </font></strong>
+tag = <strong><font color="#009999">
+/tag = </font></strong>
+inlinetag = <em><font color="#0099FF">
+/inlinetag = </font></em>
+internal = <em><font color = "#6699cc">
+/internal = </font></em>
+closetemplate = <strong><font color="blue">
+/closetemplate = </font></strong>
+docblocktemplate = <font color="blue">
+/docblocktemplate = </font color="blue">
+
+[highlightTutorialSourceTokens]
+;; this is for XML DocBook-based tutorials, highlighted by phpDocumentor_TutorialHighlightParser
+;; <tag>
+opentag = <span class="tute-tag">
+/opentag = </span>
+;; </tag>
+closetag = <span class="tute-tag">
+/closetag = </span>
+;; <tag attribute="value">
+attribute = <span class="tute-attribute-name">
+/attribute = </span>
+;; <tag attribute="value">
+attributevalue = <span class="tute-attribute-value">
+/attributevalue = </span>
+;; &entity;
+entity = <span class="tute-entity">
+/entity = </span>
+;; <!-- comment -->
+comment = <span class="tute-comment">
+/comment = </span>
+;; {@inline tag}
+itag = <span class="tute-inline-tag">
+/itag = </span>
+
+;; used for translation of html in DocBlocks
+[desctranslate]
+ul = <ul>
+/ul = </ul>
+ol = <ol>
+/ol = </ol>
+li = <li>
+/li = </li>
+code = <code><pre>
+/code = </pre></code>
+var = <var>
+/var = </var>
+samp = <samp>
+/samp = </samp>
+kbd = <kbd>
+/kbd = </kbd>
+pre = <pre>
+/pre = </pre>
+p = <p>
+/p = </p>
+b = <strong>
+/b = </strong>
+i = <em>
+/i = </em>
+br = <br />
+
+[ppage]
+;; this is the DocBook package page translation section. All DocBook tags
+;; that have a corresponding html tag must be listed here
+;;
+;; examples:
+;; 1)
+;; tagname = newtagname
+;;
+;; This is the simplest case, where all attributes will be added into the
+;; starting tag and the ending tag will be html/xml style </tranlatedtagname>
+;; <tagname></tagname> becomes <newtagname></newtagname> and
+;; <tagname attr="value"></tagname> becomes
+;; <newtagname attr="value"></newtagname>
+;;
+;; 2)
+;; tagname = newtagname
+;; tagname->attr = newattrname
+;;
+;; in this case, everything will be like the first case, except tags like:
+;; <tagname attr="value"></tagname> will become
+;; <newtagname newattrname="value"></newtagname>
+;;
+;; 3)
+;; tagname = newtagname
+;; tagname->attr = newattrname
+;; tagname->attr+value = newvalue
+;;
+;; in this case, the value is also translated to another. This can be useful
+;; for instances such as focus="middle" changing to align="center" or something
+;; of that nature.
+;; <tagname attr="value"></tagname> will become
+;; <newtagname newattrname="newvalue"></newtagname>
+;;
+;; 4)
+;; tagname = newtagname
+;; tagname->attr1 = newattrname
+;; tagname->attr2 = newattrname
+;; tagname->attr1+value|attr2+value = newvalue
+;;
+;; in this case, two attributes combine to make one new attribute, and the combined
+;; value is translated into a new value
+;; <tagname attr1="value1" attr2="value2"></tagname> will become
+;; <newtagname newattrname="newvalue"></newtagname>
+;;
+;; 5)
+;; tagname = newtagname
+;; tagname!attr = dummy
+;;
+;; here, the attribute will be ignored. dummy is not used and may be any value
+;; <tagname attr="value"></tagname> will become
+;; <newtagname></newtagname>
+;;
+;; 6)
+;; tagname = newtagname
+;; tagname! = dummy
+;;
+;; here, all attributes will be ignored. dummy is not used and may be any value
+;; <tagname attr1="value" attr2="foo"></tagname> will become
+;; <newtagname></newtagname>
+;;
+;; 7)
+;; tagname = newtagname
+;; tagname/ = 1
+;;
+;; here, the tag will be translated as a single tag with no closing tag, and all
+;; attributes
+;; <tagname attr="val">{text text}</tagname> will become
+;; <newtagname attr="val" />
+;;
+;; 8)
+;; tagname = <starttaginfo />
+;; /tagname = closetagtext
+;;
+;; in this case, the text <starttaginfo> will be inserted exactly as entered for
+;; <tagname> and closetagtext for </tagname>
+;; <tagname attr="val"></tagname> will become
+;; <starttaginfo />closetagtext
+;;
+;; 9)
+;; $attr$my_attribute = newattrname
+;;
+;; tagname = newtagname
+;;
+;; in this case, all occurences of my_attribute in any tag will be changed to
+;; newattrname. This is useful for changing things like role="php" to
+;; class="php," for example. Note that the text "$attr$" MUST be on the line
+;; start for phpDocumentor to recognize it.
+;;
+;; 10)
+;; &entity; = translation text
+;; &quot; = &quot;
+;; &quot; = """
+;; &lt; = <
+;;
+;; Use this to control translation of entities to their appropriate values
+
+&nbsp; = &nbsp;
+&quot; = &quot;
+&rdquo; = &rdquo;
+&ldquo; = &ldquo;
+&amp; = &amp;
+&lt; = &lt;
+&gt; = &gt;
+&copy; = &copy;
+
+$attr$role = class
+
+abbrev = abbr
+
+blockquote = blockquote
+
+arg = span
+arg->choice = class
+
+author = <font size="-1"><strong>by <em>
+/author = </em></strong></font>
+author! = 0
+
+authorblurb = blockquote
+
+authorgroup = <strong>Authors:</strong><br />
+/authorgroup =
+authorgroup! = 0
+
+caution = <table border="1"><th align="center">Caution</th><tr><td>
+/caution = </td></tr></table>
+caution! = 0
+
+command = <b class="cmd">
+/command = </b>
+
+cmdsynopsis = <div id="cmdsynopsis">
+/cmdsynopsis = </div>
+
+copyright = <em>
+/copyright = </em><br />
+
+emphasis = strong
+
+example = <table class="example" width="100%" border="1"><tr><td>
+/example = </td></tr></table>
+example! = 0
+
+function =
+/function = ()
+
+formalpara = p
+
+graphic = img
+graphic->fileref = src
+graphic/ =
+
+important = u
+
+informalequation = blockquote
+
+informalexample = pre
+
+inlineequation = em
+
+itemizedlist = ul
+
+listitem = li
+
+literal = code
+
+literallayout = pre
+
+option = " "
+/option =
+
+orderedlist = ol
+
+para = p
+
+programlisting = <table border="0" bgcolor="#E0E0E0" cellpadding="5"><tr><td><pre class="php">
+/programlisting = </pre></td></tr></table>
+programlisting! = 0
+
+refentry = div
+
+refnamediv = <div class="refname">
+/refnamediv = </div>
+refnamediv! = 0
+
+refname = h1
+
+refpurpose = <h2 class="refpurpose"><em>
+/refpurpose = </em></h2>
+
+refsynopsisdiv = <div class="refsynopsis">
+/refsynopsisdiv = </div>
+refsynopsisdiv! = 0
+
+refsect1 = span
+
+refsect2 =
+/refsect2 = <hr />
+
+refsect3 =
+/refsect3 = <br />
+
+releaseinfo = (
+/releaseinfo = )<br />
+
+simpara =
+/simpara = <br />
+simpara! = 0
+
+subscript = sub
+
+superscript = super
+
+table = table
+
+table->colsep = rules
+table->rowsep = rules
+table->colsep+1|rowsep+1 = all
+table->colsep+1|rowsep+0 = cols
+table->colsep+0|rowsep+1 = rows
+
+table->frame = frame
+table->frame+all = border
+table->frame+none = void
+table->frame+sides = vsides
+table->frame+top = above
+table->frame+topbot = hsides
+
+thead = thead
+
+tfoot = tfoot
+
+tbody = tbody
+
+colspec = col
+
+tgroup = colgroup
+tgroup/ = 1
+tgroup->cols = span
+
+row = tr
+
+entry = td
+entry->morerows = colspan
+entry->morerows+1 = 2
+entry->morerows+2 = 3
+entry->morerows+3 = 4
+entry->morerows+4 = 5
+entry->morerows+5 = 6
+entry->morerows+6 = 7
+entry->morerows+7 = 8
+entry->morerows+8 = 9
+entry->morerows+9 = 10
+entry->morerows+10 = 11
+;; add more if you need more colspans
+
+warning = <table border="1"><tr><td>
+/warning = </td></tr></table>
+warning! = 0
+
+;; now begins the attributes that should be tags in cdata
+[$attr$id]
+open = a
+;close = /a
+cdata! = true
+quotevalues = true
+separator = "="
+;separateall = true
+$id = name
+
+;; now begins the sections that deal with <title>
+[refsynopsisdiv_title]
+;tag_attr = true
+;attr_name = title
+cdata_start = true
+;cdata_end = true
+open = <h1 class="title" align="center">
+close = </h1>
+
+[refsect1_title]
+;tag_attr = true
+;attr_name = title
+cdata_start = true
+;cdata_end = true
+open = <h2 class="title" align="center">
+close = </h1>
+
+[refsect2_title]
+;tag_attr = true
+;attr_name = title
+cdata_start = true
+;cdata_end = true
+open = <h2 class="title" align="center">
+close = </h2>
+
+[refsect3_title]
+;tag_attr = true
+;attr_name = title
+cdata_start = true
+;cdata_end = true
+open = <h3 class="title" align="center">
+close = </h3>
+
+[para_title]
+;tag_attr = true
+;attr_name = title
+cdata_start = true
+;cdata_end = true
+open = <strong class="title" align="center">
+close = </strong>
+
+[formalpara_title]
+;tag_attr = true
+;attr_name = title
+cdata_start = true
+;cdata_end = true
+open = <strong class="title" align="center">
+close = </strong>
+
+[example_title]
+;tag_attr = true
+;attr_name = title
+;cdata_start = true
+cdata_end = true
+open = </td></tr><tr><td><strong>
+close = </strong>
+
+[table_title]
+;tag_attr = true
+;attr_name = true
+cdata_start = true
+open = <caption>
+close = </caption>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/basicindex.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/basicindex.tpl
new file mode 100644
index 00000000..a040830b
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/basicindex.tpl
@@ -0,0 +1,21 @@
+{section name=letter loop=$letters}
+ <a href="{$indexname}.html#{$letters[letter].letter}">{$letters[letter].letter}</a>
+{/section}
+<table>
+{section name=index loop=$index}
+<tr><td colspan = "2"><a name="{$index[index].letter}">&nbsp; </a>
+<a href="#top">top</a><br>
+<TABLE CELLPADDING='3' CELLSPACING='0' WIDTH='100%' CLASS="border">
+ <TR CLASS='TableHeadingColor'>
+ <TD>
+ <FONT SIZE='+2'><B>{$index[index].letter}</B></FONT>
+ </TD>
+ </TR>
+</TABLE>
+</td></tr>
+ {section name=contents loop=$index[index].index}
+ <tr><td><b>{$index[index].index[contents].name}</b></td><td width="100%" align="left" valign="top">{$index[index].index[contents].listing}</td></tr>
+ {/section}
+{/section}
+</table>
+
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/blank.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/blank.tpl
new file mode 100644
index 00000000..1fbaca2f
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/blank.tpl
@@ -0,0 +1,13 @@
+<html>
+<head>
+ <title>{$maintitle}</title>
+ <link rel="stylesheet" href="{$subdir}media/stylesheet.css" />
+ <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
+</head>
+<body>
+<div align="center"><h1>{$maintitle}</h1></div>
+<b>Welcome to {$package}!</b><br />
+<br />
+This documentation was generated by <a href="{$phpdocwebsite}">phpDocumentor v{$phpdocversion}</a><br />
+</body>
+</html> \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/class.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/class.tpl
new file mode 100644
index 00000000..1ed17562
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/class.tpl
@@ -0,0 +1,94 @@
+{include file="header.tpl" eltype="class" hasel=true contents=$classcontents}
+<!-- Start of Class Data -->
+<H3>
+ <SPAN class="type">{if $is_interface}Interface{else}Class{/if}</SPAN> {$class_name}
+ <HR>
+</H3>
+[line <span class="linenumber">{if $class_slink}{$class_slink}{else}{$line_number}{/if}</span>]<br />
+<pre>
+{section name=tree loop=$class_tree.classes}{$class_tree.classes[tree]}{$class_tree.distance[tree]}{/section}
+</pre>
+{if $tutorial}
+<div class="maintutorial">Class Tutorial: {$tutorial}</div>
+{/if}
+{if $children}
+<SPAN class="type">Classes extended from {$class_name}:</SPAN>
+ {section name=kids loop=$children}
+ <dl>
+ <dt>{$children[kids].link}</dt>
+ <dd>{$children[kids].sdesc}</dd>
+ </dl>
+ {/section}</p>
+{/if}
+{if $conflicts.conflict_type}<p class="warning">Conflicts with classes:<br />
+ {section name=me loop=$conflicts.conflicts}
+ {$conflicts.conflicts[me]}<br />
+ {/section}
+<p>
+{/if}
+<SPAN class="type">Location:</SPAN> {$source_location}
+<hr>
+{include file="docblock.tpl" type="class" sdesc=$sdesc desc=$desc}
+<hr>
+{include file="var.tpl" show="summary"}
+<hr>
+{include file="const.tpl" show="summary"}
+<hr>
+<!-- =========== INHERITED CONST SUMMARY =========== -->
+<A NAME='inheritedconst_summary'><!-- --></A>
+<H3>Inherited Class Constant Summary</H3>
+
+{section name=iconsts loop=$iconsts}
+<H4>Inherited From Class {$iconsts[iconsts].parent_class}</H4>
+<UL>
+ {section name=iconsts2 loop=$iconsts[iconsts].iconsts}
+ <!-- =========== Summary =========== -->
+ <LI><CODE>{$iconsts[iconsts].iconsts[iconsts2].link}</CODE> = <CODE class="varsummarydefault">{$iconsts[iconsts].iconsts[iconsts2].value}</CODE>
+ <BR>
+ {$iconsts[iconsts].iconsts[iconsts2].sdesc}
+ {/section}
+ </LI>
+</UL>
+{/section}
+<hr>
+<!-- =========== INHERITED VAR SUMMARY =========== -->
+<A NAME='inheritedvar_summary'><!-- --></A>
+<H3>Inherited Class Variable Summary</H3>
+
+{section name=ivars loop=$ivars}
+<H4>Inherited From Class {$ivars[ivars].parent_class}</H4>
+<UL>
+ {section name=ivars2 loop=$ivars[ivars].ivars}
+ <!-- =========== Summary =========== -->
+ <LI><CODE>{$ivars[ivars].ivars[ivars2].link}</CODE> = <CODE class="varsummarydefault">{$ivars[ivars].ivars[ivars2].default}</CODE>
+ <BR>
+ {$ivars[ivars].ivars[ivars2].sdesc}
+ {/section}
+ </LI>
+</UL>
+{/section}
+
+<hr>
+{include file="method.tpl" show="summary"}
+<!-- =========== INHERITED METHOD SUMMARY =========== -->
+<A NAME='methods_inherited'><!-- --></A>
+<H3>Inherited Method Summary</H3>
+
+{section name=imethods loop=$imethods}
+<H4>Inherited From Class {$imethods[imethods].parent_class}</h4>
+<UL>
+ {section name=im2 loop=$imethods[imethods].imethods}
+ <!-- =========== Summary =========== -->
+ <LI><CODE>{$imethods[imethods].imethods[im2].link}</CODE><br>
+ {$imethods[imethods].imethods[im2].sdesc}
+ {/section}
+</UL>
+{/section}
+<hr>
+{include file="method.tpl"}
+<hr>
+{include file="var.tpl"}
+<hr>
+{include file="const.tpl"}
+<hr>
+{include file="footer.tpl"}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/classleft.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/classleft.tpl
new file mode 100644
index 00000000..15bf6b7e
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/classleft.tpl
@@ -0,0 +1,8 @@
+{foreach key=subpackage item=files from=$classleftindex}
+ {if $subpackage != ""}<b>{$subpackage}</b><br>{/if}
+ {section name=files loop=$files}
+ {if $files[files].link != ''}<a href="{ldelim}$subdir{rdelim}{$files[files].link}">{/if}
+ {$files[files].title}
+ {if $files[files].link != ''}</a>{/if}<br>
+ {/section}
+{/foreach}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/classtrees.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/classtrees.tpl
new file mode 100644
index 00000000..28c648be
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/classtrees.tpl
@@ -0,0 +1,12 @@
+{capture name="title"}Class Trees for Package {$package}{/capture}
+{include file="header.tpl" title=$smarty.capture.title}
+
+<!-- Start of Class Data -->
+<H2>
+ {$smarty.capture.title}
+</H2>
+{section name=classtrees loop=$classtrees}
+<SPAN class="code">Root class {$classtrees[classtrees].class}</SPAN>
+<code class="vardefaultsummary">{$classtrees[classtrees].class_tree}</code>
+{/section}
+{include file="footer.tpl"} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/const.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/const.tpl
new file mode 100644
index 00000000..207491a5
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/const.tpl
@@ -0,0 +1,29 @@
+{if $show=="summary"}
+<!-- =========== CONST SUMMARY =========== -->
+<A NAME='const_summary'><!-- --></A>
+<H3>Class Constant Summary</H3>
+
+<UL>
+ {section name=consts loop=$consts}
+ <!-- =========== Summary =========== -->
+ <LI><CODE><a href="{$consts[consts].id}">{$consts[consts].const_name}</a></CODE> = <CODE class="varsummarydefault">{$consts[consts].const_value|replace:"\n":"<br>\n"|replace:" ":"&nbsp;"|replace:"\t":"&nbsp;&nbsp;&nbsp;"}</CODE>
+ <BR>
+ {$consts[consts].sdesc}
+ {/section}
+</UL>
+{else}
+<!-- ============ VARIABLE DETAIL =========== -->
+
+<A NAME='variable_detail'></A>
+
+<H3>Class Constant Detail</H3>
+
+<UL>
+{section name=consts loop=$consts}
+<A NAME="{$consts[consts].const_dest}"><!-- --></A>
+<LI><SPAN class="code">{$consts[consts].const_name}</SPAN> = <CODE class="varsummarydefault">{$consts[consts].const_value|replace:"\n":"<br>\n"|replace:" ":"&nbsp;"|replace:"\t":"&nbsp;&nbsp;&nbsp;"}</CODE> [line <span class="linenumber">{if $consts[consts].slink}{$consts[consts].slink}{else}{$consts[consts].line_number}{/if}</span>]</LI>
+{include file="docblock.tpl" sdesc=$consts[consts].sdesc desc=$consts[consts].desc tags=$consts[consts].tags}
+<BR>
+{/section}
+</UL>
+{/if} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/contents.hhc.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/contents.hhc.tpl
new file mode 100644
index 00000000..cf7ee7cb
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/contents.hhc.tpl
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<HTML>
+<HEAD>
+<meta name="GENERATOR" content="phpDocumentor version {$phpdocversion}">
+<!-- Sitemap 1.0 -->
+</HEAD><BODY>
+<OBJECT type="text/site properties">
+ <param name="ImageType" value="Folder">
+</OBJECT>
+{$toc}
+</BODY></HTML>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/define.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/define.tpl
new file mode 100644
index 00000000..3917cc70
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/define.tpl
@@ -0,0 +1,33 @@
+{if $summary}
+<!-- =========== CONSTANT SUMMARY =========== -->
+<A NAME='constant_summary'><!-- --></A>
+<H3>Constant Summary</H3>
+
+<UL>
+ {section name=def loop=$defines}
+ <LI><CODE><A HREF="{$defines[def].id}">{$defines[def].define_name}</A></CODE> = <CODE class="varsummarydefault">{$defines[def].define_value}</CODE>
+ <BR>{$defines[def].sdesc}
+ {/section}
+</UL>
+{else}
+<!-- ============ CONSTANT DETAIL =========== -->
+
+<A NAME='constant_detail'></A>
+<H3>Constant Detail</H3>
+
+<UL>
+ {section name=def loop=$defines}
+ <A NAME="{$defines[def].define_link}"><!-- --></A>
+ <LI><SPAN class="code">{$defines[def].define_name}</SPAN> = <CODE class="varsummarydefault">{$defines[def].define_value}</CODE> [line <span class="linenumber">{if $defines[def].slink}{$defines[def].slink}{else}{$defines[def].line_number}{/if}</span>]<br />
+ {if $defines[def].define_conflicts.conflict_type}
+ <p><b>Conflicts with defines:</b>
+ {section name=me loop=$defines[def].define_conflicts.conflicts}
+ {$defines[def].define_conflicts.conflicts[me]}<br />
+ {/section}
+ </p>
+ {/if}
+<BR><BR>
+ {include file="docblock.tpl" sdesc=$defines[def].sdesc desc=$defines[def].desc tags=$defines[def].tags}
+ {/section}
+</UL>
+{/if} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/docblock.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/docblock.tpl
new file mode 100644
index 00000000..0de18b67
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/docblock.tpl
@@ -0,0 +1,31 @@
+<!-- ========== Info from phpDoc block ========= -->
+{if $function}
+ {if $params}
+ <p class="label"><b>Parameters</b></p>
+ {section name=params loop=$params}
+ <p class=dt><i>{$params[params].var}</i></p>
+ <p class=indent>{$params[params].data}</p>
+ {/section}
+ {/if}
+{/if}
+{section name=tags loop=$tags}
+{if $tags[tags].keyword == 'return'}
+ <p class="label"><b>Returns</b></p>
+ <p class=indent>{$tags[tags].data}</p>
+{/if}
+{/section}
+{if $sdesc || $desc}
+<p class="label"><b>Remarks</b></p>
+{/if}
+{if $sdesc}
+<p>{$sdesc}</p>
+{/if}
+{if $desc}
+<p>{$desc}</p>
+{/if}
+{section name=tags loop=$tags}
+{if $tags[tags].keyword != 'return'}
+ <p class="label"><b>{$tags[tags].keyword}</b></p>
+ <p class=indent>{$tags[tags].data}</p>
+{/if}
+{/section} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/elementindex.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/elementindex.tpl
new file mode 100644
index 00000000..8e25db5c
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/elementindex.tpl
@@ -0,0 +1,9 @@
+{include file="header.tpl" noleftindex=true}
+<a name="top"></a>
+<h1>Index of All Elements</h1>
+<b>Indexes by package:</b><br>
+{section name=p loop=$packageindex}
+<a href="elementindex_{$packageindex[p].title}.html">{$packageindex[p].title}</a><br>
+{/section}<br>
+{include file="basicindex.tpl" indexname="elementindex"}
+{include file="footer.tpl"}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/errors.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/errors.tpl
new file mode 100644
index 00000000..1576a822
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/errors.tpl
@@ -0,0 +1,21 @@
+{include file="header.tpl" noleftindex=true}
+{section name=files loop=$files}
+<a href="#{$files[files].file}">{$files[files].file}</a><br>
+{/section}
+{foreach key=file item=issues from=$all}
+<a name="{$file}"></a>
+<h1>{$file}</h1>
+{if count($issues.warnings)}
+<h2>Warnings:</h2><br>
+{section name=warnings loop=$issues.warnings}
+<b>{$issues.warnings[warnings].name}</b> - {$issues.warnings[warnings].listing}<br>
+{/section}
+{/if}
+{if count($issues.errors)}
+<h2>Errors:</h2><br>
+{section name=errors loop=$issues.errors}
+<b>{$issues.errors[errors].name}</b> - {$issues.errors[errors].listing}<br>
+{/section}
+{/if}
+{/foreach}
+{include file="footer.tpl"}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/fileleft.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/fileleft.tpl
new file mode 100644
index 00000000..c85acbe0
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/fileleft.tpl
@@ -0,0 +1,8 @@
+{foreach key=subpackage item=files from=$fileleftindex}
+ {if $subpackage != ""}subpackage <b>{$subpackage}</b><br>{/if}
+ {section name=files loop=$files}
+ {if $files[files].link != ''}<a href="{ldelim}$subdir{rdelim}{$files[files].link}">{/if}
+ {$files[files].title}
+ {if $files[files].link != ''}</a>{/if}<br>
+ {/section}
+{/foreach}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/filesource.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/filesource.tpl
new file mode 100644
index 00000000..a0d7119e
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/filesource.tpl
@@ -0,0 +1,6 @@
+{capture name="tutle"}File Source for {$name}{/capture}
+{include file="header.tpl" title=$smarty.capture.tutle}
+<h1 align="center">Source for file {$name}</h1>
+<p>Documentation is available at {$docs}</p>
+{$source}
+{include file="footer.tpl"} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/footer.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/footer.tpl
new file mode 100644
index 00000000..a015ceea
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/footer.tpl
@@ -0,0 +1,8 @@
+{if !$index}
+ <div id="credit">
+ <hr>
+ Documentation generated on {$date} by <a href="{$phpdocwebsite}" target="_blank">phpDocumentor {$phpdocversion}</a>
+ </div>
+{/if}
+</body>
+</html>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/function.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/function.tpl
new file mode 100644
index 00000000..ea314935
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/function.tpl
@@ -0,0 +1,44 @@
+{if $summary}
+<!-- =========== FUNCTION SUMMARY =========== -->
+<A NAME='function_summary'><!-- --></A>
+<H3>Function Summary</H3>
+
+<UL>
+ {section name=func loop=$functions}
+ <!-- =========== Summary =========== -->
+ <LI><CODE><A HREF="{$functions[func].id}">{$functions[func].function_return} {$functions[func].function_name}()</A></CODE>
+ <BR>{$functions[func].sdesc}
+ {/section}
+</UL>
+{else}
+<!-- ============ FUNCTION DETAIL =========== -->
+
+<A NAME='function_detail'></A>
+<H3>Function Detail</H3>
+
+<UL>
+{section name=func loop=$functions}
+<A NAME="{$functions[func].function_dest}"><!-- --></A>
+
+<LI><SPAN class="code">{$functions[func].function_return} {$functions[func].function_name}()</SPAN> [line <span class="linenumber">{if $functions[func].slink}{$functions[func].slink}{else}{$functions[func].line_number}{/if}</span>]<br />
+<BR><BR>
+<SPAN class="type">Usage:</SPAN> <SPAN class="code">{if $functions[func].ifunction_call.returnsref}&amp;{/if}{$functions[func].function_name}(
+{if count($functions[func].ifunction_call.params)}
+{section name=params loop=$functions[func].ifunction_call.params}
+{if $smarty.section.params.iteration != 1}, {/if}{if $functions[func].ifunction_call.params[params].default != ''}[{/if}{$functions[func].ifunction_call.params[params].type} {$functions[func].ifunction_call.params[params].name}{if $functions[func].ifunction_call.params[params].default != ''} = {$functions[func].ifunction_call.params[params].default|escape:"html"}]{/if}
+{/section}
+{/if})</SPAN>
+<BR><BR>
+{if $functions[func].function_conflicts.conflict_type}
+<p><b>Conflicts with functions:</b>
+{section name=me loop=$functions[func].function_conflicts.conflicts}
+{$functions[func].function_conflicts.conflicts[me]}<br />
+{/section}
+</p>
+{/if}
+{include file="docblock.tpl" sdesc=$functions[func].sdesc desc=$functions[func].desc tags=$functions[func].tags params=$functions[func].params function=true}
+<BR>
+<p class="top">[ <a href="#top">Top</a> ]</p>
+{/section}
+</UL>
+{/if} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/global.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/global.tpl
new file mode 100644
index 00000000..c1b74a1c
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/global.tpl
@@ -0,0 +1,32 @@
+{if $summary}
+<!-- =========== GLOBAL VARIABLE SUMMARY =========== -->
+<A NAME='global_summary'><!-- --></A>
+<H3>Global Variable Summary</H3>
+
+<UL>
+ {section name=glob loop=$globals}
+ <LI><CODE><A HREF="{$globals[glob].id}">{$globals[glob].global_name}</A></CODE> = <CODE class="varsummarydefault">{$globals[glob].global_value}</CODE>
+ <BR>{$globals[glob].sdesc}
+ {/section}
+</UL>
+
+{else}
+<!-- ============ GLOBAL VARIABLE DETAIL =========== -->
+
+<A NAME='global_detail'></A>
+<H3>Global Variable Detail</H3>
+
+<UL>
+ {section name=glob loop=$globals}
+ <A NAME="{$globals[glob].global_link}"><!-- --></A>
+ <LI><i>{$globals[glob].global_type}</i> <SPAN class="code">{$globals[glob].global_name}</SPAN> = <CODE class="varsummarydefault">{$globals[glob].global_value}</CODE> [line <span class="linenumber">{if $globals[glob].slink}{$globals[glob].slink}{else}{$globals[glob].line_number}{/if}</span>]<br />
+ {if $globals[glob].global_conflicts.conflict_type}
+ <p><b>Conflicts with globals:</b>
+ {section name=me loop=$globals[glob].global_conflicts.conflicts}
+ {$globals[glob].global_conflicts.conflicts[me]}<br />
+ {/section}
+ {/if}<BR><BR>
+ {include file="docblock.tpl" sdesc=$globals[glob].sdesc desc=$globals[glob].desc tags=$globals[glob].tags}
+ {/section}
+</UL>
+{/if} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/header.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/header.tpl
new file mode 100644
index 00000000..bdf6173e
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/header.tpl
@@ -0,0 +1,22 @@
+<!--
+ IE 6 makes the page to wide with the following doctype. I accept
+ standards if they help me, not if they make anything even harder!
+//-->
+<!--<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.0 Transitional//EN' 'http://www.w3.org/TR/REC-html40/loose.dtd'>//-->
+<!--NewPage-->
+<HTML>
+<HEAD>
+ <!-- Generated by PhpDoc date: '{$date}' -->
+ <TITLE>{$title}</TITLE>
+<LINK REL ='stylesheet' TYPE='text/css' HREF='{$subdir}media/stylesheet.css' TITLE='Style'>
+{if $bgleft}
+<STYLE type="text/css"><!--
+ BODY {ldelim}
+ background-image : url("{$subdir}media/bg_left.png");
+ background-repeat : repeat-y;
+ {rdelim}
+//--></STYLE>
+{/if}
+</HEAD>
+<BODY {if !$bgleft}BGCOLOR='white'{/if}>
+<a name="top"><!-- --></a> \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/hhp.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/hhp.tpl
new file mode 100644
index 00000000..a68f02b1
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/hhp.tpl
@@ -0,0 +1,17 @@
+[OPTIONS]
+Compatibility=1.1 or later
+Compiled file=documentation.chm
+Contents file=contents.hhc
+Default topic=index.html
+Display compile progress=No
+Index file=Index.hhk
+Language=0x409 English (United States)
+
+
+[FILES]
+{section name=files loop=$files}
+{$files[files].name}
+{/section}
+
+[INFOTYPES]
+
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/include.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/include.tpl
new file mode 100644
index 00000000..1ab7440b
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/include.tpl
@@ -0,0 +1,26 @@
+{if $summary}
+<!-- =========== INCLUDE SUMMARY =========== -->
+<A NAME='include_summary'><!-- --></A>
+<H3>Include Statements Summary</H3>
+
+<UL>
+ {section name=includes loop=$includes}
+ <LI><CODE><A HREF="#{$includes[includes].include_file}">{$includes[includes].include_name}</A></CODE> = <CODE class="varsummarydefault">{$includes[includes].include_value}</CODE>
+ <BR>{$includes[includes].sdesc}
+ {/section}
+</UL>
+{else}
+<!-- ============ INCLUDE DETAIL =========== -->
+
+<A NAME='include_detail'></A>
+<H3>Include Statements Detail</H3>
+
+<UL>
+ {section name=includes loop=$includes}
+ <A NAME="{$includes[includes].include_file}"><!-- --></A>
+ <LI><SPAN class="code">{$includes[includes].include_name} file:</SPAN> = <CODE class="varsummarydefault">{$includes[includes].include_value}</CODE> [line <span class="linenumber">{if $includes[includes].slink}{$includes[includes].slink}{else}{$includes[includes].line_number}{/if}</span>]<br />
+ <BR><BR>
+ {include file="docblock.tpl" sdesc=$includes[includes].sdesc desc=$includes[includes].desc tags=$includes[includes].tags}
+ {/section}
+</UL>
+{/if} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/index.hhk.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/index.hhk.tpl
new file mode 100644
index 00000000..8b31a11d
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/index.hhk.tpl
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<HTML>
+<HEAD>
+<meta name="GENERATOR" content="phpDocumentor {$phpdocversion} {$phpdocwebsite}">
+<!-- Sitemap 1.0 -->
+</HEAD><BODY>
+{$klinks}
+</BODY></HTML>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/index.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/index.tpl
new file mode 100644
index 00000000..f73fb8a3
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/index.tpl
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+ <!-- Generated by PhpDoc on {$date} -->
+ <TITLE>{$title}</TITLE>
+</HEAD>
+<FRAMESET cols='220,*'>
+{if $package_count > 1}
+ <FRAMESET rows='220,*'>
+ <FRAME src='packages.html' name='left_top'>
+{/if}
+ <FRAME src='{$start}' name='left_bottom'>
+{if $package_count > 1}
+ </FRAMESET>
+{/if}
+ <FRAME src='{$blank}.html' name='right'>
+ <NOFRAMES>
+ <H2>Frame Alert</H2>
+ <P>This document is designed to be viewed using the frames feature.
+ If you see this message, you are using a non-frame-capable web client.</P>
+ </NOFRAMES>
+</FRAMESET>
+</HTML>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/media/bg_left.png b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/media/bg_left.png
new file mode 100644
index 00000000..19fdf05d
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/media/bg_left.png
Binary files differ
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/media/stylesheet.css b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/media/stylesheet.css
new file mode 100644
index 00000000..2c08f94f
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/media/stylesheet.css
@@ -0,0 +1,129 @@
+BODY, DIV, SPAN, PRE, CODE, TD, TH {
+ line-height: 140%;
+ font-size: 10pt;
+ font-family: verdana,arial,sans-serif;
+}
+
+H1 {
+ font-size: 12pt;
+}
+
+H4 {
+ font-size: 10pt;
+ font-weight: bold;
+}
+
+P.label {
+ margin-bottom: 5px;
+}
+P.dt {
+ margin-top: 0px;
+ margin-bottom: 0px;
+}
+P.indent {
+ margin-top: 0px;
+ margin-left: 20px;
+ margin-bottom: 0px;
+}
+P.method {
+ background-color: #f0f0f0;
+ padding: 2px;
+ border: 1px #cccccc solid;
+}
+
+A {
+ text-decoration: none;
+}
+
+A:link{
+ color: #336699;
+}
+
+A:visited {
+ color: #003366;
+}
+
+A:active, A:hover {
+ color: #6699CC;
+}
+
+A:hover{
+ text-decoration: underline;
+}
+
+SPAN.type {
+ color: #336699;
+ font-size: xx-small;
+ font-weight: normal;
+ }
+
+PRE {
+ background-color: #EEEEEE;
+ padding: 10px;
+ border-width: 1px;
+ border-color: #336699;
+ border-style: solid;
+}
+
+HR {
+ color: #336699;
+ background-color: #336699;
+ border-width: 0px;
+ height: 1px;
+ filter: Alpha (opacity=100,finishopacity=0,style=1);
+}
+
+DIV.sdesc {
+ font-weight: bold;
+ background-color: #EEEEEE;
+ padding: 10px;
+ border-width: 1px;
+ border-color: #336699;
+ border-style: solid;
+}
+
+DIV.desc {
+ font-family: monospace;
+ background-color: #EEEEEE;
+ padding: 10px;
+ border-width: 1px;
+ border-color: #336699;
+ border-style: solid;
+}
+
+SPAN.code {
+ font-family: monospace;
+}
+
+CODE.varsummarydefault{
+ padding: 1px;
+ border-width: 1px;
+ border-style: dashed;
+ border-color: #336699;
+}
+
+UL.tute {
+ margin: 0px;
+ padding: 0px;
+ padding-left: 5px;
+ }
+
+LI.tute {
+ line-height: 140%;
+ font-size: 10pt;
+ text-indent: -15px;
+ padding-bottom: 2px;
+ padding-left: 14px;
+}
+
+.small{
+ font-size: 9pt;
+}
+
+
+.tute-tag { color: #009999 }
+.tute-attribute-name { color: #0000FF }
+.tute-attribute-value { color: #0099FF }
+.tute-entity { font-weight: bold; }
+.tute-comment { font-style: italic }
+.tute-inline-tag { color: #636311; font-weight: bold }
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/method.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/method.tpl
new file mode 100644
index 00000000..9309962b
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/method.tpl
@@ -0,0 +1,55 @@
+{if $show == 'summary'}
+<!-- =========== METHOD SUMMARY =========== -->
+<A NAME='method_summary'><!-- --></A>
+<H3>Method Summary</H3>
+
+<UL>
+ {section name=methods loop=$methods}
+ <!-- =========== Summary =========== -->
+ <LI><CODE><A HREF='{$methods[methods].id}'>{$methods[methods].function_return} {$methods[methods].function_name}()</A></CODE>
+ <BR>{$methods[methods].sdesc}
+ {/section}
+</UL>
+
+{else}
+<!-- ============ METHOD DETAIL =========== -->
+
+<A NAME='method_detail'></A>
+<H3>Method Detail</H3>
+
+<UL>
+{section name=methods loop=$methods}
+<A NAME='{$methods[methods].method_dest}'><!-- --></A>
+
+<h1><A name="{$methods[methods].function_name}"></A>{$class_name}::{$methods[methods].function_name}</h1>
+
+<p class=method>
+<b>{if $methods[methods].ifunction_call.returnsref}&amp;{/if}{$methods[methods].function_name}(</b>
+{if count($methods[methods].ifunction_call.params)}
+{section name=params loop=$methods[methods].ifunction_call.params}
+{if $smarty.section.params.iteration != 1}, {/if}
+{if $methods[methods].ifunction_call.params[params].default != ''}[{/if}<b>{$methods[methods].ifunction_call.params[params].type}</b>
+<i>{$methods[methods].ifunction_call.params[params].name}</i>{if $methods[methods].ifunction_call.params[params].default != ''} = {$methods[methods].ifunction_call.params[params].default}]{/if}
+{/section}
+{/if}<b> );</b>
+</p>
+
+{if $methods[methods].descmethod}
+ <p>Overridden in child classes as:<br />
+ {section name=dm loop=$methods[methods].descmethod}
+ <dl>
+ <dt>{$methods[methods].descmethod[dm].link}</dt>
+ <dd>{$methods[methods].descmethod[dm].sdesc}</dd>
+ </dl>
+ {/section}</p>
+{/if}
+{if $methods[methods].method_overrides}
+<p>Overrides {$methods[methods].method_overrides.link} ({$methods[methods].method_overrides.sdesc|default:"parent method not documented"})</p>
+{/if}
+
+{include file="docblock.tpl" sdesc=$methods[methods].sdesc desc=$methods[methods].desc tags=$methods[methods].tags params=$methods[methods].params function=true}
+ <p class="top">[ <a href="#top">Top</a> ]</p>
+<BR>
+{/section}
+</UL>
+{/if} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/packages.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/packages.tpl
new file mode 100644
index 00000000..b48b6719
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/packages.tpl
@@ -0,0 +1,3 @@
+{section name=packages loop=$packages}
+<a href="{$packages[packages].link}">{$packages[packages].title}</a>
+{/section} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/page.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/page.tpl
new file mode 100644
index 00000000..dc93b0a1
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/page.tpl
@@ -0,0 +1,34 @@
+{include file="header.tpl" eltype="Procedural file"}
+<h3><SPAN class="type">File:</SPAN> {$source_location}<HR>
+</h3>
+{if $tutorial}
+<div class="maintutorial">Main Tutorial: {$tutorial}</div>
+{/if}
+{include file="docblock.tpl" desc=$desc sdesc=$sdesc tags=$tags}
+Classes in this file:
+<dl>
+{section name=classes loop=$classes}
+<dt>{$classes[classes].link}</dt>
+ <dd>{$classes[classes].sdesc}</dd>
+{/section}
+</dl>
+<hr>
+{include file="include.tpl" summary=true}
+<hr>
+{include file="global.tpl" summary=true}
+<hr>
+{include file="define.tpl" summary=true}
+<hr>
+{include file="function.tpl" summary=true}
+<hr>
+{include file="include.tpl"}
+<hr>
+{include file="global.tpl"}
+<hr>
+{include file="define.tpl"}
+<hr>
+{include file="function.tpl"}
+<hr>
+{include file="footer.tpl"}
+
+</HTML> \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/pkgelementindex.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/pkgelementindex.tpl
new file mode 100644
index 00000000..68897450
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/pkgelementindex.tpl
@@ -0,0 +1,14 @@
+{include file="header.tpl"}
+<a name="top"></a>
+<h1>Element index for package {$package}</h1>
+{if count($packageindex) > 1}
+<b>Indexes by package:</b><br>
+{/if}
+{section name=p loop=$packageindex}
+{if $packageindex[p].title != $package}
+<a href="elementindex_{$packageindex[p].title}.html">{$packageindex[p].title}</a><br>
+{/if}
+{/section}<br>
+<a href="elementindex.html"><b>Index of all elements</b></a><br>
+{include file="basicindex.tpl" indexname=elementindex_$package}
+{include file="footer.tpl"}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/ric.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/ric.tpl
new file mode 100644
index 00000000..c4cb83f9
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/ric.tpl
@@ -0,0 +1,6 @@
+{include file="header.tpl"}
+<h1 align="center">{$name}</h1>
+<pre>
+{$contents|htmlentities}
+</pre>
+{include file="footer.tpl"} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/tocentry.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/tocentry.tpl
new file mode 100644
index 00000000..87f68ebb
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/tocentry.tpl
@@ -0,0 +1,11 @@
+<UL>
+{section name=entry loop=$entry}
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="{$entry[entry].paramname}">
+{if $entry[entry].isclass} <param name="ImageNumber" value="1">
+{/if}{if $entry[entry].outputfile} <param name="Local" value="{$entry[entry].outputfile}">
+{/if} </OBJECT>
+ {if $entry[entry].tocsubentries}{$entry[entry].tocsubentries}{/if}
+{/section}
+ {$tocsubentries}
+</UL>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/todolist.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/todolist.tpl
new file mode 100644
index 00000000..5ab0bca2
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/todolist.tpl
@@ -0,0 +1,14 @@
+{include file="header.tpl" title="Todo List"}
+<div align="center"><h1>Todo List</h1></div>
+{foreach from=$todos key=todopackage item=todo}
+<h2>{$todopackage}</h2>
+{section name=todo loop=$todo}
+<h3>{$todo[todo].link}</h3>
+<ul>
+{section name=t loop=$todo[todo].todos}
+ <li>{$todo[todo].todos[t]}</li>
+{/section}
+</ul>
+{/section}
+{/foreach}
+{include file="footer.tpl"} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/tutorial.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/tutorial.tpl
new file mode 100644
index 00000000..22c71c3b
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/tutorial.tpl
@@ -0,0 +1,32 @@
+{include file="header.tpl" title=$title}
+{if $nav}
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr>
+<td width="10%" align="left" valign="bottom">{if $prev}<a href=
+"{$prev}">{/if}Prev{if $prev}</a>{/if}</td>
+<td width="80%" align="center" valign="bottom"></td>
+<td width="10%" align="right" valign="bottom">{if $next}<a href=
+"{$next}">{/if}Next{if $next}</a>{/if}</td>
+</tr>
+</table>
+{/if}
+{$contents}
+{if $nav}
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr>
+<td width="33%" align="left" valign="top">{if $prev}<a href="{$prev}">{/if}
+Prev{if $prev}</a>{/if}</td>
+<td width="34%" align="center" valign="top">{if $up}<a href=
+"{$up}">Up</a>{else}&nbsp;{/if}</td>
+<td width="33%" align="right" valign="top">{if $next}<a href=
+"{$next}">{/if}Next{if $next}</a>{/if}</td>
+</tr>
+
+<tr>
+<td width="33%" align="left" valign="top">{if $prevtitle}{$prevtitle}{/if}</td>
+<td width="34%" align="center" valign="top">{if $uptitle}{$uptitle}{/if}</td>
+<td width="33%" align="right" valign="top">{if $nexttitle}{$nexttitle}{/if}</td>
+</tr>
+</table>
+{/if}
+{include file="footer.tpl"} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/tutorial_toc.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/tutorial_toc.tpl
new file mode 100644
index 00000000..1db34438
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/tutorial_toc.tpl
@@ -0,0 +1,29 @@
+{if count($toc)}
+<h1 align="center">Table of Contents</h1>
+<ul>
+{section name=toc loop=$toc}
+{if $toc[toc].tagname == 'refsect1'}
+{assign var="context" value="refsect1"}
+{$toc[toc].link}<br />
+{/if}
+{if $toc[toc].tagname == 'refsect2'}
+{assign var="context" value="refsect2"}
+&nbsp;&nbsp;&nbsp;{$toc[toc].link}<br />
+{/if}
+{if $toc[toc].tagname == 'refsect3'}
+{assign var="context" value="refsect3"}
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{$toc[toc].link}<br />
+{/if}
+{if $toc[toc].tagname == 'table'}
+{if $context == 'refsect2'}&nbsp;&nbsp;&nbsp;{/if}
+{if $context == 'refsect3'}&nbsp;&nbsp;&nbsp;{/if}
+Table: {$toc[toc].link}
+{/if}
+{if $toc[toc].tagname == 'example'}
+{if $context == 'refsect2'}&nbsp;&nbsp;&nbsp;{/if}
+{if $context == 'refsect3'}&nbsp;&nbsp;&nbsp;{/if}
+Table: {$toc[toc].link}
+{/if}
+{/section}
+</ul>
+{/if} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/tutorial_tree.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/tutorial_tree.tpl
new file mode 100644
index 00000000..6997545a
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/tutorial_tree.tpl
@@ -0,0 +1,5 @@
+<ul>
+ <li><a href="{$main.link}" target="right">{$main.title|strip_tags}</a>
+{if $kids}{$kids}</li>{/if}
+</ul>
+
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/var.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/var.tpl
new file mode 100644
index 00000000..d6f04b53
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/CHM/default/templates/default/templates/var.tpl
@@ -0,0 +1,30 @@
+{if $show=="summary"}
+<!-- =========== VAR SUMMARY =========== -->
+<A NAME='var_summary'><!-- --></A>
+<H3>Class Variable Summary</H3>
+
+<UL>
+ {section name=vars loop=$vars}
+ <!-- =========== Summary =========== -->
+ <LI><CODE><a href="{$vars[vars].id}">{$vars[vars].var_name}</a></CODE> = <CODE class="varsummarydefault">{$vars[vars].var_default|replace:"\n":"<br>\n"|replace:" ":"&nbsp;"|replace:"\t":"&nbsp;&nbsp;&nbsp;"}</CODE>
+ <BR>
+ {$vars[vars].sdesc}
+ {/section}
+</UL>
+{else}
+<!-- ============ VARIABLE DETAIL =========== -->
+
+<A NAME='variable_detail'></A>
+
+<H3>Variable Detail</H3>
+
+<UL>
+{section name=vars loop=$vars}
+<A NAME="{$vars[vars].var_dest}"><!-- --></A>
+<LI><SPAN class="code">{$vars[vars].var_name}</SPAN> = <CODE class="varsummarydefault">{$vars[vars].var_default|replace:"\n":"<br>\n"|replace:" ":"&nbsp;"|replace:"\t":"&nbsp;&nbsp;&nbsp;"}</CODE> [line <span class="linenumber">{if $vars[vars].slink}{$vars[vars].slink}{else}{$vars[vars].line_number}{/if}</span>]</LI>
+<LI><b>Data type:</b> <CODE class="varsummarydefault">{$vars[vars].var_type}</CODE>{if $vars[vars].var_overrides}<b>Overrides:</b> {$vars[vars].var_overrides}<br>{/if}</LI>
+{include file="docblock.tpl" sdesc=$vars[vars].sdesc desc=$vars[vars].desc tags=$vars[vars].tags}
+<BR>
+{/section}
+</UL>
+{/if} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/HTMLSmartyConverter.inc b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/HTMLSmartyConverter.inc
new file mode 100644
index 00000000..09f5af73
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/HTMLSmartyConverter.inc
@@ -0,0 +1,1779 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+/**
+ * HTML output converter for Smarty Template.
+ * This Converter takes output from the {@link Parser} and converts it to HTML-ready output for use with {@link Smarty}.
+ *
+ * @package Converters
+ * @subpackage HTMLSmarty
+ * @see parserDocBlock, parserInclude, parserPage, parserClass, parserDefine, parserFunction, parserMethod, parserVar
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Revision: 1.1 $
+ */
+/**
+ * HTML output converter.
+ * This Converter takes output from the {@link Parser} and converts it to HTML-ready output for use with {@link Smarty}.
+ *
+ * @package Converters
+ * @subpackage HTMLSmarty
+ * @see parserDocBlock, parserInclude, parserPage, parserClass, parserDefine, parserFunction, parserMethod, parserVar
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Revision: 1.1 $
+ */
+class HTMLSmartyConverter extends Converter
+{
+ /**
+ * Smarty Converter wants elements sorted by type as well as alphabetically
+ * @see Converter::$sort_page_contents_by_type
+ * @var boolean
+ */
+ var $sort_page_contents_by_type = true;
+ /** @var string */
+ var $outputformat = 'HTML';
+ /** @var string */
+ var $name = 'Smarty';
+ /**
+ * indexes of elements by package that need to be generated
+ * @var array
+ */
+ var $leftindex = array('classes' => true, 'pages' => true, 'functions' => true, 'defines' => false, 'globals' => false);
+
+ /**
+ * output directory for the current procedural page being processed
+ * @var string
+ */
+ var $page_dir;
+
+ /**
+ * target directory passed on the command-line.
+ * {@link $targetDir} is malleable, always adding package/ and package/subpackage/ subdirectories onto it.
+ * @var string
+ */
+ var $base_dir;
+
+ /**
+ * output directory for the current class being processed
+ * @var string
+ */
+ var $class_dir;
+
+ /**
+ * array of converted package page names.
+ * Used to link to the package page in the left index
+ * @var array Format: array(package => 1)
+ */
+ var $package_pages = array();
+
+ /**
+ * controls formatting of parser informative output
+ *
+ * Converter prints:
+ * "Converting /path/to/file.php... Procedural Page Elements... Classes..."
+ * Since HTMLdefaultConverter outputs files while converting, it needs to send a \n to start a new line. However, if there
+ * is more than one class, output is messy, with multiple \n's just between class file output. This variable prevents that
+ * and is purely cosmetic
+ * @var boolean
+ */
+ var $juststarted = false;
+
+ /**
+ * contains all of the template procedural page element loop data needed for the current template
+ * @var array
+ */
+ var $current;
+
+ /**
+ * contains all of the template class element loop data needed for the current template
+ * @var array
+ */
+ var $currentclass;
+ var $wrote = false;
+ var $ric_set = array();
+
+ /**
+ * sets {@link $base_dir} to $targetDir
+ * @see Converter()
+ */
+
+ /**#@+
+ * @access private
+ */
+ var $_classleft_cache = false;
+ var $_classcontents_cache = false;
+ var $_pagecontents_cache = false;
+ var $_pageleft_cache = false;
+ var $_done_package_index = false;
+ var $_ric_done = false;
+ var $_wrote_tdir = false;
+ var $ric_contents = array();
+ /**#@-*/
+
+ function HTMLSmartyConverter(&$allp, &$packp, &$classes, &$procpages, $po, $pp, $qm, $targetDir, $templateDir, $title)
+ {
+ Converter::Converter($allp, $packp, $classes, $procpages,$po, $pp, $qm, $targetDir, $templateDir, $title);
+ $this->base_dir = $targetDir;
+ }
+
+ function writeSource($path, $value)
+ {
+ $templ = &$this->newSmarty();
+ $pathinfo = $this->proceduralpages->getPathInfo($path, $this);
+ $templ->assign('source',$value);
+ $templ->assign('package',$pathinfo['package']);
+ $templ->assign('subpackage',$pathinfo['subpackage']);
+ $templ->assign('name',$pathinfo['name']);
+ $templ->assign('source_loc',$pathinfo['source_loc']);
+ $templ->assign('docs',$pathinfo['docs']);
+ $templ->assign("subdir",'../');
+ $templ->register_outputfilter('HTMLSmarty_outputfilter');
+ $this->setTargetDir($this->getFileSourcePath($this->base_dir));
+ phpDocumentor_out("\n");
+ $this->setSourcePaths($path);
+ $this->writefile($this->getFileSourceName($path).'.html',$templ->fetch('filesource.tpl'));
+ }
+
+ function writeExample($title, $path, $source)
+ {
+ $templ = &$this->newSmarty();
+ $templ->assign('source',$source);
+ if (empty($title))
+ {
+ $title = 'example';
+ addWarning(PDERROR_EMPTY_EXAMPLE_TITLE, $path, $title);
+ }
+ $templ->assign('title',$title);
+ $templ->assign('file',$path);
+ $templ->assign("subdir",'../');
+ $templ->register_outputfilter('HTMLSmarty_outputfilter');
+ $this->setTargetDir($this->base_dir . PATH_DELIMITER . '__examplesource');
+ phpDocumentor_out("\n");
+ $this->writefile('exsource_'.$path.'.html',$templ->fetch('examplesource.tpl'));
+ }
+
+ function getExampleLink($path, $title)
+ {
+ return $this->returnLink('{$subdir}__examplesource' . PATH_DELIMITER . 'exsource_'.$path.'.html',$title);
+ }
+
+ function getSourceLink($path)
+ {
+ return $this->returnLink($this->getFileSourcePath('{$subdir}') .
+ PATH_DELIMITER . $this->getFileSourceName($path).'.html','Source Code for this file');
+ }
+
+ /**
+ * 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)
+ {
+ $extra = '';
+ if (strlen(str_replace("\n", '', $line)) == 0) {
+ $extra = '&nbsp;';
+ }
+ if ($path)
+ {
+ return '<li>' . $this->getSourceAnchor($path, $linenumber) .
+ str_replace("\n",'',$line) . $extra .
+ "</li>\n";
+ } else
+ {
+ return '<li>' . str_replace("\n",'',$line) . "$extra</li>\n";
+ }
+ }
+
+ /**
+ * Used to convert the <<code>> tag in a docblock
+ * @param string
+ * @param boolean
+ * @return string
+ */
+ function ProgramExample($example, $tutorial = false, $inlinesourceparse = null/*false*/,
+ $class = null/*false*/, $linenum = null/*false*/, $filesourcepath = null/*false*/)
+ {
+ $trans = $this->template_options['desctranslate'];
+ $this->template_options['desctranslate'] = array();
+ $example = '<ol>' . parent::ProgramExample($example, $tutorial, $inlinesourceparse, $class, $linenum, $filesourcepath)
+ .'</ol>';
+ $this->template_options['desctranslate'] = $trans;
+ 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)
+ {
+ $trans = $this->template_options['desctranslate'];
+ $this->template_options['desctranslate'] = array();
+ $example = '<ol>' . parent::TutorialExample($example)
+ .'</ol>';
+ $this->template_options['desctranslate'] = $trans;
+ 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'];
+ }
+
+ /**
+ * Retrieve a Converter-specific anchor to a segment of a source code file
+ * parsed via a {@tutorial tags.filesource.pkg} tag.
+ * @param string full path to source file
+ * @param string name of anchor
+ * @param string link text, if this is a link
+ * @param boolean returns either a link or a destination based on this
+ * parameter
+ * @return string link to an anchor, or the anchor
+ */
+ function getSourceAnchor($sourcefile,$anchor,$text = '',$link = false)
+ {
+ if ($link)
+ return $this->returnLink($this->getFileSourcePath('{$subdir}') .
+ PATH_DELIMITER . $this->getFileSourceName($sourcefile).'.html#a'.$anchor, $text);
+ else
+ return '<a name="a'.$anchor.'"></a>';
+ }
+
+ function getCurrentPageLink()
+ {
+ return $this->curname . '.html';
+ }
+
+ function unmangle($sourcecode)
+ {
+ $sourcecode = str_replace('&nbsp;',' ',$sourcecode);
+ $sourcecode = str_replace('&amp;','&',$sourcecode);
+ $sourcecode = str_replace('<br />',"<br>",$sourcecode);
+ $sourcecode = str_replace('<code>','<pre>',$sourcecode);
+ $sourcecode = str_replace('</code>','</pre>',$sourcecode);
+ $sourcecode = str_replace('&lt;','<',$sourcecode);
+ $sourcecode = str_replace('&gt;','>',$sourcecode);
+ return $sourcecode;
+ }
+
+ /**
+ * Uses htmlspecialchars() on the input
+ */
+ function postProcess($text)
+ {
+ return htmlspecialchars($text);
+ }
+
+ /**
+ * Use the template tutorial_toc.tpl to generate a table of contents for HTML
+ * @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)
+ {
+ $template = &$this->newSmarty();
+ $template->assign('toc',$toc);
+ return $template->fetch('tutorial_toc.tpl');
+ }
+
+ function &SmartyInit(&$templ)
+ {
+ $this->makeLeft();
+ $templ->assign("ric",$this->ric_set);
+ $templ->assign("packageindex",$this->package_index);
+ $templ->assign('hastodos',count($this->todoList));
+ $templ->assign('todolink','todolist.html');
+ $templ->assign("subdir",'');
+ return $templ;
+ }
+
+ /**
+ * Writes out the template file of {@link $class_data} and unsets the template to save memory
+ * @see registerCurrentClass()
+ * @see parent::endClass()
+ */
+ function endClass()
+ {
+ $a = '../';
+ if (!empty($this->subpackage)) $a .= '../';
+ if ($this->juststarted)
+ {
+ $this->juststarted = false;
+ phpDocumentor_out("\n");
+ flush();
+ }
+ $this->setTargetDir($this->base_dir . PATH_DELIMITER . $this->class_dir);
+ $this->class_data->assign("compiledclassindex",$this->getClassLeft());
+ $this->class_data->assign("compiledfileindex",$this->getPageLeft());
+ $this->class_data->assign("tutorials",$this->getTutorialList());
+ $this->class_data->assign("contents",$this->getClassContents());
+ $this->class_data->assign("packageindex",$this->package_index);
+ $this->class_data->assign("package",$this->package);
+ $this->class_data->assign("subdir",$a);
+ $this->class_data->register_outputfilter('HTMLSmarty_outputfilter');
+ $this->writefile($this->class . '.html',$this->class_data->fetch('class.tpl'));
+ unset($this->class_data);
+ }
+
+ function getTutorialList()
+ {
+ static $cache = false;
+ if ($cache)
+ {
+ if (isset($cache[$this->package])) return $cache[$this->package];
+ }
+ $package = $this->package;
+ if (!isset($this->tutorials[$package])) return false;
+ foreach($this->tutorials[$package] as $subpackage => $blah)
+ {
+ $subpackages[] = $subpackage;
+ }
+ $tutes = array();
+ foreach($subpackages as $subpackage)
+ {
+ if (isset($this->tutorial_tree) && is_array($this->tutorial_tree))
+ foreach($this->tutorial_tree as $root => $tr)
+ {
+ if ($tr['tutorial']->package == $package && $tr['tutorial']->subpackage == $subpackage)
+ $tutes[$tr['tutorial']->tutorial_type][] = $this->getTutorialTree($tr['tutorial']);
+ }
+ }
+ $cache[$this->package] = $tutes;
+ return $tutes;
+ }
+
+ function getTutorialTree($tutorial,$k = false)
+ {
+ $ret = '';
+ if (is_object($tutorial)) $tree = parent::getTutorialTree($tutorial); else $tree = $tutorial;
+ if (!$tree)
+ {
+ $template = &$this->newSmarty();
+ $template->assign('subtree',false);
+ $template->assign('name',str_replace('.','',$tutorial->name));
+ $template->assign('parent',false);
+ $template->assign('haskids',false);
+ $template->assign('kids','');
+ $link = new tutorialLink;
+ $t = $tutorial;
+ $link->addLink('',$t->path,$t->name,$t->package,$t->subpackage,$t->getTitle($this));
+ $main = array('link' => $this->getId($link), 'title' => $link->title);
+ $template->assign('main',$main);
+ return $template->fetch('tutorial_tree.tpl');
+ }
+ if (isset($tree['kids']))
+ {
+ foreach($tree['kids'] as $subtree)
+ {
+ $ret .= $this->getTutorialTree($subtree, true);
+ }
+ }
+ $template = &$this->newSmarty();
+ $template->assign('subtree',$k);
+ $template->assign('name',str_replace('.','',$tree['tutorial']->name));
+ $template->assign('parent',($k ? str_replace('.','',$tree['tutorial']->parent->name) : false));
+ $template->assign('haskids',strlen($ret));
+ $template->assign('kids',$ret);
+ $link = new tutorialLink;
+ $t = $tree['tutorial'];
+ $link->addLink('',$t->path,$t->name,$t->package,$t->subpackage,$t->getTitle($this));
+ $main = array('link' => $this->getId($link), 'title' => $link->title);
+ $template->assign('main',$main);
+ return $template->fetch('tutorial_tree.tpl');
+ }
+
+ function getClassLeft()
+ {
+ if ($this->_classleft_cache)
+ {
+ if (isset($this->_classleft_cache[$this->package][$this->subpackage])) return $this->_classleft_cache[$this->package][$this->subpackage];
+ }
+ $arr = array();
+ if (isset($this->left['#class'][$this->package]))
+ foreach($this->left['#class'][$this->package] as $subpackage => $pages)
+ {
+ $arr[$subpackage] = $pages;
+ }
+ $templ = &$this->newSmarty();
+ $templ->assign('classleftindex',$arr);
+ $arr = $templ->fetch('classleft.tpl');
+ $this->_classleft_cache[$this->package][$this->subpackage] = $arr;
+ return $arr;
+ }
+
+ function getClassContents()
+ {
+ if ($this->_classcontents_cache)
+ {
+ if (isset($this->_classcontents_cache[$this->package][$this->subpackage][$this->class])) return $this->_classcontents_cache[$this->package][$this->subpackage][$this->class];
+ }
+ $arr = array();
+ foreach($this->class_contents[$this->package][$this->subpackage][$this->class] as $i => $link)
+ {
+ if (is_object($link))
+ $arr[$link->type][] = $this->returnSee($link,$link->name);
+ }
+ $this->_classcontents_cache[$this->package][$this->subpackage][$this->class] = $arr;
+ return $arr;
+ }
+
+ function getPageContents()
+ {
+ if (!isset($this->path)) $this->path = '#####';
+ if ($this->_pagecontents_cache)
+ {
+ if (isset($this->_pagecontents_cache[$this->package][$this->subpackage][$this->path])) return $this->_pagecontents_cache[$this->package][$this->subpackage][$this->path];
+ }
+ $arr = array();
+ foreach($this->page_contents[$this->curpage->package][$this->curpage->subpackage] as $i => $link)
+ {
+ if (is_object($link))
+ $arr[$link->type][$i] = $this->returnSee($link);
+ }
+ $this->_pagecontents_cache[$this->package][$this->subpackage][$this->path] = $arr;
+ return $arr;
+ }
+
+ function getPageLeft()
+ {
+ if ($this->_pageleft_cache)
+ {
+ if (isset($this->_pageleft_cache[$this->package][$this->subpackage])) return $this->_pageleft_cache[$this->package][$this->subpackage];
+ }
+ $arr = array();
+ if (isset($this->left[$this->package]))
+ foreach($this->left[$this->package] as $subpackage => $pages)
+ {
+ $arr[$subpackage] = $pages;
+ }
+ $templ = &$this->newSmarty();
+ $templ->assign('fileleftindex',$arr);
+ $arr = $templ->fetch('fileleft.tpl');
+ $this->_pageleft_cache[$this->package][$this->subpackage] = $arr;
+ return $arr;
+ }
+
+ /**
+ * Writes out the template file of {@link $page_data} and unsets the template to save memory
+ * @see registerCurrent()
+ * @see parent::endPage()
+ */
+ function endPage()
+ {
+ $this->package = $this->curpage->package;
+ $this->subpackage = $this->curpage->subpackage;
+ $a = '../';
+ if (!empty($this->subpackage)) $a .= '../';
+ $this->setTargetDir($this->base_dir . PATH_DELIMITER . $this->page_dir);
+ $this->page_data->assign("contents",$this->getPageContents());
+ $this->page_data->assign("compiledfileindex",$this->getPageLeft());
+ $this->page_data->assign("compiledclassindex",$this->getClassLeft());
+ $this->page_data->assign("tutorials",$this->getTutorialList());
+ $this->page_data->assign("packageindex",$this->package_index);
+ $this->page_data->assign("package",$this->package);
+ $this->page_data->assign("subdir",$a);
+ $this->page_data->register_outputfilter('HTMLSmarty_outputfilter');
+ $this->writefile($this->page . '.html',$this->page_data->fetch('page.tpl'));
+ unset($this->page_data);
+ }
+
+ /**
+ * @param string
+ * @param string
+ * @return string &lt;a href="'.$link.'">'.$text.'</a&gt;
+ */
+ function returnLink($link,$text)
+ {
+ return '<a href="'.$link.'">'.$text.'</a>';
+ }
+
+ function makeLeft()
+ {
+ if ($this->_done_package_index) return;
+ $this->_done_package_index = true;
+ if (!isset($this->package_index))
+ foreach($this->all_packages as $key => $val)
+ {
+ if (isset($this->pkg_elements[$key]))
+ {
+ if (!isset($start)) $start = $key;
+ $this->package_index[] = array('link' => "li_$key.html", 'title' => $key);
+ }
+ }
+ foreach($this->page_elements as $package => $o1)
+ {
+ foreach($o1 as $subpackage => $links)
+ {
+ for($i=0;$i<count($links);$i++)
+ {
+ $this->left[$package][$subpackage][] =
+ array("link" => $this->getId($links[$i]), "title" => $links[$i]->name);
+ }
+ }
+ }
+ foreach($this->class_elements as $package => $o1)
+ {
+ foreach($o1 as $subpackage => $links)
+ {
+ for($i=0;$i<count($links);$i++)
+ {
+ $this->left['#class'][$package][$subpackage][] =
+ array("link" => $this->getId($links[$i]), "title" => $links[$i]->name);
+ }
+ }
+ }
+ }
+
+ /**
+ * HTMLdefaultConverter chooses to format both package indexes and the complete index here
+ *
+ * This function formats output for the elementindex.html and pkgelementindex.html template files. It then
+ * writes them to the target directory
+ * @see generateElementIndex(), generatePkgElementIndex()
+ */
+ function formatPkgIndex()
+ {
+ list($package_indexes,$packages,$mletters) = $this->generatePkgElementIndexes();
+ for($i=0;$i<count($package_indexes);$i++)
+ {
+ $template = &$this->newSmarty();
+ $this->package = $package_indexes[$i]['package'];
+ $this->subpackage = '';
+ $template->assign("compiledclassindex",$this->getClassLeft());
+ $template->assign("compiledfileindex",$this->getPageLeft());
+ $template->assign("tutorials",$this->getTutorialList());
+ $template->assign("index",$package_indexes[$i]['pindex']);
+ $template->assign("package",$package_indexes[$i]['package']);
+ $template->assign("letters",$mletters[$package_indexes[$i]['package']]);
+ $template->assign("title","Package ".$package_indexes[$i]['package']." Element Index");
+ $template->assign("date",date("r",time()));
+ $template->register_outputfilter('HTMLSmarty_outputfilter');
+ $this->setTargetDir($this->base_dir);
+ $this->writefile('elementindex_'.$package_indexes[$i]['package'].'.html',$template->fetch('pkgelementindex.tpl'));
+ }
+ phpDocumentor_out("\n");
+ flush();
+ }
+
+ /**
+ * HTMLdefaultConverter uses this function to format template index.html and packages.html
+ *
+ * This function generates the package list from {@link $all_packages}, eliminating any
+ * packages that don't have any entries in their package index (no files at all, due to @ignore
+ * or other factors). Then it uses the default package name as the first package index to display.
+ * It sets the right pane to be either a blank file with instructions on making package-level docs,
+ * or the package-level docs for the default package.
+ * @global string Used to set the starting package to display
+ */
+ function formatIndex()
+ {
+ global $phpDocumentor_DefaultPackageName;
+ if (!isset($this->package_index))
+ {
+ debug("\nERROR: Nothing parsed, check the command-line");
+ die();
+ }
+ list($elindex,$mletters) = $this->generateElementIndex();
+ $template = &$this->newSmarty();
+ $template->assign("index",$elindex);
+ $template->assign("letters",$mletters);
+ $template->assign("title","Element Index");
+ $template->assign("date",date("r",time()));
+ phpDocumentor_out("\n");
+ flush();
+ $this->setTargetDir($this->base_dir);
+ $template->register_outputfilter('HTMLSmarty_outputfilter');
+ $this->writefile('elementindex.html',$template->fetch('elementindex.tpl'));
+ usort($this->package_index,"HTMLSmarty_pindexcmp");
+ $index = &$this->newSmarty();
+ foreach($this->all_packages as $key => $val)
+ {
+ if (isset($this->pkg_elements[$key]))
+ {
+ if (!isset($start)) $start = $key;
+ if (!isset($this->package_pages[$key])) $this->writeNewPPage($key);
+ }
+ }
+ // Created index.html
+ $start = $phpDocumentor_DefaultPackageName;
+ if (!isset($this->pkg_elements[$key]))
+ {
+ // if there are no elements, use a random package as the default
+ $start = array_shift(array_keys($this->pkg_elements));
+ }
+ $this->package = $start;
+ $this->subpackage = '';
+ $index->assign("compiledclassindex",$this->getClassLeft());
+ $index->assign("compiledfileindex",$this->getPageLeft());
+ $index->assign('hastodos',count($this->todoList));
+ $index->assign('todolink','todolist.html');
+ $index->assign("tutorials",$this->getTutorialList());
+ $index->assign("date",date("r",time()));
+ $index->assign("package",$this->package);
+ $index->assign("title",$this->title);
+ $index->assign("start","li_$start.html");
+ if (isset($this->package_pages[$start]))
+ {
+ $index->assign("contents",$this->package_pages[$start]);
+ }
+ $index->register_outputfilter('HTMLSmarty_outputfilter');
+ phpDocumentor_out("\n");
+ flush();
+ $this->setTargetDir($this->base_dir);
+ $this->writefile("index.html",$index->fetch('index.tpl'));
+ unset($index);
+
+ }
+
+ function writeNewPPage($key)
+ {
+ $template = &$this->newSmarty();
+ $this->package = $key;
+ $this->subpackage = '';
+ $template->assign("compiledclassindex",$this->getClassLeft());
+ $template->assign("compiledfileindex",$this->getPageLeft());
+ $template->assign("tutorials",$this->getTutorialList());
+ $template->assign("date",date("r",time()));
+ $template->assign("title",$this->title);
+ $template->assign("package",$key);
+ $template->register_outputfilter('HTMLSmarty_outputfilter');
+ phpDocumentor_out("\n");
+ flush();
+ $this->setTargetDir($this->base_dir);
+ $this->writefile("li_$key.html",$template->fetch('index.tpl'));
+ unset($template);
+ }
+
+ /**
+ * Generate indexes for li_package.html and classtree output files
+ *
+ * This function generates the li_package.html files from the template file left.html. It does this by
+ * iterating through each of the $page_elements, $class_elements and $function_elements arrays to retrieve
+ * the pre-sorted {@link abstractLink} descendants needed for index generation. Conversion of these links to
+ * text is done by {@link returnSee()}.
+ *
+ * Then it uses {@link generateFormattedClassTrees()} to create class trees from the template file classtrees.html. Output
+ * filename is classtrees_packagename.html. This function also unsets {@link $elements} and {@link $pkg_elements} to free
+ * up the considerable memory these two class vars use
+ * @see $page_elements, $class_elements, $function_elements
+ */
+ function formatLeftIndex()
+ {
+ phpDocumentor_out("\n");
+ flush();
+ $this->setTargetDir($this->base_dir);
+ if (!isset($this->left))
+ {
+ debug("Nothing parsed, check the command-line");
+ die();
+ }
+ foreach($this->all_packages as $package => $rest)
+ {
+ if (!isset($this->pkg_elements[$package])) continue;
+ // Create class tree page
+ $template = &$this->newSmarty();
+ $template->assign("compiledclassindex",$this->getClassLeft());
+ $template->assign("compiledfileindex",$this->getPageLeft());
+ $template->assign("classtrees",$this->generateFormattedClassTrees($package));
+ $template->assign("package",$package);
+ $template->assign("date",date("r",time()));
+ $template->assign("title","Class Trees for Package $package");
+ $template->register_outputfilter('HTMLSmarty_outputfilter');
+ $this->writefile("classtrees_$package.html",$template->fetch('classtrees.tpl'));
+ phpDocumentor_out("\n");
+ flush();
+ }
+ $this->writeRIC();
+ // free up considerable memory
+ unset($this->elements);
+ unset($this->pkg_elements);
+ }
+
+
+ /**
+ * This function takes an {@link abstractLink} descendant and returns an html link
+ *
+ * @param abstractLink a descendant of abstractlink should be passed, and never text
+ * @param string text to display in the link
+ * @param boolean this parameter is not used, and is deprecated
+ * @param boolean determines whether the returned text is enclosed in an &lt;a> tag
+ */
+ function returnSee(&$element, $eltext = false, $with_a = true)
+ {
+ if (!is_object($element) || !$element) return false;
+ if (!$with_a) return $this->getId($element, false);
+ if (!$eltext)
+ {
+ $eltext = '';
+ switch($element->type)
+ {
+ case 'tutorial' :
+ $eltext = strip_tags($element->title);
+ break;
+ case 'method' :
+ case 'var' :
+ case 'const' :
+ $eltext .= $element->class.'::';
+ case 'page' :
+ case 'define' :
+ case 'class' :
+ case 'function' :
+ case 'global' :
+ default :
+ $eltext .= $element->name;
+ if ($element->type == 'function' || $element->type == 'method') $eltext .= '()';
+ break;
+ }
+ }
+ return '<a href="'.$this->getId($element).'">'.$eltext.'</a>';
+ }
+
+ function getId($element, $fullpath = true)
+ {
+ if (phpDocumentor_get_class($element) == 'parserdata')
+ {
+ $element = $this->addLink($element->parent);
+ $elp = $element->parent;
+ } elseif (is_a($element, 'parserbase'))
+ {
+ $elp = $element;
+ $element = $this->addLink($element);
+ }
+ $c = '';
+ if (!empty($element->subpackage))
+ {
+ $c = '/'.$element->subpackage;
+ }
+ $b = '{$subdir}';
+ switch ($element->type)
+ {
+ case 'page' :
+ if ($fullpath)
+ return $b.$element->package.$c.'/'.$element->fileAlias.'.html';
+ return 'top';
+ break;
+ case 'define' :
+ case 'global' :
+ case 'function' :
+ if ($fullpath)
+ return $b.$element->package.$c.'/'.$element->fileAlias.'.html#'.$element->type.$element->name;
+ return $element->type.$element->name;
+ break;
+ case 'class' :
+ if ($fullpath)
+ return $b.$element->package.$c.'/'.$element->name.'.html';
+ return 'top';
+ break;
+ case 'method' :
+ case 'var' :
+ case 'const' :
+ if ($fullpath)
+ return $b.$element->package.$c.'/'.$element->class.'.html#'.$element->type.$element->name;
+ return $element->type.$element->name;
+ break;
+ case 'tutorial' :
+ $d = '';
+ if ($element->section)
+ {
+ $d = '#'.$element->section;
+ }
+ return $b.$element->package.$c.'/tutorial_'.$element->name.'.html'.$d;
+ }
+ }
+
+ /**
+ * Convert README/INSTALL/CHANGELOG file contents to output format
+ * @param README|INSTALL|CHANGELOG
+ * @param string contents of the file
+ */
+ function Convert_RIC($name, $contents)
+ {
+ $this->ric_contents[$name] = $contents;
+ $this->ric_set[] = array('file' => 'ric_'.$name . '.html','name' => $name);
+ }
+
+ function writeRIC()
+ {
+ if ($this->_ric_done) return;
+ $this->_ric_done = true;
+ foreach($this->ric_contents as $name => $contents)
+ {
+ $template = &$this->newSmarty();
+ $template->assign('contents',$contents);
+ $template->assign('name',$name);
+ $template->assign('title',$name);
+ $this->setTargetDir($this->base_dir);
+ $this->writefile('ric_'.$name . '.html',$template->fetch('ric.tpl'));
+ }
+ }
+
+ function ConvertTodoList()
+ {
+ $todolist = array();
+ foreach($this->todoList as $package => $alltodos)
+ {
+ foreach($alltodos as $todos)
+ {
+ $converted = array();
+ $converted['link'] = $this->returnSee($todos[0]);
+ if (!is_array($todos[1]))
+ {
+ $converted['todos'][] = $todos[1]->Convert($this);
+ } else
+ {
+ foreach($todos[1] as $todo)
+ {
+ $converted['todos'][] = $todo->Convert($this);
+ }
+ }
+ $todolist[$package][] = $converted;
+ }
+ }
+ $templ = &$this->newSmarty();
+ $templ->assign('todos',$todolist);
+ $templ->register_outputfilter('HTMLSmarty_outputfilter');
+ $this->setTargetDir($this->base_dir);
+ $this->writefile('todolist.html',$templ->fetch('todolist.tpl'));
+ }
+
+ /**
+ * Create errors.html template file output
+ *
+ * This method takes all parsing errors and warnings and spits them out ordered by file and line number.
+ * @global ErrorTracker We'll be using it's output facility
+ */
+ function ConvertErrorLog()
+ {
+ global $phpDocumentor_errors;
+ $allfiles = array();
+ $files = array();
+ $warnings = $phpDocumentor_errors->returnWarnings();
+ $errors = $phpDocumentor_errors->returnErrors();
+ $template = &$this->newSmarty();
+ foreach($warnings as $warning)
+ {
+ $file = '##none';
+ $linenum = 'Warning';
+ if ($warning->file)
+ {
+ $file = $warning->file;
+ $allfiles[$file] = 1;
+ $linenum .= ' on line '.$warning->linenum;
+ }
+ $files[$file]['warnings'][] = array('name' => $linenum, 'listing' => $warning->data);
+ }
+ foreach($errors as $error)
+ {
+ $file = '##none';
+ $linenum = 'Error';
+ if ($error->file)
+ {
+ $file = $error->file;
+ $allfiles[$file] = 1;
+ $linenum .= ' on line '.$error->linenum;
+ }
+ $files[$file]['errors'][] = array('name' => $linenum, 'listing' => $error->data);
+ }
+ $i=1;
+ $af = array();
+ foreach($allfiles as $file => $num)
+ {
+ $af[$i++] = $file;
+ }
+ $allfiles = $af;
+ usort($allfiles,'strnatcasecmp');
+ $allfiles[0] = "Post-parsing";
+ foreach($allfiles as $i => $a)
+ {
+ $allfiles[$i] = array('file' => $a);
+ }
+ $out = array();
+ foreach($files as $file => $data)
+ {
+ if ($file == '##none') $file = 'Post-parsing';
+ $out[$file] = $data;
+ }
+ $template->assign("files",$allfiles);
+ $template->assign("all",$out);
+ $template->assign("title","phpDocumentor Parser Errors and Warnings");
+ $template->register_outputfilter('HTMLSmarty_outputfilter');
+ $this->setTargetDir($this->base_dir);
+ $this->writefile("errors.html",$template->fetch('errors.tpl'));
+ unset($template);
+ phpDocumentor_out("\n\nTo view errors and warnings, look at ".$this->base_dir. PATH_DELIMITER . "errors.html\n");
+ flush();
+ }
+
+ function getCData($value)
+ {
+ return '<pre>'.htmlentities($value).'</pre>';
+ }
+
+ function getTutorialId($package,$subpackage,$tutorial,$id)
+ {
+ return $id;
+ }
+
+ /**
+ * Converts package page and sets its package as used in {@link $package_pages}
+ * @param parserPackagePage
+ */
+ function convertPackagepage(&$element)
+ {
+ phpDocumentor_out("\n");
+ flush();
+ $template = &$this->newSmarty();
+ $this->package = $element->package;
+ $this->subpackage = '';
+ $template->assign("compiledclassindex",$this->getClassLeft());
+ $template->assign("compiledfileindex",$this->getPageLeft());
+ $template->assign("tutorials",$this->getTutorialList());
+ $template->assign("date",date("r",time()));
+ $template->assign("title",$this->title);
+ $template->assign("package",$element->package);
+ $x = $element->Convert($this);
+ $x = substr($x,strpos($x,'<body'));
+ $template->assign("contents",trim(substr($x,strpos($x,'>') + 1)));
+ $this->package_pages[$element->package] = trim(substr($x,strpos($x,'>') + 1));
+ $template->register_outputfilter('HTMLSmarty_outputfilter');
+ phpDocumentor_out("\n");
+ flush();
+ $this->setTargetDir($this->base_dir);
+ $this->writefile("li_".$element->package.".html",$template->fetch('index.tpl'));
+ unset($template);
+ }
+
+ /**
+ * @param parserTutorial
+ */
+ function convertTutorial(&$element)
+ {
+ phpDocumentor_out("\n");
+ flush();
+ $template = &parent::convertTutorial($element);
+ $this->package = $element->package;
+ $this->subpackage = $element->subpackage;
+ $template->assign("compiledclassindex",$this->getClassLeft());
+ $template->assign("compiledfileindex",$this->getPageLeft());
+ $template->assign("tutorials",$this->getTutorialList());
+ $template->assign("title",strip_tags($element->getTitle($this)));
+ $contents = $element->Convert($this);
+ if ($element->name == $this->package . '.pkg')
+ {
+ $this->package_pages[$element->package] = $contents;
+ }
+ $a = '../';
+ if (!empty($element->subpackage)) $a .= $a;
+ $template->assign("subdir",$a);
+ $a = '';
+ if ($element->subpackage) $a = PATH_DELIMITER . $element->subpackage;
+ $template->register_outputfilter('HTMLSmarty_outputfilter');
+ $this->setTargetDir($this->base_dir . PATH_DELIMITER . $element->package . $a);
+ $this->writeFile('tutorial_'.$element->name.'.html',$template->fetch('tutorial.tpl'));
+ if ($element->name == $element->package . '.pkg')
+ {
+ phpDocumentor_out("\n");
+ flush();
+ // package-level docs
+ $this->setTargetDir($this->base_dir);
+ $template->assign("subdir",'');
+ $this->writeFile('li_'.$element->package.'.html',$template->fetch('tutorial.tpl'));
+ }
+ unset($template);
+ }
+
+ /**
+ * Converts class for template output
+ * @see prepareDocBlock(), generateChildClassList(), generateFormattedClassTree(), getFormattedConflicts()
+ * @see getFormattedInheritedMethods(), getFormattedInheritedVars()
+ * @param parserClass
+ */
+ function convertClass(&$element)
+ {
+ parent::convertClass($element);
+ $this->class_dir = $element->docblock->package;
+ if (!empty($element->docblock->subpackage)) $this->class_dir .= PATH_DELIMITER . $element->docblock->subpackage;
+ $a = '../classtrees_';
+ if ($element->docblock->subpackage != '') $a = "../$a";
+
+ $this->class_data->assign('subdir',$a);
+ $this->class_data->assign("title","Docs For Class " . $element->getName());
+ $this->class_data->assign("page",$element->getName() . '.html');
+ }
+
+ /**
+ * Converts class variables for template output
+ * @see prepareDocBlock(), getFormattedConflicts()
+ * @param parserDefine
+ */
+ function convertVar(&$element)
+ {
+ parent::convertVar($element, array('var_dest' => $this->getId($element,false)));
+ }
+
+ /**
+ * Converts class variables for template output
+ * @see prepareDocBlock(), getFormattedConflicts()
+ * @param parserDefine
+ */
+ function convertConst(&$element)
+ {
+ parent::convertConst($element, array('const_dest' => $this->getId($element,false)));
+ }
+
+ /**
+ * Converts class methods for template output
+ * @see prepareDocBlock(), getFormattedConflicts()
+ * @param parserDefine
+ */
+ function convertMethod(&$element)
+ {
+ parent::convertMethod($element, array('method_dest' => $this->getId($element,false)));
+ }
+
+ /**
+ * Converts function for template output
+ * @see prepareDocBlock(), parserFunction::getFunctionCall(), getFormattedConflicts()
+ * @param parserFunction
+ */
+ function convertFunction(&$element)
+ {
+ $funcloc = $this->getId($this->addLink($element));
+ parent::convertFunction($element,array('function_dest' => $this->getId($element,false)));
+ }
+
+ /**
+ * Converts include elements for template output
+ * @see prepareDocBlock()
+ * @param parserInclude
+ */
+ function convertInclude(&$element)
+ {
+ parent::convertInclude($element, array('include_file' => '_'.strtr($element->getValue(),array('"' => '', "'" => '','.' => '_'))));
+ }
+
+ /**
+ * Converts defines for template output
+ * @see prepareDocBlock(), getFormattedConflicts()
+ * @param parserDefine
+ */
+ function convertDefine(&$element)
+ {
+ parent::convertDefine($element, array('define_link' => $this->getId($element,false)));
+ }
+
+ /**
+ * Converts global variables for template output
+ * @param parserGlobal
+ * @see prepareDocBlock(), getFormattedConflicts()
+ */
+ function convertGlobal(&$element)
+ {
+ parent::convertGlobal($element, array('global_link' => $this->getId($element,false)));
+ }
+
+ /**
+ * converts procedural pages for template output
+ * @see prepareDocBlock(), getClassesOnPage()
+ * @param parserData
+ */
+ function convertPage(&$element)
+ {
+ parent::convertPage($element);
+ $this->juststarted = true;
+ $this->page_dir = $element->parent->package;
+ if (!empty($element->parent->subpackage)) $this->page_dir .= PATH_DELIMITER . $element->parent->subpackage;
+ // registering stuff on the template
+ $a = '../';
+ if (!empty($element->docblock->subpackage)) $a = $a . $a;
+ $this->page_data->assign('subdir',$a);
+ $this->page_data->assign("page",$this->getPageName($element) . '.html');
+ $this->page_data->assign("title","Docs for page ".$element->parent->getFile());
+ }
+
+ function getPageName(&$element)
+ {
+ if (phpDocumentor_get_class($element) == 'parserpage') return '_'.$element->getName();
+ return '_'.$element->parent->getName();
+ }
+
+ /**
+ * returns an array containing the class inheritance tree from the root object to the class
+ *
+ * @param parserClass class variable
+ * @return array Format: array(root,child,child,child,...,$class)
+ * @uses parserClass::getParentClassTree()
+ */
+
+ function generateFormattedClassTree($class)
+ {
+ $tree = $class->getParentClassTree($this);
+ $out = '';
+ if (count($tree) - 1)
+ {
+ $result = array($class->getName());
+ $parent = $tree[$class->getName()];
+ $distance[] = '';
+ while ($parent)
+ {
+ $x = $parent;
+ if (is_object($parent))
+ {
+ $subpackage = $parent->docblock->subpackage;
+ $package = $parent->docblock->package;
+ $x = $parent;
+ $x = $parent->getLink($this);
+ if (!$x) $x = $parent->getName();
+ }
+ $result[] =
+ $x;
+ $distance[] =
+ "\n%s|\n" .
+ "%s--";
+ if (is_object($parent))
+ $parent = $tree[$parent->getName()];
+ elseif (isset($tree[$parent]))
+ $parent = $tree[$parent];
+ }
+ $nbsp = ' ';
+ for($i=count($result) - 1;$i>=0;$i--)
+ {
+ $my_nbsp = '';
+ for($j=0;$j<count($result) - $i;$j++) $my_nbsp .= $nbsp;
+ $distance[$i] = sprintf($distance[$i],$my_nbsp,$my_nbsp);
+ }
+ return array('classes'=>array_reverse($result),'distance'=>array_reverse($distance));
+ } else
+ {
+ return array('classes'=>$class->getName(),'distance'=>array(''));
+ }
+ }
+
+ /** @access private */
+ function sortVar($a, $b)
+ {
+ return strnatcasecmp($a->getName(),$b->getName());
+ }
+
+ /** @access private */
+ function sortMethod($a, $b)
+ {
+ if ($a->isConstructor) return -1;
+ if ($b->isConstructor) return 1;
+ return strnatcasecmp($a->getName(),$b->getName());
+ }
+
+ /**
+ * returns a template-enabled array of class trees
+ *
+ * @param string $package package to generate a class tree for
+ * @see $roots, HTMLConverter::getRootTree()
+ */
+ function generateFormattedClassTrees($package)
+ {
+ if (!isset($this->roots[$package])) return array();
+ $roots = $trees = array();
+ $roots = $this->roots[$package];
+ for($i=0;$i<count($roots);$i++)
+ {
+ $trees[] = array('class' => $roots[$i],'class_tree' => "<ul>\n".$this->getRootTree($this->getSortedClassTreeFromClass($roots[$i],$package,''),$package)."</ul>\n");
+ }
+ return $trees;
+ }
+
+ /**
+ * return formatted class tree for the Class Trees page
+ *
+ * @param array $tree output from {@link getSortedClassTreeFromClass()}
+ * @see Classes::$definitechild, generateFormattedClassTrees()
+ * @return string
+ */
+ function getRootTree($tree,$package)
+ {
+ if (!$tree) return '';
+ $my_tree = '';
+ $cur = '#root';
+ $lastcur = array(false);
+ $kids = array();
+ $dopar = false;
+ if ($tree[$cur]['parent'])
+ {
+ $dopar = true;
+ if (!is_object($tree[$cur]['parent']))
+ {
+// debug("parent ".$tree[$cur]['parent']." not found");
+ $my_tree .= '<li>' . $tree[$cur]['parent'] .'<ul>';
+ }
+ else
+ {
+// debug("parent ".$this->returnSee($tree[$cur]['parent'])." in other package");
+ $my_tree .= '<li>' . $this->returnSee($tree[$cur]['parent']);
+ if ($tree[$cur]['parent']->package != $package) $my_tree .= ' <b>(Different package)</b><ul>';
+ }
+ }
+ do
+ {
+// fancy_debug($cur,$lastcur,$kids);
+ if (count($tree[$cur]['children']))
+ {
+// debug("$cur has children");
+ if (!isset($kids[$cur]))
+ {
+// debug("set $cur kids");
+ $kids[$cur] = 1;
+ $my_tree .= '<li>'.$this->returnSee($tree[$cur]['link']);
+ $my_tree .= '<ul>'."\n";
+ }
+ array_push($lastcur,$cur);
+ list(,$cur) = each($tree[$cur]['children']);
+// var_dump('listed',$cur);
+ if ($cur)
+ {
+ $cur = $cur['package'] . '#' . $cur['class'];
+// debug("set cur to child $cur");
+// $my_tree .= '<li>'.$this->returnSee($tree[$cur]['link']);
+ continue;
+ } else
+ {
+// debug("end of children for $cur");
+ $cur = array_pop($lastcur);
+ $cur = array_pop($lastcur);
+ $my_tree .= '</ul></li>'."\n";
+ if ($dopar && ($cur == '#root' || !$cur)) $my_tree .= '</ul></li>';
+ }
+ } else
+ {
+// debug("$cur has no children");
+ $my_tree .= '<li>'.$this->returnSee($tree[$cur]['link'])."</li>";
+ if ($dopar && $cur == '#root') $my_tree .= '</ul></li>';
+ $cur = array_pop($lastcur);
+ }
+ } while ($cur);
+ return $my_tree;
+ }
+ /**
+ * Generate indexing information for given element
+ *
+ * @param parserElement descendant of parserElement
+ * @see generateElementIndex()
+ * @return array
+ */
+ function getIndexInformation($elt)
+ {
+ $Result['type'] = $elt->type;
+ $Result['file_name'] = $elt->file;
+ $Result['path'] = $elt->getPath();
+
+ if (isset($elt->docblock))
+ {
+ $Result['description'] = $elt->docblock->getSDesc($this);
+
+ if ($elt->docblock->hasaccess)
+ $Result['access'] = $elt->docblock->tags['access'][0]->value;
+ else
+ $Result['access'] = 'public';
+
+ $Result['abstract'] = isset ($elt->docblock->tags['abstract'][0]);
+ }
+ else
+ $Result['description'] = '';
+
+ $aa = $Result['description'];
+ if (!empty($aa)) $aa = "<br>&nbsp;&nbsp;&nbsp;&nbsp;$aa";
+
+ switch($elt->type)
+ {
+ case 'class':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Class';
+ $Result['link'] = $this->getClassLink($elt->getName(),
+ $elt->docblock->package,
+ $elt->getPath(),
+ $elt->getName());
+ $Result['listing'] = 'in file '.$elt->file.', class '.$Result['link']."$aa";
+ break;
+ case 'define':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Constant';
+ $Result['link'] = $this->getDefineLink($elt->getName(),
+ $elt->docblock->package,
+ $elt->getPath(),
+ $elt->getName());
+ $Result['listing'] = 'in file '.$elt->file.', constant '.$Result['link']."$aa";
+ break;
+ case 'global':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Global';
+ $Result['link'] = $this->getGlobalLink($elt->getName(),
+ $elt->docblock->package,
+ $elt->getPath(),
+ $elt->getName());
+ $Result['listing'] = 'in file '.$elt->file.', global variable '.$Result['link']."$aa";
+ break;
+ case 'function':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Function';
+ $Result['link'] = $this->getFunctionLink($elt->getName(),
+ $elt->docblock->package,
+ $elt->getPath(),
+ $elt->getName().'()');
+ $Result['listing'] = 'in file '.$elt->file.', function '.$Result['link']."$aa";
+ break;
+ case 'method':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Method';
+ $Result['link'] = $this->getMethodLink($elt->getName(),
+ $elt->class,
+ $elt->docblock->package,
+ $elt->getPath(),
+ $elt->class.'::'.$elt->getName().'()'
+ );
+ if ($elt->isConstructor) $Result['constructor'] = 1;
+ $Result['listing'] = 'in file '.$elt->file.', method '.$Result['link']."$aa";
+ break;
+ case 'var':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Variable';
+ $Result['link'] = $this->getVarLink($elt->getName(),
+ $elt->class,
+ $elt->docblock->package,
+ $elt->getPath(),
+ $elt->class.'::'.$elt->getName());
+ $Result['listing'] = 'in file '.$elt->file.', variable '.$Result['link']."$aa";
+ break;
+ case 'const':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Variable';
+ $Result['link'] = $this->getConstLink($elt->getName(),
+ $elt->class,
+ $elt->docblock->package,
+ $elt->getPath(),
+ $elt->class.'::'.$elt->getName());
+ $Result['listing'] = 'in file '.$elt->file.', class constant '.$Result['link']."$aa";
+ break;
+ case 'page':
+ $Result['name'] = $elt->getFile();
+ $Result['title'] = 'Page';
+ $Result['link'] = $this->getPageLink($elt->getFile(),
+ $elt->package,
+ $elt->getPath(),
+ $elt->getFile());
+ $Result['listing'] = 'procedural page '.$Result['link'];
+ break;
+ case 'include':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Include';
+ $Result['link'] = $elt->getValue();
+ $Result['listing'] = 'include '.$Result['name'];
+ break;
+ }
+
+ return $Result;
+ }
+ /**
+ * Generate alphabetical index of all elements
+ *
+ * @see $elements, walk()
+ */
+ function generateElementIndex()
+ {
+ $elementindex = array();
+ $letters = array();
+ $used = array();
+ foreach($this->elements as $letter => $nutoh)
+ {
+ foreach($this->elements[$letter] as $i => $yuh)
+ {
+ if ($this->elements[$letter][$i]->type != 'include')
+ {
+ if (!isset($used[$letter]))
+ {
+ $letters[]['letter'] = $letter;
+ $elindex['letter'] = $letter;
+ $used[$letter] = 1;
+ }
+
+ $elindex['index'][] = $this->getIndexInformation($this->elements[$letter][$i]);
+ }
+ }
+ if (isset($elindex['index']))
+ {
+ $elementindex[] = $elindex;
+ } else
+ {
+ unset($letters[count($letters) - 1]);
+ }
+ $elindex = array();
+ }
+ return array($elementindex,$letters);
+ }
+
+ function copyMediaRecursively($media,$targetdir,$subdir = '')
+ {
+ if (!is_array($media)) {
+ return;
+ }
+ foreach($media as $dir => $files)
+ {
+ if ($dir === '/')
+ {
+ $this->copyMediaRecursively($files,$targetdir);
+ } else
+ {
+ if (!is_numeric($dir))
+ {
+ // create the subdir
+ phpDocumentor_out("creating $targetdir/$dir\n");
+ Converter::setTargetDir($targetdir . PATH_DELIMITER . $dir);
+ if (!empty($subdir)) $subdir .= PATH_DELIMITER;
+ $this->copyMediaRecursively($files,"$targetdir/$dir",$subdir . $dir);
+ } else
+ {
+ // copy the file
+ phpDocumentor_out("copying $targetdir/".$files['file']."\n");
+ $this->copyFile($files['file'],$subdir);
+ }
+ }
+ }
+ }
+
+ /**
+ * calls the converter setTargetDir, and then copies any template images and the stylesheet if they haven't been copied
+ * @see Converter::setTargetDir()
+ */
+ function setTargetDir($dir)
+ {
+ Converter::setTargetDir($dir);
+ if ($this->_wrote_tdir) return;
+ $this->_wrote_tdir = true;
+ $template_images = array();
+ $stylesheets = array();
+ $tdir = $dir;
+ $dir = $this->templateDir;
+ $this->templateDir = $this->templateDir.'templates/';
+ $info = new Io;
+ $this->copyMediaRecursively($info->getDirTree($this->templateDir.'media',$this->templateDir),$tdir);
+ }
+
+ /**
+ * Generate alphabetical index of all elements by package and subpackage
+ *
+ * @param string $package name of a package
+ * @see $pkg_elements, walk(), generatePkgElementIndexes()
+ */
+ function generatePkgElementIndex($package)
+ {
+ $elementindex = array();
+ $letters = array();
+ $letterind = array();
+ $used = array();
+ $subp = '';
+ foreach($this->pkg_elements[$package] as $subpackage => $els)
+ {
+ if (empty($els)) continue;
+ if (!empty($subpackage)) $subp = " (<b>subpackage:</b> $subpackage)"; else $subp = '';
+ foreach($els as $letter => $yuh)
+ {
+ foreach($els[$letter] as $i => $yuh)
+ {
+ if ($els[$letter][$i]->type != 'include')
+ {
+ if (!isset($used[$letter]))
+ {
+ $letters[]['letter'] = $letter;
+ $letterind[$letter] = count($letters) - 1;
+ $used[$letter] = 1;
+ }
+ $elindex[$letter]['letter'] = $letter;
+
+ $elindex[$letter]['index'][] = $this->getIndexInformation($els[$letter][$i]);
+ }
+ }
+ }
+ }
+ ksort($elindex);
+ usort($letters,'HTMLSmarty_lettersort');
+ if (isset($elindex))
+ {
+ while(list($letter,$tempel) = each($elindex))
+ {
+ if (!isset($tempel))
+ {
+ unset($letters[$letterind[$tempel['letter']]]);
+ } else
+ $elementindex[] = $tempel;
+ }
+ } else $letters = array();
+ return array($elementindex,$letters);
+ }
+
+ /**
+ *
+ * @see generatePkgElementIndex()
+ */
+ function generatePkgElementIndexes()
+ {
+ $packages = array();
+ $package_names = array();
+ $pkg = array();
+ $letters = array();
+ foreach($this->pkg_elements as $package => $trash)
+ {
+ $pkgs['package'] = $package;
+ $pkg['package'] = $package;
+ list($pkg['pindex'],$letters[$package]) = $this->generatePkgElementIndex($package);
+ if (count($pkg['pindex']))
+ {
+ $packages[] = $pkg;
+ $package_names[] = $pkgs;
+ }
+ unset($pkgs);
+ unset($pkg);
+ }
+ foreach($packages as $i => $package)
+ {
+ $pnames = array();
+ for($j=0;$j<count($package_names);$j++)
+ {
+ if ($package_names[$j]['package'] != $package['package']) $pnames[] = $package_names[$j];
+ }
+ $packages[$i]['packageindexes'] = $pnames;
+ }
+ return array($packages,$package_names,$letters);
+ }
+
+ /**
+ * @param string name of class
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the class's documentation
+ * @see parent::getClassLink()
+ */
+ function getClassLink($expr,$package, $file = false,$text = false, $with_a = true)
+ {
+ $a = Converter::getClassLink($expr,$package,$file);
+ if (!$a) return false;
+ return $this->returnSee($a, $text, $with_a);
+ }
+
+ /**
+ * @param string name of function
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the function's documentation
+ * @see parent::getFunctionLink()
+ */
+ function getFunctionLink($expr,$package, $file = false,$text = false)
+ {
+ $a = Converter::getFunctionLink($expr,$package,$file);
+ if (!$a) return false;
+ return $this->returnSee($a, $text);
+ }
+
+ /**
+ * @param string name of define
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the define's documentation
+ * @see parent::getDefineLink()
+ */
+ function getDefineLink($expr,$package, $file = false,$text = false)
+ {
+ $a = Converter::getDefineLink($expr,$package,$file);
+ if (!$a) return false;
+ return $this->returnSee($a, $text);
+ }
+
+ /**
+ * @param string name of global variable
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the global variable's documentation
+ * @see parent::getGlobalLink()
+ */
+ function getGlobalLink($expr,$package, $file = false,$text = false)
+ {
+ $a = Converter::getGlobalLink($expr,$package,$file);
+ if (!$a) return false;
+ return $this->returnSee($a, $text);
+ }
+
+ /**
+ * @param string name of procedural page
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the procedural page's documentation
+ * @see parent::getPageLink()
+ */
+ function getPageLink($expr,$package, $path = false,$text = false)
+ {
+ $a = Converter::getPageLink($expr,$package,$path);
+ if (!$a) return false;
+ return $this->returnSee($a, $text);
+ }
+
+ /**
+ * @param string name of method
+ * @param string class containing method
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the method's documentation
+ * @see parent::getMethodLink()
+ */
+ function getMethodLink($expr,$class,$package, $file = false,$text = false)
+ {
+ $a = Converter::getMethodLink($expr,$class,$package,$file);
+ if (!$a) return false;
+ return $this->returnSee($a, $text);
+ }
+
+ /**
+ * @param string name of var
+ * @param string class containing var
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the var's documentation
+ * @see parent::getVarLink()
+ */
+ function getVarLink($expr,$class,$package, $file = false,$text = false)
+ {
+ $a = Converter::getVarLink($expr,$class,$package,$file);
+ if (!$a) return false;
+ return $this->returnSee($a, $text);
+ }
+
+ /**
+ * @param string name of class constant
+ * @param string class containing class constant
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the var's documentation
+ * @see parent::getVarLink()
+ */
+ function getConstLink($expr,$class,$package, $file = false,$text = false)
+ {
+ $a = Converter::getConstLink($expr,$class,$package,$file);
+ if (!$a) return false;
+ return $this->returnSee($a, $text);
+ }
+
+ /**
+ * does a nat case sort on the specified second level value of the array
+ *
+ * @param mixed $a
+ * @param mixed $b
+ * @return int
+ */
+ function rcNatCmp ($a, $b)
+ {
+ $aa = strtoupper($a[$this->rcnatcmpkey]);
+ $bb = strtoupper($b[$this->rcnatcmpkey]);
+
+ return strnatcasecmp($aa, $bb);
+ }
+
+ /**
+ * does a nat case sort on the specified second level value of the array.
+ * this one puts constructors first
+ *
+ * @param mixed $a
+ * @param mixed $b
+ * @return int
+ */
+ function rcNatCmp1 ($a, $b)
+ {
+ $aa = strtoupper($a[$this->rcnatcmpkey]);
+ $bb = strtoupper($b[$this->rcnatcmpkey]);
+
+ if (strpos($aa,'CONSTRUCTOR') === 0)
+ {
+ return -1;
+ }
+ if (strpos($bb,'CONSTRUCTOR') === 0)
+ {
+ return 1;
+ }
+ if (strpos($aa,strtoupper($this->class)) === 0)
+ {
+ return -1;
+ }
+ if (strpos($bb,strtoupper($this->class)) === 0)
+ {
+ return -1;
+ }
+ return strnatcasecmp($aa, $bb);
+ }
+
+ /**
+ * This function is not used by HTMLdefaultConverter, but is required by Converter
+ */
+ function Output()
+ {
+ }
+}
+
+/**
+ * @access private
+ * @global string name of the package to set as the first package
+ */
+function HTMLSmarty_pindexcmp($a, $b)
+{
+ global $phpDocumentor_DefaultPackageName;
+ if ($a['title'] == $phpDocumentor_DefaultPackageName) return -1;
+ if ($b['title'] == $phpDocumentor_DefaultPackageName) return 1;
+ return strnatcasecmp($a['title'],$b['title']);
+}
+
+/** @access private */
+function HTMLSmarty_lettersort($a, $b)
+{
+ return strnatcasecmp($a['letter'],$b['letter']);
+}
+
+/** @access private */
+function HTMLSmarty_outputfilter($src, &$smarty)
+{
+ return str_replace('{$subdir}',$smarty->_tpl_vars['subdir'],$src);
+}
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/options.ini b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/options.ini
new file mode 100644
index 00000000..4566db60
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/options.ini
@@ -0,0 +1,577 @@
+preservedocbooktags = false
+
+;; used to highlight the {@source} inline tag, @filesource tag, and @example tag
+[highlightSourceTokens]
+;; format:
+;; T_CONSTANTNAME = open
+;; /T_CONSTANTNAME = close
+
+T_INCLUDE = <span class="src-inc">
+/T_INCLUDE = </span>
+T_INCLUDE_ONCE = <span class="src-inc">
+/T_INCLUDE_ONCE = </span>
+T_REQUIRE_ONCE = <span class="src-inc">
+/T_REQUIRE_ONCE = </span>
+T_REQUIRE_ONCE = <span class="src-inc">
+/T_REQUIRE_ONCE = </span>
+
+T_CONSTANT_ENCAPSED_STRING = <span class="src-str">
+/T_CONSTANT_ENCAPSED_STRING = </span>
+T_STRING_VARNAME = <span class="src-str">
+/T_STRING_VARNAME = </span>
+
+T_STRING = <span class="src-id">
+/T_STRING = </span>
+
+T_DNUMBER = <span class="src-num">
+/T_DNUMBER = </span>
+T_LNUMBER = <span class="src-num">
+/T_LNUMBER = </span>
+
+T_VARIABLE = <span class="src-var">
+/T_VARIABLE = </span>
+
+T_COMMENT = <span class="src-comm">
+/T_COMMENT = </span>
+T_ML_COMMENT = <span class="src-comm">
+/T_ML_COMMENT = </span>
+
+T_OBJECT_OPERATOR = <span class="src-sym">
+/T_OBJECT_OPERATOR = </span>
+
+T_ABSTRACT = <span class="src-key">
+/T_ABSTRACT = </span>
+T_CLONE = <span class="src-key">
+/T_CLONE = </span>
+T_HALT_COMPILER = <span class="src-key">
+/T_HALT_COMPILER = </span>
+T_ARRAY = <span class="src-key">
+/T_ARRAY = </span>
+T_AS = <span class="src-key">
+/T_AS = </span>
+T_BREAK = <span class="src-key">
+/T_BREAK = </span>
+T_CLASS = <span class="src-key">
+/T_CLASS = </span>
+T_CASE = <span class="src-key">
+/T_CASE = </span>
+T_CONST = <span class="src-key">
+/T_CONST = </span>
+T_CONTINUE = <span class="src-key">
+/T_CONTINUE = </span>
+T_DECLARE = <span class="src-key">
+/T_DECLARE = </span>
+T_DEFAULT = <span class="src-key">
+/T_DEFAULT = </span>
+T_ELSE = <span class="src-key">
+/T_ELSE = </span>
+T_ELSEIF = <span class="src-key">
+/T_ELSEIF = </span>
+T_EMPTY = <span class="src-key">
+/T_EMPTY = </span>
+T_ENDDECLARE = <span class="src-key">
+/T_ENDDECLARE = </span>
+T_ENDFOR = <span class="src-key">
+/T_ENDFOR = </span>
+T_ENDSWITCH = <span class="src-key">
+/T_ENDSWITCH = </span>
+T_ENDFOREACH = <span class="src-key">
+/T_ENDFOREACH = </span>
+T_ENDIF = <span class="src-key">
+/T_ENDIF = </span>
+T_ENDWHILE = <span class="src-key">
+/T_ENDWHILE = </span>
+T_EXIT = <span class="src-key">
+/T_EXIT = </span>
+T_EXTENDS = <span class="src-key">
+/T_EXTENDS = </span>
+T_FINAL = <span class="src-key">
+/T_FINAL = </span>
+T_FOR = <span class="src-key">
+/T_FOR = </span>
+T_FOREACH = <span class="src-key">
+/T_FOREACH = </span>
+T_FUNCTION = <span class="src-key">
+/T_FUNCTION = </span>
+T_GLOBAL = <span class="src-key">
+/T_GLOBAL = </span>
+T_IF = <span class="src-key">
+/T_IF = </span>
+T_IMPLEMENTS = <span class="src-key">
+/T_IMPLEMENTS = </span>
+T_INTERFACE = <span class="src-key">
+/T_INTERFACE = </span>
+T_LOGICAL_AND = <span class="src-key">
+/T_LOGICAL_AND = </span>
+T_LOGICAL_OR = <span class="src-key">
+/T_LOGICAL_OR = </span>
+T_LOGICAL_XOR = <span class="src-key">
+/T_LOGICAL_XOR = </span>
+T_NEW = <span class="src-key">
+/T_NEW = </span>
+T_PRIVATE = <span class="src-key">
+/T_PRIVATE = </span>
+T_PROTECTED = <span class="src-key">
+/T_PROTECTED = </span>
+T_PUBLIC = <span class="src-key">
+/T_PUBLIC = </span>
+T_RETURN = <span class="src-key">
+/T_RETURN = </span>
+T_STATIC = <span class="src-key">
+/T_STATIC = </span>
+T_SWITCH = <span class="src-key">
+/T_SWITCH = </span>
+T_VAR = <span class="src-key">
+/T_VAR = </span>
+T_WHILE = <span class="src-key">
+/T_WHILE = </span>
+
+T_DOUBLE_COLON = <span class="src-sym">
+/T_DOUBLE_COLON = </span>
+
+T_OPEN_TAG = <span class="src-php">
+/T_OPEN_TAG = </span>
+T_OPEN_TAG_WITH_ECHO = <span class="src-php">
+/T_OPEN_TAG_WITH_ECHO = </span>
+T_CLOSE_TAG = <span class="src-php">
+/T_CLOSE_TAG = </span>
+
+
+[highlightSource]
+;; this is for highlighting things that aren't tokens like "&"
+;; format:
+;; word = open
+;; /word = close
+@ = <span class="src-sym">
+/@ = </span>
+& = <span class="src-sym">
+/& = </span>
+[ = <span class="src-sym">
+/[ = </span>
+] = <span class="src-sym">
+/] = </span>
+! = <span class="src-sym">
+/! = </span>
+";" = <span class="src-sym">
+/; = </span>
+( = <span class="src-sym">
+/( = </span>
+) = <span class="src-sym">
+/) = </span>
+, = <span class="src-sym">
+/, = </span>
+{ = <span class="src-sym">
+/{ = </span>
+} = <span class="src-sym">
+/} = </span>
+""" = <span class="src-str">
+/" = </span>
+
+[highlightDocBlockSourceTokens]
+;; this is for docblock tokens, using by phpDocumentor_HighlightParser
+;; tagphptype is for "string" in @param string description, for example
+docblock = <span class="src-doc">
+/docblock = </span>
+tagphptype = <span class="src-doc-type">
+/tagphptype = </span>
+tagvarname = <span class="src-doc-var">
+/tagvarname = </span>
+coretag = <span class="src-doc-coretag">
+/coretag = </span>
+tag = <span class="src-doc-tag">
+/tag = </span>
+inlinetag = <span class="src-doc-inlinetag">
+/inlinetag = </span>
+internal = <span class="src-doc-internal">
+/internal = </span>
+closetemplate = <span class="src-doc-close-template">
+/closetemplate = </span>
+docblocktemplate = <span class="src-doc-template">
+/docblocktemplate = </span>
+
+[highlightTutorialSourceTokens]
+;; this is for XML DocBook-based tutorials, highlighted by phpDocumentor_TutorialHighlightParser
+;; <tag>
+opentag = <span class="tute-tag">
+/opentag = </span>
+;; </tag>
+closetag = <span class="tute-tag">
+/closetag = </span>
+;; <tag attribute="value">
+attribute = <span class="tute-attribute-name">
+/attribute = </span>
+;; <tag attribute="value">
+attributevalue = <span class="tute-attribute-value">
+/attributevalue = </span>
+;; &entity;
+entity = <span class="tute-entity">
+/entity = </span>
+;; <!-- comment -->
+comment = <span class="tute-comment">
+/comment = </span>
+;; {@inline tag}
+itag = <span class="tute-inline-tag">
+/itag = </span>
+
+;; used for translation of html in DocBlocks
+[desctranslate]
+ul = <ul>
+/ul = </ul>
+ol = <ol>
+/ol = </ol>
+li = <li>
+/li = </li>
+code = <div class="listing"><pre>
+/code = </pre></div>
+var = <var>
+/var = </var>
+samp = <samp>
+/samp = </samp>
+kbd = <kbd>
+/kbd = </kbd>
+pre = <pre>
+/pre = </pre>
+p = <p>
+/p = </p>
+b = <strong>
+/b = </strong>
+i = <em>
+/i = </em>
+br = <br />
+
+[ppage]
+;; this is the DocBook package page translation section. All DocBook tags
+;; that have a corresponding html tag must be listed here. Entities should
+;; also be listed here
+;;
+;; examples:
+;; 1)
+;; tagname = newtagname
+;;
+;; This is the simplest case, where all attributes will be added into the
+;; starting tag and the ending tag will be html/xml style </tranlatedtagname>
+;; <tagname></tagname> becomes <newtagname></newtagname> and
+;; <tagname attr="value"></tagname> becomes
+;; <newtagname attr="value"></newtagname>
+;;
+;; 2)
+;; tagname = newtagname
+;; tagname->attr = newattrname
+;;
+;; in this case, everything will be like the first case, except tags like:
+;; <tagname attr="value"></tagname> will become
+;; <newtagname newattrname="value"></newtagname>
+;;
+;; 3)
+;; tagname = newtagname
+;; tagname->attr = newattrname
+;; tagname->attr+value = newvalue
+;;
+;; in this case, the value is also translated to another. This can be useful
+;; for instances such as focus="middle" changing to align="center" or something
+;; of that nature.
+;; <tagname attr="value"></tagname> will become
+;; <newtagname newattrname="newvalue"></newtagname>
+;;
+;; 4)
+;; tagname = newtagname
+;; tagname->attr1 = newattrname
+;; tagname->attr2 = newattrname
+;; tagname->attr1+value|attr2+value = newvalue
+;;
+;; in this case, two attributes combine to make one new attribute, and the combined
+;; value is translated into a new value
+;; <tagname attr1="value1" attr2="value2"></tagname> will become
+;; <newtagname newattrname="newvalue"></newtagname>
+;;
+;; 5)
+;; tagname = newtagname
+;; tagname!attr = dummy
+;;
+;; here, the attribute will be ignored. dummy is not used and may be any value
+;; <tagname attr="value"></tagname> will become
+;; <newtagname></newtagname>
+;;
+;; 6)
+;; tagname = newtagname
+;; tagname! = dummy
+;;
+;; here, all attributes will be ignored. dummy is not used and may be any value
+;; <tagname attr1="value" attr2="foo"></tagname> will become
+;; <newtagname></newtagname>
+;;
+;; 7)
+;; tagname = newtagname
+;; tagname/ = 1
+;;
+;; here, the tag will be translated as a single tag with no closing tag, and all
+;; attributes
+;; <tagname attr="val">{text text}</tagname> will become
+;; <newtagname attr="val" />
+;;
+;; 8)
+;; tagname = <starttaginfo />
+;; /tagname = closetagtext
+;;
+;; in this case, the text <starttaginfo> will be inserted exactly as entered for
+;; <tagname> and closetagtext for </tagname>
+;; <tagname attr="val"></tagname> will become
+;; <starttaginfo />closetagtext
+;;
+;; 9)
+;; $attr$my_attribute = newattrname
+;;
+;; tagname = newtagname
+;;
+;; in this case, all occurences of my_attribute in any tag will be changed to
+;; newattrname. This is useful for changing things like role="php" to
+;; class="php," for example. Note that the text "$attr$" MUST be on the line
+;; start for phpDocumentor to recognize it.
+;;
+;; 10)
+;; &entity; = translation text
+;; &quot; = &quot;
+;; &quot; = """
+;; &lt; = <
+;;
+;; Use this to control translation of entities to their appropriate values
+
+&nbsp; = &nbsp;
+&quot; = &quot;
+&rdquo; = &rdquo;
+&ldquo; = &ldquo;
+&amp; = &amp;
+&lt; = &lt;
+&gt; = &gt;
+&copy; = &copy;
+
+$attr$role = class
+
+abbrev = abbr
+
+blockquote = blockquote
+
+arg = span
+arg->choice = class
+
+author = <span class="author">
+/author = </span>
+author! = 0
+
+authorblurb = <div class="author-blurb">
+/authorblurb = </div>
+
+authorgroup = <div class="authors"><h2 class="title">Authors</h2>
+/authorgroup = </div>
+authorgroup! = 0
+
+caution = <span class="warning">
+/caution = </span>
+caution! = 0
+
+cmdsynopsis = <div class="cmd-synopsis">
+/cmdsynopsis = </div>
+
+command = <span class="cmd-title">
+/command = </span>
+
+copyright = <div class="notes">
+/copyright = </div>
+
+emphasis = strong
+
+example = <pre class="example">
+/example = </pre>
+example! = 0
+
+function =
+/function = ()
+
+formalpara = p
+
+graphic = img
+graphic->fileref = src
+graphic/ =
+
+important = strong
+
+informalequation = blockquote
+
+informalexample = div
+
+inlineequation = em
+
+itemizedlist = ul
+
+listitem = li
+
+literal = code
+
+literallayout = span
+
+option = " "
+/option =
+
+orderedlist = ol
+
+para = p
+
+programlisting = <pre class="listing">
+/programlisting = </pre>
+programlisting! = 0
+
+refentry = div
+
+refnamediv = <div class="ref-title-box">
+/refnamediv = </div>
+refnamediv! = 0
+
+refname = <h1 class="ref-title">
+/refname = </h1>
+
+refpurpose = <h2 class="ref-purpose">
+/refpurpose = </h2>
+
+refsynopsisdiv = <div class="ref-synopsis">
+/refsynopsisdiv = </div>
+refsynopsisdiv! = 0
+
+refsect1 = span
+
+refsect2 =
+/refsect2 = <hr />
+
+refsect3 =
+/refsect3 = <br />
+
+releaseinfo = <div class="release-info">(
+/releaseinfo = )</div>
+
+simpara =
+/simpara = <br />
+simpara! = 0
+
+subscript = sub
+
+superscript = super
+
+table = table
+
+table->colsep = rules
+table->rowsep = rules
+table->colsep+1|rowsep+1 = all
+table->colsep+1|rowsep+0 = cols
+table->colsep+0|rowsep+1 = rows
+
+table->frame = frame
+table->frame+all = border
+table->frame+none = void
+table->frame+sides = vsides
+table->frame+top = above
+table->frame+topbot = hsides
+
+thead = thead
+
+tfoot = tfoot
+
+tbody = tbody
+
+colspec = col
+
+tgroup = colgroup
+tgroup/ = 1
+tgroup->cols = span
+
+row = tr
+
+entry = td
+entry->morerows = colspan
+entry->morerows+1 = 2
+entry->morerows+2 = 3
+entry->morerows+3 = 4
+entry->morerows+4 = 5
+entry->morerows+5 = 6
+entry->morerows+6 = 7
+entry->morerows+7 = 8
+entry->morerows+8 = 9
+entry->morerows+9 = 10
+entry->morerows+10 = 11
+;; add more if you need more colspans
+
+warning = <span class="warning">
+/warning = </span>
+warning! = 0
+
+;; now begins the attributes that should be tags in cdata
+[$attr$id]
+open = a
+;close = /a
+cdata! = true
+quotevalues = true
+separator = "="
+;separateall = true
+$id = name
+
+;; now begins the sections that deal with <title>
+[refsynopsisdiv_title]
+;tag_attr = true
+;attr_name = title
+cdata_start = true
+;cdata_end = true
+open = <h1 class="title">
+close = </h1>
+
+[refsect1_title]
+;tag_attr = true
+;attr_name = title
+cdata_start = true
+;cdata_end = true
+open = <h2 class="title">
+close = </h2>
+
+[refsect2_title]
+;tag_attr = true
+;attr_name = title
+cdata_start = true
+;cdata_end = true
+open = <h3 class="title">
+close = </h3>
+
+[refsect3_title]
+;tag_attr = true
+;attr_name = title
+cdata_start = true
+;cdata_end = true
+open = <h4 class="title">
+close = </h4>
+
+[para_title]
+;tag_attr = true
+;attr_name = title
+cdata_start = true
+;cdata_end = true
+open = <div class="title">
+close = </div>
+
+[formalpara_title]
+;tag_attr = true
+;attr_name = title
+cdata_start = true
+;cdata_end = true
+open = <div class="title">
+close = </div>
+
+[example_title]
+;tag_attr = true
+;attr_name = title
+;cdata_start = true
+cdata_end = true
+open = </td></tr><tr><td><strong>
+close = </strong>
+
+[table_title]
+;tag_attr = true
+;attr_name = true
+cdata_start = true
+open = <caption>
+close = </caption>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/__tags.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/__tags.tpl
new file mode 100644
index 00000000..221830c4
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/__tags.tpl
@@ -0,0 +1,13 @@
+<div class="tag-list">
+ {section name=tag loop=$tags}
+ {if $tags[tag].keyword != "abstract" &&
+ $tags[tag].keyword != "access" &&
+ $tags[tag].keyword != "static" &&
+ $tags[tag].keyword != "version"
+ }
+
+ <strong>{$tags[tag].keyword|capitalize}:</strong>
+ {$tags[tag].data}<br />
+ {/if}
+ {/section}
+</div>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_class_declaration.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_class_declaration.tpl
new file mode 100644
index 00000000..d7fe2f82
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_class_declaration.tpl
@@ -0,0 +1,38 @@
+<hr size="1" noshade="noshade"/>
+<div class="class-declaration">
+ {if count($tags) > 0}
+ {section name=tag loop=$tags}
+ {if $tags[tag].keyword == "abstract"}
+ abstract
+ {/if}
+ {/section}
+ {/if}
+
+ {if $is_interface}
+ interface
+ {else}
+ class
+ {/if}
+
+ <strong>{$class_name}</strong>
+
+ {if count($class_tree) > 1}
+ {section name=tree loop=$class_tree.classes}
+ {if $smarty.section.tree.last}
+ extends {$class_tree.classes[$smarty.section.tree.index_prev]}
+ {/if}
+ {/section}
+ {/if}
+
+ {if $implements}
+ <br/>
+ implements
+ {foreach item="interface" from=$implements}
+ {if !$smarty.foreach.interface.first}
+ , {$interface}
+ {else}
+ {$interface}
+ {/if}
+ {/foreach}
+ {/if}
+</div> \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_class_description.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_class_description.tpl
new file mode 100644
index 00000000..12025c1c
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_class_description.tpl
@@ -0,0 +1,7 @@
+<div class="class-description">
+ <p>{$sdesc}</p>
+
+ {if $desc != ""}{$desc}{/if}
+</div>
+
+{include file="_tags.tpl" tags=$tags}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_class_list.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_class_list.tpl
new file mode 100644
index 00000000..d6a1d398
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_class_list.tpl
@@ -0,0 +1 @@
+{eval var=$compiledclassindex} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_constant_details.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_constant_details.tpl
new file mode 100644
index 00000000..bca71e17
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_constant_details.tpl
@@ -0,0 +1,33 @@
+{if $consts}
+ <hr size="1" noshade="noshade"/>
+ <a name="constant-details"></a>
+ <table class="constant-details" cellspacing="1">
+ <tr>
+ <th>Constant Details</th>
+ </tr>
+ {section name=const loop=$consts}
+ <tr>
+ <td>
+ <a name="{$consts[const].const_dest}"></a>
+
+ <h3>{$consts[const].const_name}</h3>
+
+ <p>{$consts[const].sdesc}</p>
+
+ {if $consts[const].desc}
+ {$consts[const].desc}
+ {/if}
+
+ <div class="tag-list">
+ <h4 class="tag">Type:</h4>
+ <div class="tag-data">{include file="_get_constant_type.tpl" const=$consts[const].const_value}</div>
+ <h4 class="tag">Value:</h4>
+ <div class="tag-data">{$consts[const].const_value}</div>
+ </div>
+ {include file="_tags.tpl" tags=$consts[const].tags}
+ <p/>
+ </td>
+ </tr>
+ {/section}
+ </table>
+{/if} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_constant_summary.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_constant_summary.tpl
new file mode 100644
index 00000000..8049c4b0
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_constant_summary.tpl
@@ -0,0 +1,22 @@
+{if $consts || $iconsts}
+ <hr size="1" noshade="noshade"/>
+ <a name="constant-summary"></a>
+ <table class="constant-summary" cellspacing="1">
+ <tr>
+ <th colspan="3">Constant Summary</th>
+ </tr>
+ {section name=const loop=$consts}
+ <tr>
+ <td class="type" nowrap="nowrap">{strip}{include file="_get_constant_type.tpl" const=$consts[const].const_value}{/strip}</td>
+ <td class="name"><a href="{$consts[const].id}">{$consts[const].const_name}</a></td>
+ <td class="description" width="100%">
+ {$consts[const].sdesc}
+
+ {if $consts[const].desc}
+ {$consts[const].desc}
+ {/if}
+ </td>
+ </tr>
+ {/section}
+ </table>
+{/if} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_constructor_details.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_constructor_details.tpl
new file mode 100644
index 00000000..ec4fd0a2
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_constructor_details.tpl
@@ -0,0 +1,55 @@
+{if $methods}
+ {section name=method loop=$methods}
+ {if $methods[method].function_name == "__construct"}
+ <hr size="1" noshade="noshade"/>
+ <a name="sec-method"></a>
+ <table class="method-details" cellspacing="1">
+ <tr>
+ <th colspan="3">Constructor Details</th>
+ </tr>
+ <tr>
+ <td class="method-data">
+ <a name="{$methods[method].method_dest}"></a>
+
+ <h2>{$methods[method].function_name}</h2>
+
+ <table class="method-detail" cellspacing="0">
+ <tr>
+ <td nowrap="nowrap">{strip}
+ {if $methods[method].access == "protected"}
+ protected&nbsp;
+ {/if}
+
+ {if $methods[method].access == "public"}
+ public&nbsp;
+ {/if}
+
+ {if $methods[method].abstract == "1"}
+ abstract&nbsp;
+ {/if}
+
+ {if $methods[method].static == "1"}
+ static&nbsp;
+ {/if}
+
+ <strong>{$methods[method].function_name}</strong>
+ {/strip}</td>
+ <td nowrap="nowrap">{strip}
+ {$methods[method].ifunction_call.params}
+ {/strip}</td>
+ </tr>
+ </table>
+
+ <p>{$methods[method].sdesc}</p>
+
+ {if $methods[method].desc}
+ {$methods[method].desc}
+ {/if}
+
+ {include file="_tags.tpl" tags=$methods[method].tags}
+ </td>
+ </tr>
+ </table>
+ {/if}
+ {/section}
+{/if}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_constructor_summary.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_constructor_summary.tpl
new file mode 100644
index 00000000..8819f63e
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_constructor_summary.tpl
@@ -0,0 +1,25 @@
+{if $methods}
+ {section name=method loop=$methods}
+ {if $methods[method].function_name == "__construct"}
+ <hr size="1" noshade="noshade"/>
+ <a name="constructor-summary"></a>
+ <table class="method-summary" cellspacing="1">
+ <tr>
+ <th colspan="2">Constructor Summary</th>
+ </tr>
+ <tr>
+ <td class="type" nowrap="nowrap" width="1%">{$methods[method].access}</td>
+ <td>
+ <div class="declaration">
+ <a href="{$methods[method].id}">{$methods[method].function_name}</a>
+ {$methods[method].ifunction_call.params}
+ </div>
+ <div class="description">
+ {$methods[method].sdesc}
+ </div>
+ </td>
+ </tr>
+ </table>
+ {/if}
+ {/section}
+{/if}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_destructor_details.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_destructor_details.tpl
new file mode 100644
index 00000000..3cb5534a
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_destructor_details.tpl
@@ -0,0 +1,55 @@
+{if $methods}
+ {section name=method loop=$methods}
+ {if $methods[method].function_name == "__destruct"}
+ <hr size="1" noshade="noshade"/>
+ <a name="sec-method"></a>
+ <table class="method-details" cellspacing="1">
+ <tr>
+ <th colspan="3">Destructor Details</th>
+ </tr>
+ <tr>
+ <td class="method-data">
+ <a name="{$methods[method].method_dest}"></a>
+
+ <h2>{$methods[method].function_name}</h2>
+
+ <table class="method-detail" cellspacing="0">
+ <tr>
+ <td nowrap="nowrap">{strip}
+ {if $methods[method].access == "protected"}
+ protected&nbsp;
+ {/if}
+
+ {if $methods[method].access == "public"}
+ public&nbsp;
+ {/if}
+
+ {if $methods[method].abstract == "1"}
+ abstract&nbsp;
+ {/if}
+
+ {if $methods[method].static == "1"}
+ static&nbsp;
+ {/if}
+
+ <strong>{$methods[method].function_name}</strong>
+ {/strip}</td>
+ <td nowrap="nowrap">{strip}
+ {build_argument_list args=$methods[method].ifunction_call.params style="vertical"}
+ {/strip}</td>
+ </tr>
+ </table>
+
+ <p>{$methods[method].sdesc}</p>
+
+ {if $methods[method].desc}
+ {$methods[method].desc}
+ {/if}
+
+ {include file="_tags.tpl" tags=$methods[method].tags}
+ </td>
+ </tr>
+ </table>
+ {/if}
+ {/section}
+{/if} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_destructor_summary.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_destructor_summary.tpl
new file mode 100644
index 00000000..53e8f1d2
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_destructor_summary.tpl
@@ -0,0 +1,27 @@
+{if $methods}
+ {section name=method loop=$methods}
+ {if $methods[method].function_name == "__destruct"}
+ <hr size="1" noshade="noshade"/>
+ <a name="desructor-summary"></a>
+ <table class="method-summary" cellspacing="1">
+ <tr>
+ <th colspan="2">Destructor Summary</th>
+ </tr>
+ <tr>
+ <td class="type" nowrap="nowrap" width="1%">{strip}
+ {$methods[method].access}
+ {/strip}</td>
+ <td>
+ <div class="declaration">{strip}
+ <a href="{$methods[method].id}">{$methods[method].function_name}</a>
+ {$methods[method].ifunction_call.params}
+ {/strip}</div>
+ <div class="description">
+ {$methods[method].sdesc}
+ </div>
+ </td>
+ </tr>
+ </table>
+ {/if}
+ {/section}
+{/if}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_footer.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_footer.tpl
new file mode 100644
index 00000000..0c2eddc2
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_footer.tpl
@@ -0,0 +1 @@
+</div>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_get_constant_type.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_get_constant_type.tpl
new file mode 100644
index 00000000..48301da4
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_get_constant_type.tpl
@@ -0,0 +1,10 @@
+{if is_numeric(strtolower(trim($const)))}
+ int
+{elseif strtolower(trim($const)) == "true" ||
+ strtolower(trim($const)) == "false"}
+ bool
+{elseif strtolower(trim($const)) == "null"}
+ null
+{else}
+ string
+{/if} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_header.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_header.tpl
new file mode 100644
index 00000000..f92571a4
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_header.tpl
@@ -0,0 +1,4 @@
+<div id="bar" nowrap="nowrap">
+ {include file="_class_list.tpl"}
+</div>
+<div id="content1">
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_inherited_constants.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_inherited_constants.tpl
new file mode 100644
index 00000000..66c37633
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_inherited_constants.tpl
@@ -0,0 +1,34 @@
+{if $iconsts}
+ {section name=iconst loop=$iconsts}
+ <table class="inherited-constants" cellspacing="1">
+ <tr>
+ <th>Constants Inherited From {$iconsts[iconst].parent_class}</th>
+ </tr>
+ <tr>
+ <td>
+ {assign var="_consts" value=""}
+
+ {section name=_const loop=$iconsts[iconst].iconsts}
+ {if $_consts != ""},
+ {* append var="_consts" value=", "*}
+ {/if}
+ <a href="{$href}">{$iconsts[iconst].iconsts[_const].name}</a>{if !$smarty.section.name.last},{/if}
+ {*
+ {extract_attribute attribute="href"
+ element=$iconsts[iconst].iconsts[_const].link
+ var="href" append="no"}
+
+ {append var="_consts" value="<a href=\""}
+ {append var="_consts" value=$href}
+ {append var="_consts" value="\">"}
+ {append var="_consts" value=$iconsts[iconst].iconsts[_const].name}
+ {append var="_consts" value="</a>"}
+ *}
+{/section}
+
+ {*$_consts*}
+ </td>
+ </tr>
+ </table>
+ {/section}
+{/if}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_inherited_methods.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_inherited_methods.tpl
new file mode 100644
index 00000000..55aafb17
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_inherited_methods.tpl
@@ -0,0 +1,42 @@
+{if $imethods}
+ {section name=imethod loop=$imethods}
+ {if count($imethods[imethod].imethods) > 1 ||
+ ($imethods[imethod].imethods[0].name != "__construct" &&
+ $imethods[imethod].imethods[0].name != "__destruct" &&
+ $imethods[imethod].imethods[0].abstract != "1")}
+ <table class="inherited-methods" cellspacing="1">
+ <tr>
+ <th>Methods Inherited From {$imethods[imethod].parent_class}</th>
+ </tr>
+ <tr>
+ <td>
+ {* assign var="_methods" value="" *}
+
+ {section name=_method loop=$imethods[imethod].imethods}
+ {if $imethods[imethod].imethods[_method].name != "__construct" &&
+ $imethods[imethod].imethods[_method].abstract != "1"}
+ {*
+ {if $_methods != ""}
+ {append var="_methods" value=", "}
+ {/if}
+
+ {extract_attribute attribute="href"
+ element=$imethods[imethod].imethods[_method].link
+ var="href" append="no"}
+
+ {append var="_methods" value="<a href=\""}
+ {append var="_methods" value=$href}
+ {append var="_methods" value="\">"}
+ {append var="_methods" value=$imethods[imethod].imethods[_method].name}
+ {append var="_methods" value="</a>"}
+ *}
+ {$imethods[imethod].imethods[_method].link}{if !$smarty.section._method.last},{/if}
+ {/if}
+ {/section}
+
+ </td>
+ </tr>
+ </table>
+ {/if}
+ {/section}
+{/if}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_inheritence_tree.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_inheritence_tree.tpl
new file mode 100644
index 00000000..471c7972
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_inheritence_tree.tpl
@@ -0,0 +1,3 @@
+<div class="inheritence-tree">
+ <pre>{section name=tree loop=$class_tree.classes}{if $smarty.section.tree.last}<strong>{$class_tree.classes[tree]}</strong>{else}{$class_tree.classes[tree]}{/if}{$class_tree.distance[tree]}{/section}</pre>
+</div> \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_method_details.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_method_details.tpl
new file mode 100644
index 00000000..b5ddfb10
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_method_details.tpl
@@ -0,0 +1,101 @@
+{if $methods && (count($methods) > 1 ||
+ ($methods[0].function_name != "__construct" &&
+ $methods[0].function_name != "__destruct"))}
+
+ <hr size="1" noshade="noshade"/>
+ <a name="method-details"></a>
+ <table class="method-details" cellspacing="1">
+ <tr>
+ <th>Method Details</th>
+ </tr>
+ {section name=method loop=$methods}
+ {if $methods[method].function_name != "__construct" &&
+ $methods[method].function_name != "__destruct"}
+
+ <tr>
+ <td class="method-data">
+
+ <a name="{$methods[method].method_dest}"></a>
+
+ <h2>{$methods[method].function_name}</h2>
+
+ <table class="method-detail" cellspacing="0">
+ <tr>
+ <td nowrap="nowrap">{strip}
+ {if $methods[method].access == "protected"}
+ protected&nbsp;
+ {/if}
+
+ {if $methods[method].access == "public"}
+ public&nbsp;
+ {/if}
+
+ {if $methods[method].abstract == 1}
+ abstract&nbsp;
+ {/if}
+
+ {if $methods[method].static == 1}
+ static&nbsp;
+ {/if}
+
+ {$methods[method].function_return}&nbsp;
+
+
+ <strong>{$methods[method].function_name}</strong>
+ {/strip}</td>
+ <td width="100%">{strip}
+ (
+ {if $methods[method].ifunction_call.params}
+ {foreach item=param name="method" from=$methods[method].ifunction_call.params}
+ {$param.type} {$param.name} {if !$smarty.foreach.method.last}, {/if}
+ {/foreach}
+
+ {/if}
+ )
+ {/strip}</td>
+ </tr>
+ </table>
+
+ <p>{$methods[method].sdesc}</p>
+
+ {if $methods[method].desc}
+ {$methods[method].desc}
+ {/if}
+ {* $methods[method]|print_r *}
+ <div class="tag-list"><table class="method-summary" cellspacing="1">
+ {if $methods[method].ifunction_call.params}
+ <tr><th colspan="3" class="small">Input</th></tr>
+ {foreach item=param name="method" from=$methods[method].ifunction_call.params}
+ <tr><td valign="top">{$param.type}</td><td valign="top"><strong>{$param.name}</strong><td valign="top">{$param.description}</td></tr>
+ {/foreach}
+ {/if}
+ {if $methods[method].tags}
+ <tr><th colspan="3" class="small">Output</th></tr>
+
+ {foreach item=param name="method" from=$methods[method].tags}
+ {if $param.keyword == "return"}
+ <tr><td valign="top">
+ {$methods[method].function_return}
+ </td><td valign="top" colspan="2">{$param.data}</td></tr>
+ {/if}
+ {/foreach}
+ {/if}
+ {if $methods[method].tags}
+ <tr><th colspan="3" class="small">Exception</th></tr>
+
+ {foreach item=param name="method" from=$methods[method].tags}
+ {if $param.keyword == "throws"}
+ <tr><td valign="top">{$param.keyword}</td><td valign="top" colspan="2">{$param.data}</td></tr>
+ {/if}
+ {/foreach}
+ {/if}
+ </table></div>
+
+ {* include file="_tags.tpl" tags=$methods[method].tags *}
+ <p/>
+ </td>
+ </tr>
+ {/if}
+ {/section}
+ </table>
+{/if}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_method_summary.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_method_summary.tpl
new file mode 100644
index 00000000..8fefd671
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_method_summary.tpl
@@ -0,0 +1,61 @@
+{if $methods || $imethods}
+ <hr size="1" noshade="noshade"/>
+ <a name="method-summary"></a>
+ <table class="method-summary" cellspacing="1">
+ <tr>
+ <th colspan="2">Method Summary</th>
+ </tr>
+ {section name=method loop=$methods}
+ {if $methods[method].function_name != "__construct" &&
+ $methods[method].function_name != "__destruct"}
+ {*
+ {if trim(substr($methods[method].function_call, 0, 1)) == "&"}
+ {assign var="ref" value="true"}
+ {assign var="css" value=" class=\"reference\""}
+ {else}
+ {assign var="ref" value="false"}
+ {assign var="css" value=""}
+ {/if}
+ *}
+ <tr>
+ <td class="type" nowrap="nowrap" width="1%">
+ {if $methods[method].access == "protected"}
+ protected&nbsp;
+ {/if}
+
+ {if $methods[method].abstract == 1}
+ abstract&nbsp;
+ {/if}
+
+ {if $methods[method].static == 1}
+ static&nbsp;
+ {/if}
+
+ {$methods[method].function_return}
+{*
+ {if $ref == "true"}
+ &nbsp;&amp;
+ {/if}
+*}
+ </td>
+ <td>
+ <div class="declaration">
+ <a href="{$methods[method].id}">{$methods[method].function_name}</a>
+ ({strip}
+ {if $methods[method].ifunction_call.params}
+ {foreach item=param name="method" from=$methods[method].ifunction_call.params}
+ {$param.type} {$param.name}{if !$smarty.foreach.method.last}, {/if}
+ {/foreach}
+
+ {/if}
+ {/strip})
+ </div>
+ <div class="description">
+ {$methods[method].sdesc}
+ </div>
+ </td>
+ </tr>
+ {/if}
+ {/section}
+ </table>
+{/if}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_sub_classes.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_sub_classes.tpl
new file mode 100644
index 00000000..e605b314
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_sub_classes.tpl
@@ -0,0 +1,19 @@
+{if $children}
+ <div class="sub-classes">
+ {if $is_interface}
+ <h4>Direct Known Sub-interfaces:</h4>
+ {else}
+ <h4>Direct Known Sub-classes:</h4>
+ {/if}
+
+ <div><small>
+ {section name=child loop=$children}
+ {if !$smarty.section.child.first}
+ , {$children[child].link}
+ {else}
+ {$children[child].link}
+ {/if}
+ {/section}
+ </small></div>
+ </div>
+{/if}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_tags.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_tags.tpl
new file mode 100644
index 00000000..221830c4
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/_tags.tpl
@@ -0,0 +1,13 @@
+<div class="tag-list">
+ {section name=tag loop=$tags}
+ {if $tags[tag].keyword != "abstract" &&
+ $tags[tag].keyword != "access" &&
+ $tags[tag].keyword != "static" &&
+ $tags[tag].keyword != "version"
+ }
+
+ <strong>{$tags[tag].keyword|capitalize}:</strong>
+ {$tags[tag].data}<br />
+ {/if}
+ {/section}
+</div>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/basicindex.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/basicindex.tpl
new file mode 100644
index 00000000..37e94343
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/basicindex.tpl
@@ -0,0 +1,18 @@
+{section name=letter loop=$letters}
+ [ <a href="{$indexname}.html#{$letters[letter].letter}">{$letters[letter].letter}</a> ]
+{/section}
+
+{section name=index loop=$index}
+ <hr />
+ <a name="{$index[index].letter}"></a>
+ <div>
+ <h2>{$index[index].letter}</h2>
+ <dl>
+ {section name=contents loop=$index[index].index}
+ <dt><b>{$index[index].index[contents].name}</b></dt>
+ <dd>{$index[index].index[contents].listing}</dd>
+ {/section}
+ </dl>
+ </div>
+ <a href="{$indexname}.html#top">top</a><br>
+{/section}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/blank.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/blank.tpl
new file mode 100644
index 00000000..b503c142
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/blank.tpl
@@ -0,0 +1,5 @@
+<div align="center"><h1>{$maintitle}</h1></div>
+<b>Welcome to {$package}!</b><br />
+<br />
+This documentation was generated by <a href="{$phpdocwebsite}">phpDocumentor v{$phpdocversion}</a><br />
+
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/class.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/class.tpl
new file mode 100644
index 00000000..e791bbba
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/class.tpl
@@ -0,0 +1,29 @@
+{include file="header.tpl" eltype="class" hasel=true contents=$classcontents}
+
+<h1>{if $is_interface}Interface{else}Class{/if} {$class_name}</h1>
+
+{*inheritence tree*}
+<div class="inheritence-tree">
+ <pre>{section name=tree loop=$class_tree.classes}{if $smarty.section.tree.last}<strong>{$class_tree.classes[tree]}</strong>{else}{$class_tree.classes[tree]}{/if}{$class_tree.distance[tree]}{/section}</pre>
+</div>
+
+{include file="_sub_classes.tpl"}
+{include file="_class_description.tpl"}
+{include file="_inherited_constants.tpl"}
+
+{include file="_constructor_summary.tpl"}
+{* include file="_destructor_summary.tpl" *}
+
+{include file="_method_summary.tpl"}
+
+{include file="_inherited_methods.tpl"}
+{include file="_constant_summary.tpl"}
+{include file="_constructor_details.tpl"}
+
+{* include file="_destructor_details.tpl" *}
+
+{include file="_method_details.tpl"}
+
+{include file="_constant_details.tpl"}
+
+{include file="footer.tpl"}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/classleft.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/classleft.tpl
new file mode 100644
index 00000000..c07fc33a
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/classleft.tpl
@@ -0,0 +1,9 @@
+{foreach key=subpackage item=files from=$classleftindex}
+ <div class="package">
+ {if $subpackage != ""}{$subpackage}<br />{/if}
+ {section name=files loop=$files}
+ {if $subpackage != ""}&nbsp;&nbsp;{/if}
+ {if $files[files].link != ''}<a href="{$files[files].link}">{/if}{$files[files].title}{if $files[files].link != ''}</a>{/if}<br />
+ {/section}
+ </div>
+{/foreach}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/classtrees.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/classtrees.tpl
new file mode 100644
index 00000000..4020e3a8
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/classtrees.tpl
@@ -0,0 +1,8 @@
+{include file="header.tpl" noleftindex=true}
+<h1>{$title}</h1>
+{section name=classtrees loop=$classtrees}
+<hr />
+<div class="classtree">Root class {$classtrees[classtrees].class}</div><br>
+{$classtrees[classtrees].class_tree}
+{/section}
+{include file="footer.tpl"}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/const.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/const.tpl
new file mode 100644
index 00000000..88856c4b
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/const.tpl
@@ -0,0 +1,14 @@
+{section name=consts loop=$consts}
+{if $show == 'summary'}
+ var {$consts[consts].const_name}, {$consts[consts].sdesc}<br>
+{else}
+ <a name="{$consts[consts].const_dest}"></a>
+ <p></p>
+ <h4>{$consts[consts].const_name} = <span class="value">{$consts[consts].const_value|replace:"\n":"<br>\n"|replace:" ":"&nbsp;"|replace:"\t":"&nbsp;&nbsp;&nbsp;"}</span></h4>
+ <p>[line {if $consts[consts].slink}{$consts[consts].slink}{else}{$consts[consts].line_number}{/if}]</p>
+ {include file="docblock.tpl" sdesc=$consts[consts].sdesc desc=$consts[consts].desc tags=$consts[consts].tags}
+
+ <br />
+ <div class="top">[ <a href="#top">Top</a> ]</div><br />
+{/if}
+{/section}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/define.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/define.tpl
new file mode 100644
index 00000000..04ce5b48
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/define.tpl
@@ -0,0 +1,32 @@
+{if count($defines) > 0}
+{section name=def loop=$defines}
+{if $show == 'summary'}
+define constant <a href="{$defines[def].id}">{$defines[def].define_name}</a> = {$defines[def].define_value}, {$defines[def].sdesc}<br>
+{else}
+ <hr />
+ <a name="{$defines[def].define_link}"></a>
+ <h3>{$defines[def].define_name} <span class="smalllinenumber">[line {if $defines[def].slink}{$defines[def].slink}{else}{$defines[def].line_number}{/if}]</span></h3>
+ <div class="tags">
+ <table width="90%" border="0" cellspacing="0" cellpadding="1"><tr><td class="code_border">
+ <table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td class="code">
+ <code>{$defines[def].define_name} = {$defines[def].define_value}</code>
+ </td></tr></table>
+ </td></tr></table>
+
+ {include file="docblock.tpl" sdesc=$defines[def].sdesc desc=$defines[def].desc tags=$defines[def].tags}
+ <br />
+ {if $defines[def].define_conflicts.conflict_type}
+ <p><b>Conflicts with defines:</b>
+ {section name=me loop=$defines[def].define_conflicts.conflicts}
+ {$defines[def].define_conflicts.conflicts[me]}<br />
+ {/section}
+ </p>
+ {/if}
+{* original {if $defines[def].define_conflicts != ""
+ <b>Conflicts:</b> {$defines[def].define_conflicts<br /><br />
+ {/if *}
+ </div>
+ <div class="top">[ <a href="#top">Top</a> ]</div><br /><br />
+{/if}
+{/section}
+{/if} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/docblock.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/docblock.tpl
new file mode 100644
index 00000000..09a603f8
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/docblock.tpl
@@ -0,0 +1,15 @@
+{if $sdesc != ''}{$sdesc|default:''}<br /><br />{/if}
+{if $desc != ''}{$desc|default:''}<br />{/if}
+{if count($tags) > 0}
+<br /><br />
+<h4>Tags:</h4>
+<div class="tags">
+<table border="0" cellspacing="0" cellpadding="0">
+{section name=tag loop=$tags}
+ <tr>
+ <td><b>{$tags[tag].keyword}:</b>&nbsp;&nbsp;</td><td>{$tags[tag].data}</td>
+ </tr>
+{/section}
+</table>
+</div>
+{/if} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/elementindex.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/elementindex.tpl
new file mode 100644
index 00000000..175a5136
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/elementindex.tpl
@@ -0,0 +1,5 @@
+{include file="header.tpl" noleftindex=true}
+<a name="top"></a>
+<h1>Index of all elements</h1>
+{include file="basicindex.tpl" indexname="elementindex"}
+{include file="footer.tpl"}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/errors.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/errors.tpl
new file mode 100644
index 00000000..1576a822
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/errors.tpl
@@ -0,0 +1,21 @@
+{include file="header.tpl" noleftindex=true}
+{section name=files loop=$files}
+<a href="#{$files[files].file}">{$files[files].file}</a><br>
+{/section}
+{foreach key=file item=issues from=$all}
+<a name="{$file}"></a>
+<h1>{$file}</h1>
+{if count($issues.warnings)}
+<h2>Warnings:</h2><br>
+{section name=warnings loop=$issues.warnings}
+<b>{$issues.warnings[warnings].name}</b> - {$issues.warnings[warnings].listing}<br>
+{/section}
+{/if}
+{if count($issues.errors)}
+<h2>Errors:</h2><br>
+{section name=errors loop=$issues.errors}
+<b>{$issues.errors[errors].name}</b> - {$issues.errors[errors].listing}<br>
+{/section}
+{/if}
+{/foreach}
+{include file="footer.tpl"}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/examplesource.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/examplesource.tpl
new file mode 100644
index 00000000..fb85654b
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/examplesource.tpl
@@ -0,0 +1,6 @@
+{include file="header.tpl" title=$title}
+<h1 align="center">{$title}</h1>
+<div class="php">
+{$source}
+</div>
+{include file="footer.tpl"} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/fileleft.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/fileleft.tpl
new file mode 100644
index 00000000..50f108d7
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/fileleft.tpl
@@ -0,0 +1,10 @@
+{foreach key=subpackage item=files from=$fileleftindex}
+ {if $subpackage != ""}subpackage <b>{$subpackage}</b><br>{/if}
+ <div class="package">
+ {section name=files loop=$files}
+ {if $files[files].link != ''}<a href="{$files[files].link}">{/if}
+ {$files[files].title}
+ {if $files[files].link != ''}</a>{/if}<br>
+ {/section}
+ </div><br />
+{/foreach}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/filesource.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/filesource.tpl
new file mode 100644
index 00000000..b23076a0
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/filesource.tpl
@@ -0,0 +1,8 @@
+{capture name="tutle"}File Source for {$name}{/capture}
+{include file="header.tpl" title=$smarty.capture.tutle}
+<h1 align="center">Source for file {$name}</h1>
+<p>Documentation is available at {$docs}</p>
+<div class="php">
+{$source}
+</div>
+{include file="footer.tpl"} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/footer.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/footer.tpl
new file mode 100644
index 00000000..0bb7a7dd
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/footer.tpl
@@ -0,0 +1,25 @@
+ <!-- content end --></td></tr></table>
+ </td>
+ </tr>
+</table>
+
+</div><!-- main -->
+
+<div id="footer">
+ <a href="/tos/">Terms of Service</a> |
+ <a href="/support/">Contact Us</a>
+ <br/>
+ Copyright &copy; 2006 by Prado Software Group.<br/>
+ <a title="Powered by PRADO" href="http://www.pradosoft.com/"><img src="http://www.pradosoft.com/images/powered.gif" style="border-width:0px;" alt="Powered by PRADO" /></a>
+</div>
+
+</div><!-- page -->
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+_uacct = "UA-186303-3";
+urchinTracker();
+</script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/function.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/function.tpl
new file mode 100644
index 00000000..098aeb17
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/function.tpl
@@ -0,0 +1,48 @@
+{section name=func loop=$functions}
+{if $show == 'summary'}
+function {$functions[func].id}, {$functions[func].sdesc}<br />
+{else}
+ <hr />
+ <a name="{$functions[func].function_dest}"></a>
+ <h3>{$functions[func].function_name} <span class="smalllinenumber">[line {if $functions[func].slink}{$functions[func].slink}{else}{$functions[func].line_number}{/if}]</span></h3>
+ <div class="function">
+ <table width="90%" border="0" cellspacing="0" cellpadding="1"><tr><td class="code_border">
+ <table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td class="code">
+ <code>{$functions[func].function_return} {if $functions[func].ifunction_call.returnsref}&amp;{/if}{$functions[func].function_name}(
+{if count($functions[func].ifunction_call.params)}
+{section name=params loop=$functions[func].ifunction_call.params}
+{if $smarty.section.params.iteration != 1}, {/if}{if $functions[func].ifunction_call.params[params].default != ''}[{/if}{$functions[func].ifunction_call.params[params].type} {$functions[func].ifunction_call.params[params].name}{if $functions[func].ifunction_call.params[params].default != ''} = {$functions[func].ifunction_call.params[params].default|escape:"html"}]{/if}
+{/section}
+{/if})</code>
+ </td></tr></table>
+ </td></tr></table><br />
+
+ {include file="docblock.tpl" sdesc=$functions[func].sdesc desc=$functions[func].desc tags=$functions[func].tags}
+ <br /><br />
+ {if $functions[func].function_conflicts.conflict_type}
+ <p><b>Conflicts with functions:</b>
+ {section name=me loop=$functions[func].function_conflicts.conflicts}
+ {$functions[func].function_conflicts.conflicts[me]}<br />
+ {/section}
+ </p>
+ {/if}
+{* original {if $functions[func].function_conflicts != ""
+ <b>Conflicts:</b> {$functions[func].function_conflicts<br /><br />
+ {/if *}
+
+ {if count($functions[func].params) > 0}
+ <h4>Parameters</h4>
+ <table border="0" cellspacing="0" cellpadding="0">
+ {section name=params loop=$functions[func].params}
+ <tr>
+ <td class="type">{$functions[func].params[params].datatype}&nbsp;&nbsp;</td>
+ <td><b>{$functions[func].params[params].var}</b>&nbsp;&nbsp;</td>
+ <td>{$functions[func].params[params].data}</td>
+ </tr>
+ {/section}
+ </table>
+ {/if}
+ <div class="top">[ <a href="#top">Top</a> ]</div><br /><br />
+ </div>
+{/if}
+{/section}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/global.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/global.tpl
new file mode 100644
index 00000000..1053f748
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/global.tpl
@@ -0,0 +1,40 @@
+{if count($globals) > 0}
+{section name=glob loop=$globals}
+{if $show == 'summary'}
+global variable <a href="{$globals[glob].id}">{$globals[glob].global_name}</a> = {$globals[glob].global_value}, {$globals[glob].sdesc}<br>
+{else}
+ <hr />
+ <a name="{$globals[glob].global_link}"></a>
+ <h4><i>{$globals[glob].global_type}</i> {$globals[glob].global_name} <span class="smalllinenumber">[line {if $globals[glob].slink}{$globals[glob].slink}{else}{$globals[glob].line_number}{/if}]</span></h4>
+ <div class="tags">
+ {if $globals[glob].sdesc != ""}
+ {include file="docblock.tpl" sdesc=$globals[glob].sdesc desc=$globals[glob].desc tags=$globals[glob].tags}
+ {/if}
+
+ <table border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td><b>Default value:</b>&nbsp;&nbsp;</td>
+ <td>{$globals[glob].global_value|replace:" ":"&nbsp;"|replace:"\n":"<br />\n"|replace:"\t":"&nbsp;&nbsp;&nbsp;"}</td>
+ </tr>
+ {if $globals[glob].global_conflicts.conflict_type}
+ <tr>
+ <td><b>Conflicts with globals:</b>&nbsp;&nbsp;</td>
+ <td>
+ {section name=me loop=$globals[glob].global_conflicts.conflicts}
+ {$globals[glob].global_conflicts.conflicts[me]}<br />
+ {/section}
+ </td>
+ </tr>
+ {/if}
+{* original {if $globals[glob].global_conflicts != ""
+ <tr>
+ <td><b>Conflicts:</b>&nbsp;&nbsp;</td>
+ <td>{$globals[glob].global_conflicts</td>
+ </tr>
+ {/if *}
+ </table>
+ </div><br /><br />
+ <div class="top">[ <a href="#top">Top</a> ]</div><br /><br />
+{/if}
+{/section}
+{/if} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/header.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/header.tpl
new file mode 100644
index 00000000..b35b0f57
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/header.tpl
@@ -0,0 +1,121 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
+
+<head>
+<title>PRADO API Manual: {$title}</title>
+
+<meta http-equiv="Expires" content="Fri, Jan 01 1900 00:00:00 GMT"/>
+<meta http-equiv="Pragma" content="no-cache"/>
+<meta http-equiv="Cache-Control" content="no-cache"/>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<meta http-equiv="content-language" content="en"/>
+<meta name="Keywords" content="PRADO PHP framework component template delphi asp.net event property OOP PHP5 object oriented programming Web programming development" />
+<meta name="Description" content="PRADO is a component-based and event-driven framework for Web application development in PHP 5." />
+<meta name="Author" content="Qiang Xue" />
+<meta name="Subject" content="Web programming, PHP framework" />
+<meta name="Language" content="en" />
+<link rel="Shortcut Icon" href="/favicon.ico" />
+<link rel="stylesheet" type="text/css" href="/css/style.css" />
+<link rel="stylesheet" type="text/css" href="/css/manual.css" />
+</head>
+<body>
+
+<div id="page">
+
+ <div id="header">
+
+ <div id="logo">
+ <img src="/css/pradoheader.gif" alt="PRADO Component Framework for PHP 5" />
+ </div>
+ <div id="mainmenu">
+ <ul>
+ <li><a href="/">Home</a></li>
+ <li><a href="/about/" >About</a></li>
+ <li><a href="/testimonials/" >Testimonials</a></li>
+ <li><a href="/demos/" >Demos</a></li>
+ <li><a href="/download/" >Download</a></li>
+ <li><a href="/documentation/" class="active">Documentation</a></li>
+ <li><a href="/community/" >Community</a></li>
+ <li><a href="/support/" >Support</a></li>
+ </ul>
+ </div><!-- mainmenu -->
+ </div><!-- header -->
+
+<div id="main">
+
+<div id="navbar">
+<ul>
+<li><a href="/tutorials/">Tutorials</a></li>
+<li><a href="/wiki/">Wiki</a></li>
+<li><a href="/docs/classdoc/">Classes</a></li>
+<li><a href="/docs/manual/" class="active">Manual</a></li>
+</ul>
+</div>
+
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr valign="top">
+ <td width="200" id="infobar">
+{if count($ric) >= 1}
+ <div id="ric">
+ {section name=ric loop=$ric}
+ <p><a href="{$subdir}{$ric[ric].file}">{$ric[ric].name}</a></p>
+ {/section}
+ </div>
+{/if}
+ <b>Packages:</b><br />
+ {section name=packagelist loop=$packageindex}
+ <a href="{$subdir}{$packageindex[packagelist].link}">{$packageindex[packagelist].title}</a><br />
+ {/section}
+ <br /><br />
+{if $tutorials}
+ <b>Tutorials/Manuals:</b><br />
+ {if $tutorials.pkg}
+ <strong>Package-level:</strong>
+ {section name=ext loop=$tutorials.pkg}
+ {$tutorials.pkg[ext]}
+ {/section}
+ {/if}
+ {if $tutorials.cls}
+ <strong>Class-level:</strong>
+ {section name=ext loop=$tutorials.cls}
+ {$tutorials.cls[ext]}
+ {/section}
+ {/if}
+ {if $tutorials.proc}
+ <strong>Procedural-level:</strong>
+ {section name=ext loop=$tutorials.proc}
+ {$tutorials.proc[ext]}
+ {/section}
+ {/if}
+{/if}
+ {if !$noleftindex}{assign var="noleftindex" value=false}{/if}
+ {if !$noleftindex}
+{*
+{if $compiledfileindex}
+ <b>Files:</b><br />
+ {eval var=$compiledfileindex}
+ {/if}
+*}
+ {if $compiledclassindex}
+ <b>Classes:</b><br />
+ {eval var=$compiledclassindex}
+ {/if}
+ {/if}
+ </td>
+ <td>
+ <table cellpadding="10" cellspacing="0" width="100%" border="0">
+ <tr><td valign="top" align="center">
+ <form type="get" action="/docs/manual/search.php">
+ Keyword <input type="text" name="keyword" size="50" />
+ <input type="submit" value="Search" />
+ </form>
+ </td></tr>
+ <tr><td valign="top"><!-- content begin -->
+{*
+{if !$hasel}{assign var="hasel" value=false}{/if}
+{if $hasel}
+<h1>{$eltype|capitalize}: {$class_name}</h1>
+Source Location: {$source_location}<br /><br />
+{/if}
+*}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/include.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/include.tpl
new file mode 100644
index 00000000..cff067db
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/include.tpl
@@ -0,0 +1,9 @@
+{if count($includes) > 0}
+<h4>Includes:</h4>
+<div class="tags">
+{section name=includes loop=$includes}
+{$includes[includes].include_name}({$includes[includes].include_value}) [line {if $includes[includes].slink}{$includes[includes].slink}{else}{$includes[includes].line_number}{/if}]<br />
+{include file="docblock.tpl" sdesc=$includes[includes].sdesc desc=$includes[includes].desc tags=$includes[includes].tags}
+{/section}
+</div>
+{/if} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/index.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/index.tpl
new file mode 100644
index 00000000..60c74b47
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/index.tpl
@@ -0,0 +1,7 @@
+{include file="header.tpl"}
+{if $contents}
+{$contents}
+{else}
+{include file="blank.tpl"}
+{/if}
+{include file="footer.tpl"}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/media/background.png b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/media/background.png
new file mode 100644
index 00000000..d6f36f60
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/media/background.png
Binary files differ
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/media/empty.png b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/media/empty.png
new file mode 100644
index 00000000..a9f29bb1
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/media/empty.png
Binary files differ
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/media/style.css b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/media/style.css
new file mode 100644
index 00000000..9419ca62
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/media/style.css
@@ -0,0 +1,197 @@
+.php {
+ padding: 1em;
+}
+/* This will not be executed by IE, so now we have a fix! */
+*[class="php-src"], *[class="php"], *[class="listing"] {
+ line-height: 0px;
+}
+
+body
+{
+ color: #000000;
+ background-color: #ffffff;
+ background-image: url("background.png");
+ background-repeat: repeat-y;
+ font-family: tahoma, verdana, arial, sans-serif;
+ font-size: 10pt;
+ margin: 0;
+ padding: 0;
+}
+
+a
+{
+ color: #000099;
+ background-color: transparent;
+ text-decoration: none;
+}
+
+a:hover
+{
+ text-decoration: underline;
+}
+
+a.menu
+{
+ color: #ffffff;
+ background-color: transparent;
+}
+
+td
+{
+ font-size: 10pt;
+}
+
+td.header_top
+{
+ color: #ffffff;
+ background-color: #9999cc;
+ font-size: 16pt;
+ font-weight: bold;
+ text-align: right;
+ padding: 10px;
+}
+
+td.header_line
+{
+ color: #ffffff;
+ background-color: #333366;
+}
+
+td.header_menu
+{
+ color: #ffffff;
+ background-color: #666699;
+ font-size: 8pt;
+ text-align: right;
+ padding: 2px;
+ padding-right: 5px;
+}
+
+td.menu
+{
+ padding: 2px;
+ padding-left: 5px;
+}
+
+td.code_border
+{
+ color: #000000;
+ background-color: #c0c0c0;
+}
+
+td.code
+{
+ color: #000000;
+ background-color: #f0f0f0;
+}
+
+td.type
+{
+ font-style: italic;
+}
+
+div.credit
+{
+ font-size: 8pt;
+ text-align: center;
+}
+
+div.package
+{
+ padding-left: 5px;
+}
+
+div.tags
+{
+ padding-left: 15px;
+}
+
+div.function
+{
+ padding-left: 15px;
+}
+
+div.top
+{
+ font-size: 8pt;
+}
+
+div.warning
+{
+ color: #ff0000;
+ background-color: transparent;
+}
+
+div.description
+{
+ padding-left: 15px;
+}
+
+hr
+{
+ height: 1px;
+ border-style: solid;
+ border-color: #c0c0c0;
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+
+span.smalllinenumber
+{
+ font-size: 8pt;
+}
+
+ul {
+ margin-left: 0px;
+ padding-left: 8px;
+}
+/* Syntax highlighting */
+
+.src-code { background-color: #f5f5f5; border: 1px solid #ccc9a4; padding: 0px; margin : 0px}
+/*.src-code pre { }*/
+
+.src-comm { color: green; }
+.src-id { }
+.src-inc { color: #0000FF; }
+.src-key { color: #0000FF; }
+.src-num { color: #CC0000; }
+.src-str { color: #66cccc; }
+.src-sym { font-weight: bold; }
+.src-var { }
+
+.src-php { font-weight: bold; }
+
+.src-doc { color: #009999 }
+.src-doc-close-template { color: #0000FF }
+.src-doc-coretag { color: #0099FF; font-weight: bold }
+.src-doc-inlinetag { color: #0099FF }
+.src-doc-internal { color: #6699cc }
+.src-doc-tag { color: #0080CC }
+.src-doc-template { color: #0000FF }
+.src-doc-type { font-style: italic }
+.src-doc-var { font-style: italic }
+
+.tute-tag { color: #009999 }
+.tute-attribute-name { color: #0000FF }
+.tute-attribute-value { color: #0099FF }
+.tute-entity { font-weight: bold; }
+.tute-comment { font-style: italic }
+.tute-inline-tag { color: #636311; font-weight: bold }
+
+/* tutorial */
+
+.authors { }
+.author { font-style: italic; font-weight: bold }
+.author-blurb { margin: .5em 0em .5em 2em; font-size: 85%; font-weight: normal; font-style: normal }
+.example { border: 1px dashed #999999; background-color: #EEEEEE; padding: .5em; }
+.listing { border: 1px dashed #999999; background-color: #EEEEEE; padding: .5em; white-space: nowrap; }
+.release-info { font-size: 85%; font-style: italic; margin: 1em 0em }
+.ref-title-box { }
+.ref-title { }
+.ref-purpose { font-style: italic; color: #666666 }
+.ref-synopsis { }
+.title { font-weight: bold; margin: 1em 0em 0em 0em; padding: .25em; border: 2px solid #999999; background-color: #9999CC }
+.cmd-synopsis { margin: 1em 0em }
+.cmd-title { font-weight: bold }
+.toc { margin-left: 2em; padding-left: 0em }
+
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/method.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/method.tpl
new file mode 100644
index 00000000..07cb76e5
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/method.tpl
@@ -0,0 +1,58 @@
+{section name=methods loop=$methods}
+{if $show == 'summary'}
+method {$methods[methods].function_call}, {$methods[methods].sdesc}<br />
+{else}
+ <hr />
+ <a name="{$methods[methods].method_dest}"></a>
+ <h3>{if $methods[methods].ifunction_call.constructor}constructor {elseif $methods[methods].ifunction_call.destructor}destructor {else}method {/if}{$methods[methods].function_name} <span class="smalllinenumber">[line {if $methods[methods].slink}{$methods[methods].slink}{else}{$methods[methods].line_number}{/if}]</span></h3>
+ <div class="function">
+ <table width="90%" border="0" cellspacing="0" cellpadding="1"><tr><td class="code_border">
+ <table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td class="code">
+ <code>{$methods[methods].function_return} {if $methods[methods].ifunction_call.returnsref}&amp;{/if}{$methods[methods].function_name}(
+{if count($methods[methods].ifunction_call.params)}
+{section name=params loop=$methods[methods].ifunction_call.params}
+{if $smarty.section.params.iteration != 1}, {/if}
+{if $methods[methods].ifunction_call.params[params].default != ''}[{/if}{$methods[methods].ifunction_call.params[params].type}
+{$methods[methods].ifunction_call.params[params].name}{if $methods[methods].ifunction_call.params[params].default != ''} = {$methods[methods].ifunction_call.params[params].default}]{/if}
+{/section}
+{/if})</code>
+ </td></tr></table>
+ </td></tr></table><br />
+
+ {include file="docblock.tpl" sdesc=$methods[methods].sdesc desc=$methods[methods].desc tags=$methods[methods].tags}<br /><br />
+
+{if $methods[methods].descmethod}
+ <p>Overridden in child classes as:<br />
+ {section name=dm loop=$methods[methods].descmethod}
+ <dl>
+ <dt>{$methods[methods].descmethod[dm].link}</dt>
+ <dd>{$methods[methods].descmethod[dm].sdesc}</dd>
+ </dl>
+ {/section}</p>
+{/if}
+{* original {if $methods[methods].descmethod != ""
+ {$methods[methods].descmethod<br /><br />
+ {/if *}
+{if $methods[methods].method_overrides}Overrides {$methods[methods].method_overrides.link} ({$methods[methods].method_overrides.sdesc|default:"parent method not documented"})<br /><br />{/if}
+{* original {if $methods[methods].method_overrides != ""
+ {$methods[methods].method_overrides<br /><br />
+ {/if *}
+
+ {if count($methods[methods].params) > 0}
+ <h4>Parameters:</h4>
+ <div class="tags">
+ <table border="0" cellspacing="0" cellpadding="0">
+ {section name=params loop=$methods[methods].params}
+ <tr>
+ <td class="type">{$methods[methods].params[params].datatype}&nbsp;&nbsp;</td>
+ <td><b>{$methods[methods].params[params].var}</b>&nbsp;&nbsp;</td>
+ <td>{$methods[methods].params[params].data}</td>
+ </tr>
+ {/section}
+ </table>
+ </div><br />
+ {/if}
+ <div class="top">[ <a href="#top">Top</a> ]</div>
+ </div>
+{/if}
+{/section}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/packages.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/packages.tpl
new file mode 100644
index 00000000..b48b6719
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/packages.tpl
@@ -0,0 +1,3 @@
+{section name=packages loop=$packages}
+<a href="{$packages[packages].link}">{$packages[packages].title}</a>
+{/section} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/page.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/page.tpl
new file mode 100644
index 00000000..6dd8683d
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/page.tpl
@@ -0,0 +1,31 @@
+{include file="header.tpl" eltype="Procedural file" class_name=$name hasel=true contents=$pagecontents}
+
+<br>
+<br>
+
+{if $classes}
+<div class="contents">
+{if $tutorial}
+<span class="maintutorial">Main Tutorial: {$tutorial}</span>
+{/if}
+<h2>Classes:</h2>
+{section name=classes loop=$classes}
+<dt>{$classes[classes].link}</dt>
+ <dd>{$classes[classes].sdesc}</dd>
+{/section}
+</div><br /><br />
+{/if}
+
+<h2>Page Details:</h2>
+{include file="docblock.tpl" type="page"}
+<br /><br />
+{include file="include.tpl"}
+<br /><br />
+{include file="global.tpl"}
+<br /><br />
+{include file="define.tpl"}
+<br />
+{include file="function.tpl"}
+
+{include file="footer.tpl"}
+
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/pkgelementindex.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/pkgelementindex.tpl
new file mode 100644
index 00000000..753ad7cf
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/pkgelementindex.tpl
@@ -0,0 +1,5 @@
+{include file="header.tpl"}
+<a name="top"></a>
+<h1>Element index for package {$package}</h1>
+{include file="basicindex.tpl" indexname=elementindex_$package}
+{include file="footer.tpl"}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/ric.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/ric.tpl
new file mode 100644
index 00000000..c4cb83f9
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/ric.tpl
@@ -0,0 +1,6 @@
+{include file="header.tpl"}
+<h1 align="center">{$name}</h1>
+<pre>
+{$contents|htmlentities}
+</pre>
+{include file="footer.tpl"} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/todolist.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/todolist.tpl
new file mode 100644
index 00000000..5ab0bca2
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/todolist.tpl
@@ -0,0 +1,14 @@
+{include file="header.tpl" title="Todo List"}
+<div align="center"><h1>Todo List</h1></div>
+{foreach from=$todos key=todopackage item=todo}
+<h2>{$todopackage}</h2>
+{section name=todo loop=$todo}
+<h3>{$todo[todo].link}</h3>
+<ul>
+{section name=t loop=$todo[todo].todos}
+ <li>{$todo[todo].todos[t]}</li>
+{/section}
+</ul>
+{/section}
+{/foreach}
+{include file="footer.tpl"} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/tutorial.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/tutorial.tpl
new file mode 100644
index 00000000..22c71c3b
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/tutorial.tpl
@@ -0,0 +1,32 @@
+{include file="header.tpl" title=$title}
+{if $nav}
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr>
+<td width="10%" align="left" valign="bottom">{if $prev}<a href=
+"{$prev}">{/if}Prev{if $prev}</a>{/if}</td>
+<td width="80%" align="center" valign="bottom"></td>
+<td width="10%" align="right" valign="bottom">{if $next}<a href=
+"{$next}">{/if}Next{if $next}</a>{/if}</td>
+</tr>
+</table>
+{/if}
+{$contents}
+{if $nav}
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+<tr>
+<td width="33%" align="left" valign="top">{if $prev}<a href="{$prev}">{/if}
+Prev{if $prev}</a>{/if}</td>
+<td width="34%" align="center" valign="top">{if $up}<a href=
+"{$up}">Up</a>{else}&nbsp;{/if}</td>
+<td width="33%" align="right" valign="top">{if $next}<a href=
+"{$next}">{/if}Next{if $next}</a>{/if}</td>
+</tr>
+
+<tr>
+<td width="33%" align="left" valign="top">{if $prevtitle}{$prevtitle}{/if}</td>
+<td width="34%" align="center" valign="top">{if $uptitle}{$uptitle}{/if}</td>
+<td width="33%" align="right" valign="top">{if $nexttitle}{$nexttitle}{/if}</td>
+</tr>
+</table>
+{/if}
+{include file="footer.tpl"} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/tutorial_toc.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/tutorial_toc.tpl
new file mode 100644
index 00000000..1db34438
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/tutorial_toc.tpl
@@ -0,0 +1,29 @@
+{if count($toc)}
+<h1 align="center">Table of Contents</h1>
+<ul>
+{section name=toc loop=$toc}
+{if $toc[toc].tagname == 'refsect1'}
+{assign var="context" value="refsect1"}
+{$toc[toc].link}<br />
+{/if}
+{if $toc[toc].tagname == 'refsect2'}
+{assign var="context" value="refsect2"}
+&nbsp;&nbsp;&nbsp;{$toc[toc].link}<br />
+{/if}
+{if $toc[toc].tagname == 'refsect3'}
+{assign var="context" value="refsect3"}
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{$toc[toc].link}<br />
+{/if}
+{if $toc[toc].tagname == 'table'}
+{if $context == 'refsect2'}&nbsp;&nbsp;&nbsp;{/if}
+{if $context == 'refsect3'}&nbsp;&nbsp;&nbsp;{/if}
+Table: {$toc[toc].link}
+{/if}
+{if $toc[toc].tagname == 'example'}
+{if $context == 'refsect2'}&nbsp;&nbsp;&nbsp;{/if}
+{if $context == 'refsect3'}&nbsp;&nbsp;&nbsp;{/if}
+Table: {$toc[toc].link}
+{/if}
+{/section}
+</ul>
+{/if} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/tutorial_tree.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/tutorial_tree.tpl
new file mode 100644
index 00000000..faf7bcef
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/tutorial_tree.tpl
@@ -0,0 +1,5 @@
+<ul>
+ <li type="square"><a href="{$main.link}">{$main.title|strip_tags}</a>
+{if $kids}{$kids}</li>{/if}
+</ul>
+
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/var.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/var.tpl
new file mode 100644
index 00000000..c76929fe
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/Smarty/templates/PradoSoft/templates/var.tpl
@@ -0,0 +1,28 @@
+{section name=vars loop=$vars}
+{if $show == 'summary'}
+ var {$vars[vars].var_name}, {$vars[vars].sdesc}<br>
+{else}
+ <a name="{$vars[vars].var_dest}"></a>
+ <p></p>
+ <h4>{$vars[vars].var_name} = <span class="value">{$vars[vars].var_default|replace:"\n":"<br>\n"|replace:" ":"&nbsp;"|replace:"\t":"&nbsp;&nbsp;&nbsp;"}</span></h4>
+ <p>[line {if $vars[vars].slink}{$vars[vars].slink}{else}{$vars[vars].line_number}{/if}]</p>
+ {include file="docblock.tpl" sdesc=$vars[vars].sdesc desc=$vars[vars].desc tags=$vars[vars].tags}
+
+ <br />
+ <div class="tags">
+ <table border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td><b>Type:</b>&nbsp;&nbsp;</td>
+ <td>{$vars[vars].var_type}</td>
+ </tr>
+ {if $vars[vars].var_overrides != ""}
+ <tr>
+ <td><b>Overrides:</b>&nbsp;&nbsp;</td>
+ <td>{$vars[vars].var_overrides}</td>
+ </tr>
+ {/if}
+ </table>
+ </div><br /><br />
+ <div class="top">[ <a href="#top">Top</a> ]</div><br />
+{/if}
+{/section}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/HTMLframesConverter.inc b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/HTMLframesConverter.inc
new file mode 100644
index 00000000..d1b8751c
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/HTMLframesConverter.inc
@@ -0,0 +1,1747 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+/**
+ * HTML original framed output converter, modified to use Smarty Template.
+ * This Converter takes output from the {@link Parser} and converts it to HTML-ready output for use with {@link Smarty}.
+ *
+ * @package Converters
+ * @subpackage HTMLframes
+ * @see parserDocBlock, parserInclude, parserPage, parserClass, parserDefine, parserFunction, parserMethod, parserVar
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: HTMLframesConverter.inc,v 1.1 2005/10/17 18:37:03 jeichorn Exp $
+ */
+/**
+ * HTML output converter.
+ * This Converter takes output from the {@link Parser} and converts it to HTML-ready output for use with {@link Smarty}.
+ *
+ * @package Converters
+ * @subpackage HTMLframes
+ * @see parserDocBlock, parserInclude, parserPage, parserClass, parserDefine, parserFunction, parserMethod, parserVar
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.2
+ * @version $Id: HTMLframesConverter.inc,v 1.1 2005/10/17 18:37:03 jeichorn Exp $
+ */
+class HTMLframesConverter extends Converter
+{
+ /**
+ * Smarty Converter wants elements sorted by type as well as alphabetically
+ * @see Converter::$sort_page_contents_by_type
+ * @var boolean
+ */
+ var $sort_page_contents_by_type = true;
+ /** @var string */
+ var $outputformat = 'HTML';
+ /** @var string */
+ var $name = 'frames';
+ /**
+ * indexes of elements by package that need to be generated
+ * @var array
+ */
+ var $leftindex = array('classes' => true, 'pages' => true, 'functions' => true, 'defines' => false, 'globals' => false);
+
+ /**
+ * output directory for the current procedural page being processed
+ * @var string
+ */
+ var $page_dir;
+
+ /**
+ * target directory passed on the command-line.
+ * {@link $targetDir} is malleable, always adding package/ and package/subpackage/ subdirectories onto it.
+ * @var string
+ */
+ var $base_dir;
+
+ /**
+ * output directory for the current class being processed
+ * @var string
+ */
+ var $class_dir;
+
+ /**
+ * array of converted package page names.
+ * Used to link to the package page in the left index
+ * @var array Format: array(package => 1)
+ */
+ var $package_pages = array();
+
+ /**
+ * controls formatting of parser informative output
+ *
+ * Converter prints:
+ * "Converting /path/to/file.php... Procedural Page Elements... Classes..."
+ * Since HTMLdefaultConverter outputs files while converting, it needs to send a \n to start a new line. However, if there
+ * is more than one class, output is messy, with multiple \n's just between class file output. This variable prevents that
+ * and is purely cosmetic
+ * @var boolean
+ */
+ var $juststarted = false;
+
+ /**
+ * contains all of the template procedural page element loop data needed for the current template
+ * @var array
+ */
+ var $current;
+
+ /**
+ * contains all of the template class element loop data needed for the current template
+ * @var array
+ */
+ var $currentclass;
+ var $wrote = false;
+ var $ric_set = array();
+
+ /**
+ * sets {@link $base_dir} to $targetDir
+ * @see Converter()
+ */
+ function HTMLframesConverter(&$allp, &$packp, &$classes, &$procpages, $po, $pp, $qm, $targetDir, $templateDir, $title)
+ {
+ Converter::Converter($allp, $packp, $classes, $procpages,$po, $pp, $qm, $targetDir, $templateDir, $title);
+ $this->base_dir = $targetDir;
+ }
+
+ /**
+ * @deprecated in favor of PHP 4.3.0+ tokenizer-based source highlighting
+ */
+ function unmangle($sourcecode)
+ {
+ $sourcecode = str_replace('<code>','<pre>',$sourcecode);
+ $sourcecode = str_replace('</code>','</pre>',$sourcecode);
+ $sourcecode = str_replace('<br />',"\n",$sourcecode);
+ $sourcecode = str_replace('&nbsp;',' ',$sourcecode);
+ $sourcecode = str_replace('&lt;','<',$sourcecode);
+ $sourcecode = str_replace('&gt;','>',$sourcecode);
+ $sourcecode = str_replace('&amp;','&',$sourcecode);
+ return $sourcecode;
+ }
+
+ /**
+ * @param string full path to the source file
+ * @param string fully highlighted source code
+ */
+ function writeSource($path, $value)
+ {
+ $templ = &$this->newSmarty();
+ $pathinfo = $this->proceduralpages->getPathInfo($path, $this);
+ $templ->assign('source',$value);
+ $templ->assign('package',$pathinfo['package']);
+ $templ->assign('subpackage',$pathinfo['subpackage']);
+ $templ->assign('name',$pathinfo['name']);
+ $templ->assign('source_loc',$pathinfo['source_loc']);
+ $templ->assign('docs',$pathinfo['docs']);
+ $templ->assign("subdir",'../');
+ $templ->register_outputfilter('HTMLframes_outputfilter');
+ $this->setTargetDir($this->getFileSourcePath($this->base_dir));
+ phpDocumentor_out("\n");
+ $this->setSourcePaths($path);
+ $this->writefile($this->getFileSourceName($path).'.html',$templ->fetch('filesource.tpl'));
+ }
+
+ function writeExample($title, $path, $source)
+ {
+ $templ = &$this->newSmarty();
+ $templ->assign('source',$source);
+ if (empty($title))
+ {
+ $title = 'example';
+ addWarning(PDERROR_EMPTY_EXAMPLE_TITLE, $path, $title);
+ }
+ $templ->assign('title',$title);
+ $templ->assign('file',$path);
+ $templ->assign("subdir",'../');
+ $templ->register_outputfilter('HTMLframes_outputfilter');
+ $this->setTargetDir($this->base_dir . PATH_DELIMITER . '__examplesource');
+ phpDocumentor_out("\n");
+ $this->writefile('exsource_'.$path.'.html',$templ->fetch('examplesource.tpl'));
+ }
+
+ function getExampleLink($path, $title)
+ {
+ return $this->returnLink('{$subdir}__examplesource' . PATH_DELIMITER . 'exsource_'.$path.'.html',$title);
+ }
+
+ function getSourceLink($path)
+ {
+ return $this->returnLink($this->getFileSourcePath('{$subdir}') .
+ PATH_DELIMITER . $this->getFileSourceName($path).'.html','Source Code for this file');
+ }
+
+ /**
+ * 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)
+ {
+ $extra = '';
+ if (strlen(str_replace("\n", '', $line)) == 0) {
+ $extra = '&nbsp;';
+ }
+ if ($path)
+ {
+ return '<li>' . $this->getSourceAnchor($path, $linenumber) .
+ str_replace("\n",'',$line) . $extra .
+ "</li>\n";
+ } else
+ {
+ return '<li>' . str_replace("\n",'',$line) . "$extra</li>\n";
+ }
+ }
+
+ /**
+ * Used to convert the <<code>> tag in a docblock
+ * @param string
+ * @param boolean
+ * @return string
+ */
+ function ProgramExample($example, $tutorial = false, $inlinesourceparse = null/*false*/,
+ $class = null/*false*/, $linenum = null/*false*/, $filesourcepath = null/*false*/)
+ {
+ return '<pre><ol>' . parent::ProgramExample($example, $tutorial, $inlinesourceparse, $class, $linenum, $filesourcepath)
+ .'</ol></pre>';
+ }
+
+ /**
+ * @param string
+ */
+ function TutorialExample($example)
+ {
+ $trans = $this->template_options['desctranslate'];
+ $this->template_options['desctranslate'] = array();
+ $example = '<ol>' . parent::TutorialExample($example)
+ .'</ol>';
+ $this->template_options['desctranslate'] = $trans;
+ 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'];
+ }
+
+ /**
+ * Retrieve a Converter-specific anchor to a segment of a source code file
+ * parsed via a {@tutorial tags.filesource.pkg} tag.
+ * @param string full path to source file
+ * @param string name of anchor
+ * @param string link text, if this is a link
+ * @param boolean returns either a link or a destination based on this
+ * parameter
+ * @return string link to an anchor, or the anchor
+ */
+ function getSourceAnchor($sourcefile,$anchor,$text = '',$link = false)
+ {
+ if ($link)
+ return $this->returnLink($this->getFileSourcePath('{$subdir}') .
+ PATH_DELIMITER . $this->getFileSourceName($sourcefile).'.html#a'.$anchor, $text);
+ else
+ return '<a name="a'.$anchor.'"></a>';
+ }
+
+ function getCurrentPageLink()
+ {
+ return $this->curname . '.html';
+ }
+
+ /**
+ * Uses htmlspecialchars() on the input
+ */
+ function postProcess($text)
+ {
+ return htmlspecialchars($text);
+ }
+
+ /**
+ * Use the template tutorial_toc.tpl to generate a table of contents for HTML
+ * @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)
+ {
+ $template = &$this->newSmarty();
+ $template->assign('toc',$toc);
+ return $template->fetch('tutorial_toc.tpl');
+ }
+
+ function &SmartyInit(&$templ)
+ {
+ if (!isset($this->package_index))
+ foreach($this->all_packages as $key => $val)
+ {
+ if (isset($this->pkg_elements[$key]))
+ {
+ if (!isset($start)) $start = $key;
+ $this->package_index[] = array('link' => "li_$key.html", 'title' => $key);
+ }
+ }
+ $templ->assign("packageindex",$this->package_index);
+ $templ->assign("subdir",'');
+ return $templ;
+ }
+
+ /**
+ * Writes out the template file of {@link $class_data} and unsets the template to save memory
+ * @see registerCurrentClass()
+ * @see parent::endClass()
+ */
+ function endClass()
+ {
+ $a = '../';
+ if (!empty($this->subpackage)) $a .= '../';
+ if ($this->juststarted)
+ {
+ $this->juststarted = false;
+ phpDocumentor_out("\n");
+ flush();
+ }
+ $this->setTargetDir($this->base_dir . PATH_DELIMITER . $this->class_dir);
+ $this->class_data->assign("subdir",$a);
+ $this->class_data->register_outputfilter('HTMLframes_outputfilter');
+ $this->writefile($this->class . '.html',$this->class_data->fetch('class.tpl'));
+ unset($this->class_data);
+ }
+
+ /**
+ * Writes out the template file of {@link $page_data} and unsets the template to save memory
+ * @see registerCurrent()
+ * @see parent::endPage()
+ */
+ function endPage()
+ {
+ $this->package = $this->curpage->package;
+ $this->subpackage = $this->curpage->subpackage;
+ $a = '../';
+ if (!empty($this->subpackage)) $a .= '../';
+ $this->setTargetDir($this->base_dir . PATH_DELIMITER . $this->page_dir);
+ $this->page_data->assign("package",$this->package);
+ $this->page_data->assign("subdir",$a);
+ $this->page_data->register_outputfilter('HTMLframes_outputfilter');
+ $this->writefile($this->page . '.html',$this->page_data->fetch('page.tpl'));
+ unset($this->page_data);
+ }
+
+ /**
+ * @param string
+ * @param string
+ * @return string &lt;a href="'.$link.'">'.$text.'</a&gt;
+ */
+ function returnLink($link,$text)
+ {
+ return '<a href="'.$link.'">'.$text.'</a>';
+ }
+
+ function makeLeft()
+ {
+ foreach($this->page_elements as $package => $o1)
+ {
+ foreach($o1 as $subpackage => $links)
+ {
+ for($i=0;$i<count($links);$i++)
+ {
+ $left[$package][$subpackage]['files'][] =
+ array("link" => $this->getId($links[$i]), "title" => $links[$i]->name);
+ }
+ }
+ }
+ foreach($this->class_elements as $package => $o1)
+ {
+ foreach($o1 as $subpackage => $links)
+ {
+ for($i=0;$i<count($links);$i++)
+ {
+ $class = $this->classes->getClassByPackage($links[$i]->name, $links[$i]->package);
+ if ($class && isset($class->docblock) && $class->docblock->hasaccess)
+ $left[$package][$subpackage]['classes'][] =
+ array("link" => $this->getId($links[$i]),
+ "title" => $links[$i]->name,
+ "access" => $class->docblock->tags['access'][0]->value,
+ "abstract" => isset ($class->docblock->tags['abstract'][0]));
+ else
+ $left[$package][$subpackage]['classes'][] =
+ array("link" => $this->getId($links[$i]),
+ "title" => $links[$i]->name,
+ "access" => 'public',
+ "abstract" => isset ($class->docblock->tags['abstract'][0]));
+ }
+ }
+ }
+ foreach($this->function_elements as $package => $o1)
+ {
+ foreach($o1 as $subpackage => $links)
+ {
+ for($i=0;$i<count($links);$i++)
+ {
+ $left[$package][$subpackage]['functions'][] =
+ array("link" => $this->getId($links[$i]), "title" => $links[$i]->name);
+ }
+ }
+ }
+ $ret = array();
+ foreach($left as $package => $r)
+ {
+ $pd = 'blank';
+ if (isset($this->package_pages[$package])) $pd = $package.'/package_'.$package.'.html';
+ if (!isset($r['']))
+ {
+ $pt = false;
+ $ptnoa = false;
+ $ptt = $package;
+ if ($t = $this->hasTutorial('pkg',$package,$package,''))
+ {
+ $pt = $t->getLink($this);
+ $ptnoa = $this->getId($t->getLink($this,true));
+ $ptt = $t->getTitle($this);
+ }
+ $tutes = array();
+ foreach($this->tutorial_tree as $root => $tr)
+ {
+ if ($tr['tutorial']->package == $package && $tr['tutorial']->subpackage == $subpackage)
+ $tutes[$tr['tutorial']->tutorial_type][] = $this->getTutorialTree($tr['tutorial']);
+ }
+ if (isset($this->childless_tutorials[$package][$subpackage]))
+ {
+ foreach($this->childless_tutorials[$package][$subpackage] as $ext => $other)
+ {
+ foreach($other as $tutorial)
+ {
+ $tutes[$tutorial->tutorial_type][] = $this->getTutorialTree($tutorial);
+ }
+ }
+ }
+ $ret[$package][] =
+ array(
+ 'package' => $package,
+ 'subpackage' => '',
+ 'packagedoc' => $pd,
+ 'packagetutorial' => $pt,
+ 'packagetutorialnoa' => $ptnoa,
+ 'packagetutorialtitle' => $ptt,
+ 'files' => array(),
+ 'functions' => array(),
+ 'classes' => array(),
+ 'tutorials' => $tutes,
+ );
+ }
+ foreach($r as $subpackage => $info)
+ {
+ $my = array();
+ $my['package'] = $package;
+ if (isset($this->package_pages[$package]))
+ $my['packagedoc'] = $pd;
+ else
+ $my['packagedoc'] = 'blank';
+ $my['subpackage'] = $subpackage;
+ if (empty($subpackage))
+ {
+ if ($t = $this->hasTutorial('pkg',$package,$package,$subpackage))
+ {
+ $my['packagetutorial'] = $t->getLink($this);
+ $my['packagetutorialnoa'] = $this->getId($t->getLink($this,true));
+ $my['packagetutorialtitle'] = $t->getTitle($this);
+ } else
+ {
+ $my['packagetutorial'] = '<a href="blank.html">No Package-Level Tutorial</a>';
+ $my['packagetutorialnoa'] = 'blank.html';
+ $my['packagetutorialtitle'] = $package;
+ }
+ } else
+ {
+ if ($t = $this->hasTutorial('pkg',$subpackage,$package,$subpackage))
+ {
+ $my['subpackagetutorial'] = $this->returnSee($this->getTutorialLink($t));
+ $my['subpackagetutorialnoa'] = $this->getId($t->getLink($this,true));
+ $my['subpackagetutorialtitle'] = $t->getTitle($this);
+ } else
+ {
+ $my['subpackagetutorial'] = false;
+ $my['subpackagetutorialnoa'] = false;
+ $my['subpackagetutorialtitle'] = $subpackage;
+ }
+ }
+ $tutes = array();
+ foreach($this->tutorial_tree as $root => $tr)
+ {
+ if ($tr['tutorial']->package == $package && $tr['tutorial']->subpackage == $subpackage)
+ {
+ $tutes[$tr['tutorial']->tutorial_type][] = $this->getTutorialTree($tr['tutorial']);
+ }
+ }
+ $my['tutorials'] = $tutes;
+ $my['files'] = $my['classes'] = $my['functions'] = array();
+ if (isset($info['files']))
+ $my['files'] = $info['files'];
+ if (isset($info['classes']))
+ $my['classes'] = $info['classes'];
+ if (isset($info['functions']))
+ $my['functions'] = $info['functions'];
+ $ret[$package][] = $my;
+ }
+ }
+ return $ret;
+ }
+
+ function getTutorialTree($tutorial,$k = false)
+ {
+ $ret = '';
+ if (is_object($tutorial)) $tree = parent::getTutorialTree($tutorial); else $tree = $tutorial;
+// debug($this->vardump_tree($tree));exit;
+ if (!$tree)
+ {
+ $template = &$this->newSmarty();
+ $template->assign('subtree',false);
+ $template->assign('name',str_replace('.','',$tutorial->name));
+ $template->assign('parent',false);
+ $template->assign('haskids',false);
+ $template->assign('kids','');
+ $link = new tutorialLink;
+ $t = $tutorial;
+ $link->addLink('',$t->path,$t->name,$t->package,$t->subpackage,$t->getTitle($this));
+ $main = array('link' => $this->getId($link), 'title' => $link->title);
+ $template->assign('main',$main);
+ return $template->fetch('tutorial_tree.tpl');
+ }
+ if (isset($tree['kids']))
+ {
+ foreach($tree['kids'] as $subtree)
+ {
+ $ret .= $this->getTutorialTree($subtree, true);
+ }
+ }
+ $template = &$this->newSmarty();
+ $template->assign('subtree',$k);
+ $template->assign('name',str_replace('.','',$tree['tutorial']->name));
+ $template->assign('parent',($k ? str_replace('.','',$tree['tutorial']->parent->name) : false));
+ $template->assign('haskids',strlen($ret));
+ $template->assign('kids',$ret);
+ $link = new tutorialLink;
+ $t = $tree['tutorial'];
+ $link->addLink('',$t->path,$t->name,$t->package,$t->subpackage,$t->getTitle($this));
+ $main = array('link' => $this->getId($link), 'title' => $link->title);
+ $template->assign('main',$main);
+ $ret = $template->fetch('tutorial_tree.tpl');
+ return $ret;
+ }
+
+ /**
+ * HTMLdefaultConverter chooses to format both package indexes and the complete index here
+ *
+ * This function formats output for the elementindex.html and pkgelementindex.html template files. It then
+ * writes them to the target directory
+ * @see generateElementIndex(), generatePkgElementIndex()
+ */
+ function formatPkgIndex()
+ {
+ list($package_indexes,$packages,$mletters) = $this->generatePkgElementIndexes();
+ for($i=0;$i<count($package_indexes);$i++)
+ {
+ $template = &$this->newSmarty();
+ $this->package = $package_indexes[$i]['package'];
+ $this->subpackage = '';
+ $template->assign("index",$package_indexes[$i]['pindex']);
+ $template->assign("package",$package_indexes[$i]['package']);
+ $template->assign("letters",$mletters[$package_indexes[$i]['package']]);
+ $template->register_outputfilter('HTMLframes_outputfilter');
+ $this->setTargetDir($this->base_dir);
+ $this->writefile('elementindex_'.$package_indexes[$i]['package'].'.html',$template->fetch('pkgelementindex.tpl'));
+ }
+ phpDocumentor_out("\n");
+ flush();
+ }
+
+ /**
+ * HTMLdefaultConverter uses this function to format template index.html and packages.html
+ *
+ * This function generates the package list from {@link $all_packages}, eliminating any
+ * packages that don't have any entries in their package index (no files at all, due to @ignore
+ * or other factors). Then it uses the default package name as the first package index to display.
+ * It sets the right pane to be either a blank file with instructions on making package-level docs,
+ * or the package-level docs for the default package.
+ * @global string Used to set the starting package to display
+ */
+ function formatIndex()
+ {
+ global $phpDocumentor_DefaultPackageName;
+ list($elindex,$mletters) = $this->generateElementIndex();
+ $template = &$this->newSmarty();
+ $template->assign("index",$elindex);
+ $template->assign("letters",$mletters);
+ $template->register_outputfilter('HTMLframes_outputfilter');
+ phpDocumentor_out("\n");
+ flush();
+ $this->setTargetDir($this->base_dir);
+ $this->writefile('elementindex.html',$template->fetch('elementindex.tpl'));
+ usort($this->package_index,"HTMLframes_pindexcmp");
+ $index = &$this->newSmarty();
+ foreach($this->all_packages as $key => $val)
+ {
+ if (isset($this->pkg_elements[$key]))
+ {
+ if (!isset($start)) $start = $key;
+ if (!isset($this->package_pages[$key])) $this->writeNewPPage($key);
+ }
+ }
+ // Created index.html
+ if (isset($this->pkg_elements[$phpDocumentor_DefaultPackageName])) $start = $phpDocumentor_DefaultPackageName;
+ $this->package = $start;
+ $this->subpackage = '';
+ $index->assign("package_count",count($this->pkg_elements));
+ if (count($this->ric_set))
+ $index->assign("package_count",2);
+ $index->assign("date",date("r",time()));
+ $index->assign("title",$this->title);
+ $index->assign("start","li_$start.html");
+ $index->register_outputfilter('HTMLframes_outputfilter');
+ if (isset($this->tutorials[$start]['']['pkg'][$start . '.pkg']))
+ {
+ $index->assign("blank",$start.'/tutorial_'.$start.'.pkg');
+ } elseif (isset($this->package_pages[$start]))
+ {
+ $index->assign("blank",$start.'/package_'.$start);
+ }
+ else
+ {
+ $index->assign("blank","blank");
+ $blank = &$this->newSmarty();
+ $blank->assign('package',$phpDocumentor_DefaultPackageName);
+ $this->setTargetDir($this->base_dir);
+ $this->writefile("blank.html",$blank->fetch('blank.tpl'));
+ }
+ phpDocumentor_out("\n");
+ flush();
+ $this->setTargetDir($this->base_dir);
+ $this->writefile("index.html",$index->fetch('index.tpl'));
+
+ // Create package index
+ $package = &$this->newSmarty();
+ $package->assign('ric',array());
+ if (isset($this->ric_set))
+ {
+ foreach($this->ric_set as $name => $u)
+ {
+ $package->append('ric',array('file' => 'ric_'.$name.'.html','name' => $name));
+ }
+ }
+ $package->assign("packages",$this->package_index);
+ $package->register_outputfilter('HTMLframes_outputfilter');
+ $this->writefile("packages.html",$package->fetch('top_frame.tpl'));
+ unset($index);
+ }
+
+ function writeNewPPage($key)
+ {
+ return;
+ $template = &$this->newSmarty();
+ $this->package = $key;
+ $this->subpackage = '';
+ $template->assign("date",date("r",time()));
+ $template->assign("title",$this->title);
+ $template->assign("package",$key);
+ $template->register_outputfilter('HTMLframes_outputfilter');
+ phpDocumentor_out("\n");
+ flush();
+ $this->setTargetDir($this->base_dir);
+
+ $this->writefile("li_$key.html",$template->fetch('index.tpl'));
+ unset($template);
+ }
+
+ /**
+ * Generate indexes for li_package.html and classtree output files
+ *
+ * This function generates the li_package.html files from the template file left.html. It does this by
+ * iterating through each of the $page_elements, $class_elements and $function_elements arrays to retrieve
+ * the pre-sorted {@link abstractLink} descendants needed for index generation. Conversion of these links to
+ * text is done by {@link returnSee()}. The {@link $local} parameter is set to false to ensure that paths are correct.
+ *
+ * Then it uses {@link generateFormattedClassTrees()} to create class trees from the template file classtrees.html. Output
+ * filename is classtrees_packagename.html. This function also unsets {@link $elements} and {@link $pkg_elements} to free
+ * up the considerable memory these two class vars use
+ * @see $page_elements, $class_elements, $function_elements
+ */
+ function formatLeftIndex()
+ {
+ phpDocumentor_out("\n");
+ flush();
+ $this->setTargetDir($this->base_dir);
+ if (0)//!isset($this->left))
+ {
+ debug("Nothing parsed, check the command-line");
+ die();
+ }
+ $x = $this->makeLeft();
+ foreach($this->all_packages as $package => $rest)
+ {
+ if (!isset($this->pkg_elements[$package])) continue;
+ $template = &$this->newSmarty();
+ $template->assign("info",$x[$package]);
+ $template->assign('package',$package);
+ $template->assign("hastutorials",isset($this->tutorials[$package]));
+ $template->assign('hastodos',count($this->todoList));
+ $template->assign('todolink','todolist.html');
+ $template->assign("classtreepage","classtrees_$package");
+ $template->assign("elementindex","elementindex_$package");
+ $template->register_outputfilter('HTMLframes_outputfilter');
+ if (isset($this->package_pages[$package]))
+ {
+ $template->assign("packagedoc",$package.'/package_' . $package . '.html');
+ } else
+ {
+ $template->assign("packagedoc",false);
+ }
+ $this->writefile("li_$package.html",$template->fetch('left_frame.tpl'));
+
+ // Create class tree page
+ $template = &$this->newSmarty();
+ $template->assign("classtrees",$this->generateFormattedClassTrees($package));
+ $template->assign("package",$package);
+ $template->register_outputfilter('HTMLframes_outputfilter');
+ $this->writefile("classtrees_$package.html",$template->fetch('classtrees.tpl'));
+ phpDocumentor_out("\n");
+ flush();
+ }
+ // free up considerable memory
+ unset($this->elements);
+ unset($this->pkg_elements);
+ }
+
+ /**
+ * This function takes an {@link abstractLink} descendant and returns an html link
+ *
+ * @param abstractLink a descendant of abstractlink should be passed, and never text
+ * @param string text to display in the link
+ * @param boolean this parameter is not used, and is deprecated
+ * @param boolean determines whether the returned text is enclosed in an <a> tag
+ */
+ function returnSee(&$element, $eltext = false, $with_a = true)
+ {
+ if (!is_object($element) || !$element) return false;
+ if (!$with_a) return $this->getId($element, false);
+ if (!$eltext)
+ {
+ $eltext = '';
+ switch($element->type)
+ {
+ case 'tutorial' :
+ $eltext = strip_tags($element->title);
+ break;
+ case 'method' :
+ case 'var' :
+ case 'const' :
+ $eltext .= $element->class.'::';
+ case 'page' :
+ case 'define' :
+ case 'class' :
+ case 'function' :
+ case 'global' :
+ default :
+ $eltext .= $element->name;
+ if ($element->type == 'function' || $element->type == 'method') $eltext .= '()';
+ break;
+ }
+ }
+ return '<a href="'.$this->getId($element).'">'.$eltext.'</a>';
+ }
+
+ function getId($element, $fullpath = true)
+ {
+ if (phpDocumentor_get_class($element) == 'parserdata')
+ {
+ $element = $this->addLink($element->parent);
+ $elp = $element->parent;
+ } elseif (is_a($element, 'parserbase'))
+ {
+ $elp = $element;
+ $element = $this->addLink($element);
+ }
+ $c = '';
+ if (!empty($element->subpackage))
+ {
+ $c = '/'.$element->subpackage;
+ }
+ $b = '{$subdir}';
+ switch ($element->type)
+ {
+ case 'page' :
+ if ($fullpath)
+ return $b.$element->package.$c.'/'.$element->fileAlias.'.html';
+ return 'top';
+ break;
+ case 'define' :
+ case 'global' :
+ case 'function' :
+ if ($fullpath)
+ return $b.$element->package.$c.'/'.$element->fileAlias.'.html#'.$element->type.$element->name;
+ return $element->type.$element->name;
+ break;
+ case 'class' :
+ if ($fullpath)
+ return $b.$element->package.$c.'/'.$element->name.'.html';
+ return 'top';
+ break;
+ case 'method' :
+ case 'var' :
+ case 'const' :
+ if ($fullpath)
+ return $b.$element->package.$c.'/'.$element->class.'.html#'.$element->type.$element->name;
+ return $element->type.$element->name;
+ break;
+ case 'tutorial' :
+ $d = '';
+ if ($element->section)
+ {
+ $d = '#'.$element->section;
+ }
+ return $b.$element->package.$c.'/tutorial_'.$element->name.'.html'.$d;
+ }
+ }
+
+ /**
+ * Convert README/INSTALL/CHANGELOG file contents to output format
+ * @param README|INSTALL|CHANGELOG
+ * @param string contents of the file
+ */
+ function Convert_RIC($name, $contents)
+ {
+ $template = &$this->newSmarty();
+ $template->assign('contents',$contents);
+ $template->assign('name',$name);
+ $this->setTargetDir($this->base_dir);
+ $this->writefile('ric_'.$name . '.html',$template->fetch('ric.tpl'));
+ $this->ric_set[$name] = true;
+ }
+
+ function ConvertTodoList()
+ {
+ $todolist = array();
+ foreach($this->todoList as $package => $alltodos)
+ {
+ foreach($alltodos as $todos)
+ {
+ $converted = array();
+ $converted['link'] = $this->returnSee($todos[0]);
+ if (!is_array($todos[1]))
+ {
+ $converted['todos'][] = $todos[1]->Convert($this);
+ } else
+ {
+ foreach($todos[1] as $todo)
+ {
+ $converted['todos'][] = $todo->Convert($this);
+ }
+ }
+ $todolist[$package][] = $converted;
+ }
+ }
+ $templ = &$this->newSmarty();
+ $templ->assign('todos',$todolist);
+ $templ->register_outputfilter('HTMLframes_outputfilter');
+ $this->setTargetDir($this->base_dir);
+ $this->writefile('todolist.html',$templ->fetch('todolist.tpl'));
+ }
+
+ /**
+ * Create errors.html template file output
+ *
+ * This method takes all parsing errors and warnings and spits them out ordered by file and line number.
+ * @global ErrorTracker We'll be using it's output facility
+ */
+ function ConvertErrorLog()
+ {
+ global $phpDocumentor_errors;
+ $allfiles = array();
+ $files = array();
+ $warnings = $phpDocumentor_errors->returnWarnings();
+ $errors = $phpDocumentor_errors->returnErrors();
+ $template = &$this->newSmarty();
+ foreach($warnings as $warning)
+ {
+ $file = '##none';
+ $linenum = 'Warning';
+ if ($warning->file)
+ {
+ $file = $warning->file;
+ $allfiles[$file] = 1;
+ $linenum .= ' on line '.$warning->linenum;
+ }
+ $files[$file]['warnings'][] = array('name' => $linenum, 'listing' => $warning->data);
+ }
+ foreach($errors as $error)
+ {
+ $file = '##none';
+ $linenum = 'Error';
+ if ($error->file)
+ {
+ $file = $error->file;
+ $allfiles[$file] = 1;
+ $linenum .= ' on line '.$error->linenum;
+ }
+ $files[$file]['errors'][] = array('name' => $linenum, 'listing' => $error->data);
+ }
+ $i=1;
+ $af = array();
+ foreach($allfiles as $file => $num)
+ {
+ $af[$i++] = $file;
+ }
+ $allfiles = $af;
+ usort($allfiles,'strnatcasecmp');
+ $allfiles[0] = "Post-parsing";
+ foreach($allfiles as $i => $a)
+ {
+ $allfiles[$i] = array('file' => $a);
+ }
+ $out = array();
+ foreach($files as $file => $data)
+ {
+ if ($file == '##none') $file = 'Post-parsing';
+ $out[$file] = $data;
+ }
+ $template->assign("files",$allfiles);
+ $template->assign("all",$out);
+ $template->assign("title","phpDocumentor Parser Errors and Warnings");
+ $this->setTargetDir($this->base_dir);
+ $this->writefile("errors.html",$template->fetch('errors.tpl'));
+ unset($template);
+ phpDocumentor_out("\n\nTo view errors and warnings, look at ".$this->base_dir. PATH_DELIMITER . "errors.html\n");
+ flush();
+ }
+
+ function getTutorialId($package,$subpackage,$tutorial,$id)
+ {
+ return $id;
+ }
+
+ function getCData($value)
+ {
+ return '<pre>'.htmlentities($value).'</pre>';
+ }
+
+ /**
+ * Converts package page and sets its package as used in {@link $package_pages}
+ * @param parserPackagePage
+ */
+ function convertPackagepage(&$element)
+ {
+ phpDocumentor_out("\n");
+ flush();
+ $this->package = $element->package;
+ $this->subpackage = '';
+ $contents = $element->Convert($this);
+ $this->package_pages[$element->package] = str_replace('{$subdir}','../',$contents);
+ phpDocumentor_out("\n");
+ flush();
+ $this->setTargetDir($this->base_dir . PATH_DELIMITER . $element->package);
+ $this->writeFile('package_'.$element->package.'.html',str_replace('{$subdir}','../',$contents));
+ }
+
+ /**
+ * @param parserTutorial
+ */
+ function convertTutorial(&$element)
+ {
+ phpDocumentor_out("\n");
+ flush();
+ $template = &parent::convertTutorial($element);
+ $a = '../';
+ if ($element->subpackage) $a .= '../';
+ $template->assign('subdir',$a);
+ $template->register_outputfilter('HTMLframes_outputfilter');
+ $contents = $template->fetch('tutorial.tpl');
+ $a = '';
+ if ($element->subpackage) $a = PATH_DELIMITER . $element->subpackage;
+ phpDocumentor_out("\n");
+ flush();
+ $this->setTargetDir($this->base_dir . PATH_DELIMITER . $element->package . $a);
+ $this->writeFile('tutorial_'.$element->name.'.html',$contents);
+ }
+
+ /**
+ * Converts class for template output
+ * @see prepareDocBlock(), generateChildClassList(), generateFormattedClassTree(), getFormattedConflicts()
+ * @see getFormattedInheritedMethods(), getFormattedInheritedVars()
+ * @param parserClass
+ */
+ function convertClass(&$element)
+ {
+ parent::convertClass($element);
+ $this->class_dir = $element->docblock->package;
+ if (!empty($element->docblock->subpackage)) $this->class_dir .= PATH_DELIMITER . $element->docblock->subpackage;
+ $a = '../';
+ if ($element->docblock->subpackage != '') $a = "../$a";
+
+ $this->class_data->assign('subdir',$a);
+ $this->class_data->assign("title","Docs For Class " . $element->getName());
+ $this->class_data->assign("page",$element->getName() . '.html');
+ }
+
+ /**
+ * Converts class variables for template output
+ * @see prepareDocBlock(), getFormattedConflicts()
+ * @param parserDefine
+ */
+ function convertVar(&$element)
+ {
+ parent::convertVar($element, array('var_dest' => $this->getId($element,false)));
+ }
+
+ /**
+ * Converts class variables for template output
+ * @see prepareDocBlock(), getFormattedConflicts()
+ * @param parserDefine
+ */
+ function convertConst(&$element)
+ {
+ parent::convertConst($element, array('const_dest' => $this->getId($element,false)));
+ }
+
+ /**
+ * Converts class methods for template output
+ * @see prepareDocBlock(), getFormattedConflicts()
+ * @param parserDefine
+ */
+ function convertMethod(&$element)
+ {
+ parent::convertMethod($element, array('method_dest' => $this->getId($element,false)));
+ }
+
+ /**
+ * Converts function for template output
+ * @see prepareDocBlock(), parserFunction::getFunctionCall(), getFormattedConflicts()
+ * @param parserFunction
+ */
+ function convertFunction(&$element)
+ {
+ $funcloc = $this->getId($this->addLink($element));
+ parent::convertFunction($element,array('function_dest' => $this->getId($element,false)));
+ }
+
+ /**
+ * Converts include elements for template output
+ * @see prepareDocBlock()
+ * @param parserInclude
+ */
+ function convertInclude(&$element)
+ {
+ parent::convertInclude($element, array('include_file' => '_'.strtr($element->getValue(),array('"' => '', "'" => '','.' => '_'))));
+ }
+
+ /**
+ * Converts defines for template output
+ * @see prepareDocBlock(), getFormattedConflicts()
+ * @param parserDefine
+ */
+ function convertDefine(&$element)
+ {
+ parent::convertDefine($element, array('define_link' => $this->getId($element,false)));
+ }
+
+ /**
+ * Converts global variables for template output
+ * @param parserGlobal
+ */
+ function convertGlobal(&$element)
+ {
+ parent::convertGlobal($element, array('global_link' => $this->getId($element,false)));
+ }
+
+ /**
+ * converts procedural pages for template output
+ * @see prepareDocBlock(), getClassesOnPage()
+ * @param parserData
+ */
+ function convertPage(&$element)
+ {
+ parent::convertPage($element);
+ $this->juststarted = true;
+ $this->page_dir = $element->parent->package;
+ if (!empty($element->parent->subpackage)) $this->page_dir .= PATH_DELIMITER . $element->parent->subpackage;
+ // registering stuff on the template
+ $this->page_data->assign("page",$this->getPageName($element) . '.html');
+ $this->page_data->assign("title","Docs for page ".$element->parent->getFile());
+ }
+
+ function getPageName(&$element)
+ {
+ if (phpDocumentor_get_class($element) == 'parserpage') return '_'.$element->getName();
+ return '_'.$element->parent->getName();
+ }
+
+ /**
+ * returns an array containing the class inheritance tree from the root object to the class
+ *
+ * @param parserClass class variable
+ * @return array Format: array(root,child,child,child,...,$class)
+ * @uses parserClass::getParentClassTree()
+ */
+
+ function generateFormattedClassTree($class)
+ {
+ $tree = $class->getParentClassTree($this);
+ $out = '';
+ if (count($tree) - 1)
+ {
+ $result = array($class->getName());
+ $parent = $tree[$class->getName()];
+ $distance[] = '';
+ while ($parent)
+ {
+ $x = $parent;
+ if (is_object($parent))
+ {
+ $subpackage = $parent->docblock->subpackage;
+ $package = $parent->docblock->package;
+ $x = $parent;
+ $x = $parent->getLink($this);
+ if (!$x) $x = $parent->getName();
+ }
+ $result[] =
+ $x;
+ $distance[] =
+ "\n%s|\n" .
+ "%s--";
+ if (is_object($parent))
+ $parent = $tree[$parent->getName()];
+ elseif (isset($tree[$parent]))
+ $parent = $tree[$parent];
+ }
+ $nbsp = ' ';
+ for($i=count($result) - 1;$i>=0;$i--)
+ {
+ $my_nbsp = '';
+ for($j=0;$j<count($result) - $i;$j++) $my_nbsp .= $nbsp;
+ $distance[$i] = sprintf($distance[$i],$my_nbsp,$my_nbsp);
+ }
+ return array('classes'=>array_reverse($result),'distance'=>array_reverse($distance));
+ } else
+ {
+ return array('classes'=>$class->getName(),'distance'=>array(''));
+ }
+ }
+
+ /** @access private */
+ function sortVar($a, $b)
+ {
+ return strnatcasecmp($a->getName(),$b->getName());
+ }
+
+ /** @access private */
+ function sortMethod($a, $b)
+ {
+ if ($a->isConstructor) return -1;
+ if ($b->isConstructor) return 1;
+ return strnatcasecmp($a->getName(),$b->getName());
+ }
+
+ /**
+ * returns a template-enabled array of class trees
+ *
+ * @param string $package package to generate a class tree for
+ * @see $roots, HTMLConverter::getRootTree()
+ */
+ function generateFormattedClassTrees($package)
+ {
+ if (!isset($this->roots[$package])) return array();
+ $roots = $trees = array();
+ $roots = $this->roots[$package];
+ for($i=0;$i<count($roots);$i++)
+ {
+ $trees[] = array('class' => $roots[$i],'class_tree' => "<ul>\n".$this->getRootTree($this->getSortedClassTreeFromClass($roots[$i],$package,''),$package)."</ul>\n");
+ }
+ return $trees;
+ }
+
+ /**
+ * return formatted class tree for the Class Trees page
+ *
+ * @param array $tree output from {@link getSortedClassTreeFromClass()}
+ * @see Classes::$definitechild, generateFormattedClassTrees()
+ * @return string
+ */
+ function getRootTree($tree,$package)
+ {
+ if (!$tree) return '';
+ $my_tree = '';
+ $cur = '#root';
+ $lastcur = array(false);
+ $kids = array();
+ $dopar = false;
+ if ($tree[$cur]['parent'])
+ {
+ $dopar = true;
+ if (!is_object($tree[$cur]['parent']))
+ {
+// debug("parent ".$tree[$cur]['parent']." not found");
+ $my_tree .= '<li>' . $tree[$cur]['parent'] .'<ul>';
+ }
+ else
+ {
+// debug("parent ".$this->returnSee($tree[$cur]['parent'])." in other package");
+ $my_tree .= '<li>' . $this->returnSee($tree[$cur]['parent']);
+ if ($tree[$cur]['parent']->package != $package) $my_tree .= ' <b>(Different package)</b><ul>';
+ }
+ }
+ do
+ {
+// fancy_debug($cur,$lastcur,$kids);
+ if (count($tree[$cur]['children']))
+ {
+// debug("$cur has children");
+ if (!isset($kids[$cur]))
+ {
+// debug("set $cur kids");
+ $kids[$cur] = 1;
+ $my_tree .= '<li>'.$this->returnSee($tree[$cur]['link']);
+ $my_tree .= '<ul>'."\n";
+ }
+ array_push($lastcur,$cur);
+ list(,$cur) = each($tree[$cur]['children']);
+// var_dump('listed',$cur);
+ if ($cur)
+ {
+ $cur = $cur['package'] . '#' . $cur['class'];
+// debug("set cur to child $cur");
+// $my_tree .= '<li>'.$this->returnSee($tree[$cur]['link']);
+ continue;
+ } else
+ {
+// debug("end of children for $cur");
+ $cur = array_pop($lastcur);
+ $cur = array_pop($lastcur);
+ $my_tree .= '</ul></li>'."\n";
+ if ($dopar && ($cur == '#root' || !$cur)) $my_tree .= '</ul></li>';
+ }
+ } else
+ {
+// debug("$cur has no children");
+ $my_tree .= '<li>'.$this->returnSee($tree[$cur]['link'])."</li>";
+ if ($dopar && $cur == '#root') $my_tree .= '</ul></li>';
+ $cur = array_pop($lastcur);
+ }
+ } while ($cur);
+ return $my_tree;
+ }
+ /**
+ * Generate indexing information for given element
+ *
+ * @param parserElement descendant of parserElement
+ * @see generateElementIndex()
+ * @return array
+ */
+ function getIndexInformation($elt)
+ {
+ $Result['type'] = $elt->type;
+ $Result['file_name'] = $elt->file;
+ $Result['path'] = $elt->getPath();
+
+ if (isset($elt->docblock))
+ {
+ $Result['description'] = $elt->docblock->getSDesc($this);
+
+ if ($elt->docblock->hasaccess)
+ $Result['access'] = $elt->docblock->tags['access'][0]->value;
+ else
+ $Result['access'] = 'public';
+
+ $Result['abstract'] = isset ($elt->docblock->tags['abstract'][0]);
+ }
+ else
+ $Result['description'] = '';
+
+ $aa = $Result['description'];
+ if (!empty($aa)) $aa = "<br>&nbsp;&nbsp;&nbsp;&nbsp;$aa";
+
+ switch($elt->type)
+ {
+ case 'class':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Class';
+ $Result['link'] = $this->getClassLink($elt->getName(),
+ $elt->docblock->package,
+ $elt->getPath(),
+ $elt->getName());
+ $Result['listing'] = 'in file '.$elt->file.', class '.$Result['link']."$aa";
+ break;
+ case 'define':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Constant';
+ $Result['link'] = $this->getDefineLink($elt->getName(),
+ $elt->docblock->package,
+ $elt->getPath(),
+ $elt->getName());
+ $Result['listing'] = 'in file '.$elt->file.', constant '.$Result['link']."$aa";
+ break;
+ case 'global':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Global';
+ $Result['link'] = $this->getGlobalLink($elt->getName(),
+ $elt->docblock->package,
+ $elt->getPath(),
+ $elt->getName());
+ $Result['listing'] = 'in file '.$elt->file.', global variable '.$Result['link']."$aa";
+ break;
+ case 'function':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Function';
+ $Result['link'] = $this->getFunctionLink($elt->getName(),
+ $elt->docblock->package,
+ $elt->getPath(),
+ $elt->getName().'()');
+ $Result['listing'] = 'in file '.$elt->file.', function '.$Result['link']."$aa";
+ break;
+ case 'method':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Method';
+ $Result['link'] = $this->getMethodLink($elt->getName(),
+ $elt->class,
+ $elt->docblock->package,
+ $elt->getPath(),
+ $elt->class.'::'.$elt->getName().'()'
+ );
+ if ($elt->isConstructor) $Result['constructor'] = 1;
+ $Result['listing'] = 'in file '.$elt->file.', method '.$Result['link']."$aa";
+ break;
+ case 'var':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Variable';
+ $Result['link'] = $this->getVarLink($elt->getName(),
+ $elt->class,
+ $elt->docblock->package,
+ $elt->getPath(),
+ $elt->class.'::'.$elt->getName());
+ $Result['listing'] = 'in file '.$elt->file.', variable '.$Result['link']."$aa";
+ break;
+ case 'const':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Class Constant';
+ $Result['link'] = $this->getConstLink($elt->getName(),
+ $elt->class,
+ $elt->docblock->package,
+ $elt->getPath(),
+ $elt->class.'::'.$elt->getName());
+ $Result['listing'] = 'in file '.$elt->file.', class constant '.$Result['link']."$aa";
+ break;
+ case 'page':
+ $Result['name'] = $elt->getFile();
+ $Result['title'] = 'Page';
+ $Result['link'] = $this->getPageLink($elt->getFile(),
+ $elt->package,
+ $elt->getPath(),
+ $elt->getFile());
+ $Result['listing'] = 'procedural page '.$Result['link'];
+ break;
+ case 'include':
+ $Result['name'] = $elt->getName();
+ $Result['title'] = 'Include';
+ $Result['link'] = $elt->getValue();
+ $Result['listing'] = 'include '.$Result['name'];
+ break;
+ }
+
+ return $Result;
+ }
+ /**
+ * Generate alphabetical index of all elements
+ *
+ * @see $elements, walk()
+ */
+ function generateElementIndex()
+ {
+ $elementindex = array();
+ $letters = array();
+ $used = array();
+ foreach($this->elements as $letter => $nutoh)
+ {
+ foreach($this->elements[$letter] as $i => $yuh)
+ {
+ if ($this->elements[$letter][$i]->type != 'include')
+ {
+ if (!isset($used[$letter]))
+ {
+ $letters[]['letter'] = $letter;
+ $elindex['letter'] = $letter;
+ $used[$letter] = 1;
+ }
+
+ $elindex['index'][] = $this->getIndexInformation($this->elements[$letter][$i]);
+ }
+ }
+ if (isset($elindex['index']))
+ {
+ $elementindex[] = $elindex;
+ } else
+ {
+ unset($letters[count($letters) - 1]);
+ }
+ $elindex = array();
+ }
+ return array($elementindex,$letters);
+ }
+
+ function copyMediaRecursively($media,$targetdir,$subdir = '')
+ {
+ if (!is_array($media)) {
+ return;
+ }
+ foreach($media as $dir => $files)
+ {
+ if ($dir === '/')
+ {
+ $this->copyMediaRecursively($files,$targetdir);
+ } else
+ {
+ if (!is_numeric($dir))
+ {
+ // create the subdir
+ phpDocumentor_out("creating $targetdir/$dir\n");
+ Converter::setTargetDir($targetdir . PATH_DELIMITER . $dir);
+ if (!empty($subdir)) $subdir .= PATH_DELIMITER;
+ $this->copyMediaRecursively($files,"$targetdir/$dir",$subdir . $dir);
+ } else
+ {
+ // copy the file
+ phpDocumentor_out("copying $targetdir/".$files['file']."\n");
+ $this->copyFile($files['file'],$subdir);
+ }
+ }
+ }
+ }
+
+ /**
+ * calls the converter setTargetDir, and then copies any template images and the stylesheet if they haven't been copied
+ * @see Converter::setTargetDir()
+ */
+ function setTargetDir($dir)
+ {
+ Converter::setTargetDir($dir);
+ if ($this->wrote) return;
+ $this->wrote = true;
+ $template_images = array();
+ $stylesheets = array();
+ $tdir = $dir;
+ $dir = $this->templateDir;
+ $this->templateDir = $this->templateDir.'templates/';
+ $info = new Io;
+ $this->copyMediaRecursively($info->getDirTree($this->templateDir.'media',$this->templateDir),$tdir);
+ }
+
+ /**
+ * Generate alphabetical index of all elements by package and subpackage
+ *
+ * @param string $package name of a package
+ * @see $pkg_elements, walk(), generatePkgElementIndexes()
+ */
+ function generatePkgElementIndex($package)
+ {
+// var_dump($this->pkg_elements[$package]);
+ $elementindex = array();
+ $letters = array();
+ $letterind = array();
+ $used = array();
+ $subp = '';
+ foreach($this->pkg_elements[$package] as $subpackage => $els)
+ {
+ if (empty($els)) continue;
+ if (!empty($subpackage)) $subp = " (<b>subpackage:</b> $subpackage)"; else $subp = '';
+ foreach($els as $letter => $yuh)
+ {
+ foreach($els[$letter] as $i => $yuh)
+ {
+ if ($els[$letter][$i]->type != 'include')
+ {
+ if (!isset($used[$letter]))
+ {
+ $letters[]['letter'] = $letter;
+ $letterind[$letter] = count($letters) - 1;
+ $used[$letter] = 1;
+ }
+ $elindex[$letter]['letter'] = $letter;
+
+ $elindex[$letter]['index'][] = $this->getIndexInformation($els[$letter][$i]);
+ }
+ }
+ }
+ }
+ ksort($elindex);
+ usort($letters,'HTMLframes_lettersort');
+ if (isset($elindex))
+ {
+ while(list($letter,$tempel) = each($elindex))
+ {
+ if (!isset($tempel))
+ {
+ unset($letters[$letterind[$tempel['letter']]]);
+ } else
+ $elementindex[] = $tempel;
+ }
+ } else $letters = array();
+ return array($elementindex,$letters);
+ }
+
+ /**
+ *
+ * @see generatePkgElementIndex()
+ */
+ function generatePkgElementIndexes()
+ {
+ $packages = array();
+ $package_names = array();
+ $pkg = array();
+ $letters = array();
+ foreach($this->pkg_elements as $package => $trash)
+ {
+ $pkgs['package'] = $package;
+ $pkg['package'] = $package;
+ list($pkg['pindex'],$letters[$package]) = $this->generatePkgElementIndex($package);
+ if (count($pkg['pindex']))
+ {
+ $packages[] = $pkg;
+ $package_names[] = $pkgs;
+ }
+ unset($pkgs);
+ unset($pkg);
+ }
+ foreach($packages as $i => $package)
+ {
+ $pnames = array();
+ for($j=0;$j<count($package_names);$j++)
+ {
+ if ($package_names[$j]['package'] != $package['package']) $pnames[] = $package_names[$j];
+ }
+ $packages[$i]['packageindexes'] = $pnames;
+ }
+ return array($packages,$package_names,$letters);
+ }
+
+ /**
+ * @param string name of class
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the class's documentation
+ * @see parent::getClassLink()
+ */
+ function getClassLink($expr,$package, $file = false,$text = false, $with_a = true)
+ {
+ $a = Converter::getClassLink($expr,$package,$file);
+ if (!$a) return false;
+ return $this->returnSee($a, $text, $with_a);
+ }
+
+ /**
+ * @param string name of function
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the function's documentation
+ * @see parent::getFunctionLink()
+ */
+ function getFunctionLink($expr,$package, $file = false,$text = false)
+ {
+ $a = Converter::getFunctionLink($expr,$package,$file);
+ if (!$a) return false;
+ return $this->returnSee($a, $text);
+ }
+
+ /**
+ * @param string name of define
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the define's documentation
+ * @see parent::getDefineLink()
+ */
+ function getDefineLink($expr,$package, $file = false,$text = false)
+ {
+ $a = Converter::getDefineLink($expr,$package,$file);
+ if (!$a) return false;
+ return $this->returnSee($a, $text);
+ }
+
+ /**
+ * @param string name of global variable
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the global variable's documentation
+ * @see parent::getGlobalLink()
+ */
+ function getGlobalLink($expr,$package, $file = false,$text = false)
+ {
+ $a = Converter::getGlobalLink($expr,$package,$file);
+ if (!$a) return false;
+ return $this->returnSee($a, $text);
+ }
+
+ /**
+ * @param string name of procedural page
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the procedural page's documentation
+ * @see parent::getPageLink()
+ */
+ function getPageLink($expr,$package, $path = false,$text = false)
+ {
+ $a = Converter::getPageLink($expr,$package,$path);
+ if (!$a) return false;
+ return $this->returnSee($a, $text);
+ }
+
+ /**
+ * @param string name of method
+ * @param string class containing method
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the method's documentation
+ * @see parent::getMethodLink()
+ */
+ function getMethodLink($expr,$class,$package, $file = false,$text = false)
+ {
+ $a = Converter::getMethodLink($expr,$class,$package,$file);
+ if (!$a) return false;
+ return $this->returnSee($a, $text);
+ }
+
+ /**
+ * @param string name of var
+ * @param string class containing var
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the var's documentation
+ * @see parent::getVarLink()
+ */
+ function getVarLink($expr,$class,$package, $file = false,$text = false)
+ {
+ $a = Converter::getVarLink($expr,$class,$package,$file);
+ if (!$a) return false;
+ return $this->returnSee($a, $text);
+ }
+
+ /**
+ * @param string name of class constant
+ * @param string class containing class constant
+ * @param string package name
+ * @param string full path to look in (used in index generation)
+ * @param boolean deprecated
+ * @param boolean return just the URL, or enclose it in an html a tag
+ * @return mixed false if not found, or an html a link to the var's documentation
+ * @see parent::getVarLink()
+ */
+ function getConstLink($expr,$class,$package, $file = false,$text = false)
+ {
+ $a = Converter::getConstLink($expr,$class,$package,$file);
+ if (!$a) return false;
+ return $this->returnSee($a, $text);
+ }
+
+ /**
+ * does a nat case sort on the specified second level value of the array
+ *
+ * @param mixed $a
+ * @param mixed $b
+ * @return int
+ */
+ function rcNatCmp ($a, $b)
+ {
+ $aa = strtoupper($a[$this->rcnatcmpkey]);
+ $bb = strtoupper($b[$this->rcnatcmpkey]);
+
+ return strnatcasecmp($aa, $bb);
+ }
+
+ /**
+ * does a nat case sort on the specified second level value of the array.
+ * this one puts constructors first
+ *
+ * @param mixed $a
+ * @param mixed $b
+ * @return int
+ */
+ function rcNatCmp1 ($a, $b)
+ {
+ $aa = strtoupper($a[$this->rcnatcmpkey]);
+ $bb = strtoupper($b[$this->rcnatcmpkey]);
+
+ if (strpos($aa,'CONSTRUCTOR') === 0)
+ {
+ return -1;
+ }
+ if (strpos($bb,'CONSTRUCTOR') === 0)
+ {
+ return 1;
+ }
+ if (strpos($aa,strtoupper($this->class)) === 0)
+ {
+ return -1;
+ }
+ if (strpos($bb,strtoupper($this->class)) === 0)
+ {
+ return -1;
+ }
+ return strnatcasecmp($aa, $bb);
+ }
+
+ /**
+ * This function is not used by HTMLdefaultConverter, but is required by Converter
+ */
+ function Output()
+ {
+ }
+}
+
+/**
+ * @access private
+ * @global string name of the package to set as the first package
+ */
+function HTMLframes_pindexcmp($a, $b)
+{
+ global $phpDocumentor_DefaultPackageName;
+ if ($a['title'] == $phpDocumentor_DefaultPackageName) return -1;
+ if ($b['title'] == $phpDocumentor_DefaultPackageName) return 1;
+ return strnatcasecmp($a['title'],$b['title']);
+}
+
+/** @access private */
+function HTMLframes_lettersort($a, $b)
+{
+ return strnatcasecmp($a['letter'],$b['letter']);
+}
+
+/** @access private */
+function HTMLframes_outputfilter($src, &$smarty)
+{
+ return str_replace('{$subdir}',$smarty->_tpl_vars['subdir'],$src);
+}
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/options.ini b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/options.ini
new file mode 100644
index 00000000..73164a39
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/options.ini
@@ -0,0 +1,577 @@
+preservedocbooktags = false
+
+;; used to highlight the {@source} inline tag, @filesource tag, and @example tag
+[highlightSourceTokens]
+;; format:
+;; T_CONSTANTNAME = open
+;; /T_CONSTANTNAME = close
+
+T_INCLUDE = <span class="src-inc">
+/T_INCLUDE = </span>
+T_INCLUDE_ONCE = <span class="src-inc">
+/T_INCLUDE_ONCE = </span>
+T_REQUIRE_ONCE = <span class="src-inc">
+/T_REQUIRE_ONCE = </span>
+T_REQUIRE_ONCE = <span class="src-inc">
+/T_REQUIRE_ONCE = </span>
+
+T_CONSTANT_ENCAPSED_STRING = <span class="src-str">
+/T_CONSTANT_ENCAPSED_STRING = </span>
+T_STRING_VARNAME = <span class="src-str">
+/T_STRING_VARNAME = </span>
+
+T_STRING = <span class="src-id">
+/T_STRING = </span>
+
+T_DNUMBER = <span class="src-num">
+/T_DNUMBER = </span>
+T_LNUMBER = <span class="src-num">
+/T_LNUMBER = </span>
+
+T_VARIABLE = <span class="src-var">
+/T_VARIABLE = </span>
+
+T_COMMENT = <span class="src-comm">
+/T_COMMENT = </span>
+T_ML_COMMENT = <span class="src-comm">
+/T_ML_COMMENT = </span>
+
+T_OBJECT_OPERATOR = <span class="src-sym">
+/T_OBJECT_OPERATOR = </span>
+
+T_ABSTRACT = <span class="src-key">
+/T_ABSTRACT = </span>
+T_CLONE = <span class="src-key">
+/T_CLONE = </span>
+T_HALT_COMPILER = <span class="src-key">
+/T_HALT_COMPILER = </span>
+T_ARRAY = <span class="src-key">
+/T_ARRAY = </span>
+T_AS = <span class="src-key">
+/T_AS = </span>
+T_BREAK = <span class="src-key">
+/T_BREAK = </span>
+T_CLASS = <span class="src-key">
+/T_CLASS = </span>
+T_CASE = <span class="src-key">
+/T_CASE = </span>
+T_CONST = <span class="src-key">
+/T_CONST = </span>
+T_CONTINUE = <span class="src-key">
+/T_CONTINUE = </span>
+T_DECLARE = <span class="src-key">
+/T_DECLARE = </span>
+T_DEFAULT = <span class="src-key">
+/T_DEFAULT = </span>
+T_ELSE = <span class="src-key">
+/T_ELSE = </span>
+T_ELSEIF = <span class="src-key">
+/T_ELSEIF = </span>
+T_EMPTY = <span class="src-key">
+/T_EMPTY = </span>
+T_ENDDECLARE = <span class="src-key">
+/T_ENDDECLARE = </span>
+T_ENDFOR = <span class="src-key">
+/T_ENDFOR = </span>
+T_ENDSWITCH = <span class="src-key">
+/T_ENDSWITCH = </span>
+T_ENDFOREACH = <span class="src-key">
+/T_ENDFOREACH = </span>
+T_ENDIF = <span class="src-key">
+/T_ENDIF = </span>
+T_ENDWHILE = <span class="src-key">
+/T_ENDWHILE = </span>
+T_EXIT = <span class="src-key">
+/T_EXIT = </span>
+T_EXTENDS = <span class="src-key">
+/T_EXTENDS = </span>
+T_FINAL = <span class="src-key">
+/T_FINAL = </span>
+T_FOR = <span class="src-key">
+/T_FOR = </span>
+T_FOREACH = <span class="src-key">
+/T_FOREACH = </span>
+T_FUNCTION = <span class="src-key">
+/T_FUNCTION = </span>
+T_GLOBAL = <span class="src-key">
+/T_GLOBAL = </span>
+T_IF = <span class="src-key">
+/T_IF = </span>
+T_IMPLEMENTS = <span class="src-key">
+/T_IMPLEMENTS = </span>
+T_INTERFACE = <span class="src-key">
+/T_INTERFACE = </span>
+T_LOGICAL_AND = <span class="src-key">
+/T_LOGICAL_AND = </span>
+T_LOGICAL_OR = <span class="src-key">
+/T_LOGICAL_OR = </span>
+T_LOGICAL_XOR = <span class="src-key">
+/T_LOGICAL_XOR = </span>
+T_NEW = <span class="src-key">
+/T_NEW = </span>
+T_PRIVATE = <span class="src-key">
+/T_PRIVATE = </span>
+T_PROTECTED = <span class="src-key">
+/T_PROTECTED = </span>
+T_PUBLIC = <span class="src-key">
+/T_PUBLIC = </span>
+T_RETURN = <span class="src-key">
+/T_RETURN = </span>
+T_STATIC = <span class="src-key">
+/T_STATIC = </span>
+T_SWITCH = <span class="src-key">
+/T_SWITCH = </span>
+T_VAR = <span class="src-key">
+/T_VAR = </span>
+T_WHILE = <span class="src-key">
+/T_WHILE = </span>
+
+T_DOUBLE_COLON = <span class="src-sym">
+/T_DOUBLE_COLON = </span>
+
+T_OPEN_TAG = <span class="src-php">
+/T_OPEN_TAG = </span>
+T_OPEN_TAG_WITH_ECHO = <span class="src-php">
+/T_OPEN_TAG_WITH_ECHO = </span>
+T_CLOSE_TAG = <span class="src-php">
+/T_CLOSE_TAG = </span>
+
+
+[highlightSource]
+;; this is for highlighting things that aren't tokens like "&"
+;; format:
+;; word = open
+;; /word = close
+@ = <span class="src-sym">
+/@ = </span>
+& = <span class="src-sym">
+/& = </span>
+[ = <span class="src-sym">
+/[ = </span>
+] = <span class="src-sym">
+/] = </span>
+! = <span class="src-sym">
+/! = </span>
+";" = <span class="src-sym">
+/; = </span>
+( = <span class="src-sym">
+/( = </span>
+) = <span class="src-sym">
+/) = </span>
+, = <span class="src-sym">
+/, = </span>
+{ = <span class="src-sym">
+/{ = </span>
+} = <span class="src-sym">
+/} = </span>
+""" = <span class="src-str">
+/" = </span>
+
+[highlightDocBlockSourceTokens]
+;; this is for docblock tokens, using by phpDocumentor_HighlightParser
+;; tagphptype is for "string" in @param string description, for example
+docblock = <span class="src-doc">
+/docblock = </span>
+tagphptype = <span class="src-doc-type">
+/tagphptype = </span>
+tagvarname = <span class="src-doc-var">
+/tagvarname = </span>
+coretag = <span class="src-doc-coretag">
+/coretag = </span>
+tag = <span class="src-doc-tag">
+/tag = </span>
+inlinetag = <span class="src-doc-inlinetag">
+/inlinetag = </span>
+internal = <span class="src-doc-internal">
+/internal = </span>
+closetemplate = <span class="src-doc-close-template">
+/closetemplate = </span>
+docblocktemplate = <span class="src-doc-template">
+/docblocktemplate = </span>
+
+[highlightTutorialSourceTokens]
+;; this is for XML DocBook-based tutorials, highlighted by phpDocumentor_TutorialHighlightParser
+;; <tag>
+opentag = <span class="tute-tag">
+/opentag = </span>
+;; </tag>
+closetag = <span class="tute-tag">
+/closetag = </span>
+;; <tag attribute="value">
+attribute = <span class="tute-attribute-name">
+/attribute = </span>
+;; <tag attribute="value">
+attributevalue = <span class="tute-attribute-value">
+/attributevalue = </span>
+;; &entity;
+entity = <span class="tute-entity">
+/entity = </span>
+;; <!-- comment -->
+comment = <span class="tute-comment">
+/comment = </span>
+;; {@inline tag}
+itag = <span class="tute-inline-tag">
+/itag = </span>
+
+;; used for translation of html in DocBlocks
+[desctranslate]
+ul = <ul>
+/ul = </ul>
+ol = <ol>
+/ol = </ol>
+li = <li>
+/li = </li>
+code = <code><pre>
+/code = </pre></code>
+var = <var>
+/var = </var>
+samp = <samp>
+/samp = </samp>
+kbd = <kbd>
+/kbd = </kbd>
+pre = <pre>
+/pre = </pre>
+p = <p>
+/p = </p>
+b = <strong>
+/b = </strong>
+i = <em>
+/i = </em>
+br = <br />
+
+[ppage]
+;; this is the DocBook package page translation section. All DocBook tags
+;; that have a corresponding html tag must be listed here. Entities should
+;; also be listed here
+;;
+;; examples:
+;; 1)
+;; tagname = newtagname
+;;
+;; This is the simplest case, where all attributes will be added into the
+;; starting tag and the ending tag will be html/xml style </tranlatedtagname>
+;; <tagname></tagname> becomes <newtagname></newtagname> and
+;; <tagname attr="value"></tagname> becomes
+;; <newtagname attr="value"></newtagname>
+;;
+;; 2)
+;; tagname = newtagname
+;; tagname->attr = newattrname
+;;
+;; in this case, everything will be like the first case, except tags like:
+;; <tagname attr="value"></tagname> will become
+;; <newtagname newattrname="value"></newtagname>
+;;
+;; 3)
+;; tagname = newtagname
+;; tagname->attr = newattrname
+;; tagname->attr+value = newvalue
+;;
+;; in this case, the value is also translated to another. This can be useful
+;; for instances such as focus="middle" changing to align="center" or something
+;; of that nature.
+;; <tagname attr="value"></tagname> will become
+;; <newtagname newattrname="newvalue"></newtagname>
+;;
+;; 4)
+;; tagname = newtagname
+;; tagname->attr1 = newattrname
+;; tagname->attr2 = newattrname
+;; tagname->attr1+value|attr2+value = newvalue
+;;
+;; in this case, two attributes combine to make one new attribute, and the combined
+;; value is translated into a new value
+;; <tagname attr1="value1" attr2="value2"></tagname> will become
+;; <newtagname newattrname="newvalue"></newtagname>
+;;
+;; 5)
+;; tagname = newtagname
+;; tagname!attr = dummy
+;;
+;; here, the attribute will be ignored. dummy is not used and may be any value
+;; <tagname attr="value"></tagname> will become
+;; <newtagname></newtagname>
+;;
+;; 6)
+;; tagname = newtagname
+;; tagname! = dummy
+;;
+;; here, all attributes will be ignored. dummy is not used and may be any value
+;; <tagname attr1="value" attr2="foo"></tagname> will become
+;; <newtagname></newtagname>
+;;
+;; 7)
+;; tagname = newtagname
+;; tagname/ = 1
+;;
+;; here, the tag will be translated as a single tag with no closing tag, and all
+;; attributes
+;; <tagname attr="val">{text text}</tagname> will become
+;; <newtagname attr="val" />
+;;
+;; 8)
+;; tagname = <starttaginfo />
+;; /tagname = closetagtext
+;;
+;; in this case, the text <starttaginfo> will be inserted exactly as entered for
+;; <tagname> and closetagtext for </tagname>
+;; <tagname attr="val"></tagname> will become
+;; <starttaginfo />closetagtext
+;;
+;; 9)
+;; $attr$my_attribute = newattrname
+;;
+;; tagname = newtagname
+;;
+;; in this case, all occurences of my_attribute in any tag will be changed to
+;; newattrname. This is useful for changing things like role="php" to
+;; class="php," for example. Note that the text "$attr$" MUST be on the line
+;; start for phpDocumentor to recognize it.
+;;
+;; 10)
+;; &entity; = translation text
+;; &quot; = &quot;
+;; &quot; = """
+;; &lt; = <
+;;
+;; Use this to control translation of entities to their appropriate values
+
+&nbsp; = &nbsp;
+&quot; = &quot;
+&rdquo; = &rdquo;
+&ldquo; = &ldquo;
+&amp; = &amp;
+&lt; = &lt;
+&gt; = &gt;
+&copy; = &copy;
+
+
+$attr$role = class
+
+abbrev = abbr
+
+blockquote = blockquote
+
+arg = span
+arg->choice = class
+
+author = <span class="author">
+/author = </span>
+author! = 0
+
+authorblurb = <div class="author-blurb">
+/authorblurb = </div>
+
+authorgroup = <div class="authors"><h2 class="title">Authors</h2>
+/authorgroup = </div>
+authorgroup! = 0
+
+caution = <span class="warning">
+/caution = </span>
+caution! = 0
+
+cmdsynopsis = <div class="cmd-synopsis">
+/cmdsynopsis = </div>
+
+command = <span class="cmd-title">
+/command = </span>
+
+copyright = <div class="notes">
+/copyright = </div>
+
+emphasis = em
+
+example = <pre class="example">
+/example = </pre>
+example! = 0
+
+function =
+/function = ()
+
+formalpara = p
+
+graphic = img
+graphic->fileref = src
+graphic/ =
+
+important = strong
+
+informalequation = blockquote
+
+informalexample = div
+
+inlineequation = em
+
+itemizedlist = ul
+
+listitem = li
+
+literal = code
+
+literallayout = span
+
+option = " "
+/option =
+
+orderedlist = ol
+
+para = p
+
+programlisting = <pre class="listing">
+/programlisting = </pre>
+programlisting! = 0
+
+refentry = div
+
+refnamediv = <div class="ref-title-box">
+/refnamediv = </div>
+refnamediv! = 0
+
+refname = <h1 class="ref-title">
+/refname = </h1>
+
+refpurpose = <h2 class="ref-purpose">
+/refpurpose = </h2>
+
+refsynopsisdiv = <div class="ref-synopsis">
+/refsynopsisdiv = </div>
+refsynopsisdiv! = 0
+
+refsect1 = span
+
+refsect2 = span
+
+refsect3 =
+/refsect3 = <br />
+
+releaseinfo = <div class="release-info">(
+/releaseinfo = )</div>
+
+simpara =
+/simpara = <br />
+simpara! = 0
+
+subscript = sub
+
+superscript = super
+
+table = table
+
+table->colsep = rules
+table->rowsep = rules
+table->colsep+1|rowsep+1 =all
+table->colsep+1|rowsep+0 =cols
+table->colsep+0|rowsep+1 =rows
+
+table->frame =frame
+table->frame+all =border
+table->frame+none =void
+table->frame+sides =vsides
+table->frame+top =above
+table->frame+topbot =hsides
+
+thead = thead
+
+tfoot = tfoot
+
+tbody = tbody
+
+colspec = col
+
+tgroup = colgroup
+tgroup/ = 1
+tgroup->cols = span
+
+row = tr
+
+entry = td
+entry->morerows = colspan
+entry->morerows+1 =2
+entry->morerows+2 =3
+entry->morerows+3 =4
+entry->morerows+4 =5
+entry->morerows+5 =6
+entry->morerows+6 =7
+entry->morerows+7 =8
+entry->morerows+8 =9
+entry->morerows+9 =10
+entry->morerows+10 =11
+;; add more if you need more colspans
+
+warning = <span class="warning">
+/warning = </span>
+warning! = 0
+
+;; now begins the attributes that should be tags in cdata
+[$attr$id]
+open = a
+;close = /a
+cdata! = true
+quotevalues = true
+separator = "="
+;separateall = true
+$id = name
+
+;; now begins the sections that deal with <title>
+[refsynopsisdiv_title]
+;tag_attr = true
+;attr_name = title
+cdata_start = true
+;cdata_end = true
+open = <h1 class="title">
+close = </h1>
+
+[refsect1_title]
+;tag_attr = true
+;attr_name = title
+cdata_start = true
+;cdata_end = true
+open = <h2 class="title">
+close = </h2>
+
+[refsect2_title]
+;tag_attr = true
+;attr_name = title
+cdata_start = true
+;cdata_end = true
+open = <h3 class="title">
+close = </h3>
+
+[refsect3_title]
+;tag_attr = true
+;attr_name = title
+cdata_start = true
+;cdata_end = true
+open = <h4 class="title">
+close = </h4>
+
+[para_title]
+;tag_attr = true
+;attr_name = title
+cdata_start = true
+;cdata_end = true
+open = <div class="title">
+close = </div>
+
+[formalpara_title]
+;tag_attr = true
+;attr_name = title
+cdata_start = true
+;cdata_end = true
+open = <div class="title">
+close = </div>
+
+[example_title]
+;tag_attr = true
+;attr_name = title
+;cdata_start = true
+cdata_end = true
+open = </td></tr><tr><td><strong>
+close = </strong>
+
+[table_title]
+;tag_attr = true
+;attr_name = true
+cdata_start = true
+open = <caption>
+close = </caption>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/basicindex.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/basicindex.tpl
new file mode 100644
index 00000000..711e1d2e
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/basicindex.tpl
@@ -0,0 +1,47 @@
+<div class="index-letter-menu">
+{section name=letter loop=$letters}
+ <a class="index-letter" href="{$indexname}.html#{$letters[letter].letter}">{$letters[letter].letter}</a>
+{/section}
+</div>
+
+{section name=index loop=$index}
+ <a name="{$index[index].letter}"></a>
+ <div class="index-letter-section">
+ <div style="float: left" class="index-letter-title">{$index[index].letter}</div>
+ <div style="float: right"><a href="#top">top</a></div>
+ <div style="clear: both"></div>
+ </div>
+ <dl>
+ {section name=contents loop=$index[index].index}
+ <dt class="field">
+ {if ($index[index].index[contents].title == "Variable")}
+ <span class="var-title">{$index[index].index[contents].name}</span>
+ {elseif ($index[index].index[contents].title == "Global")}
+ <span class="var-title">{$index[index].index[contents].name}</span>
+ {elseif ($index[index].index[contents].title == "Method")}
+ <span class="method-title">{$index[index].index[contents].name}</span>
+ {elseif ($index[index].index[contents].title == "Function")}
+ <span class="method-title">{$index[index].index[contents].name}</span>
+ {elseif ($index[index].index[contents].title == "Constant")}
+ <span class="const-title">{$index[index].index[contents].name}</span>
+ {elseif ($index[index].index[contents].title == "Page") || ($index[index].index[contents].title == "Include")}
+ <span class="include-title">{$index[index].index[contents].name}</span>
+ {else}
+ {$index[index].index[contents].name}
+ {/if}
+ </dt>
+ <dd class="index-item-body">
+ <div class="index-item-details">{$index[index].index[contents].link} in {$index[index].index[contents].file_name}</div>
+ {if $index[index].index[contents].description}
+ <div class="index-item-description">{$index[index].index[contents].description}</div>
+ {/if}
+ </dd>
+ {/section}
+ </dl>
+{/section}
+
+<div class="index-letter-menu">
+{section name=letter loop=$letters}
+ <a class="index-letter" href="{$indexname}.html#{$letters[letter].letter}">{$letters[letter].letter}</a>
+{/section}
+</div>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/blank.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/blank.tpl
new file mode 100644
index 00000000..1fbaca2f
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/blank.tpl
@@ -0,0 +1,13 @@
+<html>
+<head>
+ <title>{$maintitle}</title>
+ <link rel="stylesheet" href="{$subdir}media/stylesheet.css" />
+ <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
+</head>
+<body>
+<div align="center"><h1>{$maintitle}</h1></div>
+<b>Welcome to {$package}!</b><br />
+<br />
+This documentation was generated by <a href="{$phpdocwebsite}">phpDocumentor v{$phpdocversion}</a><br />
+</body>
+</html> \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/class.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/class.tpl
new file mode 100644
index 00000000..cc1c080b
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/class.tpl
@@ -0,0 +1,402 @@
+{include file="header.tpl" top3=true}
+
+<h2 class="class-name">{if $is_interface}Interface{else}Class{/if} {$class_name}</h2>
+
+<a name="sec-description"></a>
+<div class="info-box">
+ <div class="info-box-title">Description</div>
+ <div class="nav-bar">
+ {if $children || $vars || $ivars || $methods || $imethods || $consts || $iconsts }
+ <span class="disabled">Description</span> |
+ {/if}
+ {if $children}
+ <a href="#sec-descendents">Descendents</a>
+ {if $vars || $ivars || $methods || $imethods || $consts || $iconsts}|{/if}
+ {/if}
+ {if $vars || $ivars}
+ {if $vars}
+ <a href="#sec-var-summary">Vars</a> (<a href="#sec-vars">details</a>)
+ {else}
+ <a href="#sec-vars">Vars</a>
+ {/if}
+ {if $methods || $imethods}|{/if}
+ {/if}
+ {if $methods || $imethods}
+ {if $methods}
+ <a href="#sec-method-summary">Methods</a> (<a href="#sec-methods">details</a>)
+ {else}
+ <a href="#sec-methods">Methods</a>
+ {/if}
+ {/if}
+ {if $consts || $iconsts}
+ {if $consts}
+ <a href="#sec-const-summary">Constants</a> (<a href="#sec-consts">details</a>)
+ {else}
+ <a href="#sec-consts">Constants</a>
+ {/if}
+ {/if}
+ </div>
+ <div class="info-box-body">
+ {if $implements}
+ <p class="implements">
+ Implements interfaces:
+ <ul>
+ {foreach item="int" from=$implements}<li>{$int}</li>{/foreach}
+ </ul>
+ </p>
+ {/if}
+ {include file="docblock.tpl" type="class" sdesc=$sdesc desc=$desc}
+ <p class="notes">
+ Located in <a class="field" href="{$page_link}">{$source_location}</a> (line <span class="field">{if $class_slink}{$class_slink}{else}{$line_number}{/if}</span>)
+ </p>
+
+ {if $tutorial}
+ <hr class="separator" />
+ <div class="notes">Tutorial: <span class="tutorial">{$tutorial}</span></div>
+ {/if}
+
+ <pre>{section name=tree loop=$class_tree.classes}{$class_tree.classes[tree]}{$class_tree.distance[tree]}{/section}</pre>
+
+ {if $conflicts.conflict_type}
+ <hr class="separator" />
+ <div><span class="warning">Conflicts with classes:</span><br />
+ {section name=me loop=$conflicts.conflicts}
+ {$conflicts.conflicts[me]}<br />
+ {/section}
+ </div>
+ {/if}
+ </div>
+</div>
+
+{if $children}
+ <a name="sec-descendents"></a>
+ <div class="info-box">
+ <div class="info-box-title">Direct descendents</div>
+ <div class="nav-bar">
+ <a href="#sec-description">Description</a> |
+ <span class="disabled">Descendents</span>
+ {if $vars || $ivars || $methods || $imethods}|{/if}
+ {if $vars || $ivars}
+ {if $vars}
+ <a href="#sec-var-summary">Vars</a> (<a href="#sec-vars">details</a>)
+ {else}
+ <a href="#sec-vars">Vars</a>
+ {/if}
+ {if $methods || $imethods}|{/if}
+ {/if}
+ {if $methods || $imethods}
+ {if $methods}
+ <a href="#sec-method-summary">Methods</a> (<a href="#sec-methods">details</a>)
+ {else}
+ <a href="#sec-methods">Methods</a>
+ {/if}
+ {/if}
+ {if $consts || $iconsts}
+ {if $consts}
+ <a href="#sec-const-summary">Constants</a> (<a href="#sec-consts">details</a>)
+ {else}
+ <a href="#sec-consts">Constants</a>
+ {/if}
+ {/if}
+ </div>
+ <div class="info-box-body">
+ <table cellpadding="2" cellspacing="0" class="class-table">
+ <tr>
+ <th class="class-table-header">Class</th>
+ <th class="class-table-header">Description</th>
+ </tr>
+ {section name=kids loop=$children}
+ <tr>
+ <td style="padding-right: 2em">{$children[kids].link}</td>
+ <td>
+ {if $children[kids].sdesc}
+ {$children[kids].sdesc}
+ {else}
+ {$children[kids].desc}
+ {/if}
+ </td>
+ </tr>
+ {/section}
+ </table>
+ </div>
+ </div>
+{/if}
+
+{if $consts}
+ <a name="sec-const-summary"></a>
+ <div class="info-box">
+ <div class="info-box-title">Class Constant Summary</span></div>
+ <div class="nav-bar">
+ <a href="#sec-description">Description</a> |
+ {if $children}
+ <a href="#sec-descendents">Descendants</a> |
+ {/if}
+ <span class="disabled">Constants</span> (<a href="#sec-consts">details</a>)
+ {if $vars || $ivars}
+ {if $vars}
+ <a href="#sec-var-summary">Vars</a> (<a href="#sec-vars">details</a>)
+ {else}
+ <a href="#sec-vars">Vars</a>
+ {/if}
+ |
+ {/if}
+ {if $methods || $imethods}
+ |
+ {if $methods}
+ <a href="#sec-method-summary">Methods</a> (<a href="#sec-methods">details</a>)
+ {else}
+ <a href="#sec-methods">Methods</a>
+ {/if}
+ {/if}
+ </div>
+ <div class="info-box-body">
+ <div class="const-summary">
+ {section name=consts loop=$consts}
+ <div class="const-title">
+ <img src="{$subdir}media/images/Constant.png" alt=" " />
+ <a href="#{$consts[consts].const_name}" title="details" class="const-name">{$consts[consts].const_name}</a> = <span class="var-type">{$consts[consts].const_value}</span>
+
+ </div>
+ {/section}
+ </div>
+ </div>
+ </div>
+{/if}
+
+{if $vars}
+ <a name="sec-var-summary"></a>
+ <div class="info-box">
+ <div class="info-box-title">Variable Summary</span></div>
+ <div class="nav-bar">
+ <a href="#sec-description">Description</a> |
+ {if $children}
+ <a href="#sec-descendents">Descendents</a> |
+ {/if}
+ <span class="disabled">Vars</span> (<a href="#sec-vars">details</a>)
+ {if $methods || $imethods}
+ |
+ {if $methods}
+ <a href="#sec-method-summary">Methods</a> (<a href="#sec-methods">details</a>)
+ {else}
+ <a href="#sec-methods">Methods</a>
+ {/if}
+ {/if}
+ {if $consts || $iconsts}
+ {if $consts}
+ <a href="#sec-const-summary">Constants</a> (<a href="#sec-consts">details</a>)
+ {else}
+ <a href="#sec-consts">Constants</a>
+ {/if}
+ {/if}
+ </div>
+ <div class="info-box-body">
+ <div class="var-summary">
+ {section name=vars loop=$vars}
+ <div class="var-title">
+ <span class="var-type">{$vars[vars].var_type}</span>
+ <a href="#{$vars[vars].var_name}" title="details" class="var-name">{$vars[vars].var_name}</a>
+ </div>
+ {/section}
+ </div>
+ </div>
+ </div>
+{/if}
+
+{if $methods}
+ <a name="sec-method-summary"></a>
+ <div class="info-box">
+ <div class="info-box-title">Method Summary</span></div>
+ <div class="nav-bar">
+ <a href="#sec-description">Description</a> |
+ {if $children}
+ <a href="#sec-descendents">Descendents</a> |
+ {/if}
+ {if $consts || $iconsts}
+ {if $consts}
+ <a href="#sec-const-summary">Constants</a> (<a href="#sec-consts">details</a>)
+ {else}
+ <a href="#sec-consts">Constants</a>
+ {/if}
+ {/if}
+ {if $vars || $ivars}
+ {if $vars}
+ <a href="#sec-var-summary">Vars</a> (<a href="#sec-vars">details</a>)
+ {else}
+ <a href="#sec-vars">Vars</a>
+ {/if}
+ |
+ {/if}
+ <span class="disabled">Methods</span> (<a href="#sec-methods">details</a>)
+ </div>
+ <div class="info-box-body">
+ <div class="method-summary">
+ {section name=methods loop=$methods}
+ <div class="method-definition">
+ {if $methods[methods].function_return}
+ <span class="method-result">{$methods[methods].function_return}</span>
+ {/if}
+ <a href="#{$methods[methods].function_name}" title="details" class="method-name">{if $methods[methods].ifunction_call.returnsref}&amp;{/if}{$methods[methods].function_name}</a>
+ {if count($methods[methods].ifunction_call.params)}
+ ({section name=params loop=$methods[methods].ifunction_call.params}{if $smarty.section.params.iteration != 1}, {/if}{if $methods[methods].ifunction_call.params[params].default}[{/if}<span class="var-type">{$methods[methods].ifunction_call.params[params].type}</span>&nbsp;<span class="var-name">{$methods[methods].ifunction_call.params[params].name}</span>{if $methods[methods].ifunction_call.params[params].default} = <span class="var-default">{$methods[methods].ifunction_call.params[params].default}</span>]{/if}{/section})
+ {else}
+ ()
+ {/if}
+ </div>
+ {/section}
+ </div>
+ </div>
+ </div>
+{/if}
+
+{if $vars || $ivars}
+ <a name="sec-vars"></a>
+ <div class="info-box">
+ <div class="info-box-title">Variables</div>
+ <div class="nav-bar">
+ <a href="#sec-description">Description</a> |
+ {if $children}
+ <a href="#sec-descendents">Descendents</a> |
+ {/if}
+ {if $methods}
+ <a href="#sec-var-summary">Vars</a> (<span class="disabled">details</span>)
+ {else}
+ <span class="disabled">Vars</span>
+ {/if}
+
+ {if $consts || $iconsts}
+ {if $consts}
+ <a href="#sec-const-summary">Constants</a> (<a href="#sec-consts">details</a>)
+ {else}
+ <a href="#sec-consts">Constants</a>
+ {/if}
+ {/if}
+ {if $methods || $imethods}
+ |
+ {if $methods}
+ <a href="#sec-method-summary">Methods</a> (<a href="#sec-methods">details</a>)
+ {else}
+ <a href="#sec-methods">Methods</a>
+ {/if}
+ {/if}
+ </div>
+ <div class="info-box-body">
+ {include file="var.tpl"}
+ {if $ivars}
+ <h4>Inherited Variables</h4>
+ <A NAME='inherited_vars'><!-- --></A>
+ {section name=ivars loop=$ivars}
+ <p>Inherited from <span class="classname">{$ivars[ivars].parent_class}</span></p>
+ <blockquote>
+ {section name=ivars2 loop=$ivars[ivars].ivars}
+ <span class="var-title">
+ <span class="var-name">{$ivars[ivars].ivars[ivars2].link}</span>{if $ivars[ivars].ivars[ivars2].ivar_sdesc}: {$ivars[ivars].ivars[ivars2].ivar_sdesc}{/if}<br>
+ </span>
+ {/section}
+ </blockquote>
+ {/section}
+ {/if}
+ </div>
+ </div>
+{/if}
+
+{if $methods || $imethods}
+ <a name="sec-methods"></a>
+ <div class="info-box">
+ <div class="info-box-title">Methods</div>
+ <div class="nav-bar">
+ <a href="#sec-description">Description</a> |
+ {if $children}
+ <a href="#sec-descendents">Descendents</a> |
+ {/if}
+ {if $vars || $ivars}
+ {if $vars}
+ <a href="#sec-var-summary">Vars</a> (<a href="#sec-vars">details</a>)
+ {else}
+ <a href="#sec-vars">Vars</a>
+ {/if}
+ {/if}
+ {if $consts || $iconsts}
+ {if $consts}
+ <a href="#sec-const-summary">Constants</a> (<a href="#sec-consts">details</a>)
+ {else}
+ <a href="#sec-consts">Constants</a>
+ {/if}
+ {/if}
+ {if $methods}
+ <a href="#sec-method-summary">Methods</a> (<span class="disabled">details</span>)
+ {else}
+ <span class="disabled">Methods</span>
+ {/if}
+ </div>
+ <div class="info-box-body">
+ {include file="method.tpl"}
+ {if $imethods}
+ <h4>Inherited Methods</h4>
+ <a name='inherited_methods'><!-- --></a>
+ {section name=imethods loop=$imethods}
+ <!-- =========== Summary =========== -->
+ <p>Inherited From <span class="classname">{$imethods[imethods].parent_class}</span></p>
+ <blockquote>
+ {section name=im2 loop=$imethods[imethods].imethods}
+ <span class="method-name">{$imethods[imethods].imethods[im2].link}</span>{if $imethods[imethods].imethods[im2].ifunction_sdesc}: {$imethods[imethods].imethods[im2].ifunction_sdesc}{/if}<br>
+ {/section}
+ </blockquote>
+ {/section}
+ {/if}
+ </div>
+ </div>
+{/if}
+
+{if $consts || $iconsts}
+ <a name="sec-consts"></a>
+ <div class="info-box">
+ <div class="info-box-title">Class Constants</div>
+ <div class="nav-bar">
+ <a href="#sec-description">Description</a> |
+ {if $children}
+ <a href="#sec-descendents">Descendants</a> |
+ {/if}
+ {if $methods}
+ <a href="#sec-var-summary">Constants</a> (<span class="disabled">details</span>)
+ {else}
+ <span class="disabled">Constants</span>
+ {/if}
+
+ {if $vars || $ivars}
+ {if $vars}
+ <a href="#sec-var-summary">Vars</a> (<a href="#sec-vars">details</a>)
+ {else}
+ <a href="#sec-vars">Vars</a>
+ {/if}
+ {/if}
+ {if $methods || $imethods}
+ |
+ {if $methods}
+ <a href="#sec-method-summary">Methods</a> (<a href="#sec-methods">details</a>)
+ {else}
+ <a href="#sec-methods">Methods</a>
+ {/if}
+ {/if}
+ </div>
+ <div class="info-box-body">
+ {include file="const.tpl"}
+ {if $iconsts}
+ <h4>Inherited Constants</h4>
+ <A NAME='inherited_vars'><!-- --></A>
+ {section name=iconsts loop=$iconsts}
+ <p>Inherited from <span class="classname">{$iconsts[iconsts].parent_class}</span></p>
+ <blockquote>
+ {section name=iconsts2 loop=$iconsts[iconsts].iconsts}
+ <img src="{$subdir}media/images/{if $iconsts[iconsts].iconsts[iconsts2].access == 'private'}PrivateVariable{else}Variable{/if}.png" />
+ <span class="const-title">
+ <span class="const-name">{$iconsts[iconsts].iconsts[iconsts2].link}</span>{if $iconsts[iconsts].iconsts[iconsts2].iconst_sdesc}: {$iconsts[iconsts].iconsts[iconsts2].iconst_sdesc}{/if}<br>
+ </span>
+ {/section}
+ </blockquote>
+ {/section}
+ {/if}
+ </div>
+ </div>
+{/if}
+
+{include file="footer.tpl" top3=true}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/classtrees.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/classtrees.tpl
new file mode 100644
index 00000000..5188e8cf
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/classtrees.tpl
@@ -0,0 +1,11 @@
+{include file="header.tpl" top1=true}
+
+<!-- Start of Class Data -->
+<H2>
+ {$smarty.capture.title}
+</H2>
+{section name=classtrees loop=$classtrees}
+<h2>Root class {$classtrees[classtrees].class}</h2>
+{$classtrees[classtrees].class_tree}
+{/section}
+{include file="footer.tpl"} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/const.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/const.tpl
new file mode 100644
index 00000000..4157488f
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/const.tpl
@@ -0,0 +1,18 @@
+{section name=consts loop=$consts}
+<a name="const{$consts[consts].const_name}" id="{$consts[consts].const_name}"><!-- --></A>
+<div class="{cycle values="evenrow,oddrow"}">
+
+ <div class="const-header">
+ <img src="{$subdir}media/images/{if $consts[consts].access == 'private'}PrivateVariable{else}Variable{/if}.png" />
+ <span class="const-title">
+ <span class="const-name">{$consts[consts].const_name}</span>
+ = <span class="const-default">{$consts[consts].const_value|replace:"\n":"<br />"}</span>
+ (line <span class="line-number">{if $consts[consts].slink}{$consts[consts].slink}{else}{$consts[consts].line_number}{/if}</span>)
+ </span>
+ </div>
+
+ {include file="docblock.tpl" sdesc=$consts[consts].sdesc desc=$consts[consts].desc tags=$consts[consts].tags}
+
+</div>
+{/section}
+
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/define.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/define.tpl
new file mode 100644
index 00000000..ab76faa2
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/define.tpl
@@ -0,0 +1,24 @@
+{section name=def loop=$defines}
+<a name="{$defines[def].define_link}"><!-- --></a>
+<div class="{cycle values="evenrow,oddrow"}">
+
+ <div>
+ <span class="const-title">
+ <span class="const-name">{$defines[def].define_name}</span> = {$defines[def].define_value|replace:"\n":"<br />"}
+ (line <span class="line-number">{if $defines[def].slink}{$defines[def].slink}{else}{$defines[def].line_number}{/if}</span>)
+ </span>
+ </div>
+
+ {include file="docblock.tpl" sdesc=$defines[def].sdesc desc=$defines[def].desc tags=$defines[def].tags}
+
+ {if $globals[glob].global_conflicts.conflict_type}
+ <hr class="separator" />
+ <div><span class="warning">Conflicts with constants:</span><br />
+ {section name=me loop=$defines[def].define_conflicts.conflicts}
+ {$defines[def].define_conflicts.conflicts[me]}<br />
+ {/section}
+ </div>
+ {/if}
+
+</div>
+{/section} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/docblock.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/docblock.tpl
new file mode 100644
index 00000000..8a87c9b7
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/docblock.tpl
@@ -0,0 +1,14 @@
+<!-- ========== Info from phpDoc block ========= -->
+{if $sdesc}
+<p class="short-description">{$sdesc}</p>
+{/if}
+{if $desc}
+<p class="description">{$desc}</p>
+{/if}
+{if $tags}
+ <ul class="tags">
+ {section name=tags loop=$tags}
+ <li><span class="field">{$tags[tags].keyword}:</span> {$tags[tags].data}</li>
+ {/section}
+ </ul>
+{/if}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/elementindex.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/elementindex.tpl
new file mode 100644
index 00000000..6e651db1
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/elementindex.tpl
@@ -0,0 +1,12 @@
+{include file="header.tpl" noleftindex=true}
+<a name="top"></a>
+<h2>Full index</h2>
+<h3>Package indexes</h3>
+<ul>
+{section name=p loop=$packageindex}
+ <li><a href="elementindex_{$packageindex[p].title}.html">{$packageindex[p].title}</a></li>
+{/section}
+</ul>
+<br />
+{include file="basicindex.tpl" indexname="elementindex"}
+{include file="footer.tpl"}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/errors.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/errors.tpl
new file mode 100644
index 00000000..1576a822
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/errors.tpl
@@ -0,0 +1,21 @@
+{include file="header.tpl" noleftindex=true}
+{section name=files loop=$files}
+<a href="#{$files[files].file}">{$files[files].file}</a><br>
+{/section}
+{foreach key=file item=issues from=$all}
+<a name="{$file}"></a>
+<h1>{$file}</h1>
+{if count($issues.warnings)}
+<h2>Warnings:</h2><br>
+{section name=warnings loop=$issues.warnings}
+<b>{$issues.warnings[warnings].name}</b> - {$issues.warnings[warnings].listing}<br>
+{/section}
+{/if}
+{if count($issues.errors)}
+<h2>Errors:</h2><br>
+{section name=errors loop=$issues.errors}
+<b>{$issues.errors[errors].name}</b> - {$issues.errors[errors].listing}<br>
+{/section}
+{/if}
+{/foreach}
+{include file="footer.tpl"}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/examplesource.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/examplesource.tpl
new file mode 100644
index 00000000..c813280b
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/examplesource.tpl
@@ -0,0 +1,6 @@
+{include file="header.tpl" title=$title}
+<h1>{$title}</h1>
+<div class="listing">
+{$source}
+</div>
+{include file="footer.tpl"} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/filesource.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/filesource.tpl
new file mode 100644
index 00000000..4fd821a2
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/filesource.tpl
@@ -0,0 +1,8 @@
+{capture name="tutle"}File Source for {$name}{/capture}
+{include file="header.tpl" title=$smarty.capture.tutle}
+<h1>Source for file {$name}</h1>
+<p>Documentation is available at {$docs}</p>
+<div class="src-code">
+{$source}
+</div>
+{include file="footer.tpl"} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/footer.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/footer.tpl
new file mode 100644
index 00000000..424ebbe2
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/footer.tpl
@@ -0,0 +1,8 @@
+{if !$index}
+ <p class="notes" id="credit">
+ Documentation generated on {$date} by <a href="{$phpdocwebsite}" target="_blank">phpDocumentor {$phpdocversion}</a>
+ </p>
+{/if}
+ {if $top3}</div>{/if}
+</body>
+</html>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/function.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/function.tpl
new file mode 100644
index 00000000..2750a97e
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/function.tpl
@@ -0,0 +1,44 @@
+{section name=func loop=$functions}
+<a name="{$functions[func].function_dest}" id="{$functions[func].function_dest}"><!-- --></a>
+<div class="{cycle values="evenrow,oddrow"}">
+
+ <div>
+ <span class="method-title">{$functions[func].function_name}</span> (line <span class="line-number">{if $functions[func].slink}{$functions[func].slink}{else}{$functions[func].line_number}{/if}</span>)
+ </div>
+
+ {include file="docblock.tpl" sdesc=$functions[func].sdesc desc=$functions[func].desc tags=$functions[func].tags params=$functions[func].params function=false}
+
+ <div class="method-signature">
+ <span class="method-result">{$functions[func].function_return}</span>
+ <span class="method-name">
+ {if $functions[func].ifunction_call.returnsref}&amp;{/if}{$functions[func].function_name}
+ </span>
+ {if count($functions[func].ifunction_call.params)}
+ ({section name=params loop=$functions[func].ifunction_call.params}{if $smarty.section.params.iteration != 1}, {/if}{if $functions[func].ifunction_call.params[params].hasdefault}[{/if}<span class="var-type">{$functions[func].ifunction_call.params[params].type}</span>&nbsp;<span class="var-name">{$functions[func].ifunction_call.params[params].name}</span>{if $functions[func].ifunction_call.params[params].hasdefault} = <span class="var-default">{$functions[func].ifunction_call.params[params].default|escape:"html"}</span>]{/if}{/section})
+ {else}
+ ()
+ {/if}
+ </div>
+
+ {if $functions[func].params}
+ <ul class="parameters">
+ {section name=params loop=$functions[func].params}
+ <li>
+ <span class="var-type">{$functions[func].params[params].datatype}</span>
+ <span class="var-name">{$functions[func].params[params].var}</span>{if $functions[func].params[params].data}<span class="var-description">: {$functions[func].params[params].data}</span>{/if}
+ </li>
+ {/section}
+ </ul>
+ {/if}
+
+ {if $functions[func].function_conflicts.conflict_type}
+ <hr class="separator" />
+ <div><span class="warning">Conflicts with functions:</span><br />
+ {section name=me loop=$functions[func].function_conflicts.conflicts}
+ {$functions[func].function_conflicts.conflicts[me]}<br />
+ {/section}
+ </div>
+ {/if}
+
+</div>
+{/section}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/global.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/global.tpl
new file mode 100644
index 00000000..3c89ddfc
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/global.tpl
@@ -0,0 +1,26 @@
+{section name=glob loop=$globals}
+<a name="{$globals[glob].global_link}" id="{$globals[glob].global_link}"><!-- --></a>
+<div class="{cycle values="evenrow,oddrow"}">
+
+ <div>
+ <span class="var-title">
+ <span class="var-type">{$globals[glob].global_type}</span>
+ <span class="var-name">{$globals[glob].global_name}</span>
+ {if $vars[vars].var_default} = <span class="var-default">{$globals[glob].global_value|replace:"\n":"<br />"}</span>{/if}
+ (line <span class="line-number">{if $globals[glob].slink}{$globals[glob].slink}{else}{$globals[glob].line_number}{/if}</span>)
+ </span>
+ </div>
+
+ {include file="docblock.tpl" sdesc=$globals[glob].sdesc desc=$globals[glob].desc tags=$globals[glob].tags}
+
+ {if $globals[glob].global_conflicts.conflict_type}
+ <hr class="separator" />
+ <div><span class="warning">Conflicts with global variables:</span><br />
+ {section name=me loop=$globals[glob].global_conflicts.conflicts}
+ {$globals[glob].global_conflicts.conflicts[me]}<br />
+ {/section}
+ </div>
+ {/if}
+
+</div>
+{/section} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/header.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/header.tpl
new file mode 100644
index 00000000..d5e26dfa
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/header.tpl
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <!-- template designed by Marco Von Ballmoos -->
+ <title>{$title}</title>
+ <link rel="stylesheet" href="{$subdir}media/stylesheet.css" />
+ <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
+ </head>
+ <body>
+ {if $top3}<div class="page-body">{/if}
+
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/include.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/include.tpl
new file mode 100644
index 00000000..bd408aff
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/include.tpl
@@ -0,0 +1,16 @@
+{section name=includes loop=$includes}
+<a name="{$includes[includes].include_file}"><!-- --></a>
+<div class="{cycle values="evenrow,oddrow"}">
+
+ <div>
+ <span class="include-title">
+ <span class="include-type">{$includes[includes].include_name}</span>
+ (<span class="include-name">{$includes[includes].include_value}</span>)
+ (line <span class="line-number">{if $includes[includes].slink}{$includes[includes].slink}{else}{$includes[includes].line_number}{/if}</span>)
+ </span>
+ </div>
+
+ {include file="docblock.tpl" sdesc=$includes[includes].sdesc desc=$includes[includes].desc tags=$includes[includes].tags}
+
+</div>
+{/section} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/index.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/index.tpl
new file mode 100644
index 00000000..477d2b17
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/index.tpl
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//FR"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <!-- Generated by phpDocumentor on {$date} -->
+ <title>{$title}</title>
+ <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
+</head>
+
+<FRAMESET rows='120,*'>
+ <FRAME src='packages.html' name='left_top' frameborder="1" bordercolor="#999999">
+ <FRAMESET cols='25%,*'>
+ <FRAME src='{$start}' name='left_bottom' frameborder="1" bordercolor="#999999">
+ <FRAME src='{$blank}.html' name='right' frameborder="1" bordercolor="#999999">
+ </FRAMESET>
+ <NOFRAMES>
+ <H2>Frame Alert</H2>
+ <P>This document is designed to be viewed using the frames feature.
+ If you see this message, you are using a non-frame-capable web client.</P>
+ </NOFRAMES>
+</FRAMESET>
+</HTML>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/left_frame.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/left_frame.tpl
new file mode 100644
index 00000000..4232d845
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/left_frame.tpl
@@ -0,0 +1,149 @@
+{include file="header.tpl" top2=true}
+<div class="package-title">{$package}</div>
+<div class="package-details">
+
+ <dl class="tree">
+
+ <dt class="folder-title">Description</dt>
+ <dd>
+ <a href='{$classtreepage}.html' target='right'>Class trees</a><br />
+ <a href='{$elementindex}.html' target='right'>Index of elements</a><br />
+ {if $hastodos}
+ <a href="{$todolink}" target="right">Todo List</a><br />
+ {/if}
+ </dd>
+
+ {section name=p loop=$info}
+
+ {if $info[p].subpackage == ""}
+
+ {if $info[p].tutorials}
+ <dt class="folder-title">Tutorials/Manuals</dt>
+ <dd>
+ {if $info[p].tutorials.pkg}
+ <dl class="tree">
+ <dt class="folder-title">Package-level</dt>
+ <dd>
+ {section name=ext loop=$info[p].tutorials.pkg}
+ {$info[p].tutorials.pkg[ext]}
+ {/section}
+ </dd>
+ </dl>
+ {/if}
+
+ {if $info[p].tutorials.cls}
+ <dl class="tree">
+ <dt class="folder-title">Class-level</dt>
+ <dd>
+ {section name=ext loop=$info[p].tutorials.cls}
+ {$info[p].tutorials.cls[ext]}
+ {/section}
+ </dd>
+ </dl>
+ {/if}
+
+ {if $info[p].tutorials.proc}
+ <dl class="tree">
+ <dt class="folder-title">Function-level</dt>
+ <dd>
+ {section name=ext loop=$info[p].tutorials.proc}
+ {$info[p].tutorials.proc[ext]}
+ {/section}
+ </dd>
+ </dl>
+ {/if}
+ </dd>
+ {/if}
+ {if $info[p].classes}
+ <dt class="folder-title">Classes</dt>
+ {section name=class loop=$info[p].classes}
+ <dd><a href='{$info[p].classes[class].link}' target='right'>{$info[p].classes[class].title}</a></dd>
+ {/section}
+ {/if}
+ {if $info[p].functions}
+ <dt class="folder-title">Functions</dt>
+ {section name=f loop=$info[p].functions}
+ <dd><a href='{$info[p].functions[f].link}' target='right'>{$info[p].functions[f].title}</a></dd>
+ {/section}
+ {/if}
+ {if $info[p].files}
+ <dt class="folder-title">Files</dt>
+ {section name=nonclass loop=$info[p].files}
+ <dd><a href='{$info[p].files[nonclass].link}' target='right'>{$info[p].files[nonclass].title}</a></dd>
+ {/section}
+ {/if}
+
+ {else}
+ {if $info[p].tutorials}
+ <dt class="folder-title">Tutorials/Manuals</dt>
+ <dd>
+ {if $info[p].tutorials.pkg}
+ <dl class="tree">
+ <dt class="folder-title">Package-level</dt>
+ <dd>
+ {section name=ext loop=$info[p].tutorials.pkg}
+ {$info[p].tutorials.pkg[ext]}
+ {/section}
+ </dd>
+ </dl>
+ {/if}
+
+ {if $info[p].tutorials.cls}
+ <dl class="tree">
+ <dt class="folder-title">Class-level</dt>
+ <dd>
+ {section name=ext loop=$info[p].tutorials.cls}
+ {$info[p].tutorials.cls[ext]}
+ {/section}
+ </dd>
+ </dl>
+ {/if}
+
+ {if $info[p].tutorials.proc}
+ <dl class="tree">
+ <dt class="folder-title">Function-level</dt>
+ <dd>
+ {section name=ext loop=$info[p].tutorials.proc}
+ {$info[p].tutorials.proc[ext]}
+ {/section}
+ </dd>
+ </dl>
+ {/if}
+ </dd>
+ {/if}
+
+ <dt class="sub-package">{$info[p].subpackage}</dt>
+ <dd>
+ <dl class="tree">
+ {if $info[p].subpackagetutorial}
+ <div><a href="{$info.0.subpackagetutorialnoa}" target="right">{$info.0.subpackagetutorialtitle}</a></div>
+ {/if}
+ {if $info[p].classes}
+ <dt class="folder-title">Classes</dt>
+ {section name=class loop=$info[p].classes}
+ <dd><a href='{$info[p].classes[class].link}' target='right'>{$info[p].classes[class].title}</a></dd>
+ {/section}
+ {/if}
+ {if $info[p].functions}
+ <dt class="folder-title">Functions</dt>
+ {section name=f loop=$info[p].functions}
+ <dd><a href='{$info[p].functions[f].link}' target='right'>{$info[p].functions[f].title}</a></dd>
+ {/section}
+ {/if}
+ {if $info[p].files}
+ <dt class="folder-title">Files</dt>
+ {section name=nonclass loop=$info[p].files}
+ <dd><a href='{$info[p].files[nonclass].link}' target='right'>{$info[p].files[nonclass].title}</a></dd>
+ {/section}
+ {/if}
+ </dl>
+ </dd>
+
+ {/if}
+
+ {/section}
+ </dl>
+</div>
+<p class="notes"><a href="{$phpdocwebsite}" target="_blank">phpDocumentor v <span class="field">{$phpdocversion}</span></a></p>
+</BODY>
+</HTML>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/media/banner.css b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/media/banner.css
new file mode 100644
index 00000000..e67227b7
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/media/banner.css
@@ -0,0 +1,32 @@
+body
+{
+ background-color: #CCCCFF;
+ margin: 0px;
+ padding: 0px;
+}
+
+/* Banner (top bar) classes */
+
+.banner { }
+
+.banner-menu
+{
+ clear: both;
+ padding: .5em;
+ border-top: 2px solid #6666AA;
+}
+
+.banner-title
+{
+ text-align: right;
+ font-size: 20pt;
+ font-weight: bold;
+ margin: .2em;
+}
+
+.package-selector
+{
+ background-color: #AAAADD;
+ border: 1px solid black;
+ color: yellow;
+}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/media/stylesheet.css b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/media/stylesheet.css
new file mode 100644
index 00000000..88f471f2
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/media/stylesheet.css
@@ -0,0 +1,144 @@
+a { color: #336699; text-decoration: none; }
+a:hover { color: #6699CC; text-decoration: underline; }
+a:active { color: #6699CC; text-decoration: underline; }
+
+body { background : #FFFFFF; }
+body, table { font-family: Georgia, Times New Roman, Times, serif; font-size: 10pt }
+p, li { line-height: 140% }
+a img { border: 0px; }
+dd { margin-left: 0px; padding-left: 1em; }
+
+/* Page layout/boxes */
+
+.info-box {}
+.info-box-title { margin: 1em 0em 0em 0em; padding: .25em; font-weight: normal; font-size: 14pt; border: 2px solid #999999; background-color: #CCCCFF }
+.info-box-body { border: 1px solid #999999; padding: .5em; }
+.nav-bar { font-size: 8pt; white-space: nowrap; text-align: right; padding: .2em; margin: 0em 0em 1em 0em; }
+
+.oddrow { background-color: #F8F8F8; border: 1px solid #AAAAAA; padding: .5em; margin-bottom: 1em}
+.evenrow { border: 1px solid #AAAAAA; padding: .5em; margin-bottom: 1em}
+
+.page-body { max-width: 800px; margin: auto; }
+.tree dl { margin: 0px }
+
+/* Index formatting classes */
+
+.index-item-body { margin-top: .5em; margin-bottom: .5em}
+.index-item-description { margin-top: .25em }
+.index-item-details { font-weight: normal; font-style: italic; font-size: 8pt }
+.index-letter-section { background-color: #EEEEEE; border: 1px dotted #999999; padding: .5em; margin-bottom: 1em}
+.index-letter-title { font-size: 12pt; font-weight: bold }
+.index-letter-menu { text-align: center; margin: 1em }
+.index-letter { font-size: 12pt }
+
+/* Docbook classes */
+
+.description {}
+.short-description { font-weight: bold; color: #666666; }
+.tags { padding-left: 0em; margin-left: 3em; color: #666666; list-style-type: square; }
+.parameters { padding-left: 0em; margin-left: 3em; font-style: italic; list-style-type: square; }
+.redefinitions { font-size: 8pt; padding-left: 0em; margin-left: 2em; }
+.package { }
+.package-title { font-weight: bold; font-size: 14pt; border-bottom: 1px solid black }
+.package-details { font-size: 85%; }
+.sub-package { font-weight: bold; font-size: 120% }
+.tutorial { border-width: thin; border-color: #0066ff }
+.tutorial-nav-box { width: 100%; border: 1px solid #999999; background-color: #F8F8F8; }
+.nav-button-disabled { color: #999999; }
+.nav-button:active,
+.nav-button:focus,
+.nav-button:hover { background-color: #DDDDDD; outline: 1px solid #999999; text-decoration: none }
+.folder-title { font-style: italic }
+
+/* Generic formatting */
+
+.field { font-weight: bold; }
+.detail { font-size: 8pt; }
+.notes { font-style: italic; font-size: 8pt; }
+.separator { background-color: #999999; height: 2px; }
+.warning { color: #FF6600; }
+.disabled { font-style: italic; color: #999999; }
+
+/* Code elements */
+
+.line-number { }
+
+.class-table { width: 100%; }
+.class-table-header { border-bottom: 1px dotted #666666; text-align: left}
+.class-name { color: #000000; font-weight: bold; }
+
+.method-summary { padding-left: 1em; font-size: 8pt }
+.method-header { }
+.method-definition { margin-bottom: .3em }
+.method-title { font-weight: bold; }
+.method-name { font-weight: bold; }
+.method-signature { font-size: 85%; color: #666666; margin: .5em 0em }
+.method-result { font-style: italic; }
+
+.var-summary { padding-left: 1em; font-size: 8pt; }
+.var-header { }
+.var-title { margin-bottom: .3em }
+.var-type { font-style: italic; }
+.var-name { font-weight: bold; }
+.var-default {}
+.var-description { font-weight: normal; color: #000000; }
+
+.include-title { }
+.include-type { font-style: italic; }
+.include-name { font-weight: bold; }
+
+.const-title { }
+.const-name { font-weight: bold; }
+
+/* Syntax highlighting */
+
+.src-code { border: 1px solid #336699; padding: 1em; background-color: #EEEEEE; }
+*[class="src-code"] { line-height : 0.5em }
+
+.src-comm { color: green; }
+.src-id { }
+.src-inc { color: #0000FF; }
+.src-key { color: #0000FF; }
+.src-num { color: #CC0000; }
+.src-str { color: #66cccc; }
+.src-sym { font-weight: bold; }
+.src-var { }
+
+.src-php { font-weight: bold; }
+
+.src-doc { color: #009999 }
+.src-doc-close-template { color: #0000FF }
+.src-doc-coretag { color: #0099FF; font-weight: bold }
+.src-doc-inlinetag { color: #0099FF }
+.src-doc-internal { color: #6699cc }
+.src-doc-tag { color: #0080CC }
+.src-doc-template { color: #0000FF }
+.src-doc-type { font-style: italic }
+.src-doc-var { font-style: italic }
+
+.tute-tag { color: #009999 }
+.tute-attribute-name { color: #0000FF }
+.tute-attribute-value { color: #0099FF }
+.tute-entity { font-weight: bold; }
+.tute-comment { font-style: italic }
+.tute-inline-tag { color: #636311; font-weight: bold }
+
+/* tutorial */
+
+.authors { }
+.author { font-style: italic; font-weight: bold }
+.author-blurb { margin: .5em 0em .5em 2em; font-size: 85%; font-weight: normal; font-style: normal }
+.example { border: 1px dashed #999999; background-color: #EEEEEE; padding: .5em; }
+*[class="example"] { line-height : 0.5em }
+.listing { border: 1px dashed #999999; background-color: #EEEEEE; padding: .5em; white-space: nowrap; }
+*[class="listing"] { line-height : 0.5em }
+.release-info { font-size: 85%; font-style: italic; margin: 1em 0em }
+.ref-title-box { }
+.ref-title { }
+.ref-purpose { font-style: italic; color: #666666 }
+.ref-synopsis { }
+.title { font-weight: bold; margin: 1em 0em 0em 0em; padding: .25em; border: 2px solid #999999; background-color: #CCCCFF }
+.cmd-synopsis { margin: 1em 0em }
+.cmd-title { font-weight: bold }
+.toc { margin-left: 2em; padding-left: 0em }
+
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/method.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/method.tpl
new file mode 100644
index 00000000..3138a925
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/method.tpl
@@ -0,0 +1,61 @@
+<A NAME='method_detail'></A>
+{section name=methods loop=$methods}
+<a name="method{$methods[methods].function_name}" id="{$methods[methods].function_name}"><!-- --></a>
+<div class="{cycle values="evenrow,oddrow"}">
+
+ <div class="method-header">
+ <span class="method-title">{if $methods[methods].ifunction_call.constructor}Constructor {elseif $methods[methods].ifunction_call.destructor}Destructor {/if}{$methods[methods].function_name}</span> (line <span class="line-number">{if $methods[methods].slink}{$methods[methods].slink}{else}{$methods[methods].line_number}{/if}</span>)
+ </div>
+
+ {include file="docblock.tpl" sdesc=$methods[methods].sdesc desc=$methods[methods].desc tags=$methods[methods].tags params=$methods[methods].params function=false}
+
+ <div class="method-signature">
+ <span class="method-result">{$methods[methods].function_return}</span>
+ <span class="method-name">
+ {if $methods[methods].ifunction_call.returnsref}&amp;{/if}{$methods[methods].function_name}
+ </span>
+ {if count($methods[methods].ifunction_call.params)}
+ ({section name=params loop=$methods[methods].ifunction_call.params}{if $smarty.section.params.iteration != 1}, {/if}{if $methods[methods].ifunction_call.params[params].default}[{/if}<span class="var-type">{$methods[methods].ifunction_call.params[params].type}</span>&nbsp;<span class="var-name">{$methods[methods].ifunction_call.params[params].name}</span>{if $methods[methods].ifunction_call.params[params].default} = <span class="var-default">{$methods[methods].ifunction_call.params[params].default}</span>]{/if}{/section})
+ {else}
+ ()
+ {/if}
+ </div>
+
+ {if $methods[methods].params}
+ <ul class="parameters">
+ {section name=params loop=$methods[methods].params}
+ <li>
+ <span class="var-type">{$methods[methods].params[params].datatype}</span>
+ <span class="var-name">{$methods[methods].params[params].var}</span>{if $methods[methods].params[params].data}<span class="var-description">: {$methods[methods].params[params].data}</span>{/if}
+ </li>
+ {/section}
+ </ul>
+ {/if}
+
+ {if $methods[methods].method_overrides}
+ <hr class="separator" />
+ <div class="notes">Redefinition of:</div>
+ <dl>
+ <dt>{$methods[methods].method_overrides.link}</dt>
+ {if $methods[methods].method_overrides.sdesc}
+ <dd>{$methods[methods].method_overrides.sdesc}</dd>
+ {/if}
+ </dl>
+ {/if}
+
+ {if $methods[methods].descmethod}
+ <hr class="separator" />
+ <div class="notes">Redefined in descendants as:</div>
+ <ul class="redefinitions">
+ {section name=dm loop=$methods[methods].descmethod}
+ <li>
+ {$methods[methods].descmethod[dm].link}
+ {if $methods[methods].descmethod[dm].sdesc}
+ : {$methods[methods].descmethod[dm].sdesc}
+ {/if}
+ </li>
+ {/section}
+ </ul>
+ {/if}
+</div>
+{/section}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/page.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/page.tpl
new file mode 100644
index 00000000..e5e1913c
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/page.tpl
@@ -0,0 +1,211 @@
+{include file="header.tpl" top3=true}
+
+<h2 class="file-name">{$source_location}</h2>
+
+<a name="sec-description"></a>
+<div class="info-box">
+ <div class="info-box-title">Description</div>
+ <div class="nav-bar">
+ {if $classes || $includes || $defines || $globals || $functions}
+ <span class="disabled">Description</span> |
+ {/if}
+ {if $classes}
+ <a href="#sec-classes">Classes</a>
+ {if $includes || $defines || $globals || $functions}|{/if}
+ {/if}
+ {if $includes}
+ <a href="#sec-includes">Includes</a>
+ {if $defines || $globals || $functions}|{/if}
+ {/if}
+ {if $defines}
+ <a href="#sec-constants">Constants</a>
+ {if $globals || $functions}|{/if}
+ {/if}
+ {if $globals}
+ <a href="#sec-variables">Variables</a>
+ {if $functions}|{/if}
+ {/if}
+ {if $functions}
+ <a href="#sec-functions">Functions</a>
+ {/if}
+ </div>
+ <div class="info-box-body">
+ {include file="docblock.tpl" desc=$desc sdesc=$sdesc tags=$tags}
+
+ {if $tutorial}
+ <hr class="separator" />
+ <div class="notes">Tutorial: <span class="tutorial">{$tutorial}</div>
+ {/if}
+ </div>
+</div>
+
+{if $classes}
+ <a name="sec-classes"></a>
+ <div class="info-box">
+ <div class="info-box-title">Classes</div>
+ <div class="nav-bar">
+ <a href="#sec-description">Description</a> |
+ <span class="disabled">Classes</span>
+ {if $includes || $defines || $globals || $functions}|{/if}
+ {if $includes}
+ <a href="#sec-includes">Includes</a>
+ {if $defines || $globals || $functions}|{/if}
+ {/if}
+ {if $defines}
+ <a href="#sec-constants">Constants</a>
+ {if $globals || $functions}|{/if}
+ {/if}
+ {if $globals}
+ <a href="#sec-variables">Variables</a>
+ {if $functions}|{/if}
+ {/if}
+ {if $functions}
+ <a href="#sec-functions">Functions</a>
+ {/if}
+ </div>
+ <div class="info-box-body">
+ <table cellpadding="2" cellspacing="0" class="class-table">
+ <tr>
+ <th class="class-table-header">Class</th>
+ <th class="class-table-header">Description</th>
+ </tr>
+ {section name=classes loop=$classes}
+ <tr>
+ <td style="padding-right: 2em; vertical-align: top">
+ {$classes[classes].link}
+ </td>
+ <td>
+ {if $classes[classes].sdesc}
+ {$classes[classes].sdesc}
+ {else}
+ {$classes[classes].desc}
+ {/if}
+ </td>
+ </tr>
+ {/section}
+ </table>
+ </div>
+ </div>
+{/if}
+
+{if $includes}
+ <a name="sec-includes"></a>
+ <div class="info-box">
+ <div class="info-box-title">Includes</div>
+ <div class="nav-bar">
+ <a href="#sec-description">Description</a> |
+ {if $classes}
+ <a href="#sec-classes">Classes</a>
+ {if $includes || $defines || $globals || $functions}|{/if}
+ {/if}
+ <span class="disabled">Includes</span>
+ {if $defines || $globals || $functions}|{/if}
+ {if $defines}
+ <a href="#sec-constants">Constants</a>
+ {if $globals || $functions}|{/if}
+ {/if}
+ {if $globals}
+ <a href="#sec-variables">Variables</a>
+ {if $functions}|{/if}
+ {/if}
+ {if $functions}
+ <a href="#sec-functions">Functions</a>
+ {/if}
+ </div>
+ <div class="info-box-body">
+ {include file="include.tpl"}
+ </div>
+ </div>
+{/if}
+
+{if $defines}
+ <a name="sec-constants"></a>
+ <div class="info-box">
+ <div class="info-box-title">Constants</div>
+ <div class="nav-bar">
+ <a href="#sec-description">Description</a> |
+ {if $classes}
+ <a href="#sec-classes">Classes</a>
+ {if $includes || $defines || $globals || $functions}|{/if}
+ {/if}
+ {if $includes}
+ <a href="#sec-includes">Includes</a>
+ {if $defines || $globals || $functions}|{/if}
+ {/if}
+ <span class="disabled">Constants</span>
+ {if $globals || $functions}|{/if}
+ {if $globals}
+ <a href="#sec-variables">Variables</a>
+ {if $functions}|{/if}
+ {/if}
+ {if $functions}
+ <a href="#sec-functions">Functions</a>
+ {/if}
+ </div>
+ <div class="info-box-body">
+ {include file="define.tpl"}
+ </div>
+ </div>
+{/if}
+
+{if $globals}
+ <a name="sec-variables"></a>
+ <div class="info-box">
+ <div class="info-box-title">Variables</div>
+ <div class="nav-bar">
+ <a href="#sec-description">Description</a> |
+ {if $classes}
+ <a href="#sec-classes">Classes</a>
+ {if $includes || $defines || $globals || $functions}|{/if}
+ {/if}
+ {if $includes}
+ <a href="#sec-includes">Includes</a>
+ {if $defines || $globals || $functions}|{/if}
+ {/if}
+ {if $defines}
+ <a href="#sec-constants">Constants</a>
+ {if $globals || $functions}|{/if}
+ {/if}
+ <span class="disabled">Variables</span>
+ {if $functions}|{/if}
+ {if $globals}
+ <a href="#sec-functions">Functions</a>
+ {/if}
+ </div>
+ <div class="info-box-body">
+ {include file="global.tpl"}
+ </div>
+ </div>
+{/if}
+
+{if $functions}
+ <a name="sec-functions"></a>
+ <div class="info-box">
+ <div class="info-box-title">Functions</div>
+ <div class="nav-bar">
+ <a href="#sec-description">Description</a> |
+ {if $classes}
+ <a href="#sec-classes">Classes</a>
+ {if $includes || $defines || $globals || $functions}|{/if}
+ {/if}
+ {if $includes}
+ <a href="#sec-includes">Includes</a>
+ {if $defines || $globals || $functions}|{/if}
+ {/if}
+ {if $defines}
+ <a href="#sec-constants">Constants</a>
+ {if $globals || $functions}|{/if}
+ {/if}
+ {if $globals}
+ <a href="#sec-variables">Variables</a>
+ {if $functions}|{/if}
+ {/if}
+ <span class="disabled">Functions</span>
+ </div>
+ <div class="info-box-body">
+ {include file="function.tpl"}
+ </div>
+ </div>
+{/if}
+
+{include file="footer.tpl" top3=true}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/pkgelementindex.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/pkgelementindex.tpl
new file mode 100644
index 00000000..542af8ed
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/pkgelementindex.tpl
@@ -0,0 +1,17 @@
+{include file="header.tpl"}
+<a name="top"></a>
+<h2>[{$package}] element index</h2>
+{if count($packageindex) > 1}
+ <h3>Package indexes</h3>
+ <ul>
+ {section name=p loop=$packageindex}
+ {if $packageindex[p].title != $package}
+ <li><a href="elementindex_{$packageindex[p].title}.html">{$packageindex[p].title}</a></li>
+ {/if}
+ {/section}
+ </ul>
+{/if}
+<a href="elementindex.html">All elements</a>
+<br />
+{include file="basicindex.tpl" indexname=elementindex_$package}
+{include file="footer.tpl"}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/ric.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/ric.tpl
new file mode 100644
index 00000000..c4cb83f9
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/ric.tpl
@@ -0,0 +1,6 @@
+{include file="header.tpl"}
+<h1 align="center">{$name}</h1>
+<pre>
+{$contents|htmlentities}
+</pre>
+{include file="footer.tpl"} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/todolist.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/todolist.tpl
new file mode 100644
index 00000000..5ab0bca2
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/todolist.tpl
@@ -0,0 +1,14 @@
+{include file="header.tpl" title="Todo List"}
+<div align="center"><h1>Todo List</h1></div>
+{foreach from=$todos key=todopackage item=todo}
+<h2>{$todopackage}</h2>
+{section name=todo loop=$todo}
+<h3>{$todo[todo].link}</h3>
+<ul>
+{section name=t loop=$todo[todo].todos}
+ <li>{$todo[todo].todos[t]}</li>
+{/section}
+</ul>
+{/section}
+{/foreach}
+{include file="footer.tpl"} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/top_frame.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/top_frame.tpl
new file mode 100644
index 00000000..31f559cb
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/top_frame.tpl
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <!-- template designed by Marco Von Ballmoos -->
+ <title>{$title}</title>
+ <link rel="stylesheet" href="{$subdir}media/stylesheet.css" />
+ <link rel="stylesheet" href="{$subdir}media/banner.css" />
+ <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
+ </head>
+ <body>
+ <div class="banner">
+ <div class="banner-title">PRADO API Manual</div>
+ <div class="banner-menu">
+ <table cellpadding="0" cellspacing="0" style="width: 100%">
+ <tr>
+ <td>
+ {if count($ric) >= 1}
+ {assign var="last_ric_name" value=""}
+ {section name=ric loop=$ric}
+ {if $last_ric_name != ""} | {/if}
+ <a href="{$ric[ric].file}" target="right">{$ric[ric].name}</a>
+ {assign var="last_ric_name" value=$ric[ric].name}
+ {/section}
+ {/if}
+ </td>
+ <td style="width: 2em">&nbsp;</td>
+ <td style="text-align: right">
+ {if count($packages) > 1}
+ {assign var="last_package_name" value=""}
+ {section name=p loop=$packages}
+ {if $last_package_name != ""} | {/if}
+ <a href="{$packages[p].link}" target="left_bottom">{$packages[p].title}</a>
+ {assign var="last_package_name" value=$packages[p].title}
+ {/section}
+ {/if}
+ </td>
+ </tr>
+ </table>
+ </div>
+ </div>
+ </body>
+ </html> \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/tutorial.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/tutorial.tpl
new file mode 100644
index 00000000..deb1ee04
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/tutorial.tpl
@@ -0,0 +1,13 @@
+{include file="header.tpl" title=$title top3=true}
+
+{if $nav}
+ {include file="tutorial_nav.tpl" prev=$prev next=$next up=$up prevtitle=$prevtitle nexttitle=$nexttitle uptitle=$uptitle}
+{/if}
+
+{$contents}
+
+{if $nav}
+ {include file="tutorial_nav.tpl" prev=$prev next=$next up=$up prevtitle=$prevtitle nexttitle=$nexttitle uptitle=$uptitle}
+{/if}
+
+{include file="footer.tpl" top3=true} \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/tutorial_nav.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/tutorial_nav.tpl
new file mode 100644
index 00000000..9b42fec8
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/tutorial_nav.tpl
@@ -0,0 +1,41 @@
+<table class="tutorial-nav-box">
+ <tr>
+ <td style="width: 30%">
+ {if $prev}
+ <a href="{$prev}" class="nav-button">Previous</a>
+ {else}
+ <span class="nav-button-disabled">Previous</span>
+ {/if}
+ </td>
+ <td style="text-align: center">
+ {if $up}
+ <a href="{$up}" class="nav-button">Up</a>
+ {/if}
+ </td>
+ <td style="text-align: right; width: 30%">
+ {if $next}
+ <a href="{$next}" class="nav-button">Next</a>
+ {else}
+ <span class="nav-button-disabled">Next</span>
+ {/if}
+ </td>
+ </tr>
+ <tr>
+ <td style="width: 30%">
+ {if $prevtitle}
+ <span class="detail">{$prevtitle}</span>
+ {/if}
+ </td>
+ <td style="text-align: center">
+ {if $uptitle}
+ <span class="detail">{$uptitle}</span>
+ {/if}
+ </td>
+ <td style="text-align: right; width: 30%">
+ {if $nexttitle}
+ <span class="detail">{$nexttitle}</span>
+ {/if}
+ </td>
+ </tr>
+</table>
+ \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/tutorial_toc.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/tutorial_toc.tpl
new file mode 100644
index 00000000..314ebd81
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/tutorial_toc.tpl
@@ -0,0 +1,39 @@
+{if count($toc)}
+<h1 class="title">Table of Contents</h1>
+<ul class="toc">
+ {assign var="lastcontext" value='refsect1'}
+ {section name=toc loop=$toc}
+
+ {if $toc[toc].tagname != $lastcontext}
+ {if $lastcontext == 'refsect1'}
+ <ul class="toc">
+ <li>{$toc[toc].link}</li>
+ {else}
+ {if $lastcontext == 'refsect2'}
+ {if $toc[toc].tagname == 'refsect1'}
+ </ul>
+ <li>{$toc[toc].link}</li>
+ {/if}
+ {if $toc[toc].tagname == 'refsect3'}
+ <ul class="toc">
+ <li>{$toc[toc].link}</li>
+ {/if}
+ {else}
+ </ul>
+ <li>{$toc[toc].link}</li>
+ {/if}
+ {/if}
+ {assign var="lastcontext" value=$toc[toc].tagname}
+ {else}
+ <li>{$toc[toc].link}</li>
+ {/if}
+ {/section}
+ {if $lastcontext == 'refsect2'}
+ </ul>
+ {/if}
+ {if $lastcontext == 'refsect3'}
+ </ul>
+ </ul>
+ {/if}
+</ul>
+{/if}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/tutorial_tree.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/tutorial_tree.tpl
new file mode 100644
index 00000000..d5a18355
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/tutorial_tree.tpl
@@ -0,0 +1,6 @@
+<div><a href="{$main.link}" target="right">{$main.title|strip_tags}</a></div>
+{if $haskids}
+<div style="margin-left: 1em">
+ {$kids}
+</div>
+{/if}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/var.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/var.tpl
new file mode 100644
index 00000000..59c4d8cd
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/default/templates/var.tpl
@@ -0,0 +1,44 @@
+{section name=vars loop=$vars}
+<a name="var{$vars[vars].var_name}" id="{$vars[vars].var_name}"><!-- --></A>
+<div class="{cycle values="evenrow,oddrow"}">
+
+ <div class="var-header">
+ <span class="var-title">
+ <span class="var-type">{$vars[vars].var_type}</span>
+ <span class="var-name">{$vars[vars].var_name}</span>
+ {if $vars[vars].var_default} = <span class="var-default">{$vars[vars].var_default|replace:"\n":"<br />"}</span>{/if}
+ (line <span class="line-number">{if $vars[vars].slink}{$vars[vars].slink}{else}{$vars[vars].line_number}{/if}</span>)
+ </span>
+ </div>
+
+ {include file="docblock.tpl" sdesc=$vars[vars].sdesc desc=$vars[vars].desc tags=$vars[vars].tags}
+
+ {if $vars[vars].var_overrides}
+ <hr class="separator" />
+ <div class="notes">Redefinition of:</div>
+ <dl>
+ <dt>{$vars[vars].var_overrides.link}</dt>
+ {if $vars[vars].var_overrides.sdesc}
+ <dd>{$vars[vars].var_overrides.sdesc}</dd>
+ {/if}
+ </dl>
+ {/if}
+
+ {if $vars[vars].descvar}
+ <hr class="separator" />
+ <div class="notes">Redefined in descendants as:</div>
+ <ul class="redefinitions">
+ {section name=vm loop=$vars[vars].descvar}
+ <li>
+ {$vars[vars].descvar[vm].link}
+ {if $vars[vars].descvar[vm].sdesc}
+ : {$vars[vars].descvar[vm].sdesc}
+ {/if}
+ </li>
+ {/section}
+ </ul>
+ {/if}
+
+</div>
+{/section}
+
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/DescHTML.inc b/buildscripts/PhpDocumentor/phpDocumentor/DescHTML.inc
new file mode 100644
index 00000000..f4fa31d3
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/DescHTML.inc
@@ -0,0 +1,241 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * All abstract representations of html tags in DocBlocks are handled by the
+ * classes in this file
+ *
+ * Before version 1.2, phpDocumentor simply passed html to converters, without
+ * much thought, except the {@link adv_htmlentities()} function was provided
+ * along with a list of allowed html. That list is no longer used, in favor
+ * of these classes.
+ *
+ * The PDF Converter output looked wretched in version 1.1.0 because line breaks
+ * in DocBlocks were honored. This meant that output often had just a few words
+ * on every other line! To fix this problem, DocBlock descriptions are now
+ * parsed using the {@link ParserDescParser}, and split into paragraphs. In
+ * addition, html in DocBlocks are parsed into these objects to allow for easy
+ * conversion in destination converters. This design also allows different
+ * conversion for different templates within a converter, which separates
+ * design from logic almost 100%
+ * @package phpDocumentor
+ * @subpackage DescHTML
+ * @since 1.2
+ */
+/**
+ * Used for <<code>> in a description
+ * @package phpDocumentor
+ * @subpackage DescHTML
+ */
+class parserCode extends parserStringWithInlineTags
+{
+ /**
+ * @param Converter
+ * @uses Converter::ProgramExample()
+ */
+ function Convert(&$c)
+ {
+ if (!isset($this->value[0])) return '';
+ if (is_string($this->value[0]) && $this->value[0]{0} == "\n")
+ {
+ $this->value[0] = substr($this->value[0],1);
+ }
+ $linktags = array();
+ foreach($this->value as $val) {
+ if (phpDocumentor_get_class($val) == 'parserlinkinlinetag' ||
+ phpDocumentor_get_class($val) == 'parsertutorialinlinetag') {
+ $linktags[] = array($c->postProcess($val->Convert($c, false, false)), $val);
+ }
+ }
+ $a = $c->ProgramExample(rtrim(ltrim(parent::Convert($c, false, false), "\n\r")));
+ foreach ($linktags as $tag) {
+ $a = str_replace($tag[0], $tag[1]->Convert($c, false, false), $a);
+ }
+ return $a;
+// else return $c->PreserveWhiteSpace($this->getString(false));
+ }
+}
+
+/**
+ * Used for <<pre>> in a description
+ * @package phpDocumentor
+ * @subpackage DescHTML
+ */
+class parserPre extends parserStringWithInlineTags
+{
+ /**
+ * @param Converter
+ * @uses Converter::PreserveWhiteSpace()
+ */
+ function Convert(&$c)
+ {
+ return $c->PreserveWhiteSpace(rtrim(ltrim(parent::Convert($c, false, false), "\n\r")));
+ }
+}
+
+/**
+ * Used for <<b>> in a description
+ * @package phpDocumentor
+ * @subpackage DescHTML
+ */
+class parserB extends parserStringWithInlineTags
+{
+ /**
+ * @param Converter
+ * @uses Converter::Bolden()
+ */
+ function Convert(&$c)
+ {
+ return $c->Bolden(parent::Convert($c));
+ }
+}
+
+/**
+ * Used for <<i>> in a description
+ * @package phpDocumentor
+ * @subpackage DescHTML
+ */
+class parserI extends parserStringWithInlineTags
+{
+ /**
+ * @param Converter
+ * @uses Converter::Italicize()
+ */
+ function Convert(&$c)
+ {
+ return $c->Italicize(parent::Convert($c));
+ }
+}
+
+/**
+ * Used for <<var>> in a description
+ * @package phpDocumentor
+ * @subpackage DescHTML
+ */
+class parserDescVar extends parserStringWithInlineTags
+{
+ /**
+ * @param Converter
+ * @uses Converter::Varize()
+ */
+ function Convert(&$c)
+ {
+ return $c->Varize(parent::Convert($c));
+ }
+}
+
+/**
+ * Used for <<samp>> in a description
+ * @package phpDocumentor
+ * @subpackage DescHTML
+ */
+class parserSamp extends parserStringWithInlineTags
+{
+ /**
+ * @param Converter
+ * @uses Converter::Sampize()
+ */
+ function Convert(&$c)
+ {
+ return $c->Sampize(parent::Convert($c));
+ }
+}
+
+/**
+ * Used for <<kbd>> in a description
+ * @package phpDocumentor
+ * @subpackage DescHTML
+ */
+class parserKbd extends parserStringWithInlineTags
+{
+ /**
+ * @param Converter
+ * @uses Converter::Kbdize()
+ */
+ function Convert(&$c)
+ {
+ return $c->Kbdize(parent::Convert($c));
+ }
+}
+
+/**
+ * Used for <<br>> in a description
+ * @package phpDocumentor
+ * @subpackage DescHTML
+ */
+class parserBr extends parserStringWithInlineTags
+{
+ /**
+ * @param Converter
+ * @uses Converter::Br()
+ */
+ function Convert(&$c)
+ {
+ return $c->Br($this->getString());
+ }
+}
+
+/**
+ * Used for lists <<ol>> and <<ul>>
+ * @package phpDocumentor
+ * @subpackage DescHTML
+ */
+class parserList extends parserStringWithInlineTags
+{
+ /** @var boolean */
+ var $numbered;
+ /** @var integer */
+ var $items = 0;
+ /**
+ * @param integer
+ */
+ function parserList($numbered)
+ {
+ $this->numbered = $numbered;
+ }
+
+ /** @param parserStringWithInlineTags */
+ function addItem($item)
+ {
+ $this->value[$this->items++] = $item;
+ }
+
+ /** @param parserList */
+ function addList($list)
+ {
+ $this->value[$this->items++] = $list;
+ }
+
+ /**
+ * @uses Converter::ListItem() enclose each item of the list
+ * @uses Converter::EncloseList() enclose the list
+ * @param Converter
+ */
+ function Convert(&$c)
+ {
+ $list = '';
+ foreach($this->value as $item)
+ {
+ $list .= $c->ListItem(trim($item->Convert($c)));
+ }
+ return $c->EncloseList($list,$this->numbered);
+ }
+}
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/DocBlock/Lexer.inc b/buildscripts/PhpDocumentor/phpDocumentor/DocBlock/Lexer.inc
new file mode 100644
index 00000000..edfc896c
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/DocBlock/Lexer.inc
@@ -0,0 +1,701 @@
+<?php
+define('PHPDOC_LEXER_DESC', 1);
+define('PHPDOC_LEXER_TAGS', 2);
+define('PHPDOC_LEXER_ESCTAG', 3);
+define('PHPDOC_LEXER_INLINETAG', 4);
+define('PHPDOC_LEXER_INTERNAL', 5);
+define('PHPDOC_LEXER_INTERNALTAG', 6);
+define('PHPDOC_LEXER_SIMPLELIST', 7);
+define('PHPDOC_DOCBLOCK_TOKEN_NEWLINE', 1);
+define('PHPDOC_DOCBLOCK_TOKEN_DESC', 2);
+define('PHPDOC_DOCBLOCK_TOKEN_ESCTAGOPEN', 3);
+define('PHPDOC_DOCBLOCK_TOKEN_ESCTAGCLOSE', 4);
+define('PHPDOC_DOCBLOCK_TOKEN_TAG', 5);
+define('PHPDOC_DOCBLOCK_TOKEN_INLINETAG', 6);
+define('PHPDOC_DOCBLOCK_TOKEN_INLINETAGCLOSE', 7);
+define('PHPDOC_DOCBLOCK_TOKEN_INTERNAL', 8);
+define('PHPDOC_DOCBLOCK_TOKEN_INTERNALCLOSE', 9);
+define('PHPDOC_DOCBLOCK_TOKEN_HTMLTAG', 10);
+define('PHPDOC_DOCBLOCK_TOKEN_HTMLTAGCLOSE', 11);
+define('PHPDOC_DOCBLOCK_TOKEN_SIMPLELISTSTART', 12);
+define('PHPDOC_DOCBLOCK_TOKEN_SIMPLELISTEND', 13);
+define('PHPDOC_DOCBLOCK_TOKEN_UNORDEREDBULLET', 14);
+define('PHPDOC_DOCBLOCK_TOKEN_ORDEREDBULLET', 15);
+class PhpDocumentor_DocBlock_Lexer
+{
+ var $processedline;
+ var $tagStack = array();
+ var $tokens = array();
+ var $simplelist = array();
+ var $whitespace = array();
+ var $states = array(PHPDOC_LEXER_DESC);
+ function tokenName($token)
+ {
+ $this->tokens = array(
+ PHPDOC_DOCBLOCK_TOKEN_NEWLINE => 'PHPDOC_DOCBLOCK_TOKEN_NEWLINE',
+ PHPDOC_DOCBLOCK_TOKEN_DESC => 'PHPDOC_DOCBLOCK_TOKEN_DESC',
+ PHPDOC_DOCBLOCK_TOKEN_ESCTAGOPEN => 'PHPDOC_DOCBLOCK_TOKEN_ESCTAGOPEN',
+ PHPDOC_DOCBLOCK_TOKEN_ESCTAGCLOSE => 'PHPDOC_DOCBLOCK_TOKEN_ESCTAGCLOSE',
+ PHPDOC_DOCBLOCK_TOKEN_TAG => 'PHPDOC_DOCBLOCK_TOKEN_TAG',
+ PHPDOC_DOCBLOCK_TOKEN_INLINETAG => 'PHPDOC_DOCBLOCK_TOKEN_INLINETAG',
+ PHPDOC_DOCBLOCK_TOKEN_INLINETAGCLOSE => 'PHPDOC_DOCBLOCK_TOKEN_INLINETAGCLOSE',
+ PHPDOC_DOCBLOCK_TOKEN_INTERNAL => 'PHPDOC_DOCBLOCK_TOKEN_INTERNAL',
+ PHPDOC_DOCBLOCK_TOKEN_INTERNALCLOSE => 'PHPDOC_DOCBLOCK_TOKEN_INTERNALCLOSE',
+ );
+ if (in_array($token, array_keys($this->tokens))) {
+ return $this->tokens[$token];
+ }
+ return 'UNKNOWN';
+ }
+
+ function lex($comment)
+ {
+ $comment = str_replace(array("\r\n", "\r"), array("\n", "\n"), $comment);
+ $comment = explode("\n", $comment);
+ $this->tokens = array();
+ $state = PHPDOC_LEXER_DESC;
+ $this->states = array(PHPDOC_LEXER_DESC);
+ $tid = 0;
+ $token = '';
+ $esctag = false;
+ $this->exception = false;
+ list($lastline,) = each(array_reverse($comment, true));
+ foreach ($comment as $this->linenum => $line) {
+ if ($this->exception) {
+ $this->tokens = array();
+ return false;
+ }
+ $linestart = true;
+ $this->processedline = trim($line);
+ if ($this->processedline == '*/') {
+ break;
+ }
+ if (!$this->processedline) {
+ continue;
+ }
+ if (substr($this->processedline, 0, 3) == '/**') {
+ $this->processedline = substr($this->processedline, 3);
+ if (!$this->processedline) {
+ continue;
+ }
+ if (trim($this->processedline) == '*/') {
+ $this->endSimpleList();
+ break;
+ }
+ } else {
+ $this->processedline = substr($this->processedline, 1);
+ }
+ while (true) {
+ switch ($state) {
+ case PHPDOC_LEXER_INTERNALTAG :
+ $internalendpos = strpos($this->processedline, '}}');
+ case PHPDOC_LEXER_TAGS :
+ $trimline = trim($this->processedline);
+ if (strlen($trimline) && $trimline{0} == '@') {
+ if (preg_match('/^(@[^\s]+)\s/', $trimline, $matches) ||
+ preg_match('/^(@[^\s]+)$/', $trimline, $matches)) {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_TAG,
+ $matches[1]);
+ $this->processedline = substr($trimline, strpos($trimline, $matches[1]) +
+ strlen($matches[1]));
+ if (!$this->processedline) {
+ break 2;
+ }
+ continue 2; // to while(true)
+ }
+ } elseif (preg_match('/^@/', $trimline, $matches)) {
+ // throw exception for invalid tag
+ return $this->throwException('Invalid tag encountered in line number ' .
+ $this->linenum . ': "' . $line . '"', 'tag');
+ } else {
+ $tagpos = strpos($this->processedline, '<');
+ $inlinetagpos = strpos($this->processedline, '{@');
+ if (isset($internalendpos) && $internalendpos !== false) {
+ do {
+ if ($tagpos !== false && $internalendpos > $tagpos) {
+ break;
+ }
+ if ($inlinetagpos !== false && $internalendpos > $inlinetagpos) {
+ break;
+ }
+ // }} is the next important token
+ $this->appendDesc(substr($this->processedline, 0,
+ $internalendpos));
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_INTERNALCLOSE, '}}');
+ $this->processedline = substr($this->processedline, $internalendpos
+ + 2);
+ array_shift($this->states);
+ $state = PHPDOC_LEXER_TAGS;
+ continue 3; // to while(true);
+ } while (false);
+ }
+ if ($tagpos !== false && $inlinetagpos !== false) {
+ if ($tagpos > $inlinetagpos) {
+ $tagpos = false;
+ } else {
+ $inlinetagpos = false;
+ }
+ }
+ if ($tagpos !== false) {
+ continue $this->searchForHTMLTag($tagpos,
+ $state, $esctag, $linestart, $trimline);
+ }
+ if ($inlinetagpos !== false) {
+ $state = $this->searchForInlineTag($inlinetagpos, $comment);
+ $linestart = false;
+ continue 2; // to while (true)
+ }
+ if (strpos($this->processedline, '*/')) {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_DESC,
+ substr($this->processedline,
+ 0, strpos($this->processedline, '*/')));
+ return $this->tokens;
+ }
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_DESC, $this->processedline);
+ }
+ break;
+ case PHPDOC_LEXER_INTERNAL :
+ $internalendpos = strpos($this->processedline, '}}');
+ case PHPDOC_LEXER_SIMPLELIST :
+ if ($linestart && $state == PHPDOC_LEXER_SIMPLELIST) {
+ if (!$this->processSimpleList()) {
+ while (count($this->simplelist) && !$this->processSimpleList());
+ }
+ if (!count($this->simplelist)) {
+ array_shift($this->states);
+ $state = array_shift($this->states);
+ array_unshift($this->states, $state);
+ }
+ }
+ case PHPDOC_LEXER_DESC :
+ if (strpos($this->processedline, '*/')) {
+ $this->processedline = substr($this->processedline,
+ 0, strpos($this->processedline, '*/'));
+ }
+ if (!$this->processedline) {
+ if ($this->linenum != $lastline) {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_NEWLINE, "\n");
+ }
+ continue 3; // to foreach
+ }
+ $trimline = trim($this->processedline);
+ if ($linestart && $state != PHPDOC_LEXER_TAGS && $trimline{0} == '@') {
+ if ($state == PHPDOC_LEXER_INTERNAL) {
+ // throw exception
+ return $this->throwException('Cannot start tags in {@internal}} ' .
+ ' in line number ' .
+ $this->linenum . ': "' . $line . '"', 'tag');
+ }
+ $this->states = array(PHPDOC_LEXER_TAGS);
+ $state = PHPDOC_LEXER_TAGS;
+ continue 2; // to while(true)
+
+ }
+ if ($state != PHPDOC_LEXER_SIMPLELIST && $linestart && strlen($trimline) > 3 &&
+ ($trimline{0} == '-' || $trimline{0} == '*' ||
+ $trimline{0} == '#' || $trimline{0} == 'o' ||
+ $trimline{0} == '1')) {
+ if ($this->searchForSimplelist($trimline)) {
+ $state = PHPDOC_LEXER_SIMPLELIST;
+ $linestart = false;
+ continue 2; // to while(true)
+ }
+ }
+ $tagpos = strpos($this->processedline, '<');
+ $inlinetagpos = strpos($this->processedline, '{@');
+ if (isset($internalendpos) && $internalendpos !== false) {
+ do {
+ if ($tagpos !== false && $internalendpos > $tagpos) {
+ break;
+ }
+ if ($inlinetagpos !== false && $internalendpos > $inlinetagpos) {
+ break;
+ }
+ // }} is the next important token
+ $this->appendDesc(substr($this->processedline, 0, $internalendpos));
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_INTERNALCLOSE, '}}');
+ $this->processedline = substr($this->processedline, $internalendpos
+ + 2);
+ array_shift($this->states);
+ $state = PHPDOC_LEXER_DESC;
+ continue 3; // to while(true);
+ } while (false);
+ }
+ if ($tagpos !== false && $inlinetagpos !== false) {
+ if ($tagpos > $inlinetagpos) {
+ $tagpos = false;
+ } else {
+ $inlinetagpos = false;
+ }
+ }
+ if ($tagpos !== false) {
+ continue $this->searchForHTMLTag($tagpos, $state,
+ $esctag, $linestart, $trimline);
+ }
+ if ($inlinetagpos !== false) {
+ $state = $this->searchForInlineTag($inlinetagpos, $comment);
+ $linestart = false;
+ continue 2; // to while (true)
+ }
+ $this->appendDesc($this->processedline);
+ break;
+ case PHPDOC_LEXER_ESCTAG :
+ if (!$this->processedline) {
+ if ($this->linenum != $lastline) {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_NEWLINE, "\n");
+ }
+ continue 3; // to foreach
+ }
+ $endpos = strpos($this->processedline, $esctag);
+ $inlinetagpos = strpos($this->processedline, '{@');
+ if ($endpos !== false && $inlinetagpos !== false) {
+ if ($endpos > $inlinetagpos) {
+ $endpos = false;
+ } else {
+ $inlinetagpos = false;
+ }
+ }
+ if ($endpos !== false) {
+ if (strlen(substr($this->processedline, 0, $endpos))) {
+ $this->appendDesc(substr($this->processedline, 0, $endpos));
+ }
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_ESCTAGCLOSE, $esctag);
+ $this->processedline = substr($this->processedline, $endpos +
+ strlen($esctag));
+ $state = $this->states[0];
+ if (count($this->states) > 1) {
+ array_shift($this->states);
+ }
+ if (!$this->processedline) {
+ break 2;
+ }
+ }
+ if ($inlinetagpos !== false) {
+ array_unshift($this->states, PHPDOC_LEXER_ESCTAG);
+ $state = $this->searchForInlineTag($inlinetagpos, $comment);
+ $linestart = false;
+ continue 2; // to while (true)
+ }
+ $this->appendDesc($this->processedline);
+ break;
+ case PHPDOC_LEXER_INLINETAG :
+ if (!$this->processedline) {
+ if ($this->linenum != $lastline) {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_NEWLINE, "\n");
+ }
+ continue 3; // to foreach
+ }
+ $endpos = strpos($this->processedline, '}');
+ if ($endpos !== false) {
+ if (strlen(substr($this->processedline, 0, $endpos))) {
+ $this->appendDesc(substr($this->processedline, 0, $endpos));
+ }
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_INLINETAGCLOSE, '}');
+ $this->processedline = substr($this->processedline, $endpos + 1); // strlen('}')
+ $state = $this->states[0];
+ if (count($this->states) > 1) {
+ array_shift($this->states);
+ }
+ if (!$this->processedline) {
+ break 2;
+ }
+ if ($state != PHPDOC_LEXER_INLINETAG && strlen($this->processedline)) {
+ $linestart = false;
+ continue 2; // to while (true)
+ }
+ }
+ $this->appendDesc($this->processedline);
+ break;
+ }
+ break;
+ }
+ if ($this->linenum != $lastline) {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_NEWLINE, "\n");
+ }
+ }
+ return $this->tokens;
+ }
+
+ function searchForSimplelist($trimline)
+ {
+ $whitespace = strpos($this->processedline, $trimline);
+ switch ($trimline{0}) {
+ case '-' :
+ case '*' :
+ case '+' :
+ case 'o' :
+ if (strlen($trimline) < 3 || $trimline{1} != ' ') {
+ return false;
+ }
+ // unordered lists
+ $this->simplelist[] = 'u' . $trimline{0};
+ $this->whitespace[] = $whitespace;
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_SIMPLELISTSTART, '');
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_UNORDEREDBULLET, $trimline{0});
+ $this->processedline = substr($this->processedline, strpos($this->processedline,
+ $trimline{0}) + 2);
+ array_unshift($this->states, PHPDOC_LEXER_SIMPLELIST);
+ return true;
+ break;
+ case '#' :
+ if (strlen($trimline) < 3) {
+ return false;
+ }
+ // ordered lists
+ $this->simplelist[] = '#1';
+ $this->whitespace[] = $whitespace;
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_SIMPLELISTSTART, '');
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_ORDEREDBULLET, '#');
+ $this->processedline = substr($this->processedline, strpos($this->processedline,
+ '#') + 2);
+ array_unshift($this->states, PHPDOC_LEXER_SIMPLELIST);
+ return true;
+ case '1' :
+ if (strlen($trimline) < 4) {
+ return false;
+ }
+ if ($trimline{1} == ' ') {
+ $this->simplelist[] = 'O1';
+ } elseif ($trimline{1} == '.' && $trimline{2} == ' ') {
+ $this->simplelist[] = 'o1';
+ } else {
+ return false;
+ }
+ $this->whitespace[] = $whitespace;
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_SIMPLELISTSTART, '');
+ if ($trimline{1} == '.') {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_ORDEREDBULLET, '1.');
+ $this->processedline = substr($this->processedline, strpos($this->processedline,
+ '1.') + 3);
+ } else {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_ORDEREDBULLET, '1');
+ $this->processedline = substr($this->processedline, strpos($this->processedline,
+ '1') + 2);
+ }
+ array_unshift($this->states, PHPDOC_LEXER_SIMPLELIST);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @todo process multi-line elements via whitespace
+ * @todo process nested simple lists
+ */
+ function processSimpleList()
+ {
+ $trimline = trim($this->processedline);
+ $index = count($this->simplelist) - 1;
+ $whitespace = strpos($this->processedline, $trimline);
+ if ($whitespace < $this->whitespace[$index]) {
+ while (count($this->whitespace[$index]) && $whitespace < $this->whitespace[$index]) {
+ // the end of the current simplelist
+ $this->tokens = array(PHPDOC_DOCBLOCK_TOKEN_SIMPLELISTEND, '');
+ array_pop($this->simplelist);
+ $index--;
+ }
+ if ($index == -1) {
+ return false; // all simple lists concluded
+ }
+ }
+ if ($whitespace > $this->whitespace[$index]) {
+ // could be a multi-line element or a new list
+ if (!$this->searchForSimplelist($trimline)) {
+ // trim off the simple list whitespace if this is multi-line
+ $this->processedline = substr($this->processedline, $this->whitespace[$index] + 2);
+ }
+ return true;
+ }
+ // implied: whitespace matches exactly so this is either another
+ // bullet point or the end of the simple list
+ switch ($this->simplelist[$index]{0}) {
+ case 'u' :
+ if (strlen($trimline) < 3 || $trimline{0} != $this->simplelist[$index]{1} ||
+ $trimline{1} != ' ') {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_SIMPLELISTEND, '');
+ array_pop($this->simplelist);
+ return false;
+ }
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_UNORDEREDBULLET, $trimline{0});
+ $this->processedline = substr($this->processedline, strpos($this->processedline,
+ $trimline{0}) + 2);
+ break;
+ case 'o' :
+ if (strlen($trimline) < 4 || ($trimline{0} !=
+ ($this->simplelist[$index]{1} + 1) . '') ||
+ $trimline{1} != '.' || $trimline{2} != ' ') {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_SIMPLELISTEND, '');
+ array_pop($this->simplelist);
+ return false;
+ }
+ $this->simplelist[$index] = $this->simplelist[$index]{0} .
+ ($this->simplelist[$index]{1} + 1);
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_ORDEREDBULLET,
+ $this->simplelist[$index]{1} . '.');
+ $this->processedline = substr($this->processedline, strpos($this->processedline,
+ $trimline{0} . '.') + 3);
+ break;
+ case 'O' :
+ if (strlen($trimline) < 3 || $trimline{0} != ($this->simplelist[$index]{1} + 1) . '' ||
+ $trimline{1} != ' ') {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_SIMPLELISTEND, '');
+ array_pop($this->simplelist);
+ return false;
+ }
+ $this->simplelist[$index] = $this->simplelist[$index]{0} .
+ ($this->simplelist[$index]{1} + 1);
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_ORDEREDBULLET,
+ $this->simplelist[$index]{1});
+ $this->processedline = substr($this->processedline, strpos($this->processedline,
+ $this->simplelist[$index]{1}) + 2);
+ break;
+ case '#' :
+ if (strlen($trimline) < 3 || $trimline{0} != '#' ||
+ $trimline{1} != ' ') {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_SIMPLELISTEND, '');
+ array_pop($this->simplelist);
+ return false;
+ }
+ $this->simplelist[$index] = $this->simplelist[$index]{0} .
+ ($this->simplelist[$index]{1} + 1);
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_ORDEREDBULLET,
+ $this->simplelist[$index]{1});
+ $this->processedline = substr($this->processedline, strpos($this->processedline,
+ '#') + 2);
+ break;
+ }
+ return true;
+ }
+
+ function searchForHTMLTag($tagpos, &$state, &$esctag, &$linestart,
+ &$trimline)
+ {
+ if (preg_match('/^<(<\/?[a-zA-Z]+ ?\/?>)>/', substr($this->processedline, $tagpos),
+ $matches)) {
+ if ($tagpos) {
+ $this->appendDesc(substr($this->processedline, 0, $tagpos));
+ }
+ $this->appendDesc($matches[1]);
+ $this->processedline = substr($this->processedline, $tagpos
+ + strlen($matches[1])
+ + 2);
+ return 2;
+ } elseif (!count($matches) &&
+ preg_match('/^<(<\/?[a-zA-Z]+ ?\/?>)>/', substr($this->processedline, $tagpos + 1),
+ $matches)) {
+ if ($tagpos) {
+ $this->appendDesc(substr($this->processedline, 0, $tagpos));
+ }
+ $this->appendDesc('<' . $matches[1]);
+ $this->processedline = substr($this->processedline, $tagpos
+ + strlen($matches[1])
+ + 3);
+ return 2;
+ } elseif (preg_match('#^(br>|br/>|br />)#',
+ substr($this->processedline, $tagpos + 1), $matches)) {
+ if ($tagpos) {
+ $this->appendDesc(substr($this->processedline, 0, $tagpos));
+ }
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_HTMLTAG, 'br');
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_HTMLTAGCLOSE, 'br');
+ $this->processedline = substr($this->processedline, $tagpos
+ + strlen($matches[1])
+ + 1);
+ return 2;
+ } elseif (preg_match('/^(b>|i>|li>|ol>|ul>|p>|pre>|var>)/',
+ substr($this->processedline, $tagpos + 1), $matches)) {
+ if ($tagpos) {
+ $this->appendDesc(substr($this->processedline, 0, $tagpos));
+ }
+ $matches = substr($matches[1], 0, strlen($matches[1]) - 1);
+ array_push($this->tagStack, $matches);
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_HTMLTAG, $matches);
+ $this->processedline = substr($this->processedline, $tagpos
+ + strlen($matches)
+ + 2);
+ return 2;
+ } elseif (preg_match('#^(/b>|/i>|/li>|/ol>|/ul>|/p>|/pre>|/var>)#',
+ substr($this->processedline, $tagpos + 1), $matches)) {
+ if ($tagpos) {
+ $this->appendDesc(substr($this->processedline, 0, $tagpos));
+ }
+ $matches = substr($matches[1], 1, strlen($matches[1]) - 2);
+ $test = array_pop($this->tagStack);
+ if ($matches != $test) {
+ // throw exception
+ $this->throwException('Invalid closing html tag encountered in line number ' .
+ $this->linenum . ': "</' . $matches . '>", expecting "</' . $test . '>"', 'htmltag');
+ return 3;
+ }
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_HTMLTAGCLOSE, $matches);
+ $this->processedline = substr($this->processedline, $tagpos
+ + strlen($matches)
+ + 3);
+ return 2;
+ } elseif (preg_match('/^(code>|pre>|kbd>|samp>)/',
+ substr($this->processedline, $tagpos + 1), $matches)) {
+ $esctag = '</' . $matches[0];
+ if ($tagpos) {
+ $this->appendDesc(substr($this->processedline, 0, $tagpos));
+ }
+ switch ($matches[0]) {
+ case 'code>' :
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_ESCTAGOPEN,
+ '<code>');
+ break;
+ case 'pre>' :
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_ESCTAGOPEN,
+ '<pre>');
+ break;
+ case 'kbd>' :
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_ESCTAGOPEN,
+ '<kbd>');
+ break;
+ case 'samp>' :
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_ESCTAGOPEN,
+ '<samp>');
+ break;
+ }
+ $this->processedline = $line = substr($this->processedline, $tagpos
+ + strlen($matches[0])
+ + 1);
+ $state = PHPDOC_LEXER_ESCTAG;
+ if (!$this->processedline) {
+ return 3; // to foreach
+ }
+ if (strpos($this->processedline, $esctag) !== false) {
+ if (!strpos($this->processedline, $esctag)) {
+ $linestart = false;
+ return 2; // to while (true)
+ }
+ if (strpos($this->processedline, $esctag)) {
+ $this->appendDesc(substr($this->processedline, 0,
+ strpos($this->processedline, $esctag)));
+ }
+ $this->processedline = $trimline =
+ substr($this->processedline, strpos($this->processedline, $esctag));
+ $linestart = false;
+ return 2; // to while(true)
+ }
+ }
+ }
+
+ function searchForInlineTag($inlinetagpos, $comment)
+ {
+ if ($inlinetagpos) {
+ $this->appendDesc(substr($this->processedline, 0, $inlinetagpos));
+ }
+ if ($inlinetagpos === strpos($this->processedline, '{@internal')) {
+ $state = array_shift($this->states);
+ array_unshift($this->states, $state);
+ if ($state == PHPDOC_LEXER_INTERNAL || $state == PHPDOC_LEXER_INTERNALTAG) {
+ // throw exception
+ return $this->throwException('cannot nest {@internal}} in line number ' .
+ $this->linenum . ': "' . $line . '"', 'internaltag');
+ }
+ $basestate = array_pop($this->states);
+ array_push($this->states, $basestate);
+ if ($basestate == PHPDOC_LEXER_DESC) {
+ $newstate = PHPDOC_LEXER_INTERNAL;
+ } else {
+ $newstate = PHPDOC_LEXER_INTERNALTAG;
+ }
+ array_unshift($this->states, $newstate);
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_INTERNAL, '{@internal');
+ $this->processedline = substr($this->processedline, $inlinetagpos + strlen('{@internal'));
+ return $newstate;
+ }
+ if (!preg_match('/^({@[^}\s]+)\s/', substr($this->processedline, $inlinetagpos), $matches)) {
+ if (!preg_match('/^({@[^}\s]+)}/', substr($this->processedline, $inlinetagpos), $matches)) {
+ if ($this->hasEndchar($comment, '}')) {
+ $matches = array(substr($this->processedline, $inlinetagpos),
+ substr($this->processedline, $inlinetagpos));
+ } else {
+ // throw exception if this does not match
+ $this->throwException('Unclosed inline tag encountered on line number ' .
+ $this->linenum . ': "' . $line . '"', 'tag');
+ return PHPDOC_LEXER_DESC;
+ }
+ } else {
+ // throw exception if this does not match
+ $this->throwException('Invalid inline tag encountered in line number ' .
+ $this->linenum . ': "' . $line . '"', 'tag');
+ return PHPDOC_LEXER_DESC;
+ }
+ }
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_INLINETAG, $matches[1]);
+ $this->processedline = substr($this->processedline, $inlinetagpos + strlen($matches[1]));
+ return PHPDOC_LEXER_INLINETAG;
+ }
+
+ function appendDesc($desc)
+ {
+ if (!strlen($desc)) {
+ return;
+ }
+ if (count($this->tokens)) {
+ $last = array_pop($this->tokens);
+ if ($last[0] == PHPDOC_DOCBLOCK_TOKEN_DESC) {
+ $last[1] .= $desc;
+ $this->tokens[] = $last;
+ } else {
+ $this->tokens[] = $last;
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_DESC, $desc);
+ }
+ } else {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_DESC, $desc);
+ }
+ }
+
+ function hasEndChar($comment, $char)
+ {
+ $linenum = $this->linenum;
+ foreach ($comment as $num => $line) {
+ if ($linenum !== false && $num <= $linenum) {
+ continue;
+ }
+ $linenum = false;
+ $processedline = trim($line);
+ if ($processedline == '*/') {
+ break;
+ }
+ if (!$processedline) {
+ continue;
+ }
+ if (substr($processedline, 0, 3) == '/**') {
+ $processedline = substr($processedline, 3);
+ if (!$processedline) {
+ continue;
+ }
+ if (trim($processedline) == '*/') {
+ break;
+ }
+ } else {
+ $processedline = substr($processedline, 1);
+ }
+ if (strpos($processedline, $char) !== false) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ function endSimpleList()
+ {
+ if (count($this->tagStack)) {
+ $this->tokens = array();
+ return $this->throwException('Error: unclosed html tags: "' .
+ implode(', ', $this->tagStack) . '"', 'simplelist');
+ }
+ while (count($this->simplelist)) {
+ $this->tokens[] = array(PHPDOC_DOCBLOCK_TOKEN_SIMPLELISTEND, '');
+ }
+ }
+
+ function throwException($message, $type)
+ {
+ $this->error = array($message, $this->linenum, $type);
+ $this->exception = true;
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/DocBlockTags.inc b/buildscripts/PhpDocumentor/phpDocumentor/DocBlockTags.inc
new file mode 100644
index 00000000..fa465deb
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/DocBlockTags.inc
@@ -0,0 +1,984 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * All abstract representations of DocBlock tags are defined
+ * by the classes in this file
+ * @package phpDocumentor
+ * @subpackage DocBlockTags
+ * @since separate file since version 1.2
+ */
+/**
+ * used to represent standard tags like @access, etc.
+ * This class is aware of inline tags, and will automatically handle them
+ * using inherited functions
+ * @package phpDocumentor
+ * @subpackage DocBlockTags
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: DocBlockTags.inc,v 1.1 2005/10/17 18:36:55 jeichorn Exp $
+ */
+class parserTag extends parserStringWithInlineTags
+{
+ /**
+ * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'
+ * always '_tag'
+ * @var string
+ */
+ var $type = '_tag';
+ /**
+ * tag name (see, access, etc.)
+ * @var string
+ */
+ var $keyword = '';
+
+ /**
+ * Set up the tag
+ *
+ * {@source}
+ * @param string $keyword tag name
+ * @param parserStringWithInlineTags $value
+ * @param boolean whether to parse the $value for html tags
+ */
+ function parserTag($keyword, $value, $noparse = false)
+ {
+ $this->keyword = $keyword;
+ if (!$noparse)
+ {
+ $parser = new parserDescParser;
+ $parser->subscribe('*',$this);
+ $parser->parse($value->value,true,'parserstringwithinlinetags');
+ } else $this->value = $value;
+ }
+
+ /**
+ * @param Converter
+ * @see Converter
+ */
+ function Convert(&$converter)
+ {
+ if (is_array($this->value))
+ {
+ if (count($this->value) == 1)
+ {
+ list(,$val) = each($this->value);
+ reset($this->value);
+ return $val->Convert($converter);
+ }
+ $result = '';
+ foreach($this->value as $val)
+ {
+ // this is only true if we processed the description in
+ // the constructor
+ if (phpDocumentor_get_class($val) == 'parserstringwithinlinetags')
+ $result .= $converter->EncloseParagraph($val->Convert($converter));
+ else
+ $result .= $val->Convert($converter);
+ }
+ return $result;
+ } else
+ {
+ return $this->value->Convert($converter);
+ }
+ }
+
+ /**
+ * Gets a count of the number of paragraphs in this
+ * tag's description.
+ *
+ * Useful in determining whether to enclose the
+ * tag in a paragraph or not.
+ * @access private
+ * @return integer
+ */
+ function _valueParagraphCount()
+ {
+ }
+
+ /**
+ * Called by the {@link parserDescParser} when processing a description.
+ * @param integer not used
+ * @param array array of {@link parserStringWithInlineTags} representing
+ * paragraphs in the tag description
+ * @see parserTag::parserTag()
+ */
+ function HandleEvent($a,$desc)
+ {
+ $this->value = $desc;
+ }
+
+ /**
+ * @return string returns the text minus any inline tags
+ * @see parserStringWithInlineTags::getString()
+ */
+ function getString()
+ {
+ if (is_array($this->value))
+ {
+ $result = '';
+ foreach($this->value as $val)
+ {
+ $result .= $val->getString();
+ }
+ return $result;
+ } else return $this->value->getString();
+ }
+}
+
+/**
+ * This class represents the @name tag
+ * @tutorial tags.name.pkg
+ * @package phpDocumentor
+ * @subpackage DocBlockTags
+ */
+class parserNameTag extends parserTag
+{
+ /**
+ * tag name
+ * @var string
+ */
+ var $keyword = 'name';
+
+ /**
+ * @param string not used
+ * @param string name
+ */
+ function parserNameTag($name, $value)
+ {
+ $this->value = $value;
+ }
+
+ /**
+ * @see parserStringWithInlineTags::Convert()
+ * @param Converter
+ * @return string converted value of the tag
+ */
+ function Convert(&$c)
+ {
+ return $this->value;
+ }
+}
+
+/**
+ * This class represents the @access tag
+ * @tutorial tags.access.pkg
+ * @package phpDocumentor
+ * @subpackage DocBlockTags
+ */
+class parserAccessTag extends parserTag
+{
+ /**
+ * tag name
+ * @var string
+ */
+ var $keyword = 'access';
+
+ /**
+ * set to true if the returned tag has a value type of private, protected
+ * or public, false otherwise
+ * @var boolean
+ */
+ var $isvalid = false;
+
+ /**
+ * checks $value to make sure it is private, protected or public, otherwise
+ * it's not a valid @access tag
+ * @see $isvalid
+ * @param parserStringWithInlineTags $value
+ */
+ function parserAccessTag($value)
+ {
+ if (!is_string($value))
+ {
+ if (is_object($value))
+ {
+ if (method_exists($value,'getstring'))
+ {
+ $value = $value->getString();
+ }
+ }
+ }
+ switch(trim($value))
+ {
+ case 'private' :
+ case 'public' :
+ case 'protected' :
+ $this->value = $value;
+ $this->isvalid = true;
+ break;
+ default :
+ addError(PDERROR_ACCESS_WRONG_PARAM,$value);
+ $this->value = 'public';
+ break;
+ }
+ }
+
+ /**
+ * @see parserStringWithInlineTags::Convert()
+ * @param Converter
+ * @return string converted value of the tag
+ */
+ function Convert(&$converter)
+ {
+ return $this->value;
+ }
+
+ /**
+ * No inline tags are possible, returns 'public', 'protected' or 'private'
+ * @return string returns the text minus any inline tags
+ */
+ function getString()
+ {
+ return $this->value;
+ }
+}
+
+/**
+ * represents "@return"
+ * @tutorial tags.return.pkg
+ * @package phpDocumentor
+ * @subpackage DocBlockTags
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: DocBlockTags.inc,v 1.1 2005/10/17 18:36:55 jeichorn Exp $
+ */
+class parserReturnTag extends parserTag
+{
+ /**
+ * always 'return'
+ * @var string
+ */
+ var $keyword = 'return';
+ /**
+ * the type a function returns
+ */
+ var $returnType = 'void';
+
+ /**
+ * contains a link to the documentation for a class passed as a type in @return, @var or @param
+ *
+ * Example:
+ *
+ * <code>
+ * class myclass
+ * {
+ * ...
+ * }
+ * /** @return myclass blahblahblah
+ * ...
+ * </code>
+ *
+ * In this case, $converted_returnType will contain a link to myclass instead of the string 'myclass'
+ * @var mixed either the same as $returnType or a link to the docs for a class
+ * @see $returnType
+ */
+ var $converted_returnType = false;
+
+ /**
+ * @param string
+ * @param parserStringWithInlineTags
+ */
+ function parserReturnTag($returnType, $value)
+ {
+ $this->returnType = $returnType;
+ parent::parserTag('return',$value);
+ }
+
+ /**
+ * sets up $converted_returnType
+ * @see parserStringWithInlineTags::Convert(), $converted_returnType
+ * @param Converter
+ * @return string converted value of the tag
+ */
+ function Convert(&$converter)
+ {
+ $my_types = '';
+ if (strpos($this->returnType,'|'))
+ {
+ $types = explode('|',$this->returnType);
+ foreach($types as $returntype)
+ {
+ $a = $converter->getLink($returntype);
+ if (is_object($a) && phpDocumentor_get_class($a) == 'classlink')
+ {
+ if (!empty($my_types)) $my_types .= '|';
+ $my_types .= $converter->returnSee($a,$converter->type_adjust($returntype));
+ } else
+ {
+ if (!empty($my_types)) $my_types .= '|';
+ $my_types .= $converter->type_adjust($returntype);
+ }
+ }
+ $this->converted_returnType = $my_types;
+ } else
+ {
+ $a = $converter->getLink($this->returnType);
+ if (is_object($a) && phpDocumentor_get_class($a) == 'classlink')
+ {
+ $this->converted_returnType = $converter->returnSee($a,$converter->type_adjust($this->returnType));
+ } else
+ {
+ $this->converted_returnType = $converter->type_adjust($this->returnType);
+ }
+ }
+ return parserTag::Convert($converter);
+ }
+}
+
+/**
+ * represents "@var"
+ * @tutorial tags.var.pkg
+ * @package phpDocumentor
+ * @subpackage DocBlockTags
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: DocBlockTags.inc,v 1.1 2005/10/17 18:36:55 jeichorn Exp $
+ */
+class parserVarTag extends parserReturnTag
+{
+ /**
+ * always 'var'
+ * @var string
+ */
+ var $keyword = 'var';
+ /**
+ * the type a var has
+ * @var string
+ */
+ var $returnType = 'mixed';
+}
+
+/**
+ * Represents "@param"
+ * @tutorial tags.param.pkg
+ * @package phpDocumentor
+ * @subpackage DocBlockTags
+ */
+class parserParamTag extends parserVarTag
+{
+ /**
+ * always 'param'
+ * @var string
+ */
+ var $keyword = 'param';
+}
+
+/**
+ * Represents "@staticvar"
+ * @tutorial tags.staticvar.pkg
+ * @package phpDocumentor
+ * @subpackage DocBlockTags
+ */
+class parserStaticvarTag extends parserParamTag
+{
+ /**
+ * always 'staticvar'
+ * @var string
+ */
+ var $keyword = 'staticvar';
+}
+
+/**
+ * represents "@link"
+ * @tutorial tags.link.pkg
+ * @package phpDocumentor
+ * @subpackage DocBlockTags
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: DocBlockTags.inc,v 1.1 2005/10/17 18:36:55 jeichorn Exp $
+ */
+class parserLinkTag extends parserTag
+{
+ /**
+ * always 'link'
+ * @var string
+ */
+ var $keyword = 'link';
+
+ /**
+ * URL to link to
+ * @param string $link
+ */
+ function parserLinkTag($link)
+ {
+ $start = $val = $link->getString();
+ if (strpos($val,' '))
+ {
+ $start = array_shift($val = explode(' ',$val));
+ $val = join($val, ' ');
+ }
+ $a = new parserLinkInlineTag($start,$val);
+ $b = new parserStringWithInlineTags;
+ $b->add($a);
+ $this->value = $b;
+ }
+}
+
+/**
+ * represents "@see"
+ * @tutorial tags.see.pkg
+ * @package phpDocumentor
+ * @subpackage DocBlockTags
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: DocBlockTags.inc,v 1.1 2005/10/17 18:36:55 jeichorn Exp $
+ */
+class parserSeeTag extends parserLinkTag
+{
+ /**
+ * always 'see'
+ * @var string
+ */
+ var $keyword = 'see';
+
+ /**
+ * @param string element to link to
+ */
+ function parserSeeTag($name)
+ {
+ parserTag::parserTag($this->keyword,$name,true);
+ }
+
+ /**
+ * @param Converter
+ * @see parserStringWithInlineTags::Convert()
+ */
+ function Convert(&$converter)
+ {
+ if ($this->value->hasInlineTag())
+ {
+ addErrorDie(PDERROR_INLINETAG_IN_SEE);
+ }
+ $a = $converter->getLink(trim($this->value->Convert($converter)));
+ if (is_string($a))
+ {
+ // feature 564991
+ if (strpos($a,'://'))
+ {
+ // php function
+ return $converter->returnLink($a,str_replace('PHP_MANUAL#','',$this->value->Convert($converter)));
+ }
+ return $a;
+ }
+ if (is_object($a)) return $converter->returnSee($a);
+ // getLink parsed a comma-delimited list of linked thingies, add the commas back in
+ if (is_array($a))
+ {
+ $b = '';
+ foreach($a as $i => $bub)
+ {
+ if (!empty($b)) $b .= ', ';
+ if (is_string($a[$i])) $b .= $a[$i];
+ if (is_object($a[$i])) $b .= $converter->returnSee($a[$i]);
+ }
+ return $b;
+ }
+ return false;
+ }
+}
+
+/**
+ * represents "@license"
+ *
+ * Link to a license, instead of including lines and lines of license information
+ * in every file
+ * @tutorial tags.license.pkg
+ * @package phpDocumentor
+ * @subpackage DocBlockTags
+ */
+class parserLicenseTag extends parserLinkTag
+{
+ /**
+ * always 'license'
+ * @var string
+ */
+ var $keyword = 'license';
+
+ /**
+ * URL to link to
+ * @param string $link
+ */
+ function parserLicenseTag($name, $link)
+ {
+ $a = explode(' ',$link->getString());
+ $url = array_shift($a);
+ $license = join($a,' ');
+ if (empty($license)) $license = $url;
+ $a = new parserLinkInlineTag($url, $license);
+ $b = new parserStringWithInlineTags;
+ $b->add($a);
+ $this->value = $b;
+ }
+}
+
+/**
+ * represents "@uses"
+ *
+ * This is exactly like @see except that the element used has a @useby link to this element added to its docblock
+ * @package phpDocumentor
+ * @subpackage DocBlockTags
+ * @tutorial tags.uses.pkg
+ * @since 1.2
+ */
+class parserUsesTag extends parserSeeTag
+{
+ /**
+ * Always "uses"
+ * @var string
+ */
+ var $keyword = 'uses';
+ /** @access private */
+ var $_description;
+
+ /**
+ * @param string element to link to
+ * @param parserStringWithInlineTags description of how the element is used
+ */
+ function parserUsesTag($seeel, $description)
+ {
+ parent::parserSeeTag($seeel);
+ $this->_description = $description;
+ }
+
+ /**
+ * Return a link to documentation for other element, and description of how
+ * it is used
+ *
+ * Works exactly like {@link parent::Convert()} except that it also includes
+ * a description of how the element used is used.
+ * @return string
+ * @param Converter
+ */
+ function Convert(&$c)
+ {
+ $val = $this->value;
+ $see = parent::Convert($c);
+ $this->value = $this->_description;
+ $desc_val = parserTag::Convert($c);
+ if (!empty($desc_val)) {
+ $see .= ' - '.$desc_val;
+ }
+ $this->value = $val;
+ return $see;
+ }
+
+ /**
+ * Get the text of the link to the element that is being used
+ * @return string
+ * @access private
+ */
+ function getSeeElement()
+ {
+ return $this->value->getString();
+ }
+
+ /**
+ * Get the description of how the element used is being used.
+ * @return parserStringWithInlineTags
+ */
+ function getDescription()
+ {
+ return $this->_description;
+ }
+}
+
+/**
+ * This is a virtual tag, it is created by @uses to cross-reference the used element
+ *
+ * This is exactly like @uses.
+ * @package phpDocumentor
+ * @subpackage DocBlockTags
+ * @since 1.2
+ */
+class parserUsedByTag extends parserUsesTag
+{
+ /**
+ * Always "usedby"
+ * @var string
+ */
+ var $keyword = 'usedby';
+ /** @access private */
+ var $_link;
+
+ /**
+ * @param abstractLink link of element that uses this element
+ * @param string description of how the element is used
+ */
+ function parserUsedByTag($link, $description)
+ {
+ $this->value = $description;
+ $this->_link = $link;
+ }
+
+ /**
+ * @return string
+ * @param Converter
+ */
+ function Convert(&$c)
+ {
+ $see = $c->returnSee($this->_link);
+ $desc_val = parserTag::Convert($c);
+ if (!empty($desc_val)) {
+ $see .= ' - '.$desc_val;
+ }
+ return $see;
+ }
+}
+
+/**
+ * represents "@tutorial"
+ *
+ * This is exactly like @see except that it only links to tutorials
+ * @tutorial phpDocumentor/tutorials.pkg
+ * @tutorial tags.tutorial.pkg
+ * @package phpDocumentor
+ * @subpackage DocBlockTags
+ * @since 1.2
+ */
+class parserTutorialTag extends parserSeeTag
+{
+ /**
+ * Always "tutorial"
+ * @var string
+ */
+ var $keyword = 'tutorial';
+ /**
+ * @param Converter
+ * @see parserStringWithInlineTags::Convert()
+ */
+ function Convert(&$converter)
+ {
+ $a = $converter->getTutorialLink(trim($this->value->Convert($converter)));
+ if (is_string($a))
+ {
+ return $a;
+ }
+ if (is_object($a)) return $converter->returnSee($a);
+ // getLink parsed a comma-delimited list of linked thingies, add the commas back in
+ if (is_array($a))
+ {
+ $b = '';
+ foreach($a as $i => $bub)
+ {
+ if (!empty($b)) $b .= ', ';
+ if (is_string($a[$i])) $b .= $a[$i];
+ if (is_object($a[$i])) $b .= $converter->returnSee($a[$i]);
+ }
+ return $b;
+ }
+ return false;
+ }
+}
+
+/**
+ * represents "@filesource"
+ *
+ * Use this to create a link to a highlighted phpxref-style source file listing
+ * @package phpDocumentor
+ * @subpackage DocBlockTags
+ * @tutorial tags.filesource.pkg
+ */
+class parserFileSourceTag extends parserTag
+{
+ /**
+ * Always "filesource"
+ * @var string
+ */
+ var $keyword = 'filesource';
+ /** @var array */
+ var $source;
+ /** @var string */
+ var $path;
+ /**
+ * Flag variable, controls double writes of file for each converter
+ * @access private
+ * @var array
+ */
+ var $_converted = array();
+ /**
+ * Set {@link $source} to $value, and set up path
+ * @param string
+ * @param array output from {@link phpDocumentorTWordParser::getFileSource()}
+ */
+ function parserFileSourceTag($filepath, $value)
+ {
+ parent::parserTag($this->keyword, '');
+ $this->path = $filepath;
+ $this->source = $value;
+ }
+
+ /**
+ * Return a link to the highlighted source and generate the source
+ * @uses ConvertSource() generate source code and write it out
+ * @return string output from {@link getSourceLink()}
+ * @param Converter
+ */
+ function Convert(&$c)
+ {
+ if (!isset($this->_converted[$c->name]))
+ {
+ $this->ConvertSource($c);
+ $this->_converted[$c->name] = true;
+ }
+ return $this->getSourceLink($c);
+ }
+
+ /**
+ * @param Converter
+ * @uses phpDocumentor_HighlightParser highlights source code
+ * @uses writeSource()
+ */
+ function ConvertSource(&$c)
+ {
+ $this->writeSource($c, $c->ProgramExample($this->source, true, false, false, false, $this->path));
+ return;
+ $parser = new phpDocumentor_HighlightParser;
+ $return = '';
+ $return = $parser->parse($this->source,$c, false, false, false, $this->path);
+ $this->writeSource($c, $return);
+ }
+
+ /**
+ * @param Converter
+ * @param string highlighted source code
+ * @uses Converter::writeSource() export highlighted file source
+ */
+ function writeSource(&$c, $source)
+ {
+ $c->writeSource($this->path, $source);
+ }
+
+ /**
+ * @uses Converter::getSourceLink()
+ * @param Converter
+ * @return output from getSourceLink()
+ */
+ function getSourceLink(&$c)
+ {
+ return $c->getSourceLink($this->path);
+ }
+}
+
+/**
+ * represents "@example"
+ *
+ * The example tag
+ * @package phpDocumentor
+ * @subpackage DocBlockTags
+ * @tutorial tags.example.pkg
+ */
+class parserExampleTag extends parserFileSourceTag
+{
+ /**
+ * always "example"
+ * @var string
+ */
+ var $keyword = 'example';
+ /**
+ * Reads and parses the example file indicated
+ *
+ * The example tag takes one parameter: the full path to a php file that
+ * should be parsed and included as an example.
+ * @uses phpDocumentorTWordParser::getFileSource() uses to parse an example
+ * and retrieve all tokens by line number
+ * @param parserStringWithInlineTags
+ * @param string path of file containing this @example tag
+ */
+ function parserExampleTag($value, $current_path)
+ {
+ global $_phpDocumentor_setting;
+ parent::parserTag('example', $value);
+ $path = false;
+ // code thanks to Sam Blum, modified by Greg Beaver
+ $tagValue = $value->getString();
+ $path = $isAbsPath = $pathOnly = $fileName = $fileExt = $original_path = $title = FALSE;
+ do
+ {
+ // make sure the format is stuff.ext description
+ if (!preg_match('`(.*)\.(\w*)\s(.*)`', $tagValue, $match))
+ {
+ // or format is stuff.ext
+ if (!preg_match('`(.*)\.(\w*)\s*$`', $tagValue, $match))
+ {
+ // Murphy: Some funny path was given
+ $original_path = $tagValue; // used for error output
+ break; // try-block
+ }
+ }
+ if (strlen($match[1]) === 0)
+ {
+ // Murphy: Some funny path was given
+ $original_path = $tagValue; // used for error output
+ break; // try-block
+ }
+ $fileExt = $match[2];
+ $title = 'example';
+ if (isset($match[3]))
+ {
+ $title = trim($match[3]);
+ }
+ $pathTmp = str_replace('\\', '/', $match[1]); // Replace windows '\' the path.
+
+ // Is there a path and a file or is it just a file?
+ if (strpos($pathTmp,'/') === false)
+ {
+ // No path part
+ $pathOnly = '';
+ $fileName = $pathTmp .'.'. $fileExt;
+ } else
+ {
+ $splitPos = strrpos($pathTmp,'/'); // split the path on the last directory, find the filename
+ $pathOnly = substr($match[1], 0, $splitPos+1);
+ $fileName = substr($match[1], $splitPos+1) .'.'. $fileExt;
+ // Is the path absolute? (i.e. does it start like an absolute path?)
+ if (('/' === $pathTmp[0]) || preg_match('`^\w*:`i', $pathTmp))
+ { // works for both windows 'C:' and URLs like 'http://'
+ $isAbsPath = true; // Yes
+ }
+ }
+
+ $original_path = $pathOnly . $fileName;
+
+ // Now look for the file starting with abs. path.
+ if ($isAbsPath)
+ {
+ $tmp = realpath($original_path); // remove any weirdities like /../file.ext
+ if ($tmp && is_file($tmp))
+ {
+ $path = $tmp;
+ }
+ // Alway break if abs. path was detected; even if file was not found.
+ break; // try-block
+ }
+
+ // Search for the example file some standard places
+ // 1) Look if the ini-var examplesdir is set and look there ...
+ if (isset($_phpDocumentor_setting['examplesdir']))
+ {
+ $tmp = realpath($_phpDocumentor_setting['examplesdir'] . PATH_DELIMITER . $original_path);
+ if ($tmp && is_file($tmp))
+ {
+ $path = $tmp; // Yo! found it :)
+ break; // try-block
+ }
+ }
+
+ // 2) Then try to look for an 'example/'-dir below the *currently* parsed file ...
+ if (!empty($current_path))
+ {
+ $tmp = realpath(dirname($current_path) . PATH_DELIMITER . 'examples' . PATH_DELIMITER . $fileName);
+ if ($tmp && is_file($tmp))
+ {
+ $path = $tmp; // Yo! found it :)
+ break; // try-block
+ }
+ }
+
+ // 3) Then try to look for the example file below the subdir PHPDOCUMENTOR_BASE/examples/ ...
+ if (is_dir(PHPDOCUMENTOR_BASE . PATH_DELIMITER . 'examples'))
+ {
+ $tmp = realpath(PHPDOCUMENTOR_BASE . PATH_DELIMITER . 'examples' . PATH_DELIMITER . $original_path);
+ if ($tmp && is_file($tmp))
+ {
+ $path = $tmp; // Yo! found it :)
+ break; // try-block
+ }
+ }
+
+ $tmp = realpath(PHPDOCUMENTOR_BASE . PATH_DELIMITER . $original_path);
+ if ($tmp && is_file($tmp))
+ {
+ $path = $tmp; // Yo! found it :)
+ break; // try-block
+ }
+ // If we reach this point, nothing was found and $path is false.
+ } while (false);
+
+ if (!$path)
+ {
+ addWarning(PDERROR_EXAMPLE_NOT_FOUND, $original_path);
+ $this->_title = 'example not found';
+ $this->path = false;
+ } else
+ {
+ $this->_title = ($title) ? $title : 'example';
+ // make a unique html-filename but avoid it to get too long.
+ $uniqueFileName = str_replace(array(':', DIRECTORY_SEPARATOR,'/'), array('_', '_', '_'), $path);
+ $uniqueFileName = substr($uniqueFileName,-50) . '_' . md5($path);
+ $this->path = $uniqueFileName;
+
+ $f = @fopen($path,'r');
+ if ($f)
+ {
+ $example = fread($f,filesize($path));
+ if (tokenizer_ext)
+ {
+ $obj = new phpDocumentorTWordParser;
+ $obj->setup($example);
+ $this->source = $obj->getFileSource();
+ unset($obj);
+ } else
+ {
+ $this->source = $example;
+ }
+ }
+ }
+ }
+
+ /**
+ * @param Converter
+ * @uses phpDocumentor_HighlightParser highlights source code
+ * @uses writeSource()
+ */
+ function ConvertSource(&$c)
+ {
+ $this->writeSource($c, $c->ProgramExample($this->source, true));
+ return;
+ $parser = new phpDocumentor_HighlightParser;
+ $return = '';
+ $return = $parser->parse($this->source,$c);
+ $this->writeSource($c, $return);
+ }
+
+ /**
+ * @param Converter $c
+ * @param string parsed example source
+ * @uses Converter::writeExample() writes final example out
+ * @access private
+ */
+ function writeSource(&$c, $source)
+ {
+ if ($this->path)
+ $c->writeExample($this->_title, $this->path, $source);
+ }
+
+ /**
+ * Retrieve a converter-specific link to the example
+ *
+ * @param Converter
+ * @uses Converter::getExampleLink() retrieve the link to the example
+ */
+ function getSourceLink(&$c)
+ {
+ if (!$this->path) return $this->_title;
+ return $c->getExampleLink($this->path, $this->_title);
+ }
+}
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Errors.inc b/buildscripts/PhpDocumentor/phpDocumentor/Errors.inc
new file mode 100644
index 00000000..99bada26
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Errors.inc
@@ -0,0 +1,793 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * @package phpDocumentor
+ * @subpackage Errors
+ * @author Gregory Beaver <cellog@users.sourceforge.net>
+ * @version $Id: Errors.inc,v 1.1 2005/10/17 18:36:55 jeichorn Exp $
+ */
+/**
+ * warning triggered when inheritance could be from more than one class
+ */
+define("PDERROR_MULTIPLE_PARENT",1);
+/**
+ * warning triggered when parent class doesn't exist
+ */
+define("PDERROR_PARENT_NOT_FOUND",2);
+/**
+ * warning triggered when an {@inline tag} is not terminated (no } before the * / ending the comment)
+ */
+define("PDERROR_UNTERMINATED_INLINE_TAG",3);
+/**
+ * warning triggered when inheritance could be from more than one class
+ */
+define("PDERROR_CLASS_EXISTS",4);
+/**
+ * warning triggered when inheritance could be from more than one class
+ */
+define("PDERROR_INHERITANCE_CONFLICT",5);
+/**
+ * warning triggered when a converter is passed to {@link phpDocumentor_IntermediateParser::addConverter()} that is not a class
+ */
+define("PDERROR_CONVERTER_NOT_FOUND",6);
+/**
+ * warning triggered when a converter is passed to {@link phpDocumentor_IntermediateParser::addConverter()} that is not a class
+ */
+define("PDERROR_NO_CONVERTERS",7);
+/**
+ * warning triggered when the arguments to @access are neither public nor private
+ */
+define("PDERROR_ACCESS_WRONG_PARAM",8);
+/**
+ * warning triggered when there are multiple @access tags in a docblock
+ */
+define("PDERROR_MULTIPLE_ACCESS_TAGS",9);
+/**
+ * warning triggered when there are multiple @return tags in a docblock
+ */
+define("PDERROR_MULTIPLE_RETURN_TAGS",10);
+/**
+ * warning triggered when there are multiple @var tags in a docblock
+ */
+define("PDERROR_MULTIPLE_VAR_TAGS",11);
+/**
+ * warning triggered when there are multiple @package tags in a docblock
+ */
+define("PDERROR_MULTIPLE_PACKAGE_TAGS",12);
+/**
+ * warning triggered when there are multiple @subpackage tags in a docblock
+ */
+define("PDERROR_MULTIPLE_SUBPACKAGE_TAGS",13);
+/**
+ * warning triggered when the package or subpackage name is illegal
+ */
+define("PDERROR_ILLEGAL_PACKAGENAME",14);
+/**
+ * warning triggered when there a @package tag is used in a function, define, method, var or include
+ */
+define("PDERROR_OVERRIDDEN_PACKAGE_TAGS",15);
+/**
+ * warning triggered when there a @subpackage tag is used in a function, define, method, var or include
+ */
+define("PDERROR_OVERRIDDEN_SUBPACKAGE_TAGS",16);
+/**
+ * warning triggered when classes in the same package have the same name
+ */
+define("PDERROR_CLASS_CONFLICT",17);
+/**
+ * warning triggered when classes in the same package have the same name
+ */
+define("PDERROR_UNKNOWN_TAG",18);
+/**
+ * warning triggered when there are multiple @name tags in a docblock
+ */
+define("PDERROR_MULTIPLE_NAME_TAGS",19);
+/**
+ * warning triggered when there are multiple @name tags in a docblock
+ */
+define("PDERROR_PACKAGEOUTPUT_DELETES_PARENT_FILE",20);
+/**
+ * warning triggered when there are multiple @name tags in a docblock
+ */
+define("PDERROR_GLOBAL_NOT_FOUND",21);
+/**
+ * warning triggered when there are multiple @name tags in a docblock
+ */
+define("PDERROR_MULTIPLE_GLOBAL_TAGS",22);
+/**
+ * warning triggered when there are multiple @name tags in a docblock
+ */
+define("PDERROR_MALFORMED_GLOBAL_TAG",23);
+/**
+ * warning triggered when an @ignore tag is used in a DocBlock preceding a method, variable, include, or global variable
+ */
+define("PDERROR_IGNORE_TAG_IGNORED",24);
+/**
+ * warning triggered when a duplicate element is encountered that will be ignored by the documentor
+ */
+define("PDERROR_ELEMENT_IGNORED",25);
+/**
+ * warning triggered when an entire page is ignored because of @access private
+ */
+define("PDERROR_PARSEPRIVATE",26);
+/**
+ * warning triggered when an entire page is ignored because of @access private
+ */
+define("PDERROR_UNKNOWN_COMMANDLINE",27);
+/**
+ * warning triggered when an entire page is ignored because of @access private
+ */
+define("PDERROR_NEED_WHITESPACE",28);
+/**
+ * warning triggered when an entire page is ignored because of @access private
+ */
+define("PDERROR_CLASS_PARENT_NOT_FOUND",29);
+/**
+ * warning triggered when a getClassByPackage is called and can't find the class
+ */
+define("PDERROR_CLASS_NOT_IN_PACKAGE",30);
+/**
+ * warning triggered when a { @source } inline tag is used in a docblock not preceding a function
+ */
+define("PDERROR_SOURCE_TAG_FUNCTION_NOT_FOUND",31);
+/**
+ * warning triggered when a docblock template is never turned off with /**#@-* / (no space)
+ */
+define("PDERROR_DB_TEMPLATE_UNTERMINATED",32);
+/**
+ * warning triggered when a docblock has an unmatched &lt;ol&gt; or &lt;ul&gt;
+ */
+define("PDERROR_UNMATCHED_LIST_TAG",33);
+/**
+ * warning triggered when another tag is nested in &lt;b&gt; - not allowed in phpDocumentor
+ */
+define("PDERROR_CANT_NEST_IN_B",34);
+/**
+ * warning triggered when a docbook tag is not properly matched
+ */
+define("PDERROR_UNMATCHED_TUTORIAL_TAG",35);
+/**
+ * warning triggered when an inline tag is found inside an xml tag name in a package page
+ */
+define("PDERROR_CANT_HAVE_INLINE_IN_TAGNAME",36);
+/**
+ * warning triggered when a tutorial is referenced via @tutorial/{ @tutorial} and is not found
+ */
+define("PDERROR_TUTORIAL_NOT_FOUND",37);
+/**
+ * warning triggered when a tutorial lists itself as a child tutorial
+ */
+define("PDERROR_TUTORIAL_IS_OWN_CHILD",38);
+/**
+ * warning triggered when a tutorial's child lists the parent tutorial as a child tutorial
+ */
+define("PDERROR_TUTORIAL_IS_OWN_GRANDPA",39);
+/**
+ * warning triggered when a tutorial's child in the .ini file doesn't exist in the
+ * package and subpackage of the parent
+ */
+define("PDERROR_CHILD_TUTORIAL_NOT_FOUND",40);
+/**
+ * warning triggered when a <pdffunction:funcname /> tag is used in the PDF
+ * Converter and no funcname is present (<pdffunction: />)
+ */
+define("PDERROR_PDFFUNCTION_NO_FUNC",41);
+/**
+ * warning triggered when a <pdffunction:funcname /> tag is used in the PDF
+ * Converter and funcname is not a {@link Cezpdf} method
+ */
+define("PDERROR_PDF_METHOD_DOESNT_EXIST",42);
+/**
+ * warning triggered when a <pdffunction:funcname arg=$tempvar/> tag is used in the PDF
+ * Converter and "tempvar" is not set from the return of a previous pdffunction tag
+ */
+define("PDERROR_PDF_TEMPVAR_DOESNT_EXIST",43);
+/**
+ * warning triggered when a subsection's title is asked for, but the subsection is not found
+ */
+define("PDERROR_TUTORIAL_SUBSECTION_NOT_FOUND",44);
+/**
+ * warning triggered when a subsection's title is asked for, but the subsection is not found
+ */
+define("PDERROR_UNTERMINATED_ATTRIB",45);
+/**
+ * warning triggered when no @package tag is used in a page-level or class-level DocBlock
+ */
+define("PDERROR_NO_PACKAGE_TAG",46);
+/**
+ * warning triggered when no @access private tag is used in a global variable/method/var
+ * with _ as first char in name and --pear was specified
+ */
+define("PDERROR_PRIVATE_ASSUMED",47);
+/**
+ * warning triggered when an example's path from @example /path/to/example.php
+ * is not found
+ */
+define("PDERROR_EXAMPLE_NOT_FOUND",48);
+/**
+ * warning triggered when an example's path from @example /path/to/example.php
+ * is not found
+ */
+define("PDERROR_NO_CONVERTER_HANDLER",49);
+/**
+ * warning triggered when an example's path from @example /path/to/example.php
+ * is not found
+ */
+define("PDERROR_INLINETAG_IN_SEE",50);
+/**
+ * warning triggered when an id attribute in a tutorial docbook tag is not
+ * an {@}id} inline tag
+ */
+define("PDERROR_ID_MUST_BE_INLINE",51);
+/**
+ * warning triggered when an {@}internal}} tag is not closed
+ */
+define("PDERROR_INTERNAL_NOT_CLOSED",52);
+/**
+ * warning triggered when an {@}source} tag is found in a short description
+ */
+define("PDERROR_SOURCE_TAG_IGNORED",53);
+/**
+ * warning triggered when a child converter doesn't override getFormattedClassTrees()
+ */
+define("PDERROR_CONVERTER_OVR_GFCT",54);
+/**
+ * warning triggered when a package is already associated with a category, and
+ * a new association is found
+ */
+define("PDERROR_PACKAGECAT_SET",55);
+/**
+ * warning triggered when text in a docblock list is not contained in
+ * an <<li>> opening tag
+ */
+define("PDERROR_TEXT_OUTSIDE_LI",56);
+/**
+ * warning triggered when a DocBlock html tag is unclosed
+ */
+define("PDERROR_UNCLOSED_TAG",57);
+/**
+ * warning triggered by @filesource, if PHP < 4.3.0
+ */
+define("PDERROR_TAG_NOT_HANDLED",58);
+/**
+ * warning triggered by sourcecode="on", if PHP < 4.3.0
+ */
+define("PDERROR_SOURCECODE_IGNORED",59);
+/**
+ * warning triggered by an empty tag
+ */
+define("PDERROR_MALFORMED_TAG",60);
+/**
+ * warning triggered by more than 1 @category tag
+ */
+define("PDERROR_MULTIPLE_CATEGORY_TAGS",61);
+/**
+ * warning triggered by {@}inheritdoc} in a non-inheritable situation
+ */
+define("PDERROR_INHERITDOC_DONT_WORK_HERE",62);
+/**
+ * warning triggered by @example path/to/example with no title
+ */
+define("PDERROR_EMPTY_EXAMPLE_TITLE",63);
+/**
+ * warning triggered by non-existent template directory
+ */
+define("PDERROR_TEMPLATEDIR_DOESNT_EXIST",64);
+/**
+ * warning triggered by an unterminated entity in a tutorial
+ */
+define("PDERROR_UNTERMINATED_ENTITY",65);
+/**
+ * warning triggered by an unterminated entity in a tutorial
+ */
+define("PDERROR_BEAUTIFYING_FAILED",66);
+/**
+ * warning triggered by a function with no name
+ *
+ * <pre>
+ * function ($params)
+ * {
+ * }
+ * </pre>
+ * triggers this error
+ */
+define("PDERROR_FUNCTION_HAS_NONAME",67);
+/**
+ * warning triggered by a page-level docblock preceding a source element
+ *
+ * <code>
+ * <?php
+ * /**
+ * * Page-level DocBlock
+ * * @package pagepackage
+ * *{@*}
+ * include 'file.php';
+ * </code>
+ */
+define("PDERROR_DOCBLOCK_CONFLICT", 68);
+/**
+ * warning triggered when a file does not contain a page-level docblock
+ */
+define("PDERROR_NO_PAGE_LEVELDOCBLOCK", 69);
+/**
+ * warning triggered when the first docblock in a file with a @package tag
+ * precedes a class. In this case, the class gets the docblock.
+ */
+define("PDERROR_DOCBLOCK_GOES_CLASS", 70);
+/**
+ * warning triggered in tutorial parsing if there is a missing {@id} inline tag
+ */
+define("PDERROR_NO_DOCBOOK_ID", 71);
+/**
+ * warning triggered if someone brilliant tries "class X extends X {"
+ */
+define("PDERROR_CANNOT_EXTEND_SELF", 72);
+
+/**
+ * Error messages for phpDocumentor parser warnings
+ * @global array $GLOBALS['phpDocumentor_warning_descrip']
+ * @name $phpDocumentor_warning_descrip
+ */
+$GLOBALS['phpDocumentor_warning_descrip'] =
+ array(
+ PDERROR_MULTIPLE_PARENT => 'Class %s has multiple possible parents, package inheritance aborted',
+ PDERROR_PARENT_NOT_FOUND => 'Class %s parent %s not found',
+ PDERROR_INHERITANCE_CONFLICT => 'Class %s in file %s has multiple possible parents named %s. Cannot resolve name conflict,'."\n".' try ignoring a file that contains the conflicting parent class',
+ PDERROR_UNKNOWN_TAG => 'Unknown tag "@%s" used',
+ PDERROR_IGNORE_TAG_IGNORED => '@ignore tag used for %s element "%s" will be ignored',
+ PDERROR_ELEMENT_IGNORED => "\n".'duplicate %s element "%s" in file %s will be ignored.'."\n".'Use an @ignore tag on the original if you want this case to be documented.',
+ PDERROR_PARSEPRIVATE => "entire page %s ignored because of @access private.\nChoose -pp to enable parsing of private elements",
+ PDERROR_CLASS_PARENT_NOT_FOUND => "class %s in package %s parent not found in @see parent::%s",
+ PDERROR_CLASS_NOT_IN_PACKAGE => "class %s was not found in package %s",
+ PDERROR_DB_TEMPLATE_UNTERMINATED => "docblock template never terminated with /**#@-*/",
+ PDERROR_PDF_METHOD_DOESNT_EXIST => '<pdffunction:%s /> called, but pdf method "%s" doesn\'t exist',
+ PDERROR_TUTORIAL_NOT_FOUND => "tutorial \"%s\" not found, does it exist?",
+ PDERROR_CHILD_TUTORIAL_NOT_FOUND => 'child tutorial "%s" listed in %s not found in parent package "%s" subpackage "%s"',
+ PDERROR_TUTORIAL_SUBSECTION_NOT_FOUND => 'tutorial %s subsection "%s" doesn\'t exist, but its title was asked for',
+ PDERROR_NO_PACKAGE_TAG => 'no @package tag was used in a DocBlock for %s %s',
+ PDERROR_PRIVATE_ASSUMED => '%s "%s" is assumed to be @access private because its name starts with _, but has no @access tag',
+ PDERROR_EXAMPLE_NOT_FOUND => 'example file "%s" does not exist',
+ PDERROR_SOURCE_TAG_IGNORED => '{@source} can only be used in the long description, not in the short description: "%s"',
+ PDERROR_PACKAGECAT_SET => 'package %s is already in category %s, will now replace with category %s',
+ PDERROR_SOURCECODE_IGNORED => 'sourcecode command-line option is ignored for PHP versions < 4.3.0',
+ PDERROR_INHERITDOC_DONT_WORK_HERE => '{@inheritdoc} can only be used in the docblock of a child class',
+ PDERROR_EMPTY_EXAMPLE_TITLE => 'Example file found at "%s" has no title, using "%s"',
+ PDERROR_DOCBLOCK_CONFLICT => 'Page-level DocBlock precedes "%s %s", use another DocBlock to document the source element',
+ PDERROR_NO_PAGE_LEVELDOCBLOCK => 'File "%s" has no page-level DocBlock, use @package in the first DocBlock to create one',
+ PDERROR_DOCBLOCK_GOES_CLASS => 'DocBlock would be page-level, but precedes class "%s", use another DocBlock to document the file',
+ PDERROR_NO_DOCBOOK_ID => 'Tutorial section %s "%s" has no id="{@id subsection}" tag ({@id} for refentry)',
+ PDERROR_BEAUTIFYING_FAILED => 'Beautifying failed: %s',
+ );
+
+
+
+//********************************************************
+
+
+
+/**
+ * Error messages for phpDocumentor parser errors
+ * @global array $GLOBALS['phpDocumentor_error_descrip']
+ * @name $phpDocumentor_error_descrip
+ */
+$GLOBALS['phpDocumentor_error_descrip'] =
+ array(
+ PDERROR_UNTERMINATED_INLINE_TAG => 'Inline tag {@%s} in tag %s is unterminated, "%s"',
+ PDERROR_CLASS_EXISTS => 'Class %s already exists in package "%s"',
+ PDERROR_CONVERTER_NOT_FOUND => 'Converter %s specified by --output command-line option is not a class',
+ PDERROR_NO_CONVERTERS => 'No Converters have been specified by --output command-line option',
+ PDERROR_ACCESS_WRONG_PARAM => '@access was passed neither "public" nor "private." Was passed: "%s"',
+ PDERROR_MULTIPLE_ACCESS_TAGS => 'DocBlock has multiple @access tags, illegal. ignoring additional tag "@access %s"',
+ PDERROR_MULTIPLE_RETURN_TAGS => 'DocBlock has multiple @return tags, illegal. ignoring additional tag "@return %s %s"',
+ PDERROR_MULTIPLE_VAR_TAGS => 'DocBlock has multiple @var tags, illegal. ignoring additional tag "@var %s %s"',
+ PDERROR_MULTIPLE_PACKAGE_TAGS => 'DocBlock has multiple @package tags, illegal. ignoring additional tag "@package %s"',
+ PDERROR_MULTIPLE_SUBPACKAGE_TAGS => 'DocBlock has multiple @subpackage tags, illegal. ignoring additional tag "@subpackage %s"',
+ PDERROR_ILLEGAL_PACKAGENAME => '@%s tag has illegal %s name "%s"',
+ PDERROR_OVERRIDDEN_PACKAGE_TAGS => '%s %s\'s DocBlock has @package tag, illegal. ignoring tag "@package %s"',
+ PDERROR_OVERRIDDEN_SUBPACKAGE_TAGS => '"%s" %s\'s DocBlock has @subpackage tags, illegal. ignoring tag "@subpackage %s"',
+ PDERROR_CLASS_CONFLICT => 'class "%s" has multiple declarations in package %s, in file %s and file %s, documentation will have output errors!',
+ PDERROR_MULTIPLE_NAME_TAGS => 'DocBlock has multiple @name tags, illegal. ignoring additional tag "@name %s"',
+ PDERROR_PACKAGEOUTPUT_DELETES_PARENT_FILE => '-po (packageoutput) option deletes parent file "%s" containing class "%s."'."\n".' Try using --defaultpackagename (-dn) %s to include the parent file in the same package as the class',
+ PDERROR_GLOBAL_NOT_FOUND => 'global variable %s specified in @global tag was never found',
+ PDERROR_MULTIPLE_GLOBAL_TAGS => '@global define tag already used for global variable "%s", ignoring @global %s',
+ PDERROR_MALFORMED_GLOBAL_TAG => 'incorrect @global syntax. Should be @global vartype $varname or @global vartype description',
+ PDERROR_UNKNOWN_COMMANDLINE => 'Unknown command-line option "%s" encountered, use phpdoc -h for help',
+ PDERROR_NEED_WHITESPACE => 'phpDocumentor programmer error - wordparser whitespace set to false in handleDocBlock, notify developers. You should never see this error',
+ PDERROR_SOURCE_TAG_FUNCTION_NOT_FOUND => '{@source} tag used in a docblock that isn\'t preceding a function',
+ PDERROR_UNMATCHED_LIST_TAG => 'unmatched ol or ul tag in DocBlock, parsing will be incorrect',
+ PDERROR_CANT_NEST_IN_B => 'Can\'t nest a code, pre, ul, or ol tag in a b tag in phpDocumentor DocBlock (%s tag nested)',
+ PDERROR_UNMATCHED_TUTORIAL_TAG => 'While parsing extended documentation, "%s" tag was matched with "%s" endtag, missing endtag'."\ntag contents:\"%s\"",
+ PDERROR_CANT_HAVE_INLINE_IN_TAGNAME => 'Can\'t have an inline tag inside a package page XML tag!',
+ PDERROR_TUTORIAL_IS_OWN_CHILD => 'Tutorial %s lists itself as its own child in %s, illegal',
+ PDERROR_TUTORIAL_IS_OWN_GRANDPA => 'Tutorial %s\'s child %s lists %s as its child in %s, illegal',
+ PDERROR_PDFFUNCTION_NO_FUNC => 'Invalid pdffunction syntax: "<pdffunction: />", should be "<pdffunction:functionname [arg="value"...]/>"',
+ PDERROR_PDF_TEMPVAR_DOESNT_EXIST => '<pdffunction:%s arg=%s /> called but temporary variable "%s" doesn\'t exist',
+ PDERROR_UNTERMINATED_ATTRIB => 'Tutorial tag %s attribute %s is unterminated, current value "%s"',
+ PDERROR_NO_CONVERTER_HANDLER => 'Handler for element of type "%s" called, but %s is not a method of %s',
+ PDERROR_INLINETAG_IN_SEE => 'Inline tags are not allowed in a @see tag',
+ PDERROR_ID_MUST_BE_INLINE => '<%s id="%s"> must be <%s id="{@id %s}">',
+ PDERROR_INTERNAL_NOT_CLOSED => '{@internal was never terminated with }}',
+ PDERROR_CONVERTER_OVR_GFCT => 'Converter "%s" must override getFormattedClassTrees() but doesn\'t',
+ PDERROR_TEXT_OUTSIDE_LI => 'Text cannot be outside of li tag in a DocBlock list, parsing will be incorrect',
+ PDERROR_UNCLOSED_TAG => 'Unclosed %s tag in DocBlock, parsing will be incorrect',
+ PDERROR_TAG_NOT_HANDLED => '"%s" tag is not available in PHP versions less than 4.3.0, tag ignored',
+ PDERROR_MALFORMED_TAG => '"%s" tag was used without any parameters, illegal',
+ PDERROR_MULTIPLE_CATEGORY_TAGS => 'package has multiple @category tags, ignoring "@category %s"',
+ PDERROR_TEMPLATEDIR_DOESNT_EXIST => 'template directory "%s" does not exist',
+ PDERROR_UNTERMINATED_ENTITY => 'entity &%s is unterminated',
+ PDERROR_FUNCTION_HAS_NONAME => 'function has no name (PHP error - test your file before parsing!)',
+ PDERROR_CANNOT_EXTEND_SELF => 'class %s cannot extend itself - TEST YOUR CODE BEFORE PARSING',
+ );
+
+/**
+ * encapsulates warning information
+ * @package phpDocumentor
+ * @subpackage Errors
+ */
+class RecordWarning
+{
+ /**
+ * name of global variable that descriptors for this warning/error is kept
+ * @var string
+ */
+ var $type = 'phpDocumentor_warning_descrip';
+ /**
+ * file this error occurred in
+ * @var string
+ */
+ var $file = false;
+ /**
+ * line number of the file this error occurred in
+ * @var integer
+ */
+ var $linenum;
+ /**
+ * error string
+ * @var string
+ */
+ var $data;
+ /**
+ * error number
+ * @see Errors.inc
+ * @var string
+ */
+ var $num;
+ /**
+ * @param string $file filename this error occurred in ({@link $file})
+ * @param integer $linenum line number this error occurred on ({@link $linenum})
+ * @param integer $num Error number defined in {@link Errors.inc}
+ * @param string $data... variable number of strings, up to 4, to sprintf based on the error number
+ */
+ function RecordWarning($file,$linenum,$num)
+ {
+ $this->file = $file;
+ $this->linenum = $linenum;
+ $a = array('','','','');
+ if (func_num_args()>3)
+ {
+ for($i=3;$i<func_num_args();$i++)
+ {
+ $a[$i - 3] = func_get_arg($i);
+ }
+ }
+
+ $this->num = $num;
+ $this->data = sprintf($GLOBALS[$this->type][$this->num],$a[0],$a[1],$a[2],$a[3]);
+ $this->output();
+ }
+
+ /**
+ * prints the warning
+ */
+ function output($string = false)
+ {
+ if ($string)
+ {
+ if ($this->file)
+ return "WARNING in $this->file on line $this->linenum: $this->data\n";
+ else
+ return "WARNING: $this->data\n";
+ }
+ if ($this->file)
+ phpDocumentor_out("WARNING in $this->file on line $this->linenum: $this->data\n");
+ else
+ phpDocumentor_out("WARNING: $this->data\n");
+ flush();
+ }
+}
+
+/**
+ * encapsulates error information
+ * @package phpDocumentor
+ * @subpackage Errors
+ */
+class RecordError extends RecordWarning
+{
+ /**
+ * name of global variable that descriptors for this warning/error is kept
+ * @var string
+ */
+ var $type = 'phpDocumentor_error_descrip';
+
+ /**
+ * prints the error
+ */
+ function output($string = false)
+ {
+ if ($string)
+ {
+ if ($this->file)
+ return "\n\tERROR in $this->file on line $this->linenum: $this->data\n";
+ else
+ return "\n\tERROR: $this->data\n";
+ }
+ if ($this->file)
+ phpDocumentor_out("\n\tERROR in $this->file on line $this->linenum: $this->data\n");
+ else
+ phpDocumentor_out("\n\tERROR: $this->data\n");
+ flush();
+ }
+}
+
+/**
+ * contains all the errors/warnings
+ * @see $errors, $warnings
+ * @package phpDocumentor
+ * @subpackage Errors
+ */
+class ErrorTracker
+{
+ /**
+ * array of {@link RecordError}s
+ * @var array
+ */
+ var $errors = array();
+ /**
+ * array of {@link RecordWarning}s
+ * @var array
+ */
+ var $warnings = array();
+ /**
+ * @var string
+ */
+ var $curfile = '';
+ /**
+ * @var integer
+ */
+ var $linenum = 0;
+
+ /**
+ * index in {@link $errors} of last error triggered
+ * @var integer|false
+ */
+ var $lasterror = false;
+
+ /**
+ * index in {@link $warnings} of last warning triggered
+ * @var integer|false
+ */
+ var $lastwarning = false;
+
+ /**
+ * This function subscribes to two events in the Parser in order to keep track of line number information and file name.
+ * @param integer $num parser-passed event (see {@link PHPDOCUMENTOR_EVENT_NEWLINENUM, PHPDOCUMENTOR_EVENT_NEWFILE})
+ * @param mixed $data either a line number if $num is PHPDOCUMENTOR_EVENT_NEWLINENUM or a file name if $num is PHPDOCUMENTOR_EVENT_NEWFILE
+ */
+ function handleEvent($num,$data)
+ {
+ switch($num)
+ {
+ case PHPDOCUMENTOR_EVENT_NEWLINENUM :
+ $this->linenum = $data;
+ break;
+ case PHPDOCUMENTOR_EVENT_NEWFILE :
+ $this->linenum = 0;
+ $this->curfile = $data;
+ break;
+ // debugging
+ case 1000000635 :
+ phpDocumentor_out($this->curfile.' has '.$this->linenum.' lines'."\n");
+ flush();
+ break;
+ }
+ }
+
+ /**
+ * add a new warning to the {@link $warnings} array
+ * @param integer $num error number from {@link Errors.inc}
+ * @param string $data... up to 4 string parameters to sprintf() into the error string for error number $num
+ */
+ function addWarning($num)
+ {
+ $a = array('','','','');
+ if (func_num_args()>1)
+ {
+ for($i=1;$i<func_num_args();$i++)
+ {
+ $a[$i - 1] = func_get_arg($i);
+ }
+ }
+ $this->warnings[] = new RecordWarning($this->curfile,$this->linenum,$num,$a[0],$a[1],$a[2],$a[3]);
+ $this->lastwarning = count($this->warnings) - 1;
+ }
+
+ /**
+ * add a new error to the {@link $errors} array
+ * @param integer $num error number from {@link Errors.inc}
+ * @param string $data... up to 4 string parameters to sprintf() into the error string for error number $num
+ */
+ function addError($num)
+ {
+ $a = array('','','','');
+ if (func_num_args()>1)
+ {
+ for($i=1;$i<func_num_args();$i++)
+ {
+ $a[$i - 1] = func_get_arg($i);
+ }
+ }
+ $this->errors[] = new RecordError($this->curfile,$this->linenum,$num,$a[0],$a[1],$a[2],$a[3]);
+ $this->lasterror = count($this->errors) - 1;
+ }
+
+ /**
+ * add a new error to the {@link $errors} array and returns the error string
+ * @param integer $num error number from {@link Errors.inc}
+ * @param string $data... up to 4 string parameters to sprintf() into the error string for error number $num
+ */
+ function addErrorReturn($num)
+ {
+ $a = array('','','','');
+ if (func_num_args()>1)
+ {
+ for($i=1;$i<func_num_args();$i++)
+ {
+ $a[$i - 1] = func_get_arg($i);
+ }
+ }
+ $this->errors[] = new RecordError($this->curfile,$this->linenum,$num,$a[0],$a[1],$a[2],$a[3],false);
+ $this->lasterror = count($this->errors) - 1;
+ }
+
+ /**
+ * Get sorted array of all warnings in parsing/conversion
+ * @return array
+ */
+ function &returnWarnings()
+ {
+ usort($this->warnings,array($this,"errorsort"));
+ return $this->warnings;
+ }
+
+ /**
+ * Get sorted array of all non-fatal errors in parsing/conversion
+ * @return array
+ */
+ function &returnErrors()
+ {
+ usort($this->errors,array($this,"errorsort"));
+ return $this->errors;
+ }
+
+ /**
+ * @access private
+ * @param RecordError|RecordWarning
+ * @param RecordError|RecordWarning
+ */
+ function errorsort($a, $b)
+ {
+ if (!$a->file) return -1;
+ if (!$b->file) return 1;
+ if ($a->file == $b->file)
+ {
+ if ($a->linenum == $b->linenum) return 0;
+ if ($a->linenum < $b->linenum) return -1;
+ return 1;
+ }
+ return strnatcasecmp($a->file,$b->file);
+ }
+
+ /**
+ * Get the error message of the last error
+ * @return string
+ */
+ function returnLastError()
+ {
+ return $this->errors[$this->lasterror]->output(true);
+ }
+
+ /**
+ * Get the warning message of the last warning
+ * @return string
+ */
+ function returnLastWarning()
+ {
+ return $this->warnings[$this->lastwarning]->output(true);
+ }
+}
+
+/**
+ * @global ErrorTracker $GLOBALS['phpDocumentor_errors']
+ * @name $phpDocumentor_errors
+ */
+$GLOBALS['phpDocumentor_errors'] = new ErrorTracker;
+
+/**
+ * @param integer $num error number from {@link Errors.inc}
+ * @param string $data... up to 4 string parameters to sprintf() into the error string for error number $num
+ * @see ErrorTracker::addError()
+ */
+function addError($num)
+{
+ global $phpDocumentor_errors;
+ $a = array('','','','');
+ if (func_num_args()>1)
+ {
+ for($i=1;$i<func_num_args();$i++)
+ {
+ $a[$i - 1] = func_get_arg($i);
+ }
+ }
+ $phpDocumentor_errors->addError($num,$a[0],$a[1],$a[2],$a[3]);
+}
+
+/**
+ * like {@link addError()} but exits parsing
+ * @param integer $num error number from {@link Errors.inc}
+ * @param string $data... up to 4 string parameters to sprintf() into the error string for error number $num
+ * @global ErrorTracker repository for all errors generated by phpDocumentor
+ * @see ErrorTracker::addError()
+ */
+function addErrorDie($num)
+{
+ global $phpDocumentor_errors;
+ $a = array('','','','');
+ if (func_num_args()>1)
+ {
+ for($i=1;$i<func_num_args();$i++)
+ {
+ $a[$i - 1] = func_get_arg($i);
+ }
+ }
+ $phpDocumentor_errors->addErrorReturn($num,$a[0],$a[1],$a[2],$a[3]);
+ die($phpDocumentor_errors->returnLastError());
+}
+
+/**
+ * @param integer $num warning number from {@link Errors.inc}
+ * @param string $data... up to 4 string parameters to sprintf() into the error string for error number $num
+ * @global ErrorTracker repository for all errors generated by phpDocumentor
+ * @see ErrorTracker::addWarning()
+ */
+function addWarning($num)
+{
+ global $phpDocumentor_errors;
+ $a = array('','','','');
+ if (func_num_args()>1)
+ {
+ for($i=1;$i<func_num_args();$i++)
+ {
+ $a[$i - 1] = func_get_arg($i);
+ }
+ }
+
+ $phpDocumentor_errors->addWarning($num,$a[0],$a[1],$a[2],$a[3]);
+}
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/EventStack.inc b/buildscripts/PhpDocumentor/phpDocumentor/EventStack.inc
new file mode 100644
index 00000000..5e2690e8
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/EventStack.inc
@@ -0,0 +1,78 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * An event Stack
+ *
+ * @author Joshua Eichorn <jeichorn@phpdoc.org>
+ * @version $Id: EventStack.inc,v 1.1 2005/10/17 18:36:55 jeichorn Exp $
+ * @package phpDocumentor
+ */
+/**
+ * An event Stack
+ *
+ * @author Joshua Eichorn <jeichorn@phpdoc.org>
+ * @version $Id: EventStack.inc,v 1.1 2005/10/17 18:36:55 jeichorn Exp $
+ * @package phpDocumentor
+ */
+class EventStack
+{
+ /**
+ * The stack
+ * @var array
+ */
+ var $stack = array(PARSER_EVENT_NOEVENTS);
+
+ /**
+ * The number of events in the stack
+ * @var integer
+ */
+ var $num = 0;
+
+ /**
+ * Push an event onto the stack
+ *
+ * @param int $event All events must be constants
+ */
+ function pushEvent($event)
+ {
+ $this->num = array_push($this->stack,$event) - 1;
+ }
+
+ /**
+ * Pop an event from the stack
+ *
+ * @return int An event
+ */
+ function popEvent()
+ {
+ $this->num--;
+ return array_pop($this->stack);
+ }
+
+ /**
+ * Get the current event
+ *
+ * @return int An event
+ */
+ function getEvent()
+ {
+ return $this->stack[$this->num];
+ }
+}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/HighlightParser.inc b/buildscripts/PhpDocumentor/phpDocumentor/HighlightParser.inc
new file mode 100644
index 00000000..f2a26ee9
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/HighlightParser.inc
@@ -0,0 +1,2354 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * Source Code Highlighting
+ *
+ * The classes in this file are responsible for the dynamic @example, @filesource
+ * and {@}source} tags output. Using the phpDocumentor_HighlightWordParser,
+ * the phpDocumentor_HighlightParser retrieves PHP tokens one by one from the
+ * array generated by {@link phpDocumentorTWordParser} source retrieval functions
+ * and then highlights them individually.
+ *
+ * It accomplishes this highlighting through the assistance of methods in
+ * the output Converter passed to its parse() method, and then returns the
+ * fully highlighted source as a string
+ * @tutorial tags.example.pkg, tags.filesource.pkg, tags.inlinesource.pkg
+ * @package phpDocumentor
+ * @subpackage Parsers
+ * @since 1.2.0beta3
+ */
+/**
+ * Retrieve tokens from an array of tokens organized by line numbers
+ * @package phpDocumentor
+ * @subpackage Parsers
+ * @since 1.2.0beta3
+ */
+class phpDocumentor_HighlightWordParser extends phpDocumentorTWordParser
+{
+ /**
+ * Hash used to keep track of line numbers that have already been initialized
+ * @var array
+ * @access private
+ */
+ var $_listLineNums = array();
+ /**
+ * @param array
+ * @param phpDocumentor_HighlightParser
+ */
+ function setup(&$input, &$parser)
+ {
+ $this->_parser = &$parser;
+ $this->data = &$input;
+ $this->_all = $input;
+ $this->_sourceline = 0;
+ $this->pos = 0;
+ $this->linenum = 0;
+ }
+
+ /**
+ * debugging function
+ * @access private
+ */
+ function printState()
+ {
+ $linenum = $this->linenum;
+ $pos = $this->pos;
+ if (!isset($this->_all[$this->linenum][$this->pos]))
+ {
+ $linenum++;
+ $pos = 0;
+ }
+ $details = '';
+ $token = $this->_all[$linenum][$pos];
+ if (is_array($token))
+ {
+ $details = token_name($token[0]);
+ $token = htmlspecialchars($token[1]);
+ } else $token = htmlspecialchars($token);
+ debug('Next Token '.$this->linenum.'-'.$this->pos.':'.$details);
+ var_dump($token);
+ }
+
+ /**
+ * Retrieve the position of the next token that will be parsed
+ * in the internal token array
+ * @return array format: array(line number, position)
+ */
+ function nextToken()
+ {
+ $linenum = $this->linenum;
+ $pos = $this->pos;
+ if (!isset($this->_all[$this->linenum][$this->pos]))
+ {
+ $linenum++;
+ $pos = 0;
+ }
+ if (!isset($this->_all[$linenum][$pos])) return false;
+ return array($linenum, $pos);
+ }
+
+ /**
+ * Retrieve the next token
+ * @return array|string either array(PHP token constant, token) or string
+ * non-specific separator
+ */
+ function getWord()
+ {
+ if (!isset($this->_all[$this->linenum][$this->pos]))
+ {
+ $this->linenum++;
+ $this->pos = 0;
+ if (!isset($this->_all[$this->linenum])) return false;
+ $this->_parser->newLineNum();
+ return $this->getWord();
+ }
+ $word = $this->_all[$this->linenum][$this->pos++];
+ return str_replace("\t",' ',$word);
+ }
+
+ /**
+ * back the word parser to the previous token as defined by $last_token
+ * @param array|string token, or output from {@link nextToken()}
+ * @param boolean if true, backupPos interprets $last_token to be the
+ * position in the internal token array of the last token
+ */
+ function backupPos($last_token, $is_pos = false)
+ {
+ if ($is_pos)
+ {
+ $this->linenum = $last_token[0];
+ $this->pos = $last_token[1];
+ return;
+ }
+ if ($last_token === false) return;
+//fancy_debug('before',$this->linenum,$this->pos,token_name($this->_all[$this->linenum][$this->pos][0]),htmlentities($this->_all[$this->linenum][$this->pos][1]),$this->_all[$this->linenum]);
+ do
+ {
+ $this->pos--;
+ if ($this->pos < 0)
+ {
+ $this->linenum--;
+ if ($this->linenum < 0) {
+ var_dump($last_token);
+ break;
+ }
+ $this->pos = count($this->_all[$this->linenum]) - 1;
+ }
+ } while (!$this->tokenEquals($last_token,str_replace("\t", ' ', $this->_all[$this->linenum][$this->pos])));
+ //fancy_debug('after',$this->linenum,$this->pos,token_name($this->_all[$this->linenum][$this->pos][0]),htmlentities($this->_all[$this->linenum][$this->pos][1]));
+ }
+}
+
+/**
+ * Highlights source code using {@link parse()}
+ * @package phpDocumentor
+ * @subpackage Parsers
+ */
+class phpDocumentor_HighlightParser extends phpDocumentorTParser
+{
+ /**#@+ @access private */
+ /**
+ * Highlighted source is built up in this string
+ * @var string
+ */
+ var $_output;
+ /**
+ * contents of the current source code line as it is parsed
+ * @var string
+ */
+ var $_line;
+ /**
+ * Used to retrieve highlighted tokens
+ * @var Converter a descendant of Converter
+ */
+ var $_converter;
+ /**
+ * Path to file being highlighted, if this is from a @filesource tag
+ * @var false|string full path
+ */
+ var $_filesourcepath;
+ /**
+ * @var array
+ */
+ var $eventHandlers = array(
+ PARSER_EVENT_ARRAY => 'defaultHandler',
+ PARSER_EVENT_CLASS => 'handleClass',
+ PARSER_EVENT_COMMENT => 'handleComment',
+ PARSER_EVENT_DOCBLOCK_TEMPLATE => 'handleDocBlockTemplate',
+ PARSER_EVENT_END_DOCBLOCK_TEMPLATE => 'handleEndDocBlockTemplate',
+ PARSER_EVENT_LOGICBLOCK => 'handleLogicBlock',
+ PARSER_EVENT_METHOD_LOGICBLOCK => 'handleMethodLogicBlock',
+ PARSER_EVENT_NOEVENTS => 'defaultHandler',
+ PARSER_EVENT_OUTPHP => 'defaultHandler',
+ PARSER_EVENT_CLASS_MEMBER => 'handleClassMember',
+ PARSER_EVENT_DEFINE => 'defaultHandler',
+ PARSER_EVENT_DEFINE_PARAMS => 'defaultHandler',
+ PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS => 'defaultHandler',
+ PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS => 'defaultHandler',
+ PARSER_EVENT_DOCBLOCK => 'handleDocBlock',
+ PARSER_EVENT_TAGS => 'handleTags',
+ PARSER_EVENT_DESC => 'handleDesc',
+ PARSER_EVENT_DOCKEYWORD => 'handleTag',
+ PARSER_EVENT_DOCKEYWORD_EMAIL => 'handleDockeywordEmail',
+ PARSER_EVENT_EOFQUOTE => 'handleQuote',
+ PARSER_EVENT_FUNCTION => 'handleFunction',
+ PARSER_EVENT_METHOD => 'handleMethod',
+ PARSER_EVENT_FUNCTION_PARAMS => 'handleFunctionParams',
+ PARSER_EVENT_FUNC_GLOBAL => 'handleFuncGlobal',
+ PARSER_EVENT_INLINE_DOCKEYWORD => 'handleInlineDockeyword',
+ PARSER_EVENT_INCLUDE => 'defaultHandler',
+ PARSER_EVENT_INCLUDE_PARAMS => 'defaultHandler',
+ PARSER_EVENT_QUOTE => 'handleQuote',
+ PARSER_EVENT_QUOTE_VAR => 'handleQuoteVar',
+ PARSER_EVENT_PHPCODE => 'handlePhpCode',
+ PARSER_EVENT_SINGLEQUOTE => 'handleSingleQuote',
+ PARSER_EVENT_STATIC_VAR => 'defaultHandler',
+ PARSER_EVENT_STATIC_VAR_VALUE => 'defaultHandler',
+ PARSER_EVENT_VAR => 'handleVar',
+ );
+
+ /**
+ * event handlers for @tags
+ * @tutorial tags.pkg
+ */
+ var $tagHandlers = array(
+ '*' => 'defaultTagHandler',
+ 'abstract' => 'coreTagHandler',
+ 'access' => 'coreTagHandler',
+ 'author' => 'coreTagHandler',
+ 'category' => 'coreTagHandler',
+ 'copyright' => 'coreTagHandler',
+ 'deprecated' => 'coreTagHandler',
+ 'example' => 'coreTagHandler',
+ 'filesource' => 'coreTagHandler',
+ 'final' => 'coreTagHandler',
+ 'global' => 'globalTagHandler',
+ 'ignore' => 'coreTagHandler',
+ 'license' => 'coreTagHandler',
+ 'link' => 'coreTagHandler',
+ 'name' => 'coreTagHandler',
+ 'package' => 'coreTagHandler',
+ 'param' => 'paramTagHandler',
+ 'parameter' => 'paramTagHandler',
+ 'see' => 'coreTagHandler',
+ 'since' => 'coreTagHandler',
+ 'subpackage' => 'coreTagHandler',
+ 'internal' => 'coreTagHandler',
+ 'return' => 'returnTagHandler',
+ 'static' => 'coreTagHandler',
+ 'staticvar' => 'staticvarTagHandler',
+ 'throws' => 'coreTagHandler',
+ 'todo' => 'coreTagHandler',
+ 'tutorial' => 'coreTagHandler',
+ 'uses' => 'coreTagHandler',
+ 'var' => 'varTagHandler',
+ 'version' => 'coreTagHandler',
+ );
+ /**#@-*/
+
+ /**
+ * @uses Converter::SourceLine() encloses {@link $_line} in a
+ * converter-specific format
+ */
+ function newLineNum()
+ {
+ if ($this->_pf_no_output_yet) return;
+ $this->_flush_save();
+ $this->_line .= $this->_converter->flushHighlightCache();
+ $this->_output .= $this->_converter->SourceLine($this->_wp->linenum, $this->_line, $this->_path);
+ $this->_line = '';
+ }
+
+ /**
+ * Start the parsing at a certain line number
+ */
+ function setLineNum($num)
+ {
+ $this->_wp->linenum = $num;
+ }
+
+ /**
+ * Parse a new file
+ *
+ * The parse() method is a do...while() loop that retrieves tokens one by
+ * one from the {@link $_event_stack}, and uses the token event array set up
+ * by the class constructor to call event handlers.
+ *
+ * The event handlers each process the tokens passed to them, and use the
+ * {@link _addoutput()} method to append the processed tokens to the
+ * {@link $_line} variable. The word parser calls {@link newLineNum()}
+ * every time a line is reached.
+ *
+ * In addition, the event handlers use special linking functions
+ * {@link _link()} and its cousins (_classlink(), etc.) to create in-code
+ * hyperlinks to the documentation for source code elements that are in the
+ * source code.
+ *
+ * @uses setupStates() initialize parser state variables
+ * @uses configWordParser() pass $parse_data to prepare retrieval of tokens
+ * @param array $parse_data
+ * @param Converter $converter
+ * @param boolean $inlinesourceparse whether this data is from an
+ * inline {@}source} tag
+ * @param string|false if a string, it is the name of the class whose
+ * method we are parsing containing a {@}source} tag
+ * @param false|integer starting line number from {@}source linenum}
+ * @param false|string full path to file with @filesource tag, if this
+ * is a @filesource parse
+ * @staticvar integer used for recursion limiting if a handler for
+ * an event is not found
+ * @return bool
+ */
+ function parse (&$parse_data, &$converter, $inlinesourceparse = false, $class = false, $linenum = false, $filesourcepath = false)
+ {
+ if (!tokenizer_ext)
+ {
+ if (is_array($parse_data))
+ {
+ $parse_data = join($parse_data,'');
+ }
+ $parse_data = explode("\n", $parse_data);
+ $this->_output = '';
+ foreach($parse_data as $linenum => $line)
+ {
+ if ($linenum > 0)
+ {
+ $this->_output .= $converter->SourceLine($linenum, $line, $filesourcepath);
+ }
+ }
+ return $converter->PreserveWhiteSpace($this->_output);
+ }
+ static $endrecur = 0;
+ $this->_converter = &$converter;
+ $converter->startHighlight();
+ $this->_path = $filesourcepath;
+ $this->setupStates($inlinesourceparse, $class);
+
+ $this->configWordParser($parse_data);
+ if ($linenum !== false) $this->setLineNum($linenum);
+ // initialize variables so E_ALL error_reporting doesn't complain
+ $pevent = 0;
+ $word = 0;
+
+ do
+ {
+ $lpevent = $pevent;
+ $pevent = $this->_event_stack->getEvent();
+ if ($lpevent != $pevent)
+ {
+ $this->_last_pevent = $lpevent;
+ }
+
+ if ($pevent == PARSER_EVENT_CLASS_MEMBER)
+ {
+ $this->_wp->setWhitespace(true);
+ } else
+ {
+ $this->_wp->setWhitespace(false);
+ }
+
+ if (!is_array($word)) $lw = $word;
+ if (is_array($word) && $word[0] != T_WHITESPACE) $lw = $word;
+ $dbg_linenum = $this->_wp->linenum;
+ $dbg_pos = $this->_wp->getPos();
+ $word = $this->_wp->getWord();
+ if (is_array($word) && $word[0] == T_WHITESPACE && $pevent != PARSER_EVENT_CLASS_MEMBER)
+ {
+// debug("added ".$this->_wp->linenum.'-'.$this->_wp->pos);
+ $this->_addoutput($word);
+ continue;
+ } else $this->_pv_last_word = $lw;
+ if ($pevent != PARSER_EVENT_DOCBLOCK)
+ {
+ $this->_pv_last_next_word = $this->_pv_next_word;
+ $this->_pv_next_word = $this->_wp->nextToken();
+ }
+ // in wordparser, have to keep track of lines
+// $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWLINENUM, $this->_wp->linenum);
+ if (0)//PHPDOCUMENTOR_DEBUG == true)
+ {
+ echo "LAST: ";
+ if (is_array($this->_pv_last_word))
+ {
+ echo token_name($this->_pv_last_word[0]). ' => |'.htmlspecialchars($this->_pv_last_word[1]);
+ } else echo "|" . $this->_pv_last_word;
+ echo "|\n";
+ echo "PEVENT: " . $this->getParserEventName($pevent) . "\n";
+ echo "LASTPEVENT: " . $this->getParserEventName($this->_last_pevent) . "\n";
+// echo "LINE: ".$this->_line."\n";
+// echo "OUTPUT: ".$this->_output."\n";
+ echo $dbg_linenum.'-'.$dbg_pos . ": ";
+ if (is_array($word))
+ {
+ echo token_name($word[0]).' => |'.htmlspecialchars($word[1]);
+ } else echo '|'.htmlspecialchars($word);
+ echo "|\n";
+ $this->_wp->printState();
+ echo "NEXT TOKEN: ";
+ $tok1 = $this->_pv_next_word;
+ $tok = $this->_wp->_all[$tok1[0]][$tok1[1]];
+ if (is_array($tok))
+ {
+ echo token_name($tok[0]). ' => '.$tok1[0].'-'.$tok1[1].'|'.htmlspecialchars($tok[1]);
+ } else echo "|" . $tok;
+ echo "|\n";
+ echo "-------------------\n\n\n";
+ flush();
+ }
+ if (isset($this->eventHandlers[$pevent]))
+ {
+ $handle = $this->eventHandlers[$pevent];
+ $this->$handle($word, $pevent);
+ } else
+ {
+ debug('WARNING: possible error, no handler for event number '.$pevent);
+ if ($endrecur++ == 25)
+ {
+ die("FATAL ERROR, recursion limit reached");
+ }
+ }
+ } while (!($word === false));
+ if (strlen($this->_line)) $this->newLineNum();
+ return $this->_output;
+ }
+
+ /**#@+
+ * Event Handlers
+ *
+ * All Event Handlers use {@link checkEventPush()} and
+ * {@link checkEventPop()} to set up the event stack and parser state.
+ * @access private
+ * @param string|array token value
+ * @param integer parser event from {@link Parser.inc}
+ */
+ /**
+ * Most tokens only need highlighting, and this method handles them
+ */
+ function defaultHandler($word, $pevent)
+ {
+ $this->_addoutput($word);
+ if ($this->checkEventPush($word, $pevent)) return;
+ $this->checkEventPop($word, $pevent);
+ }
+
+ /**
+ * Handles global declarations in a function, like:
+ *
+ * <code>
+ * function foobar()
+ * {
+ * global $_phpDocumentor_setting;
+ * }
+ * </code>
+ * @uses _globallink() instead of _addoutput(), to link to global variables
+ * if they are used in a function
+ */
+ function handleFuncGlobal($word, $pevent)
+ {
+ if ($this->checkEventPush($word, $pevent)) return;
+ $this->_globallink($word);
+ $this->checkEventPop($word, $pevent);
+ }
+
+ /**
+ * Handles strings in quotation marks and heredoc
+ *
+ * Special handling is needed for strings that contain variables like:
+ *
+ * <code>$a = "$test string"</code>
+ *
+ * The tokenizer parses out tokens '"',array(T_VARIABLE,'$test'),' string',
+ * and '"'. Since it is possible to have $this->classvar in a string,
+ * we save a variable name just in case the next token is -> to allow linking
+ * to class members. Otherwise, the string is simply highlighted.
+ *
+ * constant strings (with no $variables in them) are passed as a single
+ * entity, and so will be saved in the last token parsed. This means the
+ * event handler must tell the word parser to re-retrieve the current token
+ * so that the correct event handler can process it.
+ */
+ function handleQuote($word, $pevent)
+ {
+ if ($this->_pf_inmethod && is_array($word) && $word[0] == T_VARIABLE) $this->_pv_lastvar = $word;
+ if ($this->checkEventPush($word, $pevent))
+ {
+ $this->_addoutput($word);
+ return;
+ }
+ if ($this->_pf_quote_active &&
+ (($this->_pv_last_word == '"' && $this->_last_pevent != PARSER_EVENT_QUOTE) ||
+ (is_array($this->_pv_last_word) && $this->_pv_last_word[0] == T_END_HEREDOC &&
+ $this->_last_pevent != PARSER_EVENT_EOFQUOTE)))
+ {
+ $this->_pf_quote_active = false;
+ $this->_wp->backupPos($word);
+ $this->_event_stack->popEvent();
+ return;
+ }
+ if (!$this->_pf_quote_active &&
+ (($this->_pv_last_word == '"' && $this->_last_pevent != PARSER_EVENT_QUOTE) ||
+ (is_array($this->_pv_last_word) && $this->_pv_last_word[0] == T_END_HEREDOC &&
+ $this->_last_pevent != PARSER_EVENT_EOFQUOTE)))
+ {
+ if (is_array($word) && $word[0] == T_VARIABLE) $this->_pv_lastvar = $word;
+ $this->_pf_quote_active = true;
+ $this->_save_highlight_state = $this->_converter->getHighlightState();
+ $this->_converter->startHighlight();
+ $this->_addoutput($word);
+ $this->checkEventPop($word, $pevent);
+ return;
+ } elseif (is_array($this->_pv_last_word) && $this->_pv_last_word[0] == T_CONSTANT_ENCAPSED_STRING)
+ {
+// $this->_pv_quote_data = $this->_pv_last_word[1];
+ $this->_event_stack->popEvent();
+ $this->_wp->backupPos($word);
+ return;
+ }
+ if ($this->checkEventPop($word, $pevent))
+ {
+ $this->_pf_quote_active = false;
+ }
+ $this->_addoutput($word);
+ }
+
+ /**
+ * Handles {$variable} within a "quote"
+ *
+ * This is a simple handler, for a very complex
+ * array of legal syntax. It is legal to nest control structures
+ * inside the {}, and other weird stuff.
+ */
+ function handleQuoteVar($word, $pevent)
+ {
+ if ($this->checkEventPop($word, $pevent))
+ {
+ $this->_pf_quote_active = true;
+ $this->_addoutput($word);
+ return;
+ }
+ if ($this->_pf_inmethod && is_array($word) && $word[0] == T_VARIABLE) $this->_pv_lastvar = $word;
+ if ($this->checkEventPush($word, $pevent))
+ {
+ $this->_pf_quote_active = false;
+ if (is_string($word) && ($word == '{' || $word == '"' || $word == "'"))
+ {
+ $this->_pf_quote_active = true;
+ $this->_pv_lastvar = false;
+ }
+ }
+ $this->_addoutput($word);
+ }
+
+ /**
+ * Handles define() statements
+ *
+ * The only thing this handler cares about is retrieving the name of the
+ * define variable, and the end of the define statement, so after the name
+ * is found, it simply makes sure parentheses are matched as in this case:
+ *
+ * <code>
+ * define("test",array("hello",6 => 4, 5 => array('there')));
+ * </code>
+ *
+ * This handler and the DEFINE_PARAMS_PARENTHESIS handler (which is just
+ * {@link defaultHandler()} in this version, as nothing fancy is needed)
+ * work together to ensure proper parenthesis matching.
+ *
+ * If the define variable is documented, a link will be created to its
+ * documentation using the Converter passed.
+ */
+ function handleDefine($word, $pevent)
+ {
+ static $token_save;
+ if (!isset($token_save)) $token_save = array();
+ $e = $this->checkEventPush( $word, $pevent);
+ if ($e && $e != PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS) return;
+
+ if(!isset($this->_pv_define_params_data)) $this->_pv_define_params_data = '';
+
+ if ($this->checkEventPop($word,$pevent))
+ {
+ unset($token_save);
+ $this->_addoutput($word);
+ }
+ if ($this->_pf_definename_isset)
+ {
+ $this->_addoutput($word);
+ } else
+ {
+ if ($word != ",")
+ {
+ $token_save[] = $word;
+ if (is_array($word)) $word = $word[1];
+ $this->_pv_define_params_data .= $word;
+ } else
+ {
+ if (substr($this->_pv_define_params_data,0,1) ==
+ substr($this->_pv_define_params_data,strlen($this->_pv_define_params_data) - 1) &&
+ in_array(substr($this->_pv_define_params_data,0,1),array('"',"'")))
+ { // remove leading and ending quotation marks if there are only two
+ $a = substr($this->_pv_define_params_data,0,1);
+ $b = substr($this->_pv_define_params_data,1,strlen($this->_pv_define_params_data) - 2);
+ if (strpos($b,$a) === false)
+ {
+ $this->_pv_define_params_data = $b;
+ }
+ }
+ $this->_pf_definename_isset = true;
+ $link = $this->_converter->getLink($this->_pv_define_params_data);
+ foreach ($token_save as $token)
+ {
+ if (is_object($link))
+ {
+ if (is_array($token)) $token = $token[1];
+ $this->_addoutput($this->_converter->returnSee($link, $token));
+ } else
+ {
+ $this->_addoutput($save, $token);
+ }
+ }
+ $this->_pv_define_params_data = '';
+ }
+ }
+ }
+
+ /**
+ * Handles normal global code. Special consideration is taken for DocBlocks
+ * as they need to retrieve the whole DocBlock before doing any output, so
+ * the parser flag {@link $_pf_no_output_yet} is set to tell
+ * {@link _addoutput()} not to spit anything out yet.
+ * @uses _link() make any global code that is a documentable element link
+ * to the php manual or its documentation
+ */
+ function handlePhpCode($word, $pevent)
+ {
+ $test = $this->checkEventPush($word, $pevent);
+ if ($test == PARSER_EVENT_DOCBLOCK || $test == PARSER_EVENT_COMMENT)
+ {
+ $this->_pf_no_output_yet = true;
+ $this->_pv_saveline = $this->_wp->linenum + 1;
+ return;
+ }
+ if (is_array($word) && $word[0] == T_DOUBLE_COLON) $this->_pf_colon_colon = true;
+ if (!$this->_pf_colon_colon && is_array($word) && $word[0] == T_STRING) $this->_pv_last_string = $word;
+ $this->_link($word);
+ $this->checkEventPop($word, $pevent);
+ }
+
+ /**
+ * Handle the function declaration header
+ *
+ * This handler only sees the "function name" portion of the function
+ * declaration. Handling of the function parameters is by
+ * {@link handleFunctionParams()}, and the function body is handled by
+ * {@link handleLogicBlock()}
+ */
+ function handleFunction($word, $pevent)
+ {
+ if ($this->checkEventPush($word, $pevent))
+ {
+ $this->_addoutput($word);
+ return;
+ }
+ if ($this->checkEventPop($word, $pevent)) return;
+ $this->_link($word);
+ }
+
+ /**
+ * Handle the method declaration header
+ *
+ * This handler only sees the "function name" portion of the method
+ * declaration. Handling of the method parameters is by
+ * {@link handleFunctionParams()}, and the method body is handled by
+ * {@link handleMethodLogicBlock()}
+ */
+ function handleMethod($word, $pevent)
+ {
+ if ($this->checkEventPush($word, $pevent))
+ {
+ $this->_addoutput($word);
+ return;
+ }
+ if ($this->checkEventPop($word, $pevent)) {
+ if ($word == ';') {
+ $this->_addoutput($word);
+ }
+ return;
+ }
+ $this->_methodlink($word);
+ }
+
+ /**
+ * Handler for the stuff between ( and ) in a function declaration
+ *
+ * <code>
+ * function handles($only,$these,$parameters){...}
+ * </code>
+ */
+ function handleFunctionParams($word, $pevent)
+ {
+ if ($this->checkEventPush($word, $pevent))
+ {
+ $this->_addoutput($word);
+ return;
+ }
+ $this->_addoutput($word);
+ $this->checkEventPop($word, $pevent);
+ }
+
+ /**
+ * Handler for function body.
+ *
+ * The function body is checked for php functions, documented constants,
+ * functions, and indirectly for global statements. It hyperlinks to the
+ * documentation for detected elements is created. Everything else is
+ * highlighted normally.
+ */
+ function handleLogicBlock($word, $pevent)
+ {
+ if ($this->checkEventPush($word, $pevent))
+ {
+ $this->_addoutput($word);
+ return;
+ }
+ if (is_array($word) && $word[0] == T_DOUBLE_COLON) $this->_pf_colon_colon = true;
+ if (!$this->_pf_colon_colon && is_array($word) && $word[0] == T_STRING) $this->_pv_last_string = $word;
+ $this->_link($word);
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $e = $this->_event_stack->popEvent();
+ $this->_event_stack->pushEvent($e);
+ if ($e == PARSER_EVENT_FUNCTION)
+ {
+ $this->_wp->backupPos($word);
+ }
+ }
+ }
+
+ /**
+ * Handler for method body.
+ *
+ * Like functions, the method body is checked for php functions, documented
+ * constants, functions, and indirectly for global statements. It also
+ * checks for "$this->XXXX" where XXXX is a class variable or method, and
+ * links to the documentation for detected elements is created. Everything
+ * else is highlighted normally.
+ */
+ function handleMethodLogicBlock($word, $pevent)
+ {
+ if (isset($this->_pv_prev_var_type))
+ {
+// debug('prevtype is set');
+ if (!is_array($word)) unset($this->_pv_prev_var_type);
+ else
+ {
+ if ($word[0] != T_WHITESPACE && $word[0] != T_STRING && $word[0] != T_OBJECT_OPERATOR)
+ {
+// fancy_debug('unset',$word);
+ unset($this->_pv_prev_var_type);
+ }
+ }
+ }
+ $this->_pf_inmethod = true;
+ if ($e = $this->checkEventPush($word, $pevent))
+ {
+ $this->_addoutput($word);
+ if ($e == PARSER_EVENT_CLASS_MEMBER) {
+ $this->_pf_no_output_yet = true;
+ }
+ return;
+ }
+ if (is_array($word) && $word[0] == T_DOUBLE_COLON) $this->_pf_colon_colon = true;
+ if (!$this->_pf_colon_colon && is_array($word) && $word[0] == T_STRING) $this->_pv_last_string = $word;
+ if (is_array($word) && $word[0] == T_VARIABLE) $this->_pv_lastvar = $word;
+ $this->_link($word);
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->_pf_inmethod = false;
+ $e = $this->_event_stack->popEvent();
+ $this->_event_stack->pushEvent($e);
+ if ($e == PARSER_EVENT_METHOD)
+ {
+ $this->_wp->backupPos($word);
+ }
+ }
+ }
+
+ /**
+ * Handles $obj->classmember in a method body
+ *
+ * This handler is responsible for linking to the documentation of a
+ * class member when it is used directly in a method body.
+ *
+ * There are two methods of determining whether to link:
+ * - $this->member
+ * - $this->member->submember
+ *
+ * The first case is handled by the $_pv_lastvar variable, and the
+ * second case is handled by the $_pv_prev_var_type variable. $_pv_lastvar
+ * is always set to the value of the last T_VARIABLE token, if and only if
+ * no text has occurred between the variable and a T_OBJECT_OPERATOR token
+ * "->". handleClassMember will only link if the last variable encountered
+ * was $this.
+ *
+ * When $this->variable is encountered, the variable is looked up to see
+ * if it can be found, and if so, the contents of its @var tag are processed
+ * to see if the member variable is defined to have 1 and only 1 class.
+ * If so, the $_pv_prev_var_type variable is set to this classname. When
+ * submember is processed, the HighlightParser checks to see if
+ * $_pv_prev_var_type::submember() or $_pv_prev_var_type::$submember exists,
+ * and if it does, it is linked to.
+ */
+ function handleClassMember($word, $pevent)
+ {
+ if (!isset($this->_pv_lastvar) && !isset($this->_pv_prev_var_type))
+ {
+// fancy_debug('returned from',$word,$this->_pv_prev_var_type);
+ $this->_pf_no_output_yet = false;
+ $this->_event_stack->popEvent();
+ return $this->defaultHandler($word, $pevent);
+ }
+ if (isset($this->_pv_cm_name))
+ {
+ $this->_pf_obj_op = false;
+ $name = $this->_pv_cm_name;
+ unset($this->_pv_cm_name);
+// debug('unset pvcmname');
+ $this->_event_stack->popEvent();
+ // control variable for _pv_prev_var_type
+ $setnow = false;
+ if ((isset($this->_pv_lastvar) && $this->_pv_lastvar[1] == '$this')
+ || isset($this->_pv_prev_var_type))
+ {
+ if (is_array($word) && $word[0] == T_WHITESPACE)
+ {
+ // preserve value of _pv_prev_var_type
+ $setnow = true;
+ $save = $this->_wp->nextToken();
+ $temp = $this->_wp->getWord();
+ $this->_wp->backupPos($save, true);
+ }
+ if ((is_string($word) && $word == '(') ||
+ (isset($temp) && is_string($temp) && $temp == '('))
+ { // it's a function
+ $this->_pf_no_output_yet = false;
+ $this->_methodlink($name);
+ unset($this->_pv_prev_var_type);
+ } else
+ { // it's a variable
+// fancy_debug('name is ',$name);
+ $this->_pf_no_output_yet = false;
+ $this->_varlink($name, true);
+ $templink = $this->_converter->getLink('object '.$this->_pv_class);
+ $class = false;
+ if (is_object($templink)) {
+ $class = $this->_converter->classes->getClass($templink->name, $templink->path);
+ }
+ if ($class)
+ {
+ $varname = $name;
+ if (is_array($varname)) $varname = $name[1];
+ if ($varname{0} != '$') $varname = '$'.$varname;
+ $var = $class->getVar($this->_converter, $varname);
+
+ if (is_object($var) && $var->docblock->var)
+ $type = $var->docblock->var->returnType;
+ if (isset($type))
+ {
+ if (strpos($type, 'object') === false)
+ $type = 'object '.$type;
+ $type = $this->_converter->getLink($type);
+ if (phpDocumentor_get_class($type) == 'classlink')
+ { // the variable's type is a class, save it for future ->
+// fancy_debug('set prev_var_type!',$type->name);
+ $setnow = true;
+ $this->_pv_prev_var_type = $type->name;
+ } else unset($this->_pv_prev_var_type);
+ } else unset($this->_pv_prev_var_type);
+ } else unset($this->_pv_prev_var_type);
+ }
+ } else {
+ $this->_pf_no_output_yet = false;
+ // this does NewLinenum if necessary
+ $this->_wp->backupPos($word);
+ $this->_wp->getWord();
+ $this->_addoutput($name);
+ }
+ if (!$setnow)
+ {
+// debug('unset prevtype, no setnow');
+ unset($this->_pv_prev_var_type);
+ }
+ unset($this->_pv_lastvar);
+ $this->_pf_no_output_yet = false;
+ // this does NewLinenum if necessary
+ $this->_wp->backupPos($word);
+ $this->_wp->getWord();
+ if ($word[0] == T_OBJECT_OPERATOR)
+ $this->_wp->backupPos($word);
+ else
+ $this->_addoutput($word);
+ return;
+ }
+ if (!$this->_pf_obj_op && is_array($this->_pv_last_word) && $this->_pv_last_word[0] == T_OBJECT_OPERATOR)
+ {
+ if ((isset($this->_pv_lastvar) && $this->_pv_lastvar[1] == '$this') || isset($this->_pv_prev_var_type))
+ {
+ $this->_pf_obj_op = true;
+ } else
+ {
+ $this->_pf_no_output_yet = false;
+ // this does NewLinenum if necessary
+ $this->_wp->backupPos($word);
+ $this->_wp->getWord();
+ $this->_addoutput($word);
+ $this->_event_stack->popEvent();
+ }
+ }
+ if (is_array($word) && $word == T_WHITESPACE)
+ {
+ $this->_pf_no_output_yet = false;
+ // this does NewLinenum if necessary
+ $this->_wp->backupPos($word);
+ $this->_wp->getWord();
+ $this->_addoutput($word);
+ return;
+ }
+ if ($this->_pf_obj_op)
+ {
+ if (!(is_array($word) && ($word[0] == T_STRING || $word[0] == T_WHITESPACE)))
+ {
+ unset($this->_pv_lastvar);
+// debug('unset lastvar');
+ $this->_event_stack->popEvent();
+ $this->_pf_no_output_yet = false;
+ // this does NewLinenum if necessary
+ $this->_wp->backupPos($word);
+ $this->_wp->getWord();
+ $this->_addoutput($word);
+ return;
+ }
+ if ($word[0] == T_STRING)
+ {
+// fancy_debug('set pvcmname to',$word);
+ $this->_pv_cm_name = $word;
+ } else {
+ $this->_pf_no_output_yet = false;
+ // this does NewLinenum if necessary
+ $this->_wp->backupPos($word);
+ $this->_wp->getWord();
+ $this->_addoutput($word);
+ }
+ }
+ }
+
+ /**
+ * Handles comments
+ *
+ * Comments are almost always single-line tokens, and so will be
+ * in the last word. This handler checks to see if the current token
+ * is in fact a comment, and if it isn't, it backs up and returns control
+ * to the parent event handler with that word.
+ */
+ function handleComment($word, $pevent)
+ {
+ $w = $this->_pv_last_word;
+ // don't perform this check if this is a normal comment. Docblocks
+ // have the _pf_no_output_yet variable set to true
+ if ($this->_pf_no_output_yet &&
+ is_array($w) && (in_array($w[0], array(T_COMMENT, T_DOC_COMMENT)) && strpos($w[1],'/**') === 0)) {
+ $this->_event_stack->popEvent();
+ $this->_event_stack->pushEvent(PARSER_EVENT_DOCBLOCK);
+ return $this->handleDocBlock($word, PARSER_EVENT_DOCBLOCK);
+ }
+ if ($this->_pf_no_output_yet) {
+ $flag = 1;
+ $this->_pf_no_output_yet = false;
+ $this->_addoutput($this->_pv_last_word);
+ }
+ if (!is_array($word) || !in_array($word[0], array(T_COMMENT, T_DOC_COMMENT)) ||
+ (in_array($word[0], array(T_COMMENT, T_DOC_COMMENT)) && strpos($word[1],'/**') === 0))
+ {
+ $this->_event_stack->popEvent();
+ if (strpos($this->_pv_last_word[1], "\n") !== false)
+ {
+// $this->_wp->linenum++;
+// $this->newLineNum();
+ }
+ $this->_wp->backupPos($this->_pv_last_word);
+ $this->_wp->getWord();
+// var_dump($this->_wp->nextToken());
+ return;
+ } elseif (isset($flag)) {
+ $this->newLineNum();
+ }
+ $this->_addoutput($word);
+ $this->checkEventPop($word, $pevent);
+ if (strpos($word[1], '*/') === strlen($word[1]) - 2) {
+ $this->_event_stack->popEvent();
+ }
+ }
+
+ /**
+ * Handle class declarations
+ *
+ * Handles the initial declaration line:
+ *
+ * <code>class X</code>
+ *
+ * or
+ *
+ * <code>class X extends Y implements I</code>
+ *
+ * @uses _classlink() to link to documentation for X and for Y class in
+ * "class X extends Y"
+ */
+ function handleClass($word, $pevent)
+ {
+ $this->_pf_in_class = true;
+ $a = $this->checkEventPush( $word, $pevent);
+
+ if (!isset($this->_pv_class) && is_array($word) && $word[0] == T_STRING)
+ {
+ $this->_pv_class = $this->_converter->class = $word[1];
+ $this->_classlink($word);
+ return;
+ }
+
+ if (is_array($word) && in_array($word[0], array(T_PRIVATE, T_PROTECTED, T_PUBLIC))) {
+ $starttok = $this->_wp->nextToken();
+ $test = array(T_WHITESPACE);
+ while ($test && $test[0] == T_WHITESPACE) {
+ $tok = $this->_wp->nextToken();
+ $test = $this->_wp->getWord();
+ } // while
+
+ if (is_array($test) && $test[0] == T_VARIABLE) {
+ $this->_wp->backupPos($tok, true);
+ return;
+ }
+ $this->_wp->backupPos($starttok, true);
+ }
+
+ if (@in_array($this->_pv_last_word[0], array(T_PRIVATE, T_PROTECTED, T_PUBLIC))) {
+ if (is_array($word) && $word[0] == T_VARIABLE) {
+ $this->_wp->backupPos($this->_pv_last_word);
+ $this->_event_stack->pushEvent(PARSER_EVENT_VAR);
+ return;
+ }
+ }
+
+ if ($this->_pf_extends_found && is_array($word) && $word[0] == T_STRING)
+ {
+ $this->_classlink($word);
+ return;
+ }
+ if (is_array($word) && $word[0] == T_EXTENDS) $this->_pf_extends_found = true;
+ if ($a == PARSER_EVENT_DOCBLOCK)
+ {
+ $this->_pf_no_output_yet = true;
+ $this->_pv_saveline = $this->_wp->linenum + 1;
+ return;
+ }
+ $this->_addoutput($word);
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->_pf_in_class = false;
+ unset($this->_pv_class);
+ }
+ }
+
+ /**
+ * Handles class variable declaration
+ *
+ * <code>
+ * class X
+ * {
+ * var $Y;
+ * }
+ * </code>
+ * @uses _varlink() make a link to $Y documentation in class variable
+ * declaration "var $Y;"
+ */
+ function handleVar($word, $pevent)
+ {
+ if ($this->checkEventPush($word, $pevent))
+ {
+ $this->_addoutput($word);
+ return;
+ }
+ if (is_array($word) && $word[0] == T_VARIABLE)
+ {
+ return $this->_varlink($word);
+ }
+ $this->_addoutput($word);
+ $this->checkEventPop($word, $pevent);
+ }
+
+ /**
+ * This handler is responsible for highlighting DocBlocks
+ *
+ * handleDocBlock determines whether the docblock is normal or a template,
+ * and gathers all the lines of the docblock together before doing any
+ * processing
+ *
+ * As it is not possible to distinguish any comment token from a docblock
+ * token, this handler is also called for comments, and will pass control
+ * to {@link handleComment()} if the comment is not a DocBlock
+ * @uses commonDocBlock() once all lines of the DocBlock have been retrieved
+ */
+ function handleDocBlock($word, $pevent)
+ {
+ if (!($this->_pf_docblock || $this->_pf_docblock_template))
+ {
+ if (strpos($this->_pv_last_word[1],'/**') !== 0)
+ { // not a docblock
+ $this->_wp->backupPos($this->_pv_last_word);
+ $this->_event_stack->popEvent();
+ $this->_event_stack->pushEvent(PARSER_EVENT_COMMENT);
+ $this->_pf_no_output_yet = false;
+ return;
+ } else
+ {
+ $this->_pf_no_output_yet = true;
+ $this->_pv_db_lines = array();
+ }
+ }
+ $last_word = $this->_pv_last_word[1];
+ $dtype = '_pv_docblock';
+ if ($last_word == '/**#@-*/')
+ { // stop using docblock template
+ $this->_pf_no_output_yet = false;
+ $this->_addDocBlockoutput('closetemplate', $last_word);
+ if ($this->_pv_next_word !== false) {
+ $this->_wp->backupPos($this->_pv_next_word,true);
+ }
+ $this->_event_stack->popEvent();
+ return;
+ }
+ if (!($this->_pf_docblock || $this->_pf_docblock_template))
+ {
+ $this->_pv_db_lines = array();
+ if (strpos($last_word,'/**#@+') === 0)
+ { // docblock template definition
+ $this->_pf_docblock_template = true;
+ } else
+ {
+ $this->_pf_docblock = true;
+ }
+ $this->_pv_db_lines[] = $last_word;
+ if (strpos($last_word,'*/') !== false)
+ {
+ $this->commonDocBlock();
+ return;
+ }
+ $this->_pv_db_lines[] = $word[1];
+ if (strpos($word[1],'*/') !== false)
+ {
+ $this->commonDocBlock();
+ }
+ } else
+ {
+ $this->_pv_db_lines[] = $word[1];
+ }
+ if (($this->_pf_docblock || $this->_pf_docblock_template) && (strpos($word[1],'*/') !== false))
+ {
+ $this->commonDocBlock();
+ }
+ }
+ /**#@-*/
+ /**
+ * This continuation of handleDocBlock splits DocBlock comments up into
+ * phpDocumentor tokens. It highlights DocBlock templates in a different
+ * manner from regular DocBlocks, recognizes inline tags, regular tags,
+ * and distinguishes between standard core tags and other tags, and
+ * recognizes parameters to tags like @var.
+ *
+ * the type in "@var type description" will be highlighted as a php type,
+ * and the var in "@param type $var description" will be highlighted as a
+ * php variable.
+ * @uses handleDesc() highlight inline tags in the description
+ * @uses handleTags() highlight all tags
+ * @access private
+ */
+ function commonDocBlock()
+ {
+ $this->_event_stack->popEvent();
+ $lines = $this->_pv_db_lines;
+ $go = count($this->_pv_db_lines);
+ for($i=0;$i<$go;$i++)
+ {
+ if (substr(trim($lines[$i]),0,2) == '*/' || substr(trim($lines[$i]),0,1) != '*' && substr(trim($lines[$i]),0,3) != '/**')
+ {
+ $lines[$i] = array($lines[$i],false);
+ } elseif (substr(trim($lines[$i]),0,3) == '/**')
+ {
+ $linesi = array();
+ $linesi[1] = substr(trim($lines[$i]),3); // remove leading "/**"
+ if (empty($linesi[1]))
+ $linesi[0] = $lines[$i];
+ else
+ $linesi[0] = substr($lines[$i],0,strpos($lines[$i],$linesi[1]));
+ $lines[$i] = $linesi;
+ } else
+ {
+ $linesi = array();
+ $linesi[1] = substr(trim($lines[$i]),1); // remove leading "* "
+ if (empty($linesi[1]))
+ $linesi[0] = $lines[$i];
+ else
+ $linesi[0] = substr($lines[$i],0,strpos($lines[$i],$linesi[1]));
+ $lines[$i] = $linesi;
+ }
+ }
+ for($i = 0;$i<count($lines);$i++)
+ {
+ if ($lines[$i][1] === false) continue;
+ if (substr(trim($lines[$i][1]),0,1) == '@' && substr(trim($lines[$i][1]),0,2) != '@ ')
+ {
+ $tagindex = $i;
+ $i = count($lines);
+ }
+ }
+ if (isset($tagindex))
+ {
+ $tags = array_slice($lines,$tagindex);
+ $desc = array_slice($lines,0,$tagindex);
+ } else
+ {
+ $tags = array();
+ $desc = $lines;
+ }
+// var_dump($desc,$tags);
+ $this->_pf_no_output_yet = false;
+ $save = $this->_wp->linenum;
+ $this->_wp->linenum = $this->_pv_saveline;
+ $this->handleDesc($desc);
+ $this->handleTags($tags);
+ $this->_pv_db_lines = array();
+ $this->_wp->linenum = $save;
+ if (strpos($this->_pv_last_word[1],'*/') !== false)
+ {
+ $this->_wp->backupPos($this->_pv_next_word,true);
+ }
+ $this->_pf_docblock = $this->_pf_docblock_template = false;
+ }
+
+ /**
+ * Handle the description area of a DocBlock
+ *
+ * This method simply finds inline tags and highlights them
+ * separately from the rest of the description.
+ * @uses getInlineTags()
+ * @access private
+ */
+ function handleDesc($desc)
+ {
+ $dbtype = 'docblock';
+ $dbtype .= ($this->_pf_docblock ? '' : 'template');
+ foreach($desc as $line)
+ {
+ $this->getInlineTags($line[0].$line[1]);
+ if (strpos($line[0],'*/') === false)
+ {
+ $this->newLineNum();
+ $this->_wp->linenum++;
+ }
+ }
+ if ($this->_pf_internal)
+ {
+ $this->_pf_internal = false;
+ }
+ }
+
+ /**
+ * Handle phpDocumentor tags in a DocBlock
+ *
+ * This method uses the {@link $tagHandlers} array to determine which
+ * method will handle tags found in the docblock, and passes the data to
+ * the individual handlers one by one
+ * @access private
+ */
+ function handleTags($tags)
+ {
+ $newtags = array();
+ $curtag = array();
+ for($i=0;$i < count($tags);$i++)
+ {
+ $tagsi = trim($tags[$i][1]);
+ if (substr($tagsi,0,1) == '@' && substr($tagsi,0,2) != '@ ')
+ { // start a new tag
+ $tags[$i][1] = array(substr($tags[$i][1],0,strpos($tags[$i][1],$tagsi)),$tagsi);
+ if (!empty($curtag))
+ {
+ $newtags[] = $curtag;
+ $curtag = array();
+ }
+ $curtag[] = $tags[$i];
+ } else $curtag[] = $tags[$i];
+ }
+ if (!empty($curtag)) $newtags[] = $curtag;
+ foreach($newtags as $tag)
+ {
+ foreach($tag as $i => $t)
+ {
+ if ($t[1] === false) continue;
+ if (is_array($t[1]))
+ {
+ $tag[$i][1][1] = explode(" ",str_replace("\t",' ',$t[1][1]));
+ $x = $tag[$i][1][1];
+ }
+ }
+ $tagname = substr(array_shift($x),1);
+ $restoftag = $tag;
+ if (isset($this->tagHandlers[$tagname]))
+ $handle = $this->tagHandlers[$tagname];
+ else
+ $handle = $this->tagHandlers['*'];
+ $this->$handle($tagname,$restoftag);
+ }
+ }
+
+ /**
+ * This handler recognizes all {@}inline} tags
+ *
+ * Normal inline tags are simply highlighted. the {@}internal}} inline
+ * tag {@tutorial tags.inlineinternal.pkg} is highlighted differently
+ * to distinguish it from other inline tags.
+ * @access private
+ */
+ function getInlineTags($value, $endinternal = false)
+ {
+ if (!$value) return;
+ if ($this->_pf_internal && !$endinternal)
+ {
+ if (strpos($value,'}}') !== false)
+ {
+ $x = strrpos($value,'}}');
+ // add the rest of internal
+ $this->getInlineTags(substr($value,0,$x + 3), true);
+ // strip internal from value
+ $value = substr($value,strrpos($value,'}}') + 1);
+ // turn off internal
+ $this->_pf_internal = false;
+ }
+ }
+ if (!$value) return;
+ $dbtype = 'docblock';
+ $dbtype .= ($this->_pf_docblock ? '' : 'template');
+ $save = $value;
+ $value = explode('{@',$value);
+ $newval = array();
+ // everything before the first {@ is normal text
+ $this->_addDocBlockoutput($dbtype, $value[0]);
+ for($i=1;$i<count($value);$i++)
+ {
+ if (substr($value[$i],0,1) == '}')
+ {
+ $this->_addDocBlockoutput($dbtype, '{@}'.substr($value[$i],1));
+ } else
+ {
+ $save = $value[$i];
+ $value[$i] = str_replace("\t"," ",$value[$i]);
+ $value[$i] = explode(" ",$value[$i]);
+ $word = array_shift($value[$i]);
+ $val = join(' ',$value[$i]);
+ if ($word == 'internal')
+ {
+ $this->_pf_internal = true;
+ $this->_addDocBlockoutput($dbtype, '{@internal ');
+ $value[$i] = substr($save,strlen('internal') + 1);
+ // strip internal and cycle as if it were normal text.
+ $this->_addDocBlockoutput($dbtype, $value[$i]);
+ continue;
+ }
+ if (in_array(str_replace('}','',$word),$this->allowableInlineTags))
+ {
+ if (strpos($word,'}'))
+ {
+ $word = str_replace('}','',$word);
+ $val = '} '.$val;
+ }
+ $val = explode('}',$val);
+ if (count($val) == 1)
+ {
+// addError(PDERROR_UNTERMINATED_INLINE_TAG,$word,'',$save);
+ }
+ $rest = $val;
+ $val = array_shift($rest);
+ if ($endinternal)
+ $rest = join('}',$rest);
+ else
+ $rest = join(' ',$rest);
+ if (isset($this->inlineTagHandlers[$word]))
+ $handle = $this->inlineTagHandlers[$word];
+ else
+ $handle = $this->inlineTagHandlers['*'];
+ $this->$handle($word,$val);
+ $this->_addDocBlockoutput($dbtype, $rest);
+ } else
+ {
+ $val = $word.' '.$val;
+ $this->_addDocBlockoutput($dbtype, '{@'.$val);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Handles all inline tags
+ * @access private
+ */
+ function handleDefaultInlineTag($name, $value)
+ {
+ $this->_addDocBlockoutput('inlinetag','{@'.$name.' '.$value.'}');
+ }
+
+ /**#@+
+ * phpDocumentor DocBlock tag handlers
+ * @access private
+ * @param string tag name
+ * @param array array of lines contained in the tag description
+ */
+ /**
+ * Handle normal tags
+ *
+ * This handler adds to outpu all comment information before the tag begins
+ * as in " * " before "@todo" in " * @todo"
+ *
+ * Then, it highlights the tag as a regular or coretag based on $coretag.
+ * Finally, it uses getInlineTags to highlight the description
+ * @uses getInlineTags() highlight a tag description
+ * @param boolean whether this tag is a core tag or not
+ */
+ function defaultTagHandler($name, $value, $coretag = false)
+ {
+ $dbtype = 'docblock';
+ $dbtype .= ($this->_pf_docblock ? '' : 'template');
+ foreach($value as $line)
+ {
+ $this->_addDocBlockoutput($dbtype, $line[0]);
+ if ($line[1] === false)
+ {
+ if (trim($line[0]) != '*/')
+ {
+ $this->newLineNum();
+ $this->_wp->linenum++;
+ }
+ continue;
+ }
+ $this->_addDocBlockoutput($dbtype, $line[1][0]);
+ $stored = '';
+ if (is_array($line[1][1]))
+ {
+ foreach($line[1][1] as $i => $tpart)
+ {
+ if ($tpart == '@'.$name && $i == 0)
+ {
+ $tagname = 'tag';
+ if ($coretag) $tagname = 'coretag';
+ $this->_addDocBlockoutput($tagname,'@'.$name);
+ continue;
+ }
+ $stored .= ' '.$tpart;
+ }
+ } else $stored = $line[1];
+ $this->getInlineTags($stored);
+ if (strpos($stored,'*/') === false)
+ {
+ $this->newLineNum();
+ $this->_wp->linenum++;
+ }
+ }
+ }
+
+ /**
+ * @see defaultTagHandler()
+ */
+ function coreTagHandler($name, $value)
+ {
+ return $this->defaultTagHandler($name, $value, true);
+ }
+
+ /**
+ * Handles @global
+ *
+ * This handler works like {@link defaultTagHandler()} except it highlights
+ * the type and variable (if present) in "@global type $variable" or
+ * "@global type description"
+ */
+ function globalTagHandler($name, $value)
+ {
+ $this->paramTagHandler($name, $value);
+ }
+
+ /**
+ * Handles @param
+ *
+ * This handler works like {@link defaultTagHandler()} except it highlights
+ * the type and variable (if present) in "@param type $variable description"
+ * or "@param type description"
+ * @param boolean private parameter, checks for $var or not
+ */
+ function paramTagHandler($name, $value, $checkforvar = true)
+ {
+ $dbtype = 'docblock';
+ $dbtype .= ($this->_pf_docblock ? '' : 'template');
+ $ret = $this->retrieveType($value,0,$checkforvar);
+ foreach($value as $num => $line)
+ {
+ $this->_addDocBlockoutput($dbtype, $line[0]);
+ if ($line[1] === false)
+ {
+ if (trim($line[0]) != '*/')
+ {
+ $this->newLineNum();
+ $this->_wp->linenum++;
+ }
+ continue;
+ }
+ $this->_addDocBlockoutput($dbtype, $line[1][0]);
+ $stored = '';
+ $typeloc = 1;
+ $varloc = 2;
+ if (is_array($line[1][1]))
+ {
+ $this->_addDocBlockoutput('coretag','@'.$name.' ');
+ foreach($ret[0] as $text)
+ {
+ if (is_string($text)) $this->_addDocBlockoutput($dbtype,$text);
+ if (is_array($text))
+ {
+ if ($text[0] != 'desc') $this->_addDocBlockoutput($text[0],$text[1]);
+ else $stored .= $text[1];
+ }
+ }
+ } else
+ {
+ if (isset($ret[$num]))
+ {
+ foreach($ret[$num] as $text)
+ {
+ if (is_string($text)) $this->_addDocBlockoutput($dbtype,$text);
+ if (is_array($text))
+ {
+ if ($text[0] != 'desc') $this->_addDocBlockoutput($text[0],$text[1]);
+ else $stored .= $text[1];
+ }
+ }
+ } else $stored = $line[1];
+ }
+ $this->getInlineTags($stored);
+ if (strpos($stored,'*/') === false)
+ {
+ $this->newLineNum();
+ $this->_wp->linenum++;
+ }
+ }
+ }
+
+ /**
+ * @see paramTagHandler()
+ */
+ function staticvarTagHandler($name, $value)
+ {
+ return $this->paramTagHandler($name, $value);
+ }
+
+ /**
+ * @see paramTagHandler()
+ */
+ function varTagHandler($name, $value)
+ {
+ return $this->paramTagHandler($name, $value);
+ }
+
+ /**
+ * Handles @return
+ *
+ * This handler works like {@link defaultTagHandler()} except it highlights
+ * the type in "@return type description"
+ */
+ function returnTagHandler($name, $value)
+ {
+ $this->paramTagHandler($name, $value, false);
+ }
+ /**#@-*/
+
+ /**
+ * Retrieve the type portion of a @tag type description
+ *
+ * Tags like @param, @return and @var all have a PHP type portion in their
+ * description. Since the type may contain the expression "object blah"
+ * where blah is a classname, it makes parsing out the type field complex.
+ *
+ * Even more complicated is the case where a tag variable can contain
+ * multiple types, such as object blah|object blah2|false, and so this
+ * method handles these cases.
+ * @param array array of words that were separated by spaces
+ * @param 0|1 0 = find the type, 1 = find the var, if present
+ * @param boolean flag to determine whether to check for the end of a
+ * type is defined by a $varname
+ * @return array Format: array(state (0 [find type], 1 [var], 2 [done]),
+ *
+ * @access private
+ */
+ function retrieveType($value, $state = 0, $checkforvar = false)
+ {
+ $index = 0;
+ $result = array();
+ do
+ {
+ if (!isset($value[$index][1])) return $result;
+ $val = $value[$index][1];
+ if (empty($val)) return $result;
+ if ($index == 0)
+ {
+ $val = $val[1];
+ array_shift($val);
+ } else
+ {
+ $val = explode(' ',$val);
+ }
+ $ret = $this->_retrieveType($val, $state, $checkforvar);
+ $state = $ret[0];
+ $result[$index++] = $ret[1];
+ } while ((!$checkforvar && $state < 1) || ($state < 2 && $checkforvar));
+ return $result;
+ }
+
+ function _retrieveType($value, $state, $checkforvar)
+ {
+ $result = array();
+ $result[] = $this->_removeWhiteSpace($value, 0);
+ if ($state == 0)
+ {
+ if (!count($value)) return array(2,$result);
+ $types = '';
+ $index = 0;
+ if (trim($value[0]) == 'object')
+ {
+ $result[] = array('tagphptype', $value[0].' ');
+ $types .= array_shift($value).' ';
+ $result[] = $this->_removeWhiteSpace($value, 0);
+ if (!count($value))
+ { // was just passed "object"
+ return array(2,$result);
+ }
+ if ($value[0]{0} == '$' || substr($value[0],0,2) == '&$')
+ { // was just passed "object" and the next thing is a variable name
+ if ($checkforvar)
+ {
+ $result[] = array('tagvarname' , $value[0].' ');
+ array_shift($value);
+ }
+ $result[] = array('desc', join(' ', $value));
+ return array(2,$result);
+ }
+ }
+ $done = false;
+ $loop = -1;
+ do
+ { // this loop checks for type|type|type and for
+ // type|object classname|type|object classname2
+ if (strpos($value[0], '|'))
+ {
+ $temptypes = explode('|', $value[0]);
+ while(count($temptypes))
+ {
+ $type = array_shift($temptypes);
+ $result[] = array('tagphptype',$type);
+ if (count($temptypes)) $result[] = '|';
+ }
+ if (trim($type) == 'object')
+ {
+ $result[] = array('tagphptype', $types . ' ');
+ $result[] = $this->_removeWhiteSpace($value,0);
+ } else $done = true;
+ array_shift($value);
+ if (count($value) && strlen($value[0]) && isset ($value[0]) && ($value[0]{0} == '$' || substr($value[0],0,2) == '&$'))
+ { // was just passed "object" and the next thing is a variable name
+ $result[] = array('tagvarname' , $value[0].' ');
+ array_shift($value);
+ $result[] = array('desc', join(' ', $value));
+ return array(2,$result);
+ }
+ } else
+ {
+ $result[] = array('tagphptype', $value[0].' ');
+ array_shift($value);
+ $done = true;
+ }
+ $loop++;
+ } while (!$done && count($value));
+ if ($loop) $result[] = ' ';
+ // still searching for type
+ if (!$done && !count($value)) return array(0,$result);
+ // still searching for var
+ if ($done && !count($value)) return array(1,$result);
+ }
+ $result[] = $this->_removeWhiteSpace($value,0);
+ $state = 1;
+ if ($checkforvar)
+ {
+ if (count($value))
+ {
+ $state = 2;
+ if (substr($value[0],0,1) == '$' || substr($value[0],0,2) == '&$')
+ {
+ $result[] = array('tagvarname' , $value[0].' ');
+ array_shift($value);
+ }
+ } else $state = 1;
+ }
+ $result[] = array('desc', join(' ',$value));
+ return array($state,$result);
+ }
+
+
+ /**
+ * @param array array of string
+ * @param integer index to seek non-whitespace to
+ * @access private
+ * @return string whitespace
+ */
+ function _removeWhiteSpace(&$value, $index)
+ {
+ $result = '';
+ if (count($value) > $index && empty($value[$index]))
+ {
+ $found = false;
+ for($i=$index; $i<count($value) && !strlen($value[$i]); $i++) $result .= ' ';
+ array_splice($value, $index, $i - $index);
+ }
+ return $result;
+ }
+
+ /**#@+
+ * Link generation methods
+ * @access private
+ * @param string|array token to try to link
+ */
+ /**
+ * Generate a link to documentation for an element
+ *
+ * This method tries to link to documentation for functions, methods,
+ * PHP functions, class names, and if found, adds the links to output
+ * instead of plain text
+ */
+ function _link($word)
+ {
+ if (is_array($word) && $word[0] == T_STRING)
+ {
+ if ($this->_pf_colon_colon)
+ {
+ $this->_pf_colon_colon = false;
+ $combo = $this->_pv_last_string[1].'::'.$word[1].'()';
+// debug('testing '.$combo);
+ $link = $this->_converter->getLink($combo);
+ if (is_object($link))
+ {
+ $this->_addoutput($this->_converter->returnSee($link, $word[1]), true);
+ return;
+ }
+ $this->_addoutput($word);
+ return;
+ }
+ $link = $this->_converter->getLink($word[1].'()');
+ if (is_object($link))
+ {
+ $this->_addoutput($this->_converter->returnSee($link, $word[1]), true);
+ return;
+ } elseif (is_string($link) && strpos($link,'ttp://'))
+ {
+ $this->_addoutput($this->_converter->returnLink($link, $word[1]), true);
+ return;
+ } else
+ {
+ $link = $this->_converter->getLink($word[1]);
+ if (is_object($link)) $word[1] = $this->_converter->returnSee($link, $word[1]);
+ $this->_addoutput($word, true);
+ return;
+ }
+ }
+ $this->_addoutput($word);
+ }
+
+ /**
+ * Works like {@link _link()} except it only links to global variables
+ */
+ function _globallink($word)
+ {
+ if (!is_array($word)) return $this->_addoutput($word);
+ if ($word[0] != T_VARIABLE) return $this->_addoutput($word);
+ if (is_array($word) && $word[0] == T_VARIABLE)
+ {
+ $link = $this->_converter->getLink('global '.$word[1]);
+ if (is_object($link))
+ {
+ $this->_addoutput($this->_converter->returnSee($link, $word[1]), true);
+ return;
+ }
+ }
+ $this->_addoutput($word);
+ }
+
+ /**
+ * Works like {@link _link()} except it only links to classes
+ */
+ function _classlink($word)
+ {
+// debug("checking class ".$word[1]);
+ if (is_array($word) && $word[0] == T_STRING)
+ {
+ $link = $this->_converter->getLink($word[1]);
+ if (is_object($link))
+ {
+ $this->_addoutput($this->_converter->returnSee($link, $word[1]), true);
+ return;
+ }
+ }
+ $this->_addoutput($word);
+ }
+
+ /**
+ * Works like {@link _link()} except it only links to methods
+ */
+ function _methodlink($word)
+ {
+ if (is_array($word) && $word[0] == T_STRING)
+ {
+// debug("checking method ".$this->_pv_class.'::'.$word[1].'()');
+ if (isset($this->_pv_prev_var_type))
+ {
+ $link = $this->_converter->getLink($this->_pv_prev_var_type.'::'.$word[1].'()');
+ } else
+ $link = $this->_converter->getLink($this->_pv_class.'::'.$word[1].'()');
+ if (is_object($link))
+ {
+ $this->_addoutput($this->_converter->returnSee($link, $word[1]), true);
+ return;
+ }
+ if (isset($this->_pv_prev_var_type))
+ {
+ $this->_addoutput($word);
+ return;
+ }
+// debug("checking method ".$word[1].'()');
+ $link = $this->_converter->getLink($word[1].'()');
+ if (is_object($link))
+ {
+ $this->_addoutput($this->_converter->returnSee($link, $word[1]), true);
+ return;
+ }
+ }
+ $this->_addoutput($word);
+ }
+
+ /**
+ * Works like {@link _link()} except it only links to class variables
+ */
+ function _varlink($word, $justastring=false)
+ {
+ if ($justastring)
+ {
+ $word[0] = T_VARIABLE;
+ }
+ if (is_array($word) && $word[0] == T_VARIABLE)
+ {
+ $x = ($justastring ? '$' : '');
+// debug("checking var ".$this->_pv_class.'::'.$x.$word[1]);
+ if (isset($this->_pv_prev_var_type))
+ {
+// debug("checking var ".$this->_pv_prev_var_type.'::'.$x.$word[1]);
+ $link = $this->_converter->getLink($this->_pv_prev_var_type.'::'.$x.$word[1]);
+ }
+ else
+ $link = $this->_converter->getLink($this->_pv_class.'::'.$x.$word[1]);
+ if (is_object($link))
+ {
+ $this->_addoutput($this->_converter->returnSee($link, $word[1]), true);
+ return;
+ }
+// debug("checking var ".$x.$word[1]);
+ if (isset($this->_pv_prev_var_type))
+ {
+ $this->_addoutput($word);
+ return;
+ }
+ $link = $this->_converter->getLink($x.$word[1]);
+ if (is_object($link))
+ {
+ $this->_addoutput($this->_converter->returnSee($link, $word[1]), true);
+ return;
+ }
+ }
+ $this->_addoutput($word);
+ }
+ /**#@-*/
+
+ /**#@+
+ * Output Methods
+ * @access private
+ */
+ /**
+ * This method adds output to {@link $_line}
+ *
+ * If a string with variables like "$test this" is present, then special
+ * handling is used to allow processing of the variable in context.
+ * @see _flush_save()
+ */
+ function _addoutput($word, $preformatted = false)
+ {
+ if ($this->_pf_no_output_yet) return;
+ if ($this->_pf_quote_active)
+ {
+ if (is_array($word)) $this->_save .= $this->_converter->highlightSource($word[0], $word[1]);
+ else
+ $this->_save .= $this->_converter->highlightSource(false, $word, true);
+ } else
+ {
+ $this->_flush_save();
+ if (is_string($word) && trim($word) == '')
+ {
+ $this->_line .= $word;
+ return;
+ }
+ if (is_array($word) && trim($word[1]) == '')
+ {
+ $this->_line .= $word[1];
+ return;
+ }
+ if (is_array($word))
+ {
+ $this->_line .= $this->_converter->highlightSource($word[0], $word[1], $preformatted);
+ } else
+ {
+ $this->_line .= $this->_converter->highlightSource(false, $word, $preformatted);
+ }
+ }
+ }
+
+ /**
+ * Like {@link _output()}, but for DocBlock highlighting
+ */
+ function _addDocBlockoutput($dbtype, $word, $preformatted = false)
+ {
+ if ($this->_pf_internal)
+ {
+ $this->_line .= $this->_converter->highlightDocBlockSource('internal', $word, $preformatted);
+ } else
+ {
+ $this->_line .= $this->_converter->highlightDocBlockSource($dbtype, $word, $preformatted);
+ }
+ }
+
+ /**
+ * Flush a saved string variable highlighting
+ *
+ * {@source}
+ */
+ function _flush_save()
+ {
+ if (!empty($this->_save))
+ {
+ $this->_save .= $this->_converter->flushHighlightCache();
+ // clear the existing cache, reset it to the old value
+ $this->_converter->_setHighlightCache($this->_save_highlight_state[0], $this->_save_highlight_state[1]);
+ $this->_line .= $this->_converter->highlightSource(T_CONSTANT_ENCAPSED_STRING, $this->_save, true);
+ $this->_save = '';
+ }
+ }
+ /**#@-*/
+
+ /**
+ * Give the word parser necessary data to begin a new parse
+ * @param array all tokens separated by line number
+ */
+ function configWordParser(&$data)
+ {
+ $this->_wp->setup($data, $this);
+ $this->_wp->setWhitespace(true);
+ }
+
+ /**
+ * Initialize all parser state variables
+ * @param boolean true if we are highlighting an inline {@}source} tag's
+ * output
+ * @param false|string name of class we are going to start from
+ * @uses $_wp sets to a new {@link phpDocumentor_HighlightWordParser}
+ */
+ function setupStates($inlinesourceparse, $class)
+ {
+ $this->_output = '';
+ $this->_line = '';
+ unset($this->_wp);
+ $this->_wp = new phpDocumentor_HighlightWordParser;
+ $this->_event_stack = new EventStack;
+ if ($inlinesourceparse)
+ {
+ $this->_event_stack->pushEvent(PARSER_EVENT_PHPCODE);
+ if ($class)
+ {
+ $this->_event_stack->pushEvent(PARSER_EVENT_CLASS);
+ $this->_pv_class = $class;
+ }
+ } else $this->_pv_class = null;
+ $this->_pv_define = null;
+ $this->_pv_define_name = null;
+ $this->_pv_define_value = null;
+ $this->_pv_define_params_data = null;
+ $this->_pv_dtype = null;
+ $this->_pv_docblock = null;
+ $this->_pv_dtemplate = null;
+ $this->_pv_func = null;
+ $this->_pv_global_name = null;
+ $this->_pv_global_val = null;
+ $this->_pv_globals = null;
+ $this->_pv_global_count = null;
+ $this->_pv_include_params_data = null;
+ $this->_pv_include_name = null;
+ $this->_pv_include_value = null;
+ $this->_pv_linenum = null;
+ $this->_pv_periodline = null;
+ $this->_pv_paren_count = 0;
+ $this->_pv_statics = null;
+ $this->_pv_static_count = null;
+ $this->_pv_static_val = null;
+ $this->_pv_quote_data = null;
+ $this->_pv_function_data = null;
+ $this->_pv_var = null;
+ $this->_pv_varname = null;
+ $this->_pf_definename_isset = false;
+ $this->_pf_extends_found = false;
+ $this->_pf_includename_isset = false;
+ $this->_pf_get_source = false;
+ $this->_pf_getting_source = false;
+ $this->_pf_in_class = false;
+ $this->_pf_in_define = false;
+ $this->_pf_in_global = false;
+ $this->_pf_in_include = false;
+ $this->_pf_in_var = false;
+ $this->_pf_funcparam_val = false;
+ $this->_pf_quote_active = false;
+ $this->_pf_reset_quote_data = true;
+ $this->_pf_useperiod = false;
+ $this->_pf_var_equals = false;
+ $this->_pf_obj_op = false;
+ $this->_pf_docblock = false;
+ $this->_pf_docblock_template = false;
+ $this->_pf_colon_colon = false;
+ $this->_pv_last_string = false;
+ $this->_pf_inmethod = false;
+ $this->_pf_no_output_yet = false;
+ $this->_pv_saveline = 0;
+ $this->_pv_next_word = false;
+ $this->_save = '';
+ }
+
+ /**
+ * Initialize the {@link $tokenpushEvent, $wordpushEvent} arrays
+ */
+ function phpDocumentor_HighlightParser()
+ {
+ if (!defined('T_INTERFACE')) {
+ define('T_INTERFACE', -1);
+ }
+ $this->allowableTags = $GLOBALS['_phpDocumentor_tags_allowed'];
+ $this->allowableInlineTags = $GLOBALS['_phpDocumentor_inline_doc_tags_allowed'];
+ $this->inlineTagHandlers = array('*' => 'handleDefaultInlineTag');
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_NOEVENTS] =
+ array(
+ T_OPEN_TAG => PARSER_EVENT_PHPCODE,
+ );
+
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_PHPCODE] =
+ array(
+ T_FUNCTION => PARSER_EVENT_FUNCTION,
+ T_CLASS => PARSER_EVENT_CLASS,
+ T_INTERFACE => PARSER_EVENT_CLASS,
+ T_INCLUDE_ONCE => PARSER_EVENT_INCLUDE,
+ T_INCLUDE => PARSER_EVENT_INCLUDE,
+ T_START_HEREDOC => PARSER_EVENT_EOFQUOTE,
+ T_REQUIRE => PARSER_EVENT_INCLUDE,
+ T_REQUIRE_ONCE => PARSER_EVENT_INCLUDE,
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_DOCBLOCK,
+ );
+ $this->wordpushEvent[PARSER_EVENT_PHPCODE] =
+ array(
+ "define" => PARSER_EVENT_DEFINE,
+ );
+/**************************************************************/
+
+ $this->wordpushEvent[PARSER_EVENT_FUNCTION] =
+ array(
+ '{' => PARSER_EVENT_LOGICBLOCK,
+ '(' => PARSER_EVENT_FUNCTION_PARAMS,
+ );
+ $this->tokenpushEvent[PARSER_EVENT_FUNCTION] =
+ array(
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_DOCBLOCK,
+ );
+
+ $this->wordpopEvent[PARSER_EVENT_FUNCTION] = array("}");
+/**************************************************************/
+
+ $this->tokenpopEvent[PARSER_EVENT_EOFQUOTE] = array(T_END_HEREDOC);
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_FUNCTION_PARAMS] =
+ array(
+ T_CONSTANT_ENCAPSED_STRING => PARSER_EVENT_QUOTE,
+ T_ARRAY => PARSER_EVENT_ARRAY,
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_DOCBLOCK,
+ );
+ $this->wordpushEvent[PARSER_EVENT_FUNCTION_PARAMS] =
+ array(
+ '"' => PARSER_EVENT_QUOTE,
+ "'" => PARSER_EVENT_QUOTE,
+ );
+ $this->wordpopEvent[PARSER_EVENT_FUNCTION_PARAMS] = array(")");
+/**************************************************************/
+
+ $this->wordpushEvent[PARSER_EVENT_LOGICBLOCK] =
+ array(
+ "{" => PARSER_EVENT_LOGICBLOCK,
+ '"' => PARSER_EVENT_QUOTE,
+ );
+ $this->tokenpushEvent[PARSER_EVENT_LOGICBLOCK] =
+ array(
+ T_GLOBAL => PARSER_EVENT_FUNC_GLOBAL,
+ T_STATIC => PARSER_EVENT_STATIC_VAR,
+ T_START_HEREDOC => PARSER_EVENT_EOFQUOTE,
+ T_CURLY_OPEN => PARSER_EVENT_LOGICBLOCK,
+ T_DOLLAR_OPEN_CURLY_BRACES => PARSER_EVENT_LOGICBLOCK,
+ );
+
+ $this->wordpopEvent[PARSER_EVENT_LOGICBLOCK] = array("}");
+ $this->tokenpopEvent[PARSER_EVENT_LOGICBLOCK] = array(T_CURLY_OPEN);
+
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_ARRAY] =
+ array(
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_DOCBLOCK,
+ );
+ $this->wordpopEvent[PARSER_EVENT_ARRAY] = array(")");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_FUNC_GLOBAL] =
+ array(
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_DOCBLOCK,
+ );
+
+ $this->wordpopEvent[PARSER_EVENT_FUNC_GLOBAL] = array(";");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_STATIC_VAR] =
+ array(
+ T_CONSTANT_ENCAPSED_STRING => PARSER_EVENT_QUOTE,
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_DOCBLOCK,
+ );
+ $this->wordpushEvent[PARSER_EVENT_STATIC_VAR] =
+ array(
+ "=" => PARSER_EVENT_STATIC_VAR_VALUE,
+ );
+ $this->wordpopEvent[PARSER_EVENT_STATIC_VAR] = array(";");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_STATIC_VAR_VALUE] =
+ array(
+ T_CONSTANT_ENCAPSED_STRING => PARSER_EVENT_QUOTE,
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_DOCBLOCK,
+ T_ARRAY => PARSER_EVENT_ARRAY,
+ );
+ $this->wordpushEvent[PARSER_EVENT_STATIC_VAR_VALUE] =
+ array(
+ '"' => PARSER_EVENT_QUOTE,
+ "'" => PARSER_EVENT_QUOTE,
+ );
+ $this->wordpopEvent[PARSER_EVENT_STATIC_VAR_VALUE] = array(";",",");
+/**************************************************************/
+ $this->tokenpushEvent[PARSER_EVENT_QUOTE] =
+ array(
+ T_OBJECT_OPERATOR => PARSER_EVENT_CLASS_MEMBER,
+ T_CURLY_OPEN => PARSER_EVENT_QUOTE_VAR,
+ );
+
+ $this->wordpopEvent[PARSER_EVENT_QUOTE] = array('"');
+/**************************************************************/
+ $this->tokenpushEvent[PARSER_EVENT_QUOTE_VAR] =
+ array(
+ T_OBJECT_OPERATOR => PARSER_EVENT_CLASS_MEMBER,
+ T_CURLY_OPEN => PARSER_EVENT_QUOTE_VAR,
+ );
+
+ $this->wordpushEvent[PARSER_EVENT_QUOTE_VAR] =
+ array(
+ "{" => PARSER_EVENT_QUOTE_VAR,
+ '"' => PARSER_EVENT_QUOTE_VAR,
+ "'" => PARSER_EVENT_QUOTE_VAR,
+ );
+ $this->wordpopEvent[PARSER_EVENT_QUOTE_VAR] = array('}');
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_DEFINE] =
+ array(
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_DOCBLOCK,
+ T_CONSTANT_ENCAPSED_STRING => PARSER_EVENT_QUOTE,
+ );
+ $this->wordpushEvent[PARSER_EVENT_DEFINE] =
+ array(
+ "(" => PARSER_EVENT_DEFINE_PARAMS,
+ );
+ $this->wordpopEvent[PARSER_EVENT_DEFINE] = array(";");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_DEFINE_PARAMS] =
+ array(
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_DOCBLOCK,
+ );
+ $this->wordpushEvent[PARSER_EVENT_DEFINE_PARAMS] =
+ array(
+ "(" => PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS,
+ '"' => PARSER_EVENT_QUOTE,
+ "'" => PARSER_EVENT_QUOTE,
+ );
+ $this->wordpopEvent[PARSER_EVENT_DEFINE_PARAMS] = array(")");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS] =
+ array(
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_DOCBLOCK,
+ );
+ $this->wordpushEvent[PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS] =
+ array(
+ "(" => PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS,
+ '"' => PARSER_EVENT_QUOTE,
+ "'" => PARSER_EVENT_QUOTE,
+ );
+ $this->wordpopEvent[PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS] = array(")");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_VAR] =
+ array(
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_DOCBLOCK,
+ T_ARRAY => PARSER_EVENT_ARRAY,
+ );
+ $this->wordpopEvent[PARSER_EVENT_VAR] = array(";");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_CLASS] =
+ array(
+ T_FUNCTION => PARSER_EVENT_METHOD,
+ T_VAR => PARSER_EVENT_VAR,
+ T_COMMENT => PARSER_EVENT_DOCBLOCK,
+ T_DOC_COMMENT => PARSER_EVENT_DOCBLOCK,
+ T_CLOSE_TAG => PARSER_EVENT_OUTPHP,
+ );
+ $this->wordpopEvent[PARSER_EVENT_CLASS] = array("}");
+
+/**************************************************************/
+
+ $this->wordpushEvent[PARSER_EVENT_METHOD] =
+ array(
+ '{' => PARSER_EVENT_METHOD_LOGICBLOCK,
+ '(' => PARSER_EVENT_FUNCTION_PARAMS,
+ );
+ $this->tokenpushEvent[PARSER_EVENT_METHOD] =
+ array(
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_DOCBLOCK,
+ );
+
+ $this->wordpopEvent[PARSER_EVENT_METHOD] = array("}", ";");
+/**************************************************************/
+
+ $this->wordpushEvent[PARSER_EVENT_METHOD_LOGICBLOCK] =
+ array(
+ "{" => PARSER_EVENT_METHOD_LOGICBLOCK,
+ '"' => PARSER_EVENT_QUOTE,
+ );
+ $this->tokenpushEvent[PARSER_EVENT_METHOD_LOGICBLOCK] =
+ array(
+ T_OBJECT_OPERATOR => PARSER_EVENT_CLASS_MEMBER,
+ T_GLOBAL => PARSER_EVENT_FUNC_GLOBAL,
+ T_STATIC => PARSER_EVENT_STATIC_VAR,
+ T_CURLY_OPEN => PARSER_EVENT_LOGICBLOCK,
+ T_DOLLAR_OPEN_CURLY_BRACES => PARSER_EVENT_LOGICBLOCK,
+ );
+
+ $this->wordpopEvent[PARSER_EVENT_METHOD_LOGICBLOCK] = array("}");
+ $this->tokenpopEvent[PARSER_EVENT_METHOD_LOGICBLOCK] = array(T_CURLY_OPEN);
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_INCLUDE] =
+ array(
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_DOCBLOCK,
+ );
+ $this->wordpushEvent[PARSER_EVENT_INCLUDE] =
+ array(
+ "(" => PARSER_EVENT_INCLUDE_PARAMS,
+ );
+ $this->wordpopEvent[PARSER_EVENT_INCLUDE] = array(";");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_INCLUDE_PARAMS] =
+ array(
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_DOCBLOCK,
+ );
+ $this->wordpushEvent[PARSER_EVENT_INCLUDE_PARAMS] =
+ array(
+ "(" => PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS,
+ );
+ $this->wordpopEvent[PARSER_EVENT_INCLUDE_PARAMS] = array(")");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS] =
+ array(
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_DOCBLOCK,
+ );
+ $this->wordpushEvent[PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS] =
+ array(
+ "(" => PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS,
+ );
+ $this->wordpopEvent[PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS] = array(")");
+ }
+}
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/InlineTags.inc b/buildscripts/PhpDocumentor/phpDocumentor/InlineTags.inc
new file mode 100644
index 00000000..1bea7734
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/InlineTags.inc
@@ -0,0 +1,854 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * All abstract representations of inline tags are in this file
+ * @package phpDocumentor
+ * @subpackage InlineTags
+ * @since separate file since version 1.2
+ * @version $Id: InlineTags.inc,v 1.1 2005/10/17 18:36:55 jeichorn Exp $
+ */
+/**
+ * Use this element to represent an {@}inline tag} like {@}link}
+ * @see parserStringWithInlineTags
+ * @package phpDocumentor
+ * @subpackage InlineTags
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Revision: 1.1 $
+ * @tutorial inlinetags.pkg
+ */
+class parserInlineTag extends parserBase
+{
+ /**
+ * Element type
+ *
+ * Type is used by many functions to skip the hassle of
+ *
+ * <code>
+ * if phpDocumentor_get_class($blah) == 'parserBlah'
+ * </code>
+ * always "inlinetag"
+ * @var string
+ */
+ var $type = 'inlinetag';
+ /**
+ * the name of the inline tag (like link)
+ * @var string
+ */
+ var $inlinetype = '';
+
+ /**
+ * @param string $type tag type (example: link)
+ * @param string $value tag value (example: what to link to)
+ */
+ function parserInlineTag($type,$value)
+ {
+ $this->inlinetype = $type;
+ $this->value = trim($value);
+ }
+
+ /**
+ * @return integer length of the tag
+ */
+ function Strlen()
+ {
+ // fix 1203451
+ if (is_array($this->value))
+ {
+ return array_reduce(create_function('$a,$b', 'return $a + strlen($b);')) +
+ count($this->value);
+ }
+ return strlen($this->value);
+ }
+
+ /**
+ * @return string always '', used by {@link Parser::handleDocBlock()} to
+ * calculate the short description of a DocBlock
+ * @see parserStringWithInlineTags::getString()
+ * @see parserStringWithInlineTags::trimmedStrlen()
+ */
+ function getString()
+ {
+ return '';
+ }
+}
+
+/**
+ * represents inline links
+ * @tutorial tags.inlinelink.pkg
+ * @package phpDocumentor
+ * @subpackage InlineTags
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ */
+class parserLinkInlineTag extends parserInlineTag
+{
+ /**
+ * text to display in the link, can be different from the link for standard
+ * links like websites
+ * @var string
+ */
+ var $linktext = '';
+
+ /**
+ * @param string $link stored in $value, see {@link parserBase::$value}
+ * @param string $text see {@link $linktext}
+ */
+ function parserLinkInlineTag($link,$text)
+ {
+ if (strpos($link, ','))
+ {
+ $link = explode(',',$link);
+ parserInlineTag::parserInlineTag('link','');
+ $this->value = $link;
+ } else
+ {
+ parserInlineTag::parserInlineTag('link',$link);
+ }
+ $this->linktext = trim($text);
+ }
+
+ /**
+ * @param Converter converter used to change the abstract link into text for
+ * display
+ * @return false|string returns the converted link or false if not converted
+ * successfully
+ */
+ function Convert(&$c)
+ {
+ if (is_array($this->value))
+ {
+ $ret = '';
+ foreach($this->value as $text)
+ {
+ if (!empty($ret))
+ {
+ $ret .= ', ';
+ }
+ $ret .= $this->ConvertPart($c, trim($text));
+ }
+ return $ret;
+ } else
+ {
+ return $this->ConvertPart($c, $this->value);
+ }
+ }
+
+ function ConvertPart(&$c, $value)
+ {
+ if (strpos($value,'://') || (strpos($value,'mailto:') === 0))
+ {
+ if (strpos($value, ' '))
+ {
+ $value = explode(' ', $value);
+ $link = array_shift($value);
+ $text = join(' ', $value);
+ } else
+ {
+ $link = $value;
+ $text = $this->linktext;
+ }
+ return $c->returnLink($link,htmlspecialchars($text));
+ } else
+ {
+ $savevalue = $value;
+ $descrip = false;
+ if (strpos(trim($value),' '))
+ {
+ $v = preg_split('/\s/',trim($value));
+ if (in_array(strtolower($v[0]), array('object', 'function')))
+ {
+ if (!isset($v[1]) ||
+ (isset($v[1]) && strlen($v[1])
+ && !in_array($v[1]{0}, array('$','&'))
+ && $v[1] != '###commanana####'))
+ {
+ $vsave = $v[0];
+ array_shift($v);
+ $v[0] = $vsave . ' ' . $v[0];
+ }
+ }
+ $value = $c->getLink($v[0]);
+ array_shift($v);
+ $descrip = join($v,' ');
+ $descrip = str_replace('###commanana####', ',', $descrip);
+ } else
+ {
+ $value = $c->getLink($value);
+ }
+ if (is_string($value))
+ {
+ // feature 564991
+ if (strpos($value,'://'))
+ {
+ // php function
+ return $c->returnLink($value,str_replace('PHP_MANUAL#','',$value));
+ }
+ return $value;
+ }
+ if (!$descrip) $descrip = $c->type_adjust($savevalue);
+ if (is_object($value)) return $c->returnSee($value, $descrip);
+/* // getLink parsed a comma-delimited list of linked thingies, add the commas back in
+ if (is_array($value))
+ {
+ $a = '';
+ foreach($value as $i => $bub)
+ {
+ if (!empty($a)) $a .= ', ';
+ if (is_string($value[$i]))
+ {
+ // feature 564991
+ if (strpos($value[$i],'://'))
+ {
+ // php function
+ $a .= $c->returnLink($value[$i],str_replace('PHP_MANUAL#','',$vals[$i]));
+ } else
+ $a .= $value[$i];
+ }
+ if (is_object($value[$i])) $a .= $c->returnSee($value[$i],$descrip[$i]);
+ }
+ return $a;
+ } */
+ return $savevalue;
+ }
+ }
+}
+
+/**
+ * Represents inline links to external tutorial documentation
+ * @tutorial tags.inlinetutorial.pkg
+ * @package phpDocumentor
+ * @subpackage InlineTags
+ */
+class parserTutorialInlineTag extends parserLinkInlineTag
+{
+ /**
+ * @param string $link stored in $value, see {@link parserBase::$value}
+ * @param string $text see {@link $linktext}
+ */
+ function parserTutorialInlineTag($link,$text)
+ {
+ parserInlineTag::parserInlineTag('tutorial',$link);
+ $this->linktext = trim($text);
+ }
+
+ /**
+ * @param Converter converter used to change the abstract link into text for display
+ * @return mixed returns the converted link or false if not converted successfully
+ */
+ function Convert(&$c)
+ {
+ $descrip = false;
+ if (strpos($this->value,',') === false)
+ {
+ if (strpos(trim($this->value),' '))
+ {
+ $v = split(' ',trim($this->value));
+ $value = $c->getTutorialLink($v[0]);
+ array_shift($v);
+ $descrip = join($v,' ');
+ } else $value = $c->getTutorialLink($this->value);
+ } else
+ {
+ $vals = split(',',$this->value);
+ $descrip = array();
+ foreach($vals as $val)
+ {
+ $val = trim($val);
+ if (strpos($val,' '))
+ {
+ $v = split(' ',$val);
+ $value[] = $c->getTutorialLink($v[0]);
+ array_shift($v);
+ $descrip[] = join($v,' ');
+ } else
+ {
+ $value[] = $c->getTutorialLink($val);
+ $descrip[] = false;
+ }
+ }
+ }
+ if (is_string($value))
+ {
+ return $value;
+ }
+ if (is_object($value)) return $c->returnSee($value,$descrip);
+ // getLink parsed a comma-delimited list of linked thingies, add the commas back in
+ if (is_array($value))
+ {
+ $a = '';
+ foreach($value as $i => $bub)
+ {
+ if (!empty($a)) $a .= ', ';
+ if (is_string($value[$i]))
+ {
+ $a .= $value[$i];
+ }
+ if (is_object($value[$i])) $a .= $c->returnSee($value[$i],$descrip[$i]);
+ }
+ return $a;
+ }
+ return false;
+ }
+}
+
+/**
+ * represents inline source tag, used for function/method source
+ * @tutorial tags.inlinesource.pkg
+ * @package phpDocumentor
+ * @subpackage InlineTags
+ */
+class parserSourceInlineTag extends parserInlineTag
+{
+ /**
+ * always 'source'
+ * @var string
+ */
+ var $inlinetype = 'source';
+ /**
+ * First line of source code to display
+ * @var integer
+ * @see $end
+ */
+ var $start = 1;
+ /**
+ * Last line to display
+ * @var '*'|integer If '*' then the whole source will be used, otherwise
+ * the {@link $start} to $end line numbers will be displayed
+ */
+ var $end = '*';
+ /**
+ * tokenized source organized by line numbers for php 4.3.0+, the old
+ * {@}source} tag used a string
+ * @var string|array
+ */
+ var $source = false;
+ /**#@+ @access private */
+ /** @var string|false */
+ var $_class;
+ /**#@-*/
+ /**
+ * @param string format "start [end]" where start and end are line numbers
+ * with the end line number optional
+ */
+ function parserSourceInlineTag($value)
+ {
+ parserInlineTag::parserInlineTag('source','');
+ preg_match('/^([0-9]*)\W([0-9]*)$/',trim($value), $match);
+ if (!count($match))
+ {
+ preg_match('/^([0-9]*)$/',trim($value),$match);
+ if (count($match))
+ {
+ $this->start = (int) $match[1];
+ }
+ } else
+ {
+ $this->start = (int) $match[1];
+ $this->end = (int) $match[2];
+ }
+ }
+
+ /**
+ * only used to determine blank lines. {@}source} will not be blank,
+ * probably
+ */
+ function Strlen()
+ {
+ return 1;
+ }
+
+ function getString()
+ {
+ return '{@source}';
+ }
+
+ /**
+ * @param string|array source code
+ * @param boolean in php 4.3.0, if this is a method this will be true
+ * @param string class name if this is a method
+ */
+ function setSource($source, $class = false)
+ {
+ if (is_array($source))
+ {
+ $this->_class = $class;
+ $this->source = $source;
+ } else
+ {
+ $source = strstr($source,'function');
+ $pos = strrpos($source,'}');
+ $this->source = substr($source,0,$pos + 1);
+ }
+ }
+
+ /**
+ * @uses stringConvert() in PHP 4.2.3-, this method is used to convert
+ * @uses arrayConvert() in PHP 4.3.0+, this method is used to convert
+ * @param Converter
+ */
+ function Convert(&$c)
+ {
+ if (is_string($this->source)) return $this->stringConvert($c);
+ return $this->arrayConvert($c);
+ }
+
+ /**
+ * @param Converter
+ * @uses phpDocumentor_HighlightParser Parses the tokenized source
+ */
+ function arrayConvert(&$c)
+ {
+ $source = $this->source;
+ if ($this->end != '*')
+ {
+ $source = array_slice($this->source,0,$this->end + $this->start - 1);
+ }
+ $start = $this->start - 1;
+ if ($start < 0) $start = 0;
+ return $c->ProgramExample($source, true, true, $this->_class, $start);
+ }
+
+ /**
+ * @param Converter
+ * @uses Converter::unmangle() remove the extraneous stuff from
+ * {@link highlight_string()}
+ * @deprecated in favor of PHP 4.3.0+ {@link arrayConvert()}
+ */
+ function stringConvert(&$c)
+ {
+ $source = highlight_string('<?php '.$this->source.' ?>', true);
+ $source = '<code>'.substr($source,strlen('<code><font color="#000000">
+<font color="#0000CC">&lt;?php&nbsp;</font>') - 1);
+ $source = str_replace('}&nbsp;</font><font color="#0000CC">?&gt;</font>','}</font></code>',$source);
+ if ($this->start || ($this->end != '*'))
+ {
+ $source = explode('<br />',$source);
+ $start = $this->start;
+ if ($this->end != '*')
+ {
+ $source = array_slice($source,$start - 1,$this->end - $start + 1);
+ } else
+ {
+ $source = array_slice($source,$start - 1);
+ }
+ $source = implode($source,'<br />');
+ if ($start > 0) $source = "<code>$source";
+ if ($this->end != '*') $source = "$source</code>";
+ }
+ $source = $c->unmangle($source,$this->source);
+ return $source;
+ }
+}
+
+/**
+ * Represents the example inline tag, used to display an example file
+ * inside a docblock or tutorial
+ * @tutorial tags.inlineexample.pkg
+ * @package phpDocumentor
+ * @subpackage InlineTags
+ */
+class parserExampleInlineTag extends parserSourceInlineTag
+{
+ /**
+ * @param string format "filepath[ start [end]]" where start and end are line numbers
+ * with the end line number optional
+ * @param string full path to the current file, used to check relative
+ * directory locations
+ * @param boolean if true, then this is in a tutorial
+ */
+ function parserExampleInlineTag($value, $current_path, $isTutorial = false)
+ {
+ global $_phpDocumentor_setting;
+ parserInlineTag::parserInlineTag('example','');
+ $path = false;
+ $tagValue = trim($value);
+ $path = $isAbsPath = $pathOnly = $fileName = $fileExt = $original_path = $title = FALSE;
+ do
+ {
+ // make sure the format is stuff.ext startline[ endline]
+ if (!preg_match('`(.*)\.(\w*)\s(.*)`', $tagValue, $match))
+ {
+ // or format is stuff.ext
+ if (!preg_match('`(.*)\.(\w*)\s*$`', $tagValue, $match))
+ {
+ // Murphy: Some funny path was given
+ $original_path = $tagValue; // used for error output
+ break; // try-block
+ }
+ }
+ if (strlen($match[1]) === 0)
+ {
+ // Murphy: Some funny path was given
+ $original_path = $tagValue; // used for error output
+ break; // try-block
+ }
+ $fileExt = $match[2];
+ if (isset($match[3]))
+ {
+ $lines = explode(' ', trim($match[3]));
+ $this->start = (int) $lines[0];
+ if (isset($lines[1])) {
+ $this->end = (int) $lines[1];
+ }
+ }
+ $pathTmp = str_replace('\\', '/', $match[1]); // Replace windows '\' the path.
+
+ // Is there a path and a file or is it just a file?
+ if (strpos($pathTmp,'/') === false)
+ {
+ // No path part
+ $pathOnly = '';
+ $fileName = $pathTmp .'.'. $fileExt;
+ } else
+ {
+ $splitPos = strrpos($pathTmp,'/'); // split the path on the last directory, find the filename
+ $pathOnly = substr($match[1], 0, $splitPos+1);
+ $fileName = substr($match[1], $splitPos+1) .'.'. $fileExt;
+ // Is the path absolute? (i.e. does it start like an absolute path?)
+ if (('/' === $pathTmp[0]) || preg_match('`^\w*:`i', $pathTmp))
+ { // works for both windows 'C:' and URLs like 'http://'
+ $isAbsPath = true; // Yes
+ }
+ }
+
+ $original_path = $pathOnly . $fileName;
+
+ // Now look for the file starting with abs. path.
+ if ($isAbsPath)
+ {
+ $tmp = realpath($original_path); // remove any weirdities like /../file.ext
+ if ($tmp && is_file($tmp))
+ {
+ $path = $tmp;
+ }
+ // Alway break if abs. path was detected; even if file was not found.
+ break; // try-block
+ }
+
+ // Search for the example file some standard places
+ // 1) Look if the ini-var examplesdir is set and look there ...
+ if (isset($_phpDocumentor_setting['examplesdir']))
+ {
+ $tmp = realpath($_phpDocumentor_setting['examplesdir'] . PATH_DELIMITER . $original_path);
+ if ($tmp && is_file($tmp))
+ {
+ $path = $tmp; // Yo! found it :)
+ break; // try-block
+ }
+ }
+
+ // 2) Then try to look for an 'example/'-dir below the *currently* parsed file ...
+ if (!empty($current_path))
+ {
+ $tmp = realpath(dirname($current_path) . PATH_DELIMITER . 'examples' . PATH_DELIMITER . $fileName);
+ if ($tmp && is_file($tmp))
+ {
+ $path = $tmp; // Yo! found it :)
+ break; // try-block
+ }
+ }
+
+ // 3) Then try to look for the example file below the subdir PHPDOCUMENTOR_BASE/examples/ ...
+ if (is_dir(PHPDOCUMENTOR_BASE . PATH_DELIMITER . 'examples'))
+ {
+ $tmp = realpath(PHPDOCUMENTOR_BASE . PATH_DELIMITER . 'examples' . PATH_DELIMITER . $original_path);
+ if ($tmp && is_file($tmp))
+ {
+ $path = $tmp; // Yo! found it :)
+ break; // try-block
+ }
+ }
+
+ $tmp = realpath(PHPDOCUMENTOR_BASE . PATH_DELIMITER . $original_path);
+ if ($tmp && is_file($tmp))
+ {
+ $path = $tmp; // Yo! found it :)
+ break; // try-block
+ }
+ // If we reach this point, nothing was found and $path is false.
+ } while (false);
+
+ if (!$path)
+ {
+ addWarning(PDERROR_EXAMPLE_NOT_FOUND, $original_path);
+ $this->path = false;
+ } else
+ {
+ $f = @fopen($path,'r');
+ if ($f)
+ {
+ $example = fread($f,filesize($path));
+ if (tokenizer_ext && !$isTutorial)
+ {
+ $obj = new phpDocumentorTWordParser;
+ $obj->setup($example);
+ $this->setSource($obj->getFileSource());
+ unset($obj);
+ } else
+ {
+ $this->setSource($example);
+ }
+ }
+ }
+ }
+
+ /**
+ * @param string|array source code
+ * @param boolean in php 4.3.0, if this is a method this will be true
+ * @param string class name if this is a method
+ */
+ function setSource($source, $class = false)
+ {
+ $this->_class = $class;
+ $this->source = $source;
+ }
+
+ /**
+ * @param Converter
+ * @uses phpDocumentor_HighlightParser Parses the tokenized source
+ */
+ function arrayConvert(&$c)
+ {
+ $source = $this->source;
+ if ($this->end != '*')
+ {
+ $source = array_slice($this->source,0,$this->end + $this->start - 1);
+ }
+ $start = $this->start - 1;
+ if ($start < 0) $start = 0;
+ return $c->exampleProgramExample($source, true, true, $this->_class, $start);
+ }
+
+ /**
+ * Return the source for the example file, enclosed in
+ * a <programlisting> tag to use in a tutorial
+ * @return string
+ */
+ function getProgramListing()
+ {
+ $source = explode("\n", $this->source);
+ $start = $this->start;
+ if ($this->end != '*')
+ {
+ $source = array_slice($source,$start - 1,$this->end - $start + 1);
+ } else
+ {
+ $source = array_slice($source,$start - 1);
+ }
+ $source = join("\n", $source);
+ return
+ "<programlisting role=\"php\">
+ <![CDATA[\n" .
+ $source .
+ "\n]]>\n</programlisting>";
+ }
+}
+
+/**
+ * Represents the inheritdoc inline tag, used by classes/methods/vars to inherit
+ * documentation from the parent class if possible
+ * @tutorial tags.inlineinheritdoc.pkg
+ * @package phpDocumentor
+ * @subpackage InlineTags
+ */
+class parserInheritdocInlineTag extends parserInlineTag
+{
+ /**
+ * always 'inheritdoc'
+ * @var string
+ */
+ var $inlinetype = 'inheritdoc';
+
+ /**
+ * Does nothing, overrides parent constructor
+ */
+ function parserInheritdocInlineTag()
+ {
+ }
+
+ function Convert()
+ {
+ addWarning(PDERROR_INHERITDOC_DONT_WORK_HERE);
+ return '';
+ }
+}
+
+/**
+ * Represents the inline {@}id} tag for tutorials
+ * @tutorial tags.inlineid.pkg
+ * @package phpDocumentor
+ * @subpackage InlineTags
+ */
+class parserIdInlineTag extends parserInlineTag
+{
+ /**
+ * always 'id'
+ * @var string
+ */
+ var $inlinetype = 'id';
+ /**
+ * package of the {@}id}
+ * @var string
+ */
+ var $package = 'default';
+ /**
+ * category of the {@}id}
+ * @var string
+ */
+ var $category = 'default';
+ /**
+ * subpackage of the {@}id}
+ * @var string
+ */
+ var $subpackage = '';
+ /**
+ * full name of the tutorial
+ * @var string
+ */
+ var $tutorial;
+ /**
+ * section/subsection name
+ * @var string
+ */
+ var $id;
+
+ /**
+ * @param string package name
+ * @param string subpackage name
+ * @param string tutorial name
+ * @param string section/subsection name
+ * @param string category name
+ */
+ function parserIdInlineTag($category,$package,$subpackage,$tutorial,$id = false)
+ {
+ $this->package = $package;
+ $this->subpackage = $subpackage;
+ $this->tutorial = $tutorial;
+ $this->id = $id;
+ $this->category = $category;
+ }
+
+ /**
+ * @param Converter
+ * @uses Converter::getTutorialId() retrieve converter-specific ID
+ */
+ function Convert(&$c)
+ {
+ if (!$this->id) return '';
+ return $c->getTutorialId($this->package,$this->subpackage,$this->tutorial,$this->id,$this->category);
+ }
+}
+
+/**
+ * Represents {@}toc} for table of contents generation in tutorials
+ * @tutorial tags.inlinetoc.pkg
+ * @package phpDocumentor
+ * @subpackage InlineTags
+ */
+class parserTocInlineTag extends parserInlineTag
+{
+ /**
+ * always 'toc'
+ * @var string
+ */
+ var $inlinetype = 'toc';
+ /**
+ * @var array format:
+ * <pre>
+ * array(array('tagname' => section,
+ * 'link' => returnsee link,
+ * 'id' => anchor name,
+ * 'title' => from title tag),...)
+ * </pre>
+ * @access private
+ */
+ var $_toc = false;
+ /**
+ * full path to tutorial, used in conversion
+ * @var string
+ * @access private
+ */
+ var $_path = false;
+
+ function parserTocInlineTag()
+ {
+ parent::parserInlineTag('toc','');
+ }
+
+ /**
+ * @param array format:
+ * <pre>
+ * array(array('tag' => {@link parserXMLDocBookTag},
+ * 'id' => {@link parserIdInlineTag},
+ * 'title' => {@link parserXMLDocBookTag title}),...)
+ * </pre>
+ */
+ function setTOC($toc)
+ {
+ $this->toc = $toc;
+ }
+
+ /**
+ * @param string
+ */
+ function setPath($path)
+ {
+ $this->_path = $path;
+ }
+
+ /**
+ * @uses Converter::formatTutorialTOC() passes an array of format:
+ *
+ * <pre>
+ * array(
+ * 'tagname' => string name of tag,
+ * 'link' => {@link tutorialLink} to the tutorial,
+ * 'id' => converter specific tutorial ID from {@link Converter::getTutorialId()}
+ * 'title' => title of the tutorial)
+ * </pre>
+ *
+ * and returns the results as the table of contents
+ * @uses Converter::getTutorialId() retrieve the tutorial ID for
+ * @param Converter
+ */
+ function Convert(&$c)
+ {
+ $newtoc = array();
+ foreach($this->toc as $i => $toc)
+ {
+ if (isset($toc['title']))
+ $toc['tag']->setTitle($toc['title']);
+ else
+ $toc['tag']->setTitle(new parserStringWithInlineTags);
+ $newtoc[$i]['tagname'] = $toc['tag']->name;
+ $l = new tutorialLink;
+ if (!isset($toc['title'])) $title = 'section '.$toc['id']->id;
+ else
+ $title = $toc['title']->Convert($c);
+ $l->addLink($toc['id']->id,$this->_path,basename($this->_path),$toc['id']->package, $toc['id']->subpackage, strip_tags($title));
+ $newtoc[$i]['link'] = $c->returnSee($l);
+ $newtoc[$i]['id'] = $c->getTutorialId($toc['id']->package, $toc['id']->subpackage, basename($this->_path), $toc['id']->id, $toc['id']->category);
+ $newtoc[$i]['title'] = $title;
+ }
+ return $c->formatTutorialTOC($newtoc);
+ }
+}
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/IntermediateParser.inc b/buildscripts/PhpDocumentor/phpDocumentor/IntermediateParser.inc
new file mode 100644
index 00000000..92a54ea0
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/IntermediateParser.inc
@@ -0,0 +1,1832 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/** The phpDocumentor_IntermediateParser Class
+ *
+ * The Intermediary Data Parser (intermediate between Parse and Converter)
+ *
+ * @author Gregory Beaver
+ * @version $Revision: 1.2 $
+ * @copyright 2002 Gregory Beaver
+ * @package phpDocumentor
+ */
+/** The phpDocumentor_IntermediateParser Class
+ *
+ * This class performs the work of organizing raw data from the parser in the
+ * format of descendants of the {@link parserElement} class. This is also where
+ * processing of package pages occurs, in
+ * {@link phpDocumentor_IntermediateParser::handleClass()} for class-level
+ * packages and {@link phpDocumentor_IntermediateParser::handleDocBlock()} for
+ * page-level packages.
+ *
+ * Most of the work of this parser goes to matching up
+ * DocBlocks with the elements that they are documenting. Since DocBlocks are
+ * passed before the element they document, the last DocBlock is stored in
+ * {@link phpDocumentor_IntermediateParser::$last} and then placed into the
+ * $docblock parameter of the parserElement
+ * descendant object.
+ * @author Gregory Beaver
+ * @version $Id: IntermediateParser.inc,v 1.2 2005/11/20 19:26:12 cellog Exp $
+ * @copyright 2002 Gregory Beaver
+ * @package phpDocumentor
+ */
+class phpDocumentor_IntermediateParser
+{
+ /**
+ * @var parserDocBlock
+ */
+ var $last;
+
+ /**
+ * type of the last parser Element handled
+ *
+ * This is used in handleDocBlock to determine whether a DocBlock is a
+ * page-level DocBlock in conjunction with the {@link parserData::$clean}
+ * var. A page-level DocBlock is alwaysthe first DocBlock in a file, and
+ * must be followed by another DocBlock. The first test is handled by
+ * parserData::$clean, which is set to false on the first encounter of an
+ * element, and the second test is handled by this variable, which must be
+ * equal to "docblock"
+ * @see handleDocBlock()
+ * @var string
+ */
+ var $lasttype = '';
+
+ /**
+ * Name of the class currently being parsed.
+ * It is only used (and only valid) when phpDocumentor_IntermediateParser is
+ * parsing a class
+ * @var string
+ */
+ var $cur_class = '';
+
+ /**
+ * type of the current parser Element being handled
+ *
+ * This is used by {@link HandleEvent()} to set the {@link $lasttype} var,
+ * which is used to detect page-level DocBlocks
+ * @var string
+ */
+ var $type = '';
+
+ /**
+ * set in {@link Setup.inc.php} to the value of the parseprivate commandline
+ * option. If this option is true, elements with an @access private tag
+ * will be parsed and displayed
+ * @tutorial phpDocumentor.howto.pkg#using.command-line.parseprivate
+ * @var boolean
+ */
+ var $parsePrivate = false;
+
+ /**
+ * this variable is used to prevent parsing of elements with an @ignore tag
+ * @see $packageoutput
+ * @see $parsePrivate
+ */
+ var $private_class = false;
+
+ /**
+ * used to set the output directory
+ * @see setTargetDir()
+ */
+ var $targetDir;
+
+ /**
+ * used to set the template base directory
+ * @see setTemplateBase()
+ */
+ var $templateBase;
+
+ /**
+ * array of parsed package pages
+ *
+ * used by {@link Convert()} to convert all package pages into output
+ * @var array
+ */
+ var $package_pages = array();
+
+ /**
+ * @var array array of all {@link parserData} containing page information
+ */
+ var $pages = array();
+ /**
+ * Put away a page that has been @ignored or @access private if
+ * !{@link $parsePrivate}
+ *
+ * When a page has @access private in its DocBlock, it is placed here
+ * instead of in {@link $pages}, to allow for proper Class parsing. Since
+ * classes and pages are parsed as if they were separate, this array allows
+ * public classes on private pages to retrieve information needed about the
+ * page that holds the class and to {@link addPageIfNecessary()} to the
+ * $pages array
+ * @var array
+ */
+ var $privatepages = array();
+ /**
+ * Keeps track of packages of classes that have parent classes in another
+ * package. Used in automatic linking.
+ *
+ * This array is updated by {@link addPackageParent()}, which is called in
+ * {@link Classes::processChild()} to keep track of classes that descend
+ * from classes in different packages. In other words, if class foo is in
+ * package one, and class bar is in package two, an entry
+ * $package_parents['two'] = 'one' will be made.
+ * @var array Format: packagename => parentpackagename
+ * @see Converter::getLink()
+ */
+ var $package_parents = array();
+
+ /**
+ * Used to determine the category for tutorials.
+ *
+ * <b>WARNING:</b> If more than one category exists, the last category
+ * encountered will overwrite the previous and will raise a big warning
+ * @var array Format: packagename => categoryname
+ */
+ var $packagecategories = array();
+
+ /**
+ * list of all packages encountered while documenting. Used in automatic
+ * linking.
+ *
+ * Converter::getLink() first checks if an ambiguous link is found in the
+ * current package. If not, it then checks in parent packages, and if still
+ * not found, uses this array to check in the rest of the packages before
+ * giving up
+ * @var array Format: array(packagename => 1, packagename => 1,...)
+ * @see Converter::getLink()
+ */
+ var $all_packages = array();
+
+ /**
+ * array of packages to parser and output documentation for, if not all
+ * packages should be documented
+ *
+ * Format:<br />
+ * array(package1,package2,...)<br />
+ * or false if not set
+ *
+ * Use this option to limit output similar to ignoring files. If you have
+ * some temporary files that you don't want to specify by name but don't
+ * want included in output, set a package name for all the elements in your
+ * project, and set packageoutput to that name. the default package will be
+ * ignored. Parsing speed does not improve. If you want to ignore files
+ * for speed reasons, use the ignore command-line option
+ * @tutorial phpDocumentor.howto.pkg#using.command-line.packageoutput
+ * @see Io
+ * @var false|array
+ */
+ var $packageoutput = false;
+
+ /**
+ * the functions which handle output from the {@link Parser}
+ * @see handleEvent(), handleDocBlock(), handlePage(), handleClass()
+ * @see handleDefine(), handleFunction(), handleMethod(), handleVar()
+ * @see handlePackagePage(), handleInclude(), handleTutorial()
+ */
+ var $event_handlers = array(
+ 'docblock' => 'handleDocBlock',
+ 'page' => 'handlePage',
+ 'class' => 'handleClass',
+ 'define' => 'handleDefine',
+ 'function' => 'handleFunction',
+ 'method' => 'handleMethod',
+ 'var' => 'handleVar',
+ 'const' => 'handleConst',
+ 'packagepage' => 'handlePackagePage',
+ 'include' => 'handleInclude',
+ 'global' => 'handleGlobal',
+ 'tutorial' => 'handleTutorial',
+ );
+
+ /**
+ * $data contains parsed structures for the current page being parsed
+ *
+ * In version 1.1+, $data is only used to store the current page information.
+ * All handling of documented elements is handled by the
+ * {@link ProceduralPages} and {@link Classes} classes.
+ * @var parserData
+ */
+ var $data;
+
+ /**
+ * set in {@link Setup.inc.php} to the value of the quitemode commandline
+ * option.
+ *
+ * If this option is true, informative output while parsing will not be
+ * displayed (documentation is unaffected)
+ * @var boolean
+ * @tutorial phpDocumentor.howto.pkg#using.command-line.quiet
+ */
+ var $quietMode = false;
+
+ /**
+ * used to keep track of inheritance at the smartest level possible for a
+ * dumb computer
+ * @var Classes
+ */
+ var $classes = false;
+
+ /**
+ * used to keep track of all elements in a procedural page. Handles name
+ * conflicts with elegance
+ * @since 1.1
+ * @var ProceduralPages
+ */
+ var $proceduralpages = false;
+
+ /**
+ * an array of template names indexed by converter name
+ *
+ * For example, if the default HTMLframesConverter is using the DOM/l0l33t
+ * template, the array will be
+ * <code>$converters['frames'] = 'DOM/l0l33t'</code>
+ * @var array Format: array(Convertername1 => templatename)
+ * @see Converter
+ */
+ var $converters = false;
+ /**
+ * @var string Title of generated documentation, passed to Converters
+ */
+ var $title = '';
+
+ var $uses = array();
+
+ var $db_template;
+
+ /**
+ * Stores parsed CHANGELOG/INSTALL/README files
+ * @var array Format: array(CHANGELOG => contents,
+ * INSTALL => contents,
+ * README => contents)
+ */
+ var $ric = array();
+
+ /**
+ * Flag used to determine whether the last docblock
+ * was a page-level docblock.
+ * @var boolean
+ * @access private
+ */
+ var $_lastDocBlockWasPageLevel = false;
+
+ /**
+ * Flag used to determine whether the Page-level
+ * DocBlock was declared in old or new style
+ * @var boolean
+ * @access private
+ */
+ var $_oldPageLevel = false;
+
+ /**
+ * sets up basic data structures
+ * @param string Title of generated documentation, passed to Converters
+ * @see $title, $data, $classes, $proceduralpages
+ */
+ function phpDocumentor_IntermediateParser($title='Generated Documentation')
+ {
+ $this->title = $title;
+ $this->data = new parserData;
+ $this->classes = new Classes;
+ $this->proceduralpages = new ProceduralPages;
+ }
+
+ /**
+ * Retrieve the relative path. If the path contains "pear/" it will
+ * be used as the base, otherwise the Program_Root string will be used.
+ * @global array uses 'Program_Root' option to replace it with '' for
+ * retrieving the source location of a file
+ * @param string path to file
+ * @return string
+ * @see $sourceLocation
+ * @access private
+ */
+ function _getSourceLocation($sl, $sourceloc)
+ {
+ global $_phpDocumentor_options;
+ if (empty($sl)) return false;
+ $sl = str_replace('\\','/',$sl);
+ if (strpos($sl,'pear/'))
+ {
+ $sl = substr($sl,strpos($sl,'pear/') + 5);
+ if (dirname($sl) == '.')
+ {
+ return 'PEAR';
+ }
+ return dirname($sl);
+ } else
+ {
+ if (strpos(str_replace($_phpDocumentor_options['Program_Root'] . PATH_DELIMITER,'',$sourceloc),PATH_DELIMITER) === false)
+ return '';
+ return dirname(str_replace($_phpDocumentor_options['Program_Root'] . PATH_DELIMITER,'',$sourceloc));
+ }
+ }
+
+ /**
+ * Guess the package/subpackage based on subdirectory if the --pear option
+ *
+ * A file in pear/dir/file.php will be in package "dir." A file in
+ * pear/dir/subdir/file.php will be in package "dir," subpackage "subdir."
+ * @param string full path of file
+ * @param template-ready source location Program_Root/dir/file.php
+ * @global array uses the 'pear' option to determine whether to guess based
+ * on subdirectory
+ * @tutorial phpDocumentor.howto.pkg#using.command-line.pear
+ */
+ function _guessPackage($path, $sourceloc)
+ {
+ global $_phpDocumentor_setting;
+ if ($_phpDocumentor_setting['pear'])
+ {
+ $subpath = explode(PATH_DELIMITER, $this->_getSourceLocation($path, $sourceloc));
+ if (!empty($subpath[0]))
+ { // can only have package and subpackage in this version
+ $package = $subpath[0];
+ $subpackage = '';
+ if (isset($subpath[1])) $subpackage = $subpath[1];
+ return array($package,$subpackage);
+ } else return array($this->package, $this->subpackage);
+ } else return array($this->package, $this->subpackage);
+ }
+
+ /**
+ * handles post-parsing of include/require/include_once/include_once
+ *
+ * This function sets {@link $data}->clean to false to tell the
+ * phpDocumentor_IntermediateParser that a page-level DocBlock can't be
+ * found after this point on this page. It then sets the package
+ * to be the same as the page, and adds itself to the
+ * {@link ProceduralPages} class
+ * @param integer $event Event number from {@link Parser.inc}
+ * @param parserInclude $data
+ */
+ function handleInclude($event,$data)
+ {
+ if ($this->_lastDocBlockWasPageLevel)
+ {
+ addWarning(PDERROR_DOCBLOCK_CONFLICT, $data->getName(), $data->getFile());
+ if (!$this->_oldPageLevel)
+ {
+ unset($this->last);
+ }
+ }
+ $this->_lastDocBlockWasPageLevel =
+ $this->data->clean = false;
+ // page was @ignored
+ if ($this->private_page)
+ {
+ unset($this->last);
+ return;
+ }
+ if (empty($this->last))
+ {
+ if (isset($this->db_template))
+ // use the docblock template
+ $this->last = phpDocumentor_clone($this->db_template);
+ else
+ // we don't have a docblock, create an empty one to get rid of errors
+ $this->last = new parserDocblock();
+ }
+// $this->last->setLineNumber($data->getLineNumber());
+ if ($this->last->getKeyword('ignore'))
+ {
+ $this->last = false;
+ return;
+// addWarning(PDERROR_IGNORE_TAG_IGNORED,'include',$data->getName().'('.$data->getValue().')');
+ }
+
+ $this->last->overridePackage($this->category,$this->package,$this->subpackage,$data->getName(),'include');
+ $data->setDocBlock($this->last);
+ $this->proceduralpages->addInclude($data);
+ $this->last = false;
+ }
+
+ /**
+ * handles post-parsing of global variables
+ *
+ * This function sets {@link $data}->clean to false to tell the
+ * phpDocumentor_IntermediateParser that a page-level DocBlock can't be
+ * found after this point on this page. It then sets the package
+ * to be the same as the page, and adds itself to the
+ * {@link ProceduralPages} class
+ * @param integer $event Event number from {@link Parser.inc}
+ * @param parserGlobal $data
+ */
+ function handleGlobal($event,$data)
+ {
+ if ($this->_lastDocBlockWasPageLevel)
+ {
+ addWarning(PDERROR_DOCBLOCK_CONFLICT, 'global variable', $data->getName());
+ if (!$this->_oldPageLevel)
+ {
+ unset($this->last);
+ }
+ }
+ $this->_lastDocBlockWasPageLevel =
+ $this->data->clean = false;
+ if ($this->private_page)
+ {
+ unset($this->last);
+ return;
+ }
+ if (empty($this->last))
+ {
+ if (isset($this->db_template))
+ // use the docblock template
+ $this->last = phpDocumentor_clone($this->db_template);
+ else
+ // we don't have a docblock, create an empty one to get rid of errors
+ $this->last = new parserDocblock();
+ }
+// $this->last->setLineNumber($data->getLineNumber());
+ if ($this->last->getKeyword('ignore'))
+ {
+ addWarning(PDERROR_IGNORE_TAG_IGNORED,'global variable - just don\'t document the',$data->getName());
+ $this->last = false;
+ return;
+ }
+ $this->last->overridePackage($this->category,$this->package,$this->subpackage,$data->getName(),'global');
+ $data->setDocBlock($this->last);
+ if ($data->docblock->getKeyword('name'))
+ {
+ $a = $data->docblock->getKeyword('name');
+ if (is_object($a)) $a = $a->value;
+ $data->setName($a);
+ }
+ $this->proceduralpages->addGlobal($data);
+ $this->last = false;
+ }
+
+ /**
+ * handles post-parsing of Package-level documentation pages.
+ *
+ * sets the {@link $package_pages}[$data->package] to $data
+ * @param integer $event Event number from {@link Parser.inc}
+ * @param parserPackagePage $data
+ */
+ function handlePackagePage($event,$data)
+ {
+ $this->package_pages[$data->package] = &$data;
+ $this->last = false;
+ }
+
+ /**
+ * handle post-parsing of Tutorials.
+ *
+ * This adds the parsed tutorial to the tutorial tree
+ * @uses $tutorials sets the value of tutorials to parameter $data
+ * @param integer $event Event Number
+ * @param parserTutorial $data
+ * @since 1.2
+ */
+ function handleTutorial($event,$data)
+ {
+ if (isset($this->packagecategories[$data->package]))
+ {
+ $data->category = $this->packagecategories[$data->package];
+ } else
+ {
+ $data->category = $GLOBALS['phpDocumentor_DefaultCategoryName'];
+ }
+ $this->tutorials[$data->package][$data->subpackage][$data->tutorial_type][$data->name] = $data;
+ }
+
+ /**
+ * handles post-parsing of class vars
+ *
+ * This function sets up a @var tag if none is found, and aligns $data's
+ * $path var and packages to match the parent object
+ * @param integer $event Event number from {@link Parser.inc}
+ * @param parserVar $data
+ */
+ function handleVar($event,$data)
+ {
+ global $_phpDocumentor_setting;
+ if ($this->private_class)
+ {
+ unset($this->last);
+ return;
+ }
+ if (empty($this->last))
+ {
+ if (isset($this->db_template))
+ {
+ // use the docblock template
+ $this->last = phpDocumentor_clone($this->db_template);
+ } else {
+ // we don't have a docblock, create an empty one to get rid of errors
+ $this->last = new parserDocblock();
+ }
+ }
+// $this->last->setLineNumber($data->getLineNumber());
+ $this->last->overridePackage($this->category,$this->package,$this->subpackage,$data->getName(),'var');
+ $this->last->updateModifiers($data->getModifiers());
+
+ if ($this->last->getKeyword('ignore'))
+ {
+ $this->last = false;
+ return;
+// addWarning(PDERROR_IGNORE_TAG_IGNORED,'var',$this->cur_class.'::'.$data->getName());
+ }
+ if (!$this->last->var)
+ {
+ $this->last->addVar('mixed',new parserStringWithInlineTags);
+ }
+
+ if ($_phpDocumentor_setting['pear'])
+ {
+ if (strpos($data->getName(), '_') == 1 && !$this->last->getKeyword('access'))
+ {
+ addWarning(PDERROR_PRIVATE_ASSUMED,'class variable',$data->class.'::'.$data->getName());
+ $this->last->addKeyword('access','private');
+ $data->setDocBlock($this->last);
+ }
+ }
+ $data->setDocBlock($this->last);
+ $data->path = $this->data->parent->path;
+ $this->classes->addVar($data);
+ $this->last = false;
+ }
+
+ /**
+ * handles post-parsing of class constants
+ *
+ * This function aligns $data's
+ * $path var and packages to match the parent object
+ * @param integer $event Event number from {@link Parser.inc}
+ * @param parserVar $data
+ */
+ function handleConst($event,$data)
+ {
+ global $_phpDocumentor_setting;
+ if ($this->private_class)
+ {
+ unset($this->last);
+ return;
+ }
+ if (empty($this->last))
+ {
+ if (isset($this->db_template))
+ // use the docblock template
+ $this->last = phpDocumentor_clone($this->db_template);
+ else
+ // we don't have a docblock, create an empty one to get rid of errors
+ $this->last = new parserDocblock();
+ }
+// $this->last->setLineNumber($data->getLineNumber());
+ $this->last->overridePackage($this->category,$this->package,$this->subpackage,$data->getName(),'const');
+
+ if ($this->last->getKeyword('ignore'))
+ {
+ $this->last = false;
+ return;
+// addWarning(PDERROR_IGNORE_TAG_IGNORED,'var',$this->cur_class.'::'.$data->getName());
+ }
+ $data->setDocBlock($this->last);
+ $data->path = $this->data->parent->path;
+ $this->classes->addConst($data);
+ $this->last = false;
+ }
+
+ /**
+ * handles post-parsing of class methods
+ *
+ * This function first aligns $data's path and package to match the parent
+ * object, and also aligns the docblock's @param, @global, and @staticvar
+ * tags with the information parsed from the method source code. It also
+ * checks to see if the method is a constructor and sets the $isConstructor
+ * flag. If source code has been parsed by a {@}source} tag, the source is
+ * added to its docblock
+ *
+ * Finally, it adds the method to the {@link Classes} class.
+ * @param integer $event Event number from {@link Parser.inc}
+ * @param parserMethod $data
+ */
+ function handleMethod($event,$data)
+ {
+ global $_phpDocumentor_setting;
+ if ($this->private_class)
+ {
+ unset($this->last);
+ return;
+ }
+
+ if (empty($this->last))
+ {
+ if (isset($this->db_template))
+ // use the docblock template
+ $this->last = phpDocumentor_clone($this->db_template);
+ else
+ // we don't have a docblock, create an empty one to get rid of errors
+ $this->last = new parserDocblock();
+ }
+// $this->last->setLineNumber($data->getLineNumber());
+ if ($this->last->getKeyword('ignore'))
+ {
+ $this->last = false;
+ return;
+// addWarning(PDERROR_IGNORE_TAG_IGNORED,'method',$this->cur_class.'::'.$data->getName());
+ }
+ $this->last->overridePackage($this->category,$this->package,$this->subpackage,$data->getName(),'method');
+ if ($data->hasSource())
+ {
+ $this->last->setSource($data->getSource(), $data->getClass());
+ }
+ foreach($data->listParams() as $param)
+ {
+ $update_params[] = $param[0];
+ }
+ foreach($data->listGlobals() as $param)
+ {
+ $update_globals[] = $param[1];
+ }
+ foreach($data->listStatics() as $param)
+ {
+ $update_statics[] = $param[0];
+ }
+ if (isset($update_params))
+ $this->last->updateParams($update_params);
+ if (isset($update_globals))
+ $this->last->updateGlobals($update_globals);
+ if (isset($update_statics))
+ $this->last->updateStatics($update_statics);
+ $this->last->updateModifiers($data->getModifiers());
+ unset($update_params);
+ unset($update_globals);
+ unset($update_statics);
+
+ if ($data->getName() == $this->cur_class) $data->setConstructor();
+ if ($data->getName() == '__construct') {
+ $data->setConstructor();
+ }
+ if ($data->getName() == '__destruct') {
+ $data->setDestructor();
+ }
+
+ if ($_phpDocumentor_setting['pear'])
+ {
+ if (strpos($data->getName(), '_') === 0 && substr($data->getName(), 1) == $data->class)
+ { // is destructor
+ $data->setDestructor();
+ } elseif (strpos($data->getName(), '_') === 0 && !$this->last->getKeyword('access'))
+ {
+ if (strpos($data->getName(), '__') !== 0) {
+ addWarning(PDERROR_PRIVATE_ASSUMED,'method',$data->class.'::'.$data->getName().'()');
+ $this->last->addKeyword('access','private');
+ $data->setDocBlock($this->last);
+ }
+ }
+ }
+ $data->setDocBlock($this->last);
+ $data->path = $this->data->parent->path;
+ $this->classes->addMethod($data);
+ $this->last = false;
+ }
+
+ /**
+ * handles post-parsing of functions
+ *
+ * This function sets {@link $data}->clean to false to tell the
+ * phpDocumentor_IntermediateParser that a page-level DocBlock can't be
+ * found after this point on this page. It then sets the package to be the
+ * same as the page, aligns the docblock's @param, @global, and @staticvar
+ * tags with the information parsed from the function source code.
+ *
+ * If source code has been parsed by a {@}source} tag, the source is added
+ * to its docblock, and then the parserFunction adds itself to the
+ * {@link ProceduralPages} class
+ * @param integer $event Event number from {@link Parser.inc}
+ * @param parserFunction $data
+ */
+ function handleFunction($event,$data)
+ {
+ if ($this->_lastDocBlockWasPageLevel)
+ {
+ addWarning(PDERROR_DOCBLOCK_CONFLICT, 'function', $data->getName());
+ if (!$this->_oldPageLevel)
+ {
+ unset($this->last);
+ }
+ }
+ $this->_lastDocBlockWasPageLevel =
+ $this->data->clean = false;
+ if ($this->private_page)
+ {
+ unset($this->last);
+ return;
+ }
+
+ if (empty($this->last))
+ {
+ if (isset($this->db_template))
+ // use the docblock template
+ $this->last = phpDocumentor_clone($this->db_template);
+ else
+ // we don't have a docblock, create an empty one to get rid of errors
+ $this->last = new parserDocblock();
+ }
+// $this->last->setLineNumber($data->getLineNumber());
+ if ($this->last->getKeyword('ignore'))
+ {
+ unset($this->last);
+ return;
+ }
+ $this->last->overridePackage($this->category,$this->package,$this->subpackage,$data->getName(),'function');
+
+ foreach($data->listParams() as $param)
+ {
+ $update_params[] = $param[0];
+ }
+ foreach($data->listGlobals() as $param)
+ {
+ $update_globals[] = $param[1];
+ }
+ foreach($data->listStatics() as $param)
+ {
+ $update_statics[] = $param[0];
+ }
+ if (isset($update_params))
+ $this->last->updateParams($update_params);
+ if (isset($update_globals))
+ $this->last->updateGlobals($update_globals);
+ if (isset($update_statics))
+ $this->last->updateStatics($update_statics);
+ unset($update_params);
+ unset($update_globals);
+ unset($update_statics);
+
+ if ($data->hasSource())
+ {
+ $this->last->setSource($data->getSource());
+ }
+ if (count($this->last->params) == 1 && !count($data->listParams()))
+ {
+ // if the function has no parameters, and 1 @param, add it to the list as optional, default value is description from @param
+ $pars = $this->last->listParams();
+ $data->addParam($pars[0]['var'],$pars[0]['data']->getString());
+ }
+ $data->setDocBlock($this->last);
+ $this->proceduralpages->addFunction($data);
+ $this->last = false;
+ }
+
+ /**
+ * handles post-parsing of defines
+ *
+ * This function sets {@link $data}->clean to false to tell the
+ * phpDocumentor_IntermediateParser that a page-level DocBlock can't be
+ * found after this point on this page. It then sets the package to be the
+ * same as the page and adds itself to the {@link ProceduralPages} class
+ * @param integer $event Event number from {@link Parser.inc}
+ * @param parserDefine $data
+ */
+ function handleDefine($event,$data)
+ {
+ if ($this->_lastDocBlockWasPageLevel)
+ {
+ addWarning(PDERROR_DOCBLOCK_CONFLICT, 'define', $data->getName());
+ if (!$this->_oldPageLevel)
+ {
+ unset($this->last);
+ }
+ }
+ $this->_lastDocBlockWasPageLevel =
+ $this->data->clean = false;
+ if ($this->private_page)
+ {
+ unset($this->last);
+ return;
+ }
+ if (empty($this->last))
+ {
+ if (isset($this->db_template))
+ // use the docblock template
+ $this->last = phpDocumentor_clone($this->db_template);
+ else
+ // we don't have a docblock, create an empty one to get rid of errors
+ $this->last = new parserDocblock();
+ }
+// $this->last->setLineNumber($data->getLineNumber());
+ if ($this->last->getKeyword('ignore'))
+ {
+ unset($this->last);
+ return;
+ }
+
+ $this->last->overridePackage($this->category,$this->package,$this->subpackage,$data->getName(),'define');
+ $data->setDocBlock($this->last);
+ $this->proceduralpages->addDefine($data);
+ $this->last = false;
+ }
+
+ /**
+ * handles post-parsing of classes
+ *
+ * This function sets {@link $data}->clean to false to tell the
+ * phpDocumentor_IntermediateParser that a page-level DocBlock can't be
+ * found after this point on this page. It sets {@link $cur_class} to its
+ * name, and if an @ignore tag is found in the DocBlock, it sets
+ * {@link $private_class} to true, to prevent post-parsing of any of the
+ * class's vars or methods. Then it checks for the existence of a package
+ * page for the class's package
+ * @param integer $event Event number from {@link Parser.inc}
+ * @param parserClass $data
+ */
+ function handleClass($event,$data)
+ {
+ global $_phpDocumentor_setting;
+ if ($this->_lastDocBlockWasPageLevel)
+ {
+ if (!$this->_oldPageLevel)
+ {
+ addWarning(PDERROR_DOCBLOCK_GOES_CLASS, $data->getName());
+ $doc = new parserDocBlock;
+ $doc->category = $this->category;
+ $doc->package = $this->package;
+ $doc->subpackage = $this->subpackage;
+ if ($_phpDocumentor_setting['sourcecode']) {
+ $doc->canSource();
+ $doc->addFileSource($this->data->parent->path, $this->data->parent->source);
+ }
+ $this->data->setDocBlock($doc);
+ unset($doc);
+ $this->last->cantSource();
+ }
+ }
+ $this->_lastDocBlockWasPageLevel =
+ $this->data->clean = false;
+ if (empty($this->last))
+ {
+ if (isset($this->db_template))
+ // use the docblock template
+ $this->last = phpDocumentor_clone($this->db_template);
+ else
+ // we don't have a docblock, create an empty one to get rid of errors
+ $this->last = new parserDocblock();
+ list($this->last->package, $this->last->subpackage) = $this->_guessPackage($this->data->parent->path, $this->data->parent->getSourceLocation('dummy'));
+ addWarning(PDERROR_NO_PACKAGE_TAG,'class',$data->getName(),$this->last->package);
+ } else
+ {
+ if (!$this->last->getExplicitPackage())
+ {
+ list($this->last->package, $this->last->subpackage) = $this->_guessPackage($this->data->parent->path, $this->data->parent->getSourceLocation('dummy'));
+ addWarning(PDERROR_NO_PACKAGE_TAG,'class',$data->getName(),$this->last->package);
+ } else
+ {
+ if (isset($this->packagecategories[$this->package])
+ && $this->packagecategories[$this->package] != $this->category)
+ addWarning(PDERROR_PACKAGECAT_SET,$this->package,
+ $this->packagecategories[$this->package],
+ $this->category);
+ $this->packagecategories[$this->package] = $this->category;
+ }
+ }
+ $this->last->updateModifiers($data->getModifiers());
+// $this->last->setLineNumber($data->getLineNumber());
+ $data->setDocBlock($this->last);
+ $this->cur_class = $name = $data->getName();
+ if ($this->last->getKeyword('ignore'))
+ {
+ $this->private_class = true;
+ unset($this->last);
+ return;
+ }
+ $data->path = $this->data->parent->path;
+ $this->classes->addClass($data);
+ $this->private_class = false;
+ if ($this->last->package)
+ {
+ $this->parsePackagePage($this->last->package, $this->data->parent->getPath());
+ }
+ $this->last = false;
+ }
+
+ /**
+ * handles post-parsing of procedural pages
+ *
+ * this event is called at the start of a new page, before the Parser knows
+ * whether the page will contain any procedural pages or not
+ * @param integer $event Event number from {@link Parser.inc}
+ * @param parserPage $data
+ */
+ function handlePage($event,$data)
+ {
+ $type = 'page';
+ $this->private_page = false;
+ $this->data = new parserData;
+ $data->category = $this->category = $GLOBALS['phpDocumentor_DefaultCategoryName'];
+ $this->package = $GLOBALS['phpDocumentor_DefaultPackageName'];
+ $this->subpackage = '';
+ $this->proceduralpages->addPage($data);
+ $this->data->setParent($data);
+ $this->pages[$data->getPath()] = $this->data;
+ $this->classes->nextFile($data->getPath());
+ $this->packageoutput = $data->getPackageOutput();
+ }
+
+ /**
+ * handles post-parsing of DocBlocks
+ *
+ * This function sets {@link $last} to the DocBlock represented by $data, to
+ * allow the next documentable element passed to
+ * phpDocumentor_IntermediateParser to link the DocBlock into its $docblock
+ * property. This function also checks for two special cases of DocBlocks:
+ * <ol>
+ * <li>First DocBlock in the file contains a @package tag</li>
+ * <li>First DocBlock in the file is immediately followed by another
+ * DocBlock</li>
+ * </ol>
+ * In both cases, the function extracts this tag and uses it as the
+ * page-level package. If the @package tag is in the DocBlock of an
+ * element (function, global variable, whatever) that isn't a page-level
+ * DocBlock, a warning will be raised to notify the author that a @package
+ * tag belongs in a page-level DocBlock.
+ *
+ * <b>New</b> in version 1.2.2, if the first DocBlock in a file contains
+ * a @package tag, it is a page-level DocBlock.
+ *
+ * If the DocBlock is page-level, it is processed with
+ * {@link _processPageLevelDocBlock}
+ *
+ * Finally, the function replaces the old parserPage in
+ * {@link parserData::$data}->parent with the new one containing information
+ * from the DocBlock by calling {@link addPage()}, and checks for
+ * package-level docs.
+ * @param integer $event Event number from {@link Parser.inc}
+ * @param parserDocBlock $data
+ */
+ function handleDocBlock($event,$data)
+ {
+ $type = 'docblock';
+ $data->postProcess();
+ // Zend desc support
+ if ($tdesc = $data->getKeyword('desc'))
+ {
+ $data->setShortDesc($tdesc);
+ unset($data->tags['desc']);
+ }
+ $this->_lastDocBlockWasPageLevel = false;
+ // 1st docblock in file, check for @package
+ if ($this->data->isClean() && !isset($this->last))
+ {
+ if ($data->getExplicitPackage())
+ {
+ // new with 1.2.2:
+ // if the first docblock in a file
+ // contains a @package tag, then it is
+ // a page-level docblock
+ $this->_processPageLevelDocBlock($data);
+ $this->_lastDocBlockWasPageLevel = true;
+ $this->all_packages[$data->package] = 1;
+ $this->last = $data;
+ return;
+ }
+ $doc = new parserDocBlock;
+ $doc->category = $this->category;
+ $doc->package = $this->package;
+ $doc->subpackage = $this->subpackage;
+ $this->data->setDocBlock($doc);
+ $this->proceduralpages->addPagePackage($this->data->parent->getPath(),$this->package,$this->subpackage);
+ unset($doc);
+ }
+ // 2nd docblock in a row, and it's at the top of the file, page-level docblock
+ if ($this->lasttype == "docblock" && $this->data->isClean())
+ {
+ $this->_processPageLevelDocBlock($this->last);
+ $this->_oldPageLevel = true;
+ $this->_lastDocBlockWasPageLevel = false;
+ }
+ $this->all_packages[$data->package] = 1;
+ $this->last = $data;
+ }
+
+ /**
+ * Process a Page-level DocBlock
+ *
+ * First, it checks for an @ignore tag,
+ * and if found, calls {@link ProceduralPages::ignorePage()}. An @ignore
+ * tag in a page-level DocBlock will ignore all functions, defines, global
+ * variables, and includes. It will not ignore classes! The function next
+ * checks for an @access private, and if --parseprivate is off, performs the
+ * same actions as @ignore, raising a warning for the unsuspecting user.
+ * Next, it checks for the @name tag, which is used to rename the page.
+ * This is also a PEAR compatibility issue, and may not be very useful in
+ * the long run. Documentation is best when it refers to real entities in
+ * the package, and not to aliases.
+ * @access private
+ */
+ function _processPageLevelDocBlock($data)
+ {
+ global $_phpDocumentor_setting;
+ // can only have 1 package-level docblock, others are ignored
+ if (!$this->data->isClean())
+ {
+ return;
+ }
+ $this->data->clean = false;
+ $this->data->explicitDocBlock();
+ $data->canSource();
+ if ($_phpDocumentor_setting['sourcecode'])
+ {
+ $data->addFileSource($this->data->parent->path, $this->data->parent->source);
+ }
+ if (!$data->getExplicitPackage())
+ {
+ list($data->package,$data->subpackage) = $this->_guessPackage($this->data->parent->getPath(), $this->data->parent->getSourceLocation('dummy'));
+ addWarning(PDERROR_NO_PACKAGE_TAG,'file',$this->data->parent->getPath(),$this->last->package);
+ }
+ if (isset($this->packagecategories[$this->package])
+ && $this->packagecategories[$this->package] != $this->category)
+ addWarning(PDERROR_PACKAGECAT_SET,$this->package,
+ $this->packagecategories[$this->package],
+ $data->category);
+ $this->packagecategories[$this->package] = $data->category;
+ $this->category = $this->data->parent->category = $data->category;
+ $this->packagecategories[$this->package] = $this->category;
+ $this->subpackage = $this->data->parent->subpackage = $data->subpackage;
+ if ($data->getKeyword('ignore'))
+ {
+ $this->proceduralpages->ignorePage($this->data->parent);
+ $this->private_page = true;
+ unset($this->last);
+ $this->privatepages[$this->data->parent->getPath()] = $this->data;
+ unset($this->pages[$this->data->parent->getPath()]);
+ return;
+ }
+ $this->data->setDocBlock($data);
+ $this->package = $this->data->parent->package = $data->package;
+ $this->subpackage = $this->data->parent->subpackage = $data->subpackage;
+ $this->proceduralpages->addPagePackage($this->data->parent->getPath(),$this->package,$this->subpackage);
+ if ($access = $data->getKeyword('access'))
+ {
+ if (is_object($access) && ($access->getString() == 'private') && (!$this->parsePrivate))
+ {
+ addWarning(PDERROR_PARSEPRIVATE, $this->data->parent->getPath());
+ $this->proceduralpages->ignorePage($this->data->parent);
+ $this->private_page = true;
+ unset($this->last);
+ $this->privatepages[$this->data->parent->getPath()] = $this->data;
+ unset($this->pages[$this->data->parent->getPath()]);
+ return;
+ }
+ }
+ if ($data->getKeyword('name'))
+ {
+ $a = $data->getKeyword('name');
+ if (is_object($a)) $a = $a->value;
+ $this->data->parent->setFile($a);
+ $this->proceduralpages->setName($a);
+ }
+ $this->addPage($this->data->parent, $this->data->parent->getPath());
+ if ($this->package)
+ {
+ $this->parsePackagePage($this->package, $this->data->parent->getPath());
+ }
+ }
+
+ /**
+ * Backward-compatibility only, use the new tutorials for more power
+ * @tutorial tutorials.pkg
+ * @param string package name of package file to parse
+ * @param string directory of file that contains package name
+ */
+ function parsePackagePage($package, $path)
+ {
+ if (!isset($this->package_pages[$package]))
+ {
+ if (file_exists(dirname($path) . SMART_PATH_DELIMITER . $package . '.html'))
+ {
+ if ($this->quietMode === false)
+ {
+ phpDocumentor_out("Reading package-level file ".$package . '.html');
+ flush();
+ }
+ $fp = fopen(dirname($path) . SMART_PATH_DELIMITER . $package . '.html',"r");
+ $ret = fread($fp,filesize(dirname($path) . SMART_PATH_DELIMITER . $package . '.html'));
+ fclose($fp);
+ unset($fp);
+ if ($this->quietMode === false)
+ {
+ phpDocumentor_out(" -- Parsing File\n");
+ flush();
+ }
+ $pageParser = new ppageParser;
+ $tempp = $this->package;
+ $lp = $this->last;
+ $pageParser->subscribe('*',$this);
+ $pageParser->parse($ret,false,$package);
+ $this->package = $tempp;
+ $this->last = $lp;
+ unset($tempp);
+ unset($pageParser);
+ }
+ }
+ }
+
+ /**
+ * called via {@link Parser::parse()} and Parser's inherited method
+ * {@link Publisher::publishEvent()}
+ *
+ * $event is one of the PHPDOC constants from Parser.inc. If it is not
+ * PHPDOCUMENTOR_EVENT_NEWSTATE, then a function name is retrieved from the
+ * {@link $event_handlers} array and called to handle the $data
+ * @param integer $event event number from {@link Parser.inc}
+ * @param mixed $data if $event is {@link PHPDOCUMENTOR_EVENT_NEWSTATE}, $data is a {@link PHP_DOC_EVENT_END_PAGE} or {@link STATE_END_CLASS},
+ * otherwise $data is either a {@link parserDocBlock}, {@link parserPage} or descendant of {@link parserElement}
+ * @global array we use 'sourcecode' to determine whether to highlight the source
+ * of the current file if it has no file-level docblock
+ */
+ function HandleEvent($event,$data)
+ {
+ global $_phpDocumentor_setting;
+ global $phpDocumentor_DefaultPackageName, $phpDocumentor_DefaultCategoryName;
+ if (empty($this->packagecategories))
+ $this->packagecategories[$phpDocumentor_DefaultPackageName] = $phpDocumentor_DefaultCategoryName;
+ if ($event == PHPDOCUMENTOR_EVENT_NEWSTATE)
+ {
+ if ($data == STATE_END_CLASS)
+ {
+ } elseif ($data == PHPDOCUMENTOR_EVENT_END_PAGE)
+ {
+ if (!$this->private_page)
+ {
+ $this->all_packages[$this->package] = 1;
+ if (!$this->data->hasExplicitDocBlock())
+ {
+ $doc = $this->data->docblock;
+ if (!$this->data->docblock)
+ {
+ $doc = new parserDocBlock;
+ }
+ if ($_phpDocumentor_setting['sourcecode'])
+ {
+ $doc->canSource();
+ $doc->addFileSource($this->data->parent->path, $this->data->parent->source);
+ }
+ list($doc->package,$doc->subpackage) = $this->_guessPackage($this->data->parent->getPath(), $this->data->parent->getSourceLocation('dummy'));
+ addWarning(PDERROR_NO_PAGE_LEVELDOCBLOCK,$this->data->parent->getPath());
+ $this->data->setDocBlock($doc);
+ $this->proceduralpages->addPage($this->data->parent,$doc->package,$doc->subpackage);
+ }
+ $this->pages[$this->data->parent->getPath()] = $this->data;
+ }
+ $this->private_page = false;
+ $this->private_class = false;
+ if (isset($this->db_template))
+ {
+ addWarning(PDERROR_DB_TEMPLATE_UNTERMINATED);
+ }
+ unset($this->db_template);
+ unset($this->last);
+ } elseif ($data == PHPDOCUMENTOR_EVENT_END_DOCBLOCK_TEMPLATE)
+ {
+ unset($this->db_template);
+ }
+ //echo $this->state_lookup[$data] . "\n";
+ //echo $data."\n";
+ }
+ else
+ {
+ if ($event == PHPDOCUMENTOR_EVENT_README_INSTALL_CHANGELOG)
+ {
+ $this->ric[$data[0]] = $data[1];
+ return;
+ }
+ if ($event == PHPDOCUMENTOR_EVENT_DOCBLOCK_TEMPLATE)
+ {
+ $data->postProcess();
+ $this->db_template = $data;
+ $this->_lastDocBlockWasPageLevel = false;
+ // 2nd docblock in a row, and it's at the top of the file, page-level docblock
+ if ($this->type == "docblock" && $this->data->isClean())
+ {
+ // can only have 1 package-level docblock, others are ignored
+ $this->data->clean = false;
+ if ($this->last->getKeyword('ignore'))
+ {
+ $this->proceduralpages->ignorePage($this->data->parent);
+ $this->private_page = true;
+ unset($this->last);
+ $this->privatepages[$this->data->parent->getPath()] = $this->data;
+ unset($this->pages[$this->data->parent->getPath()]);
+ return;
+ }
+ $this->data->setDocBlock($this->last);
+ $this->package = $this->data->parent->package = $this->last->package;
+ $this->subpackage = $this->data->parent->subpackage = $this->last->subpackage;
+ $this->proceduralpages->addPagePackage($this->data->parent->getPath(),$this->package,$this->subpackage);
+ if ($access = $this->last->getKeyword('access'))
+ {
+ if (is_object($access) && ($access->getString() == 'private') && (!$this->parsePrivate))
+ {
+ addWarning(PDERROR_PARSEPRIVATE, $this->data->parent->getPath());
+ $this->proceduralpages->ignorePage($this->data->parent);
+ $this->private_page = true;
+ unset($this->last);
+ $this->privatepages[$this->data->parent->getPath()] = $this->data;
+ unset($this->pages[$this->data->parent->getPath()]);
+ return;
+ }
+ }
+ if ($this->last->getKeyword('name'))
+ {
+ $a = $this->last->getKeyword('name');
+ if (is_object($a)) $a = $a->value;
+ $this->data->parent->setFile($a);
+ $this->proceduralpages->setName($a);
+ }
+ $this->addPage($this->data->parent, $this->data->parent->getPath());
+ if ($this->package)
+ {
+ $this->parsePackagePage($this->package, $this->data->parent->getPath());
+ }
+ }
+ unset($this->last);
+ } else
+ {
+ $this->lasttype = $this->type;
+ $type = $data->getType();
+// fancy_debug($type,$data);
+ if (($type != 'page') && ($type != 'docblock') && ($type != 'packagepage') && ($type != 'tutorial'))
+ {
+ $data->setFile($this->data->parent->getFile());
+ }
+ $this->type = $type;
+ //echo $type . "\n";
+
+ if (isset($this->event_handlers[$type]))
+ {
+ $handle = $this->event_handlers[$type];
+ $this->$handle($event,$data);
+ }
+ }
+ }
+ }
+
+ /**
+ * Replaces the {@link parserPage} represented by $this->pages[$path] with
+ * $page
+ *
+ * Called by {@link addPageIfNecessary(), handleDocBlock()} and
+ * {@link ProceduralPages::setupPages()}, this method first checks to see if
+ * the page has been added. If not, it assumes that the page has either
+ * been @ignored or set with @access private with --parseprivate off, and
+ * returns {@link addPrivatePage()}. Otherwise, it sets the pages[$path] to
+ * be the parserPage $page and sets the package and subpackage to that of
+ * $page
+ * @see $pages
+ * @param parserPage
+ * @param string full path to the file
+ */
+ function addPage($page, $path)
+ {
+ if (!isset($this->pages[$path])) return $this->addPrivatePage($page, $path);
+ $this->pages[$path]->setParent($page);
+ if ($page->package != $GLOBALS['phpDocumentor_DefaultPackageName'])
+ {
+ if (!$this->pages[$path]->docblock)
+ {
+ $docblock = new parserDocBlock;
+ $docblock->package = $page->package;
+ $docblock->subpackage = $page->subpackage;
+ $this->pages[$path]->docblock = $docblock;
+ } else
+ {
+ $this->pages[$path]->docblock->package = $page->package;
+ $this->pages[$path]->docblock->subpackage = $page->subpackage;
+ }
+ }
+ }
+
+ /**
+ * add a new {@link parserPage} to the $pages array if none is found
+ *
+ * This method is used when a page has been @ignored or marked with @access
+ * private, and a public class is in the page (a class with no @access
+ * private in its DocBlock). The method first creates a new page in the
+ * {@link $pages} array and then copies path information, and calls
+ * {@link addPage()} to set up packages
+ * @param string full path of page
+ */
+ function addPageIfNecessary($path, &$class)
+ {
+ global $_phpDocumentor_setting;
+ if (!$this->parsePrivate)
+ {
+ if (!isset($this->pages[$path]))
+ {
+ $this->pages[$path] = new parserData;
+ $this->pages[$path]->docblock = new parserDocBlock;
+ $this->pages[$path]->docblock->package = $this->privatepages[$path]->docblock->package;
+ $this->pages[$path]->docblock->subpackage = $this->privatepages[$path]->docblock->subpackage;
+ $par = $this->privatepages[$path]->parent;
+ $this->pages[$path]->setParent($par);
+ $this->proceduralpages->addPage($par);
+ }
+ }
+ if (isset($_phpDocumentor_setting['packageoutput']))
+ $packages = explode(',',$_phpDocumentor_setting['packageoutput']);
+ if (isset($_phpDocumentor_setting['packageoutput']) &&
+ $this->pages[$path]->parent->package != $class->docblock->package &&
+ !in_array($this->pages[$path]->parent->package,$packages))
+ {
+ $this->pages[$path]->parent->package = $class->docblock->package;
+ $this->addPage($this->pages[$path]->parent, $path);
+ $this->proceduralpages->addPage($this->pages[$path]->parent);
+ }
+ }
+
+ /**
+ * Adds a {@link parserPage} element to the {@link parserData} element in
+ * $this->privatepages[$path]
+ *
+ * Performs a similar function to addPage, but adds to the
+ * {@link $privatePages} array
+ * @param parserPage $page
+ * @param string $path full path to the page
+ * @see addPage()
+ */
+ function addPrivatePage($page, $path)
+ {
+ $this->privatepages[$path]->setParent($page);
+ if ($page->package != $GLOBALS['phpDocumentor_DefaultPackageName'])
+ {
+ if (!$this->privatepages[$path]->docblock)
+ {
+ $docblock = new parserDocBlock;
+ $docblock->package = $page->package;
+ $docblock->subpackage = $page->subpackage;
+ $this->privatepages[$path]->docblock = $docblock;
+ } else
+ {
+ $this->privatepages[$path]->docblock->package = $page->package;
+ $this->privatepages[$path]->docblock->subpackage = $page->subpackage;
+ }
+ }
+ }
+
+ /**
+ * adds a processed descendant of {@link parserElement} to the {@link $pages}
+ * array or {@link $privatepages} array
+ *
+ * This function expects the page to exist in either $pages or $privatepages. It calls the
+ * {@link parserData::addElement()} method to add $element to the page.
+ * @param parserElement $element this will actually be a descendant of parserElement
+ * @param string $path
+ */
+ function addElementToPage($element, $path)
+ {
+ if (isset($this->privatepages[$path]))
+ {
+ if (isset($this->pages[$path]))
+ {
+ if ($element->type == 'class' || $element->type == 'method'
+ || $element->type == 'var' || $element->type == 'const')
+ {
+ $this->pages[$path]->addElement($element);
+ } else
+ $this->privatepages[$path]->addElement($element);
+ } else
+ $this->privatepages[$path]->addElement($element);
+ } else
+ {
+ if (isset($this->pages[$path]))
+ {
+ $this->pages[$path]->addElement($element);
+ }
+ }
+ }
+
+ /**
+ * Add all the @uses tags from $element to the $uses array so that @usedby
+ * virtual tags can be added
+ * @uses parserUsesTag::getSeeElement() used to initialize {@link $uses}
+ * @uses parserUsesTag::getDescription() used to initialize {@link $uses}
+ * @param parserElement descendant of parserElement
+ * @param string full path to the file
+ */
+ function addUses($element, $path)
+ {
+ if ($element->type == 'page')
+ {
+ $element = $this->pages[$element->path];
+ }
+ if (!$this->parsePrivate && $element->docblock->hasaccess)
+ {
+ $a = $element->docblock->getKeyword('access');
+ if (is_object($a) && $a->getString() == 'private') return;
+ }
+ if (isset($this->privatepages[$path]))
+ {
+ if (isset($this->pages[$path]))
+ {
+// if ($element->type == 'function' || $element->type == 'method')
+ {
+ $uses = $element->docblock->getKeyword('uses');
+ if ($uses)
+ {
+ if (!is_array($uses)) $uses = array($uses);
+ foreach($uses as $use)
+ {
+ if (!is_object($use)) continue;
+ $el = $use->getSeeElement();
+ $description = $use->getDescription();
+ $this->uses[$el][] = array($element, $description);
+ }
+ }
+ }
+ }
+ } else
+ {
+ if (isset($this->pages[$path]))
+ {
+// if ($element->type == 'function' || $element->type == 'method')
+ {
+ $uses = $element->docblock->getKeyword('uses');
+ if ($uses)
+ {
+ if (!is_array($uses)) $uses = array($uses);
+ foreach($uses as $use)
+ {
+ if (!is_object($use)) continue;
+ $el = $use->getSeeElement();
+ $description = $use->getDescription();
+ $this->uses[$el][] = array($element, $description);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Add a {@link parserUsedByTag} link to every element referred to by @uses
+ * @param Converter temporary converter used to retrieve abstract links
+ * @uses phpDocumentor_IntermediateParser::addUses() indirectly, as
+ * addUses() sets up $uses, which is iterated over here
+ * @uses $pages sets up all @usedby tags from here
+ * @access private
+ */
+ function _setupUsesList(&$converter)
+ {
+ ob_start();
+ $converter->_createPkgElements($this->pages);
+ ob_end_clean();
+ foreach($this->uses as $link => $elements)
+ {
+ foreach($elements as $element)
+ {
+ if ($element[0]->type == 'method' || $element[0]->type == 'var' ||
+ $element[0]->type == 'const')
+ {
+ $converter->class = $element[0]->getClass();
+ }
+ if ($element[0]->type == 'class')
+ {
+ $converter->class = $element[0]->getName();
+ }
+ $reallink = $converter->getLink($link,$element[0]->docblock->package);
+ if (is_object($reallink))
+ {
+ // add a used by tag to the docblock of the destination
+ switch(phpDocumentor_get_class($reallink))
+ {
+ case 'pagelink' :
+ case 'functionlink' :
+ case 'definelink' :
+ case 'globallink' :
+ if (isset($this->pages[$reallink->path]))
+ {
+ for ($i=0;$i<count($this->pages[$reallink->path]->elements);$i++)
+ {
+ if ($this->pages[$reallink->path]->elements[$i]->type == str_replace('link','',phpDocumentor_get_class($reallink)) && $this->pages[$reallink->path]->elements[$i]->getName() == $reallink->name)
+ {
+ $this->pages[$reallink->path]->elements[$i]->docblock->addUsedBy($element[0]->getLink($converter,false,true), $element[1]);
+// debug('added @usedby to '.str_replace('link','',phpDocumentor_get_class($reallink)).' '.$reallink->name);
+ }
+ }
+ }
+ break;
+ case 'classlink' :
+ case 'methodlink' :
+ case 'varlink' :
+ case 'constlink' :
+ if (isset($this->pages[$reallink->path]))
+ {
+ for ($i=0;$i<count($this->pages[$reallink->path]->classelements);$i++)
+ {
+ if ($this->pages[$reallink->path]->classelements[$i]->type == str_replace('link','',phpDocumentor_get_class($reallink)) && $this->pages[$reallink->path]->classelements[$i]->getName() == $reallink->name)
+ {
+ $this->pages[$reallink->path]->classelements[$i]->docblock->addUsedBy($element[0]->getLink($converter,false,true), $element[1]);
+// debug('added @usedby to '.str_replace('link','',phpDocumentor_get_class($reallink)).' '.$reallink->name);
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Interface to the Converter
+ *
+ * This function simply passes {@link $pages} and {@link package_pages} to
+ * the walk() method, and then calls the Output() method. Note that
+ * Output() is not required to do anything, and in fact doesn't in
+ * HTMLframesConverter.
+ * @uses Converter::walk() passes {@link $pages} and {@link $package_pages}
+ * @uses Converter::Output()
+ */
+ function Convert($title, $converter)
+ {
+ $converter->walk($this->pages, $this->package_pages);
+ $converter->Output($title);
+ }
+
+ /**
+ * Clean up classes
+ *
+ * {@source}
+ * @access private
+ * @uses Classes::Inherit() passes $this
+ */
+ function fixClasses()
+ {
+ $this->classes->Inherit($this);
+ }
+
+ /**
+ * Clean up Procedural Pages
+ * {@source}
+ * @access private
+ * @uses ProceduralPages::setupPages() passes $this
+ */
+ function fixProcPages()
+ {
+ $this->proceduralpages->setupPages($this);
+ }
+
+ /**
+ * If the parent class of $class is in a different package, adds it to the
+ * {@link $package_parents} array
+ * @param parserClass &$class
+ */
+ function addPackageParent(&$class)
+ {
+ if (!is_array($class->parent)) return;
+ $par = $this->classes->getClass($class->parent[1], $class->parent[0]);
+ if ($class->docblock->package == $par->docblock->package) return;
+ $this->package_parents[$class->docblock->package] = $par->docblock->package;
+ if (!isset($this->package_parents[$par->docblock->package]) || !$this->package_parents[$par->docblock->package]) $this->package_parents[$par->docblock->package] = false;
+ }
+
+ /**
+ * Add a converter name to use to the list of converters
+ *
+ * Sets up the {@link $converters} array.
+ * {@internal
+ * First, the Converter's file is included, and then, if successful,
+ * the converter classname is tested for existance. If all is good,
+ * then the templates are added to the list of converters/templates to use}}
+ * @param string $output output format (HTML, PDF, XML). Must be all caps
+ * @param string $name Converter name (frames, for example, is the name of
+ * HTMLframesConverter)
+ * @param string $template template to use, should be a relative path to the
+ * templates dir (like DOM/default)
+ */
+ function addConverter($output,$name,$template)
+ {
+ if (strpos($name,PATH_DELIMITER))
+ {
+ $parent = explode(PATH_DELIMITER,$name);
+ $parent = $parent[0];
+ if ('@VER@' != '@'.'VER@') {
+ $filename = 'PhpDocumentor/phpDocumentor/Converters' .
+ PATH_DELIMITER . $output . PATH_DELIMITER . $parent . PATH_DELIMITER . $output . $parent . "Converter" . ".inc";
+ if (Io::isIncludeable($filename))
+ {
+ include_once($filename);
+ }
+ } else {
+ $filename = str_replace('\\','/',$GLOBALS['_phpDocumentor_install_dir']) . '/phpDocumentor/Converters' .
+ PATH_DELIMITER . $output . PATH_DELIMITER . $parent . PATH_DELIMITER . $output . $parent . "Converter" . ".inc";
+ if (file_exists($filename) && is_readable($filename))
+ {
+ include_once($filename);
+ }
+ }
+ if (!class_exists($output . $parent . 'Converter'))
+ {
+ addError(PDERROR_CONVERTER_NOT_FOUND,"parent Converter ".$output . $parent . "Converter of child Converter ".$output . str_replace(PATH_DELIMITER,'',$name) . "Converter");
+ }
+ }
+ $filename = str_replace('\\', '/', $GLOBALS['_phpDocumentor_install_dir']) . '/phpDocumentor/Converters' .
+ PATH_DELIMITER . $output . PATH_DELIMITER . $name . PATH_DELIMITER . $output .
+ str_replace(PATH_DELIMITER, '', $name) . "Converter" . ".inc";
+ if (file_exists($filename) && is_readable($filename))
+ {
+ include_once($filename);
+ }
+ if (class_exists($output . str_replace(PATH_DELIMITER,'',$name) . 'Converter'))
+ {
+ $this->converters[$output][$output . str_replace(PATH_DELIMITER,'',$name) . "Converter"][] = $template;
+ } else
+ {
+ addError(PDERROR_CONVERTER_NOT_FOUND,$output . str_replace(PATH_DELIMITER,'',$name) . "Converter");
+ }
+ }
+
+ /**
+ * does a natural case sort on two {@link parserElement} descendants
+ *
+ * @param mixed $a
+ * @param mixed $b
+ * @return int
+ * @see generateElementIndex()
+ */
+ function elementCmp ($a, $b)
+ {
+ return strnatcasecmp($a->getName(), $b->getName());
+ }
+
+ /**
+ * does a natural case sort on two class elements (either
+ * {@link parserClass, parserMethod} or {@link parserVar}
+ *
+ * @param mixed $a
+ * @param mixed $b
+ * @return int
+ * @see generateElementIndex()
+ */
+ function ClasselementCmp ($a, $b)
+ {
+ if (phpDocumentor_get_class($a) == 'parserclass') $atest = $a->name; else $atest = $a->class;
+ if (phpDocumentor_get_class($b) == 'parserclass') $btest = $b->name; else $btest = $b->class;
+
+ if(($c = strnatcasecmp($atest, $btest)) != 0) return $c;
+ if (phpDocumentor_get_class($a) != 'parserclass') $atest .= $a->name;
+ if (phpDocumentor_get_class($b) != 'parserclass') $btest .= $b->name;
+ if (phpDocumentor_get_class($a) == 'parsermethod' && phpDocumentor_get_class($b) == 'parsermethod')
+ {
+ if ($a->isConstructor) return -1;
+ if ($b->isConstructor) return 1;
+ if ($a->isDestructor) return -1;
+ if ($b->isDestructor) return 1;
+ }
+ return strnatcasecmp($atest,$btest);
+ }
+
+ /**
+ * call this method once parsing has completed.
+ *
+ * This method calls the private methods fixClasses and fixProcPages, both
+ * of which adjust inheritance and package information based on complicated
+ * post-parsing rules described in {@link ProceduralPages::setupPages()}
+ * and {@link Classes::Inherit()}. Then, it sorts elements of the $pages
+ * array and calls Convert for each Converter in the $converters array
+ * @see $converters
+ * @see $pages
+ * @see Convert()
+ */
+ function Output ($title = "Generated Documentation")
+ {
+ $GLOBALS['phpDocumentor_errors']->curfile = false;
+ $this->fixClasses();
+ $this->fixProcPages();
+// var_dump($this->uses);
+// exit;
+ phpDocumentor_out("\nSorting page elements...");
+ flush();
+ uasort($this->pages,'pagesort');
+ foreach($this->pages as $i => $page)
+ {
+ usort($this->pages[$i]->elements,array($this,'elementCmp'));
+ usort($this->pages[$i]->classelements,array($this,'ClasselementCmp'));
+ }
+ phpDocumentor_out("done\n");
+ flush();
+ $complicatedout = false;
+ if (is_array($this->converters))
+ {
+ if (count($this->converters) > 1)
+ {
+ $complicatedout = true;
+ }
+ phpDocumentor_out("Formatting @uses list...");
+ flush();
+ $a = new __dummyConverter($this->all_packages, $this->package_parents, $this->classes, $this->proceduralpages, $this->packageoutput, $this->parsePrivate, $this->quietMode, $this->targetDir , '', $this->title);
+ $this->_setupUsesList($a);
+ unset($a);
+ phpDocumentor_out("done\n\n");
+ flush();
+ foreach($this->converters as $converter => $blah)
+ {
+ if (is_array($blah))
+ {
+ if (count($blah) > 1)
+ {
+ $complicatedout = true;
+ }
+ foreach($blah as $converter => $templates)
+ {
+ foreach($templates as $template)
+ {
+ $extraout = '';
+ if ($complicatedout)
+ {
+ $extraout = SMART_PATH_DELIMITER . $converter;
+ }
+ if (count($templates) > 1)
+ {
+ $extraout .= SMART_PATH_DELIMITER . str_replace(PATH_DELIMITER, SMART_PATH_DELIMITER, substr($template,0,strlen($template) - 1));
+ }
+ $a = new $converter($this->all_packages, $this->package_parents, $this->classes, $this->proceduralpages, $this->packageoutput, $this->parsePrivate, $this->quietMode, $this->targetDir . $extraout, $template, $this->title);
+ if (isset($this->templateBase))
+ {
+ $a->setTemplateBase($this->templateBase, $template);
+ }
+ $a->ric = $this->ric;
+ $a->packagecategories = $this->packagecategories;
+ if (isset($this->tutorials)) $a->setTutorials($this->tutorials);
+ $this->Convert($title, $a);
+ unset($a);
+ }
+ }
+ }
+ }
+ } else
+ {
+ addErrorDie(PDERROR_NO_CONVERTERS);
+ }
+ }
+
+ /**
+ * Sets the output directory
+ *
+ * @param string $dir the output directory
+ */
+ function setTargetDir($dir)
+ {
+ $this->targetDir = $dir;
+ }
+
+ /**
+ * Sets the template base directory
+ *
+ * @param string $dir the template base directory
+ * @tutorial phpDocumentor.howto.pkg#using.command-line.templatebase
+ */
+ function setTemplateBase($dir)
+ {
+ $this->templateBase = $dir;
+ }
+
+ /**
+ * set parsing information output mode (quiet or verbose)
+ *
+ * If set to false, no parsing information (parsing /php/file/thisfile.php,
+ * Converting etc.) will be displayed.
+ * Useful for cron jobs
+ * @param bool $quietMode
+ */
+ function setQuietMode($quietMode)
+ {
+ $this->quietMode = $quietMode;
+ }
+
+ /**
+ * set display of elements marked with @access private
+ *
+ * If set to true, elements will be displayed
+ * @param bool $parse
+ */
+ function setParsePrivate($parse)
+ {
+ $this->parsePrivate = $parse;
+ }
+}
+
+/** @access private */
+function pagesort($a, $b)
+{
+ return strnatcasecmp($a->parent->file,$b->parent->file);
+}
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Io.inc b/buildscripts/PhpDocumentor/phpDocumentor/Io.inc
new file mode 100644
index 00000000..0425096d
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Io.inc
@@ -0,0 +1,868 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * Class to handle file and user io opperations
+ *
+ * @author Joshua Eichorn <jeichorn@phpdoc.org>
+ * @version $Id: Io.inc,v 1.5 2005/11/20 21:20:22 cellog Exp $
+ * @package phpDocumentor
+ */
+/**
+ * Class to handle file and user io opperations
+ *
+ * @author Joshua Eichorn <jeichorn@phpdoc.org>
+ * @version $Id: Io.inc,v 1.5 2005/11/20 21:20:22 cellog Exp $
+ * @package phpDocumentor
+ */
+class Io
+{
+
+ /**
+ * Holds all the options that are avaible to the cmd line interface
+ * and to the different web interfaces
+ */
+ var $phpDocOptions;
+ /**
+ * Format: array(array(regexp-ready string to search for whole path,
+ * regexp-ready string to search for basename of ignore strings),...)
+ * @var false|array
+ */
+ var $ignore = false;
+
+ /**
+ * creates an array $this->phpDocOptions and sets program options in it.
+ * Array is in the format of:
+ * <pre>
+ * [filename][tag][] = "f";
+ * [filename][tag][] = "-file";
+ * [filename][desc] "name of file to parse"
+ * </pre>
+ */
+ function Io()
+ {
+ $this->phpDocOptions['filename']['tag'] = array( "-f", "--filename");
+ $this->phpDocOptions['filename']['desc'] = "name of file(s) to parse ',' file1,file2. Can contain complete path and * ? wildcards";
+ $this->phpDocOptions['filename']['type'] = "path";
+
+ $this->phpDocOptions['directory']['tag'] = array( "-d", "--directory");
+ $this->phpDocOptions['directory']['desc'] = "name of a directory(s) to parse directory1,directory2";
+ $this->phpDocOptions['directory']['type'] = "path";
+
+ $this->phpDocOptions['examplesdir']['tag'] = array( "-ed", "--examplesdir");
+ $this->phpDocOptions['examplesdir']['desc'] = "full path of the directory to look for example files from @example tags";
+ $this->phpDocOptions['examplesdir']['type'] = "path";
+
+ $this->phpDocOptions['templatebase']['tag'] = array( "-tb", "--templatebase");
+ $this->phpDocOptions['templatebase']['desc'] = "base location of all templates for this parse.";
+ $this->phpDocOptions['templatebase']['type'] = "path";
+
+ $this->phpDocOptions['target']['tag'] = array("-t", "--target");
+ $this->phpDocOptions['target']['desc'] = "path where to save the generated files";
+ $this->phpDocOptions['target']['type'] = "path";
+
+ $this->phpDocOptions['ignore']['tag'] = array("-i", "--ignore");
+ $this->phpDocOptions['ignore']['desc'] = "file(s) that will be ignored, multiple separated by ','. Wildcards * and ? are ok";
+ $this->phpDocOptions['ignore']['type'] = "path";
+
+ $this->phpDocOptions['ignoretags']['tag'] = array("-it", "--ignore-tags");
+ $this->phpDocOptions['ignoretags']['desc'] = "tags to ignore for this parse. @package, @subpackage, @access and @ignore may not be ignored.";
+ $this->phpDocOptions['ignoretags']['type'] = "value";
+
+ $this->phpDocOptions['hidden']['tag'] = array("-dh", "--hidden");
+ $this->phpDocOptions['hidden']['desc'] = "set equal to on (-dh on) to descend into hidden directories (directories starting with '.'), default is off";
+ $this->phpDocOptions['hidden']['type'] = "value";
+
+ $this->phpDocOptions['quiet']['tag'] = array("-q", "--quiet");
+ $this->phpDocOptions['quiet']['desc'] = "do not display parsing/conversion messages. Useful for cron jobs on/off default off";
+ $this->phpDocOptions['quiet']['type'] = "value";
+
+ $this->phpDocOptions['title']['tag'] = array("-ti","--title");
+ $this->phpDocOptions['title']['desc'] = "title of generated documentation, default is 'Generated Documentation'";
+ $this->phpDocOptions['title']['type'] = "value";
+
+ $this->phpDocOptions['help']['tag'] = array("-h", "--help");
+ $this->phpDocOptions['help']['desc'] = " show this help message";
+
+ $this->phpDocOptions['useconfig']['tag'] = array("-c","--useconfig");
+ $this->phpDocOptions['useconfig']['desc'] = "Use a Config file in the users/ subdirectory for all command-line options";
+ $this->phpDocOptions['useconfig']['type'] = "value";
+
+ $this->phpDocOptions['parseprivate']['tag'] = array("-pp","--parseprivate");
+ $this->phpDocOptions['parseprivate']['desc'] = "parse @internal and elements marked private with @access. Use on/off, default off";
+ $this->phpDocOptions['parseprivate']['type'] = "value";
+
+ $this->phpDocOptions['packageoutput']['tag'] = array("-po","--packageoutput");
+ $this->phpDocOptions['packageoutput']['desc'] = "output documentation only for selected packages. Use a comma-delimited list";
+ $this->phpDocOptions['packageoutput']['type'] = "value";
+
+ $this->phpDocOptions['defaultpackagename']['tag'] = array("-dn","--defaultpackagename");
+ $this->phpDocOptions['defaultpackagename']['desc'] = "name to use for the default package. If not specified, uses 'default'";
+ $this->phpDocOptions['defaultpackagename']['type'] = "value";
+
+ $this->phpDocOptions['defaultcategoryname']['tag'] = array("-dc","--defaultcategoryname");
+ $this->phpDocOptions['defaultcategoryname']['desc'] = "name to use for the default category. If not specified, uses 'default'";
+ $this->phpDocOptions['defaultcategoryname']['type'] = "value";
+
+ $this->phpDocOptions['output']['tag'] = array("-o","--output");
+ $this->phpDocOptions['output']['desc'] = "output information to use separated by ','. Format: output:converter:templatedir like \"HTML:frames:phpedit\"";
+ $this->phpDocOptions['output']['type'] = "value";
+
+ $this->phpDocOptions['converterparams']['tag'] = array("-cp","--converterparams");
+ $this->phpDocOptions['converterparams']['desc'] = "dynamic parameters for a converter, separate values with commas";
+ $this->phpDocOptions['converterparams']['type'] = "value";
+
+ $this->phpDocOptions['customtags']['tag'] = array("-ct","--customtags");
+ $this->phpDocOptions['customtags']['desc'] = "custom tags, will be recognized and put in tags[] instead of unknowntags[]";
+ $this->phpDocOptions['customtags']['type'] = "value";
+
+ $this->phpDocOptions['sourcecode']['tag'] = array("-s","--sourcecode");
+ $this->phpDocOptions['sourcecode']['desc'] = "generate highlighted sourcecode for every parsed file (PHP 4.3.0+ only) on/off default off";
+ $this->phpDocOptions['sourcecode']['type'] = "value";
+
+ $this->phpDocOptions['javadocdesc']['tag'] = array("-j","--javadocdesc");
+ $this->phpDocOptions['javadocdesc']['desc'] = "JavaDoc-compliant description parsing. Use on/off, default off (more flexibility)";
+ $this->phpDocOptions['javadocdesc']['type'] = "value";
+
+ $this->phpDocOptions['pear']['tag'] = array("-p","--pear");
+ $this->phpDocOptions['pear']['desc'] = "Parse a PEAR-style repository (package is directory, _members are @access private) on/off default off";
+ $this->phpDocOptions['pear']['type'] = "value";
+
+ $this->phpDocOptions['readmeinstallchangelog']['tag'] = array("-ric","--readmeinstallchangelog");
+ $this->phpDocOptions['readmeinstallchangelog']['desc'] = "Specify custom filenames to parse like README, INSTALL or CHANGELOG files";
+ $this->phpDocOptions['readmeinstallchangelog']['type'] = "value";
+
+ $this->phpDocOptions['general']['message'] ="You can have multiple directories and multiple files, as well as a combination of both options";
+ }
+
+
+ /**
+ * create the help message for display on the command-line
+ * @return string a string containing a help message
+ */
+ function displayHelpMsg()
+ {
+ unset($ret);
+ $ret = "\n";
+ foreach($this->phpDocOptions as $data)
+ {
+ unset($tag);
+ $tag = "";
+ if (isset($data['tag']))
+ {
+ if (is_array($data['tag'])) {
+ foreach($data['tag'] as $param) {
+ $tag .= "$param ";
+ }
+ }
+ $taglen = 34;
+ $outputwidth = 79;
+ $tagspace = str_repeat(" ",$taglen);
+ $tmp = " ".trim($tag).$tagspace;
+ $tmp = substr($tmp,0,$taglen);
+ $d = wordwrap(ltrim($data['desc']),($outputwidth-$taglen));
+ $dt = explode("\n",$d);
+ $dt[0] = $tmp .$dt[0];
+ for($i=1;$i<count($dt);$i++)
+ {
+ $dt[$i] = $tagspace.$dt[$i];
+ }
+ $ret .= implode("\n",$dt)."\n\n";
+
+ }
+ }
+ $ret .= "\n".wordwrap($data['message'],$outputwidth)."\n";
+ return $ret;
+ }
+
+ /**
+ * calls {@link file_exists()} for each value in include_path,
+ * then calls {@link is_readable()} when it finds the file
+ * @param string
+ * @return boolean
+ */
+ function isIncludeable($filename)
+ {
+ $ip = get_include_path();
+ if (PHPDOCUMENTOR_WINDOWS)
+ {
+ $ip = explode(';', $ip);
+ } else {
+ $ip = explode(':', $ip);
+ }
+ foreach($ip as $path)
+ {
+ if ($a = realpath($path . DIRECTORY_SEPARATOR . $filename))
+ {
+ if (is_readable($a))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Parses $_SERVER['argv'] and creates a setup array
+ * @return array a setup array
+ * @global array command-line arguments
+ */
+ function parseArgv()
+ {
+ global $argv;
+ // defaults for setting
+ $setting['hidden'] = "off";
+ $setting['template'] = 'templates' . PATH_DELIMITER .'default' . PATH_DELIMITER;
+
+ $valnext = "junk";
+ if(isset($argv) && is_array($argv))
+ {
+ foreach ($argv as $cmd)
+ {
+ //if($cmd === 'phpdoc' || basename($cmd)==='phpdoc')
+ // continue;
+
+ if ($cmd == '-h' || $cmd == '--help')
+ {
+ echo $this->displayHelpMsg();
+ die();
+ }
+ $setting[$valnext] = $cmd;
+ foreach( $this->phpDocOptions as $name => $data )
+ {
+ if (!empty($data['tag']))
+ {
+ if (in_array($cmd,$data['tag']))
+ {
+ $valnext = $name;
+ break;
+ }
+ else
+ {
+ $valnext = "junk";
+ }
+ }
+ }
+ if ($valnext == 'junk' && (strpos(trim($cmd),'-') === 0))
+ {
+ addErrorDie(PDERROR_UNKNOWN_COMMANDLINE,$cmd);
+ }
+ }
+ } else
+ {
+ echo "Please use php-cli.exe in windows, or set register_argc_argv On";
+ die;
+ }
+ /* $setting will always have at least 2 elements
+ [hidden] => off
+ [template] => templates/default
+ */
+ if (count($setting) < 3) {
+ echo $this->displayhelpMsg();
+ die();
+ }
+ return $setting;
+ }
+
+
+ /**
+ * @return array list of files in a directory
+ * @param string $directory full path to the directory you want the list of
+ * @param off|on whether to list files that begin with . like .bash_history
+ */
+ function dirList($directory,$hidden = "off")
+ {
+ $directory = realpath($directory);
+ $ret = false;
+ if (@is_dir($directory))
+ {
+ $ret = array();
+ $d = @dir($directory); // thanks to Jason E Sweat (jsweat@users.sourceforge.net) for fix
+ while($d && ($entry=$d->read()) !== false) {
+ if (strcmp($entry,".") != 0 && strcmp($entry,"..") != 0) {
+ if ($hidden == "off")
+ {
+ if (substr($entry,0,1) == ".")
+ {
+ $getentry = false;
+ } else {
+ $getentry = true;
+ }
+
+ } else {
+ $getentry = true;
+ }
+
+ if ($getentry == true)
+ {
+ if (is_file($directory . PATH_DELIMITER . $entry)) {
+ $ret[] = $directory . PATH_DELIMITER . $entry;
+ }
+ if (is_dir($directory . PATH_DELIMITER . $entry)) {
+ $tmp = $this->dirList($directory . PATH_DELIMITER . $entry, $hidden);
+ if (is_array($tmp)) {
+ foreach($tmp as $ent) {
+ $ret[] = $ent;
+ }
+ }
+ }
+ }
+ }
+ }
+ if ($d) $d->close();
+ } else {
+ die("directory: '$directory' not found\n");
+ }
+ return $ret;
+ }
+
+ /**
+ * Retrieve common directory (case-insensitive in windows)
+ *
+ * takes the list of files, and returns the subdirectory they share in common,
+ * so in this list:
+ *
+ * <code>
+ * array(
+ * "/dir1/dir2/subdir/dir3/filename.ext",
+ * "/dir1/dir2/subdir/dir4/filename.ext",
+ * "/dir1/dir2/mydir/dir5/filename.ext");
+ * </code>
+ *
+ * getBase will return "/dir1/dir2"
+ * @param array array of strings
+ */
+ function getBase($filelist)
+ {
+ $masterPath = false;
+ foreach($filelist as $path)
+ {
+ if (!$masterPath)
+ {
+ $masterPath = str_replace('\\','/',dirname($path));
+ } else
+ {
+ if (dirname($path) != $masterPath)
+ {
+ $mp = split(PATH_DELIMITER,$masterPath);
+ $np = split(PATH_DELIMITER,str_replace('\\','/',dirname($path)));
+ if (count($np) < count($mp))
+ {
+ $masterPath = join($np, PATH_DELIMITER);
+ } else
+ {
+ $test = false;
+ $found = false;
+ for($i=0;$i < count($mp) && $i < count($np);$i++)
+ {
+ if (PHPDOCUMENTOR_WINDOWS)
+ {
+ if (strtolower($mp[$i]) != strtolower($np[$i])) $found = $i;
+ } else
+ {
+ if ($mp[$i] != $np[$i]) $found = $i;
+ }
+ }
+ if ($found !== false)
+ {
+ $mp = array_slice($mp,0,$found);
+ $masterPath = join($mp,PATH_DELIMITER);
+ }
+ }
+ }
+ }
+ }
+ return $masterPath;
+ }
+
+ /**
+ * Retrieve tutorial subdirectories and their contents from the list of
+ * files to parse
+ * @param array array of paths (strings)
+ * @return array array(filelist - tutorials, tutorials)
+ */
+ function getTutorials($filelist)
+ {
+ $list = $tutorials = array();
+ foreach($filelist as $file)
+ {
+ if (strpos($file,'tutorials/') !== false)
+ {
+ $tutedir = explode('/',substr($file,strpos($file,'tutorials/')));
+ array_shift($tutedir);
+ if (count($tutedir) <= 3)
+ {
+ $res = array();
+ // kludge - will need to fix for 2.0
+ $res['category'] = $GLOBALS['phpDocumentor_DefaultCategoryName'];
+ $res['package'] = array_shift($tutedir);
+ $res['subpackage'] = '';
+ if (count($tutedir) > 1)
+ $res['subpackage'] = array_shift($tutedir);
+ $f = array_shift($tutedir);
+ $res['tutename'] = $f;
+ $f = explode('.',$f);
+ $res['tutetype'] = array_pop($f);
+ if ($res['tutetype'] == 'ini') continue;
+ $res['path'] = $file;
+ if (@file_exists($file . '.ini'))
+ {
+ $res['ini'] = phpDocumentor_parse_ini_file($file . '.ini', true);
+ } else
+ {
+ $res['ini'] = false;
+ }
+ $tutorials[] = $res;
+ }
+ } else $list[] = $file;
+ }
+ return array($list,$tutorials);
+ }
+
+ /**
+ * @param string base directory from {@link getBase()}
+ * @param array file list from {@link dirList()}
+ * @return array array(filelist - README/INSTALL/CHANGELOG,
+ * README/INSTALL/CHANGELOG)
+ */
+ function getReadmeInstallChangelog($base,$filelist)
+ {
+ $list = $ric = array();
+ $names = $GLOBALS['_phpDocumentor_RIC_files'];
+ foreach($filelist as $file)
+ {
+ if ((dirname($file) == $base) && in_array(strtoupper(basename($file)), $names))
+ { // be sure to change $this->checkIgnore() if any other files are added here!!
+ $ric[] = $file;
+ } else
+ {
+ $list[] = $file;
+ }
+ }
+ return array($list,$ric);
+ }
+
+ function getDirTree($dir, $base_dir, $ignore = array(), $hidden="off")
+ {
+ $allfiles = $this->dirList($dir,$hidden);
+ $struc = array();
+ foreach($allfiles as $file)
+ {
+ if ($this->checkIgnore(basename($file),dirname($file),$ignore)) continue;
+ $path = substr(dirname($file),strlen(str_replace('\\','/',realpath($base_dir)))+1);
+ if (!$path) $path = '/';
+ $parts = pathinfo($file);
+ if (!isset($parts['extension']))
+ {
+ $parts['extension'] = '';
+ }
+ $struc[$path][] = array(
+ 'file' => $parts['basename'],
+ 'ext' => $parts['extension'],
+ 'path' => $file);
+ }
+ uksort($struc,'strnatcasecmp');
+ foreach($struc as $key => $ind)
+ {
+ usort($ind,'Ioinc_sortfiles');
+ $struc[$key] = $ind;
+ $save = $key;
+ if ($key != '/')
+ {
+ $key = explode('/',$key);
+ while (count($key))
+ {
+ array_pop($key);
+ if (isset($struc[join('/',$key)]))
+ {
+ $struc[join('/',$key)][substr($save,strlen(join('/',$key)) + 1)] = $ind;
+ unset($struc[$save]);
+ }
+ }
+ }
+ }
+ foreach($struc as $key => $ind)
+ {
+ if ($key != '/')
+ {
+ if (count(explode('/',$key)) == 1)
+ {
+ $struc['/'][$key] = $struc[$key];
+ unset($struc[$key]);
+ }
+ }
+ }
+ $tempstruc = $struc;
+ unset($tempstruc['/']);
+ $leftover_dirs = array_keys($tempstruc);
+ $splitdirs = array();
+ foreach($leftover_dirs as $dir)
+ {
+ $splitdirs[] = explode('/',$dir);
+ }
+ $leftover_dirs = array();
+
+ foreach($splitdirs as $dir)
+ {
+ $save = join($dir,'/');
+ $struc['/'] = setup_dirs($struc['/'], $dir, $tempstruc[$save]);
+ unset($struc[$save]);
+ }
+ @uksort($struc['/'],'Ioinc_mystrucsort');
+ return $struc;
+ }
+
+ /**
+ * Reads a file and returns it as a string
+ * Does basic error checking
+ *
+ * file extensions are set in {@link phpdoc.inc}
+ *
+ * @global array PHP File extensions, used to validate that $path is a PHP File
+ * @global array PHP File extensions in a CVS repository, used to validate that $path is a PHP File
+ * @param string $path
+ */
+ function readPhpFile($path, $quietMode = false)
+ {
+ global $_phpDocumentor_cvsphpfile_exts, $_phpDocumentor_phpfile_exts;
+ // tiberiusblue addition
+ $cvsExt = $_phpDocumentor_cvsphpfile_exts;
+ $ext = $_phpDocumentor_phpfile_exts;
+ if (file_exists($path))
+ {
+ if (is_file($path))
+ {
+ // check extension
+ $tmp = explode(".",$path);
+ // tiberiusblue addition
+ $tmp2 = $tmp;
+ if (in_array(array_pop($tmp),$ext))
+ {
+ phpDocumentor_out(" -- Parsing file\n");
+ flush();
+ $fp = fopen($path,"r");
+ $ret = fread($fp,filesize($path));
+ fclose($fp);
+ return $ret;
+ } elseif (in_array(array_pop($tmp2),$cvsExt))
+ {
+ phpDocumentor_out(" CVS file [EXPERIMENTAL]\n");
+ flush();
+ $fp = fopen($path,"r");
+ $ret = fread($fp,filesize($path));
+ fclose($fp);
+ $ret = strstr($ret,"<?");
+ $ret = substr($ret,0,strpos($ret,"@\n"));
+ $ret = str_replace("@@","@",$ret);
+ return $ret;
+ } else
+ {
+ phpDocumentor_out(" -- File not parsed, not a php file\n");
+ flush();
+ }
+ } else {
+ phpDocumentor_out(" -- Unable to read file, not a file\n");
+ flush();
+ }
+ } else {
+ phpDocumentor_out(" -- Unable to read file, file does not exist\n");
+ flush();
+ }
+ }
+
+ /**
+ * Tell whether to ignore a file or a directory
+ * allows * and ? wildcards
+ *
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @param string $file just the file name of the file or directory,
+ * in the case of directories this is the last dir
+ * @param string $path the full path
+ * @param array $ignore
+ * @return bool true if $path should be ignored, false if it should not
+ */
+ function checkIgnore($file,$path,$ignore,$ignore_no_ext = true)
+ {
+ global $_phpDocumentor_RIC_files;
+ $path = realpath($path);
+ if (!count($ignore)) return false;
+ if ($ignore_no_ext &&
+ !in_array(strtoupper($file), $_phpDocumentor_RIC_files))
+ {
+ if (!is_numeric(strpos($file,'.'))) return true;
+ }
+ if (!isset($this->ignore) || !$this->ignore)
+ {
+ $this->_setupIgnore($ignore);
+ if (!$this->ignore)
+ {
+ return false;
+ }
+ }
+ if (is_array($this->ignore))
+ {
+ foreach($this->ignore as $match)
+ {
+ // match is an array if the ignore parameter was a /path/to/pattern
+ if (is_array($match))
+ {
+ // check to see if the path matches with a path delimiter appended
+ preg_match('/^' . strtoupper($match[0]).'$/', strtoupper($path) . PATH_DELIMITER,$find);
+ if (!count($find))
+ {
+ // check to see if it matches without an appended path delimiter
+ preg_match('/^' . strtoupper($match[0]).'$/', strtoupper($path), $find);
+ }
+ if (count($find))
+ {
+ // check to see if the file matches the file portion of the regex string
+ preg_match('/^' . strtoupper($match[1]).'$/', strtoupper($file), $find);
+ if (count($find))
+ {
+ return true;
+ }
+ }
+ // check to see if the full path matches the regex
+ preg_match('/^' . strtoupper($match[0]).'$/',
+ strtoupper($path . DIRECTORY_SEPARATOR . $file), $find);
+ if (count($find))
+ {
+ return true;
+ }
+ } else
+ {
+ // ignore parameter was just a pattern with no path delimiters
+ // check it against the path
+ preg_match('/^' . strtoupper($match).'$/', strtoupper($path), $find);
+ if (count($find))
+ {
+ return true;
+ }
+ // check it against the file only
+ preg_match('/^' . strtoupper($match).'$/', strtoupper($file), $find);
+ if (count($find))
+ {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Construct the {@link $ignore} array
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @param array strings of files/paths/wildcards to ignore
+ * @access protected
+ */
+ function _setupIgnore($ignore)
+ {
+ $ig = array();
+ if (is_array($ignore))
+ {
+ for($i=0; $i<count($ignore);$i++)
+ {
+ $ignore[$i] = strtr($ignore[$i], "\\", "/");
+ $ignore[$i] = str_replace('//','/',$ignore[$i]);
+
+ if (!empty($ignore[$i]))
+ {
+ if (!is_numeric(strpos($ignore[$i],PATH_DELIMITER)))
+ {
+ $ig[] = $this->getRegExpableSearchString($ignore[$i]);
+ } else
+ {
+ if (basename($ignore[$i]) . PATH_DELIMITER == $ignore[$i])
+ $ig[] = $this->getRegExpableSearchString($ignore[$i]);
+ else
+ $ig[] = array($this->getRegExpableSearchString($ignore[$i]),$this->getRegExpableSearchString(basename($ignore[$i])));
+ }
+ }
+ }
+ if (count($ig)) $this->ignore = $ig;
+ } else $this->ignore = false;
+ }
+
+ /**
+ * Converts $s into a string that can be used with preg_match
+ * @param string $s string with wildcards ? and *
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @return string converts * to .*, ? to ., etc.
+ */
+ function getRegExpableSearchString($s)
+ {
+ $y = '\/';
+ if (DIRECTORY_SEPARATOR == '\\')
+ {
+ $y = '\\\\';
+ }
+ $s = str_replace('/', DIRECTORY_SEPARATOR, $s);
+ $x = strtr($s, array('?' => '.','*' => '.*','.' => '\\.','\\' => '\\\\','/' => '\\/',
+ '[' => '\\[',']' => '\\]','-' => '\\-'));
+ if (strpos($s, DIRECTORY_SEPARATOR) !== false &&
+ strrpos($s, DIRECTORY_SEPARATOR) === strlen($s) - 1)
+ {
+ $x = "(?:.*$y$x?.*|$x.*)";
+ }
+ return $x;
+ }
+
+ /**
+ * Removes files from the $dir array that do not match the search string in
+ * $match
+ * @param array $dir array of filenames (full path)
+ * @param string $match search string with wildcards
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @return string|array listing of every file in a directory that matches
+ * the search string
+ */
+ function removeNonMatches($dir, $match)
+ {
+ $match = $this->getRegExpableSearchString($match);
+ $nodir = false;
+ if (!is_array($dir))
+ {
+ $dir = array($dir);
+ $nodir = true;
+ }
+ foreach($dir as $i => $file)
+ {
+ preg_match('/^'.$match.'$/',basename($file),$find);
+ if (!count($find)) unset($dir[$i]);
+ }
+ if ($nodir) return $dir[0];
+ return $dir;
+ }
+
+ /**
+ * Take a filename with wildcards and return all files that match the
+ * wildcards
+ * @param string $file a full path from the -f command-line parameter, with
+ * potential * and ? wildcards.
+ * @return mixed if $file contains wildcards, returns an array of matching
+ * files, otherwise returns false
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ */
+ function getAllFiles($file)
+ {
+ $path = realpath(dirname($file));
+ $file = basename($file);
+ // any wildcards?
+ if (is_numeric(strpos($file,'?')) || is_numeric(strpos($file,'*')))
+ {
+ $files = $this->dirList($path);
+ $a = $this->removeNonMatches($files,$file);
+ return $a;
+ }
+ return false;
+ }
+}
+
+/**#@+
+ * Sorting functions for the file list
+ * @param string
+ * @param string
+ */
+function Ioinc_sortfiles($a, $b)
+{
+ return strnatcasecmp($a['file'],$b['file']);
+}
+
+function Ioinc_mystrucsort($a, $b)
+{
+ if (is_numeric($a) && is_string($b)) return 1;
+ if (is_numeric($b) && is_string($a)) return -1;
+ if (is_numeric($a) && is_numeric($b))
+ {
+ if ($a > $b) return 1;
+ if ($a < $b) return -1;
+ if ($a == $b) return 0;
+ }
+ return strnatcasecmp($a,$b);
+}
+/**#@-*/
+
+/**
+ * Recursively add all the subdirectories of $contents to $dir without erasing anything in
+ * $dir
+ * @param array
+ * @param array
+ * @return array processed $dir
+ */
+function set_dir($dir,$contents)
+{
+ while(list($one,$two) = each($contents))
+ {
+ if (isset($dir[$one]))
+ {
+ $dir[$one] = set_dir($dir[$one],$contents[$one]);
+ } else $dir[$one] = $two;
+ }
+ return $dir;
+}
+
+/**
+ * Recursively move contents of $struc into associative array
+ *
+ * The contents of $struc have many indexes like 'dir/subdir/subdir2'.
+ * This function converts them to
+ * array('dir' => array('subdir' => array('subdir2')))
+ * @param array struc is array('dir' => array of files in dir,'dir/subdir' => array of files in dir/subdir,...)
+ * @param array array form of 'dir/subdir/subdir2' array('dir','subdir','subdir2')
+ * @return array same as struc but with array('dir' => array(file1,file2,'subdir' => array(file1,...)))
+ */
+function setup_dirs($struc,$dir,$contents)
+{
+ if (!count($dir))
+ {
+ foreach($contents as $dir => $files)
+ {
+ if (is_string($dir))
+ {
+ if (strpos($dir,'/'))
+ {
+ $test = true;
+ $a = $contents[$dir];
+ unset($contents[$dir]);
+ $b = explode('/',$dir);
+ $c = array_shift($b);
+ if (isset($contents[$c]))
+ {
+ $contents[$c] = set_dir($contents[$c],setup_dirs(array(),$b,$a));
+ } else $contents[$c] = setup_dirs(array(),$b,$a);
+ }
+ }
+ }
+ return $contents;
+ }
+ $me = array_shift($dir);
+ if (!isset($struc[$me])) $struc[$me] = array();
+ $struc[$me] = setup_dirs($struc[$me],$dir,$contents);
+ return $struc;
+}
+
+if (!function_exists('get_include_path')) {
+function get_include_path()
+{
+ return ini_get('include_path');
+}
+}
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/LinkClasses.inc b/buildscripts/PhpDocumentor/phpDocumentor/LinkClasses.inc
new file mode 100644
index 00000000..d122f0d4
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/LinkClasses.inc
@@ -0,0 +1,206 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * Linking to element documentation is performed by the classes in this file.
+ *
+ * abstractLink descendants contain enough information to differentiate every
+ * documentable element, and so can be converted to a link string by
+ * {@link Converter::returnSee()}
+ * @package phpDocumentor
+ * @subpackage Links
+ */
+
+/**
+ * linking classes parent
+ * @package phpDocumentor
+ * @subpackage Links
+ */
+class abstractLink
+{
+ /**#@+ @var string */
+ var $path;
+ /**
+ * phpdoc alias _phpdoc_inc for phpdoc.inc
+ */
+ var $fileAlias = '';
+ /**
+ * element type linked to.
+ * can only be a documentable element
+ */
+ var $type = '';
+ var $name = '';
+ var $category = '';
+ var $package = '';
+ var $subpackage = '';
+ /**#@-*/
+
+ /**
+ * @param string full path to file containing element
+ * @param string page name, as configured by {@link Parser::parse}
+ * @param string element name
+ * @param string package element is in
+ * @param string subpackage element is in
+ * @param string optional category that documentation is in
+ */
+ function addLink($path, $fileAlias, $name, $package, $subpackage, $category = false)
+ {
+ $this->path = $path;
+ $this->fileAlias = $fileAlias;
+ $this->name = $name;
+ $this->category = $category;
+ $this->package = $package;
+ $this->subpackage = $subpackage;
+ }
+}
+
+/**
+ * procedural page link
+ * @package phpDocumentor
+ * @subpackage Links
+ */
+class pageLink extends abstractLink
+{
+ /** @var string */
+ var $type = 'page';
+}
+
+/**
+ * function link
+ * @package phpDocumentor
+ * @subpackage Links
+ */
+class functionLink extends abstractLink
+{
+ /** @var string */
+ var $type = 'function';
+}
+
+/**
+ * define link
+ * @package phpDocumentor
+ * @subpackage Links
+ */
+class defineLink extends abstractLink
+{
+ /** @var string */
+ var $type = 'define';
+}
+
+/**
+ * global variable link
+ * @package phpDocumentor
+ * @subpackage Links
+ */
+class globalLink extends abstractLink
+{
+ /** @var string */
+ var $type = 'global';
+}
+
+/**
+ * class link
+ * @package phpDocumentor
+ * @subpackage Links
+ */
+class classLink extends abstractLink
+{
+ /** @var string */
+ var $type = 'class';
+}
+
+/**
+ * method link
+ * @package phpDocumentor
+ * @subpackage Links
+ */
+class methodLink extends abstractLink
+{
+ /** @var string */
+ var $type = 'method';
+ /** @var string */
+ var $class = '';
+
+ /**
+ * @param string class name
+ * @param string full path to file containing element
+ * @param string page name, as configured by {@link Parser::parse}
+ * @param string element name
+ * @param string package element is in
+ * @param string subpackage element is in
+ */
+ function addLink($class, $path ,$fileAlias,$name,$package,$subpackage, $category = false)
+ {
+ $this->class = $class;
+ abstractLink::addLink($path, $fileAlias,$name,$package,$subpackage, $category);
+ }
+}
+
+/**
+ * class variable link
+ * @package phpDocumentor
+ * @subpackage Links
+ */
+class varLink extends methodLink
+{
+ /** @var string */
+ var $type = 'var';
+}
+
+/**
+ * class constant link
+ * @package phpDocumentor
+ * @subpackage Links
+ */
+class constLink extends methodLink
+{
+ /** @var string */
+ var $type = 'const';
+}
+
+/**
+ * tutorial link
+ * @package phpDocumentor
+ * @subpackage Links
+ */
+class tutorialLink extends abstractLink
+{
+ /**#@+ @var string */
+ var $type = 'tutorial';
+ var $section = '';
+ var $title = false;
+ /**#@-*/
+
+ /**
+ * @param string section/subsection name
+ * @param string full path to file containing element
+ * @param string page name, as configured by {@link Parser::parse}
+ * @param string element name
+ * @param string package element is in
+ * @param string subpackage element is in
+ * @param string title of tutorial
+ */
+ function addLink($section,$path,$name,$package,$subpackage,$title = false, $category = false)
+ {
+ $this->section = $section;
+ $this->title = $title;
+ parent::addLink($path,'',$name,$package,$subpackage, $category);
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/PackagePageElements.inc b/buildscripts/PhpDocumentor/phpDocumentor/PackagePageElements.inc
new file mode 100644
index 00000000..1b71b6b7
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/PackagePageElements.inc
@@ -0,0 +1,387 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * Data structures used in parsing XML DocBook-based tutorials
+ *
+ * Conversion of DocBook-based tutorials is performed using special
+ * {@link Converter} class methods. By default, these methods simply retrieve
+ * simple rules for replacement of tags and slight re-ordering from the
+ * options.ini file present for every template.
+ *
+ * In future versions, there may be utilization of xslt or other more powerful
+ * protocols. However, for most situations, the power of these classes will
+ * be more than sufficient to handle very complex documentation.
+ *
+ * Note that an entire tutorial is contained in a single parserXMLDocBookTag,
+ * matching the document model for DocBook. The top-level tag, <refentry>,
+ * contains every other tag and all text.
+ * @tutorial tutorials.pkg
+ * @package phpDocumentor
+ * @subpackage Tutorial
+ */
+/**
+ * Represents <![CDATA[ ]]> sections.
+ *
+ * These sections are interpreted as plain text
+ * @package phpDocumentor
+ * @subpackage Tutorial
+ */
+class parserCData extends parserStringWithInlineTags
+{
+ /**
+ * @uses Converter::getCData() convert contents to text
+ * @param Converter
+ */
+ function Convert(&$c, $postprocess = true)
+ {
+ $val = $this->value;
+ if ($postprocess)
+ foreach($this->value as $key => $value)
+ {
+ if (is_string($value)) $this->value[$key] = $c->getCData($value);
+ }
+ $this->cache = false;
+ $x = parent::Convert($c, false);
+ $this->value = $val;
+ return $x;
+ }
+}
+/**
+ * a standard XML DocBook Tag
+ *
+ * This class is designed to represent all DocBook tags. It is intelligent
+ * enough to understand the <title> tag, and also the <refname> tag for
+ * as title for <refentry>
+ * @since 1.2
+ * @package phpDocumentor
+ * @subpackage Tutorial
+ */
+class parserXMLDocBookTag extends parserStringWithInlineTags
+{
+ /**
+ * Attributes from the XML tag
+ *
+ * Format: array(attrname => attrvalue, attrname => attrvalue,...)
+ * @var array
+ */
+ var $attributes = array();
+ /**
+ * Name of the tag
+ * @var string
+ */
+ var $name;
+ /**#@+ @access private */
+ /** @var parserCData */
+ var $_cdata;
+ /** @var parserTag */
+ var $_title;
+ /** @var parserIdLineTag */
+ var $_id;
+ /**
+ * Set to <refpurpose> in <refsynopsisdiv>
+ * @var parserTag
+ */
+ var $_description;
+ /**#@-*/
+ /**
+ * @param string tag name
+ */
+ function parserXMLDocBookTag($name)
+ {
+ $this->name = $name;
+ }
+
+ /**
+ * @param Converter
+ * @param boolean
+ * @uses Converter::TranslateTag() Calls this to enclose the contents of the
+ * DocBook tag based on the values in template options.ini file
+ */
+ function Convert(&$c, $postprocess = true)
+ {
+ $value = parent::Convert($c, $postprocess);
+ $simvalue = parent::Convert($c, false);
+ foreach($this->attributes as $a => $v)
+ {
+ $this->attributes[$a] = (is_string($v) ? $v : $v->Convert($c, $postprocess));
+ }
+ if (isset($this->_title))
+ {
+ list($this->attributes,$value) = $c->ConvertTitle($this->name, $this->attributes, $this->_title->Convert($c, $postprocess), $value);
+ }
+ return $c->TranslateTag($this->name,$this->attributes,$value,$simvalue);
+ }
+
+ /**
+ * Begin a new CData section
+ * @see addCData()
+ */
+ function startCData()
+ {
+ $this->_cdata = new parserCData;
+ }
+
+ /**
+ * Adds {@link $_cdata} to {@link $value}
+ */
+ function endCData()
+ {
+ $this->value[] = $this->_cdata;
+ unset($this->_cdata);
+ }
+
+ /**
+ * Retrieve either the table of contents index, or the location that
+ * the TOC will go
+ * @see setTOC()
+ * @param false|integer either an index of the {@}toc} tag in $this->value
+ * or false, if the next index value of $this->value
+ * is needed
+ */
+ function getTOC($state = false)
+ {
+ if ($state !== false) return $this->value[$state];
+ return count($this->value);
+ }
+
+ /**
+ * @param integer index of the TOC in $this->value
+ * @param parserTocInlineTag
+ */
+ function setTOC($state, $val)
+ {
+ $this->value[$state] = $val;
+ }
+
+ /**
+ * add a word to CData
+ * @param string
+ */
+ function addCData($word)
+ {
+ $this->_cdata->add($word);
+ }
+
+ /**
+ * Add an xml tag attribute name="value" pair
+ *
+ * if the attribute is id, value must be a {@link parserIdInlineTag}
+ * @param string attribute name
+ * @param string|parserIdInlineTag value of attribute
+ */
+ function addAttribute($name,$value)
+ {
+ $this->attributes[$name] = $value;
+ if ($name == 'id')
+ {
+ // fix 1153593
+ if (is_string($value))
+ {
+ addWarning(PDERROR_ID_MUST_BE_INLINE,$this->name,$value,$this->name,$value);
+ } else {
+ $this->setId($value);
+ }
+ }
+ }
+
+ /**
+ * Set the title of a DocBook tag section.
+ *
+ * For most DocBook tags, the title is represented with a <title></title>
+ * tag pair. The <refentry> top-level tag is a little different. Instead
+ * of using <title></title>, phpDocumentor uses the contents of the
+ * <refname> tag in the <refnamediv> tag
+ * @param parserXMLDocBookTag the title element
+ */
+ function setTitle($title)
+ {
+ $this->_title = $title;
+ }
+
+ /**
+ * If the id attribute is present, this method will set its id
+ * @param parserIdInlineTag
+ */
+ function setId($id)
+ {
+ $this->_id = $id;
+ }
+
+ /**
+ * Return converter-specific formatting of ID.
+ *
+ * Passes $c to {@link parserIdInlineTag::Convert()}
+ * @param Converter
+ * @return string
+ */
+ function getId(&$c)
+ {
+ if ($this->_id) return trim($this->_id->Convert($c));
+ }
+
+ /**
+ * Determine whether the docbook element has a title
+ * @return boolean
+ */
+ function hasTitle()
+ {
+ return isset($this->_title);
+ }
+
+ /**
+ * Retrieve Converter-specific formatting of the title of this element
+ * @return string
+ * @param Converter
+ */
+ function getTitle(&$c)
+ {
+ if ($this->name == 'refentry')
+ {
+ foreach($this->value as $tag)
+ {
+ if (is_object($tag) && $tag->name == 'refnamediv')
+ {
+ return $tag->getTitle($c);
+ }
+ }
+ }
+ if ($this->name == 'refnamediv')
+ {
+ foreach($this->value as $tag)
+ {
+ if (is_object($tag) && $tag->name == 'refname')
+ {
+ $t = new parserStringWithInlineTags;
+ foreach($tag->value as $val) $t->add($val);
+ $this->_title = $t;
+ }
+ if (is_object($tag) && $tag->name == 'refpurpose')
+ {
+ $t = new parserStringWithInlineTags;
+ foreach($tag->value as $val) $t->add($val);
+ $this->_description = $t;
+ }
+ }
+ }
+ if (isset($this->_title))
+ return $this->_title->Convert($c);
+ if (is_object($this->value[0])) return $this->value[0]->getTitle($c);
+ if (isset($this->value[1]))
+ if (is_object($this->value[1])) return $this->value[1]->getTitle($c);
+ return '';
+ }
+
+ /**
+ * Retrieve the contents of a subsection
+ *
+ * This method uses the $_id members of nested docbook tags to retrieve
+ * the section defined by $subsection
+ * @param Converter
+ * @param string converter-specific subsection
+ */
+ function getSubsection(&$c,$subsection)
+ {
+ if (!is_object($this->_id)) {
+ return false;
+ }
+ $search = phpDocumentor_clone($this->_id);
+ if (is_string($this->_id)) return false;
+ if (phpDocumentor_get_class($search) != 'parseridinlinetag') return false;
+ $search->id = $subsection;
+ foreach($this->value as $el)
+ {
+ if (phpDocumentor_get_class($el) == 'parserxmldocbooktag')
+ {
+ if ($el->getId($c) == $search->Convert($c))
+ {
+ return $el;
+ } elseif ($a = $el->getSubsection($c,$subsection))
+ {
+ return $a;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Add contents to this tag.
+ *
+ * There are four kinds of data in a DocBook tutorial:
+ * 1. <b>tags</b> - normal tags like <refentry>
+ * 2. <b>entities</b> - normal entities like &rdquo;
+ * 3. <b><![CDATA[</b> - character data that should not be interpreted,
+ * like <programlisting> contents
+ * 4. <b>text</b> - normal non-markup text
+ *
+ * All four kinds of data are added here
+ * @param parserEntity|parserCData|parserXMLDocBookTag|string nested tag,
+ * entity, or text
+ */
+ function add($el)
+ {
+ if (is_string($el)) return parent::add($el);
+ if (phpDocumentor_get_class($el) == 'parserxmldocbooktag')
+ {
+ if ($el->name == 'title')
+ {
+ $this->setTitle($el);
+ } else return parent::add($el);
+ } else return parent::add($el);
+ }
+}
+
+/**
+ * a standard entity like &rdquo;
+ *
+ * This class is designed to represent all DocBook entities.
+ * @since 1.2
+ * @package phpDocumentor
+ * @subpackage Tutorial
+ */
+class parserEntity
+{
+ /**
+ * @param string entity name
+ */
+ function parserEntity($name)
+ {
+ $this->value = $name;
+ }
+
+ /**
+ * @uses Converter::TranslateEntity() convert contents to text
+ * @param Converter
+ * @return string
+ */
+ function Convert(&$c, $postprocess = true)
+ {
+ if ($postprocess)
+ return $c->TranslateEntity($this->value);
+ else
+ {
+ $trans_tbl = get_html_translation_table (HTML_ENTITIES);
+ $trans_tbl = array_flip ($trans_tbl);
+ $ret = strtr ('&'.$this->value.';', $trans_tbl);
+ return $ret;
+ }
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Parser.inc b/buildscripts/PhpDocumentor/phpDocumentor/Parser.inc
new file mode 100644
index 00000000..55e67685
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Parser.inc
@@ -0,0 +1,3185 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * @package phpDocumentor
+ * @subpackage Parsers
+ */
+/** used when a backslash is encountered in parsing a string or other escapable entity */
+define("PARSER_EVENT_ESCAPE" , 900);
+/** used when a backslash is encountered in parsing a string or other escapable entity */
+define("STATE_ESCAPE" , 1000);
+
+/** Class published to IntermediateParser with this event */
+define("PHPDOCUMENTOR_EVENT_CLASS" , 800);
+/** DocBlock published to IntermediateParser with this event */
+define("PHPDOCUMENTOR_EVENT_DOCBLOCK" , 801);
+/** Function published to IntermediateParser with this event */
+define("PHPDOCUMENTOR_EVENT_FUNCTION" , 802);
+/** Class Variable published to IntermediateParser with this event */
+define("PHPDOCUMENTOR_EVENT_VAR" , 803);
+/** New File (page) published to IntermediateParser with this event */
+define("PHPDOCUMENTOR_EVENT_PAGE" , 804);
+/** Constant (define) published to IntermediateParser with this event */
+define("PHPDOCUMENTOR_EVENT_DEFINE" , 805);
+/** Class Constant published to IntermediateParser with this event */
+define("PHPDOCUMENTOR_EVENT_CONST" , 806);
+/** @deprecated */
+define("PHPDOCUMENTOR_EVENT_MESSAGE" , 807);
+/** use to inform IntermediateParser of a new element being parsed */
+define("PHPDOCUMENTOR_EVENT_NEWSTATE" , 808);
+/**
+ * used to inform phpDocumentor_IntermediateParser that the current file has been completely parsed.
+ * Render then flushes all buffers for functions/classes/defines/includes on the current page
+ * @see phpDocumentor_IntermediateParser::HandleEvent()
+ */
+define("PHPDOCUMENTOR_EVENT_END_PAGE" , 808);
+/** Package-level page published to IntermediateParser with this event */
+define("PHPDOCUMENTOR_EVENT_PACKAGEPAGE" , 809);
+/** Include (include/require/include_once/include_once) published to IntermediateParser with this event */
+define("PHPDOCUMENTOR_EVENT_INCLUDE" , 810);
+/** Tutorial published to IntermediateParser with this event */
+define("PHPDOCUMENTOR_EVENT_TUTORIAL" , 811);
+/** Contents of README/INSTALL/CHANGELOG files published to IntermediateParser with this event */
+define("PHPDOCUMENTOR_EVENT_README_INSTALL_CHANGELOG" , 812);
+
+/** use to inform ErrorTracker of a new file being parsed */
+define("PHPDOCUMENTOR_EVENT_NEWFILE" , 811);
+/** use to inform ErrorTracker of the next line number being parsed */
+define("PHPDOCUMENTOR_EVENT_NEWLINENUM" , 812);
+/** used when a global variable definition is encountered in the source */
+define("PHPDOCUMENTOR_EVENT_GLOBAL" , 813);
+/** used when a docblock template is encountered in the source */
+define("PHPDOCUMENTOR_EVENT_DOCBLOCK_TEMPLATE" , 814);
+/** used when a docblock template is encountered in the source */
+define("PHPDOCUMENTOR_EVENT_END_DOCBLOCK_TEMPLATE" , 815);
+/** used when double quotation mark (") encountered in parsing */
+define("PARSER_EVENT_QUOTE" , 101);
+/** currently parsing a quote */
+define("STATE_QUOTE" , 201);
+
+/** { encountered in parsing a function or php code */
+define("PARSER_EVENT_LOGICBLOCK" , 102);
+/** currently parsing a { } block */
+define("STATE_LOGICBLOCK" , 202);
+
+/** used for the beginning of parsing, before first < ? php encountered */
+define("PARSER_EVENT_NOEVENTS" , 103);
+/** out of < ? php tag */
+define("STATE_NOEVENTS" , 203);
+
+/** used when long comment /x x/ where x is an asterisk is encountered in parsing */
+define("PARSER_EVENT_COMMENTBLOCK" , 104);
+/** currently parsing a long comment /x x/ where x is an asterisk */
+define("STATE_COMMENTBLOCK" , 204);
+
+/** used when short comment // is encountered in parsing */
+define("PARSER_EVENT_COMMENT" , 105);
+/** currently parsing a short comment // */
+define("STATE_COMMENT" , 205);
+
+/** used when php code processor instruction (< ? php) is encountered in parsing */
+define("PARSER_EVENT_PHPCODE" , 106);
+/** currently parsing php code */
+define("STATE_PHPCODE" , 206);
+
+/** used when a define statement is encountered in parsing */
+define("PARSER_EVENT_DEFINE" , 107);
+/** currently parsing a define statement */
+define("STATE_DEFINE" , 207);
+
+/** used when a define statement opening parenthesis is encountered in parsing */
+define("PARSER_EVENT_DEFINE_PARAMS" , 108);
+/** currently parsing the stuff in ( ) of a define statement */
+define("STATE_DEFINE_PARAMS" , 208);
+
+/** used when a function statement opening parenthesis is encountered in parsing */
+define("PARSER_EVENT_FUNCTION_PARAMS" , 109);
+/** currently parsing the stuff in ( ) of a function definition */
+define("STATE_FUNCTION_PARAMS" , 209);
+
+/** used when a single quote (') is encountered in parsing */
+define("PARSER_EVENT_SINGLEQUOTE" , 110);
+/** currently parsing a string enclosed in single quotes (') */
+define("STATE_SINGLEQUOTE" , 210);
+
+/** used when a class definition is encountered in parsing */
+define("PARSER_EVENT_CLASS" , 111);
+/** currently parsing a class definition */
+define("STATE_CLASS" , 211);
+/** used to tell Render that a class has been completely parsed, and to flush buffers */
+define("STATE_END_CLASS" , 311);
+
+/** used when a DocBlock is encountered in parsing */
+define("PARSER_EVENT_DOCBLOCK" , 112);
+/** currently parsing a DocBlock */
+define("STATE_DOCBLOCK" , 212);
+
+/** used when a @tag is encountered in DocBlock parsing */
+define("PARSER_EVENT_DOCKEYWORD" , 113);
+/** currently parsing a @tag in a DocBlock */
+define("STATE_DOCKEYWORD" , 213);
+
+/** used when a <email@address> is encountered in parsing an @author tag*/
+define("PARSER_EVENT_DOCKEYWORD_EMAIL" , 114);
+/** currently parsing an email in brackets in an @author tag of a DocBlock */
+define("STATE_DOCKEYWORD_EMAIL" , 214);
+
+/** used when an array definition is encountered in parsing */
+define("PARSER_EVENT_ARRAY" , 115);
+/** currently parsing an array */
+define("STATE_ARRAY" , 215);
+
+/** used when a var statement is encountered in parsing a class definition */
+define("PARSER_EVENT_VAR" , 116);
+/** currently parsing a Class variable */
+define("STATE_VAR" , 216);
+
+/** used when a function definition is encountered in parsing */
+define("PARSER_EVENT_FUNCTION" , 117);
+/** currently parsing a Function or Method */
+define("STATE_FUNCTION" , 217);
+
+/** used when a ? > (with no space) is encountered in parsing */
+define("PARSER_EVENT_OUTPHP" , 118);
+/** currently out of php code */
+define("STATE_OUTPHP" , 218);
+
+/** used when an inline {@tag} is encountered in parsing a DocBlock */
+define("PARSER_EVENT_INLINE_DOCKEYWORD" , 119);
+/** currently parsing an inline tag like { @link} in a DocBlock */
+define("STATE_INLINE_DOCKEYWORD" , 219);
+
+/** used when a define statement's opening parenthesis is encountered in parsing */
+define("PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS" , 120);
+/** currently parsing an inner parenthetical statement of a define( ) */
+define("STATE_DEFINE_PARAMS_PARENTHESIS" , 220);
+
+define("PARSER_EVENT_END_STATEMENT", 121);
+
+/** used when a <<< is encountered in parsing */
+define("PARSER_EVENT_EOFQUOTE" , 122);
+/** currently parsing a string defined using Perl <<< */
+define("STATE_EOFQUOTE" , 222);
+
+/** used when an include/require/include_once/include_once statement is encountered in parsing */
+define("PARSER_EVENT_INCLUDE" , 123);
+/** currently parsing an include/require/include_once/include_once */
+define("STATE_INCLUDE" , 223);
+
+/** used when an opening parenthesis of an include/require/include_once/include_once statement is encountered in parsing */
+define("PARSER_EVENT_INCLUDE_PARAMS" , 124);
+/** currently parsing the stuff in ( ) of a define statement */
+define("STATE_INCLUDE_PARAMS" , 224);
+
+/** used when an inner ( ) is encountered while parsing an include/require/include_once/include_once statement */
+define("PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS" , 125);
+/** currently parsing an inner parenthetical statement of an include/includeonce/require/requireonce( ) */
+define("STATE_INCLUDE_PARAMS_PARENTHESIS" , 225);
+
+/** used when parsing the desc part of a docblock */
+define("PARSER_EVENT_DESC" , 126);
+/** currently parsing the desc part of a docblock */
+define("STATE_DESC" , 226);
+
+/** used when parsing the @tag block of a docblock */
+define("PARSER_EVENT_TAGS" , 127);
+/** currently parsing the @tag block of a docblock */
+define("STATE_TAGS" , 227);
+
+/** used when parsing a global variable declaration */
+define("PARSER_EVENT_DEFINE_GLOBAL" , 128);
+/** currently parsing a global variable declaration */
+define("STATE_GLOBAL" , 228);
+
+/** used when parsing the default value in a global variable declaration */
+define("PARSER_EVENT_GLOBAL_VALUE" , 129);
+/** currently parsing the default value in a global variable declaration */
+define("STATE_GLOBAL_VALUE" , 229);
+
+/** used when parsing a "global $var1, $var2;" declaration in a function */
+define("PARSER_EVENT_FUNC_GLOBAL" , 130);
+/** currently parsing a "global $var1, $var2;" declaration in a function */
+define("STATE_FUNC_GLOBAL" , 230);
+
+/** used when parsing a "static $var1, $var2;" declaration in a function */
+define("PARSER_EVENT_STATIC_VAR" , 131);
+/** currently parsing a "static $var1, $var2;" declaration in a function */
+define("STATE_STATIC_VAR" , 231);
+
+/** used when parsing the value in a "static $var1 = x" declaration in a function */
+define("PARSER_EVENT_STATIC_VAR_VALUE" , 132);
+/** currently parsing the value in a "static $var1 = x" declaration in a function */
+define("STATE_STATIC_VAR_VALUE" , 232);
+
+/** used when encountering a /**#@+ comment marking a new docblock template */
+define("PARSER_EVENT_DOCBLOCK_TEMPLATE" , 133);
+/** currently parsing the value in a "static $var1 = x" declaration in a function */
+define("STATE_DOCBLOCK_TEMPLATE" , 233);
+
+/** used when encountering a /**#@-* / comment (no space) marking the end of using a docblock template */
+define("PARSER_EVENT_END_DOCBLOCK_TEMPLATE" , 134);
+/** currently parsing the value in a "static $var1 = x" declaration in a function */
+define("STATE_END_DOCBLOCK_TEMPLATE" , 234);
+
+/** used by the {@link HighlightParser} only, when a method starts */
+define("PARSER_EVENT_METHOD" , 135);
+/** currently parsing a method using the {@link HighlightParser} */
+define("STATE_METHOD" , 235);
+
+/** used by the {@link HighlightParser} only, when a method body is parsed */
+define("PARSER_EVENT_METHOD_LOGICBLOCK" , 136);
+/** currently parsing the method body using the {@link HighlightParser} */
+define("STATE_METHOD_LOGICBLOCK" , 236);
+
+/** used by the {@link HighlightParser} only, when ->var or ->function() is encountered in a method */
+define("PARSER_EVENT_CLASS_MEMBER" , 137);
+/** currently parsing a class member using the {@link HighlightParser} */
+define("STATE_CLASS_MEMBER" , 237);
+
+/** used by the {@link HighlightParser} only, when {$var} is encountered in a string */
+define("PARSER_EVENT_QUOTE_VAR" , 138);
+/** currently parsing a {$encapsed_var} using the {@link HighlightParser} */
+define("STATE_QUOTE_VAR" , 238);
+
+/** used when parsing an access modifier */
+define("PARSER_EVENT_ACCESS_MODIFIER" , 139);
+/** currently parsing an access modifier */
+define("STATE_ACCESS_MODIFIER" , 239);
+
+/** used when a class implements interfaces */
+define("PARSER_EVENT_IMPLEMENTS" , 140);
+/** currently parsing an implements clause */
+define("STATE_IMPLEMENTS" , 240);
+
+/** used when a class implements interfaces */
+define("PARSER_EVENT_CLASS_CONSTANT" , 141);
+/** currently parsing a class constant */
+define("STATE_CLASS_CONSTANT" , 241);
+
+/** used when a variable value is an array */
+define("PARSER_EVENT_VAR_ARRAY" , 142);
+/** currently parsing a variable value is an array */
+define("STATE_VAR_ARRAY" , 242);
+
+/** used when a comment is found in a variable array value */
+define("PARSER_EVENT_VAR_ARRAY_COMMENT" , 143);
+/** currently parsing a comment in a variable array value */
+define("STATE_VAR_ARRAY_COMMENT" , 243);
+
+if (!defined('T_INTERFACE'))
+{
+ define('T_INTERFACE', 'foo');
+ if (!defined('T_CONST')) {
+ define('T_CONST', 'foo');
+ }
+ define('T_ABSTRACT', 'foo');
+ define('T_PRIVATE', 'foo');
+ define('T_PUBLIC', 'foo');
+ define('T_PROTECTED', 'foo');
+ define('T_FINAL', 'foo');
+ define('T_IMPLEMENTS', 'foo');
+}
+if (!defined('T_DOC_COMMENT'))
+{
+ define('T_DOC_COMMENT', T_ML_COMMENT);
+}
+/**
+ * PHP Parser for PHP 4.2.3-
+ *
+ * This parser is slower than the tokenizer-based parser, and is deprecated.
+ * @author Joshua Eichorn <jeichorn@phpdoc.org>
+ * @author Gregory Beaver <cellog@users.sourceforge.net>
+ * @version $Id: Parser.inc,v 1.1 2005/10/17 18:36:56 jeichorn Exp $
+ * @package phpDocumentor
+ * @subpackage Parsers
+ * @deprecated in favor of {@link phpDocumentorTParser}
+ */
+class Parser extends Publisher
+{
+ /**#@+
+ * @access private
+ */
+ /**
+ * Word parser
+ * @see WordParser
+ */
+ var $wp;
+
+ /**
+ * temporary parser variables
+ */
+ var $p_vars = array('func' => false, 'function_data' => '', 'quote_data' => '', 'event_stack' => false, 'last_pevent' => 0,
+ 'two_words_ago' => '', 'temp_word' => '', 'docblock' => false, 'line' => array(), 'linecount' => 0, 'startword' => '',
+ 'periodline' => 0, 'shortdesc' => '', 'docblock_desc' => '', 'class' => false, 'source_location' => '',
+ 'define_params_data' => '', 'define' => false, 'define_name' => '', 'define_value' => '', 'var' => false,
+ 'oldtoken' => false, 'comment_data' => '', 'function_param' => NULL, 'inline_dockeyword_type' => false,
+ 'inline_dockeyword_data' => false, 'dockeyword_type' => false, 'dockeyword_data' =>false, 'param_var' => false,
+ 'include_name' => '', 'include_value' => '','include' => false, 'return_type' => '', 'cur_class' => '',
+ 'function_data' => false, 'varname' => '', 'returntype' => false, 'vartype' => false, 'paramtype' => false,
+ 'tagname' => '', 'find_global' => '', 'global_type' => '', 'paramname' => false, 'statics' => array(),
+ 'static_count' => 0, 'static_val' => array(), 'docblock_type' => 'docblock', 'seelement' => false);
+
+ /**
+ * parser flags, for states that don't warrant a new event (like new line in a docblock)
+ */
+ var $p_flags = array('docblocknewline' => false, 'docblockintags' => false, 'useperiod' => false,
+ 'definename_isset' => false, 'define_parens' => false, 'reset_quote_data' => false,
+ 'in_desc' => true, 'in_tag' => false, 'newline' => true, 'tempnewline' => false,
+ 'start_docblock' => false, 'includename_isset' => false, 'return_isset' => false,
+ 'is_return' => false, 'in_class' => false, 'asterisk' => false, 'var_equals' => false,
+ 'arrayinvarname' => false, 'valid_newline' => true, 'startline' => false,
+ 'function_global' => false, 'define_global' => false, 'static_value' => false,'funcparam_val' => false,
+ 'get_source' => false, 'getting_source' => false);
+
+ /**
+ * lookup table for event handler methods
+ * @see Parser::parse()
+ */
+ var $eventHandlers = array(
+ 'handleArray' => PARSER_EVENT_ARRAY,
+ 'handleClass' => PARSER_EVENT_CLASS,
+ 'handleComment' => PARSER_EVENT_COMMENT,
+ 'handleDocBlockTemplate' => PARSER_EVENT_DOCBLOCK_TEMPLATE,
+ 'handleEndDocBlockTemplate' => PARSER_EVENT_END_DOCBLOCK_TEMPLATE,
+ 'handleEscape' => PARSER_EVENT_ESCAPE,
+ 'handleLogicBlock' => PARSER_EVENT_LOGICBLOCK,
+ 'defaultHandler' => PARSER_EVENT_NOEVENTS,
+// 'defaultHandler' => PARSER_EVENT_COMMENTBLOCK, (set in constructor below)
+// 'defaultHandler' => PARSER_EVENT_OUTPHP,
+ 'handleDefine' => PARSER_EVENT_DEFINE,
+ 'handleDefineParams' => PARSER_EVENT_DEFINE_PARAMS,
+ 'handleDefineParamsParenthesis' => PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS,
+ 'handleIncludeParamsParenthesis' => PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS,
+// 'handleDocBlock' => PARSER_EVENT_DOCBLOCK,
+ 'BetterhandleDocBlock' => PARSER_EVENT_DOCBLOCK,
+ 'handleTags' => PARSER_EVENT_TAGS,
+ 'handleDesc' => PARSER_EVENT_DESC,
+// 'handleDockeyword' => PARSER_EVENT_DOCKEYWORD,
+ 'handleTag' => PARSER_EVENT_DOCKEYWORD,
+ 'handleDockeywordEmail' => PARSER_EVENT_DOCKEYWORD_EMAIL,
+ 'handleEOFQuote' => PARSER_EVENT_EOFQUOTE,
+ 'handleFunction' => PARSER_EVENT_FUNCTION,
+ 'handleFunctionParams' => PARSER_EVENT_FUNCTION_PARAMS,
+ 'handleFuncGlobal' => PARSER_EVENT_FUNC_GLOBAL,
+ 'handleGlobal' => PARSER_EVENT_DEFINE_GLOBAL,
+ 'handleGlobalValue' => PARSER_EVENT_GLOBAL_VALUE,
+ 'handleInlineDockeyword' => PARSER_EVENT_INLINE_DOCKEYWORD,
+ 'handleInclude' => PARSER_EVENT_INCLUDE,
+ 'handleIncludeParams' => PARSER_EVENT_INCLUDE_PARAMS,
+ 'handleQuote' => PARSER_EVENT_QUOTE,
+ 'handlePhpCode' => PARSER_EVENT_PHPCODE,
+ 'handleSingleQuote' => PARSER_EVENT_SINGLEQUOTE,
+ 'handleStaticVar' => PARSER_EVENT_STATIC_VAR,
+ 'handleStaticValue' => PARSER_EVENT_STATIC_VAR_VALUE,
+ 'handleVar' => PARSER_EVENT_VAR,
+ );
+
+ /**
+ * event handlers for @tags
+ * @tutorial tags.pkg
+ */
+ var $tagHandlers = array(
+ '*' => 'defaultTagHandler',
+ 'category' => 'categoryTagHandler',
+ 'example' => 'exampleTagHandler',
+ 'filesource' => 'invalidTagHandler',
+ 'return' => 'returnTagHandler',
+ 'returns' => 'returnTagHandler',
+ 'var' => 'varTagHandler',
+ 'package' => 'packageTagHandler',
+ 'param' => 'paramTagHandler',
+ 'parameter' => 'paramTagHandler',
+ 'global' => 'globalTagHandler',
+ 'staticvar' => 'staticvarTagHandler',
+ 'uses' => 'usesTagHandler'
+ );
+
+ var $laststart = false;
+
+ /**
+ * An array of allowable @tags
+ */
+ var $allowableTags;
+
+
+ /**
+ * An array of allowed inline @tags
+ */
+ var $allowableInlineTags;
+
+ /**
+ * Sets the states up, and creates a new WordParser
+ */
+
+ /**
+ * an array of parsing tokens organized by event number.
+ * A token is defined as the smallest group of characters that separates or
+ * defines a new parser element. In English, a space or punctuation are
+ * tokens that separate words. in PHP, tokens may be //, or even "
+ * Format: array(eventnum =>array(token1, token2, token3, ...),...)
+ * @var array
+ */
+ var $tokens;
+
+ /**
+ * array of events that are raised, organized by the tokens that raise them.
+ * Format: array(eventnum => array(token => neweventnum, token2 => neweventnum2,...),...)
+ * @var array
+ */
+ var $pushEvent;
+
+ /**
+ * array of tokens that end an event, organized by event
+ * Format: array(eventnum => array(token => neweventnum, token2 => neweventnum2,...),...)
+ * @var array
+ */
+ var $popEvent;
+ /**#@-*/
+
+ /**
+ * Set up invariant parsing variables
+ */
+ function Parser()
+ {
+ $this->allowableTags = $GLOBALS['_phpDocumentor_tags_allowed'];
+ $this->allowableInlineTags = $GLOBALS['_phpDocumentor_inline_doc_tags_allowed'];
+ $this->wp = new WordParser;
+ // strange PHP 4.0.6 behavior: it converts constants to strings without warning if it's an array index
+ $this->eventHandlers = array_flip($this->eventHandlers);
+ $this->eventHandlers[PARSER_EVENT_COMMENTBLOCK] = 'defaultHandler';
+ $this->eventHandlers[PARSER_EVENT_OUTPHP] = 'defaultHandler';
+ $this->subscribe(PHPDOCUMENTOR_EVENT_NEWLINENUM,$GLOBALS['phpDocumentor_errors']);
+ $this->subscribe(PHPDOCUMENTOR_EVENT_NEWFILE,$GLOBALS['phpDocumentor_errors']);
+ }
+
+ /**
+ * Parse a new file
+ *
+ * @param string $parse_data
+ * @param string $path
+ * @param int $base number of directories to drop off the bottom when creating names using path
+ * @staticvar integer used for recursion limiting if a handler for an event is not found
+ * @return bool
+ */
+ function parse (&$parse_data, $path, $base = 0, $packages = false)
+ {
+ global $_phpDocumentor_options;
+ static $endrecur = 0;
+ $this->p_vars = array('func' => false, 'function_data' => '', 'quote_data' => '', 'event_stack' => false, 'last_pevent' => 0,
+ 'two_words_ago' => '', 'temp_word' => '', 'docblock' => false, 'line' => array(), 'linecount' => 0, 'startword' => '',
+ 'periodline' => 0, 'shortdesc' => '', 'docblock_desc' => '', 'class' => false, 'source_location' => '',
+ 'define_params_data' => '', 'define' => false, 'define_name' => '', 'define_value' => '', 'var' => false,
+ 'oldtoken' => false, 'comment_data' => '', 'function_param' => NULL, 'inline_dockeyword_type' => false,
+ 'inline_dockeyword_data' => false, 'dockeyword_type' => false, 'dockeyword_data' =>false, 'param_var' => false,
+ 'include_name' => '', 'include_value' => '','include' => false, 'return_type' => '', 'cur_class' => '',
+ 'function_data' => false, 'varname' => '', 'returntype' => false, 'vartype' => false, 'paramtype' => false,
+ 'tagname' => '', 'find_global' => '', 'global_type' => '', 'paramname' => false, 'statics' => array(),
+ 'static_count' => 0, 'static_val' => array(), 'docblock_type' => 'docblock', 'linenum' => false,
+ 'seelement' => false);
+
+ $this->p_flags = array('docblocknewline' => false, 'docblockintags' => false, 'useperiod' => false,
+ 'definename_isset' => false, 'define_parens' => false, 'reset_quote_data' => false,
+ 'in_desc' => true, 'in_tag' => false, 'newline' => true, 'tempnewline' => false,
+ 'start_docblock' => false, 'includename_isset' => false, 'return_isset' => false,
+ 'is_return' => false, 'in_class' => false, 'asterisk' => false, 'var_equals' => false,
+ 'arrayinvarname' => false, 'valid_newline' => true, 'startline' => false,
+ 'function_global' => false, 'define_global' => false, 'static_value' => false,'funcparam_val' => false,
+ 'get_source' => false, 'getting_source' => false, 'in_define' => false, 'in_include' => false,
+ 'in_var' => false, 'in_global' => false);
+ $this->p_vars['parsepath'] = $path;
+ $this->setupStates();
+ if (strlen($parse_data) == 0)
+ {
+ return false;
+ }
+
+ // initialize variables so E_ALL error_reporting doesn't complain
+ $pevent = 0;
+ $word = 0;
+ $this->p_vars['event_stack'] = new EventStack;
+
+ $this->wp->setup($parse_data);
+
+
+ $page = new ParserPage;
+ $page->setPath($path);
+ $page->setPackageOutput($packages);
+ $page->setFile(basename($path));
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWFILE,basename($path));
+ //$name = str_replace("/","_",dirname($path)) . "_" . array_shift(explode(".",$page->getFile()));
+ // fc@fc.clever-soft.com 11/29/2001
+ $name = str_replace(PATH_DELIMITER,"_",dirname($path)) . "_" . str_replace(".","_",$page->getFile());
+ $tmp = explode("_",$name);
+ $name = str_replace(':','_',implode("_",array_slice($tmp,$base)));
+ // if base is '', drive letter is present in windows
+
+ $page->setName($name);
+ $temploc = $_phpDocumentor_options['Program_Root'] . PATH_DELIMITER. implode(PATH_DELIMITER,
+ array_slice(explode(PATH_DELIMITER,$path),$base));
+
+ if ($temploc == $_phpDocumentor_options['Program_Root'] . PATH_DELIMITER) $temploc .= $path;
+
+ $this->p_vars['source_location'] = $source_location = $temploc;
+ $page->setSourceLocation($source_location);
+
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_PAGE,$page);
+ unset($page);
+ $this->p_flags['reset_quote_data'] = true;
+
+ do
+ {
+ $lpevent = $pevent;
+ $pevent = $this->p_vars['event_stack']->getEvent();
+ if ($lpevent != $pevent)
+ {
+ $this->p_vars['last_pevent'] = $lpevent;
+ }
+
+ if ($this->p_vars['last_pevent'] != $pevent)
+ {
+ // its a new event so the word parser needs to be reconfigured
+ $this->configWordParser($pevent);
+ }
+
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE,($pevent + 100));
+
+ if ($pevent == PARSER_EVENT_GLOBAL_VALUE || $pevent == PARSER_EVENT_DOCBLOCK || $pevent == PARSER_EVENT_DOCBLOCK_TEMPLATE)
+ {
+ $this->wp->setWhitespace(true);
+ }
+
+ $this->p_vars['last_word'] = $word;
+ $word = $this->wp->getWord();
+ // in wordparser, have to keep track of lines
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWLINENUM, $this->wp->linenum);
+
+ if (0)//PHPDOCUMENTOR_DEBUG == true)
+ {
+ echo "\nLAST: |" . $this->p_vars['last_word'] . "|\n";
+ echo "PEVENT: " . $this->getParserEventName($pevent) . "\n";
+ echo "LASTPEVENT: " . $this->getParserEventName($this->p_vars['last_pevent']) . "\n";
+ echo $this->wp->getPos() . ": |$word|\n--------------------------\n\n";
+ }
+ if ($this->p_flags['get_source'])
+ {
+ if ($pevent == PARSER_EVENT_FUNCTION)
+ {
+ $this->wp->retrievesource("function $word");
+ $this->p_flags['get_source'] = false;
+ $this->p_flags['getting_source'] = true;
+ }
+ }
+ if (false)//$this->p_flags['getting_source'] && ($pevent == PARSER_EVENT_DOCBLOCK) || ($pevent == PARSER_EVENT_NOEVENTS))
+ {
+ addError(PDERROR_SOURCE_TAG_FUNCTION_NOT_FOUND);
+ // throw away source
+ $this->wp->getSource();
+ }
+ if (isset($this->eventHandlers[$pevent]))
+ {
+ $handle = $this->eventHandlers[$pevent];
+ $this->$handle($word, $pevent);
+ } else
+ {
+ debug('WARNING: possible error, no handler for event number '.$pevent);
+ if ($endrecur++ == 25)
+ {
+ die("FATAL ERROR, recursion limit reached");
+ }
+ }
+ } while (!($word === false));
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE,PHPDOCUMENTOR_EVENT_END_PAGE);
+ }
+
+ /**#@+
+ * @access private
+ * @param string token parsed from source
+ * @param integer parser constant from {@link Parser.inc}
+ */
+ /**
+ * handler for NOEVENTS, OUTPHP, COMMENTBLOCK
+ */
+
+ function defaultHandler($word, $pevent)
+ {
+ $this->checkEventPush( $word, $pevent);
+ $this->checkEventPop($word,$pevent);
+ }
+
+ /**
+ * handler for LOGICBLOCK
+ *
+ * Logic Blocks are the stuff between { and } in a function/method. A
+ * logic block can clearly contain other logic blocks, as in:
+ *
+ * <code>
+ * function test($a)
+ * {
+ * if (testcondition)
+ * { // nested logic block
+ * }
+ * }
+ * </code>
+ *
+ * So, the exit portion of the logic block handler must check to see if the
+ * logic block being exited is the top-level, and it does this by retrieving
+ * the last event from the stack. If it is a function (and not a logic block)
+ * then it backs up the word parser so that the function will exit properly.
+ *
+ * {@source 11}
+ */
+
+ function handleLogicBlock($word, $pevent)
+ {
+ $a = $this->checkEventPush( $word, $pevent);
+ if ($a == PARSER_EVENT_FUNC_GLOBAL || $a == PARSER_EVENT_STATIC_VAR)
+ {
+ if (substr($this->p_vars['last_word'],strlen($this->p_vars['last_word']) - 1,1) != ' ' && substr($this->p_vars['last_word'],strlen($this->p_vars['last_word']) - 1,1) != "\t" && substr($this->p_vars['last_word'],strlen($this->p_vars['last_word']) - 1,1) != "\n" && substr($this->p_vars['last_word'],strlen($this->p_vars['last_word']) - 1,1) != ";" && substr($this->p_vars['last_word'],strlen($this->p_vars['last_word']) - 1,1) != "}" && substr($this->p_vars['last_word'],strlen($this->p_vars['last_word']) - 1,1) != "{")
+ {
+ $this->p_vars['event_stack']->popEvent();
+ }
+ }
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $e = $this->p_vars['event_stack']->popEvent();
+ $this->p_vars['event_stack']->pushEvent($e);
+ if ($e == PARSER_EVENT_FUNCTION)
+ {
+ $this->wp->backupPos($word);
+ }
+ }
+ }
+
+ /**
+ * handler for ESCAPE.
+ * this event handler parses <code>"this string \"with its escape backslashes\""</code> and returns:
+ * <code>this string "with its escape backslashes"</code>
+ * to make it human-readable
+ */
+
+ function handleEscape($word, $pevent)
+ {
+ $this->p_vars['event_stack']->popEvent();
+ }
+
+ /**
+ * handler for COMMENT.
+ * this event handler parses single-line comments like:
+ * // this one
+ */
+
+ function handleComment($word, $pevent)
+ {
+ $this->checkEventPush( $word, $pevent);
+
+ if (!isset($this->p_vars['comment_data'])) $this->p_vars['comment_data'] = '';
+ $this->p_vars['comment_data'] .= $word;
+
+ $this->checkEventPop($word,$pevent);
+ }
+
+ /**
+ * handler for ARRAY.
+ * this event handler parses arrays in default values of function and var definitions
+ */
+
+ function handleArray($word, $pevent)
+ {
+ $e = $this->checkEventPush( $word, $pevent);
+ if (($e == PARSER_EVENT_COMMENTBLOCK) ||
+ ($e == PARSER_EVENT_COMMENT)) return;
+
+ if (!isset($this->p_vars['function_data']) || (isset($this->p_vars['function_data']) && empty($this->p_vars['function_data'])))
+ {
+ $this->p_vars['function_data'] = "array";
+ }
+
+ if ( ($this->p_vars['last_word'] == "'"))
+ {
+ $this->p_vars['function_data'] .= $this->p_vars['quote_data']."'";
+ }
+ if ( ($this->p_vars['last_word'] == "\""))
+ {
+ $this->p_vars['function_data'] .= $this->p_vars['quote_data']."\"";
+ }
+
+ $this->p_vars['function_data'] .= $word;
+ //echo "function_data = |$this->p_vars['function_data']|\n";
+
+ if ($this->checkEventPop($word,$pevent))
+ {
+ }
+ }
+
+ /**
+ * handler for DEFINE.
+ * handles define(constant, value); statements
+ */
+
+ function handleDefine($word, $pevent)
+ {
+ if (!$this->p_flags['in_define'])
+ {
+ $this->p_vars['linenum'] = $this->wp->linenum;
+ }
+ $this->p_flags['in_define'] = true;
+ $this->checkEventPush( $word, $pevent);
+
+ $this->p_flags['definename_isset'] = false;
+ $this->p_vars['define_params_data'] = '';
+ unset($this->p_vars['quote_data']);
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->p_flags['in_define'] = false;
+ $this->p_vars['define'] = new parserDefine;
+ $this->p_vars['define']->setLineNumber($this->p_vars['linenum']);
+ $this->p_vars['define']->setName($this->p_vars['define_name']);
+ $this->p_vars['define']->setValue($this->p_vars['define_value']);
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_DEFINE,$this->p_vars['define']);
+ $this->p_flags['definename_isset'] = false;
+ unset($this->p_vars['define']);
+ unset($this->p_vars['define_name']);
+ unset($this->p_vars['define_value']);
+ $this->p_flags['in_define'] = false;
+ $this->p_vars['define_params_data'] = '';
+ }
+ }
+
+ /**
+ * handler for DEFINE_PARAMS.
+ * handles the parsing of constant and value in define(constant, value);
+ */
+
+ function handleDefineParams($word, $pevent)
+ {
+ if ($this->checkEventPush( $word, $pevent))
+ {
+ if ($word == '(')
+ {
+ $this->p_vars['define_params_data'] .= $word;
+ }
+ return;
+ }
+
+ $this->p_flags['define_parens'] = true;
+ if(!isset($this->p_vars['define_params_data'])) $this->p_vars['define_params_data'] = '';
+
+ if ($this->checkEventPop($word,$pevent))
+ {
+ if (!empty($this->p_vars['quote_data']))
+ {
+ $this->p_vars['define_params_data'] .= $this->p_vars['quote_data'];
+ }
+ if (!empty($this->p_vars['define_params_data']))
+ {
+ //echo $this->p_vars['define_params_data']."\n";
+ $this->p_vars['define_value'] = $this->p_vars['define_params_data'];
+ }
+ else
+ {
+ if ( $this->p_vars['last_word'] != "/*" &&
+ $this->p_vars['last_word'] != "//" && $this->p_vars['last_word'] != "#")
+ {
+ $this->p_vars['define_value'] = trim($this->p_vars['last_word']);
+ }
+ else
+ {
+ $this->p_vars['define_value'] = "";
+ }
+ }
+ }
+ if ($this->p_flags['definename_isset'])
+ {
+ if (isset($this->p_vars['quote_data']))
+ {
+ $this->p_vars['define_params_data'] .= '"'.$this->p_vars['quote_data'].'"';
+ unset($this->p_vars['quote_data']);
+ }
+ $this->p_vars['define_params_data'] .= $word;
+ } else
+ {
+ if ($word != ",")
+ {
+ if (isset($this->p_vars['quote_data']))
+ {
+ $this->p_vars['define_params_data'] .= $this->p_vars['quote_data'];
+ unset($this->p_vars['quote_data']);
+ }
+ $this->p_vars['define_params_data'] .= $word;
+ } else
+ {
+ if (isset($this->p_vars['quote_data']) && !$this->p_flags['definename_isset'])
+ {
+ $this->p_vars['define_params_data'] .= $this->p_vars['quote_data'];
+ unset($this->p_vars['quote_data']);
+ }
+ $this->p_flags['definename_isset'] = true;
+ $this->p_vars['define_name'] = $this->p_vars['define_params_data'];
+ unset($this->p_vars['quote_data']);
+ $this->p_vars['define_params_data'] = '';
+ }
+ }
+ }
+
+ /**
+ * handler for DEFINE_PARAMS_PARENTHESIS.
+ * this handler takes all parenthetical statements within constant or value in:
+ * define(constant, value) of a define statement, and handles them properly
+ */
+
+ function handleDefineParamsParenthesis($word, $pevent)
+ {
+ if (isset($this->p_vars['quote_data']))
+ {
+ $this->p_vars['define_params_data'] .= '"'.$this->p_vars['quote_data'].'"';
+ unset($this->p_vars['quote_data']);
+ }
+ $this->p_vars['define_params_data'] .= $word;
+ $this->checkEventPush( $word, $pevent);
+ $this->checkEventPop( $word, $pevent);
+ }
+
+ /**
+ * handler for CLASS.
+ * this handler parses a class statement
+ */
+
+ function handleClass($word, $pevent)
+ {
+ $this->p_flags['in_class'] = true;
+ $a = $this->checkEventPush( $word, $pevent);
+ if ($a == PARSER_EVENT_DOCBLOCK || $a == PARSER_EVENT_DOCBLOCK_TEMPLATE)
+ {
+ $this->wp->setWhitespace(true);
+ }
+
+ if (!isset($this->p_vars['class'])) $this->p_vars['class'] = false;
+ if (!is_subclass_of($this->p_vars['class'],"parserBase"))
+ {
+ $this->p_vars['class'] = new parserClass;
+ $this->p_vars['class']->setLineNumber($this->wp->linenum);
+ $this->p_vars['class']->setname($word);
+ $this->p_vars['cur_class'] = $word;
+ $this->p_vars['class']->setSourceLocation($this->p_vars['source_location']);
+ }
+
+ if (strtolower($this->p_vars['last_word']) == "extends")
+ {
+ $this->p_vars['class']->setExtends($word);
+ }
+
+ if ($word == "{")
+ {
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_CLASS,$this->p_vars['class']);
+ }
+ //echo $this->wp->getPos() . ": |$word|\n";
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->p_flags['in_class'] = false;
+ // throw an event when class is done
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE,STATE_END_CLASS);
+ $this->p_vars['class'] = false;
+ }
+ }
+
+ /**
+ * handler for VAR.
+ * handle a var $varname = default_value; or var $varname; statement in a class definition
+ */
+
+ function handleVar($word, $pevent)
+ {
+ if (!$this->p_flags['in_var'])
+ {
+ $this->p_vars['linenum'] = $this->wp->linenum;
+ }
+ $this->p_flags['in_var'] = true;
+ //echo $word."\n";
+ $e = $this->checkEventPush( $word, $pevent);
+
+ if (!isset($this->p_vars['var'])) $this->p_vars['var'] = false;
+ if ($word == '=' || $word == ';') $this->p_flags['var_equals'] = true;
+ if (!$this->p_flags['var_equals'])
+ {
+ // if we haven't parsed the = yet, no arrays are possible!
+ if ($e == PARSER_EVENT_ARRAY)
+ {
+ $this->p_flags['arrayinvarname'] = true;
+ $this->p_vars['event_stack']->popEvent();
+ }
+ if (!$e || ($e == PARSER_EVENT_ARRAY))
+ $this->p_vars['varname'] .= $word;
+ }
+
+ if (!$this->p_flags['var_equals'])
+ {
+ if ($word != "/*" && $word != "//" && $word != "#")
+ {
+ $this->p_vars['var'] = new parserVar($this->p_vars['cur_class']);
+ $this->p_vars['var']->setName($this->p_vars['varname']);
+ }
+ }
+ if ($this->p_vars['last_word'] == "=")
+ {
+ if ($word != "/*" && $word != "//" && $word != "#")
+ {
+ $this->p_vars['var']->setValue($word);
+ }
+ }
+ // fix 1202772
+ if (isset($this->p_vars['quote_data']) && ($this->p_vars['last_pevent'] == PARSER_EVENT_QUOTE || $this->p_vars['last_pevent'] == PARSER_EVENT_SINGLEQUOTE))
+ {
+ $this->p_vars['var']->setValue($this->p_vars['quote_data']);
+ unset($this->p_vars['quote_data']);
+ }
+ if ($this->p_vars['last_pevent'] == PARSER_EVENT_ARRAY)
+ {
+ $this->p_vars['var']->setValue($this->p_vars['function_data']);
+ $this->p_vars['function_data'] = false;
+ }
+
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->p_vars['var']->setLineNumber($this->p_vars['linenum']);
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_VAR,$this->p_vars['var']);
+ unset($this->p_vars['var']);
+ $this->p_flags['in_var'] = false;
+ $this->p_flags['var_equals'] = false;
+ $this->p_flags['arrayinvarname'] = false;
+ $this->p_vars['varname'] = '';
+ }
+ }
+
+ /**
+ * handler for QUOTE.
+ * this handler recognizes strings defined with double quotation marks (") and handles them correctly
+ * in any place that they legally appear in php code
+ */
+
+ function handleQuote($word, $pevent)
+ {
+ if ($this->p_flags['reset_quote_data'] === true)
+ {
+ $this->p_flags['reset_quote_data'] = false;
+ $this->p_vars['quote_data'] = "";
+ }
+ $this->checkEventPush( $word, $pevent);
+ if ($word != "\"")
+ {
+ $this->p_vars['quote_data'] .= $word;
+ }
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->p_flags['reset_quote_data'] = true;
+ }
+ }
+
+ /**
+ * handler for SINGLEQUOTE.
+ * this handler recognizes strings defined with single quotation marks (') and handles them correctly
+ * in any place that they legally appear in php code
+ */
+
+ function handleSingleQuote($word, $pevent)
+ {
+ $this->checkEventPush( $word, $pevent);
+ if ($this->checkEventPop($word,$pevent))
+ {
+ if ($this->p_vars['last_word'] != "'")
+ {
+ $this->p_vars['quote_data'] = $this->p_vars['last_word'];
+ } else {
+ $this->p_vars['quote_data'] = "";
+ }
+ }
+ }
+
+ /**
+ * handler for EOFQUOTE.
+ * this handler recognizes strings defined with perl-style <<< EOF quotes, and handles them correctly
+ * in any place that they legally appear in php code
+ *
+ * an example:
+ * <code>$var <<< EOF
+ * blah blah blah
+ * EOF;</code>
+ */
+
+ function handleEOFQuote($word, $pevent)
+ {
+ // echo $this->wp->getPos() . ": word=|$word|\t\t\tlastword=|$this->p_vars['last_word']|\n";
+ if (trim($this->p_vars['last_word']) == "<<<")
+ {
+ // ok we found the keyword
+ //echo "Keyword == $word\n";
+ $this->p_vars['oldtoken'] = $this->tokens[STATE_EOFQUOTE];
+ $this->tokens[STATE_EOFQUOTE] = array($word);
+ }
+ else if ($this->p_vars['last_pevent'] || PARSER_EVENT_EOFQUOTE)
+ {
+ // i don't think anything will ever use this so were not going to set it
+ //$this->p_vars['quote_data'] = $this->p_vars['last_word'];
+ $this->p_vars['event_stack']->popEvent();
+ $this->tokens[STATE_EOFQUOTE] = $this->p_vars['oldtoken'];
+ }
+ }
+ /**#@-*/
+
+ /**
+ * Tells the parser to search for a global variable definition as
+ * defined by a @global type $name tag.
+ *
+ * The parser is fooled into looking for the entire global variable as a
+ * single token by amending the {@link $tokens} array.
+ *
+ * {@source}
+ * @access private
+ * @param string name of global variable as it appears in the source code
+ */
+ function findGlobal($name)
+ {
+ if (!isset($this->p_vars['globaltofind']))
+ {
+ $this->p_vars['globaltofind'] = $name;
+ $this->pushEvent[PARSER_EVENT_PHPCODE][strtolower($name)] = PARSER_EVENT_DEFINE_GLOBAL;
+ $this->tokens[STATE_PHPCODE][] = $name;
+ } else
+ {
+ addError(PDERROR_MULTIPLE_GLOBAL_TAGS,$this->p_vars['globaltofind'],$name);
+ }
+ }
+
+ /**#@+
+ * @access private
+ * @param string token parsed from source
+ * @param integer parser constant from {@link Parser.inc}
+ */
+ /**
+ * handler for PHPCODE.
+ * this handler recognizes the <code><?</code> php processor directive, and begins parsing php code
+ */
+
+ function handlePhpCode($word, $pevent)
+ {
+ $e = $this->checkEventPush( $word, $pevent);
+ if ($e == PARSER_EVENT_DOCBLOCK || $e == PARSER_EVENT_DOCBLOCK_TEMPLATE)
+ {
+ $this->wp->setWhitespace(true);
+ }
+ if (isset($this->p_vars['globaltofind']) && $e)
+ {
+ if ($e != PARSER_EVENT_DEFINE_GLOBAL && $e != PARSER_EVENT_ARRAY && $e != PARSER_EVENT_QUOTE && $e != PARSER_EVENT_SINGLEQUOTE && $e != PARSER_EVENT_COMMENT && $e != PARSER_EVENT_COMMENTBLOCK)
+ {
+ addError(PDERROR_GLOBAL_NOT_FOUND,$this->p_vars['globaltofind']);
+ unset($this->pushEvent[PARSER_EVENT_PHPCODE][strtolower($this->p_vars['globaltofind'])]);
+ foreach($this->tokens[STATE_PHPCODE] as $i => $notme)
+ if ($this->tokens[STATE_PHPCODE][$i] == $this->p_vars['globaltofind'])
+ unset($this->tokens[STATE_PHPCODE][$i]);
+ unset($this->p_vars['globaltofind']);
+ }
+ }
+ }
+
+ /**
+ * handler for global variables
+ */
+ function handleGlobal($word, $pevent)
+ {
+ if (!$this->p_flags['in_global'])
+ {
+ $this->p_vars['linenum'] = $this->wp->linenum;
+ }
+ $this->p_flags['in_global'] = true;
+ $e = $this->checkEventPush($word, $pevent);
+ if ($this->checkEventPop($word, $pevent))
+ {
+ $this->p_flags['in_global'] = false;
+ $a = new parserGlobal;
+ $a->setDataType($this->p_vars['global_type']);
+ $this->p_vars['global_type'] = '';
+ $a->setLineNumber($this->p_vars['linenum']);
+ $a->setName($this->p_vars['globaltofind']);
+ if (isset($this->p_vars['global_val']))
+ $a->setValue(trim($this->p_vars['global_val']));
+ unset($this->p_vars['global_val']);
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_GLOBAL,$a);
+ unset($this->pushEvent[PARSER_EVENT_PHPCODE][strtolower($this->p_vars['globaltofind'])]);
+ foreach($this->tokens[STATE_PHPCODE] as $i => $notme)
+ if ($this->tokens[STATE_PHPCODE][$i] == $this->p_vars['globaltofind'])
+ unset($this->tokens[STATE_PHPCODE][$i]);
+ unset($this->p_vars['globaltofind']);
+ }
+ }
+
+ /**
+ * Handles the stuff after the = in <code>$globalvar = value</code>
+ */
+ function handleGlobalValue($word, $pevent)
+ {
+ if ($this->checkEventPush($word, $pevent))
+ {
+ $this->wp->setWhitespace(false);
+ return;
+ }
+ if (!isset($this->p_vars['global_val'])) $this->p_vars['global_val'] = '';
+ if ($this->p_vars['last_pevent'] == PARSER_EVENT_QUOTE || $this->p_vars['last_pevent'] == PARSER_EVENT_SINGLEQUOTE)
+ {
+ if (!isset($this->p_vars['quote_data'])) $this->p_vars['quote_data'] = '';
+ $this->p_vars['global_val'] .= '"'.$this->p_vars['quote_data'].'"';
+ unset($this->p_vars['quote_data']);
+ $this->p_vars['last_pevent'] = PARSER_EVENT_GLOBAL_VALUE;
+ }
+ if ($this->p_vars['last_pevent'] == PARSER_EVENT_ARRAY)
+ {
+ $this->p_vars['global_val'] .= $this->p_vars['function_data'];
+ $this->p_vars['function_data'] = false;
+ }
+ if ($word != ';')
+ $this->p_vars['global_val'] .= $word;
+ if ($this->checkEventPop($word, $pevent))
+ {
+ $this->wp->setWhitespace(false);
+ $this->wp->backupPos($word);
+ }
+ }
+
+ /**
+ * handler for FUNC_GLOBAL.
+ * this handler recognizes "global $var1, $var2" declarations in a function, and parses them
+ */
+
+ function handleFuncGlobal($word, $pevent)
+ {
+ if ((substr(trim($word),0,1) != '$') && ($word != ',') && ($word != ';'))
+ { // not a global declaration, using a variable named "$global"
+ $this->p_vars['event_stack']->popEvent();
+ return;
+ }
+ if ($this->checkEventPop($word, $pevent))
+ {
+ return;
+ }
+ if (!$this->checkEventPush($word, $pevent))
+ {
+ if ($word == ',')
+ { // another variable
+ $this->p_vars['global_count']++;
+ } else
+ {
+ if (!isset($this->p_vars['globals'][$this->p_vars['global_count']]))
+ $this->p_vars['globals'][$this->p_vars['global_count']] = '';
+ if (!empty($this->p_vars['globals'][$this->p_vars['global_count']])) $this->p_vars['global_count']++;
+ $this->p_vars['globals'][$this->p_vars['global_count']] = trim($word);
+ }
+ }
+ }
+
+ /**
+ * handler for STATIC_VAR.
+ * this handler recognizes "static $var1, $var2 = 6" declarations in a function, and parses them
+ */
+
+ function handleStaticVar($word, $pevent)
+ {
+ if ($this->checkEventPop($word, $pevent))
+ {
+ $this->p_vars['static_count']++;
+ return;
+ }
+ if (!$this->checkEventPush($word, $pevent))
+ {
+ if ($word == ',')
+ {
+ $this->p_vars['static_count']++;
+ return;
+ }
+ if (!isset($this->p_vars['statics'][$this->p_vars['static_count']]))
+ $this->p_vars['statics'][$this->p_vars['static_count']] = '';
+ if (!empty($this->p_vars['statics'][$this->p_vars['static_count']])) $this->p_vars['static_count']++;
+ $this->p_vars['statics'][$this->p_vars['static_count']] = trim($word);
+ }
+ }
+
+ /**
+ * handler for STATIC_VAR_VALUE.
+ * this handler parses the 6 in "static $var1, $var2 = 6"
+ */
+
+ function handleStaticValue($word, $pevent)
+ {
+ if ($this->checkEventPush($word, $pevent))
+ {
+ return;
+ }
+ if (!isset($this->p_vars['static_val'][$this->p_vars['static_count']])) $this->p_vars['static_val'][$this->p_vars['static_count']] = '';
+ if ($this->p_vars['last_pevent'] == PARSER_EVENT_QUOTE || $this->p_vars['last_pevent'] == PARSER_EVENT_SINGLEQUOTE)
+ {
+ $this->p_vars['static_val'][$this->p_vars['static_count']] .= '"'.$this->p_vars['quote_data'].'"';
+ unset($this->p_vars['quote_data']);
+ }
+ if ($this->p_vars['last_pevent'] == PARSER_EVENT_ARRAY)
+ {
+ $this->p_vars['static_val'][$this->p_vars['static_count']] .= $this->p_vars['function_data'];
+ $this->p_vars['function_data'] = false;
+ }
+ if ($this->checkEventPop($word, $pevent))
+ {
+ $this->p_vars['static_val'][$this->p_vars['static_count']] = trim($this->p_vars['static_val'][$this->p_vars['static_count']]);
+ $this->wp->backupPos($word);
+ return;
+ } else $this->p_vars['static_val'][$this->p_vars['static_count']] .= $word;
+ }
+
+ /**
+ * handler for FUNCTION.
+ * this handler recognizes function declarations, and parses them. The body
+ * of the function is parsed by handleLogicBlock()
+ * @see handleLogicBlock()
+ */
+
+ function handleFunction($word, $pevent)
+ {
+ if ($e = $this->checkEventPush( $word, $pevent))
+ {
+ if ($e == PARSER_EVENT_COMMENT || $e == PARSER_EVENT_COMMENTBLOCK) return;
+ }
+
+ if (!isset($this->p_vars['func'])) $this->p_vars['func'] = false;
+ if (! is_subclass_of($this->p_vars['func'],"parserBase"))
+ {
+ $this->p_vars['globals'] = array();
+ $this->p_vars['global_count'] = 0;
+ if ($this->p_flags['in_class'])
+ $this->p_vars['func'] = new parserMethod($this->p_vars['cur_class']);
+ else
+ $this->p_vars['func'] = new parserFunction;
+ $this->p_vars['func']->setLineNumber($this->wp->linenum);
+ if (trim($word) != '&')
+ $this->p_vars['func']->setName(trim($word));
+ else
+ $this->p_vars['func']->setReturnsReference();
+ } else
+ {
+ if ($this->p_vars['func']->getReturnsReference())
+ {
+ if ($this->p_vars['last_word'] == '&')
+ {
+ $this->p_vars['func']->setName(trim($word));
+ }
+ }
+ }
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->p_vars['func']->addGlobals($this->p_vars['globals']);
+ $this->p_vars['func']->addStatics($this->p_vars['statics'],$this->p_vars['static_val']);
+ $this->p_vars['globals'] = array();
+ $this->p_vars['global_count'] = 0;
+ if ($this->p_flags['getting_source'])
+ {
+ $x = $this->wp->getSource();
+ $this->p_vars['func']->addSource($x);
+ $this->p_flags['get_source'] = false;
+ $this->p_flags['getting_source'] = false;
+ }
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_FUNCTION,$this->p_vars['func']);
+ $this->p_vars['func'] = false;
+ }
+ }
+
+ /**#@-*/
+ /**
+ * Helper function for {@link handleFunctionParams()}
+ *
+ * This function adds a new parameter to the parameter list
+ * @access private
+ * @param string
+ */
+ function endFunctionParam($word)
+ {
+ if (isset($this->p_vars['quote_data']) && ($this->p_vars['last_pevent'] == PARSER_EVENT_SINGLEQUOTE))
+ {
+ $this->p_vars['function_data'] .= "'".$this->p_vars['quote_data']."'";
+ unset($this->p_vars['quote_data']);
+ }
+ if (isset($this->p_vars['quote_data']) && ($this->p_vars['quote_data'] != '') && ($this->p_vars['last_pevent'] == PARSER_EVENT_QUOTE))
+ {
+ $this->p_vars['function_data'] .= '"'.$this->p_vars['quote_data'].'"';
+ unset($this->p_vars['quote_data']);
+ }
+ if (isset($this->p_vars['function_param']))
+ {
+ $this->p_vars['func']->addParam($this->p_vars['function_param'],$this->p_vars['function_data'], $this->p_flags['funcparam_val']);
+ unset($this->p_vars['function_param']);
+ $this->p_vars['function_data'] = '';
+ $this->p_flags['funcparam_val'] = false;
+ }
+ }
+ /**#@+
+ * @access private
+ * @param string token parsed from source
+ * @param integer parser constant from {@link Parser.inc}
+ */
+ /**
+ * handler for FUNCTION_PARAMS.
+ * this handler recognizes the parameters of a function within parentheses like function(param, param = default_value)
+ * and parses them
+ * @see endFunctionParam()
+ */
+
+ function handleFunctionParams($word, $pevent)
+ {
+ //echo $this->wp->getPos() . ": word=|$word|\t\t\tlastword=|".$this->p_vars['last_word']."|\n";
+ //echo "function_param = '".$this->p_vars['function_param']."'\n";
+ //echo "function_data = '".$this->p_vars['function_data']."'\n";
+ $e1 = $this->checkEventPush( $word, $pevent);
+
+ if (!$e1)
+ {
+ if ($word == ',' || $this->checkEventPop($word,$pevent))
+ {
+ $this->endFunctionParam($word);
+ } elseif ($word == '=')
+ {
+ $this->p_flags['funcparam_val'] = true;
+ } else
+ {
+ if ($this->p_flags['funcparam_val'])
+ {
+ if (isset($this->p_vars['quote_data']) && ($this->p_vars['last_pevent'] == PARSER_EVENT_SINGLEQUOTE))
+ {
+ $this->p_vars['function_data'] .= "'".$this->p_vars['quote_data']."'";
+ unset($this->p_vars['quote_data']);
+ }
+ if (isset($this->p_vars['quote_data']) && ($this->p_vars['last_pevent'] == PARSER_EVENT_QUOTE))
+ {
+ $this->p_vars['function_data'] .= '"'.$this->p_vars['quote_data'].'"';
+ unset($this->p_vars['quote_data']);
+ }
+ $this->p_vars['function_data'] .= $word;
+ } else
+ {
+ $this->p_vars['function_param'] = $word;
+ }
+ }
+ }
+ }
+
+
+ /**
+ * javadoc-desc-compliant handler for DOCBLOCK.
+ * this handler recognizes @tags in DocBlocks and parses them for display.
+ * It also parses out unknown tags into their own array for use by the docblock
+ */
+
+ function JavaDochandleDocblock($word, $pevent)
+ {
+ $e1 = $this->checkEventPush( $word, $pevent);
+ if (!isset($this->p_vars[$this->p_vars['docblock_type']]) || !$this->p_vars[$this->p_vars['docblock_type']])
+ {
+ $this->p_vars[$this->p_vars['docblock_type']] = new parserDocBlock();
+ $this->p_vars['returntype'] = false;
+ $this->p_vars['vartype'] = false;
+ $this->p_flags['startdocblock'] = true;
+ $this->p_flags['valid_newline'] = true;
+ $this->p_flags['startline'] = true;
+ $this->p_flags['newline'] = true;
+ $this->p_flags['in_desc'] = true;
+ $this->p_flags['in_tag'] = false;
+ $this->p_flags['useperiod'] = false;
+ $this->p_vars['line'] = array();
+ $this->p_vars['linecount'] = 0;
+ }
+ $e = $this->checkEventPop( $word, $pevent);
+ if (!$e1 && !$e)
+ {
+ if ($this->p_flags['in_desc']) $this->JavaDochandleDesc($word, $pevent);
+ else $this->handleTags($word, $pevent);
+ }
+ if ($e)
+ {
+ if (!isset($this->p_vars['periodline'])) $this->p_vars['periodline'] = 0;
+ if ($this->p_vars['periodline'] > 3)
+ {
+ $this->p_flags['useperiod'] = false;
+ }
+
+ $this->p_vars['docblock_desc'] = new parserDesc;
+// echo "i = ".$this->p_vars['periodline']."; i < " . count($this->p_vars['line']) . "\n";
+ if ($this->p_vars['docblock_type'] == 'docblock')
+ {
+ if (isset($this->p_vars['docblock_template']))
+ {
+ // copy template values if not overridden
+ if (!$this->p_vars['docblock']->getExplicitPackage())
+ {
+ if ($p = $this->p_vars['docblock_template']->getKeyword('package'))
+ {
+ $this->p_vars['docblock']->addKeyword('package',$p);
+ $this->p_vars['docblock']->setExplicitPackage();
+ }
+ if ($p = $this->p_vars['docblock_template']->getKeyword('category'))
+ {
+ $this->p_vars['docblock']->addKeyword('category',$p);
+ $this->p_vars['docblock']->setExplicitCategory();
+ }
+ if ($p = $this->p_vars['docblock_template']->getKeyword('subpackage'))
+ {
+ $this->p_vars['docblock']->addKeyword('subpackage',$p);
+ }
+ }
+ $tags = $this->p_vars['docblock_template']->listTags();
+ foreach($tags as $tag)
+ {
+ $this->p_vars['docblock']->addKeyword($tag->keyword,$tag->value);
+ }
+ $this->p_vars['docblock_desc']->add($this->p_vars['docblock_template']->desc);
+ if (!count($this->p_vars['docblock']->params)) $this->p_vars['docblock']->params = $this->p_vars['docblock_template']->params;
+ }
+ if ($a = strpos(trim($this->p_vars['shortdesc']),'<p>') === 0)
+ $this->p_vars['shortdesc'] = substr($this->p_vars['shortdesc'],strpos($this->p_vars['shortdesc'],'<p>') + 4);
+ $this->p_vars[$this->p_vars['docblock_type']]->setShortDesc($this->p_vars['shortdesc']);
+ }
+ for($i = 0; $i < count($this->p_vars['line']); $i++)
+ {
+ // the line will not be set if it doesn't start with a *
+ if (isset($this->p_vars['line'][$i]))
+ $this->p_vars['docblock_desc']->add($this->p_vars['line'][$i]);
+ }
+
+
+ $this->p_vars[$this->p_vars['docblock_type']]->setDesc($this->p_vars['docblock_desc']);
+ unset($this->p_vars['docblock_desc']);
+// var_dump($this->p_vars[$this->p_vars['docblock_type']]);
+// exit;
+ if ($this->p_vars['docblock_type'] == 'docblock')
+ {
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_DOCBLOCK,$this->p_vars[$this->p_vars['docblock_type']]);
+ unset($this->p_vars[$this->p_vars['docblock_type']]);
+ $this->p_vars[$this->p_vars['docblock_type']] = new parserDocBlock();
+ }
+ $this->p_flags['in_desc'] = true;
+ $this->p_flags['in_tag'] = false;
+ $this->p_flags['useperiod'] = false;
+ $this->p_vars['line'] = array();
+ $this->p_vars['linecount'] = 0;
+ $this->p_flags['start_docblock'] = true;
+ $this->p_flags['valid_newline'] = true;
+ $this->wp->setWhitespace(false);
+ }
+ }
+
+ /**
+ * handler for DOCKEYWORD_DESC.
+ * this handler parses the short and long description of a dockeyword
+ */
+
+ function JavaDochandleDesc($word, $pevent)
+ {
+ if ($this->p_flags['valid_newline'])
+ {
+ if ($word == '@' && $this->p_flags['startline'])
+ {
+ return $this->handleTag($word, $pevent);
+ }
+ if (!isset($this->p_vars['line'][$this->p_vars['linecount']]))
+ {
+ $this->p_vars['line'][$this->p_vars['linecount']] = new parserStringWithInlineTags;
+ }
+ if ($this->p_vars['last_word'] == "." && $this->p_flags['useperiod'] == false)
+ {
+ $this->p_vars['periodline'] = $this->p_vars['linecount'];
+ $this->p_vars['shortdesc'] = new parserDesc;
+ for($i = 0; ($i <= $this->p_vars['periodline']) && ($i < count($this->p_vars['line'])); $i++)
+ {
+ if (isset($this->p_vars['line'][$i]))
+ $this->p_vars['shortdesc']->add($this->p_vars['line'][$i]);
+ }
+ $this->p_flags['useperiod'] = true;
+ }
+ $this->p_vars['line'][$this->p_vars['linecount']]->add($word);
+// debug("DESC $word");
+ }
+ $this->handleCR($word);
+ }
+
+ /**
+ * handler for DOCBLOCK.
+ * this handler recognizes @tags in DocBlocks and parses them for display.
+ * It also parses out unknown tags into their own array for use by the docblock
+ */
+
+ function BetterhandleDocblock($word, $pevent)
+ {
+ $e1 = $this->checkEventPush( $word, $pevent);
+ if (!$this->wp->returnWhiteSpace)
+ {
+ addErrorDie(PDERROR_NEED_WHITESPACE);
+ }
+ if (!isset($this->p_vars[$this->p_vars['docblock_type']]) || !$this->p_vars[$this->p_vars['docblock_type']])
+ {
+ $this->p_vars[$this->p_vars['docblock_type']] = new parserDocBlock();
+ $this->p_vars['returntype'] = false;
+ $this->p_vars['vartype'] = false;
+ $this->p_flags['startdocblock'] = true;
+ $this->p_flags['valid_newline'] = true;
+ $this->p_flags['startline'] = true;
+ $this->p_flags['newline'] = true;
+ $this->p_flags['in_desc'] = true;
+ $this->p_flags['in_tag'] = false;
+ $this->p_flags['useperiod'] = false;
+ $this->p_vars['line'] = array();
+ $this->p_vars['linecount'] = 0;
+ }
+ $e = $this->checkEventPop( $word, $pevent);
+ if (!$e1 && !$e)
+ {
+ if ($this->p_flags['in_desc']) $this->handleDesc($word, $pevent);
+ else $this->handleTags($word, $pevent);
+ }
+ if ($e)
+ {
+ if (!isset($this->p_vars['periodline'])) $this->p_vars['periodline'] = 0;
+ if ($this->p_vars['periodline'] > 3)
+ {
+ $this->p_flags['useperiod'] = false;
+ } else
+ {
+ for($i = 0; $i < $this->p_vars['periodline']; $i++)
+ {
+ if (isset($this->p_vars['line'][$i]))
+ {
+ if ($this->p_vars['line'][$i]->trimmedStrlen() == 0 && isset($this->p_vars['line'][$i - 1]) && $this->p_vars['line'][$i - 1]->trimmedStrlen())
+ {
+ $this->p_vars['periodline'] = $i;
+ }
+ }
+ }
+ }
+ // figure out the shortdesc
+ if ($this->p_flags['useperiod'] === false)
+ {
+ // use the first non blank line for short desc
+ for($i = 0; $i < count($this->p_vars['line']); $i++)
+ {
+ if (!isset($this->p_vars['line'][$i]))
+ $this->p_vars['line'][$i] = new parserStringWithInlineTags;
+ if ($this->p_vars['line'][$i]->trimmedStrlen() > 0)
+ {
+ $this->p_vars['periodline'] = $i;
+ $i = count($this->p_vars['line']);
+ }
+ }
+
+ // check to see if we are going to use a blank line to end the shortdesc
+ // this can only be in the first 4 lines
+ if (count($this->p_vars['line']) > 4)
+ {
+ $max = 4;
+ } else {
+ $max = count($this->p_vars['line']);
+ }
+
+ for($i = $this->p_vars['periodline']; $i < $max; $i++)
+ {
+ if (isset($this->p_vars['line'][$i]))
+ if ($this->p_vars['line'][$i]->trimmedStrlen() == 0)
+ {
+ $this->p_vars['periodline'] = $i;
+ $i = $max;
+ }
+ }
+ }
+
+ if ($this->p_vars['docblock_type'] == 'docblock')
+ {
+ $this->p_vars['shortdesc'] = new parserDesc;
+ for($i = 0; ($i <= $this->p_vars['periodline']) && ($i < count($this->p_vars['line'])); $i++)
+ {
+ if (isset($this->p_vars['line'][$i]))
+ $this->p_vars['shortdesc']->add($this->p_vars['line'][$i]);
+ }
+ $this->p_vars['periodline']++;
+
+ $this->p_vars['docblock_desc'] = new parserDesc;
+ if (isset($this->p_vars['docblock_template']))
+ {
+ // copy template values if not overridden
+ if (!$this->p_vars['docblock']->getExplicitPackage())
+ {
+ if ($p = $this->p_vars['docblock_template']->getKeyword('package'))
+ {
+ $this->p_vars['docblock']->addKeyword('package',$p);
+ $this->p_vars['docblock']->setExplicitPackage();
+ }
+ if ($p = $this->p_vars['docblock_template']->getKeyword('category'))
+ {
+ $this->p_vars['docblock']->addKeyword('category',$p);
+ $this->p_vars['docblock']->setExplicitCategory();
+ }
+ if ($p = $this->p_vars['docblock_template']->getKeyword('subpackage'))
+ {
+ $this->p_vars['docblock']->addKeyword('subpackage',$p);
+ }
+ }
+ $tags = $this->p_vars['docblock_template']->listTags();
+ foreach($tags as $tag)
+ {
+ $this->p_vars['docblock']->addKeyword($tag->keyword,$tag->value);
+ }
+ if (!count($this->p_vars['docblock']->params)) $this->p_vars['docblock']->params = $this->p_vars['docblock_template']->params;
+ $this->p_vars['docblock_desc']->add($this->p_vars['docblock_template']->desc);
+ }
+ // echo "i = ".$this->p_vars['periodline']."; i < " . count($this->p_vars['line']) . "\n";
+ for($i = $this->p_vars['periodline']; $i < count($this->p_vars['line']); $i++)
+ {
+ // the line will not be set if it doesn't start with a *
+ if (isset($this->p_vars['line'][$i]))
+ $this->p_vars['docblock_desc']->add($this->p_vars['line'][$i]);
+ }
+ } else
+ {
+ $this->p_vars['shortdesc'] = new parserDesc;
+ for($i = 0; ($i <= $this->p_vars['periodline']) && ($i < count($this->p_vars['line'])); $i++)
+ {
+ if (isset($this->p_vars['line'][$i]))
+ $this->p_vars['shortdesc']->add($this->p_vars['line'][$i]);
+ }
+ $this->p_vars['periodline']++;
+
+ $this->p_vars['docblock_desc'] = new parserDesc;
+ for($i=$this->p_vars['periodline']; $i < count($this->p_vars['line']); $i++)
+ {
+ if (isset($this->p_vars['line'][$i]))
+ $this->p_vars['docblock_desc']->add($this->p_vars['line'][$i]);
+ }
+ }
+
+
+ $this->p_vars[$this->p_vars['docblock_type']]->setShortDesc($this->p_vars['shortdesc']);
+ $this->p_vars[$this->p_vars['docblock_type']]->setDesc($this->p_vars['docblock_desc']);
+ unset($this->p_vars['docblock_desc']);
+// var_dump($this->p_vars[$this->p_vars['docblock_type']]);
+// exit;
+ if ($this->p_vars['docblock_type'] == 'docblock')
+ {
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_DOCBLOCK,$this->p_vars[$this->p_vars['docblock_type']]);
+ unset($this->p_vars[$this->p_vars['docblock_type']]);
+ $this->p_vars[$this->p_vars['docblock_type']] = new parserDocBlock();
+ } else
+ {
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_DOCBLOCK_TEMPLATE,$this->p_vars[$this->p_vars['docblock_type']]);
+ }
+ $this->p_flags['in_desc'] = true;
+ $this->p_flags['in_tag'] = false;
+ $this->p_flags['useperiod'] = false;
+ $this->p_vars['line'] = array();
+ $this->p_vars['linecount'] = 0;
+ $this->p_flags['start_docblock'] = true;
+ $this->p_flags['valid_newline'] = true;
+ $this->wp->setWhitespace(false);
+ $this->p_vars['docblock_type'] = 'docblock';
+ }
+ }
+
+ /**
+ * Handles docblock templates
+ * @tutorial phpDocumentor.howto.pkg#basics.docblocktemplate
+ */
+ function handleDocBlockTemplate($word, $pevent)
+ {
+ $this->p_vars['docblock_type'] = 'docblock_template';
+ $this->p_vars['event_stack']->popEvent();
+ $this->p_vars['event_stack']->pushEvent(PARSER_EVENT_DOCBLOCK);
+ // fool the docblock handler into thinking everything is totally normal
+ $this->p_vars['last_word'] = '/**';
+ $pevent = PARSER_EVENT_DOCBLOCK;
+ $this->BetterhandleDocBlock($word, $pevent);
+ }
+
+ /**
+ * Handles closing docblock templates /**#@-* /
+ * @tutorial phpDocumentor.howto.pkg#basics.docblocktemplate
+ */
+ function handleEndDocBlockTemplate($word, $pevent)
+ {
+ unset($this->p_vars['docblock_template']);
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE,PHPDOCUMENTOR_EVENT_END_DOCBLOCK_TEMPLATE);
+ $this->p_vars['event_stack']->popEvent();
+ }
+ /**#@-*/
+ /**
+ * Handles a new line in a DocBlock
+ * @param string token containing a newline \n
+ * @access private
+ */
+ function handleCR($word)
+ {
+ $this->laststart = $this->p_flags['startline'];
+ if ($word == "\n" || $word == ".\n")
+ {
+ $this->p_flags['start_docblock'] = false;
+ $this->p_flags['newline'] = true;
+ $this->p_flags['valid_newline'] = false;
+ if ($this->p_flags['in_desc'] && !$this->p_flags['useperiod'])
+ {
+ if ($word == ".\n")
+ {
+ $this->p_flags['useperiod'] = true;
+ $this->p_vars['periodline'] = $this->p_vars['linecount'];
+ }
+ }
+ } else
+ {
+ if ($this->p_flags['valid_newline'] && strlen(trim($word)))
+ {
+ $this->p_flags['startline'] = false;
+ }
+ if ($this->p_flags['newline'] && ($word == '*' || $this->p_flags['start_docblock']))
+ {
+ $this->p_flags['newline'] = false;
+ $this->p_flags['valid_newline'] = true;
+ if (!$this->p_flags['start_docblock'])
+ $this->p_vars['linecount']++;
+ $this->p_flags['startline'] = true;
+ $justset = true;
+// debug('valid newline');
+ }
+ }
+ }
+
+ /**
+ * handler for DOCKEYWORD_DESC.
+ * this handler parses the short and long description of a dockeyword
+ * @access private
+ */
+
+ function handleDesc($word, $pevent)
+ {
+// echo "|$word|\n";
+ if ($this->p_flags['valid_newline'])
+ {
+ if ($word == '@' && $this->p_flags['startline'])
+ {
+ return $this->handleTag($word, $pevent);
+ }
+ if ($this->p_vars['last_word'] == ". " || $this->p_vars['last_word'] == ".\t")
+ {
+ $this->p_flags['useperiod'] = true;
+ $this->p_vars['periodline'] = $this->p_vars['linecount'];
+ $this->p_vars['linecount']++;
+ }
+ if (!isset($this->p_vars['line'][$this->p_vars['linecount']]))
+ {
+ $this->p_vars['line'][$this->p_vars['linecount']] = new parserStringWithInlineTags;
+ }
+ if ($this->p_flags['startline'])
+ {
+ if ($word[0] == ' ') $word = substr($word,1);
+// $word = ltrim($word," \t");
+ }
+ if ($word != '') $this->p_vars['line'][$this->p_vars['linecount']]->add($word);
+// debug("DESC $word");
+ }
+ $this->handleCR($word);
+ }
+
+ /**#@+
+ * @access private
+ * @param string token parsed from source
+ * @param integer parser constant from {@link Parser.inc}
+ */
+ /**
+ * handler for DOCKEYWORD_TAGS.
+ * this handler recognizes @tags in DocBlocks and parses them for display
+ * I think this may be unused. We'll delete from 1.1 if so
+ */
+ function handleTags($word, $pevent)
+ {
+ if ($this->p_flags['valid_newline'])
+ {
+// debug("TAGS $word");
+ }
+ $this->handleCR($word);
+ }
+
+ /**
+ * handler for DOCKEYWORD.
+ * this handler recognizes @tags in DocBlocks and parses them for display
+ */
+ function handleTag($word, $pevent)
+ {
+ if ($this->p_flags['in_desc'] && !$this->p_flags['valid_newline'])
+ {
+ $this->p_vars['event_stack']->popEvent();
+ return $this->handleDesc($word, $pevent);
+ }
+// if ($this->p_vars['last_word'] == '@') fancy_debug('here'.$word,$this->p_flags['startline'],$this->p_flags['in_tag']);
+ if ($this->p_vars['tagname'] == 'author')
+ {
+ if ($word == '<')
+ {
+ $this->p_vars['event_stack']->pushEvent(PARSER_EVENT_DOCKEYWORD_EMAIL);
+ return $this->handleDockeywordEmail($word, $pevent);
+ }
+ }
+ if ($this->checkEventPush( $word, $pevent)) return;
+ if ($this->p_vars['last_word'] == '@' && !$this->p_flags['startline'] && $this->p_flags['in_desc'])
+ {
+ // fix 1203445
+ if (!isset($this->p_vars['line'][$this->p_vars['linecount']]))
+ {
+ $this->p_vars['line'][$this->p_vars['linecount']] = new parserStringWithInlineTags;
+ }
+ $this->p_vars['event_stack']->popEvent();
+ $this->p_vars['line'][$this->p_vars['linecount']]->add('@');
+ return $this->handleDesc($word, $pevent);
+ } elseif($this->p_vars['last_word'] == '@' && !strlen(trim($word)) && empty($this->p_vars['tagname']) && $this->p_flags['in_desc'])
+ {
+ // fix 1203445
+ if (!isset($this->p_vars['line'][$this->p_vars['linecount']]))
+ {
+ $this->p_vars['line'][$this->p_vars['linecount']] = new parserStringWithInlineTags;
+ }
+ $pevent = $this->p_vars['event_stack']->popEvent();
+ $this->p_vars['line'][$this->p_vars['linecount']]->add('@');
+ return $this->handleDesc($word, $pevent);
+ }
+ if ($word == '@' && $this->p_flags['startline'] && $this->p_flags['in_tag'])
+ {
+ $this->wp->backupPos($word);
+ $white = $this->wp->returnWhiteSpace;
+ $this->wp->setWhitespace(true);
+ $word1 = $this->wp->getWord();
+ $this->wp->backupPos($word1);
+ if (strlen(trim($word1)))
+ {
+ $this->endTag();
+ }
+ $this->wp->getWord();
+ $this->wp->setWhitespace($white);
+ }
+ $this->p_flags['in_tag'] = true;
+ $e = $this->checkEventPop($word, $pevent);
+ if (!$e)
+ {
+ if ($this->p_flags['valid_newline'])
+ {
+ if (($this->p_flags['startline'] || $this->laststart) && $word != '@')
+ {
+ if ($this->p_vars['last_word'] == '@')
+ {
+// debug("TAGSTART $word");
+ $this->p_flags['in_tag'] = true;
+ $this->p_vars['tagname'] = $word;
+ $this->p_flags['startline'] = false;
+ $this->p_vars['tag_value'] = new parserStringWithInlineTags;
+ } else
+ {
+// debug("TAG1 $word");
+ if (isset($this->tagHandlers[$this->p_vars['tagname']]))
+ $handler = $this->tagHandlers[$this->p_vars['tagname']];
+ else $handler = $this->tagHandlers['*'];
+ $this->$handler($word);
+ }
+ } else
+ {
+ if (empty($this->p_vars['tagname']))
+ {
+ if ($this->p_flags['in_desc'])
+ {
+ $this->p_flags['in_tag'] = false;
+ // fix 1203445
+ if (!isset($this->p_vars['line'][$this->p_vars['linecount']]))
+ {
+ $this->p_vars['line'][$this->p_vars['linecount']] =
+ new parserStringWithInlineTags;
+ }
+ $this->p_vars['line'][$this->p_vars['linecount']]->add('@');
+ $this->p_vars['event_stack']->popEvent();
+ $this->handleCR($word);
+ return $this->handleDesc($word, $pevent);
+ }
+ }
+// debug("TAG2 $word");
+ if (isset($this->tagHandlers[$this->p_vars['tagname']]))
+ $handler = $this->tagHandlers[$this->p_vars['tagname']];
+ else $handler = $this->tagHandlers['*'];
+ $this->$handler($word);
+ }
+ }
+ $this->handleCR($word);
+ }
+ $this->p_flags['in_desc'] = false;
+ if ($e)
+ {
+ $this->endTag();
+ $this->wp->setWhitespace(false);
+ // walk back a word
+ $this->wp->backupPos($word);
+ $this->wp->setWhitespace(true);
+ }
+ }
+ /**#@-*/
+ /**
+ * Called to clean up at the end of parsing a @tag in a docblock
+ */
+ function endTag()
+ {
+ if (isset($this->tagHandlers[$this->p_vars['tagname']]))
+ $handler = $this->tagHandlers[$this->p_vars['tagname']];
+ else $handler = $this->tagHandlers['*'];
+ $this->$handler(false);
+ $this->p_vars['tagname'] = '';
+ $this->p_flags['startline'] = true;
+// debug("ENDTAG");
+ }
+
+ /**#@+
+ * Tag Handlers
+ * @param string
+ */
+ /**
+ * Handles all standard tags that only have a description
+ */
+ function defaultTagHandler($word)
+ {
+ if ($word !== false)
+ {
+ $this->p_vars['tag_value']->add($word);
+ } else
+ {
+ $this->p_vars[$this->p_vars['docblock_type']]->addKeyword($this->p_vars['tagname'],$this->p_vars['tag_value']);
+ }
+ }
+
+ /**
+ * Handles tags like '@filesource' that only work in PHP 4.3.0+
+ */
+ function invalidTagHandler($word)
+ {
+ if ($word === false)
+ {
+ addError(PDERROR_TAG_NOT_HANDLED,$this->p_vars['tagname']);
+ }
+ }
+
+ /**
+ * handles @package
+ * @tutorial tags.package.pkg
+ */
+ function packageTagHandler($word)
+ {
+ if ($word !== false)
+ {
+ $this->p_vars['tag_value']->add($word);
+ } else
+ {
+ $this->p_vars[$this->p_vars['docblock_type']]->addKeyword($this->p_vars['tagname'],$this->p_vars['tag_value']);
+ $this->p_vars[$this->p_vars['docblock_type']]->setExplicitPackage();
+ }
+ }
+
+ /**
+ * handles @example
+ * @tutorial tags.example.pkg
+ */
+ function exampleTagHandler($word)
+ {
+ if ($word !== false)
+ {
+ $this->p_vars['tag_value']->add($word);
+ } else
+ {
+ $this->p_vars[$this->p_vars['docblock_type']]->addExample($this->p_vars['tag_value'], $this->p_vars['parsepath']);
+ }
+ }
+
+ /**
+ * handles @category
+ * @tutorial tags.category.pkg
+ */
+ function categoryTagHandler($word)
+ {
+ if ($word !== false)
+ {
+ $this->p_vars['tag_value']->add($word);
+ } else
+ {
+ $this->p_vars[$this->p_vars['docblock_type']]->addKeyword($this->p_vars['tagname'],$this->p_vars['tag_value']);
+ $this->p_vars[$this->p_vars['docblock_type']]->setExplicitCategory();
+ }
+ }
+
+ /**
+ * handles @global
+ * @tutorial tags.global.pkg
+ */
+ function globalTagHandler($word)
+ {
+ if ($word !== false)
+ {
+ // no data yet
+ $a = trim($this->p_vars['tag_value']->getString());
+ if (empty($a))
+ {
+ // not an empty word
+ if (trim($word) != '')
+ {
+ if (!empty($this->p_vars['global_type']))
+ {
+ if (!$this->p_flags['define_global'] && !$this->p_flags['function_global'])
+ {
+ // @global type $GLOBALVARNAME ?
+ if (substr($word,0,1) == '$')
+ {
+ $this->p_flags['define_global'] = true;
+ $this->p_flags['function_global'] = false;
+ $this->p_vars['find_global'] = $word;
+ } else
+ { // function @global type description
+ $this->p_flags['function_global'] = true;
+ $this->p_flags['define_global'] = false;
+ $this->p_vars['tag_value']->add($word);
+ }
+ } else
+ {
+ if ($this->p_flags['define_global'])
+ {
+ $this->p_vars['find_global'] .= $word;
+ } elseif($this->p_flags['function_global'])
+ {
+ // description, to be added to the tag
+ $this->p_vars['tag_value']->add($word);
+ }
+ }
+ } else
+ {
+ $this->p_vars['global_type'] = $word;
+ }
+ } else $this->p_vars['tag_value']->add($word); // add whitespace to the tag description
+ } else
+ { // tag_value has data, must be a function @global
+ $this->p_vars['tag_value']->add($word);
+ }
+ } else
+ { // endtag
+ if ($this->p_flags['define_global'])
+ {
+ $this->findGlobal($this->p_vars['find_global']);
+ }
+ elseif ($this->p_flags['function_global'])
+ {
+ $this->p_vars[$this->p_vars['docblock_type']]->addFuncGlobal($this->p_vars['global_type'],$this->p_vars['tag_value']);
+ $this->p_vars['global_type'] = '';
+ }
+ else
+ {
+ addError(PDERROR_MALFORMED_GLOBAL_TAG);
+ }
+ $this->p_vars['find_global'] = '';
+ $this->p_flags['define_global'] = false;
+ $this->p_flags['function_global'] = false;
+ }
+ }
+
+ /**
+ * handles @staticvar
+ * @tutorial tags.staticvar.pkg
+ */
+ function staticvarTagHandler($word)
+ {
+ if ($word !== false)
+ {
+ if (!$this->p_vars['returntype']) $this->p_vars['returntype'] = trim($word);
+ else
+ {
+ if (!$this->p_vars['paramname'])
+ {
+ if (substr(trim($word),0,1) == "$")
+ $this->p_vars['paramname'] = trim($word);
+ else $this->p_vars['tag_value']->add($word);
+ } else
+ {
+ if (0)//strtolower($this->p_vars['paramtype']) == 'object')
+ {
+ if (strlen(trim($word)))
+ $this->p_vars['paramname'] = trim($word);
+ } else $this->p_vars['tag_value']->add($word);
+ }
+ }
+ } else
+ {
+ if (!$this->p_vars['paramname'])
+ $this->p_vars[$this->p_vars['docblock_type']]->addStaticVar(null,$this->p_vars['returntype'],$this->p_vars['tag_value']);
+ else
+ $this->p_vars[$this->p_vars['docblock_type']]->addStaticVar($this->p_vars['paramname'],$this->p_vars['returntype'],$this->p_vars['tag_value']);
+ $this->p_vars['paramname'] = false;
+ $this->p_vars['returntype'] = false;
+ }
+ }
+
+ /**
+ * handles @uses
+ * @tutorial tags.uses.pkg
+ */
+ function usesTagHandler($word)
+ {
+ if ($word !== false)
+ {
+ if (!$this->p_vars['seelement']) $this->p_vars['seelement'] = trim($word);
+ else
+ {
+ $this->p_vars['tag_value']->add($word);
+ }
+ } else
+ {
+ $see = new parserStringWithInlineTags;
+ $see->add($this->p_vars['seelement']);
+ $this->p_vars[$this->p_vars['docblock_type']]->addUses($see,$this->p_vars['tag_value']);
+ $this->p_vars['seelement'] = false;
+ }
+ }
+
+ /**
+ * handles @param
+ * @tutorial tags.param.pkg
+ */
+ function paramTagHandler($word)
+ {
+ if ($word !== false)
+ {
+ if (!$this->p_vars['returntype']) $this->p_vars['returntype'] = trim($word);
+ else
+ {
+ if (!$this->p_vars['paramname'])
+ {
+ if (substr(trim($word),0,1) == "$" || substr(trim($word),0,2) == "&$")
+ $this->p_vars['paramname'] = trim($word);
+ else $this->p_vars['tag_value']->add($word);
+ } else
+ {
+ if (0)//strtolower($this->p_vars['paramtype']) == 'object')
+ {
+ if (strlen(trim($word)))
+ $this->p_vars['paramname'] = trim($word);
+ } else $this->p_vars['tag_value']->add($word);
+ }
+ }
+ } else
+ {
+ if (!$this->p_vars['paramname'])
+ $this->p_vars[$this->p_vars['docblock_type']]->addParam(null,$this->p_vars['returntype'],$this->p_vars['tag_value']);
+ else
+ $this->p_vars[$this->p_vars['docblock_type']]->addParam($this->p_vars['paramname'],$this->p_vars['returntype'],$this->p_vars['tag_value']);
+ $this->p_vars['paramname'] = false;
+ $this->p_vars['returntype'] = false;
+ }
+ }
+
+ /**
+ * handles @return
+ * @tutorial tags.return.pkg
+ */
+ function returnTagHandler($word)
+ {
+ if ($word !== false)
+ {
+ if (!$this->p_vars['returntype']) $this->p_vars['returntype'] = trim($word);
+ else
+ {
+ if (strtolower($this->p_vars['returntype']) == 'object')
+ {
+ if (strlen(trim($word)))
+ $this->p_vars['returntype'] = trim($word);
+ } else $this->p_vars['tag_value']->add($word);
+ }
+ } else
+ {
+ $this->p_vars[$this->p_vars['docblock_type']]->addReturn($this->p_vars['returntype'],$this->p_vars['tag_value']);
+ $this->p_vars['returntype'] = false;
+ }
+ }
+
+ /**
+ * handles @var
+ * @tutorial tags.var.pkg
+ */
+ function varTagHandler($word)
+ {
+ if ($word)
+ {
+ if (!$this->p_vars['vartype']) $this->p_vars['vartype'] = trim($word);
+ else
+ {
+ if (strtolower($this->p_vars['vartype']) == 'object')
+ {
+ if (strlen(trim($word)))
+ $this->p_vars['vartype'] = trim($word);
+ }
+ else $this->p_vars['tag_value']->add($word);
+ }
+ } elseif ($word === false)
+ {
+ $this->p_vars[$this->p_vars['docblock_type']]->addVar($this->p_vars['vartype'],$this->p_vars['tag_value']);
+ $this->p_vars['vartype'] = false;
+ }
+ }
+ /**#@-*/
+ /** @access private */
+ function getSource()
+ {
+ $this->p_flags['get_source'] = true;
+ }
+ /**#@+
+ * @access private
+ * @param string token parsed from source
+ * @param integer parser constant from {@link Parser.inc}
+ */
+ /**
+ * handler for DOCKEYWORD_EMAIL.
+ * this handler recognizes angle brackets < and > surrounding an email address in an @author tag,
+ * and returns a mailto: hyperlink
+ */
+
+ function handleDockeywordEmail($word, $pevent)
+ {
+ //echo $this->wp->getPos() . ": |$word|\n";
+ if (!$this->checkEventPop($word,$pevent) && $word != "<")
+ {
+ if (strstr($word,"@"))
+ {
+ $this->p_vars['tag_value']->add('<');
+ $this->p_vars['tag_value']->add(new parserLinkInlineTag("mailto:$word",$word));
+ $this->p_vars['tag_value']->add('>');
+ } else {
+ $this->p_vars['tag_value']->add("<$word>");
+ }
+ }
+ }
+
+ /**
+ * handler for INLINE_DOCKEYWORD.
+ * this handler recognizes {@inline tags} like link, and parses them, replacing them directly
+ * in the text flow with their output.
+ */
+
+ function handleInlineDockeyword($word, $pevent)
+ {
+ // echo $this->wp->getPos() . ": |$word|\n";
+
+ // echo "docktype: $this->p_vars['inline_dockeyword_type']\n";
+ if (!isset($this->p_vars['inline_dockeyword_type'])) $this->p_vars['inline_dockeyword_type'] = false;
+ if (!isset($this->p_vars['inline_dockeyword_data'])) $this->p_vars['inline_dockeyword_data'] = '';
+ if (!$this->p_vars['inline_dockeyword_type'])
+ {
+ if (in_array($word,$this->allowableInlineTags))
+ {
+ if ($word == '}')
+ $this->p_vars['inline_dockeyword_type'] = '';
+ else
+ $this->p_vars['inline_dockeyword_type'] = strtolower($word);
+ $this->p_vars['whitesp'] = $this->wp->returnWhiteSpace;
+ $this->wp->setWhiteSpace(true);
+ } else {
+ if ($this->p_flags['in_desc'])
+ {
+ // fix 1203445
+ if (!isset($this->p_vars['line'][$this->p_vars['linecount']]))
+ {
+ $this->p_vars['line'][$this->p_vars['linecount']] =
+ new parserStringWithInlineTags;
+ }
+ if ($word == '}')
+ {
+ $this->p_vars['line'][$this->p_vars['linecount']]->add('{@');
+ } else
+ {
+ $this->p_vars['line'][$this->p_vars['linecount']]->add('{@'.$word);
+ }
+ } elseif($this->p_flags['in_tag'])
+ {
+ if ($word == '}')
+ $this->p_vars['tag_value']->add('{@'.$word);
+ else
+ $this->p_vars['tag_value']->add('{@'.$word);
+ }
+ $this->p_vars['event_stack']->popEvent();
+ $this->p_vars['inline_dockeyword_type'] = false;
+ $this->p_vars['inline_dockeyword_data'] = '';
+ return;
+ }
+ } else
+ {
+ if ($word != "}")
+ {
+ $this->p_vars['inline_dockeyword_data'] .= $word;
+ }
+ }
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->wp->setWhiteSpace($this->p_vars['whitesp']);
+ if ($this->p_vars['inline_dockeyword_type']=='link')
+ {
+ // support hyperlinks of any protocol
+ if (is_numeric(strpos($this->p_vars['inline_dockeyword_data'],'://')) || (strpos(trim($this->p_vars['inline_dockeyword_data']),'mailto:') === 0))
+ {
+ // if there is more than 1 parameter, the stuff after the space is the hyperlink text
+ if (strpos(trim($this->p_vars['inline_dockeyword_data']),' '))
+ {
+ $i1 = strpos(trim($this->p_vars['inline_dockeyword_data']),' ') + 1;
+ $link = substr(trim($this->p_vars['inline_dockeyword_data']),0,$i1 - 1);
+ $text = substr(trim($this->p_vars['inline_dockeyword_data']),$i1);
+ $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($link,$text);
+// '<a href="'.$link.'">'.$text.'</a>';
+ }
+ else
+ {
+ $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($this->p_vars['inline_dockeyword_data'],$this->p_vars['inline_dockeyword_data']);
+ }
+// '<a href="'.$this->p_vars['inline_dockeyword_data'].'">'.$this->p_vars['inline_dockeyword_data'].'</a>';
+ } else
+ {
+ if (!strpos($this->p_vars['inline_dockeyword_data'],','))
+ {
+ $testp = explode('#',$this->p_vars['inline_dockeyword_data']);
+ if (count($testp) - 1)
+ $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($this->p_vars['inline_dockeyword_data'],$testp[1]);
+ else
+ $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($this->p_vars['inline_dockeyword_data'],$this->p_vars['inline_dockeyword_data']);
+ } else
+ $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($this->p_vars['inline_dockeyword_data'],$this->p_vars['inline_dockeyword_data']);
+ }
+ }
+ if ($this->p_vars['inline_dockeyword_type'] == 'tutorial')
+ {
+ $this->p_vars['inline_dockeyword_data'] = new parserTutorialInlineTag($this->p_vars['inline_dockeyword_data'],$this->p_vars['inline_dockeyword_data']);
+ }
+ if ($this->p_vars['inline_dockeyword_type'] == 'source')
+ {
+ $this->getSource();
+ $this->p_vars['inline_dockeyword_data'] = new parserSourceInlineTag($this->p_vars['inline_dockeyword_data']);
+ }
+ if ($this->p_vars['inline_dockeyword_type'] == 'inheritdoc')
+ {
+ $this->p_vars['inline_dockeyword_data'] = new parserInheritdocInlineTag();
+ }
+ if ($word == '*/')
+ {
+ if (!isset($this->p_vars['inline_dockeyword_type'])) $this->p_vars['inline_dockeyword_type'] = '';
+ if (!isset($this->p_vars['tagname'])) $this->p_vars['tagname'] = '';
+ if (!isset($this->p_vars['tag_value']) || !is_object($this->p_vars['tag_value'])) $this->p_vars['tag_value'] = new parserStringWithInlineTags;
+ addError(PDERROR_UNTERMINATED_INLINE_TAG,$this->p_vars['inline_dockeyword_type'],$this->p_vars['tagname'],'@'.$this->p_vars['tagname'].' '.$this->p_vars['tag_value']->getString());
+ // when we add the error class, raise error here: we reached the end of the docblock
+ $this->wp->backupPos($word);
+ }
+ if ($this->p_flags['in_desc'])
+ {
+ $this->p_vars['line'][$this->p_vars['linecount']]->add($this->p_vars['inline_dockeyword_data']);
+ $this->p_vars['inline_dockeyword_type'] = false;
+ $this->p_vars['inline_dockeyword_data'] = '';
+ }
+ elseif ($this->p_flags['in_tag'])
+ {
+ $this->p_vars['tag_value']->add($this->p_vars['inline_dockeyword_data']);
+ $this->p_vars['inline_dockeyword_type'] = false;
+ $this->p_vars['inline_dockeyword_data'] = '';
+ }
+ }
+ }
+
+ /**
+ * handler for INCLUDE.
+ * this handler recognizes include/require/include_once/include_once statements, and publishes the
+ * data to Render
+ */
+
+ function handleInclude($word, $pevent)
+ {
+ if (!$this->p_flags['in_include'])
+ {
+ $this->p_vars['linenum'] = $this->wp->linenum;
+ }
+ $this->p_flags['in_include'] = true;
+ $a = $this->checkEventPush( $word, $pevent);
+ if (!$this->p_flags['includename_isset'])
+ {
+ $this->p_flags['includename_isset'] = true;
+ $this->p_vars['include_name'] = $this->p_vars['last_word'];
+ if ($a)
+ $this->p_vars['include_value'] = '';
+ else
+ $this->p_vars['include_value'] = $word;
+ unset($this->p_vars['quote_data']);
+ } else
+ {
+ if (!$a)
+ {
+ if (empty($this->p_vars['include_params_data']))
+ {
+ if (isset($this->p_vars['quote_data']))
+ {
+ $this->p_vars['include_value'] .= '"'.$this->p_vars['quote_data'].'"';
+ unset($this->p_vars['quote_data']);
+ }
+ if ($word != ';')
+ $this->p_vars['include_value'] .= $word;
+ }
+ } else
+ {
+ $this->p_vars['include_params_data'] = '';
+ }
+ }
+
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->p_vars['include'] = new parserInclude;
+ $this->p_vars['include']->setLineNumber($this->p_vars['linenum']);
+ $this->p_flags['in_include'] = false;
+ $this->p_vars['include']->setName($this->p_vars['include_name']);
+ $this->p_vars['include']->setValue($this->p_vars['include_value']);
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_INCLUDE,$this->p_vars['include']);
+ $this->p_flags['includename_isset'] = false;
+ unset($this->p_vars['include']);
+ unset($this->p_vars['include_name']);
+ unset($this->p_vars['include_value']);
+ unset($this->p_vars['include_params_data']);
+ }
+ }
+
+ /**
+ * handler for INCLUDE_PARAMS.
+ * this handler parses the contents of ( ) in include/require/include_once/include_once statements
+ */
+
+ function handleIncludeParams($word, $pevent)
+ {
+ $this->checkEventPush( $word, $pevent);
+
+ $this->p_flags['include_parens'] = true;
+ if(!isset($this->p_vars['include_params_data'])) $this->p_vars['include_params_data'] = '';
+
+ if ($this->checkEventPop($word,$pevent))
+ {
+ if (isset($this->p_vars['quote_data']))
+ {
+ $this->p_vars['include_value'] = $this->p_vars['include_params_data'].'"'.$this->p_vars['quote_data'].'"';
+ unset($this->p_vars['quote_data']);
+ } else {
+ if (!empty($this->p_vars['include_params_data']))
+ $this->p_vars['include_value'] = $this->p_vars['include_params_data'];
+ else
+ $this->p_vars['include_value'] = trim($this->p_vars['last_word']);
+ }
+ }
+ if (isset($this->p_vars['quote_data']))
+ {
+ $this->p_vars['include_params_data'] .= '"'.$this->p_vars['quote_data'].'"';
+ unset($this->p_vars['quote_data']);
+ }
+ if (($word != "'") && ($word != '"'))
+ $this->p_vars['include_params_data'] .= $word;
+ }
+
+ /**
+ * handler for INCLUDE_PARAMS_PARENTHESIS.
+ * this handler takes all parenthetical statements within file in:
+ * include statement include(file), and handles them properly
+ */
+
+ function handleIncludeParamsParenthesis($word, $pevent)
+ {
+ if (isset($this->p_vars['quote_data']))
+ {
+ $this->p_vars['include_params_data'] .= '"'.$this->p_vars['quote_data'].'"';
+ unset($this->p_vars['quote_data']);
+ }
+ $this->p_vars['include_params_data'] .= $word;
+ $this->checkEventPush( $word, $pevent);
+ $this->checkEventPop( $word, $pevent);
+ }
+ /**#@-*/
+ /**
+ * this function checks whether parameter $word is a token for pushing a new event onto the Event Stack.
+ * @return mixed returns false, or the event number
+ */
+
+ function checkEventPush($word,$pevent)
+ {
+ $e = false;
+ if (isset($this->pushEvent[$pevent]))
+ {
+ if (isset($this->pushEvent[$pevent][strtolower($word)]))
+ $e = $this->pushEvent[$pevent][strtolower($word)];
+ }
+ if ($e)
+ {
+ $this->p_vars['event_stack']->pushEvent($e);
+ return $e;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * this function checks whether parameter $word is a token for popping the current event off of the Event Stack.
+ * @return mixed returns false, or the event number popped off of the stack
+ */
+
+ function checkEventPop($word,$pevent)
+ {
+ if (!isset($this->popEvent[$pevent])) return false;
+ if (in_array(strtolower($word),$this->popEvent[$pevent]))
+ {
+ return $this->p_vars['event_stack']->popEvent();
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * setup the parser tokens, and the pushEvent/popEvent arrays
+ * @see $tokens, $pushEvent, $popEvent
+ */
+
+ function setupStates()
+ {
+ $this->tokens[STATE_PHPCODE] = array(" ", "\t",";","?>","</script>","/**#@+","/**#@-*/","/**", "//","/*","#","\r\n","\n","\r","(",'<<<','"',"'");
+ $this->tokens[STATE_QUOTE] = array("\\\"","\\\\","\"");
+ $this->tokens[STATE_LOGICBLOCK] = array("{","}","\"","'","/*","//","#","?>","</script>",'<<<','global','static');
+ $this->tokens[STATE_FUNC_GLOBAL] = array("\"","'","/*","//","#",";",",");
+ $this->tokens[STATE_STATIC_VAR] = array("\"","'","/*","//","#",";",",",'=','array');
+ $this->tokens[STATE_STATIC_VAR_VALUE] = array("/*","//","#"," ","\t",";","=","\"","'","array",",");
+ $this->tokens[STATE_NOEVENTS] = array("<?php","<?",'<script language="php">');
+ $this->tokens[STATE_COMMENTBLOCK] = array("*/","\n");
+ $this->tokens[STATE_COMMENT] = array("\r\n","\r","\n");
+ $this->tokens[STATE_DEFINE] = array(" ","(",";");
+ $this->tokens[STATE_DEFINE_PARAMS] = array("/*","//","#",",",")"," ","'","\"","(");
+ $this->tokens[STATE_DEFINE_PARAMS_PARENTHESIS] = array("(","'","\"",")");
+ $this->tokens[STATE_FUNCTION_PARAMS] = array("/*","//","#","\"",",",")","="," ","'","(");
+ $this->tokens[STATE_SINGLEQUOTE] = array("'","\\'","\\\\");
+ $this->tokens[STATE_CLASS] = array(" ", "\t", "?>", "</script>", ";", "}", "{",
+ "/**#@+", "/**#@-*/", "/**", "//", "/*", "#",
+ "\r\n", "\n", "\r","(");
+ $this->tokens[STATE_DOCBLOCK] = array("*/","*","@","\r\n","\n","\r",". ",".\n",".\t",'{@');
+ $this->tokens[STATE_DOCBLOCK_TEMPLATE] = array("*/","*","@","\r\n","\n","\r",". ",".\n",".\t",'{@');
+ $this->tokens[STATE_DOCKEYWORD] = array("@","*/","*","\n","\r\n","\r","\t"," ","<",">",'{@');
+ $this->tokens[STATE_INLINE_DOCKEYWORD] = array("{@","}","\t"," ","*/");
+ $this->tokens[STATE_DOCKEYWORD_EMAIL] = array(">","\n","\r\n","\r");
+ $this->tokens[STATE_VAR] = array("/*","//","#"," ","\t",";","=",",","\"","'","array");
+ $this->tokens[STATE_GLOBAL] = array("/*","//","#"," ","\t",";","=","\"","'");
+ $this->tokens[STATE_GLOBAL_VALUE] = array("/*","//","#"," ","\t",";","=","\"","'","array");
+ $this->tokens[STATE_ARRAY] = array("/*","//","#","(",")","\"","'","array");
+ $this->tokens[STATE_FUNCTION] = array("(","{","}"," ","\t","&","/*","//","#");
+ $this->tokens[STATE_OUTPHP] = array("<?php","<?",'<script language="php">');
+ $this->tokens[STATE_EOFQUOTE] = array(" ","\t","\n");
+ $this->tokens[STATE_ESCAPE] = false;// this tells the word parser to just cycle
+ $this->tokens[STATE_INCLUDE] = array(" ","(",";","'",'"');
+ $this->tokens[STATE_INCLUDE_PARAMS] = array("/*",")"," ","'","\"","(");
+ $this->tokens[STATE_INCLUDE_PARAMS_PARENTHESIS] = array("(","'","\"",")");
+
+ // For each event word to event mapings
+ $this->pushEvent[PARSER_EVENT_QUOTE] =
+ array(
+ "\\" => PARSER_EVENT_ESCAPE
+ );
+ $this->popEvent[PARSER_EVENT_QUOTE] = array("\"");
+##########################
+
+ $this->pushEvent[PARSER_EVENT_LOGICBLOCK] =
+ array(
+ "\"" => PARSER_EVENT_QUOTE,
+ "'" => PARSER_EVENT_SINGLEQUOTE,
+ "//" => PARSER_EVENT_COMMENT,
+ "#" => PARSER_EVENT_COMMENT,
+ "global" => PARSER_EVENT_FUNC_GLOBAL,
+ "static" => PARSER_EVENT_STATIC_VAR,
+ "/*" => PARSER_EVENT_COMMENTBLOCK,
+ "{" => PARSER_EVENT_LOGICBLOCK,
+ "?>" => PARSER_EVENT_OUTPHP,
+ "</script>" => PARSER_EVENT_OUTPHP,
+ "<<<" => PARSER_EVENT_EOFQUOTE
+ );
+ $this->popEvent[PARSER_EVENT_LOGICBLOCK] = array("}");
+##########################
+
+ $this->pushEvent[PARSER_EVENT_FUNC_GLOBAL] =
+ array(
+ "\"" => PARSER_EVENT_QUOTE,
+ "'" => PARSER_EVENT_SINGLEQUOTE,
+ "//" => PARSER_EVENT_COMMENT,
+ "#" => PARSER_EVENT_COMMENT,
+ "/*" => PARSER_EVENT_COMMENTBLOCK,
+ );
+ $this->popEvent[PARSER_EVENT_FUNC_GLOBAL] = array(";");
+##########################
+
+ $this->pushEvent[PARSER_EVENT_STATIC_VAR] =
+ array(
+ "\"" => PARSER_EVENT_QUOTE,
+ "'" => PARSER_EVENT_SINGLEQUOTE,
+ "//" => PARSER_EVENT_COMMENT,
+ "#" => PARSER_EVENT_COMMENT,
+ "/*" => PARSER_EVENT_COMMENTBLOCK,
+ "=" => PARSER_EVENT_STATIC_VAR_VALUE,
+ );
+ $this->popEvent[PARSER_EVENT_STATIC_VAR] = array(";");
+##########################
+
+ $this->pushEvent[PARSER_EVENT_STATIC_VAR_VALUE] =
+ array(
+ "\"" => PARSER_EVENT_QUOTE,
+ "'" => PARSER_EVENT_SINGLEQUOTE,
+ "array" => PARSER_EVENT_ARRAY,
+ "/*" => PARSER_EVENT_COMMENTBLOCK,
+ "//" => PARSER_EVENT_COMMENT,
+ "#" => PARSER_EVENT_COMMENT
+ );
+ $this->popEvent[PARSER_EVENT_STATIC_VAR_VALUE] = array(";",",");
+##########################
+
+ $this->pushEvent[PARSER_EVENT_NOEVENTS] =
+ array(
+ "<?php" => PARSER_EVENT_PHPCODE,
+ "<?" => PARSER_EVENT_PHPCODE,
+ '<script language="php">' => PARSER_EVENT_PHPCODE,
+ );
+##########################
+
+ $this->pushEvent[PARSER_EVENT_PHPCODE] =
+ array(
+ "function" => PARSER_EVENT_FUNCTION,
+ "class" => PARSER_EVENT_CLASS,
+ "define" => PARSER_EVENT_DEFINE,
+ "include_once" => PARSER_EVENT_INCLUDE,
+ "require_once" => PARSER_EVENT_INCLUDE,
+ "include" => PARSER_EVENT_INCLUDE,
+ "require" => PARSER_EVENT_INCLUDE,
+ "//" => PARSER_EVENT_COMMENT,
+ "#" => PARSER_EVENT_COMMENT,
+ "/*" => PARSER_EVENT_COMMENTBLOCK,
+ "/**" => PARSER_EVENT_DOCBLOCK,
+ "/**#@+" => PARSER_EVENT_DOCBLOCK_TEMPLATE,
+ "/**#@-*/" => PARSER_EVENT_END_DOCBLOCK_TEMPLATE,
+ "\"" => PARSER_EVENT_QUOTE,
+ "'" => PARSER_EVENT_SINGLEQUOTE,
+ "<<<" => PARSER_EVENT_EOFQUOTE,
+ "?>" => PARSER_EVENT_OUTPHP,
+ "</script>" => PARSER_EVENT_OUTPHP,
+ );
+##########################
+
+ $this->pushEvent[PARSER_EVENT_FUNCTION] =
+ array(
+ "(" => PARSER_EVENT_FUNCTION_PARAMS,
+ "//" => PARSER_EVENT_COMMENT,
+ "#" => PARSER_EVENT_COMMENT,
+ "/*" => PARSER_EVENT_COMMENTBLOCK,
+ "{" => PARSER_EVENT_LOGICBLOCK
+ );
+ $this->popEvent[PARSER_EVENT_FUNCTION] = array("}");
+##########################
+
+ $this->pushEvent[PARSER_EVENT_DOCBLOCK] =
+ array(
+ "@" => PARSER_EVENT_DOCKEYWORD,
+ "{@" => PARSER_EVENT_INLINE_DOCKEYWORD
+ );
+ $this->popEvent[PARSER_EVENT_DOCBLOCK] = array("*/");
+##########################
+
+ $this->pushEvent[PARSER_EVENT_DOCBLOCK_TEMPLATE] =
+ array(
+ "@" => PARSER_EVENT_DOCKEYWORD,
+ "{@" => PARSER_EVENT_INLINE_DOCKEYWORD
+ );
+ $this->popEvent[PARSER_EVENT_DOCBLOCK_TEMPLATE] = array("*/");
+##########################
+
+ $this->pushEvent[PARSER_EVENT_CLASS] =
+ array(
+ "function" => PARSER_EVENT_FUNCTION,
+ "var" => PARSER_EVENT_VAR,
+ "/**" => PARSER_EVENT_DOCBLOCK,
+ "/**#@+" => PARSER_EVENT_DOCBLOCK_TEMPLATE,
+ "/**#@-*/" => PARSER_EVENT_END_DOCBLOCK_TEMPLATE,
+ "//" => PARSER_EVENT_COMMENT,
+ "/*" => PARSER_EVENT_COMMENTBLOCK,
+ "#" => PARSER_EVENT_COMMENT,
+ "?>" => PARSER_EVENT_OUTPHP,
+ "</script>" => PARSER_EVENT_OUTPHP,
+ );
+ $this->popEvent[PARSER_EVENT_CLASS] = array("}");
+##########################
+
+ $this->pushEvent[PARSER_EVENT_DEFINE] =
+ array(
+ "/*" => PARSER_EVENT_COMMENTBLOCK,
+ "(" => PARSER_EVENT_DEFINE_PARAMS
+ );
+ $this->popEvent[PARSER_EVENT_DEFINE] = array(";");
+##########################
+
+ $this->pushEvent[PARSER_EVENT_INCLUDE] =
+ array(
+ "/*" => PARSER_EVENT_COMMENTBLOCK,
+ "(" => PARSER_EVENT_INCLUDE_PARAMS,
+ "'" => PARSER_EVENT_SINGLEQUOTE,
+ '"' => PARSER_EVENT_QUOTE,
+ );
+ $this->popEvent[PARSER_EVENT_INCLUDE] = array(";");
+##########################
+
+ $this->pushEvent[PARSER_EVENT_DEFINE_PARAMS] =
+ array(
+ "(" => PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS,
+ "'" => PARSER_EVENT_SINGLEQUOTE,
+ '"' => PARSER_EVENT_QUOTE,
+ "/*" => PARSER_EVENT_COMMENTBLOCK,
+ "//" => PARSER_EVENT_COMMENT,
+ "#" => PARSER_EVENT_COMMENT
+ );
+ $this->popEvent[PARSER_EVENT_DEFINE_PARAMS] = array(")");
+##########################
+
+ $this->pushEvent[PARSER_EVENT_INCLUDE_PARAMS] =
+ array(
+ "(" => PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS,
+ "'" => PARSER_EVENT_SINGLEQUOTE,
+ '"' => PARSER_EVENT_QUOTE,
+ );
+ $this->popEvent[PARSER_EVENT_INCLUDE_PARAMS] = array(")");
+##########################
+
+ $this->pushEvent[PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS] =
+ array(
+ "(" => PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS,
+ "'" => PARSER_EVENT_SINGLEQUOTE,
+ '"' => PARSER_EVENT_QUOTE,
+ );
+ $this->popEvent[PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS] = array(")");
+##########################
+
+ $this->pushEvent[PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS] =
+ array(
+ "(" => PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS,
+ "'" => PARSER_EVENT_SINGLEQUOTE,
+ '"' => PARSER_EVENT_QUOTE,
+ );
+ $this->popEvent[PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS] = array(")");
+##########################
+
+ $this->pushEvent[PARSER_EVENT_VAR] =
+ array(
+ "\"" => PARSER_EVENT_QUOTE,
+ "'" => PARSER_EVENT_SINGLEQUOTE,
+ "array" => PARSER_EVENT_ARRAY,
+ "/*" => PARSER_EVENT_COMMENTBLOCK,
+ "//" => PARSER_EVENT_COMMENT,
+ "#" => PARSER_EVENT_COMMENT
+ );
+ $this->popEvent[PARSER_EVENT_VAR] = array(";");
+##########################
+
+ $this->pushEvent[PARSER_EVENT_DEFINE_GLOBAL] =
+ array(
+ "=" => PARSER_EVENT_GLOBAL_VALUE,
+ "\"" => PARSER_EVENT_QUOTE,
+ "'" => PARSER_EVENT_SINGLEQUOTE,
+ "/*" => PARSER_EVENT_COMMENTBLOCK,
+ "//" => PARSER_EVENT_COMMENT,
+ "#" => PARSER_EVENT_COMMENT
+ );
+ $this->popEvent[PARSER_EVENT_DEFINE_GLOBAL] = array(";");
+##########################
+
+ $this->pushEvent[PARSER_EVENT_GLOBAL_VALUE] =
+ array(
+ "\"" => PARSER_EVENT_QUOTE,
+ "'" => PARSER_EVENT_SINGLEQUOTE,
+ "array" => PARSER_EVENT_ARRAY,
+ "/*" => PARSER_EVENT_COMMENTBLOCK,
+ "//" => PARSER_EVENT_COMMENT,
+ "#" => PARSER_EVENT_COMMENT
+ );
+ $this->popEvent[PARSER_EVENT_GLOBAL_VALUE] = array(";");
+##########################
+
+ $this->pushEvent[PARSER_EVENT_COMMENT] =
+ array(
+ "\\" => PARSER_EVENT_ESCAPE
+ );
+ $this->popEvent[PARSER_EVENT_COMMENT] = array("\n");
+##########################
+
+ $this->popEvent[PARSER_EVENT_COMMENTBLOCK] = array("*/");
+##########################
+ $this->pushEvent[PARSER_EVENT_SINGLEQUOTE] =
+ array(
+ "\\" => PARSER_EVENT_ESCAPE
+ );
+
+ $this->popEvent[PARSER_EVENT_SINGLEQUOTE] = array("'");
+##########################
+ $this->pushEvent[PARSER_EVENT_FUNCTION_PARAMS] =
+ array(
+ "\"" => PARSER_EVENT_QUOTE,
+ "'" => PARSER_EVENT_SINGLEQUOTE,
+ "array" => PARSER_EVENT_ARRAY,
+ "/*" => PARSER_EVENT_COMMENTBLOCK,
+ "//" => PARSER_EVENT_COMMENT,
+ "#" => PARSER_EVENT_COMMENT
+ );
+ $this->popEvent[PARSER_EVENT_FUNCTION_PARAMS] = array(")");
+##########################
+ $this->pushEvent[PARSER_EVENT_DOCKEYWORD] =
+ array(
+// "<" => PARSER_EVENT_DOCKEYWORD_EMAIL,
+ "{@" => PARSER_EVENT_INLINE_DOCKEYWORD,
+ );
+
+ $this->popEvent[PARSER_EVENT_DOCKEYWORD] = array("*/");
+##########################
+
+ $this->popEvent[PARSER_EVENT_INLINE_DOCKEYWORD] = array("}","*/");
+##########################
+
+ $this->popEvent[PARSER_EVENT_OUTPHP] = array("<?php","<?",'<script language="php">');
+##########################
+
+ $this->popEvent[PARSER_EVENT_DOCKEYWORD_EMAIL] = array(">","\n");
+
+##########################
+ $this->pushEvent[PARSER_EVENT_ARRAY] =
+ array(
+ "\"" => PARSER_EVENT_QUOTE,
+ "'" => PARSER_EVENT_SINGLEQUOTE,
+ "array" => PARSER_EVENT_ARRAY,
+ "/*" => PARSER_EVENT_COMMENTBLOCK,
+ "//" => PARSER_EVENT_COMMENT,
+ "#" => PARSER_EVENT_COMMENT
+ );
+ $this->popEvent[PARSER_EVENT_ARRAY] = array(")");
+##########################
+ }
+
+ /**
+ * tell the parser's WordParser {@link $wp} to set up tokens to parse words by.
+ * tokens are word separators. In English, a space or punctuation are examples of tokens.
+ * In PHP, a token can be a ;, a parenthesis, or even the word "function"
+ * @param $value integer an event number
+ * @see WordParser
+ */
+
+ function configWordParser($e)
+ {
+ $this->wp->setSeperator($this->tokens[($e + 100)]);
+ }
+
+ /**
+ * Debugging function, takes an event number and attempts to return its name
+ * @param $value integer an event number
+ */
+
+
+ function getParserEventName ($value)
+ {
+ $lookup = array(
+ PARSER_EVENT_NOEVENTS => "PARSER_EVENT_NOEVENTS",
+ PARSER_EVENT_PHPCODE => "PARSER_EVENT_PHPCODE",
+ PARSER_EVENT_DOCBLOCK => "PARSER_EVENT_DOCBLOCK",
+ PARSER_EVENT_FUNCTION => "PARSER_EVENT_FUNCTION",
+ PARSER_EVENT_CLASS => "PARSER_EVENT_CLASS",
+ PARSER_EVENT_DEFINE => "PARSER_EVENT_DEFINE",
+ PARSER_EVENT_DEFINE_PARAMS => "PARSER_EVENT_DEFINE_PARAMS",
+ PARSER_EVENT_COMMENT => "PARSER_EVENT_COMMENT",
+ PARSER_EVENT_COMMENTBLOCK => "PARSER_EVENT_COMMENTBLOCK",
+ PARSER_EVENT_ESCAPE => "PARSER_EVENT_ESCAPE",
+ PARSER_EVENT_QUOTE => "PARSER_EVENT_QUOTE",
+ PARSER_EVENT_FUNCTION_PARAMS => "PARSER_EVENT_FUNCTION_PARAMS",
+ PARSER_EVENT_SINGLEQUOTE => "PARSER_EVENT_SINGLEQUOTE",
+ PARSER_EVENT_VAR => "PARSER_EVENT_VAR",
+ PARSER_EVENT_LOGICBLOCK => "PARSER_EVENT_LOGICBLOCK",
+ PARSER_EVENT_OUTPHP => "PARSER_EVENT_OUTPHP",
+ PARSER_EVENT_DOCKEYWORD => "PARSER_EVENT_DOCKEYWORD",
+ PARSER_EVENT_DOCKEYWORD_EMAIL => "PARSER_EVENT_DOCKEYWORD_EMAIL",
+ PARSER_EVENT_ARRAY => "PARSER_EVENT_ARRAY",
+ PARSER_EVENT_INLINE_DOCKEYWORD => "PARSER_EVENT_INLINE_DOCKEYWORD",
+ PARSER_EVENT_EOFQUOTE => "PARSER_EVENT_EOFQUOTE",
+ PARSER_EVENT_INCLUDE => "PARSER_EVENT_INCLUDE",
+ PARSER_EVENT_INCLUDE_PARAMS => "PARSER_EVENT_INCLUDE_PARAMS",
+ PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS => "PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS",
+ PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS => "PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS",
+ PARSER_EVENT_DEFINE_GLOBAL => "PARSER_EVENT_DEFINE_GLOBAL",
+ PARSER_EVENT_GLOBAL_VALUE => "PARSER_EVENT_GLOBAL_VALUE",
+ PARSER_EVENT_FUNC_GLOBAL => "PARSER_EVENT_FUNC_GLOBAL",
+ PARSER_EVENT_STATIC_VAR => "PARSER_EVENT_STATIC_VAR",
+ PARSER_EVENT_DOCBLOCK_TEMPLATE => "PARSER_EVENT_DOCBLOCK_TEMPLATE",
+ PARSER_EVENT_END_DOCBLOCK_TEMPLATE => "PARSER_EVENT_END_DOCBLOCK_TEMPLATE",
+ PARSER_EVENT_METHOD_LOGICBLOCK => 'PARSER_EVENT_METHOD_LOGICBLOCK',
+ PARSER_EVENT_CLASS_MEMBER => 'PARSER_EVENT_CLASS_MEMBER',
+ PARSER_EVENT_METHOD => 'PARSER_EVENT_METHOD',
+ PARSER_EVENT_QUOTE_VAR => 'PARSER_EVENT_QUOTE_VAR',
+ PARSER_EVENT_ACCESS_MODIFIER => 'PARSER_EVENT_ACCESS_MODIFIER',
+ PARSER_EVENT_IMPLEMENTS => 'PARSER_EVENT_IMPLEMENTS',
+ PARSER_EVENT_CLASS_CONSTANT => 'PARSER_EVENT_CLASS_CONSTANT',
+ PARSER_EVENT_VAR_ARRAY => 'PARSER_EVENT_VAR_ARRAY',
+ PARSER_EVENT_VAR_ARRAY_COMMENT =>'PARSER_EVENT_VAR_ARRAY_COMMENT',
+ );
+ if (isset($lookup[$value]))
+ return $lookup[$value];
+ else return $value;
+ }
+}
+
+/**
+ * Global package page parser
+ *
+ * @deprecated in favor of tutorials
+ * @tutorial tutorials.pkg
+ * @package phpDocumentor
+ * @subpackage Parsers
+ */
+class ppageParser extends Parser
+{
+ /** @var string */
+ var $package = false;
+ /** @var string */
+ var $subpackage = '';
+ /**
+ * set up invariant Parser variables
+ */
+ function ppageParser()
+ {
+ Parser::Parser();
+ $this->allowableInlineTags = $GLOBALS['_phpDocumentor_inline_tutorial_tags_allowed'];
+ $this->eventHandlers = array();
+ $this->eventHandlers[PARSER_EVENT_NOEVENTS] = 'defaultHandler';
+ $this->eventHandlers[PARSER_EVENT_INLINE_DOCKEYWORD] = 'handleInlineDocKeyword';
+ }
+
+ /**
+ * set up invariant Parser variables
+ */
+ function setupStates()
+ {
+ $this->tokens[STATE_NOEVENTS] = array("{@","}");
+ $this->tokens[STATE_INLINE_DOCKEYWORD] = array("{@","}","\t"," ");
+
+##########################
+
+ $this->pushEvent[PARSER_EVENT_NOEVENTS] =
+ array(
+ "{@" => PARSER_EVENT_INLINE_DOCKEYWORD
+ );
+##########################
+
+ $this->popEvent[PARSER_EVENT_INLINE_DOCKEYWORD] = array("}");
+ }
+
+ /**
+ * Parse a new file
+ *
+ * @param string $parse_data
+ * @param string $package
+ * @param int $subpackage
+ * @return mixed false or parsed data
+ */
+ function parse (&$parse_data,$xml,$package = 'default',$subpackage = '',$tutorial = '',
+ $category='default', $path='')
+ {
+ $this->setupStates();
+ $this->p_vars['total'] = new parserPackagePage($package,$xml);
+ $this->p_vars['tutorial'] = $tutorial;
+ $this->_path = $path;
+ $this->category = $category;
+ $this->package = $package;
+ if (!isset($subpackage) || !$subpackage) $subpackage = '';
+ $this->subpackage = $subpackage;
+ if (strlen($parse_data) == 0)
+ {
+ return false;
+ }
+
+ // initialize variables so E_ALL error_reporting doesn't complain
+ $pevent = 0;
+ $word = 0;
+ $this->p_vars['event_stack'] = new EventStack;
+ // change this to a new ParserStringWithInlineTags, and change all $total .= blah to $total->add(blah)
+ // then modify phpDocumentor_IntermediateParser->Convert to convert all package pages (the package page handler in phpDocumentor_IntermediateParser should
+ // save them all in a variable) to perform the linking. then, remove the legacy code from handleDocBlock
+ // and handleClass in Render.inc, and do a loop that converts each package page, and passes it to handleEvent
+ // just like Converter::walk does with the other elements. The only other addition that might be good is a
+ // new descendant of parserElement parserPackagePage that contains the data and stuff. Hope this helps :)
+ $total = '';
+
+ $this->wp->setup($parse_data);
+
+ $this->p_flags['reset_quote_data'] = true;
+
+ do
+ {
+ $lpevent = $pevent;
+ $pevent = $this->p_vars['event_stack']->getEvent();
+ if ($lpevent != $pevent)
+ {
+ $this->p_vars['last_pevent'] = $lpevent;
+ }
+
+ if ($this->p_vars['last_pevent'] != $pevent)
+ {
+ // its a new event so the word parser needs to be reconfigured
+ $this->configWordParser($pevent);
+ }
+
+ if (!$xml)
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE,($pevent + 100));
+
+
+ $this->p_vars['last_word'] = $word;
+ $word = $this->wp->getWord();
+
+ if (0)//PHPDOCUMENTOR_DEBUG == true)
+ {
+ echo "LAST: |" . $this->p_vars['last_word'] . "|\n";
+ echo "PEVENT: " . $this->getParserEventName($pevent) . "\n";
+ echo $this->wp->getPos() . ": |$word|\n";
+ }
+ if (isset($this->eventHandlers[$pevent]))
+ {
+ $handle = $this->eventHandlers[$pevent];
+ $this->$handle($word, $pevent);
+ }
+ } while (!($word === false));
+ if (!$xml)
+ $this->PublishEvent(PHPDOCUMENTOR_EVENT_PACKAGEPAGE,$this->p_vars['total']);
+ else
+ return $this->p_vars['total']->value;
+ }
+
+ /**
+ * Handles all non-inline tags
+ *
+ * @param string token
+ * @param integer parser event
+ */
+ function defaultHandler($word, $pevent)
+ {
+ if (!$this->checkEventPush( $word, $pevent))
+ {
+ if ($word) $this->p_vars['total']->add($word);
+ }
+ }
+
+ /**
+ * handler for INLINE_DOCKEYWORD.
+ * this handler recognizes {@inline tags} like link, and parses them, replacing them directly
+ * in the text flow with their output.
+ * @param string token
+ * @param integer parser event
+ */
+
+ function handleInlineDockeyword($word, $pevent)
+ {
+ // echo $this->wp->getPos() . ": |$word|\n";
+
+ // echo "docktype: $this->p_vars['inline_dockeyword_type']\n";
+ if (!isset($this->p_vars['inline_dockeyword_type'])) $this->p_vars['inline_dockeyword_type'] = false;
+ if (!isset($this->p_vars['inline_dockeyword_data'])) $this->p_vars['inline_dockeyword_data'] = '';
+ if (!$this->p_vars['inline_dockeyword_type'])
+ {
+ if (in_array($word,$this->allowableInlineTags))
+ {
+ $this->p_vars['inline_dockeyword_type'] = strtolower($word);
+ $this->p_vars['whitesp'] = $this->wp->returnWhiteSpace;
+ $this->wp->setWhiteSpace(true);
+ } else {
+ if ($word == '}')
+ $this->p_vars['total']->add('{@');
+ else
+ {
+ $this->p_vars['total']->add('{@'.$word);
+ $this->p_vars['event_stack']->popEvent();
+ }
+ $this->p_vars['inline_dockeyword_type'] = false;
+ $this->p_vars['inline_dockeyword_data'] = '';
+ }
+ } else
+ {
+ if ($word != "}")
+ {
+ $this->p_vars['inline_dockeyword_data'] .= $word;
+ }
+ }
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->wp->setWhiteSpace($this->p_vars['whitesp']);
+ if ($this->p_vars['inline_dockeyword_type']=='link')
+ {
+ // support hyperlinks of any protocol
+ if (is_numeric(strpos($this->p_vars['inline_dockeyword_data'],'://')) || (strpos(trim($this->p_vars['inline_dockeyword_data']),'mailto:') === 0))
+ {
+ // if there is more than 1 parameter, the stuff after the space is the hyperlink text
+ if (strpos(trim($this->p_vars['inline_dockeyword_data']),' '))
+ {
+ $i1 = strpos(trim($this->p_vars['inline_dockeyword_data']),' ') + 1;
+ $link = substr(trim($this->p_vars['inline_dockeyword_data']),0,$i1 - 1);
+ $text = substr(trim($this->p_vars['inline_dockeyword_data']),$i1);
+ $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($link,$text);
+// '<a href="'.$link.'">'.$text.'</a>';
+ }
+ else
+ {
+ $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($this->p_vars['inline_dockeyword_data'],$this->p_vars['inline_dockeyword_data']);
+ }
+// '<a href="'.$this->p_vars['inline_dockeyword_data'].'">'.$this->p_vars['inline_dockeyword_data'].'</a>';
+ } else
+ {
+ $testp = explode('#',$this->p_vars['inline_dockeyword_data']);
+ if (count($testp) - 1) $this->p_vars['inline_dockeyword_data'] = $testp[1];
+ $this->p_vars['inline_dockeyword_data'] = new parserLinkInlineTag($this->p_vars['inline_dockeyword_data'],$this->p_vars['inline_dockeyword_data']);
+ }
+ }
+ if ($this->p_vars['inline_dockeyword_type']=='id')
+ {
+ $this->p_vars['inline_dockeyword_data'] = new parserIdInlineTag($this->category,$this->package,$this->subpackage,$this->p_vars['tutorial'],trim($this->p_vars['inline_dockeyword_data']));
+ }
+ if ($this->p_vars['inline_dockeyword_type'] == 'tutorial')
+ {
+ $this->p_vars['inline_dockeyword_data'] = new parserTutorialInlineTag($this->p_vars['inline_dockeyword_data'],$this->p_vars['inline_dockeyword_data']);
+ }
+ if ($this->p_vars['inline_dockeyword_type'] == 'toc')
+ {
+ $this->p_vars['inline_dockeyword_data'] = new parserTocInlineTag();
+ }
+ if ($this->p_vars['inline_dockeyword_type'] == 'example')
+ {
+ $example =
+ new parserExampleInlineTag($this->p_vars['inline_dockeyword_data'], $this->_path, true);
+ $this->p_vars['total']->add($example->getProgramListing());
+ } else
+ {
+ $this->p_vars['total']->add($this->p_vars['inline_dockeyword_data']);
+ }
+ $this->p_vars['inline_dockeyword_type'] = false;
+ $this->p_vars['inline_dockeyword_data'] = '';
+ }
+ }
+}
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/ParserData.inc b/buildscripts/PhpDocumentor/phpDocumentor/ParserData.inc
new file mode 100644
index 00000000..d7d0f285
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/ParserData.inc
@@ -0,0 +1,725 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * Parser Data Structures
+ * @package phpDocumentor
+ * @subpackage ParserData
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: ParserData.inc,v 1.1 2005/10/17 18:36:57 jeichorn Exp $
+ */
+/**
+ * Contains information about a PHP file, used to group procedural elements
+ * together.
+ * @package phpDocumentor
+ * @subpackage ParserData
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: ParserData.inc,v 1.1 2005/10/17 18:36:57 jeichorn Exp $
+ */
+class parserPage
+{
+ /**
+ * Type is used by many functions to skip the hassle of if
+ * <code>phpDocumentor_get_class($blah) == 'parserBlah'</code>
+ * @var string
+ */
+ var $type = 'page';
+ /**
+ * not implemented in this version, will be used to link xml output pages
+ * @var string
+ */
+ var $id = '';
+ /**
+ * filename.ext (no path)
+ * @var string
+ */
+ var $file = '';
+ /**
+ * relative source location
+ * @var string
+ */
+ var $sourceLocation = '';
+ /**
+ * phpdoc-safe name (only letters, numbers and _)
+ * @var string
+ */
+ var $name = '';
+ /**
+ * @var string
+ */
+ var $category = 'default';
+ /**
+ * @var string
+ */
+ var $package = 'default';
+ /**
+ * @var string
+ */
+ var $subpackage = '';
+ /**
+ * @var string
+ */
+ var $parserVersion = PHPDOCUMENTOR_VER;
+ /**
+ * not implemented yet
+ * file modification date, will be used for makefiles
+ * @var string
+ */
+ var $modDate = '';
+ /**
+ * @var string full path this page represents
+ */
+ var $path = '';
+ /**
+ * Tokenized source code of the file
+ * @var array
+ */
+ var $source = array();
+ /**
+ * Used to limit output, contains contents of --packageoutput commandline.
+ * Does not increase parsing time. Use --ignore for that
+ * @see phpDocumentor_IntermediateParser::$packageoutput, Converter::$package_output
+ * @var mixed either false or an array of packages
+ */
+ var $packageOutput = false;
+
+ /**
+ * sets package to default package
+ * @global string default package name
+ */
+ function parserPage()
+ {
+ global $phpDocumentor_DefaultPackageName;
+ $this->package = $GLOBALS['phpDocumentor_DefaultPackageName'];
+ }
+
+ /**
+ * @return string always "page"
+ */
+ function getType()
+ {
+ return 'page';
+ }
+
+ /**
+ * Sets the source code of the file for highlighting.
+ *
+ * PHP 4.3.0+ passes an array of tokenizer tokens by line number. PHP
+ * 4.2.3- passes a string to be passed to {@link highlight_string()}
+ * @param string|array
+ */
+ function setSource($source)
+ {
+ $this->source = $source;
+ }
+
+ /**
+ * Sets the name to display in documentation (can be an alias set with @name)
+ * @param string $file
+ */
+ function setFile($file)
+ {
+ $this->file = $file;
+ }
+
+ /**
+ * @return string filename.ext or @name alias
+ */
+ function getFile()
+ {
+ if (!isset($this->file)) return false;
+ return $this->file;
+ }
+
+ /**
+ * @param string $path full path to file
+ */
+ function setPath($path)
+ {
+ // look for special windows case
+ if(SMART_PATH_DELIMITER === '\\')
+ $this->path = strtr($path,'/','\\');
+ else
+ $this->path = $path;
+ }
+
+ /**
+ * @return string fully delimited path (OS-dependent format)
+ */
+ function getPath()
+ {
+ if (!isset($this->path)) return false;
+ return $this->path;
+ }
+
+ /**
+ * @param array $packages array of packages to display in documentation (package1,package2,...)
+ * @see phpDocumentor_IntermediateParser::$packageoutput
+ */
+ function setPackageOutput($packages)
+ {
+ $this->packageOutput = $packages;
+ }
+
+ /**
+ * @return array array of packages (package1,package2,...)
+ * @see phpDocumentor_IntermediateParser::$packageoutput
+ */
+ function getPackageOutput()
+ {
+ return $this->packageOutput;
+ }
+
+ /**
+ * @param string $name phpdoc-safe name (only _, numbers and letters) set by Parser::parse()
+ * @see Parser::parse()
+ */
+ function setName($name)
+ {
+ $this->name = $name;
+ }
+
+ /**
+ * @return string phpdoc-safe name (only _, numbers and letters)
+ */
+ function getName()
+ {
+ if (!isset($this->name)) return false;
+ return $this->name;
+ }
+
+ /**
+ * @param string $source path of this file relative to program root
+ */
+ function setSourceLocation($source)
+ {
+ $this->sourceLocation = $source;
+ }
+
+ /**
+ * @param Converter
+ * @param boolean if this parameter is true, it will truncate the source location to the
+ * subdirectory of pear
+ * @return string path of this file relative to program root
+ */
+ function getSourceLocation ($c,$pearize = false)
+ {
+ global $_phpDocumentor_options;
+ if (!isset($this->sourceLocation)) return false;
+ if ($pearize)
+ {
+ $sl = $this->sourceLocation;
+ if (strpos($sl,'pear/'))
+ {
+ $sl = substr($sl,strpos($sl,'pear/') + 5);
+ return $sl;
+ } else
+ {
+ return str_replace($_phpDocumentor_options['Program_Root'] . PATH_DELIMITER,'',$sl);
+ }
+ return $sl;
+ }
+ return $this->sourceLocation;
+ }
+ /**
+ * Not implemented in this version
+ * @return boolean tell the parser whether to parse the file, otherwise
+ * this function will retrieve the parsed data from external file
+ */
+ function getParseData()
+ {
+ return true;
+ }
+}
+
+/**
+ * Contains an in-memory representation of all documentable elements
+ * ({@link parserPage}, {@link parserFunction}, {@link parserDefine},
+ * {@link parserInclude}, {@link parserClass}, {@link parserMethod},
+ * {@link parserVar}) and their DocBlocks ({@link parserDocBlock}).
+ *
+ * This class works in coordination with {@link phpDocumentor_IntermediateParser}
+ * to take output from {@link Parser::handleEvent()} and create indexes, links,
+ * and other assorted things (all documented in phpDocumentor_IntermediateParser
+ * and {@link Converter})
+ * @package phpDocumentor
+ * @subpackage ParserData
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: ParserData.inc,v 1.1 2005/10/17 18:36:57 jeichorn Exp $
+ */
+class parserData
+{
+ /**
+ * {@link parserPage} element that is this parserData's parent, or false if
+ * not set.
+ * @var false|parserPage
+ */
+ var $parent = false;
+ /**
+ * array of parsed elements
+ * @var array
+ */
+ var $elements = array();
+ /**
+ * array of parsed elements with @access private
+ * @var array
+ */
+ var $privateelements = array();
+ /**
+ * array of parsed class elements
+ * @var array
+ */
+ var $classelements = array();
+
+ /**
+ * @var parserTutorial|false
+ */
+ var $tutorial = false;
+ /**
+ * array of parsed class elements with @access private
+ * @var array
+ */
+ var $privateclasselements = array();
+ /**
+ * array of links descended from {@link abstractLink}
+ * @var array
+ * @see pageLink, defineLink, classLink, functionLink, methodLink, varLink
+ */
+ var $links = array();
+ /**
+ * used by {@link phpDocumentor_IntermediateParser::handleDocBlock()} to
+ * determine whether a docblock is a page-level docblock or not. $clean is
+ * true as long as only 0 or 1 docblock has been parsed, and no element
+ * other than parserPage has been parsed
+ * @var boolean
+ */
+ var $clean = true;
+ /**
+ * DocBlock ({@link parserDocBlock}) for this page, or false if not set
+ * @var mixed
+ */
+ var $docblock = false;
+ /**
+ * Flag used to determine whether a page-level docblock is present
+ * @var boolean
+ * @access private
+ */
+ var $_explicitdocblock = false;
+ /**
+ * Type is used by many functions to skip the hassle of if
+ * <code>phpDocumentor_get_class($blah) == 'parserBlah'</code>
+ * always 'page', used in element indexing and conversion functions found in
+ * {@link Converter}
+ * @var string
+ */
+ var $type = 'page';
+
+ /**
+ * @param parserElement add a parsed element to the {@link $elements} array,
+ * also sets {@link $clean} to false
+ */
+ function addElement(&$element)
+ {
+ $element->setPath($this->parent->path);
+ if ($element->getType() == 'class' || $element->getType() == 'method' || $element->getType() == 'var'
+ || $element->getType() == 'const')
+ {
+ $this->classelements[] = $element;
+ } else
+ {
+ $this->elements[] = $element;
+ }
+ $this->clean = false;
+ }
+
+ /**
+ * @param parserTutorial
+ * @param Converter
+ */
+ function addTutorial($t,&$c)
+ {
+ $this->tutorial = new tutorialLink;
+ $this->tutorial->addLink('',$t->path,$t->name,$t->package,$t->subpackage,$t->getTitle($c));
+ }
+
+ /**
+ * If this file has a tutorial associated with it, returns a link to the
+ * tutorial.
+ * @return tutorialLink
+ */
+ function getTutorial()
+ {
+ return $this->tutorial;
+ }
+
+ /**
+ * If the page-level DocBlock was present in the source, returns true
+ * @return boolean
+ */
+ function hasExplicitDocBlock()
+ {
+ return $this->_explicitdocblock;
+ }
+
+ /**
+ * Tells this page that its DocBlock was not implicit
+ */
+ function explicitDocBlock()
+ {
+ $this->_explicitdocblock = true;
+ }
+
+ /**
+ * @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,$classorpackage = '', $subpackage = '')
+ {
+ switch($element->type)
+ {
+ case 'function':
+ $x = new functionLink;
+ $x->addLink($this->parent->path, $this->parent->name, $element->name, $element->docblock->package, $element->docblock->subpackage);
+ return $x;
+ break;
+ case 'define':
+ $x = new defineLink;
+ $x->addLink($this->parent->path, $this->parent->name, $element->name, $element->docblock->package, $element->docblock->subpackage);
+ return $x;
+ break;
+ case 'global':
+ $x = new globalLink;
+ $x->addLink($this->parent->path, $this->parent->name, $element->name, $element->docblock->package, $element->docblock->subpackage);
+ return $x;
+ break;
+ case 'class':
+ $x = new classLink;
+ $x->addLink($this->parent->path, $this->parent->name, $element->name, $element->docblock->package, $element->docblock->subpackage);
+ return $x;
+ break;
+ case 'method':
+ $x = new methodLink;
+ $x->addLink($classorpackage, $this->parent->path, $this->parent->name, $element->name, $element->docblock->package, $element->docblock->subpackage);
+ return $x;
+ break;
+ case 'var':
+ $x = new varLink;
+ $x->addLink($classorpackage, $this->parent->path, $this->parent->name, $element->name, $element->docblock->package, $element->docblock->subpackage);
+ return $x;
+ break;
+ case 'page':
+ if (empty($classorpackage)) $classorpackage = $GLOBALS['phpDocumentor_DefaultPackageName'];
+ $x = new pageLink;
+ $x->addLink($element->path,$element->name,$element->file,$classorpackage, $subpackage);
+ return $x;
+ break;
+ }
+ }
+
+ function &getLink(&$c, $text = false)
+ {
+ return $c->getPageLink($this->parent->file, $this->docblock->package, $this->parent->path, $text);
+ }
+
+ /**
+ * returns a list of all classes declared in a file
+ * @param Converter &$c
+ * @return array Format: array(packagename => parserClass,packagename => parserClass,...)
+ */
+ function getClasses(&$c)
+ {
+ $r = $c->classes->getClassesInPath($this->parent->path);
+ $rr = array();
+ if ($r)
+ foreach($r as $class => $obj)
+ {
+ $rr[$obj->docblock->package][] = $obj;
+ }
+ return $rr;
+ }
+
+ /**
+ * Get the output-safe filename (. changed to _)
+ * @return string
+ */
+ function getName()
+ {
+ if (isset($this->parent) && $this->parent)
+ return $this->parent->getName();
+ }
+
+ /**
+ * @param parserPage parent element of this parsed data
+ */
+ function setParent(&$parent)
+ {
+ $this->parent = $parent;
+ }
+
+ /**
+ * @return bool returns the value of {@link $clean}
+ */
+ function isClean()
+ {
+ return $this->clean;
+ }
+
+ /**
+ * @param parserDocBlock
+ * @see parserDocBlock
+ */
+ function setDocBlock(&$docblock)
+ {
+ $this->docblock = $docblock;
+ }
+}
+
+/**
+ * Base class for all elements
+ * @package phpDocumentor
+ * @subpackage ParserData
+ * @abstract
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: ParserData.inc,v 1.1 2005/10/17 18:36:57 jeichorn Exp $
+ */
+class parserBase
+{
+ /**
+ * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'
+ * always base
+ * @var string
+ */
+ var $type = 'base';
+ /**
+ * set to different things by its descendants
+ * @abstract
+ * @var mixed
+ */
+ var $value = false;
+
+ /**
+ * @return string returns value of {@link $type}
+ */
+ function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * @param mixed set the value of this element
+ */
+ function setValue($value)
+ {
+ $this->value = $value;
+ }
+
+ /**
+ * @return mixed get the value of this element (element-dependent)
+ */
+ function getValue()
+ {
+ return $this->value;
+ }
+}
+
+
+/**
+ * Used to represent strings that contain inline tags, so that they can be properly parsed at link time
+ * @package phpDocumentor
+ * @subpackage ParserData
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: ParserData.inc,v 1.1 2005/10/17 18:36:57 jeichorn Exp $
+ */
+class parserStringWithInlineTags extends parserBase
+{
+ /**
+ * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'
+ * always '_string'
+ * @var string
+ */
+ var $type = '_string';
+ /** @access private */
+ var $cache = false;
+ /**
+ * array of strings and {@link parserInlineTag}s
+ * Format:
+ * array(string1,string2,parserInlineTag1,string3,parserInlineTag2,...)
+ * @var array
+ */
+ var $value = array();
+
+ /**
+ * equivalent to the . operator ($a = $b . $c)
+ * @param mixed either a string or a {@link parserInlineTag}
+ */
+ function add($stringOrInlineTag)
+ {
+ if (is_string($stringOrInlineTag))
+ {
+ if (!count($this->value))
+ {
+ $this->value[] = $stringOrInlineTag;
+ return;
+ }
+ if (is_string($this->value[count($this->value) - 1]))
+ {
+ $this->value[count($this->value) - 1] .= $stringOrInlineTag;
+ return;
+ } else
+ {
+ $this->value[] = $stringOrInlineTag;
+ return;
+ }
+ } else
+ {
+ if (is_a($stringOrInlineTag,'parserinlinetag') && phpDocumentor_setup::checkIgnoreTag($stringOrInlineTag->inlinetype, true)) return;
+ $this->value[] = $stringOrInlineTag;
+ }
+ }
+
+ /**
+ * Determine whether the string contains any inline tags
+ * @tutorial inlinetags.pkg
+ * @return boolean
+ */
+ function hasInlineTag()
+ {
+ for($i=0;$i<count($this->value);$i++)
+ {
+ if (is_a($this->value[$i],'parserinlinetag')) return true;
+ }
+ return false;
+ }
+
+ /**
+ * Pass source code to any {@}source} tags contained within the string
+ * for later conversion.
+ * @param string|array source code ready to be highlighted
+ */
+ function setSource($source)
+ {
+ for($i=0;$i<count($this->value);$i++)
+ {
+ if (phpDocumentor_get_class($this->value[$i]) == 'parsersourceinlinetag')
+ {
+ $this->value[$i]->setSource($source);
+ }
+ }
+ }
+
+ /**
+ * equivalent to trim(strlen($string))
+ * @return integer length of the string this object represents
+ */
+ function trimmedStrlen()
+ {
+ $a = 0;
+ for($i=0;$i<count($this->value);$i++)
+ {
+ if (is_string($this->value[$i]))
+ {
+ if ($i == 0)
+ {
+ $a += strlen(ltrim($this->value[$i]));
+ } elseif ($i == count($this->value[$i]) - 1)
+ {
+ $a += strlen(chop($this->value[$i]));
+ }
+ } else
+ {
+ $a += $this->value[$i]->Strlen();
+ }
+ }
+ return $a;
+ }
+
+ /**
+ * return the string unconverted (all inline tags are taken out - this
+ * should only be used in pre-parsing to see if any other text
+ * is in the string)
+ * @uses parserInlineTag::getString() removes inline tag length, as it is
+ * indeterminate until conversion.
+ * @return string trimmed value
+ */
+ function getString($trim = true)
+ {
+ $a = '';
+ for($i=0; $i<count($this->value); $i++)
+ {
+ if (is_string($this->value[$i]))
+ {
+ $a .= $this->value[$i];
+ } else
+ {
+ $a .= $this->value[$i]->getString();
+ }
+ }
+ if ($trim) $a = trim($a);
+ return $a;
+ }
+
+ /**
+ * Use to convert the string to a real string with all inline tags parsed and linked
+ * @see Converter::returnSee()
+ * @param Converter
+ * @param boolean true if one needs to postprocess
+ * @param boolean false if the output should not be trimmed
+ */
+ function Convert(&$converter,$postprocess = true, $trim = true)
+ {
+ if ($this->cache)
+ {
+ if ($converter->name == $this->cache['name'] && $converter->outputformat == $this->cache['output'] && $converter->checkState($this->cache['state']) && $this->cache['postprocess'] === $postprocess) return $this->cache['contents'];
+ if ($converter->name != $this->cache['name']) {
+ $this->cache = false;
+ }
+ }
+ if (is_string($this->value)) return $this->value;
+ $a = '';
+ for($i=0; $i<count($this->value); $i++)
+ {
+ if (is_string($this->value[$i]))
+ {
+ if ($postprocess && !method_exists($converter,'postProcess')) var_dump('a',$converter);
+ if ($postprocess) $a .= $converter->postProcess($this->value[$i]);
+ else $a .= $this->value[$i];
+ } else
+ {
+ $a .= $this->value[$i]->Convert($converter, $postprocess);
+ }
+ }
+ if ($trim) {
+ $a = trim($a);
+ }
+ $this->cache = array('name' => $converter->name,'output' => $converter->outputformat, 'contents' => $a, 'state' => $converter->getState(), 'postprocess' => $postprocess);
+ return $a;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/ParserDescCleanup.inc b/buildscripts/PhpDocumentor/phpDocumentor/ParserDescCleanup.inc
new file mode 100644
index 00000000..bd80d104
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/ParserDescCleanup.inc
@@ -0,0 +1,1456 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * All of the functions to clean up and handle the long description
+ * of a DocBlock are in this file.
+ *
+ * The primary functionality is based on Parser and WordParser, and modified to recognize
+ * only the tokens defined in the PHPDOCUMENTOR_PDP_* constants
+ * @see Parser, WordParser
+ * @package phpDocumentor
+ * @subpackage Parsers
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.2
+ */
+/**#@+
+ * {@link parserDescParser} token constants
+ */
+/** when <<code>> is found in a desc */
+define('PHPDOCUMENTOR_PDP_EVENT_CODE', 600);
+/** when <<code>> is found in a desc */
+define('PHPDOCUMENTOR_PDP_STATE_CODE', 700);
+/** when <<p>> is found in a desc */
+define('PHPDOCUMENTOR_PDP_EVENT_P', 601);
+/** when <<p>> is found in a desc */
+define('PHPDOCUMENTOR_PDP_STATE_P', 701);
+/** when \n\n is found in a desc */
+define('PHPDOCUMENTOR_PDP_EVENT_DOUBLECR', 602);
+/** when \n\n is found in a desc */
+define('PHPDOCUMENTOR_PDP_STATE_DOUBLECR', 702);
+/** when <<pre>> is found in a desc */
+define('PHPDOCUMENTOR_PDP_EVENT_PRE', 603);
+/** when <<pre>> is found in a desc */
+define('PHPDOCUMENTOR_PDP_STATE_PRE', 703);
+/** when <<ul>>/<<ol>> is found in a desc */
+define('PHPDOCUMENTOR_PDP_EVENT_LIST', 604);
+/** when <<ul>>/<<ol>> is found in a desc */
+define('PHPDOCUMENTOR_PDP_STATE_LIST', 704);
+/** when <<b>> is found in a desc */
+define('PHPDOCUMENTOR_PDP_EVENT_B', 605);
+/** when <<b>> is found in a desc */
+define('PHPDOCUMENTOR_PDP_STATE_B', 705);
+/** when <<i>> is found in a desc */
+define('PHPDOCUMENTOR_PDP_EVENT_I', 606);
+/** when <<i>> is found in a desc */
+define('PHPDOCUMENTOR_PDP_STATE_I', 706);
+/** when <<br>> is found in a desc */
+define('PHPDOCUMENTOR_PDP_EVENT_BR', 607);
+/** when <<br>> is found in a desc */
+define('PHPDOCUMENTOR_PDP_STATE_BR', 707);
+/** when the << potential escape for tags is found in a desc */
+define('PHPDOCUMENTOR_PDP_EVENT_ESCAPE',608);
+/** when the << potential escape for tags is found in a desc */
+define('PHPDOCUMENTOR_PDP_STATE_ESCAPE',708);
+/** when << /pre>> is found in a <<pre>><</pre>> section */
+define('PHPDOCUMENTOR_PDP_EVENT_ESCAPE_PRE',609);
+/** when << /pre>> is found in a <<pre>><</pre>> section */
+define('PHPDOCUMENTOR_PDP_STATE_ESCAPE_PRE',709);
+/** when << /code>> is found in a <<code>><</code>> section */
+define('PHPDOCUMENTOR_PDP_EVENT_ESCAPE_CODE',610);
+/** when << /code>> is found in a <<code>><</code>> section */
+define('PHPDOCUMENTOR_PDP_STATE_ESCAPE_CODE',710);
+/** when <<var>> is found in a desc */
+define('PHPDOCUMENTOR_PDP_EVENT_VAR',611);
+/** when <<var>> is found in a desc */
+define('PHPDOCUMENTOR_PDP_STATE_VAR',711);
+/** when <<samp>> is found in a desc */
+define('PHPDOCUMENTOR_PDP_EVENT_SAMP',612);
+/** when <<samp>> is found in a desc */
+define('PHPDOCUMENTOR_PDP_STATE_SAMP',712);
+/** when <<kbd>> is found in a desc */
+define('PHPDOCUMENTOR_PDP_EVENT_KBD',613);
+/** when <<kbd>> is found in a desc */
+define('PHPDOCUMENTOR_PDP_STATE_KBD',713);
+/** when a simple list is found in a desc
+ *
+ * like
+ * <pre>
+ * o item 1
+ * o item 2
+ * </pre>
+ */
+define('PHPDOCUMENTOR_PDP_EVENT_SIMLIST',614);
+/** when a simple list is found in a desc
+ *
+ * like
+ * <pre>
+ * o item 1
+ * o item 2
+ * </pre>
+ */
+define('PHPDOCUMENTOR_PDP_STATE_SIMLIST',714);
+/**#@-*/
+/**
+* Like WordParser but designed to handle an array with strings and
+* {@link parserInlineTag}s
+* @package phpDocumentor
+* @subpackage WordParsers
+* @author Greg Beaver <cellog@users.sourceforge.net>
+* @since 1.2
+*/
+class ObjectWordParser extends WordParser
+{
+ /**
+ * Determines whether text searching is case-sensitive or not
+ * @access private
+ */
+ var $_casesensitive = false;
+
+ function ObjectWordParser($casesensitive = false)
+ {
+ $this->_casesensitive = $casesensitive;
+ }
+
+ /**
+ * Set the word parser to go.
+ *
+ * @param array {@link parserStringWithInlineTags::$value} style-array, with
+ * alternating text and inline tags
+ */
+ function setup(&$input)
+ {
+// if (is_string($input[0])) $input[0] = ltrim($input[0]);
+ $this->data = & $input;
+ $this->pos = 0;
+ $this->linenum = 0;
+ $this->linenumpos = 0;
+ $this->cache = array();
+ reset($this->data);
+ list($this->index,) = each($this->data);
+ if (!is_object($this->data[$this->index]))
+ $this->size = strlen($this->data[$this->index]);
+ else $this->size = 0;
+ //$this->run = 0;
+ //$this->word = WORD_PARSER_RET_WORD;
+ }
+
+ function getWord()
+ {
+ if (!isset($this->data[$this->index])) return false;
+ // return any inline tags unchanged
+ if (is_object($this->data[$this->index]))
+ {
+ $index = $this->index;
+ list($this->index,) = each($this->data);
+ $this->pos = 0;
+ if ($this->index)
+ {
+ if (!is_object($this->data[$this->index]))
+ $this->size = strlen($this->data[$this->index]);
+ else $this->size = 0;
+ $this->cache = array();
+ return $this->data[$index];
+ } else
+ {
+ return false;
+ }
+ }
+ //$st = $this->mtime();
+ if ($this->size == $this->pos)
+ {
+ // cycle to next line in the array
+ list($this->index,) = each($this->data);
+ if (!$this->index) return false;
+ $this->pos = 0;
+ if (!is_object($this->data[$this->index]))
+ $this->size = strlen($this->data[$this->index]);
+ else $this->size = 0;
+ $this->cache = array();
+ return $this->getWord();
+ }
+
+ $npos = $this->size;
+ if (is_array($this->wordseperators))
+ {
+ //$this->wordseperators = array();
+ foreach($this->wordseperators as $sep)
+ {
+ if (isset($this->cache[$sep]))
+ $tpos = $this->cache[$sep];
+ else
+ $tpos = false;
+ if ($tpos < $this->pos || !is_int($tpos))
+ {
+ if ($this->_casesensitive)
+ $tpos = strpos($this->data[$this->index],$sep,$this->pos);
+ else
+ $tpos = strpos(strtolower($this->data[$this->index]),$sep,$this->pos);
+ }
+
+ if ( ($tpos < $npos) && !($tpos === false))
+ {
+ //echo trim($sep) . "=$tpos\n";
+ $npos = $tpos;
+ $seplen = strlen($sep);
+ }
+ else if (!($tpos === false))
+ {
+ $this->cache[$sep] = $tpos;
+ }
+ }
+ } else {
+ // its time to cycle
+ return "";
+ }
+
+ $len = $npos - $this->pos;
+ if ($len == 0)
+ {
+ $len = $seplen;
+ }
+
+ //$st3 = $this->mtime();
+ $word = substr($this->data[$this->index],$this->pos,$len);
+
+ // Change random other os newlines to the unix one
+ if ($word == "\r" || $word == "\r\n")
+ {
+ $word = "\n";
+ }
+
+ if ($this->linenumpos <= $this->pos)
+ {
+ $this->linenumpos = $this->pos + $len;
+ $this->linenum += count(explode("\n",$word)) - 1;
+ }
+
+ if ($this->getsource)
+ {
+ $this->source .= $word;
+ }
+ $this->pos = $this->pos + $len;
+ //$this->word = WORD_PARSER_RET_SEP;
+
+ // Things like // commenats rely on the newline to find their end so im going to have to return them
+ // never return worthless white space /t ' '
+ if ($this->returnWhiteSpace == false)
+ {
+ if (strlen(trim($word)) == 0 && $word != "\n")
+ {
+ $word = $this->getWord();
+ }
+ }
+ //$this->time3 = $this->time3 + ($this->mtime() - $st3);
+ //$this->time = $this->time + ($this->mtime() - $st);
+ return $word;
+ }
+
+ /**
+ * Determine if the next word is an inline tag
+ * @return boolean
+ */
+ function nextIsObjectOrNonNL()
+ {
+ return (($this->size == $this->pos) && isset($this->data[$this->index + 1])
+ && is_object($this->data[$this->index + 1])) ||
+ (($this->size > $this->pos) && !in_array($this->data[$this->index]{$this->pos}, array("\n", "\r")));
+ }
+}
+
+/**
+ * Parses a DocBlock description to retrieve abstract representations of
+ * <<pre>>,<<code>>,<<p>>,<<ul>>,<<ol>>,<<li>>,<<b>>,<<i>>
+ * @tutorial phpDocumentor.howto.pkg#basics.desc
+ * @package phpDocumentor
+ * @subpackage Parsers
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.2
+ */
+class parserDescParser extends Parser
+{
+ /**#@+
+ * @access private
+ */
+ /**
+ * @var array
+ */
+ var $eventHandlers = array(PHPDOCUMENTOR_PDP_EVENT_CODE => 'handleCode',
+ PHPDOCUMENTOR_PDP_EVENT_PRE => 'handlePre',
+ PHPDOCUMENTOR_PDP_EVENT_P => 'handleP',
+ PHPDOCUMENTOR_PDP_EVENT_DOUBLECR => 'handleDoubleCR',
+ PHPDOCUMENTOR_PDP_EVENT_LIST => 'handleList',
+ PHPDOCUMENTOR_PDP_EVENT_B => 'handleB',
+ PHPDOCUMENTOR_PDP_EVENT_I => 'handleI',
+ PHPDOCUMENTOR_PDP_EVENT_VAR => 'handleVar',
+ PHPDOCUMENTOR_PDP_EVENT_KBD => 'handleKbd',
+ PHPDOCUMENTOR_PDP_EVENT_SAMP => 'handleSamp',
+ PHPDOCUMENTOR_PDP_EVENT_BR => 'handleBr',
+ PHPDOCUMENTOR_PDP_EVENT_ESCAPE => 'handleEscape',
+ PHPDOCUMENTOR_PDP_EVENT_ESCAPE_CODE => 'handleEscapeCode',
+ PHPDOCUMENTOR_PDP_EVENT_ESCAPE_PRE => 'handleEscapePre',
+ PHPDOCUMENTOR_PDP_EVENT_SIMLIST => 'handleSimpleList',
+ PARSER_EVENT_NOEVENTS => 'defaultHandler',
+ );
+
+ /**
+ * @var array
+ */
+ var $pars = array();
+ /**
+ * Determines whether parsing of &lt;p&gt; tags will occur, or double CR will
+ * be used
+ * @var boolean
+ */
+ var $parse_Ps;
+ /**
+ * Context stack.
+ *
+ * Values can be 'normal', or any tag container like 'my_i', 'my_b'. This
+ * is used to determine which tag text or nested tags should be added to
+ * @var array
+ */
+ var $_context = array('normal');
+ /**#@-*/
+
+ /**
+ * sets $wp to be a {@link ObjectWordParser}
+ *
+ * $wp is the word parser that retrieves tokens
+ */
+ function parserDescParser()
+ {
+ $this->wp = new ObjectWordParser;
+ }
+
+ /**
+ * Parse a long or short description for tags
+ *
+ * @param array array of strings or {@link parserInlineTag}s
+ * @param boolean true if the description is a short description. (only 1 paragraph allowed in short desc)
+ * @param string name of the class to instantiate for each paragraph. parserDesc for desc/sdesc,
+ * parserStringWithInlineTags for tag data
+ * @staticvar integer used for recursion limiting if a handler for an event is not found
+ */
+ function parse (&$parse_data,$sdesc = false,$ind_type = 'parserDesc')
+ {
+ static $endrecur = 0;
+ global $_phpDocumentor_setting;
+ if (!is_array($parse_data) || count($parse_data) == 0)
+ {
+ return false;
+ }
+ $this->p_vars['indtype'] = $ind_type;
+ $this->setupStates($sdesc);
+ if (isset($_phpDocumentor_setting['javadocdesc']) && $_phpDocumentor_setting['javadocdesc'] == 'on')
+ $this->parse_Ps = true;
+
+ // initialize variables so E_ALL error_reporting doesn't complain
+ $pevent = 0;
+ $word = 0;
+ $this->p_vars['curpar'] = 0;
+ $this->pars = array();
+ $this->p_vars['start'] = true;
+ $this->p_vars['event_stack'] = new EventStack;
+
+ $this->wp->setup($parse_data,$sdesc);
+ $this->wp->setWhitespace(true);
+ $this->p_vars['list_count'] = 0;
+ if ($sdesc) $this->p_vars['start'] = false;
+ do
+ {
+ if (!isset($this->pars[$this->p_vars['curpar']])) $this->pars[$this->p_vars['curpar']] = new $ind_type;
+ $lpevent = $pevent;
+ $pevent = $this->p_vars['event_stack']->getEvent();
+ if ($lpevent != $pevent)
+ {
+ $this->p_vars['last_pevent'] = $lpevent;
+ }
+
+ if ($this->p_vars['last_pevent'] != $pevent)
+ {
+ // its a new event so the word parser needs to be reconfigured
+ $this->configWordParser($pevent);
+ }
+
+
+ $this->p_vars['last_word'] = $word;
+ $word = $this->wp->getWord();
+
+ if (0)//PHPDOCUMENTOR_DEBUG == true)
+ {
+ echo "----------------\n";
+ echo "LAST: |" . htmlentities($this->p_vars['last_word']) . "|\n";
+// echo "INDEX: ".$this->p_vars['curpar']."\n";
+ echo "PEVENT: " . $this->getParserEventName($pevent) . "\n";
+ echo "LASTPEVENT: " . $this->getParserEventName($this->p_vars['last_pevent']) . "\n";
+ echo $this->wp->getPos() . " WORD: |".htmlentities($word)."|\n\n";
+ var_dump($this->_context);
+ }
+ if (isset($this->eventHandlers[$pevent]))
+ {
+ $handle = $this->eventHandlers[$pevent];
+ if ($word !== false) $this->$handle($word, $pevent);
+ else
+ {
+ if (!count($this->pars[$this->p_vars['curpar']]->value)) unset($this->pars[$this->p_vars['curpar']]);
+ }
+ } else
+ {
+ debug('WARNING: possible error, no ParserDescParser handler for event number '.$pevent);
+ if ($endrecur++ == 25)
+ {
+ die("FATAL ERROR, recursion limit reached");
+ }
+ }
+ if (is_object($word) || trim($word) != '')
+ {
+ $this->p_vars['start'] = false;
+ }
+ } while (is_object($word) || !($word === false) && $word != '');
+ $context = $this->getContext();
+ if ($context != 'normal')
+ {
+ if ($context == 'list' && $this->p_flags['simplelist'])
+ {
+ $this->p_vars['lists'][0]->addItem($this->p_vars['list_item'][0]);
+ unset($this->p_vars['list_item'][0]);
+ $this->setContext('normal');
+ $this->addText($this->p_vars['lists'][0]);
+ } else addError(PDERROR_UNCLOSED_TAG,str_replace('my_','',$context));
+ }
+ if ($this->p_vars['list_count'] > 0) addError(PDERROR_UNMATCHED_LIST_TAG);
+ if ($sdesc)
+ $this->publishEvent(2,$this->pars);
+ else
+ $this->publishEvent(1,$this->pars);
+ }
+ /**#@+ @access private */
+ /**
+ * basic handling
+ *
+ * This function checks to see if the first thing in
+ * a description is the <p> tag. If so, it will switch
+ * into a mode of parsing out paragraphs by <p> instead
+ * of a double line-break
+ *
+ * It also removes extra whitespace
+ * @uses doSimpleList()
+ */
+ function defaultHandler($word, $pevent)
+ {
+ $context = $this->getContext();
+ if ($context != 'normal') $this->setContext('normal');
+ if ($this->p_vars['start'] && is_string($word) && strtolower($word) == '<p>')
+ {
+ $this->parse_Ps = true;
+ }
+ if (is_string($word) && $this->checkEventPush($word, $pevent)) return;
+// if (!isset($this->parse_Ps) || !$this->parse_Ps)
+ {
+ if (!is_object($word) && ($word == ' ' && $this->p_vars['last_word'] == ' ')) return;
+ if ($pevent == PARSER_EVENT_NOEVENTS)
+ {
+ if ($this->doSimpleList($word)) return;
+ }
+ $this->addText($word);
+ }
+ }
+
+ /**
+ * Retrieve the current top-level tag to add text into
+ * @uses $_context
+ */
+ function getContext()
+ {
+ array_push($this->_context,$a = array_pop($this->_context));
+ return $a;
+ }
+
+ /**
+ * Pop a context off of the context stack
+ * @uses $_context
+ */
+ function dropContext()
+ {
+ array_pop($this->_context);
+ if (count($this->_context) == 0)
+ $this->_context = array('normal');
+ }
+
+ /**
+ * @uses $_context
+ * @param string context name
+ */
+ function setContext($context)
+ {
+ array_push($this->_context,$context);
+ }
+
+ /**
+ * add input as text to the current paragraph or list
+ * @param string|parserInlineTag
+ */
+ function addText($text)
+ {
+ $context = $this->getContext();
+ if ($context == 'list')
+ {
+// debug('aded to '.$context);
+ $this->p_vars['list_item'][$this->p_vars['list_count']]->add($text);
+ } elseif ($context != 'normal')
+ {
+// debug('added to '.$context);
+ $this->p_vars[$context]->add($text);
+ } else
+ {
+// debug('added to normal ');
+ $indtype = $this->p_vars['indtype'];
+ if (!isset($this->pars[$this->p_vars['curpar']]))
+ $this->pars[$this->p_vars['curpar']] = new $indtype;
+ $this->pars[$this->p_vars['curpar']]->add($text);
+ }
+ }
+
+ /**#@-*/
+ /**#@+
+ * @access private
+ * @param string|parserInlineTag token from the ObjectWordParser
+ * @param integer parser event from {@link ParserDescCleanup.inc}
+ */
+ /**
+ * Handles special case where a description needs the text "<tag>" and tag
+ * is one of code, b, i, pre, var, or any other valid in-DocBlock html tag.
+ *
+ * the text <<<code>>> in a DocBlock will parse out as <<code>>, instead
+ * of being parsed as markup.
+ */
+ function handleEscape($word, $pevent)
+ {
+ $this->p_vars['event_stack']->popEvent();
+ if (!in_array($word, $this->tokens[PHPDOCUMENTOR_PDP_STATE_ESCAPE]))
+ {
+ if ($word == '<')
+ {
+ $this->addText($word);
+ $this->wp->backupPos($word.$word);
+ } else
+ $this->wp->backupPos($word);
+ return;
+ }
+ $this->addText('<'.str_replace('>>','>',$word));
+ }
+
+ /**
+ * Just like {@link handleEscape}, except the only valid escape is
+ * <<</pre>>>
+ */
+ function handleEscapePre($word, $pevent)
+ {
+ $this->p_vars['event_stack']->popEvent();
+ $this->addText('</pre>');
+ }
+
+ /**
+ * Just like {@link handleEscape}, except the only valid escape is
+ * <<</code>>>
+ */
+ function handleEscapeCode($word, $pevent)
+ {
+ $this->p_vars['event_stack']->popEvent();
+ $this->addText('</code>');
+ }
+
+ /**
+ * Handle "<<br>>"
+ * Add a new {@link parserBr}
+ * @uses addText()
+ */
+ function handleBr($word, $pevent)
+ {
+ if (is_string($word) && $this->checkEventPop($word, $pevent))
+ {
+ $this->addText(new parserBr);
+ }
+ }
+
+ /**
+ * Handles simple lists
+ *
+ * phpEdit has an ingenious facility to handle simple lists used in a
+ * DocBlock like this:
+ *
+ * - item 1
+ * - item 2
+ * - item 3
+ *
+ * The DocBlock is:
+ * <pre>
+ * * - item 1
+ * * - item 2
+ * * - item 3
+ * </pre>
+ * This function converts these simple lists into the parserList class
+ * @param boolean true if this is the first list item in the list
+ */
+ function handleSimpleList($word, $pevent, $start = false)
+ {
+ if (is_object($word) && $this->p_flags['in_item'])
+ {
+ $this->p_vars['list_item'][0]->add($word);
+ return;
+ }
+ if (is_string($word) && $this->checkEventPush($word, $pevent))
+ {
+ $this->p_flags['in_event'] = true;
+ return;
+ }
+ $ltrimword = @substr($word, @strpos($word, ltrim($word)));
+ $is_valid = false;
+ if (strlen(trim($word)) == 0)
+ {
+ if ($this->wp->nextIsObjectOrNonNL())
+ {
+ $is_valid = true;
+ }
+ }
+ if ($word == "\n" && is_string($this->p_vars['last_word'])
+ && $this->p_vars['last_word']{strlen($this->p_vars['last_word']) - 1}
+ == "\n")
+ {
+ if ($this->p_flags['in_item'])
+ {
+ $this->p_vars['lists'][0]->addItem($this->p_vars['list_item'][0]);
+ unset($this->p_vars['list_item'][0]);
+ $this->setContext('normal');
+ $this->p_flags['simplelist'] = false;
+ $this->addText($this->p_vars['lists'][0]);
+ unset($this->p_vars['lists']);
+ unset($this->p_vars['last_list']);
+ $this->wp->backuppos($word);
+ $this->p_vars['event_stack']->popEvent();
+ $this->p_flags['in_item'] = false;
+// debug('end of list 3');
+ return;
+ } else
+ {
+ $this->wp->backuppos($word);
+ $this->p_vars['event_stack']->popEvent();
+ $this->p_flags['in_item'] = false;
+// debug('not a list 2');
+ return;
+ }
+ }
+ $start_list = $this->getStartList($word);
+ if (substr($ltrimword,0,strlen($start_list)) != $start_list
+ || $this->p_flags['in_event'] || is_object($this->p_vars['last_word']))
+ {
+ if (((strlen($this->p_vars['whitespace']) + 1) < strlen(substr($word,0,strpos($word, $ltrimword))))
+ || $word == "\n"
+ || $is_valid
+ || $this->p_flags['in_event']
+ || (is_object($this->p_vars['last_word']) && $this->p_flags['in_item']))
+ {
+ $this->p_vars['list_item'][0]->add($word);
+ $this->resetStartList($start_list);
+ $this->p_flags['in_event'] = false;
+// debug('middle of list');
+ } else
+ {
+ if ($this->p_flags['in_item'])
+ {
+ $this->p_vars['lists'][0]->addItem($this->p_vars['list_item'][0]);
+ unset($this->p_vars['list_item'][0]);
+ $this->setContext('normal');
+ $this->p_flags['simplelist'] = false;
+ $this->addText($this->p_vars['lists'][0]);
+ unset($this->p_vars['lists']);
+ unset($this->p_vars['last_list']);
+ $this->wp->backuppos($word);
+ $this->p_vars['event_stack']->popEvent();
+ $this->p_flags['in_item'] = false;
+// debug('end of list 1');
+ return;
+ } else
+ {
+ $this->wp->backuppos($word);
+ $this->p_vars['event_stack']->popEvent();
+ $this->p_flags['in_item'] = false;
+// debug('not a list');
+ return;
+ }
+ }
+ } else
+ {
+ if ($this->p_vars['whitespace'] != substr($word,0,strpos($word, $start_list)))
+ { // if the whitespace is greater than that preceding the list
+ // delimiter, it's a multi-line list item
+ $this->setContext('normal');
+ $this->p_flags['simplelist'] = false;
+ $this->addText($this->p_vars['lists'][0]);
+ unset($this->p_vars['lists']);
+ $this->wp->backuppos($word);
+ $this->p_vars['event_stack']->popEvent();
+ unset($this->p_vars['last_list']);
+ $this->p_flags['in_item'] = false;
+// debug('end of list 2');
+ return;
+ } else
+ {
+ if ($this->p_flags['in_item'])
+ {
+ // end of a list item, add it to the list
+ $this->p_vars['lists'][0]->addItem($this->p_vars['list_item'][0]);
+ unset($this->p_vars['list_item'][0]);
+ }
+// debug('next list item');
+ $this->p_vars['list_item'][0] = new parserStringWithInlineTags;
+ $this->p_vars['list_item'][0]->add(ltrim(substr($ltrimword,strlen($start_list))));
+ $this->p_flags['in_item'] = true;
+ }
+ }
+ }
+ /**#@-*/
+ /**
+ * Get the next list marker
+ *
+ * In unordered lists, this will be something like "o", "-"
+ *
+ * In ordered lists, this will be either the number "3", "5" or "3.", "5."
+ * @return string text of the next list marker to look for
+ * @param string current word from the parser
+ * @access private
+ */
+ function getStartList($word)
+ {
+ // unordered, return the first marker found
+ if (!$this->p_flags['orderedlist']) return $this->p_vars['start_list'];
+ if (isset($this->p_vars['last_list']))
+ {
+ $this->p_vars['save_list'] = $this->p_vars['last_list'];
+ $next = $this->p_vars['last_list'];
+ // increment to next list number, convert to string
+ if (substr($this->p_vars['start_list'], strlen($this->p_vars['start_list']) - 1) == '.')
+ $next = (substr($next, 0, strpos($next,'.')) + 1) . '.';
+ else
+ $next = ($next + 1) . '';
+// debug("next is '$next'");
+ if ($this->p_vars['whitespace'] == substr($word,0,strpos($word, $next)))
+ return $this->p_vars['last_list'] = $next;
+ // the next number is not in this word, so return but don't save
+ return $next;
+ } else
+ {
+ $this->p_vars['last_list'] = $this->p_vars['start_list'];
+ return $this->p_vars['start_list'];
+ }
+ }
+
+ /**
+ * Set the next list marker to the current list marker
+ *
+ * In ordered lists, this will ensure that the next number returned is the
+ * right number
+ * @param string token for next list marker
+ * @access private
+ */
+ function resetStartList($start)
+ {
+ if (!isset($this->p_vars['save_list'])) return false;
+ $this->p_vars['last_list'] = $this->p_vars['save_list'];
+ }
+
+ /**#@+
+ * @access private
+ * @param string|parserInlineTag token from the ObjectWordParser
+ * @param integer parser event from {@link ParserDescCleanup.inc}
+ */
+ /**
+ * Handles <<ol>>,<<li>>,<<ul>>
+ *
+ * This allows parsing of lists nested to any level. Using
+ * the lists and list_item temporary variables and using
+ * list_count to control nesting, the method creates a {@link parserList}
+ * for each <<ol>> or <<ul>> tag, and a
+ * standard {@link parserStringWithInlineTags} for all the text, adding
+ * in nested lists as if they were inline tags (the conversion interface
+ * is the same for both object types)
+ */
+ function handleList($word, $pevent)
+ {
+ if (is_string($word) && $this->checkEventPush($word, $pevent))
+ {
+ return;
+ }
+ $ordered = false;
+ if (!is_object($this->p_vars['last_word']) && strtolower($this->p_vars['last_word']) == '<ol>')
+ {
+ // ordered list
+ $ordered = true;
+ }
+ // start a new list
+ if (!is_object($this->p_vars['last_word']) && (strtolower($this->p_vars['last_word']) == '<ol>' || strtolower($this->p_vars['last_word']) == '<ul>'))
+ {
+ $this->p_flags['in_item'] = false;
+ $this->setContext('list');
+ $this->p_vars['lists'][++$this->p_vars['list_count']] = new parserList($ordered);
+ }
+ if (!is_object($word) && strtolower($word) == '<li>')
+ {
+ if ($this->p_flags['in_item'])
+ {
+ // end of a list item (no end tag), add it to the list
+ $this->p_vars['lists'][$this->p_vars['list_count']]->addItem($this->p_vars['list_item'][$this->p_vars['list_count']]);
+ unset($this->p_vars['list_item'][$this->p_vars['list_count']]);
+ }
+ // start a new list item
+ $this->p_vars['list_item'][$this->p_vars['list_count']] = new parserStringWithInlineTags;
+ $this->p_flags['in_item'] = true;
+ } else
+ {
+ if (is_object($word) || (strtolower($word) != '</li>'))
+ {
+ if (is_object($word) || (strtolower($word) != '</ul>' && strtolower($word) != '</ol>'))
+ {
+ // item text
+ if (isset($this->p_vars['list_item'][$this->p_vars['list_count']]))
+ {
+ if ($word == ' ' && $this->p_vars['last_word'] == ' ') return;
+ $this->p_vars['list_item'][$this->p_vars['list_count']]->add($word);
+ }
+ } else
+ {
+ if ($this->p_flags['in_item'])
+ {
+ // end the current list item before ending a list
+ $this->p_vars['lists'][$this->p_vars['list_count']]->addItem($this->p_vars['list_item'][$this->p_vars['list_count']]);
+ unset($this->p_vars['list_item'][$this->p_vars['list_count']]);
+ $this->p_flags['in_item'] = false;
+ }
+ if (is_string($word) && $this->checkEventPop($word, $pevent))
+ {
+ if ($this->p_vars['list_count'] > 1)
+ {
+ // this is a sublist, add it to the list item of the parent list
+ $this->p_vars['list_item'][$this->p_vars['list_count'] - 1]->add($this->p_vars['lists'][$this->p_vars['list_count']]);
+ // remove the sublist item and sublist, drop to parent list
+ unset($this->p_vars['lists'][$this->p_vars['list_count']]);
+ unset($this->p_vars['lists'][$this->p_vars['list_count']]);
+ $this->p_vars['list_count']--;
+ $this->p_flags['in_item'] = true;
+ } else
+ {
+ // this is a primary list and it has concluded
+ $this->pars[$this->p_vars['curpar']]->add($this->p_vars['lists'][$this->p_vars['list_count']]);
+ unset($this->p_vars['lists']);
+ unset($this->p_vars['list_item']);
+ $this->p_vars['list_count'] = 0;
+ $this->dropContext();
+ }
+ }
+ }
+ } else
+ {
+ // check to make sure our list item is not unclosed
+ if (!$this->p_flags['in_item'])
+ {
+ addError(PDERROR_TEXT_OUTSIDE_LI);
+ } else
+ {
+ // end of a list item, add it to the list
+ $this->p_vars['lists'][$this->p_vars['list_count']]->addItem($this->p_vars['list_item'][$this->p_vars['list_count']]);
+ unset($this->p_vars['list_item'][$this->p_vars['list_count']]);
+ $this->p_flags['in_item'] = false;
+ }
+ }
+ }
+ }
+
+ /**
+ * Handles <<code>><</code>> blocks
+ */
+ function handleCode($word, $pevent)
+ {
+ if (!isset($this->p_vars['my_code']))
+ {
+ $this->setContext('my_code');
+ $this->p_vars['my_code'] = new parserCode;
+ }
+ if (is_string($word) && $this->checkEventPush($word, $pevent)) return;
+ if (is_object($word) || strtolower($word) != '</code>') $this->p_vars['my_code']->add($word);
+ if (is_string($word))
+ {
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->dropContext();
+ $this->addText($this->p_vars['my_code']);
+ unset($this->p_vars['my_code']);
+ }
+ }
+ }
+
+ /**
+ * Handles <<pre>><</pre>> blocks
+ */
+ function handlePre($word, $pevent)
+ {
+ if (!isset($this->p_vars['my_pre']))
+ {
+ $this->setContext('my_pre');
+ $this->p_vars['my_pre'] = new parserPre;
+ }
+ if (is_string($word) && $this->checkEventPush($word, $pevent)) return;
+ if (is_object($word) || strtolower($word) != '</pre>') $this->p_vars['my_pre']->add($word);
+ if (is_string($word))
+ {
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->dropContext();
+ $this->addText($this->p_vars['my_pre']);
+ unset($this->p_vars['my_pre']);
+ }
+ }
+ }
+
+ /**
+ * Handles <<b>><</b>> blocks
+ */
+ function handleB($word, $pevent)
+ {
+ if (!isset($this->p_vars['my_b']))
+ {
+ $this->setContext('my_b');
+ $this->p_vars['my_b'] = new parserB;
+ }
+ if (is_string($word))
+ {
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->dropContext();
+ $this->addText($this->p_vars['my_b']);
+ unset($this->p_vars['my_b']);
+ } else
+ {
+ $this->p_vars['my_b']->add($word);
+ }
+ } else $this->p_vars['my_b']->add($word);
+ }
+
+ /**
+ * Handles <<i>><</i>> blocks
+ */
+ function handleI($word, $pevent)
+ {
+ if (!isset($this->p_vars['my_i']))
+ {
+ $this->p_vars['my_i'] = new parserI;
+ $this->setContext('my_i');
+ }
+ if (is_string($word))
+ {
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->dropContext();
+ $this->addText($this->p_vars['my_i']);
+ unset($this->p_vars['my_i']);
+ } else
+ {
+ $this->p_vars['my_i']->add($word);
+ }
+ } else $this->p_vars['my_i']->add($word);
+ }
+
+ /**
+ * Handles <<var>><</var>> blocks
+ */
+ function handleVar($word, $pevent)
+ {
+ if (!isset($this->p_vars['my_var']))
+ {
+ $this->setContext('my_var');
+ $this->p_vars['my_var'] = new parserDescVar;
+ }
+ if (is_string($word))
+ {
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->dropContext();
+ $this->addText($this->p_vars['my_var']);
+ unset($this->p_vars['my_var']);
+ } else
+ {
+ $this->p_vars['my_var']->add($word);
+ }
+ } else $this->p_vars['my_var']->add($word);
+ }
+
+ /**
+ * Handles <<samp>><</samp>> blocks
+ */
+ function handleSamp($word, $pevent)
+ {
+ if (!isset($this->p_vars['my_samp']))
+ {
+ $this->setContext('my_samp');
+ $this->p_vars['my_samp'] = new parserSamp;
+ }
+ if (is_string($word))
+ {
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->dropContext();
+ $this->addText($this->p_vars['my_samp']);
+ unset($this->p_vars['my_samp']);
+ } else
+ {
+ $this->p_vars['my_samp']->add($word);
+ }
+ } else $this->p_vars['my_samp']->add($word);
+ }
+
+ /**
+ * Handles <<kbd>><</kbd>> blocks
+ */
+ function handleKbd($word, $pevent)
+ {
+ if (!isset($this->p_vars['my_kbd']))
+ {
+ $this->setContext('my_kbd');
+ $this->p_vars['my_kbd'] = new parserKbd;
+ }
+ if (is_string($word))
+ {
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->dropContext();
+ $this->addText($this->p_vars['my_kbd']);
+ unset($this->p_vars['my_kbd']);
+ } else
+ {
+ $this->p_vars['my_kbd']->add($word);
+ }
+ } else $this->p_vars['my_kbd']->add($word);
+ }
+
+ /**
+ * Handles <<p>><</p>> blocks
+ *
+ * Note that the only time <<p>> will be interpreted as delimiting a
+ * paragraph is if it is the first thing in the description.
+ */
+ function handleP($word, $pevent)
+ {
+ if (!isset($this->parse_Ps)) $this->parse_Ps = false;
+ if (is_string($word))
+ {
+ if (is_string($word) && $this->checkEventPush($word, $pevent)) return;
+ }
+ if (!$this->parse_Ps)
+ {
+ $this->p_vars['event_stack']->popEvent();
+ if (!is_object($word) && strtolower($this->p_vars['last_word']) == '<p>') $this->addText('<p>');
+ $this->addText($word);
+ return;
+ }
+ if ($word == "\n") $word = " ";
+ if (is_string($word))
+ {
+ if ($this->checkEventPop($word, $pevent))
+ {
+ $this->p_vars['curpar']++;
+ return;
+ }
+ // if no closing tag, pretend there was one
+ if (!is_object($word) && strtolower($word) == '<p>' && $this->parse_Ps)
+ {
+ $this->p_vars['curpar']++;
+ return;
+ }
+ }
+ if ($this->p_vars['start'])
+ {
+ $this->addText($word);
+ } else
+ {// if the <p> is not at the beginning of the desc, then it is not
+ // possible to parse into paragraphs using this tag
+ if ($word == ' ' && $this->p_vars['last_word'] == ' ') return;
+ $this->addText($word);
+ }
+ }
+
+ /**
+ * Handles \n\n as a paragraph marker
+ * @uses doSimpleList()
+ */
+ function handleDoubleCR($word, $pevent)
+ {
+ $this->p_vars['event_stack']->popEvent();
+ if ($word == "\n")
+ {
+ // only use this if <p> isn't being used
+ if ((!isset($this->parse_Ps) || !$this->parse_Ps))
+ {
+ if ($this->p_vars['last_word'] == "\n")
+ {
+ $this->p_vars['curpar']++;
+ $this->parse_Ps = false;
+ } else
+ {
+ if (is_string($word) && !$this->checkEventPush($word, $pevent))
+ {
+ if ($word == ' ' && $this->p_vars['last_word'] == ' ') return;
+ $this->addText($word);
+ }
+ }
+ } else
+ {
+ if (is_string($word) && !$this->checkEventPush($word, $pevent))
+ {
+ if ($word == ' ' && $this->p_vars['last_word'] == ' ') return;
+ $this->addText($word);
+ }
+ }
+ } else
+ {
+ if ($this->p_vars['last_word'] == "\n")
+ {
+ if ((!isset($this->parse_Ps) || !$this->parse_Ps))
+ {
+ $this->addText(' ');
+ }
+ }
+ if (is_string($word) && !($e = $this->checkEventPush($word, $pevent)))
+ {
+ if ($word == ' ' && $this->p_vars['last_word'] == ' ') return;
+ if ($this->doSimpleList($word)) return;
+ $this->addText($word);
+ }
+ }
+ }
+
+ /**#@-*/
+ /**
+ * Return a simple list, if found
+ *
+ * This helper function extracts a simple list beginning with any of
+ * 'o','-'.'#','+','0','1','0.','1.' and starts parsing it.
+ * @param string line that may contain a simple list
+ * @return boolean true if a list is found, false otherwise
+ */
+ function doSimpleList($word)
+ {
+ if ($this->p_flags['in_event']) return true;
+ if (is_object($word)) return false;
+ $ltrimword = ltrim($word);
+ if ((strlen($ltrimword) != strlen($word))
+ && strlen($ltrimword) > 1
+ && ((in_array($ltrimword{0},array('o','-','1','0','#','+')) && $ltrimword{1} == ' '))
+ || ((strlen($ltrimword) >= 2) && (in_array(substr($ltrimword,0,2),array('1.','0.')) && $ltrimword{2} == ' ')))
+ {
+ // save the whitespace for comparison
+ $this->p_vars['whitespace'] = substr($word,0,strlen($word) - strlen($ltrimword));
+ $this->p_vars['start_list'] = $ltrimword{0};
+ if ($this->p_vars['start_list'] != '1' && $this->p_vars['start_list'] != '1.' &&
+ $this->p_vars['start_list'] != '0' && $this->p_vars['start_list'] != '0.')
+ {
+ $this->p_flags['orderedlist'] = false;
+ } else
+ {
+ if (substr($ltrimword,0,2) == '1.')
+ {
+ $this->p_vars['start_list'] = '1.';
+ }
+ $this->p_flags['orderedlist'] = true;
+ }
+ $this->p_vars['event_stack']->pushEvent(PHPDOCUMENTOR_PDP_EVENT_SIMLIST);
+ $this->setContext('list');
+ $this->p_flags['simplelist'] = true;
+ $this->p_vars['lists'][0] = new parserList($this->p_flags['orderedlist']);
+ $this->p_vars['list_count'] = 0;
+ $this->handleSimpleList($word, PHPDOCUMENTOR_PDP_EVENT_SIMLIST, true);
+ return true;
+ }
+ return false;
+ }
+ /**
+ * setup the parser tokens, and the pushEvent/popEvent arrays
+ * @see $tokens, $pushEvent, $popEvent
+ * @param boolean determines whether to allow paragraph parsing
+ * @global boolean used to determine whether to slow things down or not by
+ * eliminating whitespace from comments
+ */
+
+ function setupStates($sdesc)
+ {
+ $this->p_flags['in_item'] = false;
+ $this->p_flags['in_event'] = false;
+ $this->p_flags['simplelist'] = false;
+ $this->_context = array('normal');
+ $this->tokens[STATE_NOEVENTS] = array("\n", "<code>", "<pre>", "<ol>", "<ul>",
+ "<b>", "<i>", '<var>', '<kbd>', '<samp>', "<br", '<<');
+ if (!$sdesc)
+ {
+ $this->tokens[STATE_NOEVENTS][] = "<p>";
+ $this->tokens[STATE_NOEVENTS][] = "</p>";
+ }
+ if (PHPDOCUMENTOR_KILL_WHITESPACE) $this->tokens[STATE_NOEVENTS][] = ' ';
+ $this->tokens[PHPDOCUMENTOR_PDP_STATE_P] = array("</p>","<code>","<pre>","\n","<ol>","<ul>","<b>","<i>","<br","<p>", '<<',
+ '<var>', '<kbd>', '<samp>');
+ if (PHPDOCUMENTOR_KILL_WHITESPACE) $this->tokens[PHPDOCUMENTOR_PDP_STATE_P][] = ' ';
+ $this->tokens[PHPDOCUMENTOR_PDP_STATE_CODE] = array("</code>", '<</code>>');
+ $this->tokens[PHPDOCUMENTOR_PDP_STATE_PRE] = array("</pre>", '<</pre>>');
+ $this->tokens[PHPDOCUMENTOR_PDP_STATE_LIST] = array("<ul>","<ol>","</ul>","</ol>","<li>","</li>","<b>","<i>","<br", '<<',"<code>","<pre>","<br",
+ '<var>', '<kbd>', '<samp>');
+ $this->tokens[PHPDOCUMENTOR_PDP_STATE_DOUBLECR] = array("\n","<ol>","<ul>","<code>","<pre>","<b>","<i>","<br","<p>","</p>",
+ '<var>', '<kbd>', '<samp>', '<<');
+ $this->tokens[PHPDOCUMENTOR_PDP_STATE_SIMLIST] = array("\n",'<var>', '<kbd>', '<samp>','<b>','<i>', '<pre>', '<code>',
+ '<br', '<<');
+
+ $this->tokens[PHPDOCUMENTOR_PDP_STATE_B] = array("<code>","\n","<pre>","<ol>","<ul>","</b>","<i>","<br", '<<',
+ '<var>', '<kbd>', '<samp>');
+ $this->tokens[PHPDOCUMENTOR_PDP_STATE_KBD] = array("<code>","\n","<pre>","<ol>","<ul>","<b>","<i>","<br", '<<',
+ '<var>', '</kbd>', '<samp>');
+ $this->tokens[PHPDOCUMENTOR_PDP_STATE_VAR] = array("<code>","\n","<pre>","<ol>","<ul>","<b>","<i>","<br", '<<',
+ '</var>', '<kbd>', '<samp>');
+ $this->tokens[PHPDOCUMENTOR_PDP_STATE_SAMP] = array("<code>","\n","<pre>","<ol>","<ul>","<b>","<i>","<br", '<<',
+ '<var>', '<kbd>', '</samp>');
+ $this->tokens[PHPDOCUMENTOR_PDP_STATE_I] = array("<code>","\n","<pre>","<ol>","<ul>","<b>","</i>","<br", '<<',
+ '<var>', '<kbd>', '<samp>');
+ $this->tokens[PHPDOCUMENTOR_PDP_STATE_BR] = array(">","/>");
+ $this->tokens[PHPDOCUMENTOR_PDP_STATE_ESCAPE] = array('code>>', '/code>>', 'pre>>', '/pre>>', 'b>>', '/b>>',
+ 'i>>', '/i>>', 'ol>>', '/ol>>', 'ul>>', '/ul>>',
+ 'br>>', 'br />>', 'p>>', '/p>>', 'samp>>', '/samp>>',
+ 'kbd>>', '/kbd>>', 'var>>', '/var>>');
+ if (PHPDOCUMENTOR_KILL_WHITESPACE) $this->tokens[PHPDOCUMENTOR_PDP_STATE_DOUBLECR][] = ' ';
+
+ // For each event word to event mapings
+ $this->pushEvent[PARSER_EVENT_NOEVENTS] =
+ array(
+ "<code>" => PHPDOCUMENTOR_PDP_EVENT_CODE,
+ "<pre>" => PHPDOCUMENTOR_PDP_EVENT_PRE,
+ "<p>" => PHPDOCUMENTOR_PDP_EVENT_P,
+ "<var>" => PHPDOCUMENTOR_PDP_EVENT_VAR,
+ "<samp>" => PHPDOCUMENTOR_PDP_EVENT_SAMP,
+ "<kbd>" => PHPDOCUMENTOR_PDP_EVENT_KBD,
+ "<ol>" => PHPDOCUMENTOR_PDP_EVENT_LIST,
+ "<ul>" => PHPDOCUMENTOR_PDP_EVENT_LIST,
+ "<b>" => PHPDOCUMENTOR_PDP_EVENT_B,
+ "<i>" => PHPDOCUMENTOR_PDP_EVENT_I,
+ "<br" => PHPDOCUMENTOR_PDP_EVENT_BR,
+ "\n" => PHPDOCUMENTOR_PDP_EVENT_DOUBLECR,
+ '<<' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE,
+ );
+##########################
+ $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_CODE] =
+ array(
+ '<</code>>' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE_CODE,
+ );
+
+ $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_CODE] = array("</code>");
+##########################
+ $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_PRE] =
+ array(
+ '<</pre>>' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE_PRE,
+ );
+
+ $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_PRE] = array("</pre>");
+##########################
+
+ $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_BR] = array(">","/>");
+##########################
+ $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_P] =
+ array(
+ "<code>" => PHPDOCUMENTOR_PDP_EVENT_CODE,
+ "<ol>" => PHPDOCUMENTOR_PDP_EVENT_LIST,
+ "<ul>" => PHPDOCUMENTOR_PDP_EVENT_LIST,
+ "<var>" => PHPDOCUMENTOR_PDP_EVENT_VAR,
+ "<samp>" => PHPDOCUMENTOR_PDP_EVENT_SAMP,
+ "<kbd>" => PHPDOCUMENTOR_PDP_EVENT_KBD,
+ "<pre>" => PHPDOCUMENTOR_PDP_EVENT_PRE,
+ "<b>" => PHPDOCUMENTOR_PDP_EVENT_B,
+ "<i>" => PHPDOCUMENTOR_PDP_EVENT_I,
+ "<br" => PHPDOCUMENTOR_PDP_EVENT_BR,
+ '<<' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE,
+ );
+
+ $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_P] = array("</p>");
+##########################
+
+ $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_LIST] =
+ array(
+ "<ul>" => PHPDOCUMENTOR_PDP_EVENT_LIST,
+ "<ol>" => PHPDOCUMENTOR_PDP_EVENT_LIST,
+ "<code>" => PHPDOCUMENTOR_PDP_EVENT_CODE,
+ "<var>" => PHPDOCUMENTOR_PDP_EVENT_VAR,
+ "<samp>" => PHPDOCUMENTOR_PDP_EVENT_SAMP,
+ "<kbd>" => PHPDOCUMENTOR_PDP_EVENT_KBD,
+ "<b>" => PHPDOCUMENTOR_PDP_EVENT_B,
+ "<i>" => PHPDOCUMENTOR_PDP_EVENT_I,
+ "<pre>" => PHPDOCUMENTOR_PDP_EVENT_PRE,
+ "<br" => PHPDOCUMENTOR_PDP_EVENT_BR,
+ '<<' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE,
+ );
+
+ $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_LIST] = array("</ul>","</ol>");
+##########################
+
+ $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_SIMLIST] =
+ array(
+ "<code>" => PHPDOCUMENTOR_PDP_EVENT_CODE,
+ "<pre>" => PHPDOCUMENTOR_PDP_EVENT_PRE,
+ "<p>" => PHPDOCUMENTOR_PDP_EVENT_P,
+ "<var>" => PHPDOCUMENTOR_PDP_EVENT_VAR,
+ "<samp>" => PHPDOCUMENTOR_PDP_EVENT_SAMP,
+ "<kbd>" => PHPDOCUMENTOR_PDP_EVENT_KBD,
+ "<b>" => PHPDOCUMENTOR_PDP_EVENT_B,
+ "<i>" => PHPDOCUMENTOR_PDP_EVENT_I,
+ "<br" => PHPDOCUMENTOR_PDP_EVENT_BR,
+ '<<' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE,
+ );
+##########################
+
+ $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_DOUBLECR] =
+ array(
+ "<code>" => PHPDOCUMENTOR_PDP_EVENT_CODE,
+ "<ol>" => PHPDOCUMENTOR_PDP_EVENT_LIST,
+ "<ul>" => PHPDOCUMENTOR_PDP_EVENT_LIST,
+ "<pre>" => PHPDOCUMENTOR_PDP_EVENT_PRE,
+ "<b>" => PHPDOCUMENTOR_PDP_EVENT_B,
+ "<i>" => PHPDOCUMENTOR_PDP_EVENT_I,
+ "<var>" => PHPDOCUMENTOR_PDP_EVENT_VAR,
+ "<samp>" => PHPDOCUMENTOR_PDP_EVENT_SAMP,
+ "<kbd>" => PHPDOCUMENTOR_PDP_EVENT_KBD,
+ "<br" => PHPDOCUMENTOR_PDP_EVENT_BR,
+ "<p>" => PHPDOCUMENTOR_PDP_EVENT_P,
+ '<<' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE,
+ );
+
+##########################
+ $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_B] =
+ array(
+ "<code>" => PHPDOCUMENTOR_PDP_EVENT_CODE,
+ "<ol>" => PHPDOCUMENTOR_PDP_EVENT_LIST,
+ "<ul>" => PHPDOCUMENTOR_PDP_EVENT_LIST,
+ "<pre>" => PHPDOCUMENTOR_PDP_EVENT_PRE,
+ "<var>" => PHPDOCUMENTOR_PDP_EVENT_VAR,
+ "<samp>" => PHPDOCUMENTOR_PDP_EVENT_SAMP,
+ "<kbd>" => PHPDOCUMENTOR_PDP_EVENT_KBD,
+ "<br" => PHPDOCUMENTOR_PDP_EVENT_BR,
+ '<i>' => PHPDOCUMENTOR_PDP_EVENT_I,
+ '<<' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE,
+ );
+
+ $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_B] = array("</b>");
+
+##########################
+ $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_I] =
+ array(
+ "<code>" => PHPDOCUMENTOR_PDP_EVENT_CODE,
+ "<ol>" => PHPDOCUMENTOR_PDP_EVENT_LIST,
+ "<ul>" => PHPDOCUMENTOR_PDP_EVENT_LIST,
+ "<pre>" => PHPDOCUMENTOR_PDP_EVENT_PRE,
+ "<var>" => PHPDOCUMENTOR_PDP_EVENT_VAR,
+ "<samp>" => PHPDOCUMENTOR_PDP_EVENT_SAMP,
+ "<kbd>" => PHPDOCUMENTOR_PDP_EVENT_KBD,
+ "<br" => PHPDOCUMENTOR_PDP_EVENT_BR,
+ '<b>' => PHPDOCUMENTOR_PDP_EVENT_B,
+ '<<' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE,
+ );
+
+ $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_I] = array("</i>");
+
+##########################
+ $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_VAR] =
+ array(
+ "<code>" => PHPDOCUMENTOR_PDP_EVENT_CODE,
+ "<ol>" => PHPDOCUMENTOR_PDP_EVENT_LIST,
+ "<ul>" => PHPDOCUMENTOR_PDP_EVENT_LIST,
+ "<pre>" => PHPDOCUMENTOR_PDP_EVENT_PRE,
+ "<i>" => PHPDOCUMENTOR_PDP_EVENT_I,
+ "<samp>" => PHPDOCUMENTOR_PDP_EVENT_SAMP,
+ "<kbd>" => PHPDOCUMENTOR_PDP_EVENT_KBD,
+ "<br" => PHPDOCUMENTOR_PDP_EVENT_BR,
+ '<b>' => PHPDOCUMENTOR_PDP_EVENT_B,
+ '<<' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE,
+ );
+
+ $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_VAR] = array("</var>");
+
+##########################
+ $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_SAMP] =
+ array(
+ "<code>" => PHPDOCUMENTOR_PDP_EVENT_CODE,
+ "<ol>" => PHPDOCUMENTOR_PDP_EVENT_LIST,
+ "<ul>" => PHPDOCUMENTOR_PDP_EVENT_LIST,
+ "<pre>" => PHPDOCUMENTOR_PDP_EVENT_PRE,
+ "<var>" => PHPDOCUMENTOR_PDP_EVENT_VAR,
+ "<i>" => PHPDOCUMENTOR_PDP_EVENT_I,
+ "<kbd>" => PHPDOCUMENTOR_PDP_EVENT_KBD,
+ "<br" => PHPDOCUMENTOR_PDP_EVENT_BR,
+ '<b>' => PHPDOCUMENTOR_PDP_EVENT_B,
+ '<<' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE,
+ );
+
+ $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_SAMP] = array("</samp>");
+
+##########################
+ $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_KBD] =
+ array(
+ "<code" => PHPDOCUMENTOR_PDP_EVENT_CODE,
+ "<ol>" => PHPDOCUMENTOR_PDP_EVENT_LIST,
+ "<ul>" => PHPDOCUMENTOR_PDP_EVENT_LIST,
+ "<pre" => PHPDOCUMENTOR_PDP_EVENT_PRE,
+ "<var>" => PHPDOCUMENTOR_PDP_EVENT_VAR,
+ "<samp>" => PHPDOCUMENTOR_PDP_EVENT_SAMP,
+ "<i>" => PHPDOCUMENTOR_PDP_EVENT_I,
+ "<br" => PHPDOCUMENTOR_PDP_EVENT_BR,
+ '<b>' => PHPDOCUMENTOR_PDP_EVENT_B,
+ '<<' => PHPDOCUMENTOR_PDP_EVENT_ESCAPE,
+ );
+
+ $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_KBD] = array("</kbd>");
+ }
+
+ function getParserEventName ($value)
+ {
+ $lookup = array(
+ PARSER_EVENT_NOEVENTS => "PARSER_EVENT_NOEVENTS",
+ PHPDOCUMENTOR_PDP_EVENT_CODE => "PHPDOCUMENTOR_PDP_EVENT_CODE",
+ PHPDOCUMENTOR_PDP_EVENT_P => "PHPDOCUMENTOR_PDP_EVENT_P",
+ PHPDOCUMENTOR_PDP_EVENT_B => "PHPDOCUMENTOR_PDP_EVENT_B",
+ PHPDOCUMENTOR_PDP_EVENT_I => "PHPDOCUMENTOR_PDP_EVENT_I",
+ PHPDOCUMENTOR_PDP_EVENT_BR => "PHPDOCUMENTOR_PDP_EVENT_BR",
+ PHPDOCUMENTOR_PDP_EVENT_VAR => "PHPDOCUMENTOR_PDP_EVENT_VAR",
+ PHPDOCUMENTOR_PDP_EVENT_SAMP => "PHPDOCUMENTOR_PDP_EVENT_SAMP",
+ PHPDOCUMENTOR_PDP_EVENT_KBD => "PHPDOCUMENTOR_PDP_EVENT_KBD",
+ PHPDOCUMENTOR_PDP_EVENT_ESCAPE => "PHPDOCUMENTOR_PDP_EVENT_ESCAPE",
+ PHPDOCUMENTOR_PDP_EVENT_ESCAPE_CODE => "PHPDOCUMENTOR_PDP_EVENT_ESCAPE_CODE",
+ PHPDOCUMENTOR_PDP_EVENT_ESCAPE_PRE => "PHPDOCUMENTOR_PDP_EVENT_ESCAPE_PRE",
+ PHPDOCUMENTOR_PDP_EVENT_DOUBLECR => "PHPDOCUMENTOR_PDP_EVENT_DOUBLECR",
+ PHPDOCUMENTOR_PDP_EVENT_LIST => "PHPDOCUMENTOR_PDP_EVENT_LIST",
+ PHPDOCUMENTOR_PDP_EVENT_PRE => "PHPDOCUMENTOR_PDP_EVENT_PRE",
+ PHPDOCUMENTOR_PDP_EVENT_SIMLIST => "PHPDOCUMENTOR_PDP_EVENT_SIMLIST",
+ );
+ if (isset($lookup[$value]))
+ return $lookup[$value];
+ else return $value;
+ }
+}
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/ParserDocBlock.inc b/buildscripts/PhpDocumentor/phpDocumentor/ParserDocBlock.inc
new file mode 100644
index 00000000..96ea1b20
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/ParserDocBlock.inc
@@ -0,0 +1,1165 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * DocBlock Parser Classes
+ * @package phpDocumentor
+ * @subpackage ParserDocBlock
+ */
+/**
+ * represents a short or long description in a DocBlock ({@link parserDocBlock})
+ * @package phpDocumentor
+ * @subpackage ParserDocBlock
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: ParserDocBlock.inc,v 1.1 2005/10/17 18:36:57 jeichorn Exp $
+ */
+class parserDesc extends parserStringWithInlineTags
+{
+ /**
+ * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'
+ * always '_desc'
+ * @var string
+ */
+ var $type = '_desc';
+
+ /**
+ * @param mixed like {@link parserStringWithInlineTags::add()}, this can be a string or parserInlineTag, but it can also be a
+ * parserStringWithInlineTags, and the contents will be merged
+ */
+ function add($stringOrClass)
+ {
+ if (is_object($stringOrClass))
+ {
+ if (phpDocumentor_get_class($stringOrClass) == 'parserstringwithinlinetags' ||
+ phpDocumentor_get_class($stringOrClass) == 'parserdesc')
+ {
+ for($i=0;$i<count($stringOrClass->value);$i++)
+ {
+ parserStringWithInlineTags::add($stringOrClass->value[$i]);
+ }
+ } else
+ {
+ parserStringWithInlineTags::add($stringOrClass);
+ }
+ } else return parserStringWithInlineTags::add($stringOrClass);
+ }
+
+ /**
+ * @return boolean whether this desc has an {@}inheritdoc} inline tag
+ */
+ function hasInheritDoc()
+ {
+ for($i=0;$i<count($this->value);$i++)
+ {
+ if (phpDocumentor_get_class($this->value[$i])=='parserinheritdocinlinetag') return true;
+ }
+ }
+
+ /**
+ * @return boolean whether this desc has an {@}source} inline tag
+ */
+ function hasSource()
+ {
+ for($i=0;$i<count($this->value);$i++)
+ {
+ if (phpDocumentor_get_class($this->value[$i])=='parsersourceinlinetag') return true;
+ }
+ }
+
+ /**
+ * replaces {@}inheritdoc} with the contents of the parent DocBlock
+ * @param parserDesc parent parserDesc, used to retrieve the description
+ */
+ function replaceInheritDoc($desc)
+ {
+ $value = $this->value;
+ $this->value = array();
+ for($i=0;$i<count($value);$i++)
+ {
+ if (phpDocumentor_get_class($value[$i])=='parserinheritdocinlinetag')
+ {
+ for($j=0;$j<count($desc->value);$j++)
+ {
+ $this->add($desc->value[$j]);
+ }
+ } else $this->add($value[$i]);
+ }
+ }
+}
+
+/**
+ * Represents a docblock and its components, {@link $desc}, {@link $sdesc}, {@link $tags}, and also {@link $params} for functions
+ * @package phpDocumentor
+ * @subpackage ParserDocBlock
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: ParserDocBlock.inc,v 1.1 2005/10/17 18:36:57 jeichorn Exp $
+ */
+class parserDocBlock
+{
+ /**
+ * @var parserDesc
+ */
+ var $desc = false;
+ /**
+ * @var array array of {@link parserDesc}s
+ */
+ var $processed_desc = false;
+ /**
+ * @var array array of {@link parserDesc}s
+ */
+ var $processed_sdesc = false;
+ /**
+ * @var parserDesc
+ */
+ var $sdesc = false;
+ /**
+ * Line number in the source on which this docblock begins
+ * @since 1.2
+ * @var false|integer
+ */
+ var $linenumber = false;
+ /**
+ * Line number in the source on which this docblock ends
+ * @since 1.2
+ * @var false|integer
+ */
+ var $endlinenumber = false;
+ /**
+ * array of {@link parserTag}s
+ * @var array
+ */
+ var $tags = array();
+ /**
+ * array of unrecognized {@link parserTag}s
+ * @var array
+ */
+ var $unknown_tags = array();
+ /**
+ * array of param data.
+ * Format:
+ * array(index of param in function parameter list -OR- parameter name =>
+ * parserStringWithInlineTags,...)
+ * @var array
+ */
+ var $params = array();
+ /**
+ * array of global variable data.
+ * Format:
+ * array(index of global variable in @global tag list -OR- global variable name =>
+ * array(datatype,parserStringWithInlineTags),...)
+ * @var array
+ */
+ var $funcglobals = array();
+
+ /**
+ * array of static variable data.
+ * Format:
+ * array(index of static variable in @global tag list -OR- static variable name =>
+ * {@link parserStaticvarTag},...)
+ * @var array
+ */
+ var $statics = array();
+ /**
+ * This is either a {@link parserReturnTag} or false if no return tag is present
+ * @var mixed
+ */
+ var $return = false;
+ /**
+ * This is either a {@link parserVarTag} or false if no var tag is present
+ * @var mixed
+ */
+ var $var = false;
+ /**
+ * fix for bug 591396
+ * @var boolean
+ */
+ var $explicitpackage = false;
+ /**
+ * fix for bug 708559
+ * @var boolean
+ */
+ var $explicitcategory = false;
+ /** @var string */
+ var $category;
+ /** @var string */
+ var $package = 'default';
+ /** @var string */
+ var $subpackage = '';
+ /**
+ * whether this DocBlock has an @access tag
+ * @var boolean */
+ var $hasaccess = false;
+ /**
+ * whether this DocBlock has a @name tag
+ * @var boolean */
+ var $hasname = false;
+ /**
+ * description of package parsed from @package tag
+ * Unused in this version
+ * @var string
+ */
+ var $packagedescrip = '';
+ /**
+ * description of subpackage parsed from @package tag
+ * Unused in this version
+ * @var string
+ */
+ var $subpackagedescrip = '';
+ /**
+ * Determines whether a DocBlock can legally have a {@}source} tag
+ * @tutorial tags.inlinesource.pkg
+ * @var boolean
+ * @access private
+ */
+ var $_canSource = false;
+
+ /**
+ * sets package to default
+ * @global string default package name
+ */
+ function parserDocBlock()
+ {
+ global $phpDocumentor_DefaultPackageName;
+ $this->package = $GLOBALS['phpDocumentor_DefaultPackageName'];
+ $this->category = $GLOBALS['phpDocumentor_DefaultCategoryName'];
+ }
+
+ /**
+ * Sets the starting line number for the DocBlock
+ * @param integer
+ */
+ function setLineNumber($number)
+ {
+ $this->linenumber = $number;
+ }
+
+ /**
+ * Retrieve starting line number
+ * @return integer
+ */
+ function getLineNumber()
+ {
+ return $this->linenumber;
+ }
+
+ /**
+ * Sets the ending line number for the DocBlock
+ * @param integer
+ */
+ function setEndLineNumber($number)
+ {
+ $this->endlinenumber = $number;
+ }
+
+ /**
+ * Retrieve ending line number
+ * @return integer
+ */
+ function getEndLineNumber()
+ {
+ return $this->endlinenumber;
+ }
+
+ /**
+ * Parse out any html tags from doc comments, and make them into
+ * abstract structures
+ * @uses parserDescParser::parse()
+ */
+ function postProcess()
+ {
+ if ($this->sdesc)
+ {
+ $parser = new parserDescParser;
+ $parser->subscribe('*',$this);
+ if ($this->desc) $parser->parse($this->desc->value);
+ $parser->parse($this->sdesc->value,true);
+ }
+ }
+
+ /**
+ * Tells the DocBlock it can have a @filesource tag
+ *
+ * Only page-level DocBlocks may have a @filesource tag
+ */
+ function canSource()
+ {
+ $this->_canSource = true;
+ }
+
+ /**
+ * Tells the DocBlock it can't have a @filesource tag
+ *
+ * Only page-level DocBlocks may have a @filesource tag
+ */
+ function cantSource()
+ {
+ $this->_canSource = false;
+ }
+
+ /**
+ * Indirectly called after parsing by {@link postProcess}
+ *
+ * @param integer either 1 for long desc or 2 for short desc
+ * @param array data organized into paragraphs. Each entry is a {@link parserStringWithInlineTags}
+ * @uses $processed_desc sets to the array passed from {@link parserDescParser::parse()}
+ * @uses $processed_sdesc sets to the array passed from {@link parserDescParser::parse()}
+ * @access private
+ */
+ function HandleEvent($event,$data)
+ {
+ if ($event == 1)
+ $this->processed_desc = $data;
+ else
+ $this->processed_sdesc = $data;
+ }
+
+ /**
+ * @param array
+ */
+ function updateModifiers($modifiers)
+ {
+ if (is_array($modifiers) && count($modifiers))
+ {
+ foreach ($modifiers as $modifier)
+ {
+ switch ($modifier)
+ {
+ case 'private' :
+ case 'public' :
+ case 'protected' :
+ unset($this->tags['access']);
+ $x = new parserAccessTag($modifier);
+ if ($x->isvalid)
+ {
+ $this->hasaccess = true;
+ $this->tags['access'][] = $x;
+ }
+ break;
+ case 'static' :
+ case 'abstract' :
+ unset($this->tags[$modifier]);
+ $this->addKeyword($modifier, '');
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Set the short description of the DocBlock
+ *
+ * Setting the short description is possible by passing in one of three
+ * possible parameters:
+ * <ul>
+ * <li>another DocBlock's short description</li>
+ * <li>another DocBlock, the short description will be extracted</li>
+ * <li>a Zend Studio-compatible @desc tag</li>
+ * </ul>
+ * @param parserDesc|parserDocBlock|parserTag sets {@link $sdesc}
+ */
+ function setShortDesc($desc)
+ {
+ if (phpDocumentor_get_class($desc) == 'parsertag')
+ {
+ $this->sdesc = new parserDesc;
+ $this->processed_sdesc = $desc->value;
+ return;
+ }
+ if (phpDocumentor_get_class($desc) == 'parserdesc') {
+ $this->sdesc = $desc;
+ } else
+ {
+ $this->sdesc = $desc->sdesc;
+ $this->processed_sdesc = $desc->processed_sdesc;
+ }
+
+ if ($this->sdesc && $this->sdesc->hasSource())
+ {
+ addWarning(PDERROR_SOURCE_TAG_IGNORED,$this->sdesc->getString());
+ }
+ }
+
+ /**
+ * Passes to {@link parserStringWithInlineTags::setSource()}
+ *
+ * After passing, it calls {@link postProcess()} to set up the new
+ * source
+ * @param string|array tokenized highlight-ready source code
+ * @param false|string name of class if this is a method source
+ */
+ function setSource($source, $class = false)
+ {
+ if ($this->desc)
+ {
+ $this->desc->setSource($source, $class);
+ $this->postProcess();
+ }
+ }
+
+ /**
+ * @param parserDesc|parserDocBlock sets {@link $desc}
+ */
+ function setDesc($desc)
+ {
+ if (phpDocumentor_get_class($desc) == 'parserdesc')
+ $this->desc = $desc;
+ else
+ {
+ $this->desc = $desc->desc;
+ $this->processed_desc = $desc->processed_desc;
+ }
+ }
+
+ /**
+ * Wrapper for {@link parserDesc::hasInheritDoc()}
+ * @return boolean
+ */
+ function hasInheritDoc()
+ {
+ if (!$this->desc) return false;
+ return $this->desc->hasInheritDoc();
+ }
+
+ /**
+ * Wrapper for {@link parserDesc::replaceInheritDoc()}
+ *
+ * Also replaces {@}inheritdoc} in the {@link $processed_desc}
+ * @param parserDesc
+ */
+ function replaceInheritDoc($desc)
+ {
+ if (!$this->desc) return false;
+ $this->desc->replaceInheritDoc($desc->desc);
+ $this->postProcess();
+ }
+
+ /**
+ * @param Converter takes {@link $sdesc} and converts it to a string and returns it if present, otherwise returns ''
+ * @return string
+ */
+ function getSDesc(&$converter)
+ {
+ if ($this->sdesc && $this->processed_sdesc)
+ {
+ $result = '';
+ foreach($this->processed_sdesc as $desc)
+ {
+ if (count($desc->value))
+ $result .= $desc->Convert($converter);
+ }
+ return $result;
+ } else
+ {
+// var_dump($this->desc,$this->processed_desc);
+ }
+ return '';
+ }
+
+ /**
+ * @param Converter takes {@link $desc} and converts it to a string and returns it if present, otherwise returns ''
+ * @return string
+ */
+ function getDesc(&$converter)
+ {
+ if ($this->desc && $this->processed_desc)
+ {
+ $result = '';
+ foreach($this->processed_desc as $desc)
+ {
+ if (count($desc->value))
+ $result .= $converter->EncloseParagraph($desc->Convert($converter));
+ }
+ return $result;
+ } else
+ {
+// var_dump($this->desc,$this->processed_desc);
+ }
+ return '';
+ }
+
+ /**
+ * @param string $paramVar if empty, param is indexed in the order received and set using {@link changeParam()}
+ * @param parserStringWithInlineTags $value
+ */
+ function addParam($paramVar, $paramType, $value)
+ {
+ if (empty($paramVar))
+ $this->params[count($this->params)] = new parserParamTag($paramType,$value);
+ else
+ $this->params[$paramVar] = new parserParamTag($paramType,$value);
+ }
+
+ /**
+ * @param integer $index index of parameter in the {@link $params} array
+ * @param string $name name of the parameter to set in the $params array
+ */
+ function changeParam($index,$name)
+ {
+ $this->params[$name] = $this->params[$index];
+ unset($this->params[$index]);
+ }
+
+ /**
+ * replaces nameless parameters in the {@link $params} array with their names
+ * @param array $params Format: array(parameter index => parameter name,...)
+ */
+ function updateParams($params)
+ {
+ for($i=0;$i<count($params);$i++)
+ {
+ if (isset($this->params[$i]))
+ {
+ $this->changeParam($i,$params[$i]);
+ }
+ }
+ if (isset($this->tags))
+ unset($this->tags['param']);
+ }
+
+ /**
+ * Used to insert DocBlock Template tags into a docblock
+ * @param parserTag tag
+ * @global array used to determine whether to add ignored tags, or not
+ */
+ function addTag($tag)
+ {
+ global $_phpDocumentor_setting;
+ if (phpDocumentor_setup::checkIgnoreTag($tag->keyword)) return;
+ $value = $tag->value;
+ if (is_array($value)) $value = $value[0];
+ if ($tag->keyword == 'uses')
+ {
+ $this->addUses($value, $tag->_description);
+ } else
+ {
+ $this->addKeyword($tag->keyword, $value);
+ }
+ }
+
+ /**
+ * @param string $keyword tag name
+ * @param parserStringWithInlineTags $value the contents of the tag
+ * @global array used to determine whether to add the @internal tag or not
+ */
+ function addKeyword($keyword, $value)
+ {
+ global $_phpDocumentor_setting;
+ if (phpDocumentor_setup::checkIgnoreTag($keyword)) return;
+ // don't add the tag at all if it was specified to ignore it with --ignore-tags
+ if ($keyword == 'package' || $keyword == 'subpackage' || $keyword == 'category') return $this->addPackage($keyword, $value);
+ if ($keyword == 'access') return $this->addAccess($value);
+ if ($keyword == 'link') return $this->addLink($value);
+ if ($keyword == 'see' || $keyword == 'tutorial') return $this->addSee($keyword,$value);
+ if ($keyword == 'uses') return $this->addUses($keyword, $value);
+ if ($keyword == 'name') return $this->addName($value);
+ if (!in_array($keyword,$GLOBALS['_phpDocumentor_tags_allowed']))
+ $this->addUnknownTag($keyword,$value);
+ else
+ {
+ if ($keyword == 'internal' && (!isset($_phpDocumentor_setting['parseprivate']) || $_phpDocumentor_setting['parseprivate'] == 'off')) return;
+ if (!isset($this->tags[$keyword])) {
+ $this->tags[$keyword] = array();
+ }
+ $ptag = 'parserTag';
+ if (class_exists('parser'.$keyword.'tag'))
+ $ptag = 'parser'.ucfirst($keyword).'Tag';
+ array_unshift($this->tags[$keyword], new $ptag($keyword, $value));
+ }
+ }
+
+ /**
+ * adds an @example tag
+ * @param string contents of the tag
+ * @param string path to the file containing this tag
+ */
+ function addExample($value, $path)
+ {
+ $this->tags['example'][] = new parserExampleTag($value, $path);
+ }
+
+ /**
+ * adds an unknown tag to the {@link $unknown_tags} array for use by custom converters
+ * @param string tag name
+ * @param string tag value
+ */
+ function addUnknownTag($keyword, $value)
+ {
+ addWarning(PDERROR_UNKNOWN_TAG,$keyword);
+ $this->unknown_tags[$keyword][] = new parserTag($keyword, $value);
+ }
+
+ /**
+ * set the element's package to the passed values. Used in {@link phpDocumentor_IntermediateParser} to align package of
+ * elements inside a class or procedural page to the package of the class/procedural page
+ * @param string
+ * @param string
+ * @param string
+ * @param string element name
+ * @param string element type (include, define, var, method, global, function, const)
+ */
+ function overridePackage($category, $package,$subpackage,$elname,$type)
+ {
+ if ($this->package != $GLOBALS['phpDocumentor_DefaultPackageName'])
+ {
+ addError(PDERROR_OVERRIDDEN_PACKAGE_TAGS,$elname,$type,$this->package);
+ $this->explicitpackage = false;
+ }
+ if (!empty($this->subpackage))
+ addError(PDERROR_OVERRIDDEN_SUBPACKAGE_TAGS,$type,$elname,$this->subpackage);
+ $this->package = $GLOBALS['phpDocumentor_DefaultPackageName'];
+ $this->subpackage = '';
+ $this->category = $category;
+ $this->addPackage('package',$package);
+ $this->addPackage('subpackage',$subpackage);
+ }
+
+ /**
+ * Used if this docblock has a @package tag.
+ *
+ * phpDocumentor will guess package for DocBlocks that don't have
+ * a @package tag
+ * @uses $explicitpackage
+ */
+ function setExplicitPackage()
+ {
+ $this->explicitpackage = true;
+ }
+
+ /**
+ * If the DocBlock has a @package tag, then this returns true
+ * @return boolean
+ */
+ function getExplicitPackage()
+ {
+ return $this->explicitpackage;
+ }
+
+ /**
+ * Used if this docblock has a @category tag.
+ *
+ * phpDocumentor will guess category for DocBlocks that don't have
+ * a @category tag
+ * @uses $explicitcategory
+ */
+ function setExplicitCategory()
+ {
+ $this->explicitcategory = true;
+ }
+
+ /**
+ * If the DocBlock has a @category tag, then this returns true
+ * @return boolean
+ */
+ function getExplicitCategory()
+ {
+ return $this->explicitcategory;
+ }
+
+ /**
+ * @param string $keyword tag name (either package or subpackage)
+ * @param mixed $value either a string or a parserStringWithInlineTags. Strips all inline tags and use the text as the package
+ */
+ function addPackage($keyword, $value)
+ {
+ if ($keyword == 'package')
+ {
+ if (!$this->explicitpackage)
+ {
+ if (!is_string($value))
+ $value = $value->getString();
+ $rest = '';
+ $value = explode(' ',$value);
+ if (count($value) - 1)
+ {
+ $rest = $value;
+ $value = $value[0];
+ unset($rest[0]);
+ $rest = implode($rest,' ');
+ } else
+ {
+ $value = explode("\t",$value[0]);
+ if (count($value) - 1)
+ {
+ $rest = $value;
+ $value = $value[0];
+ unset($rest[0]);
+ $rest = implode($rest,"\t");
+ } else $value = $value[0];
+ }
+ preg_match("/^([^`~!@#$%^&*(){}|<>,;]+)$/",$value,$match);
+ if (!isset($match[0]))
+ {
+ // if were a single line and the only bad character is a space then will fix things for them
+ preg_match("/^([^`~!@#$%^&*(){}|<>,;]+)$/",$value,$match);
+ if (!isset($match[0]))
+ {
+ addError(PDERROR_ILLEGAL_PACKAGENAME,'package','package',$value);
+ $value = $GLOBALS['phpDocumentor_DefaultPackageName'];
+ }
+ else
+ {
+ $value =
+ str_replace(array(" ","/","\\",":"),"_",
+ trim($value));
+ }
+ }
+ $this->packagedescrip = $this->package = trim($value);
+ if (!empty($rest)) $this->packagedescrip = $rest;
+ } else
+ {
+ if (is_string($value))
+ addError(PDERROR_MULTIPLE_PACKAGE_TAGS,$value);
+ else
+ addError(PDERROR_MULTIPLE_PACKAGE_TAGS,$value->getString());
+ }
+ } elseif ($keyword == 'subpackage')
+ {
+ if (empty($this->subpackage))
+ {
+ if (!is_string($value))
+ $value = $value->getString();
+ $rest = '';
+ $value = explode(' ',$value);
+ if (count($value) - 1)
+ {
+ $rest = $value;
+ $value = $value[0];
+ unset($rest[0]);
+ $rest = implode($rest,' ');
+ } else
+ {
+ $value = explode("\t",$value[0]);
+ if (count($value) - 1)
+ {
+ $rest = $value;
+ $value = $value[0];
+ unset($rest[0]);
+ $rest = implode($rest,"\t");
+ } else $value = $value[0];
+ }
+ if (!empty($value))
+ {
+ preg_match("/^([^`~!@#$%^&*(){}|<>,;]+)$/",$value,$match);
+ if (!isset($match[0]))
+ {
+ // if were a single line and the only bad character is a space then will fix things for them
+ preg_match("/^([^`~!@#$%^&*(){}|<>,;]+)$/",$value,$match);
+ if (!isset($match[0]))
+ {
+ addError(PDERROR_ILLEGAL_PACKAGENAME,'subpackage','subpackage',$value);
+ $value = '';
+ }
+ else
+ {
+ $value =
+ str_replace(array(" ","/","\\",":"),"_",
+ trim($value));
+ }
+ }
+ }
+ $this->subpackage = trim($value);
+ if (!empty($rest)) $this->subpackagedescrip = $rest;
+ } else
+ {
+ if (is_string($value))
+ addError(PDERROR_MULTIPLE_SUBPACKAGE_TAGS,$value);
+ else
+ addError(PDERROR_MULTIPLE_SUBPACKAGE_TAGS,$value->getString());
+ }
+ } elseif ($keyword == 'category')
+ {
+ if (!$this->explicitcategory)
+ {
+ if (!is_string($value))
+ $value = $value->getString();
+ $this->category = $value;
+ } else
+ {
+ if (is_string($value))
+ addError(PDERROR_MULTIPLE_CATEGORY_TAGS,$value);
+ else
+ addError(PDERROR_MULTIPLE_CATEGORY_TAGS,$value->getString());
+ }
+ }
+ }
+
+ /**
+ * Adds a @name tag to the tag list
+ * @param string new name of element
+ */
+ function addName($value)
+ {
+ if (is_object($value)) $value = $value->getString();
+ if (!$this->hasname)
+ {
+ $x = new parserNameTag('name',$value);
+ $this->hasname = true;
+ $this->tags['name'][] = $x;
+ } else
+ {
+ addError(PDERROR_MULTIPLE_NAME_TAGS,$value);
+ }
+ }
+
+ /**
+ * @param string if empty, staticvar is indexed in the order received and set using {@link changeStatic()}
+ * @param string data type
+ * @param parserStringWithInlineTags
+ */
+ function addStaticVar($staticvar, $type, $descrip)
+ {
+ if (empty($staticvar))
+ $this->statics[] = new parserStaticvarTag($type,$descrip);
+ else
+ $this->statics[$staticvar] = new parserStaticvarTag($type,$descrip);
+ }
+
+ /**
+ * adds a function declaration of @global to the {@link $funcglobals} array
+ * @param string global type
+ * @param string description of how the global is used in the function
+ */
+ function addFuncGlobal($type,$value)
+ {
+ $this->funcglobals[] = array($type,$value);
+ }
+
+ /**
+ * @param integer $index index of parameter in the {@link $funcglobals} array
+ * @param string $name name of the parameter to set in the $funcglobals array
+ */
+ function changeGlobal($index,$name)
+ {
+ $this->funcglobals[$name] = $this->funcglobals[$index];
+ unset($this->funcglobals[$index]);
+ }
+
+ /**
+ * @param integer $index index of parameter in the {@link $statics} array
+ * @param string $name name of the parameter to set in the $statics array
+ */
+ function changeStatic($index,$name)
+ {
+ $this->statics[$name] = $this->statics[$index];
+ unset($this->statics[$index]);
+ }
+
+ /**
+ * replaces nameless global variables in the {@link $funcglobals} array with their names
+ * @param array
+ */
+ function updateGlobals($funcs)
+ {
+ for($i=0;$i<count($funcs);$i++)
+ {
+ if (isset($this->funcglobals[$i]))
+ {
+ $this->changeGlobal($i,$funcs[$i]);
+ }
+ }
+ }
+
+ /**
+ * replaces nameless static variables in the {@link $statics} array with their names
+ * @param array
+ */
+ function updateStatics($funcs)
+ {
+ for($i=0;$i<count($funcs);$i++)
+ {
+ if (isset($this->statics[$i]))
+ {
+ $this->changeStatic($i,$funcs[$i]);
+ }
+ }
+ }
+
+ /**
+ * add an @access tag to the {@link tags} array
+ * @param string should be either public or private
+ */
+ function addAccess($value)
+ {
+ if (is_object($value)) $value = $value->getString();
+ $value = strtolower($value);
+ if (!$this->hasaccess)
+ {
+ $x = new parserAccessTag($value);
+ if ($x->isvalid)
+ {
+ $this->hasaccess = true;
+ $this->tags['access'][] = $x;
+ }
+ } else
+ {
+ if (is_string($value))
+ addError(PDERROR_MULTIPLE_ACCESS_TAGS,$value);
+ else
+ addError(PDERROR_MULTIPLE_ACCESS_TAGS,$value->getString());
+ }
+ }
+
+ /**
+ * Adds a new @filesource tag to the DocBlock
+ * @tutorial tags.filesource.pkg
+ * @param string full path to the file
+ * @param array tokenized source code, ordered by line number
+ */
+ function addFileSource($path, $source)
+ {
+ if (isset($this->tags['filesource'])) return;
+ $this->tags['filesource'][] = new parserFileSourceTag($path, $source);
+ }
+
+ /**
+ * creates a {@link parserLinkTag} and adds it to the {@link $tags} array
+ * @param string $link
+ */
+ function addLink($link)
+ {
+ if (phpDocumentor_setup::checkIgnoreTag('@link')) return;
+ $this->tags['link'][] = new parserLinkTag($link);
+ }
+
+ /**
+ * creates a {@link parserLinkTag} and adds it to the {@link $tags} array
+ * @param string either see or uses
+ * @param string $value
+ */
+ function addSee($keyword,$value)
+ {
+ if (phpDocumentor_setup::checkIgnoreTag($keyword)) return;
+ $tag = 'parser'.ucfirst($keyword).'Tag';
+ $this->tags[$keyword][] = new $tag($value);
+ }
+
+ /**
+ * creates a {@link parserReturnTag} and adds it to the {@link $tags} array
+ * @param string $returnType the one-word name of the return type (mixed should be used if more than one type)
+ * @param parserStringWithInlineTags $value
+ */
+ function addReturn($returnType, $value)
+ {
+ // only take the first one
+ if (!$this->return)
+ {
+ $this->return = new parserReturnTag($returnType, $value);
+ } else
+ {
+ addError(PDERROR_MULTIPLE_RETURN_TAGS,$returnType,$value->getString());
+ }
+ }
+
+ /**
+ * creates a {@link parserVarTag} and adds it to the {@link $tags} array
+ * @param string $varType the one-word name of the variable type (mixed should be used if more than one type)
+ * @param parserStringWithInlineTags $value
+ */
+ function addVar($varType, $value)
+ {
+ // only take the first one
+ if (!$this->var)
+ {
+ $this->var = new parserVarTag($varType, $value);
+ } else
+ {
+ addError(PDERROR_MULTIPLE_VAR_TAGS,$varType,$value->getString());
+ }
+ }
+
+ /**
+ * Adds a virtual @usedby tag to output
+ * @param abstractLink link to the element that has a @uses tag
+ * @param parserStringWithInlinetags description of how the elements uses
+ * this one
+ * @access private
+ */
+ function addUsedBy($link, $descrip)
+ {
+ $this->tags['usedby'][] = new parserUsedByTag($link, $descrip);
+ }
+
+ /**
+ * Add a @uses tag to the DocBlock
+ * @param string @see-style text, used for {@link Converter::getLink()}
+ * @param parserStringWithInlineTags description of how the used element is
+ * used
+ * @tutorial tags.uses.pkg
+ */
+ function addUses($seeel, $description)
+ {
+ $this->tags['uses'][] = new parserUsesTag($seeel, $description);
+ }
+
+ /**
+ * @param string
+ * @return mixed false if no keyword, unconverted value if one keyword, array of unconverted values if more than one keyword
+ */
+ function getKeyword($keyword)
+ {
+ if ($keyword == 'filesource' && !$this->_canSource) return false;
+ if (isset($this->tags[$keyword]))
+ {
+ if (count($this->tags[$keyword]) == 1)
+ {
+ return $this->tags[$keyword][0];
+ } else return $this->tags[$keyword];
+ } else return false;
+ }
+
+ /**
+ * @return array Format: array('var' => tag name, 'data' => unconverted tag value)
+ */
+ function listParams()
+ {
+ if (isset($this->params))
+ {
+ $ret = array();
+ foreach($this->params as $key => $val)
+ {
+ $ret[] = array("var" => ucfirst($key),"data" => $val);
+ }
+ return $ret;
+ } else {
+ return array();
+ }
+ }
+
+ /**
+ * @param Converter
+ */
+ function listTags()
+ {
+ $tags = array();
+ foreach($this->tags as $keyword => $vals)
+ {
+ if ($keyword == 'filesource' && !$this->_canSource) continue;
+ foreach($vals as $val)
+ {
+ $tags[] = $val;
+ }
+ }
+ usort($tags,'tagsort');
+ return $tags;
+ }
+
+ /** @return string always 'docblock' */
+ function getType()
+ {
+ return 'docblock';
+ }
+}
+
+/**
+ * @access private
+ */
+function tagsort($a, $b)
+{
+ switch(phpDocumentor_get_class($a))
+ {
+ case 'parsertag' :
+ switch ($a->keyword)
+ {
+ case 'author' :
+ $o = 3;
+ break;
+ case 'version' :
+ $o = 4;
+ break;
+ case 'deprecated' :
+ case 'deprec' :
+ $o = 7;
+ break;
+ case 'todo' :
+ case 'TODO' :
+ $o = 8;
+ break;
+ case 'abstract' :
+ $o = 9;
+ break;
+ }
+ case 'parseraccesstag' :
+ $o = 10;
+ break;
+ case 'parsernametag' :
+ $o = 11;
+ break;
+ case 'parserseetag' :
+ $o = 5;
+ break;
+ case 'parserlinktag' :
+ $o = 6;
+ break;
+ case 'parserreturntag' :
+ $o = 0;
+ break;
+ case 'parservartag' :
+ $o = 1;
+ break;
+ case 'parserstaticvartag' :
+ $o = 2;
+ break;
+ default :
+ $o = 12;
+ break;
+ }
+ switch(phpDocumentor_get_class($b))
+ {
+ case 'parsertag' :
+ switch ($b->keyword)
+ {
+ case 'author' :
+ $p = 3;
+ case 'version' :
+ $p = 4;
+ case 'deprecated' :
+ case 'deprec' :
+ $p = 7;
+ case 'todo' :
+ case 'TODO' :
+ $p = 8;
+ case 'abstract' :
+ $p = 9;
+ }
+ case 'parseraccesstag' :
+ $p = 10;
+ case 'parsernametag' :
+ $p = 11;
+ case 'parserseetag' :
+ $p = 5;
+ case 'parserlinktag' :
+ $p = 6;
+ case 'parserreturntag' :
+ $p = 0;
+ case 'parservartag' :
+ $p = 1;
+ case 'parsertutorialtag' :
+ $p = 1;
+ case 'parserstaticvartag' :
+ $p = 2;
+ default :
+ $p = 12;
+ }
+ if ($o == $p) return 0;
+ if ($o < $p) return -1;
+ if ($o > $p) return 1;
+}
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/ParserElements.inc b/buildscripts/PhpDocumentor/phpDocumentor/ParserElements.inc
new file mode 100644
index 00000000..a95d24b8
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/ParserElements.inc
@@ -0,0 +1,1910 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * Parser Elements, all classes representing documentable elements
+ * @package phpDocumentor
+ * @subpackage ParserElements
+ * @since 1.1
+ * @version $Id: ParserElements.inc,v 1.2 2005/11/28 07:27:59 cellog Exp $
+ */
+
+/**
+ * all elements except {@link parserPackagePage} descend from this abstract class
+ * @abstract
+ * @package phpDocumentor
+ * @subpackage ParserElements
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: ParserElements.inc,v 1.2 2005/11/28 07:27:59 cellog Exp $
+ */
+class parserElement extends parserBase
+{
+ /**
+ * @var mixed either false or a {@link parserDocBlock}
+ */
+ var $docblock = false;
+ /**
+ * name of this element, or include type if element is a {@link parserInclude}
+ */
+ var $name;
+
+ /**
+ * @var mixed either false or an array of paths to files with conflicts
+ */
+ var $conflicts = false;
+
+ /**
+ * location of this element (filename)
+ * @var string
+ */
+ var $file = '';
+
+ /**
+ * full path location of this element (filename)
+ * @var string
+ */
+ var $path = '';
+
+ /**
+ * line number on file where this element stops
+ * @since 1.2
+ * @var false|integer
+ */
+ var $endlinenumber = 0;
+
+ /**
+ * Line number in the source on which this element appears
+ * @since 1.2
+ * @var false|integer
+ */
+ var $linenumber = false;
+
+ /**
+ * @param parserDocBlock
+ */
+ function setDocBlock($docblock)
+ {
+ $this->docblock = $docblock;
+ }
+
+ /**
+ * @param string
+ */
+ function setName($name)
+ {
+ $this->name = trim($name);
+ }
+
+ /**
+ * Set starting line number
+ * @param integer
+ */
+ function setLineNumber($number)
+ {
+ $this->linenumber = $number;
+ }
+
+ /**
+ * Sets the ending line number of elements
+ * @param integer
+ */
+ function setEndLineNumber($l)
+ {
+ $this->endlinenumber = $l;
+ }
+
+ /**
+ * @return integer
+ */
+ function getLineNumber()
+ {
+ return $this->linenumber;
+ }
+
+ /**
+ * @return integer
+ */
+ function getEndLineNumber()
+ {
+ return $this->endlinenumber;
+ }
+
+ /** @return string package containing this element */
+ function getPackage()
+ {
+ if ($this->docblock)
+ {
+ return $this->docblock->package;
+ } else return $GLOBALS['phpDocumentor_DefaultPackageName'];
+ }
+
+ /** @param string */
+ function setFile($file)
+ {
+ $this->file = $file;
+ }
+
+ /** @param string */
+ function setPath($file)
+ {
+ // look for special windows case
+ if(SMART_PATH_DELIMITER === '\\')
+ $this->path = strtr($file,'/','\\');
+ else
+ $this->path = $file;
+ $this->path = $file;
+ }
+
+ /**
+ * @return string
+ */
+ function getName()
+ {
+ if (!isset($this->name)) return false;
+ return $this->name;
+ }
+
+ /**
+ * @return string
+ */
+ function getFile()
+ {
+ if (!isset($this->file)) return false;
+ return $this->file;
+ }
+
+ /**
+ * @return string
+ */
+ function getPath()
+ {
+ if (!isset($this->path)) return false;
+ return $this->path;
+ }
+}
+
+/**
+ * @package phpDocumentor
+ * @subpackage ParserElements
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: ParserElements.inc,v 1.2 2005/11/28 07:27:59 cellog Exp $
+ */
+class parserInclude extends parserElement
+{
+ /**
+ * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'
+ * @var string always 'include'
+ */
+ var $type = 'include';
+}
+
+/**
+ * @package phpDocumentor
+ * @subpackage ParserElements
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.1
+ * @version $Id: ParserElements.inc,v 1.2 2005/11/28 07:27:59 cellog Exp $
+ */
+class parserGlobal extends parserElement
+{
+ /**
+ * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'
+ * @var string always 'global'
+ */
+ var $type = 'global';
+
+ /**
+ * Name of the global's data type
+ * @var string
+ */
+ var $datatype = 'mixed';
+
+ /**
+ * quick way to link to this element
+ * @return mixed converter-specific link to this global variable
+ * @param Converter
+ * @param string text to display for the link or false for default text
+ */
+ function getLink(&$c, $text = false, $returnobj = false)
+ {
+ if ($returnobj)
+ {
+ return $c->getLink('global ' . $this->name, $this->docblock->package);
+ }
+ return $c->getGlobalLink($this->name, $this->docblock->package, $this->path, $text);
+ }
+
+ /**
+ * Returns all global variables in other packages that have the same name as this global variable
+ * @return mixed false or an array Format: (package => {@link parserGlobal} of conflicting global variable)
+ * @param Converter
+ */
+ function getConflicts(&$c)
+ {
+ $a = $c->proceduralpages->getGlobalConflicts($this->name);
+ unset($a[$this->docblock->package]);
+ return $a;
+ }
+
+ /**
+ * Sets the name of the global variable's type
+ * @param string
+ */
+ function setDataType($type)
+ {
+ $this->datatype = $type;
+ }
+
+ /**
+ * Retrieve converter-specific representation of the data type
+ *
+ * If the data type is a documented class name, then this function will
+ * return a Converter-specific link to that class's documentation, so users
+ * can click/browse to the documentation directly from the global variable
+ * declaration
+ * @return string
+ * @param Converter
+ */
+ function getDataType(&$converter)
+ {
+ $converted_datatype = $this->datatype;
+ if (strpos($this->datatype,'|'))
+ {
+ $types = explode('|',$this->datatype);
+ foreach($types as $returntype)
+ {
+ $a = $converter->getLink($returntype);
+ if (is_object($a) && phpDocumentor_get_class($a) == 'classlink')
+ {
+ if (!empty($my_types)) $my_types .= '|';
+ $my_types .= $converter->returnSee($a,$converter->type_adjust($returntype));
+ } else
+ {
+ if (!empty($my_types)) $my_types .= '|';
+ $my_types .= $converter->type_adjust($returntype);
+ }
+ }
+ $converted_datatype = $my_types;
+ } else
+ {
+ $a = $converter->getLink($this->datatype);
+ if (is_object($a) && phpDocumentor_get_class($a) == 'classlink')
+ {
+ $converted_datatype = $converter->returnSee($a,$converter->type_adjust($this->datatype));
+ } else
+ {
+ $converted_dataype = $converter->type_adjust($this->datatype);
+ }
+ }
+ return $converted_datatype;
+ }
+
+}
+
+/**
+ * @package phpDocumentor
+ * @subpackage ParserElements
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: ParserElements.inc,v 1.2 2005/11/28 07:27:59 cellog Exp $
+ */
+class parserFunction extends parserElement
+{
+ /**
+ * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'
+ * @var string always 'function'
+ */
+ var $type = 'function';
+ /**
+ * parameters parsed from function definition.
+ *
+ * param name may be null, in which case, updateParams() must be called from the Converter
+ * @var array Format: array(param name => default value parsed from function definition)
+ * @see updateParams()
+ */
+ var $params = false;
+ /**
+ * Function returns a reference to an element, instead of a value
+ *
+ * set to true if function is declared as:
+ * <code>
+ * function &func(...
+ * </code>
+ * @var boolean
+ */
+ var $returnsreference = false;
+ /**
+ * global declarations parsed from function definition
+ *
+ * @var array Format: array(globalname1, globalname2,....)
+ */
+ var $globals = false;
+ /**
+ * static variable declarations parsed from function definition
+ * @var array Format: array(array('name' => staticvar1,'val' => '' or default val of staticvar1),...)
+ */
+ var $statics = false;
+
+ var $source = '';
+ /**
+ * @param string
+ * @param string default value parsed from function definition
+ * @param boolean indicates whether this parameter has a default value
+ */
+ function addParam($name, $value, $has_default = true)
+ {
+ $this->params[$name] = array($value, $has_default);
+ }
+
+ /**
+ * Set the source code. Always array in PHP 4.3.0+
+ * @param string|array
+ */
+ function addSource($source)
+ {
+ $this->source = $source;
+ }
+
+ /**
+ * Determine whether the source code has been requested via {@}source}
+ * @return boolean
+ */
+ function hasSource()
+ {
+ if (is_array($this->source)) return true;
+ return strlen($this->source);
+ }
+
+ /**
+ * @return string|array source code ready for highlighting
+ */
+ function getSource()
+ {
+ return $this->source;
+ }
+
+ /**
+ * quick way to link to this element
+ * @return mixed converter-specific link to this function
+ * @param Converter
+ * @param string text to display for the link or false for default text
+ */
+ function getLink($c, $text = false, $returnobj = false)
+ {
+ if ($returnobj)
+ {
+ return $c->getLink('function ' . $this->name, $this->docblock->package);
+ }
+ return $c->getFunctionLink($this->name, $this->docblock->package, $this->path, $text);
+ }
+
+ /**
+ * Returns all functions in other packages that have the same name as this function
+ * @return mixed false or an array Format: (package => {@link parserFunction} of conflicting functions)
+ * @param Converter
+ */
+ function getConflicts(&$c)
+ {
+ $a = $c->proceduralpages->getFuncConflicts($this->name);
+ unset($a[$this->docblock->package]);
+ return $a;
+ }
+
+ /**
+ * Add all "global $var, $var2" declarations to this function
+ * @param array $globals Format: array(globalname1, globalname2,....)
+ */
+ function addGlobals($globals)
+ {
+ $this->globals = $globals;
+ }
+
+ /**
+ * Add all "static $var, $var2 = 6" declarations to this function
+ * @param array Format: array(varname1, varname2,...)
+ * @param array Format: array(default val of var 1, default val of var 2,...) if var 1 has no default, array(default val of var 2,...)
+ */
+ function addStatics($static,$vals)
+ {
+ if (count($static))
+ {
+ $this->statics = array();
+ for($i=0;$i<count($static);$i++)
+ {
+ if (isset($static[$i]))
+ {
+ $a = '';
+ if (isset($vals[$i])) $a = $vals[$i];
+ $this->statics[] = array('name' => $static[$i],'val' => $a);
+ }
+ }
+ }
+ }
+
+ /**
+ * @return string default value of param $name
+ * @param string
+ */
+ function getParam ($name)
+ {
+ if (!isset($this->params[$name])) return false;
+ $test = $this->params[$name];
+ if ($test[1])
+ {
+ return $this->params[$name];
+ } else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * @return array format: array(array(paramname, default value),...)
+ */
+ function listParams ()
+ {
+ if (isset($this->params))
+ {
+ $ret = array();
+ if ($this->params)
+ foreach($this->params as $key => $val)
+ {
+ if ($val[1])
+ {
+ $arr = array($key,$val[0]);
+ if (isset($val[2]))
+ {
+ $arr[2] = $val[2];
+ }
+ $ret[] = $arr;
+ } else
+ {
+ $arr = array($key,false);
+ if (isset($val[2]))
+ {
+ $arr[2] = $val[2];
+ }
+ $ret[] = $arr;
+ }
+ }
+ return $ret;
+ } else {
+ return array();
+ }
+ }
+
+ /**
+ * @return array format: array(array(index, globalname),...)
+ */
+ function listGlobals ()
+ {
+ if (isset($this->globals))
+ {
+ $ret = array();
+ if ($this->globals)
+ foreach($this->globals as $key => $val)
+ {
+ $ret[] = array($key,$val);
+ }
+ return $ret;
+ } else {
+ return array();
+ }
+ }
+
+ /**
+ * @return array format: array(array(static var name, static var default value),...)
+ */
+ function listStatics ()
+ {
+ if (isset($this->statics))
+ {
+ $ret = array();
+ if ($this->statics)
+ foreach($this->statics as $key => $val)
+ {
+ $ret[] = array($val['name'],$val['val']);
+ }
+ return $ret;
+ } else {
+ return array();
+ }
+ }
+
+ /**
+ * sets {@link $returnsreference} to true
+ */
+ function setReturnsReference()
+ {
+ $this->returnsreference = true;
+ }
+
+ /**
+ * @return boolean returns value of {@link $returnsreference}
+ */
+ function getReturnsReference()
+ {
+ return $this->returnsreference;
+ }
+
+ /**
+ * Get a human-friendly description of the function call
+ *
+ * takes declaration like:
+ * <code>
+ * /** @returns string ... {rest of docblock}
+ * function &func($param1, $param2 = 6,
+ * $param3 = array('20',9 => "heroo"))
+ * {...}
+ * </code>
+ * and returns:
+ * string &func( $param1, [$param2 = 6], [$param3 = array('20',9 => "heroo")] )
+ * @return string stylized function declaration
+ */
+ function getFunctionCall()
+ {
+ $a = '';
+ if ($this->getReturnsReference()) $a = '&';
+ $function_call = $a.$this->getName() . " ( ";
+ $tmp = 0;
+ foreach($this->listParams() as $param)
+ {
+ if ($tmp == 0)
+ {
+ $tmp = 1;
+ } else {
+ $function_call .= ", ";
+ }
+ if ($param[1] !== false)
+ {
+ $function_call .= "[$param[0] = $param[1]]";
+ } else {
+ $function_call .= $param[0];
+ }
+ $update_params[] = $param[0];
+ }
+ $function_call .= " )";
+ return $function_call;
+ }
+
+ /**
+ * Like getFunctionCall(), but has no English or pre-determined formatting.
+ *
+ * Much more flexible.
+ * @return array Format:
+ * <code>
+ * array('name' => function name,
+ * 'returnsref' => boolean if declared as "function &name()"
+ * 'params' => array('type' => data type of parameter,
+ * 'description' => from @param tag,
+ * 'name' => variable name,
+ * 'default' => default value if any))
+ * </code>
+ * @see getFunctionCall()
+ */
+ function getIntricateFunctionCall($converter,$paramtags)
+ {
+ $a = array();
+ if ($this->getReturnsReference()) $a['returnsref'] = true;
+ $a['name'] = $converter->type_adjust($this->getName());
+ $c = $this->listParams();
+ foreach($c as $param)
+ {
+ $b = array();
+ $b['type'] = 'mixed';
+ if (isset($paramtags[$param[0]]))
+ {
+ $b['type'] = $paramtags[$param[0]]['datatype'];
+ $b['description'] = $paramtags[$param[0]]['data'];
+ unset($paramtags[$param[0]]);
+ } elseif(isset($paramtags[substr($param[0],1)]))
+ {
+ $b['type'] = $paramtags[substr($param[0],1)]['datatype'];
+ $b['description'] = $paramtags[substr($param[0],1)]['data'];
+ unset($paramtags[substr($param[0],1)]);
+ }
+ if (isset($param[2]))
+ {
+ $b['type'] = $param[2];
+ }
+ $b['name'] = $param[0];
+ $b['default'] = $param[1];
+ $b['hasdefault'] = ($param[1] !== false);
+ $a['params'][] = $b;
+ }
+ // @param tags that don't correspond to actual parameters (like extra function values)
+ if (count($paramtags))
+ {
+ foreach($paramtags as $param)
+ {
+ $b = array();
+ $b['type'] = $param['datatype'];
+ $b['description'] = $param['data'];
+ $b['name'] = $param['var'];
+ $b['default'] = '';
+ $b['hasdefault'] = false;
+ $a['params'][] = $b;
+ }
+ }
+ return $a;
+ }
+}
+
+/**
+ * @package phpDocumentor
+ * @subpackage ParserElements
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: ParserElements.inc,v 1.2 2005/11/28 07:27:59 cellog Exp $
+ */
+class parserClass extends parserElement
+{
+ /**
+ * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'
+ * @var string always 'class'
+ */
+ var $type = 'class';
+ /** @var string
+ * @see parserPage::$sourceLocation */
+ var $sourceLocation = '';
+ /**
+ * @var mixed false or contents of extends clause in class declaration
+ */
+ var $extends = false;
+ /**
+ * @var array a list of interfaces this class implements
+ */
+ var $_implements = array();
+ /**
+ * @var array a list of interfaces this class implements
+ * @access private
+ */
+ var $_modifiers = false;
+ /**
+ * @var boolean determines whether a class is considered to be an interface
+ * @access private
+ */
+ var $_isInterface = false;
+ /**
+ * Format: array(file, parent) where parent class is found or false if no parent
+ * @var mixed
+ */
+ var $parent = false;
+ /**
+ * Used to determine whether a class should be ignored or not. Helps maintain integrity of parsing
+ * @var boolean
+ * @see Classes::getParentClass()
+ */
+ var $ignore = false;
+
+ /**
+ * @var string same as {@link parserElement::$path}
+ */
+ var $curfile = false;
+ /**
+ * @var tutorialLink|false either a link to the tutorial associated with this class, or false
+ */
+ var $tutorial = false;
+
+ /**
+ * Return name of the class that contains this method
+ * @return string
+ */
+ function getModifiers()
+ {
+ return $this->_modifiers;
+ }
+
+ /**
+ * Return name of the class that contains this method
+ * @return string
+ */
+ function setModifiers($m)
+ {
+ $this->_modifiers = $m;
+ }
+
+ /**
+ * @param parserTutorial
+ * @param Converter
+ */
+ function addTutorial($t,&$c)
+ {
+ $this->tutorial = new tutorialLink;
+ $this->tutorial->addLink('',$t->path,$t->name,$t->package,$t->subpackage,$t->getTitle($c));
+ }
+
+ /**
+ * Get the associated tutorial for this class, if any
+ * @tutorial tutorials.pkg
+ * @return parserTutorial
+ */
+ function getTutorial()
+ {
+ return $this->tutorial;
+ }
+
+ /**
+ * Returns all classes in other packages that have the same name as this class
+ * @return mixed false or an array Format: (package => {@link parserClass} of conflicting classes)
+ * @param Converter
+ */
+ function getConflicts(&$c)
+ {
+ $a = $c->classes->getConflicts($this->name);
+ unset($a[$this->docblock->package]);
+ return $a;
+ }
+
+ /**
+ * quick way to link to this element
+ * @return mixed converter-specific link to this class
+ * @param Converter
+ * @param string text to display for the link or false for default text
+ */
+ function getLink($c, $text = false, $returnobj = false)
+ {
+ if ($returnobj)
+ {
+ return $c->getLink('object ' . $this->name, $this->docblock->package);
+ }
+ return $c->getClassLink($this->name, $this->docblock->package, $this->curfile, $text);
+ }
+
+ /**
+ * @param string parent class name
+ * @param string parent class file
+ * @param Classes {@link Classes} object currently calling setParent
+ * @see Classes::setClassParent()
+ */
+
+ function setParent($p,$f, &$c)
+ {
+ $this->parent = array($f, $p);
+ $p = $c->getClass($p, $f);
+ // inherit package if no @package tag is in the docblock, fixes 591396
+ if (!$this->docblock->getExplicitPackage())
+ {
+ $this->docblock->package = $p->docblock->package;
+ }
+ if ($this->docblock->package == $p->docblock->package)
+ {
+ if ($this->docblock->subpackage == '')
+ $this->docblock->subpackage = $p->docblock->subpackage;
+ }
+ $author = $p->docblock->getKeyword('author');
+ $version = $p->docblock->getKeyword('version');
+ $copyright = $p->docblock->getKeyword('copyright');
+ // inherit tags
+ if (!$this->docblock->getKeyword('author'))
+ {
+ if ($author && !is_array($author)) $author = array($author);
+ if ($author) $this->docblock->tags['author'] = $author;
+ }
+ if (!$this->docblock->getKeyword('version'))
+ {
+ if ($version && !is_array($version)) $version = array($version);
+ if ($version) $this->docblock->tags['version'] = $version;
+ }
+ if (!$this->docblock->getKeyword('copyright'))
+ {
+ if ($copyright && !is_array($copyright)) $copyright = array($copyright);
+ if ($copyright) $this->docblock->tags['copyright'] = $copyright;
+ }
+ if (!$this->docblock->sdesc)
+ {
+ $this->docblock->setShortDesc($p->docblock);
+ $this->docblock->setDesc($p->docblock);
+ } else
+ {
+ if ($this->docblock->hasInheritDoc())
+ {
+ $this->docblock->replaceInheritDoc($p->docblock);
+ }
+ }
+ }
+
+ /**
+ * @param string $par parent class name (used by {@link Classes::setClassParent()} if parent class not found
+ */
+ function setParentNoClass($par)
+ {
+ $this->parent = $par;
+ }
+
+ /**
+ * Use this method to set the type of class to be an interface
+ */
+ function setInterface()
+ {
+ $this->_isInterface = true;
+ }
+
+ /**
+ * @return boolean true if this is an interface class
+ */
+ function isInterface()
+ {
+ return $this->_isInterface;
+ }
+
+ /**
+ * Use this method to set access modifiers for a class
+ * @param array
+ */
+ function setAccessModifiers($modifiers)
+ {
+ $this->_modifiers = $modifiers;
+ }
+
+ /**
+ * retrieve object that represents the parent class
+ * @param Converter this function will not work before the Conversion stage of parsing
+ * @return mixed returns the {@link parserClass} representation of the parent class, or false if no parent class
+ */
+ function &getParent(&$c)
+ {
+ $a = false;
+ if (!$this->parent) return $a;
+ if (is_array($this->parent))
+ {
+ return $c->classes->getClass($this->parent[1],$this->parent[0]);
+ } else return $this->parent;
+ }
+
+ /**
+ * @param Converter this function will not work before the Conversion stage of parsing
+ * @return array returns a simple array of method objects
+ */
+ function getMethods(&$c)
+ {
+ return $c->classes->getMethods($this->name,$this->curfile);
+ }
+
+ /**
+ * @return mixed {@link parserMethod} or false if not found
+ * @param Converter this function will not work before the Conversion stage of parsing
+ * @param string method name in this class
+ */
+ function getMethod(&$c, $name)
+ {
+ return $c->classes->getMethod($this->name,$this->curfile,$name);
+ }
+
+ /**
+ * @return mixed {@link parserVar} or false if not found
+ * @param Converter this function will not work before the Conversion stage of parsing
+ * @param string var name in this class
+ */
+ function getVar(&$c, $name)
+ {
+ return $c->classes->getVar($this->name,$this->curfile,$name);
+ }
+
+ /**
+ * @param Converter this function will not work before the Conversion stage of parsing
+ * @return array returns a simple array of method name strings
+ */
+ function getMethodNames(&$c)
+ {
+ if (!$c->classes->hasMethods($this->curfile, $this->name)) return array();
+ $arr = array();
+ $arr1 = $this->getMethods($c);
+ for($i=0; $i < count($arr1); $i++)
+ {
+ $arr[] = $arr1[$i]->name;
+ }
+ return $arr;
+ }
+
+ /**
+ * @param Converter this function will not work before the Conversion stage of parsing
+ * @param string method name
+ * @return boolean whether this class has a method of name $name
+ */
+ function hasMethod(&$c,$name)
+ {
+ return $c->classes->hasMethod($this->name, $this->curfile, $name);
+ }
+
+ /**
+ * @param Converter this function will not work before the Conversion stage of parsing
+ * @param string var name
+ * @return boolean whether this class has a var of name $name
+ */
+ function hasVar(&$c,$name)
+ {
+ return $c->classes->hasVar($this->name, $this->curfile, $name);
+ }
+
+ /**
+ * @param Converter this function will not work before the Conversion stage of parsing
+ * @param string class constant name
+ * @return boolean whether this class has a constant of name $name
+ */
+ function hasConst(&$c,$name)
+ {
+ return $c->classes->hasConst($this->name, $this->curfile, $name);
+ }
+
+ /**
+ * @param Converter this function will not work before the Conversion stage of parsing
+ * @return array returns a simple array of var objects
+ */
+ function getVars(&$c)
+ {
+ return $c->classes->getVars($this->name,$this->curfile);
+ }
+
+ /**
+ * @param Converter this function will not work before the Conversion stage of parsing
+ * @return array returns a simple array of const objects
+ */
+ function getConsts(&$c)
+ {
+ return $c->classes->getConsts($this->name,$this->curfile);
+ }
+
+ /**
+ * @param Converter this function will not work before the Conversion stage of parsing
+ * @return array returns a simple array of var name strings
+ */
+ function getVarNames(&$c)
+ {
+ if (!$c->classes->hasVars($this->curfile, $this->name)) return array();
+ $arr = array();
+ $arr1 = $this->getVars($c);
+ for($i=0; $i < count($arr1); $i++)
+ {
+ $arr[] = $arr1[$i]->name;
+ }
+ return $arr;
+ }
+
+ /**
+ * @param Converter this function will not work before the Conversion stage of parsing
+ * @return array returns a simple array of const name strings
+ */
+ function getConstNames(&$c)
+ {
+ if (!$c->classes->hasConsts($this->curfile, $this->name)) return array();
+ $arr = array();
+ $arr1 = $this->getConsts($c);
+ for($i=0; $i < count($arr1); $i++)
+ {
+ $arr[] = $arr1[$i]->name;
+ }
+ return $arr;
+ }
+
+ /**
+ * @param Converter this function will not work before the Conversion stage of parsing
+ * @param boolean determines whether overriden methods should be included in the list of inherited methods
+ * @return array returns an array of methods by parent classname array(name => array(method1,method2..),name2 => array(method1....))
+ */
+ function getInheritedMethods(&$c,$override = false)
+ {
+ $x = $this;
+ $methods = array();
+ $arr = array();
+ while ($x->parent && is_array($x->parent))
+ {
+ $methods = array_merge($methods,$x->getMethodNames($c));
+ $par = $x->getParent($c);
+ $parmethodnames = $par->getMethodNames($c);
+ $parmethods = $par->getMethods($c);
+ for($i=0; $i<count($parmethodnames); $i++)
+ {
+ if ($override)
+ {
+ if (!in_array($parmethodnames[$i],$methods))
+ {
+ // fix for bug 587733
+ if ($parmethods[$i]->docblock && $parmethods[$i]->docblock->hasaccess && !$c->parseprivate && $parmethods[$i]->docblock->tags['access'][0]->value == 'private')
+ {
+ continue;
+ }
+ $methods[] = $parmethodnames[$i];
+ $arr[$par->getName()]['methods'][] = $parmethods[$i];
+ $arr[$par->getName()]['file'] = $par->curfile;
+ }
+ } else
+ {
+ // fix for bug 587733
+ if ($parmethods[$i]->docblock && $parmethods[$i]->docblock->hasaccess && !$c->parseprivate && $parmethods[$i]->docblock->tags['access'][0]->value == 'private')
+ {
+ continue;
+ }
+ $arr[$par->getName()]['methods'][] = $parmethods[$i];
+ $arr[$par->getName()]['file'] = $par->curfile;
+ }
+ }
+ $x = &$par;
+ }
+ return $arr;
+ }
+
+ /**
+ * @param Converter this function will not work before the Conversion stage of parsing
+ * @param boolean determines whether overriden vars should be included in the list of inherited vars
+ * @return array returns an array of vars by parent classname array(name => array(var1,var1..),name2 => array(var1....))
+ */
+ function getInheritedVars(&$c,$override = true, $vars = false)
+ {
+ $x = $this;
+ $vars = array();
+ $arr = array();
+ while ($x->parent && is_array($x->parent))
+ {
+ $vars = array_merge($vars,$x->getVarNames($c));
+ $par = $x->getParent($c);
+ $parvarnames = $par->getVarNames($c);
+ $parvars = $par->getVars($c);
+ for($i=0; $i<count($parvarnames); $i++)
+ {
+ if ($override)
+ {
+ if (!in_array($parvarnames[$i],$vars))
+ {
+ // fix for bug 587733
+ if ($parvars[$i]->docblock && $parvars[$i]->docblock->hasaccess && !$c->parseprivate && $parvars[$i]->docblock->tags['access'][0]->value == 'private')
+ {
+ continue;
+ }
+ $vars[] = $parvarnames[$i];
+ $arr[$par->getName()]['vars'][] = $parvars[$i];
+ $arr[$par->getName()]['file'] = $par->curfile;
+ }
+ } else
+ {
+ // fix for bug 587733
+ if ($parvars[$i]->docblock && $parvars[$i]->docblock->hasaccess && !$c->parseprivate && $parvars[$i]->docblock->tags['access'][0]->value == 'private')
+ {
+ continue;
+ }
+ $arr[$par->getName()]['vars'][] = $parvars[$i];
+ $arr[$par->getName()]['file'] = $par->curfile;
+ }
+ }
+ $x = &$par;
+ }
+ return $arr;
+ }
+
+ /**
+ * @param Converter this function will not work before the Conversion stage of parsing
+ * @param boolean determines whether overriden vars should be included in the list of inherited vars
+ * @return array returns an array of consts by parent classname array(name => array(const1,const2..),name2 => array(const1....))
+ */
+ function getInheritedConsts(&$c,$override = false, $consts = false)
+ {
+ $x = $this;
+ $consts = array();
+ $arr = array();
+ while ($x->parent && is_array($x->parent))
+ {
+ $consts = array_merge($consts,$x->getConstNames($c));
+ $par = $x->getParent($c);
+ $parvarnames = $par->getConstNames($c);
+ $parvars = $par->getConsts($c);
+ for($i=0; $i<count($parvarnames); $i++)
+ {
+ if ($override)
+ {
+ if (!in_array($parvarnames[$i],$consts))
+ {
+ // fix for bug 587733
+ if ($parvars[$i]->docblock && $parvars[$i]->docblock->hasaccess && !$c->parseprivate && $parvars[$i]->docblock->tags['access'][0]->value == 'private')
+ {
+ continue;
+ }
+ $consts[] = $parvarnames[$i];
+ $arr[$par->getName()]['consts'][] = $parvars[$i];
+ $arr[$par->getName()]['file'] = $par->curfile;
+ }
+ } else
+ {
+ // fix for bug 587733
+ if ($parvars[$i]->docblock && $parvars[$i]->docblock->hasaccess && !$c->parseprivate && $parvars[$i]->docblock->tags['access'][0]->value == 'private')
+ {
+ continue;
+ }
+ $arr[$par->getName()]['consts'][] = $parvars[$i];
+ $arr[$par->getName()]['file'] = $par->curfile;
+ }
+ }
+ $x = &$par;
+ }
+ return $arr;
+ }
+
+ /**
+ * @param Converter this function will not work before the Conversion stage of parsing
+ * @return array Format: array(parentclassname => parserClass/false if no parent, parentclassname2 => ...)
+ */
+ function getParentClassTree(&$c)
+ {
+ $result = array();
+ $result[$this->name] = $arr = $this->getParent($c);
+ if (is_string($arr)) $result[$arr] = false;
+ while ($arr && is_object($arr))
+ {
+ $result[$arr->name] = $arr->getParent($c);
+ $arr = $arr->getParent($c);
+ if (is_string($arr)) $result[$arr] = false;
+ }
+ return $result;
+ }
+
+ /**
+ * returns a list of all child classes of this class
+ * @param Converter this function will not work before the Conversion stage of parsing
+ * @return array Format: array(parserClass child1,parserClass child2,...)
+ */
+ function getChildClassList(&$c)
+ {
+ $list = array();
+ $kids = $c->classes->getDefiniteChildren($this->name,$this->curfile);
+ if ($kids)
+ {
+ foreach($kids as $chile => $file)
+ {
+ $list[] = $c->classes->getClass($chile,$file);
+ }
+ }
+ return $list;
+ }
+
+ /**
+ * @param string
+ * @see $sourceLocation
+ */
+ function setSourceLocation($sl)
+ {
+ $this->sourceLocation = $sl;
+ }
+
+ /**
+ * @param Converter
+ * @param boolean
+ * @return string
+ * @see $sourceLocation
+ */
+ function getSourceLocation($c,$pearize = false)
+ {
+ global $_phpDocumentor_options;
+ if (!isset($this->sourceLocation)) return false;
+ if ($pearize)
+ {
+ $sl = $this->sourceLocation;
+ if (strpos($sl,'pear/'))
+ {
+ $sl = substr($sl,strpos($sl,'pear/') + 5);
+ return $sl;
+ } else
+ {
+ return $sl;
+ }
+ return $sl;
+ }
+ return $this->sourceLocation;
+ }
+
+ /**
+ * @param string
+ * @see $extends
+ */
+ function setExtends($extends)
+ {
+ $this->extends = $extends;
+ }
+
+ /**
+ * @param string
+ */
+ function addImplements($implements)
+ {
+ $this->_implements[] = $implements;
+ }
+
+ /**
+ * @return array
+ */
+ function getImplements()
+ {
+ return $this->_implements;
+ }
+
+ /**
+ * @return boolean
+ * @see $extends
+ */
+ function getExtends()
+ {
+ if (!isset($this->extends)) return false;
+ return $this->extends;
+ }
+}
+
+/**
+ * @package phpDocumentor
+ * @subpackage ParserElements
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: ParserElements.inc,v 1.2 2005/11/28 07:27:59 cellog Exp $
+ */
+class parserVar extends parserElement
+{
+ /**
+ * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'
+ * @var string always 'var'
+ */
+ var $type = 'var';
+ /** @var string class that contains this var */
+ var $class = '';
+ /** @var array */
+ var $_modifiers;
+
+ /**
+ * @param string
+ */
+ function parserVar($class)
+ {
+ $this->class = $class;
+ }
+
+ /**
+ * Retrieve the class name
+ * @return string Class name that this var belongs to
+ */
+ function getClass()
+ {
+ return $this->class;
+ }
+
+ /**
+ * Return name of the class that contains this method
+ * @return string
+ */
+ function getModifiers()
+ {
+ return $this->_modifiers;
+ }
+
+ /**
+ * Return name of the class that contains this method
+ * @return string
+ */
+ function setModifiers($m)
+ {
+ $this->_modifiers = $m;
+ }
+
+ /**
+ * quick way to link to this element
+ * @return mixed converter-specific link to this var
+ * @param Converter $c
+ * @param string $text text to display for the link or false for default text
+ */
+ function getLink($c, $text = false, $returnobj = false)
+ {
+ if ($returnobj)
+ {
+ return $c->getLink($this->class . '::' . $this->name, $this->docblock->package);
+ }
+ return $c->getVarLink($this->name, $this->class, $this->docblock->package, false, $text);
+ }
+
+ /**
+ * @param Converter
+ * @return mixed {@link parserVar} representing var this var overrides from the parent class, or false if none
+ */
+ function getOverrides(&$c)
+ {
+ $class = $c->classes->getClass($this->class,$this->path);
+ $par = $class->getParent($c);
+
+ while (is_object($par))
+ {
+ if ($par->hasVar($c,$this->name))
+ {
+ $var = $par->getVar($c,$this->name);
+ if (!($var->docblock && $var->docblock->hasaccess && !$c->parseprivate && $var->docblock->tags['access'][0]->value == 'private'))
+ return $var;
+ }
+ $par = $par->getParent($c);
+ }
+
+ return false;
+ }
+
+ /**
+ * @param Converter
+ * @return array an array of parserVars from ALL child classes that override this var
+ */
+ function getOverridingVars(&$c)
+ {
+ $class = $c->classes->getClass($this->class,$this->path);
+
+ return $this->getOverridingVarsForClass($c, $class);
+ }
+
+ /**
+ * @param Converter
+ * @param parserClass
+ * @return array an array of parserVars from ALL child classes that override this var in the given class
+ */
+ function getOverridingVarsForClass(&$c, &$class)
+ {
+ $vars = array();
+ if (!$class) return $meths;
+ $kids = $class->getChildClassList($c);
+ for($i=0; $i<count($kids); $i++)
+ {
+ if ($kids[$i]->hasVar($c, $this->name))
+ {
+ $var = $kids[$i]->getVar($c,$this->name);
+ if (!($var->docblock && $var->docblock->hasaccess && !$c->parseprivate && $var->docblock->tags['access'][0]->value == 'private'))
+ $vars[] = $var;
+ }
+
+ $vars = array_merge($vars, $this->getOverridingVarsForClass($c, $kids[$i]));
+ }
+ return $vars;
+ }
+}
+
+/**
+ * @package phpDocumentor
+ * @subpackage ParserElements
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.2.4
+ */
+class parserConst extends parserElement
+{
+ /**
+ * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'
+ * @var string always 'const'
+ */
+ var $type = 'const';
+ /** @var string class that contains this var */
+ var $class = '';
+
+ /**
+ * @param string
+ */
+ function parserConst($class)
+ {
+ $this->class = $class;
+ }
+
+ /**
+ * Retrieve the class name
+ * @return string Class name that this var belongs to
+ */
+ function getClass()
+ {
+ return $this->class;
+ }
+
+ /**
+ * quick way to link to this element
+ * @return mixed converter-specific link to this var
+ * @param Converter $c
+ * @param string $text text to display for the link or false for default text
+ */
+ function getLink($c, $text = false, $returnobj = false)
+ {
+ if ($returnobj)
+ {
+ return $c->getLink($this->class . '::'. $this->name, $this->docblock->package);
+ }
+ return $c->getConstLink($this->name, $this->class, $this->docblock->package, false, $text);
+ }
+}
+
+/**
+ * @package phpDocumentor
+ * @subpackage ParserElements
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: ParserElements.inc,v 1.2 2005/11/28 07:27:59 cellog Exp $
+ */
+class parserMethod extends parserFunction
+{
+ /**
+ * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'
+ * @var string always 'method'
+ */
+ var $type = 'method';
+ /** @var boolean whether this method is a constructor */
+ var $isConstructor = false;
+ /** @var boolean whether this method is a destructor by PEAR standards */
+ var $isDestructor = false;
+ /** @var string class that contains this method */
+ var $class = '';
+ var $_modifiers = array();
+
+ /**
+ * @param string
+ */
+ function parserMethod($class)
+ {
+ $this->class = $class;
+ }
+
+ /**
+ * @param string
+ * @param string default value parsed from function definition
+ * @param boolean indicates whether this parameter has a default value
+ * @param null|string class type hint
+ */
+ function addParam($name, $value, $has_default = true, $typehint = null)
+ {
+ $this->params[$name] = array($value, $has_default);
+ if (isset($typehint))
+ {
+ $this->params[$name][2] = $typehint;
+ }
+ }
+
+ /**
+ * adds "constructor " to start of function call if {@link $isConstructor} is true
+ * @return string
+ * @see parent::getFunctionCall()
+ */
+ function getFunctionCall()
+ {
+ $a = parserFunction::getFunctionCall();
+ if ($this->isConstructor) $a = "constructor $a";
+ return $a;
+ }
+
+ function getIntricateFunctionCall($converter,$paramtags)
+ {
+ $a = parserFunction::getIntricateFunctionCall($converter,$paramtags);
+ if ($this->isConstructor) $a['constructor'] = true;
+ if ($this->isDestructor) $a['destructor'] = true;
+ return $a;
+ }
+
+ /**
+ * Return name of the class that contains this method
+ * @return string
+ */
+ function getClass()
+ {
+ return $this->class;
+ }
+
+ /**
+ * Return name of the class that contains this method
+ * @return string
+ */
+ function getModifiers()
+ {
+ return $this->_modifiers;
+ }
+
+ /**
+ * Return name of the class that contains this method
+ * @return string
+ */
+ function setModifiers($m)
+ {
+ $this->_modifiers = $m;
+ }
+
+ /**
+ * @param Converter
+ * @return mixed {@link parserMethod} representing method this method overrides from the parent class, or false if none
+ */
+ function getOverrides(&$c)
+ {
+ $class = $c->classes->getClass($this->class,$this->path);
+
+ $par = $class->getParent($c);
+
+ while (is_object($par))
+ {
+ if ($par->hasMethod($c,$this->name))
+ {
+ $meth = $par->getMethod($c,$this->name);
+ if (!($meth->docblock && $meth->docblock->hasaccess && !$c->parseprivate && $meth->docblock->tags['access'][0]->value == 'private'))
+ return $meth;
+ }
+
+ $par = $par->getParent($c);
+ }
+
+ return false;
+ }
+
+ /**
+ * quick way to link to this element
+ * @return mixed converter-specific link to this method
+ * @param Converter $c
+ * @param string $text text to display for the link or false for default text
+ */
+ function getLink($c, $text = false, $returnobj = false)
+ {
+ if ($returnobj)
+ {
+ return $c->getLink($this->class . '::' . $this->name . '()', $this->docblock->package);
+ }
+ return $c->getMethodLink($this->name, $this->class, $this->docblock->package, false, $text);
+ }
+
+ /**
+ * Use this method to tell the parser that this method is the class constructor
+ */
+ function setConstructor()
+ {
+ $this->isConstructor = true;
+ }
+
+ /**
+ * Use this method to tell the parser that this method is the class constructor
+ */
+ function setDestructor()
+ {
+ $this->isDestructor = true;
+ }
+
+ /**
+ * @param Converter
+ * @return array an array of parserMethods from child classes that override this method
+ */
+ function getOverridingMethods(&$c)
+ {
+ $class = $c->classes->getClass($this->class,$this->path);
+
+ return $this->getOverridingMethodsForClass($c, $class);
+ }
+
+ /**
+ * @param Converter
+ * @param parserClass
+ * @return array an array of parserMethods from ALL child classes that override this method in the given class
+ */
+ function getOverridingMethodsForClass(&$c, &$class)
+ {
+ $meths = array();
+ if (!$class) return $meths;
+ $kids = $class->getChildClassList($c);
+ for($i=0; $i<count($kids); $i++)
+ {
+ if ($kids[$i]->hasMethod($c, $this->name))
+ {
+ $meth = $kids[$i]->getMethod($c,$this->name);
+ if (!($meth->docblock && $meth->docblock->hasaccess && !$c->parseprivate && $meth->docblock->tags['access'][0]->value == 'private'))
+ $meths[] = $meth;
+ }
+
+ $meths = array_merge($meths, $this->getOverridingMethodsForClass($c, $kids[$i]));
+ }
+ return $meths;
+ }
+}
+
+/**
+ * @package phpDocumentor
+ * @subpackage ParserElements
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: ParserElements.inc,v 1.2 2005/11/28 07:27:59 cellog Exp $
+ */
+class parserDefine extends parserElement
+{
+ /**
+ * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'
+ * @var string always 'define'
+ */
+ var $type = 'define';
+
+ /**
+ * quick way to link to this element
+ * @return mixed converter-specific link to this define
+ * @param Converter $c
+ * @param string $text text to display for the link or false for default text
+ */
+ function getLink($c, $text = false, $returnobj = false)
+ {
+ if ($returnobj)
+ {
+ return $c->getLink('constant ' . $this->name, $this->docblock->package);
+ }
+ return $c->getDefineLink($this->name, $this->docblock->package, false, $text);
+ }
+
+ /**
+ * Returns all defines in other packages that have the same name as this define
+ * @return mixed false or an array Format: (package => {@link parserDefine} of conflicting defines)
+ * @param Converter
+ */
+ function getConflicts(&$c)
+ {
+ $a = $c->proceduralpages->getDefineConflicts($this->name);
+ unset($a[$this->docblock->package]);
+ return $a;
+ }
+
+}
+
+/**
+ * @package phpDocumentor
+ * @subpackage ParserElements
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.0rc1
+ * @version $Id: ParserElements.inc,v 1.2 2005/11/28 07:27:59 cellog Exp $
+ */
+class parserPackagePage extends parserStringWithInlineTags
+{
+ /**
+ * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'
+ * @var string always 'packagepage'
+ */
+ var $type = 'packagepage';
+ /** @var string */
+ var $package = 'default';
+
+ /**
+ * @param string
+ */
+ function parserPackagePage($package)
+ {
+ $this->package = $package;
+ }
+
+ /**
+ * @param Converter
+ */
+ function Convert(&$c)
+ {
+ return parent::Convert($c,false);
+ }
+}
+
+/**
+ * @package phpDocumentor
+ * @subpackage ParserElements
+ * @since 1.2
+ */
+class parserTutorial extends parserPackagePage
+{
+ /**
+ * Type is used by many functions to skip the hassle of if phpDocumentor_get_class($blah) == 'parserBlah'
+ * @var string always 'tutorial'
+ */
+ var $type = 'tutorial';
+ /** @var string */
+ var $package = 'default';
+ /**
+ * Either cls, pkg, or proc
+ * @var string
+ */
+ var $tutorial_type;
+ /**
+ * The documentable element this tutorial is linked to
+ *
+ * Can be a parserData, parserClass, or nothing for package/subpackage docs
+ */
+ var $linked_element;
+ /**
+ * path to the tutorial page
+ * @var string
+ */
+ var $path;
+ /**
+ * filename minus extension of this tutorial (used for @tutorial tag)
+ * @var string
+ */
+ var $name;
+ /** @var boolean */
+ var $_xml = true;
+ /**
+ * output from tutorialname.ext.ini
+ *
+ * an array generated by {@link phpDocumentor_parse_ini_file()} containing
+ * an index 'Linked Tutorials' with an array of tutorial names in the order
+ * they should appear. This is used to generate a linked list of tutorials like
+ * {@tutorial phpDocumentor/tags.pkg}
+ * @var array
+ */
+ var $ini = false;
+ /**
+ * link to the next tutorial in a document series, or false if none
+ * @var tutorialLink
+ */
+ var $next = false;
+ /**
+ * link to the previous tutorial in a document series, or false if none
+ * @var tutorialLink
+ */
+ var $prev = false;
+ /**
+ * link to the parent tutorial in a document series, or false if none
+ *
+ * This is used to generate an "Up" or "Home" link like the php manual.
+ * The parent is defined as a tutorial that has a parenttutorialname.ext.ini
+ * file and is not contained by any other tutorial's tutorialname.ext.ini
+ * @var tutorialLink
+ */
+ var $parent = false;
+ /**
+ * links to the child tutorials, or false if none
+ * @var array
+ */
+ var $children = false;
+
+ /**
+ * @param parserXMLDocBookTag top-level tag (<refentry> for 1.2.0)
+ * @param information about the tutorial file. Format:
+ *
+ * <pre>
+ * array('tutename' => tutorial name,
+ * 'path' => relative path of tutorial to tutorials/ directory
+ * 'ini' => contents of the tutorial .ini file, if any)
+ * </pre>
+ */
+ function parserTutorial($data, $info)
+ {
+ $this->value = $data;
+ $this->package = $info['package'];
+ $this->subpackage = $info['subpackage'];
+ $this->tutorial_type = $info['tutetype'];
+ $this->name = $info['tutename'];
+ $this->path = $info['path'];
+ $this->ini = $info['ini'];
+ }
+
+ /**
+ * Retrieve the title of the tutorial, or of any subsection
+ * @param Converter
+ * @param string which subsection to retrieve the title from, if any
+ * @uses parserXMLDocBookTag::getSubSection() retrieve the subsection to
+ * to get a title from
+ */
+ function getTitle(&$c,$subsection = '')
+ {
+ if (!empty($subsection))
+ {
+ $z = $this->value->getSubSection($c,$subsection);
+ if (!$z)
+ {
+ addWarning(PDERROR_TUTORIAL_SUBSECTION_NOT_FOUND,$this->name,$subsection);
+ return $subsection;
+ }
+ return $z->getTitle($c);
+ }
+ return $this->value->getTitle($c);
+ }
+
+ /**
+ * @param Converter
+ * @param boolean determines whether character data is postprocessed to be
+ * Converter-friendly or not.
+ */
+ function Convert(&$c, $postprocess = true)
+ {
+ return $this->value->Convert($c, $postprocess);
+ }
+
+ /**
+ * @uses $parent creates a link to the documentation for the parent tutorial
+ * @param parserTutorial
+ * @param Converter
+ */
+ function setParent($parent,&$c)
+ {
+ $this->parent = new tutorialLink;
+ $this->parent->addLink('', $parent->path, $parent->name, $parent->package, $parent->subpackage, $parent->getTitle($c));
+ }
+
+ /**
+ * @param array array of parserTutorials that have child tutorials
+ */
+ function isChildOf($parents)
+ {
+ foreach($parents as $i => $parent)
+ {
+ if ($parent->path == $this->path) continue;
+ if ($parent->ini && ($parent->package == $this->package) && ($parent->subpackage == $this->subpackage) && ($parent->tutorial_type == $this->tutorial_type))
+ {
+ foreach($parent->ini['Linked Tutorials'] as $child)
+ {
+ if ($child . '.' . $this->tutorial_type == $this->name) return true;
+ }
+ }
+ }
+ }
+
+ /**
+ * Retrieve converter-specific link to the parent tutorial's documentation
+ * @param Converter
+ */
+ function getParent(&$c)
+ {
+ if (!$this->parent) return false;
+ return $c->returnSee($this->parent);
+ }
+
+ /**
+ * @uses $next creates a link to the documentation for the next tutorial
+ * @param parserTutorial
+ * @param Converter
+ */
+ function setNext($next,&$c)
+ {
+ if (phpDocumentor_get_class($next) == 'tutoriallink') return $this->next = $next;
+ $this->next = new tutorialLink;
+ $this->next->addLink('', $next->path, $next->name, $next->package, $next->subpackage, $next->getTitle($c));
+ }
+
+ /**
+ * Retrieve converter-specific link to the next tutorial's documentation
+ * @param Converter
+ */
+ function getNext(&$c)
+ {
+ if (!$this->next) return false;
+ return $c->returnSee($this->next);
+ }
+
+ /**
+ * @uses $prev creates a link to the documentation for the previous tutorial
+ * @param parserTutorial
+ * @param Converter
+ */
+ function setPrev($prev,&$c)
+ {
+ if (phpDocumentor_get_class($prev) == 'tutoriallink') return $this->prev = $prev;
+ $this->prev = new tutorialLink;
+ $this->prev->addLink('', $prev->path, $prev->name, $prev->package, $prev->subpackage, $prev->getTitle($c));
+ }
+
+ /**
+ * Retrieve converter-specific link to the previous tutorial's documentation
+ * @param Converter
+ */
+ function getPrev(&$c)
+ {
+ if (!$this->prev) return false;
+ return $c->returnSee($this->prev);
+ }
+
+ /**
+ * Get a link to this tutorial, or to any subsection of this tutorial
+ * @param Converter
+ * @param boolean if true, returns a {@link tutorialLink} instead of a string
+ * @param string section name to link to
+ * @return string|tutorialLink
+ */
+ function getLink(&$c,$pure = false,$section = '')
+ {
+ $link = new tutorialLink;
+ $link->addLink($section, $this->path, $this->name, $this->package, $this->subpackage, $this->getTitle($c), $this->category);
+ if ($pure) return $link;
+ return $c->returnSee($link);
+ }
+}
+
+?> \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/ProceduralPages.inc b/buildscripts/PhpDocumentor/phpDocumentor/ProceduralPages.inc
new file mode 100644
index 00000000..a26fbacc
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/ProceduralPages.inc
@@ -0,0 +1,782 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * Intermediate procedural page parsing structure.
+ * This structure parses defines, functions, and global variables by file,
+ * and then iterates over the elements to document conflicts.
+ * @package phpDocumentor
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.1
+ * @version $Id: ProceduralPages.inc,v 1.1 2005/10/17 18:36:57 jeichorn Exp $
+ */
+/**
+ * Intermediate procedural page parsing structure.
+ * This structure parses defines, functions, and global variables by file,
+ * and then iterates over the elements to document conflicts.
+ * @package phpDocumentor
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.1
+ * @version $Id: ProceduralPages.inc,v 1.1 2005/10/17 18:36:57 jeichorn Exp $
+ */
+class ProceduralPages
+{
+ /**
+ * file being parsed, used in every add function to match up elements with the file that contains them
+ * @see addClass(), addMethod(), addVar(), nextFile()
+ * @var string
+ */
+ var $curfile;
+ /**
+ * array of all procedural pages ordered by name
+ * Format:
+ * array(name => array(fullpath => parserPage,fullpath => parserPage2 [if there are name conflicts],...))
+ * @var array
+ */
+ var $pages = array();
+ /**
+ * array of all procedural pages ordered by name that have been ignored via -po or @access private or @ignore
+ * Format:
+ * array(name => array(fullpath => parserPage,fullpath => parserPage2 [if there are name conflicts],...))
+ * @var array
+ */
+ var $ignorepages = array();
+ /**
+ * array of all procedural page names ordered by full path to the file
+ * Format:
+ * array(fullpath => name)
+ * @var array
+ */
+ var $pathpages = array();
+ /**
+ * array of parsed includes organized by the full path of the file that contains the include.
+ * Format:
+ * array(full path => array(includename => {@link parserInclude}))
+ * @var array
+ */
+ var $includesbyfile = array();
+ /**
+ * array of parsed functions organized by the full path of the file that contains the function.
+ * Format:
+ * array(full path => array(functionname => {@link parserFunction}))
+ * @var array
+ */
+ var $functionsbyfile = array();
+ /**
+ * array of parsed defines organized by the full path of the file that contains the define.
+ * Format:
+ * array(full path => array(definename => {@link parserDefine}))
+ * @var array
+ */
+ var $definesbyfile = array();
+ /**
+ * array of parsed global variables organized by the full path of the file that contains the global variable definition.
+ * Format:
+ * array(full path => array(globalname => {@link parserGlobal}))
+ * @var array
+ */
+ var $globalsbyfile = array();
+ /**
+ * array of file names organized by functions that are in the file.
+ * This structure is designed to handle name conflicts. Two files can contain functions with the same name, and this array will
+ * record both filenames to help control namespace errors
+ * Format:
+ * array(functionname => array(full path of file containing functionname, full path of file 2 containing functionname...)
+ * @var array
+ */
+ var $functionsbynamefile = array();
+ /**
+ * array of file names organized by defines that are in the file.
+ * This structure is designed to handle name conflicts. Two files can contain defines with the same name, and this array will
+ * record both filenames to help control namespace errors
+ * Format:
+ * array(definename => array(full path of file containing definename, full path of file 2 containing definename...)
+ * @var array
+ */
+ var $definesbynamefile = array();
+ /**
+ * array of file names organized by global variables that are in the file.
+ * This structure is designed to handle name conflicts. Two files can contain global variables with the same name, and this array will
+ * record both filenames to help control namespace errors
+ * Format:
+ * array(global variablename => array(full path of file containing global variablename, full path of file 2 containing global variablename...)
+ * @var array
+ */
+ var $globalsbynamefile = array();
+ /**
+ * array of packages ordered by full path
+ * Format:
+ * array(fullpath => array(packagename,subpackagename))
+ * @var array
+ */
+ var $pagepackages = array();
+ /**
+ * array of packages assigned to classes in a file, ordered by fullpath
+ * Format:
+ * array(fullpath => array(packagename => array(subpackagename => 1,subpackagename => 1,..),packagename2 =>...)
+ * @var array
+ */
+ var $pageclasspackages = array();
+ /**
+ * Namespace conflicts within all documented packages of functions
+ * Format:
+ * array(functionname => array(full path, full path,...))
+ * @var array
+ */
+ var $functionconflicts = array();
+ /**
+ * Namespace conflicts within all documented pages
+ * Format:
+ * array(pagename => array(fullpath, fullpath,...))
+ * @var array
+ */
+ var $pageconflicts = array();
+ /**
+ * Namespace conflicts within all documented packages of functions
+ * Format:
+ * array(functionname => array(full path, full path,...))
+ * @var array
+ */
+ var $defineconflicts = array();
+ /**
+ * Namespace conflicts within all documented packages of functions
+ * Format:
+ * array(functionname => array(full path, full path,...))
+ * @var array
+ */
+ var $globalconflicts = array();
+ /** @access private
+ * @var array */
+ var $revcpbf = array();
+ /** @access private
+ * @var boolean */
+ var $packagesetup = false;
+
+ /**
+ * sets up the {@link $pages} array
+ * @param parserPage &$element
+ */
+ function addPage(&$element)
+ {
+ $this->curfile = $element->getPath();
+ $this->pages[$element->getFile()][$element->getPath()] = $element;
+ $this->pathpages[$this->curfile] = $element->getFile();
+ $this->addPagePackage($this->curfile, $element->package, $element->subpackage);
+ }
+
+ /**
+ * moves a page from the {@link $pages} array to the {@link $ignorepages} array
+ * @param parserPage &$element
+ */
+ function ignorePage(&$element)
+ {
+ $this->ignorepages[$element->getFile()][$element->getPath()] = $this->pages[$element->getFile()][$element->getPath()];
+ unset($this->pages[$element->getFile()][$element->getPath()]);
+ }
+
+ function getPathInfo($path,&$c)
+ {
+ $path = str_replace('/',SMART_PATH_DELIMITER,$path);
+ $info = array();
+ if (!isset($this->pathpages[$path])) return false;
+ $p = $this->pages[$this->pathpages[$path]][$path];
+ $p->name = $c->getPageName($p);
+ $info['package'] = $p->package;
+ $info['subpackage'] = $p->subpackage;
+ $info['name'] = $p->getFile();
+ $info['source_loc'] = $p->getSourceLocation($c);
+ $x = new pageLink;
+ $x->addLink($p->path,$p->name,$p->file,$p->package, $p->subpackage);
+ $info['docs'] = $c->returnSee($x);
+ return $info;
+ }
+
+ /**
+ * Change a page's name from its file to alias $name
+ *
+ * This function is used to handle a @name tag in a page-level DocBlock
+ * @param string $name
+ */
+ function setName($name)
+ {
+ $this->pages[$name][$this->curfile] = $this->pages[$this->pathpages[$this->curfile]][$this->curfile];
+ $this->pages[$name][$this->curfile]->file = $name;
+ unset($this->pages[$this->pathpages[$this->curfile]][$this->curfile]);
+ $this->pathpages[$this->curfile] = $name;
+ }
+
+ /**
+ * Changes the package of the page represented by $path
+ *
+ * changes package in both the {@link $pages} array and the {@link pagepackages} array
+ * @param string $path full path
+ * @param string $package
+ * @param string $subpackage
+ */
+ function addPagePackage($path,$package,$subpackage)
+ {
+ $this->pages[$this->pathpages[$path]][$path]->package = $package;
+ $this->pages[$this->pathpages[$path]][$path]->subpackage = $subpackage;
+ $this->pagepackages[$path] = array($package, $subpackage);
+ if (isset($this->includesbyfile[$path]))
+ {
+ foreach($this->includesbyfile[$path] as $i => $el)
+ {
+ $el->package = $package;
+ $el->subpackage = $subpackage;
+ $this->includesbyfile[$path][$i] = $el;
+ }
+ }
+ if (isset($this->functionsbyfile[$path]))
+ {
+ foreach($this->functionsbyfile[$path] as $i => $el)
+ {
+ $el->package = $package;
+ $el->subpackage = $subpackage;
+ $this->functionsbyfile[$path][$i] = $el;
+ }
+ }
+ if (isset($this->definesbyfile[$path]))
+ {
+ foreach($this->definesbyfile[$path] as $i => $el)
+ {
+ $el->package = $package;
+ $el->subpackage = $subpackage;
+ $this->definesbyfile[$path][$i] = $el;
+ }
+ }
+ if (isset($this->globalsbyfile[$path]))
+ {
+ foreach($this->globalsbyfile[$path] as $i => $el)
+ {
+ $el->package = $package;
+ $el->subpackage = $subpackage;
+ $this->globalsbyfile[$path][$i] = $el;
+ }
+ }
+ }
+
+ /**
+ * sets up the {@link $includesbyfile} array using {@link $curfile}
+ * @param parserInclude &$element
+ */
+ function addInclude(&$element)
+ {
+ $this->includesbyfile[$this->curfile][] = $element;
+ }
+
+ /**
+ * sets up the {@link $functionsbyfile} array using {@link $curfile}
+ * @param parserFunction &$element
+ */
+ function addFunction(&$element)
+ {
+ if (isset($this->functionsbyfile[$this->curfile]))
+ {
+ foreach($this->functionsbyfile[$this->curfile] as $i => $function)
+ {
+ if ($function->getName() == $element->getName())
+ {
+ addWarning(PDERROR_ELEMENT_IGNORED,'function',$element->getName(),$this->curfile);
+ return;
+ }
+ }
+ }
+ $this->functionsbyfile[$this->curfile][] = $element;
+ $this->functionsbynamefile[$element->getName()][] = $this->curfile;
+ }
+
+ /**
+ * sets up the {@link $globalsbyfile} array using {@link $curfile}
+ * @param parserGlobal &$element
+ */
+ function addGlobal(&$element)
+ {
+ if (isset($this->globalsbyfile[$this->curfile]))
+ {
+ foreach($this->globalsbyfile[$this->curfile] as $i => $global)
+ {
+ if ($global->getName() == $element->getName())
+ {
+ addWarning(PDERROR_ELEMENT_IGNORED,'global variable',$element->getName(),$this->curfile);
+ return;
+ }
+ }
+ }
+ $this->globalsbyfile[$this->curfile][] = $element;
+ $this->globalsbynamefile[$element->getName()][] = $this->curfile;
+ }
+
+ /**
+ * sets up the {@link $definesbyfile} array using {@link $curfile}
+ * @param parserDefine &$element
+ */
+ function addDefine(&$element)
+ {
+ if (isset($this->definesbyfile[$this->curfile]))
+ {
+ foreach($this->definesbyfile[$this->curfile] as $i => $define)
+ {
+ if ($define->getName() == $element->getName())
+ {
+ addWarning(PDERROR_ELEMENT_IGNORED,'define',$element->getName(),$this->curfile);
+ return;
+ }
+ }
+ }
+ $this->definesbyfile[$this->curfile][] = $element;
+ $this->definesbynamefile[$element->getName()][] = $this->curfile;
+ }
+
+ /**
+ * Used to align an element with the package of its parent page prior to Conversion.
+ * @param parserElement &$element
+ */
+ function replaceElement(&$element)
+ {
+ if ($element->type == 'define')
+ {
+ foreach($this->definesbyfile[$element->getPath()] as $i => $el)
+ {
+ if ($el->getName() == $element->getName())
+ {
+ $this->definesbyfile[$element->getPath()][$i] = &$element;
+ }
+ }
+ } elseif ($element->type == 'global')
+ {
+ foreach($this->globalsbyfile[$element->getPath()] as $i => $el)
+ {
+ if ($el->getName() == $element->getName())
+ {
+ $this->globalsbyfile[$element->getPath()][$i] = &$element;
+ }
+ }
+ } elseif ($element->type == 'include')
+ {
+ foreach($this->includesbyfile[$element->getPath()] as $i => $el)
+ {
+ if ($el->getName() == $element->getName())
+ {
+ $this->includesbyfile[$element->getPath()][$i] = &$element;
+ }
+ }
+ } elseif ($element->type == 'function')
+ {
+ foreach($this->functionsbyfile[$element->getPath()] as $i => $el)
+ {
+ if ($el->getName() == $element->getName())
+ {
+ $this->functionsbyfile[$element->getPath()][$i] = &$element;
+ }
+ }
+ }
+ }
+
+ /**
+ * adds a package from a class to the current file
+ * @param string $file full path to the file that contains the class
+ * @param string $package package name
+ */
+ function addClassPackageToFile($file,$package,$subpackage)
+ {
+ // don't care about default
+// if ($package == $GLOBALS['phpDocumentor_DefaultPackageName'])
+// $this->revcpbf[$file][$package][$subpackage] = 1;
+ if (!isset($this->revcpbf[$file][$package][$subpackage]))
+ {
+ $this->pageclasspackages[$file][$package][$subpackage] = 1;
+ }
+ $this->revcpbf[$file][$package][$subpackage] = 1;
+ }
+
+ /**
+ * if there is one class package in a file, the parent path inherits the package if its package is default.
+ * helps with -po to avoid dumb bugs
+ */
+ function setupPagePackages()
+ {
+ if ($this->packagesetup) return;
+ foreach($this->pageclasspackages as $fullpath => $packages)
+ {
+ if (isset($this->pagepackages[$fullpath]))
+ {
+ if ($this->pagepackages[$fullpath][0] == $GLOBALS['phpDocumentor_DefaultPackageName'])
+ {
+ if (count($packages) == 1)
+ {
+ list($package,$subpackage) = each($packages);
+ if (count($subpackage) == 1) list($subpackage,) = each($subpackage);
+ else $subpackage = '';
+ $this->addPagePackage($fullpath,$package,$subpackage);
+ }
+ }
+ }
+ }
+ $this->packagesetup = true;
+ }
+
+ /**
+ * extracts function, define, and global variable name conflicts within the same package and between different
+ * packages. No two elements with the same name are allowed in the same package, to keep automatic linking
+ * possible.
+ * @access private
+ */
+ function setupConflicts(&$render)
+ {
+
+ foreach($this->functionsbynamefile as $function => $paths)
+ {
+ if (count($paths) - 1)
+ { //conflict
+ $package = array();
+ foreach($paths as $path)
+ {
+ // create a list of conflicting functions in each package
+ $package[$this->pagepackages[$path][0]][] = $path;
+ }
+ foreach($package as $pathpackages)
+ {
+ // if at least 2 functions exist in the same package, delete all but the first one and add warnings
+ if (count($pathpackages) - 1)
+ {
+ for($i=1; $i < count($pathpackages); $i++)
+ {
+ addWarning(PDERROR_ELEMENT_IGNORED,'function',$function,$pathpackages[$i]);
+ foreach($this->functionsbyfile[$pathpackages[$i]] as $j => $blah)
+ {
+ if ($this->functionsbyfile[$pathpackages[$i]][$j]->getName() == $function)
+ unset($this->functionsbyfile[$pathpackages[$i]][$j]);
+ }
+ $oth = array_flip($paths);
+ unset($paths[$oth[$pathpackages[$i]]]);
+ }
+ }
+ }
+ $this->functionconflicts[$function] = $paths;
+ }
+ }
+
+ foreach($this->definesbynamefile as $define => $paths)
+ {
+ if (count($paths) - 1)
+ { //conflict
+ $package = array();
+ foreach($paths as $path)
+ {
+ // create a list of conflicting functions in each package
+ $package[$this->pagepackages[$path][0]][] = $path;
+ }
+ foreach($package as $pathpackages)
+ {
+ // if at least 2 functions exist in the same package, delete all but the first one and add warnings
+ if (count($pathpackages) - 1)
+ {
+ for($i=1; $i < count($pathpackages); $i++)
+ {
+ addWarning(PDERROR_ELEMENT_IGNORED,'define',$define,$pathpackages[$i]);
+ foreach($this->definesbyfile[$pathpackages[$i]] as $j => $blah)
+ {
+ if ($this->definesbyfile[$pathpackages[$i]][$j]->getName() == $define)
+ unset($this->definesbyfile[$pathpackages[$i]][$j]);
+ }
+ $oth = array_flip($paths);
+ unset($paths[$oth[$pathpackages[$i]]]);
+ }
+ }
+ }
+ $this->defineconflicts[$define] = $paths;
+ }
+ }
+
+ foreach($this->globalsbynamefile as $global => $paths)
+ {
+ if (count($paths) - 1)
+ { //conflict
+ $package = array();
+ foreach($paths as $path)
+ {
+ // create a list of conflicting functions in each package
+ $package[$this->pagepackages[$path][0]][] = $path;
+ }
+ foreach($package as $pathpackages)
+ {
+ // if at least 2 functions exist in the same package, delete all but the first one and add warnings
+ if (count($pathpackages) - 1)
+ {
+ for($i=1; $i < count($pathpackages); $i++)
+ {
+ addWarning(PDERROR_ELEMENT_IGNORED,'global variable',$global,$pathpackages[$i]);
+ foreach($this->globalsbyfile[$pathpackages[$i]] as $j => $blah)
+ {
+ if ($this->globalsbyfile[$pathpackages[$i]][$j]->getName() == $global)
+ unset($this->globalsbyfile[$pathpackages[$i]][$j]);
+ }
+ $oth = array_flip($paths);
+ unset($paths[$oth[$pathpackages[$i]]]);
+ }
+ }
+ }
+ $this->globalconflicts[$global] = $paths;
+ }
+ }
+
+ foreach($this->pages as $name => $pages)
+ {
+ if (count($pages) - 1)
+ { // possible conflict
+
+ }
+ }
+ }
+
+ /**
+ * called by {@link parserFunction::getConflicts()} to get inter-package conflicts, should not be called directly
+ * @access private
+ * @return array Format: (package => {@link parserFunction} of conflicting function)
+ */
+ function getFuncConflicts($name)
+ {
+ if (!isset($this->functionconflicts[$name])) return false;
+ $a = array();
+ foreach($this->functionconflicts[$name] as $conflict)
+ {
+ foreach($this->functionsbyfile[$conflict] as $i => $func)
+ {
+ if ($func->getName() == $name)
+ $a[$this->functionsbyfile[$conflict][$i]->docblock->package] = $this->functionsbyfile[$conflict][$i];
+ }
+ }
+ return $a;
+ }
+
+ /**
+ * called by {@link parserGlobal::getConflicts()} to get inter-package conflicts, should not be called directly
+ * @access private
+ * @return array Format: (package => {@link parserGlobal} of conflicting global variable)
+ */
+ function getGlobalConflicts($name)
+ {
+ if (!isset($this->globalconflicts[$name])) return false;
+ $a = array();
+ foreach($this->globalconflicts[$name] as $conflict)
+ {
+ foreach($this->globalsbyfile[$conflict] as $i => $func)
+ {
+ if ($func->getName() == $name)
+ $a[$this->globalsbyfile[$conflict][$i]->docblock->package] = $this->globalsbyfile[$conflict][$i];
+ }
+ }
+ return $a;
+ }
+
+ /**
+ * called by {@link parserDefine::getConflicts()} to get inter-package conflicts, should not be called directly
+ * @access private
+ * @return array Format: (package => {@link parserDefine} of conflicting define)
+ */
+ function getDefineConflicts($name)
+ {
+ if (!isset($this->defineconflicts[$name])) return false;
+ $a = array();
+ foreach($this->defineconflicts[$name] as $conflict)
+ {
+ foreach($this->definesbyfile[$conflict] as $i => $func)
+ {
+ if ($func->getName() == $name)
+ $a[$this->definesbyfile[$conflict][$i]->docblock->package] = $this->definesbyfile[$conflict][$i];
+ }
+ }
+ return $a;
+ }
+
+ /**
+ * Adjusts packages of all pages and removes name conflicts within a package
+ *
+ * Automatic linking requires that each linkable name have exactly one element associated with it. In other words, there
+ * cannot be two functions named foo() in the same package. This also adheres to php rules with one exception:
+ *
+ * <code>
+ * if ($test == 3)
+ * {
+ * define('whatever','this thing');
+ * } else
+ * {
+ * define('whatever','this other thing');
+ * }
+ * </code>
+ *
+ * phpDocumentor is not aware of conditional control structures because it would slow things down considerably.
+ * So, what phpDocumentor does is automatically ignore the second define and raise a warning. The warning can
+ * be eliminated with an @ignore tag on the second element like so:
+ *
+ * <code>
+ * if ($test == 3)
+ * {
+ * define('whatever','this thing');
+ * } else
+ * {
+ * /** @ignore {@*}
+ * define('whatever','this other thing');
+ * }
+ * </code>
+ *
+ * if there are two files that contain the same procedural elements in the same package (for example,
+ * a common configuration file common.php), they will also be ignored as if they were in the same file. The
+ * reasoning behind this is simple. A package is an indivisible set of files and classes that a user will
+ * include in their code. Name conflicts must be avoided to allow successful execution.
+ *
+ * This function also plays the all-important role of calling {@link phpDocumentor_IntermediateParser::addElementToPage()} in
+ * order to add processed elements to their pages for Conversion.
+ * @param phpDocumentor_IntermediateParser &$render
+ */
+ function setupPages(&$render)
+ {
+ global $_phpDocumentor_setting;
+ phpDocumentor_out("\nProcessing Procedural Page Element Name Conflicts\n\n");
+ flush();
+ $this->setupPagePackages();
+ $this->setupConflicts($render);
+// phpDocumentor_out("\nProcessing Procedural Pages\n\n");
+ foreach($this->pathpages as $path => $name)
+ {
+// phpDocumentor_out("Processing $path\n");
+ $a = $this->pagepackages[$path];
+ $b = &$this->pages[$name][$path];
+ $render->addPage($b, $path);
+ $render->addUses($b, $path);
+ if (isset($this->includesbyfile[$path]))
+ foreach($this->includesbyfile[$path] as $include)
+ {
+ $include->docblock->package = $a[0];
+ $include->docblock->subpackage = $a[1];
+ $render->addElementToPage($include,$path);
+ }
+
+ if (isset($this->functionsbyfile[$path]))
+ foreach($this->functionsbyfile[$path] as $function)
+ {
+ $function->docblock->package = $a[0];
+ $function->docblock->subpackage = $a[1];
+ $render->addElementToPage($function,$path);
+ $render->addUses($function,$path);
+ }
+
+ if (isset($this->definesbyfile[$path]))
+ foreach($this->definesbyfile[$path] as $define)
+ {
+ $define->docblock->package = $a[0];
+ $define->docblock->subpackage = $a[1];
+ $render->addElementToPage($define,$path);
+ $render->addUses($define,$path);
+ }
+
+ if (isset($this->globalsbyfile[$path]))
+ foreach($this->globalsbyfile[$path] as $global)
+ {
+ $global->docblock->package = $a[0];
+ $global->docblock->subpackage = $a[1];
+ $render->addElementToPage($global,$path);
+ $render->addUses($global,$path);
+ }
+ }
+ }
+
+ function setParseBase($pbase)
+ {
+ $this->_parsedbase = $pbase;
+ }
+
+ /**
+ * @return false|parserPage returns matched parserPage if found
+ */
+ function pathMatchesParsedFile($path, $infile)
+ {
+ $test = $this->getRealPath($path, $infile);
+ if (is_string($test))
+ {
+ if (isset($this->pathpages[$test]))
+ return $this->pages[$this->pathpages[$test]][$test];
+ if (PHPDOCUMENTOR_WINDOWS) $test = str_replace('/','\\',$test);
+ if (isset($this->pathpages[$test]))
+ {
+ $a = $this->pages[$this->pathpages[$test]][$test];
+ if (is_array($a->packageOutput) && !in_array($a->package, $a->packageOutput))
+ return false;
+ return $this->pages[$this->pathpages[$test]][$test];
+ }
+ } else
+ {
+ foreach($test as $file)
+ {
+ if (isset($this->pathpages[$file]))
+ return $this->pages[$this->pathpages[$file]][$file];
+ if (PHPDOCUMENTOR_WINDOWS) $file = str_replace('/','\\',$file);
+ if (isset($this->pathpages[$file]))
+ {
+ $a = $this->pages[$this->pathpages[$file]][$file];
+ if (is_array($a->packageOutput) && !in_array($a->package, $a->packageOutput))
+ return false;
+ return $this->pages[$this->pathpages[$file]][$file];
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @param string include() statement path to check
+ * @param string full path of file the statement is in
+ * @param string full path to base directory of parsing, used for .
+ * @return array|string returns an array of possible file locations or
+ * a string if there is an exact match
+ */
+ function getRealPath($path, $file)
+ {
+ $curdir = str_replace('\\','/',dirname($file));
+ $path = str_replace('\\','/',$path);
+ if (strpos($path,':') !== false)
+ { // windows, and we have a drive letter
+ return $path;
+ } elseif(strpos($path,'/') === 0)
+ {
+ return $path;
+ }
+ // not an absolute path
+ $path = explode('/',$path);
+ if ($path[0] == '.')
+ {
+ $path[0] = dirname($file);
+ return join($path,'/');
+ } elseif ($path[0] == '..')
+ {
+ $dirfile = explode('/',dirname(str_replace('\\','/',$file)));
+ array_pop($dirfile); // remove the current directory
+ if (!count($dirfile)) return false; // we were at a top-level dir!
+ $path[0] = join($dirfile,'/'); // replace .. with parent dirname
+ return join($path,'/');
+ } else
+ {
+ $path = join($path,'/');
+ return array($curdir . PATH_DELIMITER . $path,
+ str_replace('\\','/',PHPDOCUMENTOR_BASE) . PATH_DELIMITER . $path);
+ }
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Publisher.inc b/buildscripts/PhpDocumentor/phpDocumentor/Publisher.inc
new file mode 100644
index 00000000..7e038021
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Publisher.inc
@@ -0,0 +1,84 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Publisher Copyright 2000-2003 Kellin |
+// | Email passionplay@hotmail.com |
+// | phpDocumentor Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * a class for handling the publishing of data
+ *
+ * @author Kellin <passionplay@hotmail.com>
+ * @author Joshua Eichorn <jeichorn@phpdoc.org>
+ * @version $Id: Publisher.inc,v 1.1 2005/10/17 18:36:57 jeichorn Exp $
+ * @package phpDocumentor
+ */
+/**
+ * a class for handling the publishing of data
+ *
+ * @author Kellin <passionplay@hotmail.com>
+ * @author Joshua Eichorn <jeichorn@phpdoc.org>
+ * @version $Id: Publisher.inc,v 1.1 2005/10/17 18:36:57 jeichorn Exp $
+ * @package phpDocumentor
+ */
+class Publisher
+{
+ /**#@+
+ * @var array
+ */
+ /**
+ * Array of references objects that have Subscribed to this publisher
+ */
+ var $subscriber = array();
+
+ var $tokens = array();
+
+ var $pushEvent = array();
+ var $popEvent = array();
+ /**#@-*/
+
+
+ /**
+ * Adds a subscriber to the {@link $subscriber} array().
+ * if $event is '*', the publisher will use $object as the default event handler
+ * @param integer $event see {@link Parser.inc} PARSER_EVENT_* constants
+ * @param class $object any class that has a HandleEvent() method like {@link phpDocumentor_IntermediateParser::HandleEvent()} or {@link Classes::HandleEvent()}
+ */
+ function subscribe($event, &$object)
+ {
+ $this->subscriber[$event] =& $object;
+ }
+
+ /**
+ * @param integer $event see {@link Parser.inc} PARSER_EVENT_* constants
+ * @param mixed $data anything the subscribed event handler is expecting
+ */
+ function publishEvent($event,$data)
+ {
+
+ // see if there is a specific event handler
+ if (!empty($this->subscriber[$event]))
+ {
+ $this->subscriber[$event]->HandleEvent($event,$data);
+ }
+ else if (isset($this->subscriber['*']) && is_object($this->subscriber['*'])) // check to see if a generic handler exists
+ {
+ $this->subscriber['*']->HandleEvent($event,$data);
+ }
+ }
+}
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Setup.inc.php b/buildscripts/PhpDocumentor/phpDocumentor/Setup.inc.php
new file mode 100644
index 00000000..1d953088
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Setup.inc.php
@@ -0,0 +1,785 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * This was all in phpdoc.inc, and now encapsulates the complexity
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @version $Revision: 1.6 $
+ * @package phpDocumentor
+ * @since 1.2
+ */
+error_reporting(E_ALL);
+/** common settings */
+include_once("phpDocumentor/common.inc.php");
+
+include_once("phpDocumentor/Io.inc");
+include_once("phpDocumentor/Publisher.inc");
+include_once("phpDocumentor/Classes.inc");
+include_once("phpDocumentor/ProceduralPages.inc");
+include_once("phpDocumentor/IntermediateParser.inc");
+include_once("phpDocumentor/WordParser.inc");
+include_once("phpDocumentor/EventStack.inc");
+include_once("phpDocumentor/ParserData.inc");
+include_once("phpDocumentor/InlineTags.inc");
+include_once("phpDocumentor/DocBlockTags.inc");
+include_once("phpDocumentor/DescHTML.inc");
+include_once("phpDocumentor/ParserDocBlock.inc");
+include_once("phpDocumentor/ParserElements.inc");
+include_once("phpDocumentor/Parser.inc");
+include_once("phpDocumentor/phpDocumentorTWordParser.inc");
+include_once("phpDocumentor/phpDocumentorTParser.inc");
+include_once("phpDocumentor/HighlightParser.inc");
+include_once("phpDocumentor/TutorialHighlightParser.inc");
+include_once("phpDocumentor/ParserDescCleanup.inc");
+include_once("phpDocumentor/PackagePageElements.inc");
+include_once("phpDocumentor/XMLpackagePageParser.inc");
+include_once("phpDocumentor/LinkClasses.inc");
+include_once("phpDocumentor/Converter.inc");
+include_once("phpDocumentor/Errors.inc");
+if (isset($_GET))
+{
+/**
+ * $interface is either 'web' or is not set at all
+ * @global array $interface
+ */
+ if (isset($_GET['interface'])) $interface = $_GET['interface'];
+/**
+ * $_phpDocumentor_setting is either the value from the web interface, or is set up by {@link Io::parseArgv()}
+ * @global array $_phpDocumentor_setting
+ */
+ if (isset($_GET['setting'])) $_phpDocumentor_setting = $_GET['setting'];
+}
+
+/**
+ * default package name, set using -dn --defaultpackagename
+ * @global string $GLOBALS['phpDocumentor_DefaultPackageName']
+ * @name $phpDocumentor_DefaultPackageName
+ */
+$GLOBALS['phpDocumentor_DefaultPackageName'] = 'default';
+
+/**
+ * default package name, set using -dn --defaultcategoryname
+ * @global string $GLOBALS['phpDocumentor_DefaultCategoryName']
+ * @name $phpDocumentor_DefaultCategoryName
+ */
+$GLOBALS['phpDocumentor_DefaultCategoryName'] = 'default';
+
+/**
+ * @package phpDocumentor
+ */
+class phpDocumentor_setup
+{
+ /**
+ * The main parser
+ * @var Parser|phpDocumentorTParser
+ */
+ var $parse;
+ /**
+ * Used to parse command-line options
+ * @var Io
+ */
+ var $setup;
+ /**
+ * Used to organize output from the Parser before Conversion
+ * @var phpDocumentor_IntermediateParser
+ */
+ var $render = false;
+ /**
+ * Packages to create documentation for
+ * @var string
+ */
+ var $packages = false;
+ /**
+ * contents of --filename commandline
+ * @tutorial phpDocumentor.howto.pkg#using.command-line.filename
+ * @var string
+ */
+ var $files = '';
+ /**
+ * contents of --directory commandline
+ * @tutorial phpDocumentor.howto.pkg#using.command-line.directory
+ * @var string
+ */
+ var $dirs = '';
+ /**
+ * contents of --hidden commandline
+ * @tutorial phpDocumentor.howto.pkg#using.command-line.hidden
+ * @var boolean
+ */
+ var $hidden = false;
+ /**
+ * time that parsing was started, used for informative timing of output
+ * @access private
+ */
+ var $parse_start_time;
+ /**
+ * contents of --ignore commandline
+ * @tutorial phpDocumentor.howto.pkg#using.command-line.ignore
+ * @var string
+ */
+ var $ignore_files = array();
+ /**
+ * Checks PHP version, makes sure it is 4.2.0+, and chooses the
+ * phpDocumentorTParser if version is 4.3.0+
+ * @uses parseIni()
+ */
+ function phpDocumentor_setup()
+ {
+ global $_phpDocumentor_cvsphpfile_exts;
+ if (!function_exists('is_a'))
+ {
+ print "phpDocumentor requires PHP version 4.2.0 or greater to function";
+ exit;
+ }
+
+ // set runtime to a large value since this can take quite a while
+ // we can only set_time_limit when not in safe_mode bug #912064
+ if (!ini_get('safe_mode'))
+ {
+ set_time_limit(0); // unlimited runtime
+ } else
+ {
+ phpDocumentor_out("time_limit cannot be set since your in safe_mode, please edit time_limit in your php.ini to allow enough time for phpDocumentor to run");
+ }
+ ini_set("memory_limit","256M");
+
+ $phpver = phpversion();
+ $phpdocver = PHPDOCUMENTOR_VER;
+ if (isset($_GET['interface'])) {
+ $phpver = "<b>$phpver</b>";
+ $phpdocver = "<b>$phpdocver</b>";
+ }
+ phpDocumentor_out("PHP Version $phpver\n");
+ phpDocumentor_out("phpDocumentor version $phpdocver\n\n");
+
+ $this->parseIni();
+ // create new classes
+ $this->setup = new Io;
+ if (tokenizer_ext)
+ {
+ phpDocumentor_out("using tokenizer Parser\n");
+ $this->parse = new phpDocumentorTParser;
+ } else
+ {
+ phpDocumentor_out("using default (slower) Parser - get PHP 4.3.0+
+and load the tokenizer extension for faster parsing (your version is ".phpversion()."\n");
+ $this->parse = new Parser;
+ }
+ }
+
+ /**
+ * Get phpDocumentor settings from a user configuration file
+ * @param string user configuration file
+ */
+ function readConfigFile($file)
+ {
+ global $_phpDocumentor_setting, $_phpDocumentor_options;
+ // security
+ $file = str_replace(array('..','.ini','\\'),array('','','/'),$file);
+ if (is_file($file . '.ini'))
+ {
+ $_phpDocumentor_setting = phpDocumentor_parse_ini_file($file.'.ini');
+ } else
+ {
+ if ('@DATA-DIR@' != '@'.'DATA-DIR@')
+ {
+ $configdir = str_replace('\\','/', '@DATA-DIR@/PhpDocumentor') . PATH_DELIMITER . 'user' . PATH_DELIMITER;
+ } else {
+ $configdir = str_replace('\\','/',$GLOBALS['_phpDocumentor_install_dir']) . PATH_DELIMITER . 'user' . PATH_DELIMITER;
+ }
+ if (isset($_phpDocumentor_options['userdir'])) $configdir = $_phpDocumentor_options['userdir'];
+ if (substr($configdir,-1) != '/')
+ {
+ $configdir .= '/';
+ }
+ $_phpDocumentor_setting = phpDocumentor_parse_ini_file( $configdir . $file . '.ini');
+ if (empty($_phpDocumentor_setting['defaultpackagename']))
+ {
+ $_phpDocumentor_setting['defaultpackagename'] = 'default';
+ }
+ }
+ // don't want a loop condition!
+ unset($_phpDocumentor_setting['useconfig']);
+ $this->readCommandLineSettings();
+ }
+
+ /**
+ * Get phpDocumentor settings from command-line or web interface
+ */
+ function readCommandLineSettings()
+ {
+ global $_phpDocumentor_setting,$interface,$_phpDocumentor_RIC_files;
+ // subscribe $render class to $parse class events
+ if (!isset($interface) && !isset($_GET['interface']) && !isset($_phpDocumentor_setting))
+ {
+ // Parse the argv settings
+ $_phpDocumentor_setting = $this->setup->parseArgv();
+ }
+ if (isset($_phpDocumentor_setting['useconfig']) && !empty($_phpDocumentor_setting['useconfig'])) return $this->readConfigFile($_phpDocumentor_setting['useconfig']);
+ if (!isset($_phpDocumentor_setting['junk'])) $_phpDocumentor_setting['junk'] = '';
+ if (!isset($_phpDocumentor_setting['title'])) $_phpDocumentor_setting['title'] = 'Generated Documentation';
+ $temp_title = $_phpDocumentor_setting['title'];
+ $this->render = new phpDocumentor_IntermediateParser($temp_title);
+ if (isset($_phpDocumentor_setting['help']) || $_phpDocumentor_setting['junk'] == "-h" || $_phpDocumentor_setting['junk'] == "--help")
+ {
+ echo $this->setup->displayHelpMsg();
+ die();
+ }
+
+ if (isset($_phpDocumentor_setting['hidden'])) $this->hidden = true;
+
+ // set to parse elements marked private with @access private
+ if (isset($_phpDocumentor_setting['parseprivate']) && $_phpDocumentor_setting['parseprivate'] == 'on')
+ {
+ $this->render->setParsePrivate(true);
+ }
+
+ if (isset($_phpDocumentor_setting['ignoretags']))
+ {
+ $ignoretags = explode(',', $_phpDocumentor_setting['ignoretags']);
+ $ignoretags = array_map('trim', $ignoretags);
+ $tags = array();
+ foreach($ignoretags as $tag)
+ {
+ if (!in_array($tag,array('@global', '@access', '@package', '@ignore', '@name', '@param', '@return', '@staticvar', '@var')))
+ $tags[] = $tag;
+ }
+ $_phpDocumentor_setting['ignoretags'] = $tags;
+ }
+
+ if (isset($_phpDocumentor_setting['readmeinstallchangelog']))
+ {
+ $_phpDocumentor_setting['readmeinstallchangelog'] = explode(',',str_replace(' ','',$_phpDocumentor_setting['readmeinstallchangelog']));
+ $rics = array();
+ foreach($_phpDocumentor_setting['readmeinstallchangelog'] as $ric)
+ {
+ $rics[] = strtoupper(trim($ric));
+ }
+ $_phpDocumentor_RIC_files = $rics;
+ }
+
+ if (isset($_phpDocumentor_setting['javadocdesc']) && $_phpDocumentor_setting['javadocdesc'] == 'on')
+ {
+ $this->parse->eventHandlers[PARSER_EVENT_DOCBLOCK] = 'JavaDochandleDocblock';
+ }
+ if (tokenizer_ext)
+ {
+ if (isset($_phpDocumentor_setting['sourcecode']) && $_phpDocumentor_setting['sourcecode'] == 'on')
+ {
+ $_phpDocumentor_setting['sourcecode'] = true;
+ } else
+ {
+ $_phpDocumentor_setting['sourcecode'] = false;
+ }
+ } else
+ {
+ if (isset($_phpDocumentor_setting['sourcecode']) && $_phpDocumentor_setting['sourcecode'] == 'on')
+ {
+ addWarning(PDERROR_SOURCECODE_IGNORED);
+ }
+ $_phpDocumentor_setting['sourcecode'] = false;
+ }
+ if (isset($_phpDocumentor_setting['converterparams']))
+ {
+ $_phpDocumentor_setting['converterparams'] = explode($_phpDocumentor_setting['converterparams']);
+ foreach($_phpDocumentor_setting['converterparams'] as $i => $p)
+ {
+ $_phpDocumentor_setting['converterparams'][$i] = trim($p);
+ }
+ }
+ if (isset($_phpDocumentor_setting['customtags']) && !empty($_phpDocumentor_setting['customtags']))
+ {
+ $c = explode(',',$_phpDocumentor_setting['customtags']);
+ for($i=0;$i<count($c); $i++)
+ {
+ $GLOBALS['_phpDocumentor_tags_allowed'][] = trim($c[$i]);
+ }
+ }
+ if (isset($_phpDocumentor_setting['pear']))
+ {
+ if ($_phpDocumentor_setting['pear'] === 'off') $_phpDocumentor_setting['pear'] = false;
+ if ($_phpDocumentor_setting['pear'] === 'on') $_phpDocumentor_setting['pear'] = true;
+ }
+ if (!isset($_phpDocumentor_setting['pear'])) $_phpDocumentor_setting['pear'] = false;
+ // set to change the default package name from "default" to whatever you want
+ if (isset($_phpDocumentor_setting['defaultpackagename']))
+ {
+ $GLOBALS['phpDocumentor_DefaultPackageName'] = trim($_phpDocumentor_setting['defaultpackagename']);
+ }
+ // set to change the default category name from "default" to whatever you want
+ if (isset($_phpDocumentor_setting['defaultcategoryname']))
+ {
+ $GLOBALS['phpDocumentor_DefaultCategoryName'] = trim($_phpDocumentor_setting['defaultcategoryname']);
+ }
+
+ // set the mode (quiet or verbose)
+ if ( isset($_phpDocumentor_setting['quiet']) || strcasecmp($_phpDocumentor_setting['junk'], "-q") == 0 || strcasecmp($_phpDocumentor_setting['junk'], "--quiet") == 0)
+ {
+ if (isset($_phpDocumentor_setting['quiet']) && $_phpDocumentor_setting['quiet'] != 'on');
+ else
+ $this->render->setQuietMode(true);
+ }
+
+ // Setup the different classes
+ if (isset($_phpDocumentor_setting['templatebase']))
+ {
+ $this->render->setTemplateBase($_phpDocumentor_setting['templatebase']);
+ }
+ if (isset($_phpDocumentor_setting['target']) && !empty($_phpDocumentor_setting['target']))
+ {
+ $this->render->setTargetDir($_phpDocumentor_setting['target']);
+ }
+ else
+ {
+ echo "a target directory must be specified\n try phpdoc -h\n";
+ die();
+ }
+ if (!empty($_phpDocumentor_setting['packageoutput']))
+ {
+ $this->packages = explode(",",$_phpDocumentor_setting['packageoutput']);
+ foreach($this->packages as $p => $v)
+ {
+ $this->packages[$p] = trim($v);
+ }
+ }
+ if (!empty($_phpDocumentor_setting['filename']))
+ $this->files = $_phpDocumentor_setting['filename'];
+ if (!empty($_phpDocumentor_setting['directory']))
+ $this->dirs = $_phpDocumentor_setting['directory'];
+ }
+
+ function checkIgnoreTag($tagname, $inline = false)
+ {
+ global $_phpDocumentor_setting;
+ $tagname = '@'.$tagname;
+ if (!isset($_phpDocumentor_setting['ignoretags'])) return false;
+ if ($inline) $tagname = '{'.$tagname.'}';
+ return in_array($tagname, $_phpDocumentor_setting['ignoretags']);
+ }
+
+ function setJavadocDesc()
+ {
+ $this->parse->eventHandlers[PARSER_EVENT_DOCBLOCK] = 'JavaDochandleDocblock';
+ }
+
+ function setParsePrivate()
+ {
+ $this->render->setParserPrivate(true);
+ }
+
+ function setQuietMode()
+ {
+ $this->render->setQuietMode(true);
+ }
+
+ function setTargetDir($target)
+ {
+ $this->render->setTargetDir($target);
+ }
+
+ function setTemplateBase($dir)
+ {
+ $this->render->setTemplateBase($dir);
+ }
+
+ function setPackageOutput($po)
+ {
+ $this->packages = explode(",",$po);
+ }
+
+ function setTitle($ti)
+ {
+ $this->render = new phpDocumentor_IntermediateParser($ti);
+ }
+
+ function setFilesToParse($files)
+ {
+ $this->files = $files;
+ }
+
+ function setDirectoriesToParse($dirs)
+ {
+ $this->dirs = $dirs;
+ }
+
+ function parseHiddenFiles()
+ {
+ $this->hidden = true;
+ }
+
+ function setIgnore($ig)
+ {
+ if (strstr($ig,","))
+ {
+ $this->ignore_files = explode(",",$ig);
+ } else {
+ if (!empty($ig))
+ $this->ignore_files = array($ig);
+ }
+ $this->ignore_files = array_map('trim', $this->ignore_files);
+ }
+
+ function createDocs($title = false)
+ {
+ $this->parse_start_time = time();
+ global $_phpDocumentor_setting;
+ if (!$this->render)
+ {
+ $this->render = new phpDocumentor_IntermediateParser($title);
+ }
+ // setup ignore list
+ $this->ignore_files =array();
+ if(isset($_phpDocumentor_setting['ignore']))
+ {
+ $this->setIgnore($_phpDocumentor_setting['ignore']);
+ }
+ $this->parse->subscribe("*",$this->render);
+ // parse the directory
+ if (!empty($this->files))
+ {
+ $files = explode(",",$this->files);
+ foreach($files as $file)
+ {
+ $file = trim($file);
+ $test = $this->setup->getAllFiles($file);
+ if ($test)
+ {
+ foreach($test as $file)
+ {
+ $file = trim($file);
+ $dir = realpath(dirname($file));
+ $dir = strtr($dir, "\\", "/");
+ $dir = str_replace('//','/',$dir);
+ // strip trailing directory seperator
+ if (substr($dir,-1) == "/" || substr($dir,-1) == "\\")
+ {
+ $dir = substr($dir,0,-1);
+ }
+ $file = strtr(realpath($file), "\\", "/");
+ $file = str_replace('//','/',$file);
+
+ if (!$this->setup->checkIgnore(basename($file),dirname($file),$this->ignore_files))
+ {
+ $filelist[] = str_replace('\\','/',$file);
+ } else {
+ phpDocumentor_out("File $file Ignored\n");
+ flush();
+ }
+ }
+ } else
+ {
+ $dir = realpath(dirname(realpath($file)));
+ $dir = strtr($dir, "\\", "/");
+ $dir = str_replace('//','/',$dir);
+ // strip trailing directory seperator
+ if (substr($dir,-1) == "/" || substr($dir,-1) == "\\")
+ {
+ $dir = substr($dir,0,-1);
+ }
+ $base = count(explode("/",$dir));
+ $file = strtr(realpath($file), "\\", "/");
+ $file = str_replace('//','/',$file);
+ flush();
+
+ if (!$this->setup->checkIgnore(basename($file),dirname($file),$this->ignore_files))
+ {
+ $filelist[] = str_replace('\\','/',$file);
+ } else {
+ phpDocumentor_out("File $file Ignored\n");
+ flush();
+ }
+ }
+ }
+ }
+ if (!empty($this->dirs))
+ {
+ $dirs = explode(",",$this->dirs);
+ foreach($dirs as $dir)
+ {
+ $dir = trim(realpath($dir));
+ $dir = strtr($dir, "\\", "/");
+ $dir = str_replace('//','/',$dir);
+ // strip trailing directory seperator
+ if (substr($dir,-1) == "/" || substr($dir,-1) == "\\")
+ {
+ $dir = substr($dir,0,-1);
+ }
+ $files = $this->setup->dirList($dir,$this->hidden);
+ if (is_array($files))
+ {
+ foreach($files as $file)
+ {
+ // Make sure the file isn't a hidden file
+ $file = strtr($file, "\\", "/");
+ if (substr(basename($file),0,1) != ".")
+ {
+ if (!$this->setup->checkIgnore(basename($file),str_replace('\\','/',dirname($file)),$this->ignore_files))
+ {
+ $filelist[] = str_replace('\\','/',$file);
+ } else {
+ phpDocumentor_out("File $file Ignored\n");
+ flush();
+ }
+ }
+ }
+ }
+ }
+ }
+ if (isset($filelist))
+ {
+ if (PHPDOCUMENTOR_WINDOWS)
+ {
+ // case insensitive array_unique
+ usort($filelist,'strnatcasecmp');
+ reset($filelist);
+
+ $newarray = array();
+ $i = 0;
+
+ $element = current($filelist);
+ for ($n=0;$n<sizeof($filelist);$n++)
+ {
+ if (strtolower(next($filelist)) != strtolower($element))
+ {
+ $newarray[$i] = $element;
+ $element = current($filelist);
+ $i++;
+ }
+ }
+ $filelist = $newarray;
+ } else $filelist = array_unique($filelist);
+
+ $base = count(explode("/",$source_base = $this->setup->getBase($filelist)));
+ define("PHPDOCUMENTOR_BASE",$source_base);
+ list($filelist,$ric) = $this->setup->getReadmeInstallChangelog($source_base, $filelist);
+ phpDocumentor_out("\n\nGrabbing README/INSTALL/CHANGELOG\n");
+ flush();
+ foreach($ric as $file)
+ {
+ phpDocumentor_out(basename($file).'...');
+ flush();
+ $fp = fopen($file,'r');
+ $contents = fread($fp,filesize($file));
+ $this->render->HandleEvent(PHPDOCUMENTOR_EVENT_README_INSTALL_CHANGELOG, array(basename($file),$contents));
+ fclose($fp);
+ }
+ phpDocumentor_out("\ndone\n");
+ flush();
+ list($filelist,$tutorials) = $this->setup->getTutorials($filelist);
+ phpDocumentor_out("\n\nTutorial/Extended Documentation Parsing Stage\n\n");
+ flush();
+ if (count($tutorials))
+ {
+ $tuteparser = new XMLPackagePageParser;
+ $tuteparser->subscribe('*',$this->render);
+ foreach($tutorials as $tutorial)
+ {
+ switch($tutorial['tutetype'])
+ {
+ case 'pkg' :
+ case 'cls' :
+ case 'proc' :
+ switch($tutorial['tutetype'])
+ {
+ case 'pkg' :
+ $ptext = 'Package-level Docs ';
+ if (!empty($tutorial['subpackage']))
+ $ptext = 'Sub-Package Docs ';
+ break;
+ case 'cls' :
+ $ptext = 'Class-level Docs ';
+ break;
+ case 'proc' :
+ $ptext = 'Procedural-level Docs ';
+ break;
+ }
+ $fp = @fopen($tutorial['path'],"r");
+ if ($fp)
+ {
+ $ret = fread($fp,filesize($tutorial['path']));
+ // fix 1151650
+ if (stristr($ret, "utf-8") !== "")
+ {
+ $ret = utf8_decode($ret);
+ }
+ fclose($fp);
+ unset($fp);
+ phpDocumentor_out('Parsing '.$ptext.$tutorial['path'].'...');
+ flush();
+ $tuteparser->parse($ret,$tutorial);
+ phpDocumentor_out("done\n");
+ flush();
+ } else
+ {
+ phpDocumentor_out('Error '.$ptext.$tutorial['path'].' doesn\'t exist'."\n");
+ flush();
+ }
+ default :
+ break;
+ }
+ }
+ }
+ phpDocumentor_out("done\n");
+ flush();
+ phpDocumentor_out("\n\nGeneral Parsing Stage\n\n");
+ flush();
+ foreach($filelist as $file)
+ {
+ phpDocumentor_out("Reading file $file");
+ flush();
+ $this->parse->parse($a = $this->setup->readPhpFile($file, $this->render->quietMode),$file,$base,$this->packages);
+
+ }
+ $b = (time() - $this->parse_start_time);
+ phpDocumentor_out("done\n");
+ flush();
+ // render output
+ phpDocumentor_out("\nConverting From Abstract Parsed Data\n");
+ flush();
+ $this->render->output();
+ $a = (time() - $this->parse_start_time);
+ $c = ($a - $b);
+ phpDocumentor_out("\nParsing time: $b seconds\n");
+ phpDocumentor_out("\nConversion time: $c seconds\n");
+ phpDocumentor_out("\nTotal Documentation Time: $a seconds\n");
+ phpDocumentor_out("done\n");
+ flush();
+ } else
+ {
+ print "ERROR: nothing parsed";
+ exit;
+ }
+ }
+ /**
+ * Parse configuration file phpDocumentor.ini
+ */
+ function parseIni()
+ {
+ phpDocumentor_out("Parsing configuration file phpDocumentor.ini...");
+ flush();
+ if ('@DATA-DIR@' != '@'.'DATA-DIR@')
+ {
+ $options = phpDocumentor_parse_ini_file(str_replace('\\','/', '@DATA-DIR@/PhpDocumentor') . PATH_DELIMITER . 'phpDocumentor.ini',true);
+ } else {
+ $options = phpDocumentor_parse_ini_file(str_replace('\\','/',$GLOBALS['_phpDocumentor_install_dir']) . PATH_DELIMITER . 'phpDocumentor.ini',true);
+ }
+
+ if (!$options)
+ {
+ print "ERROR: cannot open phpDocumentor.ini in directory " . $GLOBALS['_phpDocumentor_install_dir']."\n";
+ print "-Is phpdoc in either the path or include_path in your php.ini file?";
+ exit;
+ }
+
+ foreach($options as $var => $values)
+ {
+ if ($var != 'DEBUG')
+ {
+// phpDocumentor_out("\n$var");
+ if ($var != '_phpDocumentor_setting' && $var != '_phpDocumentor_options' && $var != '_phpDocumentor_install_dir' ) $values = array_values($values);
+// fancy_debug("\n$var",$values);
+ $GLOBALS[$var] = $values;
+ }
+ }
+ phpDocumentor_out("\ndone\n");
+ flush();
+ /** Debug Constant */
+ define("PHPDOCUMENTOR_DEBUG",$options['DEBUG']['PHPDOCUMENTOR_DEBUG']);
+ define("PHPDOCUMENTOR_KILL_WHITESPACE",$options['DEBUG']['PHPDOCUMENTOR_KILL_WHITESPACE']);
+ $GLOBALS['_phpDocumentor_cvsphpfile_exts'] = $GLOBALS['_phpDocumentor_phpfile_exts'];
+ foreach($GLOBALS['_phpDocumentor_cvsphpfile_exts'] as $key => $val)
+ {
+ $GLOBALS['_phpDocumentor_cvsphpfile_exts'][$key] = "$val,v";
+ }
+ // none of this stuff is used anymore
+ if (isset($GLOBALS['_phpDocumentor_html_allowed']))
+ {
+ $___htmltemp = array_flip($GLOBALS['_phpDocumentor_html_allowed']);
+ $___html1 = array();
+ foreach($___htmltemp as $tag => $trans)
+ {
+ $___html1['<'.$tag.'>'] = htmlentities('<'.$tag.'>');
+ $___html1['</'.$tag.'>'] = htmlentities('</'.$tag.'>');
+ }
+ $GLOBALS['phpDocumentor___html'] = array_flip($___html1);
+ }
+ }
+
+ function setupConverters($output = false)
+ {
+ global $_phpDocumentor_setting;
+ if ($output)
+ {
+ $_phpDocumentor_setting['output'] = $output;
+ }
+ if (isset($_phpDocumentor_setting['output']) && !empty($_phpDocumentor_setting['output']))
+ {
+ $c = explode(',',$_phpDocumentor_setting['output']);
+ for($i=0; $i< count($c); $i++)
+ {
+ $c[$i] = explode(':',$c[$i]);
+ $a = $c[$i][0];
+ $b = false;
+ $d = 'default/';
+ if (count($c[$i]) > 1)
+ {
+ $a = $c[$i][0];
+ $b = $c[$i][1];
+ if (isset($c[$i][2]))
+ {
+ $d = $c[$i][2];
+ $d = str_replace("\\","/",$d);
+ if (substr($d,-1) != "/")
+ {
+ $d .= "/";
+ }
+ }
+ else $d = 'default/';
+ }
+ if (strtoupper(trim($a)) == 'HTML' && (trim($b) == 'default'))
+ {
+ phpDocumentor_out("WARNING: HTMLdefaultConverter is deprecated, using HTMLframesConverter.\n");
+ phpDocumentor_out("WARNING: template output is identical, HTMLframes is more flexible.\n");
+ phpDocumentor_out("WARNING: please adjust your usage\n");
+ flush();
+ $b = 'frames'; // change default to frames.
+ }
+ $this->render->addConverter(strtoupper(trim($a)),trim($b),trim($d));
+ }
+ } else
+ {
+ $this->render->addConverter('HTML','frames','default/');
+ }
+ if (empty($this->render->converters)) addErrorDie(PDERROR_NO_CONVERTERS);
+ }
+}
+
+/**
+ * Print parse information if quiet setting is off
+ */
+function phpDocumentor_out($string)
+{
+ global $_phpDocumentor_setting;
+ if (!isset($_phpDocumentor_setting['quiet']) || !$_phpDocumentor_setting['quiet'])
+ {
+ print $string;
+ }
+
+}
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/BUGS b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/BUGS
new file mode 100644
index 00000000..fcbe48af
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/BUGS
@@ -0,0 +1,7 @@
+Smarty is supported only in PHP 4.0.6 or later.
+
+Smarty versions previous to 2.0 require the PEAR libraries. Be sure to include
+the path to the PEAR libraries in your php include_path. Config_file.class.php
+uses the PEAR library for its error handling routines. PEAR comes with the PHP
+distribution. Unix users check /usr/local/lib/php, windows users check
+C:/php/pear.
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/COPYING.lib b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/COPYING.lib
new file mode 100644
index 00000000..3b204400
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/COPYING.lib
@@ -0,0 +1,458 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/ChangeLog b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/ChangeLog
new file mode 100644
index 00000000..6dcda589
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/ChangeLog
@@ -0,0 +1,5421 @@
+2003-11-18 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php:
+ move Smarty::quote_replace() to Smarty_Compiler::_quote_replace()
+
+ * libs/Smarty.class.php:
+ removed extract-calls from _include()- and _eval()-wrappers
+ variables passed with {include_php} have to accessed as members of $params
+ now
+
+2003-11-17 Messju Mohr <messju@lammfellpuschen.de>
+
+ * docs/designers.sgml:
+ fixed typo
+
+2003-11-13 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Config_File.class.php:
+ fix occasional notice
+
+2003-11-13 andreas halter <phpcvs@andreashalter.ch>
+
+ * docs/de/designers.sgml:
+ - added cat modifier, thanks messju :-)
+
+2003-11-13 Monte Ohrt <monte@ispi.net>
+
+ * (Smarty_2_6_0-RC3)
+ NEWS
+ libs/Config_File.class.php
+ libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php:
+ commit RC3 tags
+
+2003-11-13 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/Smarty_Compiler.class.php:
+ fix handling of $var.key inside []
+
+ * libs/Smarty.class.php:
+ fix unnecessary loading of core.load_resource_plugin.php
+
+ * (Smarty_2_6_0-RC3)
+ docs/fr/designers.sgml:
+ fixed example of html_table
+
+2003-11-11 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/core/core.process_cached_inserts.php:
+ fix handling of assign inside {insert}-tags
+
+2003-11-06 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/core/core.read_cache_file.php:
+ added $exp_time-parameter
+
+ * docs/programmers.sgml:
+ added $exp_time to cache_handler_func-example
+
+ * libs/Smarty.class.php
+ libs/core/core.write_cache_file.php:
+ added $exp_time-parameter of clear_cache() and clear_all_cache() to
+ cache_handler_func.
+
+2003-11-05 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/Config_File.class.php:
+ fix handling if [...] inside triple-quotes in config-files
+
+2003-11-04 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty.class.php:
+ fixed little bug in _parse_resource_name() (jlgunter, messju)
+
+2003-11-03 andreas halter <phpcvs@andreashalter.ch>
+
+ * docs/designers.sgml
+ docs/de/designers.sgml
+ docs/fr/designers.sgml:
+ - changed Smarty.php.class occurences to Smarty.class.php
+
+2003-10-29 boots <jayboots@yahoo.com>
+
+ * docs/appendixes.sgml
+ docs/designers.sgml
+ docs/manual.sgml
+ docs/programmers.sgml
+ docs/de/appendixes.sgml
+ docs/de/designers.sgml
+ docs/de/programmers.sgml
+ docs/fr/appendixes.sgml
+ docs/fr/designers.sgml
+ docs/fr/getting-started.sgml
+ docs/fr/manual.sgml
+ docs/fr/preface.sgml
+ docs/fr/programmers.sgml:
+ Fixes to documentation syntax so that all content can be processed used
+ xsltproc docbook-xsl tools. In particular, fixes unescaped entities,
+ broken tags, unquoted attributes.
+
+2003-10-27 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/Smarty_Compiler.class.php:
+ fix handling of simple-math-operators inside modifiers
+
+2003-10-25 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty_Compiler.class.php:
+ removed unused property _output_type
+ removed unused param $tag_attrs of _parse_var_props()
+ cleaned up alignment of class-properties
+
+2003-10-23 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty_Compiler.class.php:
+ removed notice in php-tag handling in Smarty_Compiler::_compile_file()
+
+ * libs/Smarty_Compiler.class.php:
+ removed two occasional E_NOTICES from
+ Smarty_Compiler::_compile_include_php_tag()
+
+ * NEWS
+ libs/core/core.create_dir_structure.php:
+ fix handling of trailing-slashes in open_basedir in
+ smarty_core_create_dir_structure()
+
+2003-10-20 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty_Compiler.class.php:
+ elements inside `` are bracketed now inside the compiled-tpl. this
+ fixes some issues with simple-math inside backticks.
+
+2003-10-16 Monte Ohrt <monte@ispi.net>
+
+ * docs/designers.sgml:
+ update overlib docs, no working examples
+
+2003-10-12 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty.class.php
+ libs/core/core.is_secure.php:
+ move check for template_dir in secure_dir-array into core.is_secure.php
+
+ this makes template_exists() work correctly with security=true even if
+ template_dir is not inside the secure_dir-array
+
+2003-10-11 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/plugins/shared.make_timestamp.php:
+ tightened check for YYYYMMDDHHMMSS-format. thanks konstantin for
+ pointing this out.
+
+ removed a few tabs.
+
+ * libs/Smarty_Compiler.class.php:
+ fix precedence of simple-math-operators before modifiers.
+ thanks dominik!
+
+ * libs/Config_File.class.php
+ libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php
+ libs/core/core.assemble_plugin_filepath.php
+ libs/core/core.assign_smarty_interface.php
+ libs/core/core.create_dir_structure.php
+ libs/core/core.display_debug_console.php
+ libs/core/core.get_include_path.php
+ libs/core/core.get_microtime.php
+ libs/core/core.get_php_resource.php
+ libs/core/core.is_secure.php
+ libs/core/core.is_trusted.php
+ libs/core/core.load_plugins.php
+ libs/core/core.load_resource_plugin.php
+ libs/core/core.process_cached_inserts.php
+ libs/core/core.process_compiled_include.php
+ libs/core/core.read_cache_file.php
+ libs/core/core.rm_auto.php
+ libs/core/core.rmdir.php
+ libs/core/core.run_insert_handler.php
+ libs/core/core.smarty_include_php.php
+ libs/core/core.write_compiled_include.php
+ libs/core/core.write_compiled_resource.php
+ libs/core/core.write_file.php:
+ removed tabs from the main and the core/*.php files
+
+2003-10-08 Monte Ohrt <monte@ispi.net>
+
+ * (Smarty_2_6_0-RC2)
+ NEWS
+ libs/Config_File.class.php
+ libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php:
+ update version numbers to RC2
+
+2003-09-18 Messju Mohr <messju@lammfellpuschen.de>
+
+ * docs/designers.sgml
+ docs/de/designers.sgml:
+ fixed description of cycle's advance-attribute
+
+2003-09-16 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/Smarty_Compiler.class.php:
+ apply modifiers only once to section-loop and foreach-from attributes
+
+2003-09-15 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php
+ libs/core/core.write_cache_paths_file.php:
+ backed out _smarty_cached_paths-file-handling
+
+ * libs/Smarty.class.php
+ libs/core/core.rm_auto.php:
+ fixed clear_compiled_tpl with explicit $tpl_file given
+ fixed return value of smarty_core_rm_auto() + Smarty::_unlink()
+
+ * libs/Smarty.class.php:
+ little fix in _get_auto_filename()
+
+2003-09-14 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty.class.php
+ libs/core/core.assemble_auto_filename.php:
+ removed auto-filenames from path-cache. merged assemble_auto_filename
+ back into Smarty::_get_auto_filename()
+
+2003-09-12 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty_Compiler.class.php:
+ fixed quoting of modifier parameters
+
+ * NEWS
+ libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php
+ libs/core/core.get_php_resource.php
+ libs/core/core.load_plugins.php
+ libs/core/core.load_resource_plugin.php:
+ remove Smarty::_plugin_implementation_exists() - use php's native
+ is_callable()
+
+2003-09-11 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty.class.php:
+ silenced two notices acces HTTP_SERVER_VARS
+
+2003-09-10 andreas halter <phpcvs@andreashalter.ch>
+
+ * docs/de/designers.sgml
+ docs/de/getting-started.sgml
+ docs/de/programmers.sgml:
+ - minor fixes (2 rep), slight wording changes
+ - jade transform problem fixed
+
+2003-09-08 andreas halter <phpcvs@andreashalter.ch>
+
+ * docs/de/designers.sgml
+ docs/de/getting-started.sgml
+ docs/de/manual.sgml
+ docs/de/preface.sgml
+ docs/de/programmers.sgml:
+ all updated for 2.6.0 release, translated everything from 2_5_0 branch to
+ 20030908
+
+2003-09-04 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty.class.php:
+ proper checking for files in _fetch_resource_info()
+
+2003-09-02 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/Smarty_Compiler.class.php:
+ ignore {strip}/{/strip) inside {strip}-blocks
+
+ * libs/plugins/function.mailto.php:
+ fixed 2 notices in smarty_function_mailto()
+
+2003-09-01 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty.class.php:
+ re-include cache_paths on multiple calls to fetch() to avoid
+ inconsistencies
+ at multiple calls to fetch() in one script
+
+ * libs/Smarty_Compiler.class.php:
+ fixed handling of \r in {strip}
+ renamed $_trailing_lf to $_additional_newline
+
+ * libs/Smarty_Compiler.class.php:
+ the weekly fix for {strip} :)
+
+ * docs/designers.sgml:
+ fixed example for simple math.
+
+2003-08-29 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/core/core.assign_smarty_interface.php
+ libs/core/core.display_debug_console.php
+ libs/plugins/function.assign.php
+ libs/plugins/function.html_options.php
+ libs/plugins/function.html_table.php:
+ fixed PHPDocumentor-comments (thanks Konstantin)
+
+ * libs/core/core.rmdir.php:
+ made rmdir a bit more optimistic. especially it now removes
+ directories correctly that where created accidently by "safe_mode=On
+ && $use_sub_dirs=true"
+
+2003-08-27 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/Smarty_Compiler.class.php:
+ fixed removal of leading/trailing newlines in {strip}-blocks
+
+2003-08-25 Messju Mohr <messju@lammfellpuschen.de>
+
+ * INSTALL:
+ added note emphasizing the introduction of "libs/" with 2.5.0
+
+ * NEWS
+ libs/plugins/modifier.escape.php:
+ fixed proper escaping of " and ' with escape:javascript
+
+2003-08-22 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/core/core.assemble_plugin_filepath.php:
+ fixed bug in traversal of $smarty->plugins_dir-array in
+ smarty_core_assemble_plugin_filepath(). the first matching plugin in
+ the path should be used, not the last one.
+
+ * libs/core/core.read_cache_file.php:
+ discard $_cache_info when the cache should be regenerated
+
+2003-08-20 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/Smarty_Compiler.class.php
+ libs/plugins/block.strip.php:
+ reverted {strip} from a block-plugin back into the compiler
+
+ * docs/programmers.sgml:
+ fixed examples for register_function() and register_block()
+
+ * libs/Smarty.class.php:
+ made template_exists() quiet when the template does not exist (thanks
+ to konstatin for pointing this out)
+
+2003-08-18 Monte Ohrt <monte@ispi.net>
+
+ * docs/getting-started.sgml:
+ fix example title
+
+ * docs/README
+ docs/getting-started.sgml:
+ change installation wording confusion
+
+2003-08-18 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty.class.php
+ libs/core/core.read_cache_file.php:
+ fixed unnecessary load of source in template_exists() and the
+ compile-check of smarty_core_read_cache_file()
+
+ * libs/Smarty_Compiler.class.php:
+ allow section-, array- and object-dereference in $smarty-references
+
+2003-08-15 Messju Mohr <messju@lammfellpuschen.de>
+
+ * docs/designers.sgml:
+ added parameter-descriptions for count_characters (thanks Konstantin
+ A. Pelepelin)
+
+ fixed docs for {html_checkboxes}
+
+2003-08-14 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty.class.php
+ libs/core/core.read_cache_file.php:
+ fixed timestamp-check of config-files in smarty_core_read_cache_file()
+
+ * libs/Smarty.class.php:
+ fixed typecasting for arrays in _parse_resource_name()
+
+ * NEWS
+ libs/plugins/function.config_load.php:
+ fixes in config_load:
+ - handling of section-attribute
+ - reusing the same config-file multiple times
+ - serialization of config-data for php<4.2.0 (no var_export)
+
+ many thanks to atu for pointing this out and for testing
+
+2003-08-13 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty.class.php
+ libs/core/core.smarty_include_php.php:
+ fixed problem with vars as attributes in {include_php}
+
+2003-08-13 Monte Ohrt <monte@ispi.net>
+
+ * docs/README:
+ commit README file for documentation compiling
+
+2003-08-13 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/debug.tpl
+ libs/plugins/modifier.debug_print_var.php:
+ removed '\r' from debug_print_vars' output
+ properly escape vars in javascript-version of debug.tpl
+
+2003-08-11 Monte Ohrt <monte@ispi.net>
+
+ * (Smarty_2_6_0_RC1)
+ NEWS
+ docs/designers.sgml
+ docs/html.dsl
+ docs/php.dsl
+ libs/Config_File.class.php
+ libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php:
+ get ready for 2.6.0-RC1 release
+
+2003-08-10 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/Smarty.class.php:
+ fixed status-header for cache_modified_check under cgi-sapi
+
+2003-08-09 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/core/core.is_secure.php
+ libs/core/core.is_trusted.php:
+ synced secure_dir-checking with trusted_dir-checking
+
+ * libs/core/core.is_secure.php:
+ tightenend path checking in smarty_core_is_secure()
+
+2003-08-08 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty.class.php:
+ fix: proper nesting of $smarty->_cache_including flag in cascaded
+ cached/not-cached/fetched/inserted/foo-templates
+
+ * libs/debug.tpl:
+ better escaping for $_debug_tpls[templates].filenames
+
+ * libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php:
+ removed redundant $smarty from Smarty::_smarty_include()
+
+ * libs/debug.tpl:
+ proper escaping of filenames in debug-console (thanks to prossel).
+
+2003-08-07 Messju Mohr <messju@lammfellpuschen.de>
+
+ * docs/programmers.sgml:
+ added docs for block-methods of registered objects
+
+ * docs/programmers.sgml:
+ fixed typo in example for registered objects
+
+ * docs/designers.sgml:
+ fixed exampls of html_image and html_checkboxes
+
+ * libs/plugins/function.debug.php:
+ fixed {debug} and removed tabs in function.debug.php
+
+ * docs/programmers.sgml:
+ fixed example for register_object
+
+ * docs/designers.sgml
+ docs/programmers.sgml:
+ updated docs for capture, html_table, html_image and register_object
+
+2003-08-07 Monte Ohrt <monte@ispi.net>
+
+ * docs/designers.sgml
+ docs/programmers.sgml:
+ add math and default_resource_type to docs
+
+ * docs/getting-started.sgml:
+ add core to example, add tech note
+
+2003-08-07 Messju Mohr <messju@lammfellpuschen.de>
+
+ * docs/manual.sgml
+ docs/fr/manual.sgml:
+ upd copyright in the docs
+
+2003-08-07 Monte Ohrt <monte@ispi.net>
+
+ * docs/getting-started.sgml:
+ added core directory to install instructions
+
+2003-08-07 Messju Mohr <messju@lammfellpuschen.de>
+
+ * docs/designers.sgml
+ docs/programmers.sgml:
+ added docs for php-functions as modifiers
+
+ * libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php:
+ better caching of attributes for $cacheable=false-plugins
+
+ * docs/programmers.sgml:
+ added section "caching.cacheable" to the docs, explaining the usage of
+ the $cacheable-flag of the register_(block|compiler|function)-functions
+
+ * libs/Smarty_Compiler.class.php:
+ fixed output of custom-functions with cached attributes
+
+ * docs/programmers.sgml:
+ docs update on callbacks to the register_*-functions
+
+2003-08-06 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php
+ libs/core/core.process_compiled_include.php:
+ added optional parameter $cache_attrs to register_function() and
+ register_block(). $cache_attrs is an array containing attribute- names
+ that should be cached on calls to functions that have $cacheable set
+ to false.
+
+ * libs/Smarty.class.php:
+ fixed bug in _run_mod_handler
+
+ * libs/Smarty_Compiler.class.php:
+ fixed bug with autoload-handling of modifiers. thanks ándre.
+
+2003-08-05 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Config_File.class.php
+ libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php:
+ updated copyright notice
+
+ * libs/Smarty.class.php
+ libs/core/core.load_plugins.php:
+ fixed bug that occurred when using the same not-cacheable plugin in
+ multiple includes
+
+ * docs/programmers.sgml:
+ docs-update for plugins.writing
+
+2003-08-04 Messju Mohr <messju@lammfellpuschen.de>
+
+ * docs/designers.sgml
+ docs/programmers.sgml:
+ updated docs for register_block_function(), block-functions,
+ $request_use_auto_globals and html_checkboxes
+
+2003-07-31 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php:
+ enabled registration of class-methods as callbacks for the
+ register_*-functions
+
+ use: array('classname', 'method_name')) as callback
+
+2003-07-29 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php:
+ modifiers are resolved at compile-time now. _run_mod_handler() is
+ still used for modifiers with map_array=true (== no preceeding '@')
+
+ * libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php
+ libs/core/core.smarty_include.php:
+ moved _smarty_include() back into Smarty.class.php
+
+ * libs/Smarty.class.php
+ libs/core/core.load_plugins.php:
+ prevent unnecessary calls to _read_file() in _is_compiled()
+ converted method-call to internal function-call in
+ smarty_core_load_plugins()
+
+2003-07-28 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty_Compiler.class.php:
+ quote smarty-header properly to prevent resource-names from escaping from
+ the comment
+
+2003-07-25 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/core/core.create_dir_structure.php:
+ weakend race-condition and removed bogus error-message caused by that
+ in smarty_core_create_dir_structure().
+
+2003-07-23 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty.class.php
+ libs/core/core.display_debug_console.php
+ libs/core/core.fetch_resource_info.php
+ libs/core/core.get_php_resource.php
+ libs/core/core.parse_resource_name.php
+ libs/core/core.process_cached_inserts.php
+ libs/core/core.read_cache_file.php
+ libs/core/core.run_insert_handler.php
+ libs/core/core.smarty_include.php
+ libs/core/core.smarty_include_php.php
+ libs/plugins/function.eval.php:
+ moved _fetch_resource_info and _parse_resource_name back into
+ Smarty.class.php
+ renamed smarty_include and smarty_eval wrappers to _include and _eval
+
+2003-07-17 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/core/core.process_compiled_include.php
+ libs/core/core.read_cache_file.php:
+ improved checking of compiled_include against cached-template with
+ non-cached-chunks
+
+ * libs/core/core.write_compiled_include.php:
+ fixed too short open-tag
+
+ * libs/plugins/function.eval.php:
+ fixed assign parameter for eval (must have gotton lost on its way to 2.5.0)
+ cleaned up indentiation
+
+2003-07-03 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty_Compiler.class.php:
+ resurrected $foo->$bar syntax
+
+ * libs/Smarty_Compiler.class.php:
+ i'm so stupid. kick me.
+
+ * libs/Smarty_Compiler.class.php:
+ fixed initialisation of $this->_plugins in compile_block_tag()
+
+2003-07-03 Monte Ohrt <monte@ispi.net>
+
+ * libs/Config_File.class.php:
+ add preg_quote delimiter
+
+2003-07-03 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty_Compiler.class.php:
+ applied fix for {$var1->p1|modifier:$var2->p2}-syntax - thanks Dominik
+
+2003-07-02 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty_Compiler.class.php:
+ fixed duplicate generation of arg-list in _compile_block_tag()
+
+ * libs/Smarty_Compiler.class.php:
+ fixed off-by-one-error in nocache-tag-handling
+
+2003-06-30 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty_Compiler.class.php:
+ backed out errornously committed support for $foo->$bar
+
+ * libs/core/core.write_file.php:
+ fixed indentiation, silenced occasional warning
+
+ * libs/plugins/function.html_image.php:
+ match first character of file-attribute against "/" instead of
+ DIRECTORY_SEPARATOR since it is a url-path and not a file-path.
+
+ * libs/Smarty_Compiler.class.php
+ libs/core/core.write_file.php
+ libs/plugins/function.html_image.php:
+ libs/plugins/function.html_image.php
+
+ * libs/Smarty_Compiler.class.php:
+ re-fixed cacheable_state-handling
+
+ * libs/core/core.display_debug_console.php
+ libs/core/core.process_cached_inserts.php
+ libs/core/core.process_compiled_include.php
+ libs/core/core.run_insert_handler.php:
+ extincting $this out of smarty_core_*-functions
+
+ * libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php:
+ fixed handling of nocache-state
+
+2003-06-29 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty.class.php
+ libs/core/core.smarty_include.php
+ libs/core/core.smarty_include_php.php
+ libs/plugins/function.eval.php:
+ removed $this from smarty_include and smarty_include_php
+ added cleaner handling of $this to {eval}
+
+ * libs/core/core.load_resource_plugin.php:
+ fixed inlude_once-call
+
+ * docs/de/designers.sgml
+ docs/fr/designers.sgml:
+ fixed examples of html_radios and html_checkboxes in german and french docs
+
+2003-06-25 Monte Ohrt <monte@ispi.net>
+
+ * libs/core/core.assemble_auto_filename.php
+ libs/core/core.write_cache_paths_file.php:
+ fix typo, fix write_cache_paths logic
+
+ * libs/Smarty.class.php
+ libs/core/core.assemble_auto_filename.php:
+ fix SMARTY_COMPILE_DIR_SEP problem, make local var
+
+2003-06-24 Monte Ohrt <monte@ispi.net>
+
+ * libs/Smarty.class.php
+ libs/core/core.assemble_auto_filename.php
+ libs/core/core.write_cache_paths_file.php:
+ fixed cache_paths bug, simplified filename assembly logic
+
+2003-06-24 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/plugins/function.html_image.php:
+ added parsing of forgotton param "basedir"
+
+ * libs/Smarty_Compiler.class.php:
+ fixed $smarty.get-reference
+
+ * libs/plugins/block.textformat.php:
+ removed warning
+
+ * libs/Smarty_Compiler.class.php:
+ fixed value of _cacheable_state on compiler-startup
+
+2003-06-23 Monte Ohrt <monte@ispi.net>
+
+ * libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php
+ libs/core/core.write_cache_paths_file.php:
+ make cache_path per resource, fix a couple directory path issues
+
+2003-06-23 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty_Compiler.class.php:
+ removed warning when compiling empty template
+
+ * libs/core/core.write_compiled_include.php:
+ fixed bug in write_compiled_include
+
+ * libs/core/core.assemble_plugin_filepath.php:
+ fixed warning
+
+2003-06-22 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/plugins/function.eval.php:
+ fixed propagation of $this into evald code in smarty_function_eval()
+
+ * libs/core/core.write_cache_paths_file.php
+ libs/core/core.write_compiled_include.php:
+ fix in compiled-include-handling
+
+ * libs/core/core.assemble_auto_filename.php
+ libs/core/core.assemble_plugin_filepath.php
+ libs/core/core.assign_smarty_interface.php
+ libs/core/core.create_dir_structure.php
+ libs/core/core.fetch_resource_info.php
+ libs/core/core.get_include_path.php
+ libs/core/core.get_microtime.php
+ libs/core/core.get_php_resource.php
+ libs/core/core.is_secure.php
+ libs/core/core.is_trusted.php
+ libs/core/core.load_plugins.php
+ libs/core/core.load_resource_plugin.php
+ libs/core/core.parse_resource_name.php
+ libs/core/core.read_cache_file.php
+ libs/core/core.rm_auto.php
+ libs/core/core.rmdir.php
+ libs/core/core.write_cache_file.php
+ libs/core/core.write_cache_paths_file.php
+ libs/core/core.write_compiled_include.php
+ libs/core/core.write_compiled_resource.php
+ libs/core/core.write_file.php
+ libs/plugins/modifier.date_format.php:
+ started moving from $this to $smarty in core.*.php
+
+2003-06-21 Monte Ohrt <monte@ispi.net>
+
+ * libs/core/core.create_dir_structure.php
+ libs/core/core.write_file.php
+ libs/plugins/function.config_load.php:
+ fix more dir paths
+
+ * NEWS
+ libs/Smarty.class.php
+ libs/core/core.assemble_auto_filename.php
+ libs/core/core.assemble_plugin_filepath.php
+ libs/core/core.fetch_resource_info.php
+ libs/core/core.get_php_resource.php
+ libs/core/core.parse_resource_name.php
+ libs/core/core.process_cached_inserts.php
+ libs/core/core.read_cache_file.php
+ libs/core/core.rm_auto.php
+ libs/core/core.rmdir.php
+ libs/core/core.run_insert_handler.php
+ libs/core/core.smarty_include.php
+ libs/core/core.smarty_include_php.php
+ libs/core/core.write_cache_file.php
+ libs/core/core.write_cache_paths_file.php
+ libs/core/core.write_compiled_include.php
+ libs/core/core.write_compiled_resource.php
+ libs/core/core.write_file.php
+ libs/plugins/function.config_load.php
+ libs/plugins/function.fetch.php
+ libs/plugins/function.html_image.php:
+ fix filepaths to core files to use DIRECTORY_SEPARATOR
+
+2003-06-21 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty_Compiler.class.php:
+ fixed {plugin|modifier} syntax
+
+ * libs/Smarty.class.php
+ libs/core/core.write_compiled_include.php:
+ fixed compiled include handling
+
+2003-06-21 Monte Ohrt <monte@ispi.net>
+
+ * libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php
+ libs/core/core.assemble_auto_filename.php
+ libs/core/core.assemble_plugin_filepath.php
+ libs/core/core.write_cache_paths_file.php:
+ added filepath caching
+
+2003-06-20 Monte Ohrt <monte@ispi.net>
+
+ * libs/Smarty_Compiler.class.php:
+ update more varnames
+
+ * libs/Smarty.class.php
+ libs/core/core.display_debug_console.php
+ libs/core/core.fetch_file_info.php
+ libs/core/core.fetch_resource_info.php
+ libs/core/core.get_php_resource.php
+ libs/core/core.parse_file_path.php
+ libs/core/core.parse_resource_name.php
+ libs/core/core.process_cached_inserts.php
+ libs/core/core.read_cache_file.php
+ libs/core/core.run_insert_handler.php
+ libs/core/core.smarty_include.php
+ libs/core/core.smarty_include_php.php
+ libs/core/core.write_compiled_resource.php
+ libs/core/core.write_compiled_template.php
+ libs/plugins/function.config_load.php:
+ refactored var naming to better reflect "resource" instead of "file" where
+ appropriate
+
+2003-06-19 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty.class.php:
+ updated version-number to 2.5.0-cvs
+
+ * libs/core/core.write_cache_file.php:
+ omit is-cache_dir-writable-check if a cache_handler_function is in use
+
+ * libs/core/core.smarty_include_php.php:
+ fixed comments in smarty_include_php
+
+2003-06-19 Monte Ohrt <monte@ispi.net>
+
+ * libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php
+ libs/core/core.display_debug_console.php
+ libs/core/core.smarty_include.php
+ libs/plugins/function.eval.php:
+ split up _compile_template to _compile_file and _compile_source, fix eval
+ function
+ VS: ----------------------------------------------------------------------
+
+ * libs/plugins/function.config_load.php:
+ fix logic for _is_compiled()
+
+2003-06-19 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/Smarty_Compiler.class.php:
+ added optional assign-attribute to {capture}-tag
+
+ * NEWS
+ libs/Smarty.class.php:
+ added $cacheable-parameter to register_compiler_function()
+
+2003-06-18 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php
+ libs/core/core.load_plugins.php
+ libs/core/core.process_compiled_include.php
+ libs/core/core.read_cache_file.php
+ libs/core/core.write_cache_file.php
+ libs/core/core.write_compiled_include.php:
+ added $cacheable-parameter to register_function() and register_block()
+
+ * libs/Smarty.class.php:
+ append '.php' to all compiled templates regardless of the settings of
+ $use_sub_dirs
+
+ * libs/Smarty.class.php
+ libs/core/core.read_cache_file.php:
+ fixed $file_path-parameters passed to smarty_core_fetch_file_info()
+
+2003-06-17 Monte Ohrt <monte@ispi.net>
+
+ * NEWS:
+ fix name
+
+ * libs/Smarty_Compiler.class.php:
+ change varnames to follow coding methods
+
+ * NEWS
+ libs/Smarty_Compiler.class.php:
+ add math patch to core
+
+2003-06-17 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/core/core.smarty_include.php:
+ switched _process_template() to _is_compiled()-logic
+
+2003-06-17 Monte Ohrt <monte@ispi.net>
+
+ * libs/Smarty.class.php:
+ fix _is_compiled logic
+
+ * NEWS:
+ update news file
+
+ * libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php:
+ fix _run_mod_handler routine
+
+ * libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php
+ libs/core/core.display_debug_console.php
+ libs/core/core.fetch_file_info.php
+ libs/core/core.parse_file_path.php
+ libs/core/core.write_compiled_template.php
+ libs/plugins/function.config_load.php:
+ fix path problems, rename some varibles from "template" to "file"
+
+2003-06-16 Monte Ohrt <monte@ispi.net>
+
+ * libs/core/core.fetch_file_info.php
+ libs/core/core.fetch_template_info.php:
+ rename file, commit
+
+ * libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php
+ libs/core/core.parse_file_path.php
+ libs/core/core.read_cache_file.php
+ libs/plugins/block.strip.php
+ libs/plugins/block.textformat.php
+ libs/plugins/compiler.config_load.php
+ libs/plugins/function.config_load.php
+ libs/plugins/function.eval.php
+ libs/plugins/function.fetch.php
+ libs/plugins/function.html_image.php:
+ fix config_load, compile fetched arrays to compile_dir, switch display
+ back to runtime. clean up var names and function names, split up compile
+ testing and compiling to separate funcs, rename some template_* functions
+ to
+ file_* functions and update logic so they can be used for file resources
+ other than templates.
+
+2003-06-16 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty_Compiler.class.php:
+ fixed little bug in _compile_custom_tag()
+
+2003-06-16 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php
+ libs/core/core.assign_smarty_interface.php
+ libs/core/core.create_dir_structure.php
+ libs/core/core.display_debug_console.php
+ libs/core/core.fetch_template_info.php
+ libs/core/core.get_include_path.php
+ libs/core/core.get_microtime.php
+ libs/core/core.get_php_resource.php
+ libs/core/core.is_secure.php
+ libs/core/core.is_trusted.php
+ libs/core/core.load_plugins.php
+ libs/core/core.load_resource_plugin.php
+ libs/core/core.parse_file_path.php
+ libs/core/core.process_cached_inserts.php
+ libs/core/core.read_cache_file.php
+ libs/core/core.rm_auto.php
+ libs/core/core.rmdir.php
+ libs/core/core.run_insert_handler.php
+ libs/core/core.smarty_include.php
+ libs/core/core.smarty_include_php.php
+ libs/core/core.write_cache_file.php
+ libs/core/core.write_compiled_template.php
+ libs/core/core.write_file.php
+ libs/plugins/core.assign_smarty_interface.php
+ libs/plugins/core.create_dir_structure.php
+ libs/plugins/core.display_debug_console.php
+ libs/plugins/core.fetch_template_info.php
+ libs/plugins/core.get_include_path.php
+ libs/plugins/core.get_microtime.php
+ libs/plugins/core.get_php_resource.php
+ libs/plugins/core.is_secure.php
+ libs/plugins/core.is_trusted.php
+ libs/plugins/core.load_plugins.php
+ libs/plugins/core.load_resource_plugin.php
+ libs/plugins/core.parse_file_path.php
+ libs/plugins/core.process_cached_inserts.php
+ libs/plugins/core.read_cache_file.php
+ libs/plugins/core.rm_auto.php
+ libs/plugins/core.rmdir.php
+ libs/plugins/core.run_insert_handler.php
+ libs/plugins/core.smarty_include.php
+ libs/plugins/core.smarty_include_php.php
+ libs/plugins/core.write_cache_file.php
+ libs/plugins/core.write_compiled_template.php
+ libs/plugins/core.write_file.php:
+ move core files into their own directory under SMARTY_DIR,
+ remove abstraction function _execute_core_function
+
+ * libs/Smarty_Compiler.class.php:
+ fix newline handling for template for all template tags
+
+2003-06-11 Monte Ohrt <monte@ispi.net>
+
+ * libs/plugins/compiler.config_load.php:
+ add compiler function to cvs repository
+
+2003-06-11 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php:
+ added config-option "request_use_auto_globals" to make auto-globals be
+ used as request vars instead of HTTP_*_VARS
+
+2003-06-11 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php
+ libs/plugins/function.config_load.php:
+ make config vars compile statically
+
+2003-06-11 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/Smarty_Compiler.class.php:
+ backed out newlines patch
+
+ * NEWS
+ libs/Smarty_Compiler.class.php:
+ removed newlines in compiled templates after closing tags
+
+2003-06-10 Messju Mohr <messju@lammfellpuschen.de>
+
+ * docs/de/designers.sgml:
+ fixed german note on html_image and disk-access
+
+2003-06-10 Monte Ohrt <monte@ispi.net>
+
+ * libs/plugins/core.parse_file_path.php:
+ fix bug with resource_type resolving
+
+2003-06-09 Monte Ohrt <monte@ispi.net>
+
+ * docs/designers.sgml:
+ replace example with more practical one
+
+2003-06-08 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php:
+ added block-methods for registered objects
+
+2003-06-07 Messju Mohr <messju@lammfellpuschen.de>
+
+ * docs/programmers.sgml:
+ fixed bug in documentation for $smarty->default_modifiers
+
+2003-06-06 Monte Ohrt <monte@ispi.net>
+
+ * libs/plugins/core.parse_file_path.php:
+ fix problem with new default_resource_type changes
+
+ * NEWS:
+ update NEWS file info
+
+ * NEWS
+ libs/Smarty.class.php
+ libs/plugins/core.parse_file_path.php:
+ add default_resource_type, ignore 1 char resource names
+
+ * NEWS
+ libs/Config_File.class.php:
+ fix bug where config file starts with hidden section
+
+2003-06-04 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ libs/Smarty.class.php:
+ -** empty log message ***
+
+2003-06-03 Monte Ohrt <monte@ispi.net>
+
+ * libs/plugins/function.html_image.php:
+ fix example in code comments
+
+2003-06-03 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/plugins/function.counter.php:
+ fixed behaviour of start=... for {counter}
+
+2003-06-02 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/plugins/function.counter.php:
+ fixed assign for {counter}
+
+2003-05-30 Monte Ohrt <monte@ispi.net>
+
+ * libs/plugins/core.write_cache_file.php
+ libs/plugins/core.write_compiled_template.php:
+ add discrete error checking pertaining to $cache_dir
+ and $compile_dir, their existance and writability
+
+2003-05-28 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/plugins/function.html_table.php:
+ added params vdir, hdir and inner to html_table to allow looping over
+ the data in various directions
+
+2003-05-28 Monte Ohrt <monte@ispi.net>
+
+ * libs/plugins/core.compile_template.php
+ libs/plugins/core.display_debug_console.php:
+ fix problem with security and debug.tpl file
+
+2003-05-23 Monte Ohrt <monte@ispi.net>
+
+ * NEWS:
+ upd NEWS file
+
+ * libs/Smarty_Compiler.class.php:
+ allow spaces in literal tags
+
+2003-05-22 Monte Ohrt <monte@ispi.net>
+
+ * docs/fr/programmers.sgml:
+ fix special chars
+
+2003-05-19 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ libs/Smarty_Compiler.class.php:
+ speed up compiled templates, hardcode plugin filepaths instead of
+ recalculate at runtime
+
+2003-05-19 Messju Mohr <messju@lammfellpuschen.de>
+
+ * docs/designers.sgml:
+ fixed example of {html_image}
+
+ * docs/designers.sgml:
+ fixed typo
+
+2003-05-12 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty.class.php
+ libs/plugins/core.read_cache_file.php
+ libs/plugins/core.smarty_include.php
+ libs/plugins/function.config_load.php:
+ fixed multiple redundant occurrences for 'config' and 'template' in
+ $smarty->_cache_info
+
+2003-05-10 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/plugins/core.create_dir_structure.php:
+ refurbished create_dir_structure to use '/' internally
+
+ * libs/plugins/core.create_dir_structure.php:
+ fixed windows absolute-paths in smarty_core_create_dir_structure()
+
+ * libs/plugins/core.create_dir_structure.php:
+ fixed error-message
+
+2003-05-09 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty_Compiler.class.php:
+ fixed warning due to missing param to _execute_core_function()
+
+ * libs/Smarty_Compiler.class.php:
+ fixed quoting in _compile_include_php
+
+ * libs/Smarty_Compiler.class.php:
+ fixed quoting of "file"-parameter in _compile_include_tag()
+
+2003-05-08 Monte Ohrt <monte@ispi.net>
+
+ * docs/programmers.sgml:
+ fix typo
+
+ * libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php
+ libs/plugins/core.compile_template.php
+ libs/plugins/core.create_dir_structure.php
+ libs/plugins/core.fetch_template_info.php
+ libs/plugins/core.get_include_path.php
+ libs/plugins/core.get_microtime.php
+ libs/plugins/core.get_php_resource.php
+ libs/plugins/core.is_secure.php
+ libs/plugins/core.is_trusted.php
+ libs/plugins/core.load_plugins.php
+ libs/plugins/core.load_resource_plugin.php
+ libs/plugins/core.parse_file_path.php
+ libs/plugins/core.process_cached_inserts.php
+ libs/plugins/core.read_cache_file.php
+ libs/plugins/core.rm_auto.php
+ libs/plugins/core.rmdir.php
+ libs/plugins/core.run_insert_handler.php
+ libs/plugins/core.smarty_include.php
+ libs/plugins/core.smarty_include_php.php
+ libs/plugins/core.write_cache_file.php
+ libs/plugins/core.write_compiled_template.php
+ libs/plugins/core.write_file.php
+ libs/plugins/function.config_load.php
+ libs/plugins/function.fetch.php
+ libs/plugins/function.html_image.php:
+ abstract more private functions to plugin directory
+
+ * libs/Config_File.class.php:
+ only add DIRECTORY_SEPARATOR if it isn't already present
+
+ * libs/Config_File.class.php:
+ fix directory separator code, use DIRECTORY_SEPARATOR
+
+2003-05-08 Messju Mohr <messju@lammfellpuschen.de>
+
+ * docs/designers.sgml:
+ fixed example of html_checkboxes
+
+ * NEWS
+ libs/Smarty.class.php:
+ fixed bug in _create_dir_structure() when used with
+ open_basedir-restriction and relative paths
+
+ * docs/designers.sgml:
+ fixed example for html_radios
+
+2003-05-07 Monte Ohrt <monte@ispi.net>
+
+ * libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php
+ libs/plugins/core.assign_smarty_interface.php
+ libs/plugins/core.display_debug_console.php
+ libs/plugins/function.display_debug_console.php:
+ abstracted display_debug_console and assign_smarty_interface to plugin dir
+ as a test
+
+ * libs/Smarty.class.php
+ libs/plugins/function.display_debug_console.php:
+ correct misc varnames, abstract debug console display to plugin function
+
+ * libs/plugins/modifier.escape.php:
+ fix typo
+
+2003-05-05 Monte Ohrt <monte@ispi.net>
+
+ * libs/Smarty_Compiler.class.php:
+ add % to math
+
+ * libs/Smarty.class.php:
+ clean up comments, formatting
+
+ * NEWS
+ libs/Smarty.class.php:
+ keep DIR_SEP for 3rd party compatability
+
+ * NEWS
+ libs/Smarty.class.php:
+ remove DIR_SEP, use DIRECTORY_SEPARATOR exclusively
+
+ * libs/Smarty_Compiler.class.php:
+ remove ++ and -- math operators on template vars
+
+2003-05-04 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty_Compiler.class.php:
+ removed unused parameter $quote from Smarty_Compiler::_parse_attrs()
+
+ * libs/plugins/function.html_image.php:
+ fixed DIR_SEP in html_image-plugin
+
+2003-05-04 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ libs/Smarty.class.php:
+ rename DIR_SEP to SMARTY_DIR_SEP to avoid varname collisions
+
+2003-05-04 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/plugins/function.html_image.php:
+ changed "link" to "href" in html_image. "link" is still working but
+ deprecated
+ html_image always renders an alt-tag now (default alt="")
+ cleaned up indentiation of function.html_image.php
+
+2003-05-03 Monte Ohrt <monte@ispi.net>
+
+ * libs/debug.tpl:
+ fix typo
+
+2003-05-02 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/plugins/function.counter.php:
+ fixed assign attribute for multiple counters
+
+2003-05-02 Monte Ohrt <monte@ispi.net>
+
+ * libs/Smarty_Compiler.class.php:
+ allow math on negative number
+
+ * NEWS
+ libs/Smarty_Compiler.class.php:
+ added simple math operators to variables
+
+2003-05-02 Messju Mohr <messju@lammfellpuschen.de>
+
+ * docs/designers.sgml:
+ fixed typos
+
+2003-04-30 Monte Ohrt <monte@ispi.net>
+
+ * docs/fr/appendixes.sgml
+ docs/fr/common.dsl
+ docs/fr/designers.sgml
+ docs/fr/getting-started.sgml
+ docs/fr/html-common.dsl
+ docs/fr/html.dsl
+ docs/fr/manual.sgml
+ docs/fr/php.dsl
+ docs/fr/preface.sgml
+ docs/fr/programmers.sgml:
+ add frech docs to cvs repository
+
+2003-04-29 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php:
+ reverted patch for case-insensitive tag-names
+
+2003-04-28 Messju Mohr <messju@lammfellpuschen.de>
+
+ * docs/programmers.sgml:
+ reverted back to humerous redundancy in the docs :). although we all
+ know we are here to generate template-based output, and not to have
+ fun ;-)
+
+ * docs/getting-started.sgml:
+ fixed default user and group for max os x installation
+
+ * libs/Smarty.class.php:
+ made $function[2] and $function[3] options for register_resource
+
+ * libs/Smarty.class.php:
+ fixed issue with object-callback when fetching a php-resource
+
+ * NEWS
+ libs/Smarty.class.php:
+ enabled array(&$obj. 'source', 'timestamp', 'secure', 'trusted') as
+ callback for register_resource()
+
+ enabled array(&$obj, 'method') as callback for
+ $default_template_handler_func
+
+2003-04-27 Messju Mohr <messju@lammfellpuschen.de>
+
+ * docs/designers.sgml
+ docs/programmers.sgml:
+ fixed some typos, thank to mehdi
+
+ * libs/plugins/function.counter.php:
+ prevent assign from overruling print-attribute in function.counter.php
+
+ * libs/plugins/function.counter.php:
+ fixed problem with counter and assign
+
+ * libs/Smarty.class.php:
+ fixed notice in _load_plugins()
+
+ * NEWS
+ libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php:
+ made plugin-names case-insensitive. this affects
+ compiler/block/custom-functions and modifers.
+
+2003-04-26 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ libs/Smarty_Compiler.class.php:
+ remove unnecessary close/open tags from compiled templates
+
+2003-04-26 Messju Mohr <messju@lammfellpuschen.de>
+
+ * docs/designers.sgml:
+ added documentation for foreach.property.*
+
+2003-04-24 Messju Mohr <messju@lammfellpuschen.de>
+
+ * docs/designers.sgml:
+ fixed example table_attr and tr_attr in html_table-example
+
+2003-04-21 Greg Beaver <greg@chiaraquartet.net>
+
+ * libs/Smarty.class.php:
+ fixed small bug in doc comments
+
+2003-04-21 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/plugins/function.html_image.php:
+ fixed errornous creation of '//' in image_path in html_image
+
+2003-04-21 Monte Ohrt <monte@ispi.net>
+
+ * libs/plugins/modifier.debug_print_var.php:
+ fix htmlspecialchars() conflict
+
+ * NEWS
+ libs/plugins/modifier.debug_print_var.php:
+ fix escapement of special chars in key values of debug console
+
+ * NEWS
+ libs/plugins/function.config_load.php:
+ fixed debug timing logic for config_load
+
+ * docs/designers.sgml:
+ fix example text
+
+
+2003-04-20 Greg Beaver <cellog@users.sourceforge.net>
+ * plugins/*
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ Config_File.class.php:
+ updated all doc comments to phpDocumentor format (whew!)
+
+2003-04-06 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/plugins/function.math.php:
+ allowed "_" in the name of variable-parameters to {math}-function
+
+2003-04-04 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ docs/designers.sgml
+ libs/Smarty_Compiler.class.php:
+ change backtic syntax from $`foo` to `$foo`
+
+ * NEWS
+ libs/Smarty_Compiler.class.php:
+ recognize $foo[][] syntax in embedded quotes without backticks
+
+2003-04-03 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/Smarty_Compiler.class.php:
+ name=123 is passed as an integer (not a string) to plugins now
+
+2003-04-01 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php:
+ added CVS $Id: ChangeLog,v 1.1 2005/10/17 18:37:38 jeichorn Exp $
+
+2003-03-31 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty.class.php:
+ added missing compile_id inside Smarty_Compiler
+
+ * libs/Smarty_Compiler.class.php:
+ fixed flaw when generating an error for missing postfilter
+
+2003-03-31 Monte Ohrt <monte@ispi.net>
+
+ * docs/getting-started.sgml
+ docs/programmers.sgml:
+ fix typos
+
+2003-03-27 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/plugins/modifier.debug_print_var.php:
+ $length is now propagated to sub-values in debug_print_var
+
+2003-03-26 Monte Ohrt <monte@ispi.net>
+
+ * NEWS:
+ update header
+
+ * RELEASE_NOTES:
+ commit changes to release notes
+
+ * (Smarty_2_5_0_RC2)
+ libs/Config_File.class.php
+ libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php:
+ committing RC2
+
+2003-03-24 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/Smarty.class.php:
+ made clear_cache() ignore compile_id when clearing cache_groups
+
+ * libs/plugins/function.popup.php:
+ made onmouseout XHTML-compatible in function.popup.php
+
+2003-03-21 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/Smarty.class.php:
+ applied new var-names to fetch()
+
+ * NEWS
+ libs/Smarty.class.php:
+ renamed $localvars to $_localvars in cache-file-handling-functions,
+ added _get_auto_id()-function
+
+2003-03-21 Monte Ohrt <monte@ispi.net>
+
+ * libs/plugins/function.mailto.php
+ libs/plugins/function.popup.php:
+ update functions for XHTML compatability
+
+2003-03-21 Messju Mohr <messju@lammfellpuschen.de>
+
+ * libs/Smarty.class.php:
+ fixed wrong $auto_id in _read_cache_file()
+
+ * NEWS
+ libs/Smarty.class.php:
+ swapped compile_id and cache_id in read_cache_file and write_cache_file
+
+ * libs/Smarty.class.php:
+ reverted patch for ignoring compile-id back to -r1.364, due to problems
+
+ * NEWS
+ libs/plugins/function.html_checkboxes.php
+ libs/plugins/function.html_radios.php:
+ html_radios and html_checkboxes accept "selected" instead of "checked"
+ optionally now
+
+ * NEWS
+ libs/Smarty.class.php:
+ swapped compile_id and cache_id for cache-file-handling again
+
+2003-03-20 Monte Ohrt <monte@ispi.net>
+
+ * libs/Smarty_Compiler.class.php:
+ fix notice when no parameter is passed to default
+
+2003-03-20 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/Smarty.class.php:
+ removed notice of undefined var in _rm_auto()
+
+2003-03-19 Monte Ohrt <monte@ispi.net>
+
+ * libs/plugins/function.html_checkboxes.php
+ libs/plugins/function.html_radios.php
+ libs/plugins/function.html_table.php:
+ fix a few error messages, follow consistancy format plugin_name: errormsg
+
+ * libs/plugins/function.html_radios.php:
+ update error messages
+
+ * NEWS
+ libs/plugins/function.html_radios.php:
+ add a warning when an array is passed as the 'checked' value of html_radios
+
+2003-03-19 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/Smarty_Compiler.class.php:
+ fixed errormessage in _compile_smarty_ref()
+
+ * NEWS
+ docs/designers.sgml:
+ updated docs for html_image
+
+2003-03-18 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/Smarty.class.php:
+ cleaned up calls to readdir()
+
+ * libs/plugins/function.html_options.php:
+ fixed label for optgroup in html_options
+
+2003-03-18 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ libs/Smarty_Compiler.class.php:
+ fix (newly introduced) bug with passing multiple modifiers to a parameter
+
+2003-03-18 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ docs/designers.sgml:
+ updated docs for html_checkboxes, html_options and html_radios
+
+ * libs/plugins/function.html_options.php:
+ fixed wrong default-"name" in function.html_options.php
+
+ * NEWS
+ libs/plugins/function.html_checkboxes.php
+ libs/plugins/function.html_radios.php:
+ renamed "checkbox" and "radios" to "options" in {html_checkboxes} and
+ {html_radios}
+
+ * libs/plugins/outputfilter.trimwhitespace.php:
+ tried to optimize re-replacement in outputfilter.trimwhitespace.php a
+ little
+
+ * libs/plugins/outputfilter.trimwhitespace.php:
+ fixed greedy str_replace in outputfilter.trimwhitespace.php
+
+ * NEWS
+ libs/plugins/function.html_checkboxes.php
+ libs/plugins/function.html_options.php
+ libs/plugins/function.html_radios.php:
+ html_options, html_checkboxes and html_radios now pass-thru all unknown
+ paramters
+
+2003-03-17 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/plugins/function.html_options.php:
+ html_options passthru all unknown paramters now
+
+2003-03-17 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ libs/plugins/function.html_image.php:
+ Fix link bug in html_image function, also make output XHTML compatible
+
+ * libs/Smarty_Compiler.class.php:
+ fix issue of embedded var and escaped double quotes
+
+2003-03-15 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ libs/Smarty_Compiler.class.php:
+ back out "@" logic, apply only to default modifier special case
+
+ * libs/Smarty_Compiler.class.php:
+ fix @ logic, only use upon an echo
+
+ * NEWS
+ libs/Smarty_Compiler.class.php:
+ append "@" to template var echoes to supress possible notices
+
+ * NEWS
+ libs/Smarty_Compiler.class.php:
+ append "@" to _run_mod_handler to supress warnings
+
+2003-03-14 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ libs/Smarty_Compiler.class.php:
+ fix problem with escaped double quotes
+
+ * NEWS
+ libs/plugins/function.html_radios.php:
+ fixed html_options to not return an array
+
+2003-03-12 Messju Mohr <messju@lammfellpuschen.de>
+
+ * NEWS
+ libs/plugins/modifier.truncate.php:
+ fixed length in modifier.truncate.php
+
+ * NEWS
+ libs/plugins/outputfilter.trimwhitespace.php:
+ fixed handling of '$'-signs in trimwhitespace outputfilter (messju)
+
+2003-03-12 Monte Ohrt <monte@ispi.net>
+
+ * docs/programmers.sgml:
+ update technical explanation of assign_by_ref and append_by_ref
+
+2003-03-11 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ libs/Smarty.class.php:
+ fix config file recompiling code
+
+2003-03-07 Monte Ohrt <monte@ispi.net>
+
+ * libs/plugins/function.html_image.php:
+ change E_USER_ERROR to E_USER_NOTICE
+
+ * libs/plugins/function.html_image.php:
+ suppress warning in html_image
+
+ * NEWS
+ libs/plugins/function.html_image.php:
+ update changes to html_image
+
+2003-03-06 Monte Ohrt <monte@ispi.net>
+
+ * docs/designers.sgml
+ docs/de/appendixes.sgml
+ docs/de/common.dsl
+ docs/de/designers.sgml
+ docs/de/getting-started.sgml
+ docs/de/html-common.dsl
+ docs/de/html.dsl
+ docs/de/manual.sgml
+ docs/de/preface.sgml
+ docs/de/programmers.sgml:
+ add german docs to dist
+
+ * NEWS:
+ update news file
+
+ * libs/plugins/function.html_image.php:
+ fix width/height parameter index
+
+ * NEWS
+ libs/Smarty.class.php:
+ get rid of unsetting name and script attributes to insert tags
+
+2003-03-05 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ RELEASE_NOTES:
+ update NEWS file
+
+ * libs/plugins/modifier.string_format.php:
+ fix argument order, erroneously swapped a while back
+
+ * (Smarty_2_5_0_RC1)
+ NEWS
+ README
+ RELEASE_NOTES
+ libs/Config_File.class.php
+ libs/Smarty.class.php
+ libs/Smarty_Compiler.class.php:
+ commit final changes for 2.5.0-RC1
+
+2003-03-04 Monte Ohrt <monte@ispi.net>
+
+ * docs/programmers.sgml:
+ remove $show_info_header and $show_info_include property vars from docs
+
+2003-03-03 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ libs/plugins/function.popup.php:
+ fixed PHP notice
+
+2003-02-28 Monte Ohrt <monte@ispi.net>
+
+ * libs/Smarty_Compiler.class.php:
+ simplify smarty.const.foo and smarty.const.$foo logic
+
+ * libs/Smarty_Compiler.class.php:
+ only allow $foo syntax in embedded quotes, unless escaped with backticks
+ then allow any dollar var
+
+ * NEWS
+ libs/Smarty_Compiler.class.php:
+ fix "once" var compiling to work with new attr compiling methods for
+ include_php
+
+ * FAQ
+ NEWS
+ README
+ docs/designers.sgml
+ docs/getting-started.sgml
+ libs/Smarty_Compiler.class.php
+ libs/plugins/function.html_checkboxes.php
+ libs/plugins/function.html_image.php
+ libs/plugins/function.html_options.php
+ libs/plugins/function.html_radios.php
+ libs/plugins/function.html_select_date.php
+ libs/plugins/function.html_select_time.php
+ libs/plugins/function.html_table.php:
+ fix $smarty.const.foo compiling, clean up double quoted strings,
+ allow full dollar var syntax in quotes again
+
+2003-02-27 Monte Ohrt <monte@ispi.net>
+
+ * docs/designers.sgml
+ docs/programmers.sgml
+ libs/Smarty_Compiler.class.php:
+ update docs, fix smarty var compiling, allow any $smarty.*.$foo syntax,
+ add $`foobar` for embedded variables
+
+ * libs/plugins/function.html_image.php:
+ update functionality
+
+2003-02-26 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ libs/plugins/modifier.nl2br.php:
+ add nl2br modifier
+
+ * libs/plugins/function.html_image.php:
+ add link parameter
+
+2003-02-24 Monte Ohrt <monte@ispi.net>
+
+ * libs/Smarty.class.php
+ libs/plugins/function.html_image.php:
+ fix rename problem in windows, unlink first
+
+ * libs/plugins/function.html_checkboxes.php
+ libs/plugins/function.html_image.php
+ libs/plugins/function.html_options.php
+ libs/plugins/function.html_radios.php
+ libs/plugins/shared.escape_special_chars.php:
+ update functions with separate escape_special_chars routine
+
+ * NEWS
+ libs/plugins/function.html_checkboxes.php
+ libs/plugins/function.html_radios.php:
+ commit checkboxes, update radios
+
+ * NEWS
+ libs/Smarty.class.php
+ libs/plugins/function.html_image.php:
+ fix bug with get_registered_object
+
+ * NEWS
+ libs/plugins/modifier.cat.php:
+ added cat modifier to distribution
+
+ * NEWS
+ libs/Smarty_Compiler.class.php:
+ added << >> <> support to IF statements
+
+ * libs/plugins/function.html_radios.php:
+ apply patch to initial html_radios function
+
+ * NEWS
+ libs/Smarty.class.php:
+ fix _assign_smarty_interface to not overwrite keys other than 'request'
+
+ * NEWS
+ libs/plugins/function.html_radios.php:
+ added html_radios to distribution
+
+ * NEWS
+ libs/plugins/modifier.string_format.php:
+ fixed arg order of string_format
+
+ * NEWS
+ libs/Smarty.class.php:
+ use tmp file for file writes, avoid race condition
+
+ * NEWS
+ libs/Smarty_Compiler.class.php:
+ add $smarty.config.foo var, handle embedded smarty var correctly
+
+ * NEWS
+ libs/plugins/function.fetch.php:
+ silence warnings in fetch plugin
+
+2003-02-21 Monte Ohrt <monte@ispi.net>
+
+ * INSTALL:
+ update wording
+
+ * INSTALL:
+ update install instructions
+
+ * AUTHORS
+ BUGS
+ CREDITS
+ QUICKSTART
+ README
+ RESOURCES
+ TESTIMONIALS:
+ remove some files already in docs or elsewhere
+
+ * demo/index.php:
+ add templates_c to repository
+
+ * index.php:
+ move demo files to demo directory
+
+ * Config_File.class.php
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ debug.tpl:
+ moved lib files under libs directory
+
+2003-02-20 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty.class.php:
+ add get_config_vars() method, update get_template_vars() functionality
+
+ * NEWS
+ Smarty.class.php:
+ fix minor logic in _fetch_template_info()
+
+ * NEWS
+ Smarty.class.php:
+ support merging appended vars
+
+ * NEWS
+ Smarty.class.php:
+ fix cache groups behavior with compile_id set
+
+2003-02-19 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php:
+ back out third parameter, extend functionality of append
+
+ * NEWS
+ Smarty_Compiler.class.php:
+ update imbedded vars, allow special $smarty vars
+
+ * plugins/function.html_table.php:
+ add plugin html_table
+
+ * NEWS
+ Smarty.class.php:
+ support appending key=>val pairs
+
+ * NEWS
+ Smarty_Compiler.class.php:
+ change embedded variable logic to only recognize $foo and $foo[0][bar]
+ syntax
+
+ * NEWS
+ Smarty_Compiler.class.php:
+ allow null as function attribute value
+
+2003-02-18 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php:
+ support foo->bar[index] syntax
+
+ * Smarty_Compiler.class.php:
+ allow $foo->bar[0] syntax
+
+2003-02-17 Monte Ohrt <monte@ispi.net>
+
+ * plugins/modifier.escape.php:
+ fix syntax error from previous commit
+
+ * NEWS
+ Smarty.class.php:
+ add error msgs to get_registered_object
+
+ * Smarty.class.php:
+ add function for getting reference to registered object
+
+ * Smarty_Compiler.class.php:
+ back out patches for object and objref calls on $smarty var
+
+ * NEWS
+ Smarty_Compiler.class.php:
+ treat unrecognized param attribute syntax as a string
+
+ * NEWS
+ Smarty_Compiler.class.php:
+ support $smarty.const.$foo syntax
+
+ * NEWS
+ debug.tpl
+ plugins/modifier.count_words.php
+ plugins/modifier.escape.php:
+ fix E_NOTICE messages
+
+ * NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php:
+ add @ and === to if tokens, few param cleanups
+
+2003-02-16 Greg Beaver <greg@chiaraquartet.net>
+
+ * ChangeLog
+ Smarty.class.php
+ Smarty_Compiler.class.php:
+ many more phpdoc comment upgrades
+
+2003-02-15 Greg Beaver <cellog@sourceforge.net>
+ * Smarty.class.php
+ Smarty_Compiler.class.php
+ continue cleaning of phpdoc comments. All that is needed is the
+ addition of @return tags and perhaps a bit more verbose comments
+ and they are finished.
+
+2003-02-14 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty.class.php:
+ enable config_load error messages
+
+ * NEWS
+ plugins/function.html_options.php:
+ fix html_options to not escape already escaped entities
+
+ * NEWS
+ Smarty.class.php:
+ send Last-Modified header on cache creation, misc tab/spacing cleanup
+
+2003-02-13 Monte Ohrt <monte@ispi.net>
+
+ * Smarty_Compiler.class.php
+ docs/designers.sgml:
+ allow dash in plain text
+
+ * NEWS
+ Smarty_Compiler.class.php:
+ check strict syntax of function attributes
+
+2003-02-12 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty_Compiler.class.php:
+ dropped support for modifiers on object parameters,
+ added support for objects as modifier parameters
+
+ * NEWS
+ Smarty_Compiler.class.php
+ docs/designers.sgml:
+ fix bug with decimal numbers in if statements, misc doc updates
+
+2003-02-11 Monte Ohrt <monte@ispi.net>
+
+ * (Smarty_2_4_2)
+ Config_File.class.php
+ NEWS
+ README
+ RELEASE_NOTES
+ Smarty.class.php
+ Smarty_Compiler.class.php:
+ update version numbers
+
+2003-02-10 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty_Compiler.class.php:
+ add support for $foo->$bar syntax
+
+ * NEWS:
+ update NEWS file
+
+ * NEWS
+ Smarty_Compiler.class.php:
+ support full var syntax in quoted text, fix problem with const var access,
+ clean up some more regex code, fix object problem with no properties
+
+2003-02-06 Monte Ohrt <monte@ispi.net>
+
+ * (Smarty_2_4_1)
+ Config_File.class.php
+ NEWS
+ README
+ RELEASE_NOTES
+ Smarty.class.php
+ Smarty_Compiler.class.php:
+ committed 2.4.1 changes
+
+ * NEWS
+ Smarty_Compiler.class.php:
+ ignore case in IF statements
+
+2003-02-05 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty_Compiler.class.php:
+ treat undefined constants as null
+
+ * NEWS
+ Smarty.class.php:
+ fix problem with inserts and nested fetches
+
+ * Smarty_Compiler.class.php:
+ fix "if" regex for math tokens
+
+ * NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ docs/getting-started.sgml:
+ added support for extracting params to include_php
+
+2003-02-04 Monte Ohrt <monte@ispi.net>
+
+ * RELEASE_NOTES:
+ reformat text
+
+2003-02-03 Monte Ohrt <monte@ispi.net>
+
+ * NEWS:
+ update news file
+
+2003-02-03 Greg Beaver <greg@chiaraquartet.net>
+
+ * ChangeLog
+ Smarty.class.php:
+ begin fixing phpdoc comments in Smarty.class.php
+
+ * ChangeLog
+ Config_File.class.php:
+ fixed phpdoc comments
+
+2003-02-03 Monte Ohrt <monte@ispi.net>
+
+ * Smarty_Compiler.class.php:
+ allow $foo->bar[$x].foo syntax
+
+ * Smarty_Compiler.class.php
+ index.php
+ configs/test.conf
+ templates/index.tpl:
+ fix accidental commit
+
+ * index.php
+ configs/test.conf
+ templates/index.tpl:
+ allow $foo->bar[$j].blah type of syntax
+
+2003-02-02 Greg Beaver <cellog@php.net>
+
+ * Smarty.class.php
+ begin fixing of phpdoc comments
+
+ * Config_File.class.php
+ fix phpdoc comments, add phpDocumentor docblock templates
+
+2003-02-02 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php
+ docs/html.dsl
+ docs/php.dsl:
+ fix version number
+
+ * (Smarty_2_4_0)
+ Config_File.class.php
+ NEWS
+ README
+ RELEASE_NOTES
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ docs/appendixes.sgml
+ docs/designers.sgml
+ docs/programmers.sgml:
+ update Smarty version numbers
+
+2003-01-30 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty_Compiler.class.php
+ TODO:
+ fix order of php tag comparisons
+
+ * NEWS
+ Smarty_Compiler.class.php:
+ fix known php tag handling problems
+
+2003-01-29 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php
+ Smarty_Compiler.class.php:
+ change comments to phpdoc style
+
+2003-01-28 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php
+ docs/programmers.sgml:
+ make separate var for compiler file
+
+ * plugins/function.fetch.php:
+ fix error call
+
+2003-01-25 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php
+ Smarty_Compiler.class.php:
+ add support for restriction to registered methods
+
+ * plugins/outputfilter.trimwhitespace.php:
+ update with textarea support
+
+2003-01-24 Monte Ohrt <monte@ispi.net>
+
+ * Smarty_Compiler.class.php:
+ fix compiling problem with {foreach} tags
+
+ * Smarty.class.php
+ Smarty_Compiler.class.php:
+ put objects in own array, add object param format support, change
+ object syntax from foo.bar to foo->bar
+
+2003-01-23 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php:
+ add support for object registration
+
+2003-01-22 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php:
+ add file & line number of calling error to error message
+
+2003-01-21 Monte Ohrt <monte@ispi.net>
+
+ * Smarty_Compiler.class.php:
+ put php style object syntax back in
+
+2003-01-20 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php:
+ move security settings to fetch function for template_dir
+
+ * NEWS
+ Smarty.class.php:
+ fix debug template and security, add template_dir to secure_dir at runtime
+
+2003-01-17 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php:
+ added new object support without new template syntax
+
+2003-01-15 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php:
+ fix if statement syntax for negative integers, fix issue with directories
+ named '0'
+
+2003-01-08 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php
+ plugins/function.counter.php
+ plugins/function.cycle.php
+ plugins/function.debug.php
+ plugins/function.eval.php
+ plugins/function.fetch.php
+ plugins/function.html_options.php
+ plugins/function.html_select_date.php
+ plugins/function.html_select_time.php
+ plugins/function.mailto.php
+ plugins/function.math.php
+ plugins/function.popup.php
+ plugins/function.popup_init.php:
+ update plugins to return values instead of echo, fix config file cache
+ to include global config variables in cache file
+
+ * Smarty_Compiler.class.php:
+ fix bug with >= tests in if statements, comment out full object support
+
+2003-01-06 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ docs/html.dsl
+ plugins/modifier.escape.php:
+ add javascript escape parameter to escape modifier
+
+2003-01-02 Monte Ohrt <monte@ispi.net>
+
+ * templates/header.tpl:
+ move the title into head where it should be
+
+2002-12-24 Monte Ohrt <monte@ispi.net>
+
+ * Smarty_Compiler.class.php:
+ added correct line numbers to smarty syntax error messages
+
+ * docs/programmers.sgml:
+ update append documentation, make more clear on its function
+
+ * Smarty_Compiler.class.php:
+ fix modifier matching regexp
+
+2002-12-23 Monte Ohrt <monte@ispi.net>
+
+ * Smarty_Compiler.class.php:
+ support nested function calls in IF statements
+
+2002-12-20 Monte Ohrt <monte@ispi.net>
+
+ * Smarty_Compiler.class.php:
+ few more fixes, spaces around function parameters
+
+ * Smarty_Compiler.class.php:
+ fix misc syntax issues with {if} tags
+
+2002-12-20 Monte Ohrt <monte@ispi.net>
+
+ * Smarty_Compiler.class.php:
+ fix misc syntax issues with {if} tags
+
+2002-12-19 Monte Ohrt <monte@ispi.net>
+
+ * Smarty_Compiler.class.php:
+ commit updates, passes all smoke tests
+
+ * NEWS:
+ update NEWS file
+
+ * Smarty_Compiler.class.php:
+ fixed literal string not in quotes as parameters
+
+ * NEWS
+ Smarty_Compiler.class.php:
+ fix misc syntax issues, add ability to pass modifiers to functions
+
+2002-12-18 Monte Ohrt <monte@ispi.net>
+
+ * NEWS:
+ update NEWS
+
+ * NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php:
+ update compiler code, clean up regex, add new syntax features
+
+2002-12-16 Monte Ohrt <monte@ispi.net>
+
+ * NEWS:
+ update NEWS file
+
+ * Smarty_Compiler.class.php:
+ commit updates for objects
+
+2002-12-14 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php
+ Smarty_Compiler.class.php:
+ fix bug with compiling config files with caching on
+
+2002-12-13 Monte Ohrt <monte@ispi.net>
+
+ * Smarty_Compiler.class.php:
+ fix problem with matching single quoted strings
+
+ * Smarty_Compiler.class.php:
+ update embedded variable logic, get rid of ."" at end of output
+
+ * NEWS
+ docs/designers.sgml
+ plugins/function.html_select_date.php:
+ add day_value_format to html_select_date
+
+2002-12-12 Monte Ohrt <monte@ispi.net>
+
+ * plugins/modifier.debug_print_var.php:
+ fix bug, double escaped values in display
+
+ * Smarty.class.php:
+ move debug test back into fetch()
+
+ * NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ plugins/outputfilter.trimwhitespace.php:
+ assigned vars are no longer in global name space, few debug cleanups
+
+2002-12-11 Monte Ohrt <monte@ispi.net>
+
+ * plugins/function.popup.php:
+ fix error in newline code
+
+ * plugins/function.popup.php:
+ fix popup to allow newlines in text data
+
+2002-12-10 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php:
+ fix plugin error logic
+
+ * docs/designers.sgml
+ docs/programmers.sgml:
+ edit examples, make more verbose
+
+ * NEWS
+ plugins/function.html_options.php:
+ escape html entities in the option values and output
+
+ * NEWS
+ plugins/function.html_options.php:
+ fixed bug with label of html_options
+
+2002-12-09 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php:
+ add support for var_export()
+
+ * Config_File.class.php
+ Smarty.class.php:
+ clean up code, respect force_compile and compile_check flags
+
+ * NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ docs/designers.sgml
+ plugins/function.mailto.php:
+ add caching feature to config loading, document update, add mailto plugin
+
+2002-12-08 Monte Ohrt <monte@ispi.net>
+
+ * plugins/function.fetch.php:
+ fix query part of URL
+
+2002-12-05 Monte Ohrt <monte@ispi.net>
+
+ * docs/designers.sgml:
+ fix typos
+
+2002-11-22 Monte Ohrt <monte@ispi.net>
+
+ * Smarty_Compiler.class.php:
+ patch for warning message
+
+2002-11-21 Monte Ohrt <monte@ispi.net>
+
+ * RELEASE_NOTES
+ Smarty.class.php:
+ get rid of testing for a set value with assign function, just set to
+ whatever is passed into the template
+
+ * docs/programmers.sgml:
+ fix typo
+
+2002-11-19 Monte Ohrt <monte@ispi.net>
+
+ * Config_File.class.php
+ NEWS
+ README
+ RELEASE_NOTES
+ Smarty.class.php
+ Smarty_Compiler.class.php:
+ commit changes, ready for 2.3.1 release
+
+2002-11-01 Monte Ohrt <monte@ispi.net>
+
+ * plugins/function.html_options.php:
+ added label attribute to all option outputs, cover w3c spec.
+
+ * NEWS: update NEWS file
+
+ * docs/designers.sgml: update docs for optgroup output
+
+ * plugins/function.html_options.php:
+ make html_options work with optgroup, make func modular and recursive.
+
+2002-10-29 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty.class.php: set mtime on compile files so they match source files
+
+2002-10-18 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty.class.php: added proper support for open_basedir setting
+
+ * docs/designers.sgml: clear up docs on index, iteration and rownum
+
+2002-10-16 Monte Ohrt <monte@ispi.net>
+
+ * plugins/modifier.default.php: fix warning message in default modifier
+
+2002-09-25 Monte Ohrt <monte@ispi.net>
+
+ * docs/designers.sgml
+ plugins/modifier.strip.php
+ NEWS: added strip variable modifier
+
+2002-09-24 Andrei Zmievski <andrei@php.net>
+
+ * NEWS: *** empty log message ***
+
+ * Smarty_Compiler.class.php:
+ Fix to be able to use $smarty.x variables as arrays.
+
+2002-09-23 Monte Ohrt <monte@ispi.net>
+
+ * Config_File.class.php:
+ add support for mac/dos formatted config files (fix newlines)
+
+ * docs/programmers.sgml: add optional tags to clear_cache parameters
+
+ * docs/designers.sgml:
+ fix error with include_php description, add $this to description
+
+2002-09-20 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ docs/getting-started.sgml: fixed errors with example setup docs
+
+2002-09-16 Monte Ohrt <monte@ispi.net>
+
+ * plugins/block.textformat.php
+ docs/designers.sgml
+ NEWS: add textformat block function
+
+2002-09-10 Monte Ohrt <monte@ispi.net>
+
+ * docs/designers.sgml:
+ add assign attribute to cycle function documentation
+
+ * docs/designers.sgml
+ docs/programmers.sgml: fix typos
+
+2002-09-09 Monte Ohrt <monte@ispi.net>
+
+ * plugins/function.debug.php
+ templates/header.tpl:
+ fix header in debug template, fix typo in header.tpl example
+
+2002-08-15 mohrt <mohrt@pb1.pair.com>
+
+ * docs/programmers.sgml: fix typos
+
+2002-08-08 mohrt <mohrt@pb1.pair.com>
+
+ * RELEASE_NOTES
+ Smarty.class.php:
+ supress warnings from unlink() and is_dir(), let error handler deal with it
+
+2002-08-07 mohrt <mohrt@pb1.pair.com>
+
+ * docs/appendixes.sgml
+ docs/designers.sgml
+ docs/programmers.sgml
+ Config_File.class.php
+ NEWS
+ README
+ RELEASE_NOTES
+ Smarty.class.php
+ Smarty_Compiler.class.php: update files with new version numbers
+
+2002-08-02 mohrt <mohrt@pb1.pair.com>
+
+ * NEWS: update NEWS file with credits
+
+ * NEWS
+ Smarty.class.php: added assign_by_ref() and append_by_ref() functions
+
+2002-08-01 mohrt <mohrt@pb1.pair.com>
+
+ * TODO
+ NEWS
+ Smarty.class.php:
+ changed default warning type for plugin errors from E_USER_WARNING to E_USER_ERROR
+
+2002-07-29 mohrt <mohrt@pb1.pair.com>
+
+ * plugins/function.html_select_time.php
+ docs/designers.sgml
+ NEWS: added paramters to html_select_time plugin
+
+2002-07-25 Andrei Zmievski <andrei@pb1.pair.com>
+
+ * TODO: *** empty log message ***
+
+2002-07-24 mohrt <mohrt@pb1.pair.com>
+
+ * QUICKSTART: update QUICKSTART guide
+
+ * NEWS
+ debug.tpl
+ plugins/modifier.debug_print_var.php:
+ update debug console to show objects, fix warning in debug.tpl
+
+2002-07-23 mohrt <mohrt@pb1.pair.com>
+
+ * docs/programmers.sgml: fix load_filter examples
+
+ * Config_File.class.php
+ NEWS: fix error when there are no sections in config file
+
+2002-07-19 mohrt <mohrt@pb1.pair.com>
+
+ * docs/getting-started.sgml: fix error in install guide
+
+2002-07-18 mohrt <mohrt@pb1.pair.com>
+
+ * Smarty_Compiler.class.php:
+ correct the expression match for smarty:nodefaults
+
+2002-07-17 mohrt <mohrt@pb1.pair.com>
+
+ * Smarty_Compiler.class.php: fix default modifier to work with config vars
+
+ * Smarty_Compiler.class.php: got args to strstr backwards...
+
+ * NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php:
+ change default modifiers to array instead of string
+
+ * Smarty_Compiler.class.php
+ docs/designers.sgml
+ Smarty.class.php: add default modifier logic, minor doc updates
+
+ * NEWS
+ Smarty.class.php
+ plugins/function.popup_init.php:
+ make popup_init xhtml compliant, minor variable name changes for consistancy
+
+2002-07-16 mohrt <mohrt@pb1.pair.com>
+
+ * NEWS: update NEWS file
+
+ * plugins/function.debug.php
+ Smarty.class.php
+ debug.tpl
+ NEWS:
+ fix problem with filenames on windows, add ability to supply expire time in seconds when clearing cache or compiled files
+
+2002-07-15 mohrt <mohrt@pb1.pair.com>
+
+ * Smarty.class.php:
+ fixed problem with insert tags when loading function from script attribute
+ and caching enabled (Monte)
+
+2002-07-14 mohrt <mohrt@pb1.pair.com>
+
+ * NEWS
+ Smarty.class.php: fix bug with debug_tpl file path for Windows
+
+2002-07-12 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php: fix append function with array/string issue
+
+2002-07-11 Monte Ohrt <monte@ispi.net>
+
+ * RELEASE_NOTES: update release notes
+
+ * NEWS
+ README
+ RELEASE_NOTES
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ Config_File.class.php: update files to 2.2.0 tags, get ready for release
+
+2002-07-09 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty.class.php: make debug.tpl work with any delimiter
+
+ * NEWS
+ Smarty.class.php:
+ change tests in append and assign to != '' instead of empty(), which is more accurate
+
+2002-07-08 Monte Ohrt <monte@ispi.net>
+
+ * docs/designers.sgml: minor doc update
+
+ * Smarty.class.php:
+ cast var as an array, simplify and get rid of PHP warning messages
+
+2002-07-03 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php: one more N
+
+ * Smarty.class.php:
+ prepend "N" to filenames to avoid possible OS issues with dir names starting with "-"
+
+ * Smarty.class.php: only set $debug_tpl in constructor if empty
+
+ * Smarty.class.php
+ docs/designers.sgml
+ docs/getting-started.sgml
+ docs/programmers.sgml:
+ make use_sub_dirs go back to crc32 for subdir separation
+
+2002-06-29 Monte Ohrt <monte@ispi.net>
+
+ * plugins/function.eval.php: do nothing if $val is empty
+
+ * TODO
+ plugins/function.eval.php
+ plugins/function.popup_init.php:
+ add zindex to popup init, fix error message for eval.
+
+2002-06-27 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php:
+ only loop through relative paths for PHP include_path, remove $_relative variable
+
+ * Smarty_Compiler.class.php: added {$smarty.version} variable
+
+2002-06-26 Monte Ohrt <monte@ispi.net>
+
+ * docs/appendixes.sgml
+ docs/designers.sgml
+ docs/getting-started.sgml
+ docs/programmers.sgml
+ Smarty.class.php:
+ update plugin loading logic, look in SMARTY_DIR, then cwd. If all fail, then retry all with include_path
+
+ * templates/header.tpl
+ Smarty.class.php: update get_include_path, get _path_array only once
+
+ * Smarty.class.php: fix get_include_path function for windows
+
+ * Smarty.class.php: update plugin search logic
+
+ * Smarty.class.php: only search include_path if relative path
+
+ * plugins/function.html_select_date.php
+ plugins/function.html_select_time.php
+ plugins/modifier.date_format.php
+ Smarty_Compiler.class.php
+ NEWS
+ Smarty.class.php: allow plugins_dir to be an array of directories
+
+2002-06-25 Monte Ohrt <monte@ispi.net>
+
+ * docs/programmers.sgml
+ docs/getting-started.sgml: update installation docs
+
+ * debug.tpl
+ docs/getting-started.sgml
+ templates/debug.tpl
+ NEWS
+ Smarty.class.php: move debug.tpl to SMARTY_DIR, add to constructor
+
+2002-06-24 Monte Ohrt <monte@ispi.net>
+
+ * plugins/function.assign_debug_info.php
+ NEWS: fixed warning message in function.assign_debug_info
+
+ * Smarty.class.php: update include_path fixes
+
+ * NEWS:
+ fixed $template_dir, $compile_dir, $cache_dir, $config_dir to respect include_path
+
+2002-06-23 Monte Ohrt <monte@ispi.net>
+
+ * plugins/shared.make_timestamp.php:
+ update timestamp plugin to work when passed a timestamp
+
+2002-06-19 Monte Ohrt <monte@ispi.net>
+
+ * NEWS: update NEWS file
+
+ * plugins/modifier.date_format.php
+ docs/designers.sgml:
+ update date_format, allow optional 2nd paramater as default date if passed date is empty. update docs.
+
+ * plugins/modifier.date_format.php:
+ fix date_format modifier, return nothing if given empty string
+
+2002-06-18 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ plugins/function.cycle.php:
+ gave $reset a default value in cycle function
+
+ * plugins/function.html_select_date.php
+ plugins/shared.make_timestamp.php
+ NEWS:
+ corrected warnings in html_select_time function, made make timestamp always return a timestamp
+
+2002-06-17 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php: swapped around cache_id and compile_id order
+
+2002-06-14 Monte Ohrt <monte@ispi.net>
+
+ * docs/programmers.sgml
+ plugins/function.popup_init.php
+ Smarty.class.php:
+ change directory delimiter to "^" for cache and compile files
+
+2002-06-13 Andrei Zmievski <andrei@php.net>
+
+ * TODO: done.
+
+ * Smarty_Compiler.class.php:
+ Optimize the calculation of section 'total' property.
+
+2002-06-11 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty.class.php:
+ added support for subdir exclusion, deletion by full or partial cache_id and compile_id, change file format to urlencoded values instead of crc32
+
+2002-06-07 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php: fix bug with last_modified_check code
+
+ * NEWS
+ Smarty.class.php:
+ updated $GLOBALS refererence for HTTP_IF_MODIFIED_SINCE
+
+2002-06-06 Monte Ohrt <monte@ispi.net>
+
+ * docs/designers.sgml
+ overlib.js:
+ remove overlib.js file from distribution, update plugin and docs
+
+2002-06-05 Monte Ohrt <monte@ispi.net>
+
+ * docs/designers.sgml
+ NEWS
+ Smarty.class.php: fix 304 Not Modified, don't send content
+
+2002-06-03 Monte Ohrt <monte@ispi.net>
+
+ * plugins/function.cycle.php: update version number
+
+ * plugins/function.cycle.php
+ NEWS:
+ fixed cycle function to respect delimiter setting after initial setting
+
+ * Smarty.class.php
+ NEWS:
+ update $GLOBALS references to work properly with track_globals settings
+
+ * plugins/function.math.php: fixed bug with call $assign
+
+ * docs/appendixes.sgml
+ docs/designers.sgml
+ plugins/function.html_options.php
+ plugins/function.html_select_time.php
+ NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php:
+ optimized for loops with count() function calls
+
+2002-06-01 Andrei Zmievski <andrei@php.net>
+
+ * TODO: *** empty log message ***
+
+2002-05-21 Monte Ohrt <monte@ispi.net>
+
+ * NEWS: update NEWS file
+
+ * plugins/function.html_select_date.php
+ RESOURCES
+ docs/designers.sgml
+ Config_File.class.php:
+ update html_select_date with month_value_format attribute for controlling the format of the month values.
+
+2002-05-17 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty_Compiler.class.php:
+ Made it possible to use simple variables inside [] for indexing.
+
+2002-05-16 Monte Ohrt <monte@ispi.net>
+
+ * docs/designers.sgml
+ docs/getting-started.sgml
+ NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ TESTIMONIALS: add "once" attribute to php_include, update docs
+
+2002-05-09 Andrei Zmievski <andrei@ispi.net>
+
+ * NEWS
+ TODO: *** empty log message ***
+
+2002-05-07 Monte Ohrt <monte@ispi.net>
+
+ * plugins/function.cycle.php: remove \n from cycle function
+
+ * docs/designers.sgml
+ plugins/function.cycle.php
+ README
+ RELEASE_NOTES
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ NEWS:
+ update cycle function to handle array as input, update files to 2.1.1
+
+2002-05-06 Monte Ohrt <monte@ispi.net>
+
+ * plugins/function.fetch.php:
+ update fetch function with more error checking
+
+2002-05-03 Monte Ohrt <monte@ispi.net>
+
+ * docs/designers.sgml
+ plugins/function.counter.php:
+ update counter to use name instead of id (id still works though)
+
+ * plugins/function.cycle.php
+ docs/designers.sgml: rename id to name for cycle function
+
+ * plugins/function.cycle.php:
+ update cycle function to allow blank values parameter after initialized
+
+ * plugins/function.cycle.php: fix syntax error
+
+2002-05-02 Monte Ohrt <monte@ispi.net>
+
+ * plugins/function.cycle.php: ugh, another typo
+
+ * plugins/function.cycle.php: update comments
+
+ * docs/designers.sgml
+ plugins/function.cycle.php
+ NEWS: added function cycle
+
+ * FAQ
+ Smarty.class.php: fix register_outputfilter function
+
+2002-05-01 Monte Ohrt <monte@ispi.net>
+
+ * docs/designers.sgml
+ NEWS
+ Smarty.class.php: fixed bug with resource testing and include_path
+
+2002-04-30 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ README
+ RELEASE_NOTES
+ Smarty.class.php
+ Smarty_Compiler.class.php: update files for 2.1.0 release
+
+2002-04-30 Andrei Zmievski <andrei@ispi.net>
+
+ * plugins/function.fetch.php
+ docs/programmers.sgml
+ Smarty.class.php: Fix.
+
+2002-04-29 Andrei Zmievski <andrei@ispi.net>
+
+ * docs/programmers.sgml
+ docs/designers.sgml: A whole bunch of docs.
+
+2002-04-26 Monte Ohrt <monte@ispi.net>
+
+ * FAQ
+ QUICKSTART
+ docs/programmers.sgml: update FAQ, QUICKSTART, small doc syntax fix
+
+2002-04-24 Monte Ohrt <monte@ispi.net>
+
+ * docs/programmers.sgml
+ templates/debug.tpl
+ Smarty.class.php: changed doc structure a bit
+
+2002-04-16 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php: Add register/unregister API for output filters.
+
+ * NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ TODO:
+ Changed the way filters are loaded, which now has to be done explicitly,
+ either through load_filter() API or by filling in $autoload_filters variable.
+ Also renamed internal variable to avoid namespace pollution.
+
+2002-04-15 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php:
+ Fixed _get_php_resource() to take include_path into account.
+
+2002-04-15 Monte Ohrt <monte@ispi.net>
+
+ * docs/designers.sgml:
+ update docs, get modifiers and functions into index for easy access
+
+ * docs/programmers.sgml
+ NEWS
+ Smarty.class.php: update caching documentation
+
+2002-04-15 Andrei Zmievski <andrei@php.net>
+
+ * NEWS: *** empty log message ***
+
+ * Smarty.class.php: Only turn down error notices if $debugging is false.
+
+2002-04-15 Monte Ohrt <monte@ispi.net>
+
+ * NEWS: update NEWS file
+
+ * plugins/function.html_select_date.php:
+ fixed logic so this works right when field_separator = "/"
+
+ * plugins/function.html_select_date.php:
+ fix regular expression for matching date
+
+2002-04-13 Monte Ohrt <monte@ispi.net>
+
+ * docs/designers.sgml: updated html_select_date docs to reflect changes
+
+ * NEWS
+ plugins/function.html_select_date.php:
+ added YYYY-MM-DD support to html_select_date
+
+2002-04-12 Andrei Zmievski <andrei@php.net>
+
+ * TESTIMONIALS: New entry.
+
+2002-04-12 Monte Ohrt <monte@ispi.net>
+
+ * plugins/modifier.strip_tags.php: back out changes to strip_tags
+
+ * docs/programmers.sgml: update docs regarding cache_lifetime
+
+ * plugins/modifier.strip_tags.php
+ Smarty.class.php:
+ update cache_lifetime logic: -1 = never expire, 0 = always expire
+
+2002-04-11 Andrei Zmievski <andrei@php.net>
+
+ * BUGS
+ FAQ
+ INSTALL
+ NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ docs/getting-started.sgml:
+ Fixed directory separtor issue. Requiring PHP 4.0.6 now.
+
+ * NEWS
+ Smarty_Compiler.class.php:
+ Added ability to use simple variables for array indices or object properties.
+
+ * TESTIMONIALS: Another one.
+
+ * TESTIMONIALS: Adding one from Mark P.
+
+2002-04-05 Andrei Zmievski <andrei@php.net>
+
+ * Smarty_Compiler.class.php
+ NEWS
+ Smarty.class.php: Make it possible to unregister pre/postfilter plugins.
+
+2002-04-05 Monte Ohrt <monte@ispi.net>
+
+ * INSTALL: Remove addons file from INSTALL instructions
+
+2002-04-04 Monte Ohrt <monte@ispi.net>
+
+ * docs/designers.sgml: update doc error
+
+ * docs/designers.sgml
+ plugins/modifier.escape.php
+ NEWS
+ Smarty.class.php: added htmlall attribute to escape modifier
+
+2002-04-03 Andrei Zmievski <andrei@php.net>
+
+ * Smarty_Compiler.class.php: Fixed undefined offset warning in {if} tag.
+
+ * Smarty.class.php
+ NEWS: Added template_exists() API.
+
+ * Smarty.class.php
+ Smarty_Compiler.class.php
+ NEWS:
+ - Added $smarty.template variable.
+ - Fixed {include_php} tag when dynamic values were used for 'file' attribute.
+
+ * Config_File.class.php: Separator setting fix.
+
+2002-03-28 Monte Ohrt <monte@ispi.net>
+
+ * FAQ
+ README: add digest address
+
+ * FAQ
+ README
+ Smarty.class.php: update mailing list addresses
+
+2002-03-28 Andrei Zmievski <andrei@php.net>
+
+ * NEWS: *** empty log message ***
+
+ * plugins/function.html_select_date.php
+ plugins/function.html_select_time.php
+ plugins/modifier.date_format.php:
+ Fix for when plugins directory is not the default one.
+
+2002-03-28 Andrei Zmievski <andrei@ispi.net>
+
+ * NEWS: *** empty log message ***
+
+ * plugins/function.html_select_date.php
+ plugins/function.html_select_time.php
+ plugins/modifier.date_format.php:
+ Fix for when plugins directory is not the default one.
+
+2002-03-27 Monte Ohrt <monte@ispi.net>
+
+ * FAQ: update FAQ page
+
+2002-03-26 Andrei Zmievski <andrei@ispi.net>
+
+ * CREDITS
+ NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ TODO: Block functions changes.
+
+ * Config_File.class.php: *** empty log message ***
+
+2002-03-25 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php
+ Smarty_Compiler.class.php: Initial implementation of block functions.
+
+2002-03-22 Monte Ohrt <monte@ispi.net>
+
+ * docs/designers.sgml: fix documentation error in capture
+
+2002-03-22 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php: *** empty log message ***
+
+ * Smarty.class.php: Turn off notices.
+
+2002-03-21 Andrei Zmievski <andrei@php.net>
+
+ * Smarty_Compiler.class.php: Make _current_file available to prefilters.
+
+ * NEWS
+ Smarty.class.php:
+ Made is possible to assign variables in pre/postfilters.
+
+2002-03-20 Andrei Zmievski <andrei@php.net>
+
+ * plugins/function.html_select_date.php: Fixed +/- functionality.
+
+ * NEWS: *** empty log message ***
+
+2002-03-20 Monte Ohrt <monte@ispi.net>
+
+ * Config_File.class.php
+ NEWS
+ README
+ RELEASE_NOTES
+ Smarty.class.php
+ Smarty_Compiler.class.php: update version numbers
+
+ * plugins/function.html_select_date.php
+ plugins/function.html_select_time.php
+ plugins/modifier.date_format.php:
+ move .make_timestamp.php to shared.make_timestamp.php
+
+ * NEWS
+ Smarty.class.php
+ docs/designers.sgml
+ plugins/function.fetch.php
+ plugins/function.html_select_date.php:
+ update file generation, replace crc32() '-' with 'N'
+
+2002-03-20 Andrei Zmievski <andrei@php.net>
+
+ * Smarty_Compiler.class.php: *** empty log message ***
+
+2002-03-19 Andrei Zmievski <andrei@php.net>
+
+ * NEWS: *** empty log message ***
+
+ * Smarty.class.php
+ Smarty_Compiler.class.php:
+ Fix plugin behavior for inserts with script attribute.
+
+ * NEWS: *** empty log message ***
+
+ * Smarty_Compiler.class.php: Fix bug with $smarty.cookies.
+
+ * TESTIMONIALS: *** empty log message ***
+
+2002-03-15 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ docs/designers.sgml: update Changelog
+
+ * plugins/modifier.indent.php
+ plugins/modifier.wordwrap.php: add wordwrap and indent to repository
+
+2002-03-14 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php:
+ remove show_info_include and show_info_header functions
+
+2002-03-13 Monte Ohrt <monte@ispi.net>
+
+ * plugins/function.fetch.php: update fetch function
+
+ * plugins/function.fetch.php: update fetch function with new parameters
+
+2002-03-12 Monte Ohrt <monte@ispi.net>
+
+ * docs/designers.sgml: update doc tables
+
+ * docs/designers.sgml: update docs columns
+
+ * docs/getting-started.sgml
+ docs/appendixes.sgml: update docs
+
+ * TESTIMONIALS
+ docs/appendixes.sgml: update syntax error in docs, add to testimonials
+
+2002-03-04 Monte Ohrt <monte@ispi.net>
+
+ * FAQ
+ README: update FAQ, README with digest mode info
+
+2002-03-02 Monte Ohrt <monte@ispi.net>
+
+ * QUICKSTART: update quickstart
+
+ * Smarty.class.php:
+ change behavior so cache_lifetime = 0 never expires (instead of always regenerate)
+
+2002-03-01 Monte Ohrt <monte@ispi.net>
+
+ * docs/designers.sgml: update doc example
+
+2002-03-01 Andrei Zmievski <andrei@php.net>
+
+ * CREDITS
+ RELEASE_NOTES
+ TODO
+ NEWS: *** empty log message ***
+
+2002-03-01 Monte Ohrt <monte@ispi.net>
+
+ * docs/appendixes.sgml
+ docs/designers.sgml
+ docs/getting-started.sgml
+ docs/programmers.sgml: update document id tags
+
+ * docs.sgml: remove docs.sgml
+
+ * RESOURCES
+ Smarty.class.php: update resources
+
+2002-02-28 Andrei Zmievski <andrei@php.net>
+
+ * TESTIMONIALS
+ docs/appendixes.sgml
+ docs/designers.sgml
+ docs/programmers.sgml: *** empty log message ***
+
+2002-02-27 Andrei Zmievski <andrei@php.net>
+
+ * plugins/function.eval.php
+ docs/designers.sgml: *** empty log message ***
+
+2002-02-27 Monte Ohrt <monte@ispi.net>
+
+ * plugins/function.eval.php: added eval function to plugin dir
+
+2002-02-27 Andrei Zmievski <andrei@php.net>
+
+ * NEWS: *** empty log message ***
+
+2002-02-27 Monte Ohrt <monte@ispi.net>
+
+ * docs/designers.sgml: fix syntax error
+
+ * docs/appendixes.sgml
+ docs/designers.sgml
+ docs/getting-started.sgml
+ docs/programmers.sgml: convert technical notes to docbook format
+
+ * NEWS
+ docs/designers.sgml: added "eval" plugin docs
+
+2002-02-26 Andrei Zmievski <andrei@php.net>
+
+ * docs/programmers.sgml
+ docs/designers.sgml
+ docs/appendixes.sgml
+ docs/getting-started.sgml
+ docs/html-common.dsl
+ docs/.cvsignore: *** empty log message ***
+
+ * docs/appendixes.sgml
+ docs/common.dsl
+ docs/designers.sgml
+ docs/getting-started.sgml
+ docs/html-common.dsl
+ docs/html.dsl
+ docs/manual.sgml
+ docs/preface.sgml
+ docs/programmers.sgml: Split up docs.
+
+2002-02-25 Andrei Zmievski <andrei@php.net>
+
+ * docs.sgml: *** empty log message ***
+
+2002-02-22 Monte Ohrt <monte@ispi.net>
+
+ * docs.sgml: update docs
+
+2002-02-22 Andrei Zmievski <andrei@php.net>
+
+ * docs.sgml
+ AUTHORS
+ NEWS: *** empty log message ***
+
+2002-02-21 Monte Ohrt <monte@ispi.net>
+
+ * Config_File.class.php
+ NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ docs.sgml: update misc changes
+
+2002-02-21 Andrei Zmievski <andrei@php.net>
+
+ * docs.sgml: *** empty log message ***
+
+2002-02-20 Monte Ohrt <monte@ispi.net>
+
+ * docs.sgml: misc updates
+
+2002-02-20 Andrei Zmievski <andrei@php.net>
+
+ * docs.sgml: *** empty log message ***
+
+ * Smarty.class.php
+ plugins/function.assign.php
+ plugins/function.assign_debug_info.php
+ plugins/function.counter.php
+ plugins/function.fetch.php
+ plugins/function.math.php
+ plugins/function.popup.php
+ plugins/function.popup_init.php
+ plugins/modifier.escape.php: Fixup some naming.
+
+2002-02-20 Monte Ohrt <monte@ispi.net>
+
+ * docs.sgml: update docs
+
+2002-02-20 Andrei Zmievski <andrei@php.net>
+
+ * docs.sgml: *** empty log message ***
+
+2002-02-20 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ docs.sgml
+ plugins/modifier.escape.php:
+ removed global vars from fetch function, added attrs to escape modifier
+
+ * docs.sgml: add plugin chapter outline
+
+2002-02-19 Monte Ohrt <monte@ispi.net>
+
+ * README
+ RELEASE_NOTES
+ RESOURCES
+ Smarty.class.php
+ docs.sgml
+ BUGS
+ FAQ
+ INSTALL
+ QUICKSTART: update docs
+
+2002-02-19 Andrei Zmievski <andrei@php.net>
+
+ * docs.sgml: Updated resources docs.
+
+ * README: *** empty log message ***
+
+ * docs.sgml: Updated description of {$smarty} variable.
+
+ * BUGS
+ FAQ
+ INSTALL
+ QUICKSTART
+ RELEASE_NOTES
+ docs.sgml: Remove PEAR notes.
+
+2002-02-18 Andrei Zmievski <andrei@php.net>
+
+ * Config_File.class.php
+ NEWS: Removed dependency on PEAR.
+
+2002-02-18 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ docs.sgml
+ plugins/function.popup_init.php: add src attribute to popup_init
+
+2002-02-15 Andrei Zmievski <andrei@php.net>
+
+ * Smarty_Compiler.class.php
+ plugins/modifier.debug_print_var.php
+ NEWS
+ Smarty.class.php: Performance enhancements.
+
+2002-02-06 Andrei Zmievski <andrei@php.net>
+
+ * plugins/function.html_options.php:
+ Fix html_options output to be XHTML compatible.
+
+2002-02-05 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php
+ Smarty_Compiler.class.php: Fix up plugin inclusion.
+
+ * Smarty.class.php
+ Smarty_Compiler.class.php
+ TODO
+ plugins/function.html_select_date.php
+ plugins/function.html_select_time.php
+ plugins/modifier.date_format.php: Fix plugin directory access.
+
+2002-02-04 Andrei Zmievski <andrei@php.net>
+
+ * .cvsignore
+ Smarty_Compiler.class.php: *** empty log message ***
+
+2002-01-31 Andrei Zmievski <andrei@php.net>
+
+ * NEWS: *** empty log message ***
+
+ * Smarty.addons.php
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ TODO
+ plugins/function.assign.php
+ plugins/function.assign_debug_info.php
+ plugins/function.counter.php
+ plugins/function.fetch.php
+ plugins/function.html_options.php
+ plugins/function.html_select_date.php
+ plugins/function.html_select_time.php
+ plugins/function.math.php
+ plugins/function.popup.php
+ plugins/function.popup_init.php
+ plugins/modifier.capitalize.php
+ plugins/modifier.count_characters.php
+ plugins/modifier.count_paragraphs.php
+ plugins/modifier.count_sentences.php
+ plugins/modifier.count_words.php
+ plugins/modifier.date_format.php
+ plugins/modifier.debug_print_var.php
+ plugins/modifier.default.php
+ plugins/modifier.escape.php
+ plugins/modifier.lower.php
+ plugins/modifier.regex_replace.php
+ plugins/modifier.replace.php
+ plugins/modifier.spacify.php
+ plugins/modifier.string_format.php
+ plugins/modifier.strip_tags.php
+ plugins/modifier.truncate.php
+ plugins/modifier.upper.php
+ plugins/shared.make_timestamp.php
+ templates/index.tpl
+ AUTHORS
+ CREDITS
+ Config_File.class.php
+ README: Implemented plugin architecture.
+
+ * NEWS: *** empty log message ***
+
+2002-01-30 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty.addons.php
+ Smarty.class.php
+ docs.sgml: added modifiers wordwrap and indent
+
+2002-01-28 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php
+ docs.sgml:
+ add support for is-modified-since headers, adjust a doc example
+
+2002-01-24 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php: cleanup formatting
+
+ * NEWS
+ Smarty.class.php
+ docs.sgml: update ChangeLog, remove insert_tag_check parameter
+
+2002-01-24 Andrei Zmievski <andrei@php.net>
+
+ * plugins/standard.plugin.php: *** empty log message ***
+
+2002-01-24 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php: fix syntax error
+
+ * Smarty.class.php: removed unneccesary test from fetch()
+
+2002-01-23 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.addons.php: update overlib fixes
+
+ * NEWS: update changelog
+
+ * FAQ
+ NEWS
+ RESOURCES
+ Smarty.addons.php: updated overlib fixes
+
+2001-12-31 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty.class.php: Fixed compile_id problem.
+
+2001-12-28 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php:
+ fixed problem with using assigned var with include_php filepath
+
+2001-12-21 Monte Ohrt <monte@ispi.net>
+
+ * RESOURCES: update RESOURCES
+
+2001-12-20 Monte Ohrt <monte@ispi.net>
+
+ * FAQ
+ README: update FAQ
+
+2001-12-18 Monte Ohrt <monte@ispi.net>
+
+ * Smarty_Compiler.class.php
+ docs.sgml
+ Config_File.class.php
+ NEWS
+ README
+ RELEASE_NOTES
+ Smarty.addons.php
+ Smarty.class.php: update version numbers
+
+2001-12-18 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty.class.php: Fixed clear_cache().
+
+2001-12-14 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty.addons.php:
+ fixed bug in smarty_make_timestamp introduced in PHP 4.1.0
+
+2001-12-13 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty.class.php
+ docs.sgml: update default function args, fix cached insert debug timing
+
+2001-12-12 Monte Ohrt <monte@ispi.net>
+
+ * docs.sgml: fix syntax error in documentation
+
+ * Smarty.class.php: update default template handling functionality
+
+2001-12-11 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php
+ Smarty_Compiler.class.php: update file fetching logic
+
+2001-12-11 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty.class.php: Added 'script' attribute to {insert..}.
+
+2001-12-10 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty.class.php: added default template function handler
+
+ * Config_File.class.php
+ NEWS
+ README
+ RELEASE_NOTES
+ Smarty.addons.php
+ Smarty.class.php
+ Smarty_Compiler.class.php: update version numbers in files to 1.5.1
+
+2001-12-10 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty.class.php: Removed error message from the _read_file() method.
+
+ * Smarty.class.php: Fix check for compile and cache IDs.
+
+2001-12-06 Monte Ohrt <monte@ispi.net>
+
+ * QUICKSTART: fix spelling error in QUICKSTART
+
+ * docs.sgml: fixed spelling errors in documenation
+
+ * Smarty_Compiler.class.php
+ docs.sgml
+ Config_File.class.php
+ NEWS
+ README
+ RELEASE_NOTES
+ Smarty.addons.php
+ Smarty.class.php: commit 1.5.0 release
+
+ * RESOURCES
+ docs.sgml: added RESOURCES file
+
+2001-12-05 Andrei Zmievski <andrei@php.net>
+
+ * Smarty_Compiler.class.php: Refactor.
+
+2001-12-05 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty_Compiler.class.php
+ docs.sgml: added assign to include and php_include
+
+ * Smarty.class.php
+ Smarty_Compiler.class.php
+ docs.sgml: *** empty log message ***
+
+2001-12-04 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty_Compiler.class.php: Formatting.
+
+2001-12-04 Monte Ohrt <monte@ispi.net>
+
+ * Smarty_Compiler.class.php
+ NEWS
+ Smarty.class.php: update ChangeLog
+
+2001-12-04 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty.class.php: Formatting.
+
+2001-12-04 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php: removed SMARTY_DIR setting in constructor
+
+ * Smarty.class.php: fix Smarty.class.php indention error
+
+ * Smarty.class.php: update trusted logic
+
+2001-12-03 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php:
+ fix up is_secure, is_trusted, make _parse_tpl_path function
+
+ * Smarty.class.php: fix problem with testing SMARTY_DIR as empty
+
+ * NEWS
+ docs.sgml: update documentation, change log
+
+ * Smarty.class.php:
+ update constructor to check for SMARTY_DIR before assigning
+
+2001-12-03 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty.class.php: *** empty log message ***
+
+2001-12-03 Monte Ohrt <monte@ispi.net>
+
+ * FAQ
+ INSTALL
+ RELEASE_NOTES: update a few files
+
+ * NEWS
+ QUICKSTART
+ Smarty.class.php
+ docs.sgml: added trusted_dir functionality, cleaned up secure_dir logic
+
+2001-12-03 Andrei Zmievski <andrei@php.net>
+
+ * NEWS: *** empty log message ***
+
+ * NEWS
+ Smarty.class.php: - Introduced $compile_id class variable.
+ - Fixed a situation where if $cache_id and $compile_id were both null
+ they were passed to auto functions as empty string instead of null.
+
+2001-11-30 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty.class.php:
+ change variable names in fetch() fuction to smarty_* to avoid namespace conflicts
+
+ * NEWS
+ Smarty.class.php: fixed bug in _rm_auto with catenated null values
+
+2001-11-29 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty_Compiler.class.php: Added $smarty.section.* syntax.
+
+ * Smarty_Compiler.class.php: Made 'name' attribute optional for {foreach}.
+
+2001-11-29 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php
+ index.php: remove assign "now" in index.tpl
+
+2001-11-29 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty.addons.php
+ Smarty.class.php: Fix formatting.
+
+2001-11-28 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty.class.php
+ docs.sgml:
+ removed return statements from _read_cache_file (how did they get in there?)
+
+2001-11-27 Monte Ohrt <monte@ispi.net>
+
+ * docs.sgml
+ NEWS
+ Smarty.addons.php
+ Smarty.class.php:
+ fixed bugs and added assign attribute to several functions
+
+2001-11-27 Andrei Zmievski <andrei@php.net>
+
+ * NEWS: Some rewording.
+
+ * Smarty_Compiler.class.php: Fix $smarty.capture access.
+
+ * TODO: *** empty log message ***
+
+ * NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php:
+ Made {config_load ..} merge globals from each config file only once per scope.
+
+ * NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php: - Added {foreach ...}.
+ - Made certain $smarty.* references handled at compilation time.
+
+2001-11-26 Monte Ohrt <monte@ispi.net>
+
+ * Config_File.class.php
+ NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ docs.sgml: commit cache handler functionality
+
+2001-11-20 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty.addons.php
+ Smarty_Compiler.class.php: Various fixes and additions.
+
+ * NEWS
+ index.php: *** empty log message ***
+
+2001-11-05 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php: changed _read_file parameter from $end to $lines
+
+ * NEWS
+ Smarty.class.php: fixed is_cache, make cache reading more efficient
+
+2001-11-02 Monte Ohrt <monte@ispi.net>
+
+ * FAQ
+ NEWS: update FAQ with mailing list Reply-To header FAQ
+
+ * NEWS
+ Smarty.class.php
+ index.php: supress fopen errors, return false if cache file won't load
+
+2001-11-01 Monte Ohrt <monte@ispi.net>
+
+ * QUICKSTART
+ docs.sgml
+ index.php: update QUICKSTART guide with index key example
+
+ * Config_File.class.php
+ NEWS
+ README
+ RELEASE_NOTES
+ Smarty.addons.php
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ docs.sgml: commit all updates for 1.4.6
+
+2001-11-01 Andrei Zmievski <andrei@php.net>
+
+ * NEWS: *** empty log message ***
+
+2001-10-30 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.addons.php: fix assign function problem with empty value passed
+
+ * NEWS
+ Smarty.addons.php
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ templates/debug.tpl:
+ fixed bug in assign function when passing an empty value
+
+2001-10-26 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.addons.php
+ Smarty.class.php
+ index.php: fix minor typo in debug code
+
+2001-10-26 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php: Typo.
+
+2001-10-26 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.addons.php:
+ update debug console output, handle html encoding correctly
+
+2001-10-26 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.addons.php
+ templates/debug.tpl: Debug formatting.
+
+ * Smarty.class.php: Disable rmdir warning.
+
+2001-10-26 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.addons.php
+ Smarty.class.php
+ templates/debug.tpl: update debugging to expand array variables
+
+ * Smarty.class.php
+ docs.sgml:
+ update docs for fetching only timestamp with custom template source functions
+
+ * Smarty.addons.php: fix debug console error
+
+2001-10-26 Andrei Zmievski <andrei@php.net>
+
+ * docs.sgml: Typos.
+
+ * Smarty.addons.php: Cleanup whitespace.
+
+ * Smarty_Compiler.class.php: Clean up whitespace.
+
+ * Smarty.class.php: Cleaning up code, formatting mostly.
+
+ * NEWS: *** empty log message ***
+
+2001-10-25 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ docs.sgml: update documentation to current version
+
+ * NEWS
+ Smarty.addons.php:
+ updated fetch to give proper warning when fetching unreadable or nonexistant files
+
+ * NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php:
+ fixed problem with newline at the end of compiled templates
+
+ * NEWS
+ Smarty.class.php: recompile cache if config file gets modified too.
+
+ * NEWS
+ Smarty.class.php:
+ added feature to regenerate cache if compile_check is enabled and an
+ involved template is modified
+
+2001-10-23 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php: fix indent for insert tags in debug console
+
+ * templates/debug.tpl: update debug.tpl file format
+
+ * NEWS
+ Smarty.addons.php
+ Smarty.class.php
+ templates/debug.tpl:
+ update execution time debugging, move into include list
+
+2001-10-10 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty.addons.php
+ Smarty.class.php
+ Smarty_Compiler.class.php:
+ fixed up execution time output in debug console
+
+2001-10-09 Andrei Zmievski <andrei@php.net>
+
+ * Config_File.class.php
+ NEWS
+ Smarty.class.php
+ TODO: Added support for hidden config vars.
+
+2001-10-04 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty.addons.php
+ Smarty.class.php
+ templates/debug.tpl: added execution times to debug console
+
+2001-10-02 Andrei Zmievski <andrei@php.net>
+
+ * Smarty_Compiler.class.php: Add space.
+
+2001-10-01 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php: Fix reference to compile_id.
+
+2001-09-28 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php: Added postfilter functions.
+
+2001-09-26 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty.class.php
+ docs.sgml: Rename to clear_compiled_tpl().
+
+2001-09-25 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty_Compiler.class.php:
+ Fixed line number reporting when removing comments.
+
+2001-09-20 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ RELEASE_NOTES
+ Smarty.addons.php: made html_options output xhtml compatible
+
+2001-09-19 Monte Ohrt <monte@ispi.net>
+
+ * Config_File.class.php
+ NEWS
+ README
+ RELEASE_NOTES
+ Smarty.addons.php
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ templates/debug.tpl: updated version numbers
+
+2001-09-16 Monte Ohrt <monte@ispi.net>
+
+ * FAQ
+ NEWS
+ docs.sgml: fix doc error with insert function
+
+2001-09-06 Andrei Zmievski <andrei@php.net>
+
+ * NEWS: *** empty log message ***
+
+2001-08-31 Monte Ohrt <monte@ispi.net>
+
+ * NEWS: update ChangeLog
+
+ * overlib.js
+ Smarty.addons.php
+ Smarty.class.php
+ docs.sgml:
+ update overlib to 3.50, adjust addon code so that the overlib.js file isn't modified
+
+2001-08-31 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php: - compile_id changes
+
+ * NEWS
+ Smarty.addons.php: - compile_id support
+ - new options for html_select_date
+
+2001-08-23 Andrei Zmievski <andrei@php.net>
+
+ * TODO: *** empty log message ***
+
+2001-08-10 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty.addons.php
+ Smarty.class.php
+ Smarty_Compiler.class.php:
+ Modified to pass Smarty object as second parameter to insert functions.
+ Also moved _smarty_mod_handler() and _smarty_insert_handler() into the class.
+
+ * NEWS
+ Smarty_Compiler.class.php:
+ Passing Smarty as second parameter to prefilter functions.
+
+2001-08-09 Andrei Zmievski <andrei@php.net>
+
+ * NEWS: *** empty log message ***
+
+2001-08-09 Monte Ohrt <monte@ispi.net>
+
+ * templates/index.tpl
+ Smarty.class.php: add smarty.now variable to template
+
+2001-08-06 Monte Ohrt <monte@ispi.net>
+
+ * templates/index.tpl: change config_load section back to setup
+
+2001-08-06 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.addons.php: Optimize a bit.
+
+2001-08-04 Monte Ohrt <monte@ispi.net>
+
+ * docs.sgml: update capture documentation
+
+2001-08-03 Monte Ohrt <monte@ispi.net>
+
+ * FAQ
+ NEWS
+ Smarty.class.php:
+ fix bug with URL controlled debugging, works now (Monte)
+
+2001-08-01 Andrei Zmievski <andrei@php.net>
+
+ * Config_File.class.php: *** empty log message ***
+
+ * Smarty_Compiler.class.php
+ Smarty.class.php: - Fixed some E_NOTICE stuff in compiler.
+ - Generalized assign_smarty_interface() a bit.
+
+2001-07-24 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty_Compiler.class.php
+ TODO: See ChangeLog for details.
+
+2001-07-20 Andrei Zmievski <andrei@php.net>
+
+ * Config_File.class.php: Booleanize case-insensitively.
+
+2001-07-17 Monte Ohrt <monte@ispi.net>
+
+ * NEWS: update ChangeLog
+
+ * Smarty.class.php
+ docs.sgml: put SMARTY_DIR on Config_File require
+
+2001-07-11 Monte Ohrt <monte@ispi.net>
+
+ * docs.sgml
+ FAQ
+ NEWS
+ Smarty.class.php:
+ updated security to not include insecure docs, only warning
+
+2001-07-10 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php: Adding 'sizeof' as an allowed {if} function.
+
+2001-07-06 Andrei Zmievski <andrei@php.net>
+
+ * NEWS: *** empty log message ***
+
+2001-07-06 Monte Ohrt <monte@ispi.net>
+
+ * Config_File.class.php
+ NEWS
+ README
+ RELEASE_NOTES
+ Smarty.addons.php
+ Smarty.class.php
+ Smarty_Compiler.class.php: update version number to 1.4.4
+
+ * NEWS
+ Smarty.addons.php
+ Smarty_Compiler.class.php
+ docs.sgml
+ templates/header.tpl
+ templates/index.tpl: update documenatation, template examples
+
+2001-07-03 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty.class.php: Implemented access to request vars via $smarty var.
+
+ * NEWS
+ Smarty_Compiler.class.php:
+ Fixed a bug with parsing function arguments in {if} tags.
+
+2001-06-30 Monte Ohrt <monte@ispi.net>
+
+ * NEWS: update ChangeLog
+
+2001-06-29 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.addons.php
+ Smarty.class.php
+ docs.sgml
+ overlib.js:
+ moved overlib to separate file, added SMARTY_DIR, documented. added much documentation
+
+2001-06-29 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ RELEASE_NOTES
+ TODO: *** empty log message ***
+
+2001-06-29 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ README
+ RELEASE_NOTES
+ Smarty.addons.php
+ Smarty.class.php
+ docs.sgml
+ index.php
+ templates/debug.tpl
+ templates/header.tpl
+ templates/index.tpl: update release notes
+
+2001-06-27 Andrei Zmievski <andrei@php.net>
+
+ * Smarty_Compiler.class.php: *** empty log message ***
+
+ * NEWS
+ Smarty_Compiler.class.php: Implemented 'step' section attribute.
+
+ * Smarty_Compiler.class.php: Negative values of 'max' will mean no max.
+
+ * AUTHORS
+ NEWS: *** empty log message ***
+
+2001-06-26 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ index.php: Added 'max' and 'start' section attributes.
+ Added 'total' and 'iteration' section properties.
+
+2001-06-25 Andrei Zmievski <andrei@php.net>
+
+ * Config_File.class.php
+ RELEASE_NOTES
+ Smarty.addons.php
+ Smarty.class.php
+ Smarty_Compiler.class.php: Update version numbers.
+
+2001-06-23 Andrei Zmievski <andrei@php.net>
+
+ * TODO: *** empty log message ***
+
+2001-06-21 Andrei Zmievski <andrei@php.net>
+
+ * Config_File.class.php
+ NEWS: Fixed booleanization bug.
+
+2001-06-20 Monte Ohrt <monte@ispi.net>
+
+ * docs.sgml:
+ update documents to reflect changes to cached content & debugging
+
+2001-06-20 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.addons.php
+ Smarty.class.php: Remove debug output for cached and fetched cases.
+
+2001-06-20 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php: update include_info to false
+
+ * Smarty.class.php
+ docs.sgml
+ index.php
+ templates/footer.tpl:
+ moved debug logic into Smarty completely, created flags for it
+
+2001-06-19 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.addons.php
+ Smarty.class.php
+ templates/debug.tpl: *** empty log message ***
+
+ * NEWS
+ Smarty.class.php: Remove unneeded debug functions.
+
+2001-06-19 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty.addons.php
+ Smarty.class.php
+ docs.sgml
+ templates/debug.tpl
+ templates/footer.tpl: commit updates, add debug template
+
+2001-06-19 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php
+ Smarty_Compiler.class.php
+ TODO:
+ Moved config loading code inside main class, the compiled template now
+ simply calls that method.
+
+2001-06-15 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ templates/index.tpl: * moved config array into class itself
+ * added 'scope' attribute for config_load
+
+ * Smarty_Compiler.class.php
+ Smarty.addons.php
+ Smarty.class.php: Finishing up secure mode.
+
+2001-06-15 Monte Ohrt <monte@ispi.net>
+
+ * NEWS: update ChangeLog
+
+ * Smarty_Compiler.class.php: cleaned up logic of if statement security
+
+ * Smarty_Compiler.class.php: update if logic to cover more situations
+
+ * Smarty_Compiler.class.php
+ docs.sgml: update if statement security feature
+
+2001-06-14 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.addons.php
+ Smarty.class.php: *** empty log message ***
+
+ * NEWS
+ Smarty_Compiler.class.php:
+ Fixed a bug with quoted strings inside if statements.
+
+2001-06-13 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.addons.php
+ Smarty.class.php: added secure_dir array for multiple secure directories
+
+ * Smarty.addons.php: update fetch funtion to respect security setting
+
+ * NEWS
+ Smarty.addons.php
+ Smarty.class.php
+ docs.sgml: update documentation, changelog
+
+ * Smarty.addons.php
+ Smarty.class.php: moved _extract setting to assign functions
+
+ * Smarty.addons.php
+ Smarty.class.php
+ Smarty_Compiler.class.php:
+ added assign/unassign custom functions, ability to re-extract tpl_vars
+
+ * Smarty.class.php
+ Smarty_Compiler.class.php
+ docs.sgml
+ index.php: commit security features
+
+2001-06-11 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php: Version variable typo.
+
+2001-06-05 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php:
+ Create config object in fetch() or just set the config path if it already
+ exists.
+
+2001-06-04 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php: *** empty log message ***
+
+ * NEWS
+ Smarty_Compiler.class.php:
+ Fixed a problem with $<number> inside strip tags.
+
+2001-05-31 Andrei Zmievski <andrei@php.net>
+
+ * NEWS: *** empty log message ***
+
+ * Config_File.class.php: Allow empty config_path.
+
+2001-05-29 Monte Ohrt <monte@ispi.net>
+
+ * Smarty_Compiler.class.php
+ docs.sgml
+ NEWS
+ README
+ RELEASE_NOTES
+ Smarty.addons.php
+ Smarty.class.php: update version numbers
+
+ * NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ docs.sgml: moved version variable to internal variable
+
+2001-05-22 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php:
+ Moved $_smarty_sections and $_smarty_conf_obj into Smarty class.
+
+2001-05-18 Monte Ohrt <monte@ispi.net>
+
+ * NEWS: update ChangeLog
+
+ * FAQ
+ QUICKSTART: update FAQ, QUICKSTART for windows include_path setup
+
+ * configs/test.conf: added configs directory to cvs
+
+2001-05-18 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php: Use compiler_class for including the file.
+
+2001-05-18 Monte Ohrt <monte@ispi.net>
+
+ * docs.sgml: fix typo
+
+2001-05-16 Monte Ohrt <monte@ispi.net>
+
+ * README
+ RELEASE_NOTES
+ Smarty.addons.php
+ Smarty.class.php
+ Smarty_Compiler.class.php: update files to version 1.4.1
+
+ * NEWS: update ChangeLog
+
+2001-05-15 Andrei Zmievski <andrei@php.net>
+
+ * NEWS: *** empty log message ***
+
+ * index.php: forget that!
+
+ * NEWS
+ Smarty_Compiler.class.php
+ index.php: Fixed a few E_NOTICE warnings.
+
+2001-05-09 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ RELEASE_NOTES
+ Smarty.addons.php
+ Smarty.class.php
+ docs.sgml: update dates versions
+
+2001-05-09 Andrei Zmievski <andrei@php.net>
+
+ * NEWS: *** empty log message ***
+
+ * Smarty.class.php:
+ Use absolute paths when requiring/including Smart components.
+
+ * NEWS: *** empty log message ***
+
+ * Smarty.class.php: Use write mode instead of append.
+
+2001-05-02 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty_Compiler.class.php: Fix indexing by section properties.
+
+2001-05-02 Monte Ohrt <monte@ispi.net>
+
+ * NEWS: update changelog
+
+ * Smarty.class.php: remove period from syntax error
+
+2001-05-02 Andrei Zmievski <andrei@php.net>
+
+ * Smarty_Compiler.class.php: Double-quote the attribute values by default.
+
+2001-04-30 Monte Ohrt <monte@ispi.net>
+
+ * Smarty_Compiler.class.php
+ NEWS: added simple {capture} logic
+
+2001-04-30 Andrei Zmievski <andrei@php.net>
+
+ * TODO: *** empty log message ***
+
+ * Smarty_Compiler.class.php
+ Smarty.class.php: Fix passing config vars to included files.
+
+ * Smarty.class.php
+ Smarty_Compiler.class.php: Fix inclusion again.
+
+2001-04-30 Monte Ohrt <monte@ispi.net>
+
+ * FAQ
+ RELEASE_NOTES
+ Smarty.class.php
+ misc/fix_vars.php
+ NEWS: update paths for windows (c:)
+
+2001-04-28 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php
+ Smarty_Compiler.class.php: Fix passing variables to included files.
+
+ * templates/index.tpl: *** empty log message ***
+
+2001-04-27 Andrei Zmievski <andrei@php.net>
+
+ * Smarty_Compiler.class.php: Fix includes.
+
+2001-04-26 Andrei Zmievski <andrei@php.net>
+
+ * Smarty_Compiler.class.php
+ docs.sgml
+ Smarty.class.php: Formatting mostly.
+
+ * Smarty_Compiler.class.php
+ Config_File.class.php: *** empty log message ***
+
+2001-04-26 Monte Ohrt <monte@ispi.net>
+
+ * Smarty_Compiler.class.php
+ docs.sgml
+ FAQ
+ NEWS
+ QUICKSTART
+ RELEASE_NOTES
+ Smarty.class.php: update docs with new changes
+
+2001-04-26 Andrei Zmievski <andrei@php.net>
+
+ * RELEASE_NOTES: *** empty log message ***
+
+ * docs.sgml
+ templates/index.tpl
+ NEWS
+ Smarty_Compiler.class.php: Added ability to reference object properties.
+
+2001-04-25 Andrei Zmievski <andrei@php.net>
+
+ * README
+ Smarty.addons.php
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ docs.sgml
+ AUTHORS
+ Config_File.class.php
+ CREDITS
+ RELEASE_NOTES
+ NEWS: *** empty log message ***
+
+ * docs.sgml: Docs on new parameter to custom functions.
+
+ * NEWS: *** empty log message ***
+
+ * Smarty_Compiler.class.php:
+ Changing the way tpl vars are referenced and passing smarty object
+ to custom functions.
+
+ * RELEASE_NOTES
+ docs.sgml: Fixing docs a bit.
+
+2001-04-24 Andrei Zmievski <andrei@php.net>
+
+ * docs.sgml: Docs for $compiler_class and compiler functions.
+
+ * templates/index.tpl: *** empty log message ***
+
+ * Smarty_Compiler.class.php: Remove debugging.
+
+2001-04-24 Monte Ohrt <monte@ispi.net>
+
+ * docs.sgml: update compiler function docs
+
+2001-04-24 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ templates/index.tpl: Added compiler function support.
+
+2001-04-24 Monte Ohrt <monte@ispi.net>
+
+ * RELEASE_NOTES
+ Smarty.class.php:
+ update notes, change show_info_header to false by default
+
+ * Smarty.class.php
+ Smarty_Compiler.class.php
+ docs.sgml
+ CREDITS
+ FAQ
+ NEWS
+ README
+ RELEASE_NOTES: update documenation, bug fixes
+
+2001-04-24 Andrei Zmievski <andrei@php.net>
+
+ * misc/fix_vars.php: Hopefully fix for sure.
+
+2001-04-23 Monte Ohrt <monte@ispi.net>
+
+ * misc/fix_vars.php: uncomment copy/unlink
+
+2001-04-23 Andrei Zmievski <andrei@php.net>
+
+ * misc/fix_vars.php: Do it more thoroughly.
+
+ * misc/fix_vars.php: check for }
+
+2001-04-22 Andrei Zmievski <andrei@php.net>
+
+ * misc/fix_vars.php: Fix variable parsing.
+
+2001-04-20 Monte Ohrt <monte@ispi.net>
+
+ * misc/fix_vars.php: fix problem with 4.0.5-dev and preg_replace_callback
+
+2001-04-19 Monte Ohrt <monte@ispi.net>
+
+ * Smarty_Compiler.class.php
+ docs.sgml
+ misc/fix_vars.php
+ NEWS
+ RELEASE_NOTES
+ Smarty.class.php: update notes/documentation
+
+ * NEWS
+ README
+ RELEASE_NOTES
+ Smarty.addons.php
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ docs.sgml: update files for 1.4.0 release
+
+2001-04-16 Andrei Zmievski <andrei@php.net>
+
+ * misc/fix_vars.php: Added fix_vars.php script.
+
+2001-04-16 Monte Ohrt <monte@ispi.net>
+
+ * QUICKSTART
+ RELEASE_NOTES
+ docs.sgml
+ templates/index.tpl:
+ update RELEASE_NOTES & scripts with new section var syntax
+
+2001-04-13 Andrei Zmievski <andrei@php.net>
+
+ * Smarty_Compiler.class.php: * Implement new variable format parser.
+ * Optimizing config load a bit.
+
+2001-04-13 Monte Ohrt <monte@ispi.net>
+
+ * FAQ
+ NEWS
+ RELEASE_NOTES
+ Smarty.class.php:
+ added $check_cached_insert_tags to speed up cached pages if
+ {insert ...} is not used (Monte)
+
+2001-04-12 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty.class.php
+ RELEASE_NOTES: *** empty log message ***
+
+ * Smarty_Compiler.class.php: Remove redundant functions.
+
+ * Smarty.class.php: Formatting.
+
+2001-04-12 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php: update file: parsing
+
+ * Smarty.class.php
+ docs.sgml: update documentation
+
+2001-04-12 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php
+ Smarty_Compiler.class.php
+ TODO: *** empty log message ***
+
+2001-04-11 Monte Ohrt <monte@ispi.net>
+
+ * FAQ
+ QUICKSTART
+ RELEASE_NOTES: added RELEASE_NOTES file to cvs
+
+ * NEWS
+ docs.sgml: update ChangeLog, update documentation
+
+ * Smarty.class.php
+ Smarty_Compiler.class.php
+ templates/index.tpl:
+ update Smarty to compile at run-time. added ability to get files from
+ absolute paths, added work around for LOCK_EX and windows, changed a few
+ file permissions to be more secure.
+
+2001-03-29 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty.addons.php:
+ allow arbitrary date strings instead of just timestamps
+
+2001-03-28 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php
+ Smarty_Compiler.class.php
+ docs.sgml
+ FAQ
+ NEWS
+ README
+ Smarty.addons.php:
+ update version in class, update docs for count_ and new vars
+
+ * templates/index.tpl
+ docs.sgml: update docs, example template
+
+2001-03-28 Andrei Zmievski <andrei@php.net>
+
+ * Smarty_Compiler.class.php: Some variable renaming.
+
+2001-03-23 Andrei Zmievski <andrei@php.net>
+
+ * Smarty_Compiler.class.php
+ NEWS: Fixed nested include infinite repeat bug.
+
+2001-03-23 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php: fix version number
+
+ * Smarty.class.php
+ NEWS: added optional HTML header to output
+
+2001-03-22 Andrei Zmievski <andrei@php.net>
+
+ * Smarty_Compiler.class.php: Fixed inclusion of dynamic files.
+
+2001-03-16 Andrei Zmievski <andrei@php.net>
+
+ * Smarty_Compiler.class.php: Fixing the config_load scoping.
+
+ * Smarty_Compiler.class.php: making config variables global for now.
+
+2001-03-15 Andrei Zmievski <andrei@php.net>
+
+ * NEWS: *** empty log message ***
+
+ * Smarty_Compiler.class.php:
+ * Includes are now always done via generated function call to protect
+ namespace.
+ * config_load now always uses global config object to improve
+ performance.
+
+2001-03-13 Monte Ohrt <monte@ispi.net>
+
+ * docs.sgml: update math documentation with format attribute
+
+2001-03-11 Monte Ohrt <monte@ispi.net>
+
+ * docs.sgml
+ NEWS
+ Smarty.addons.php
+ Smarty.class.php
+ Smarty_Compiler.class.php: update math function with format attribute
+
+2001-03-10 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.addons.php: *** empty log message ***
+
+ * NEWS
+ Smarty.addons.php
+ Smarty.class.php: Added html_select_time custom function.
+
+2001-03-08 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php
+ Smarty_Compiler.class.php
+ NEWS
+ README
+ Smarty.addons.php: rename 1.3.1b to 1.3.1pl1
+
+ * NEWS
+ Smarty.addons.php
+ Smarty.class.php
+ Smarty_Compiler.class.php: update version numbers, changelog
+
+ * Smarty.class.php
+ Smarty_Compiler.class.php:
+ moved _syntax_error to Smarty_Compiler.class.php
+
+ * Smarty.class.php
+ docs.sgml:
+ missing _syntax_error function recovered. fixed minor syntax in docs
+
+2001-03-07 Monte Ohrt <monte@ispi.net>
+
+ * QUICKSTART
+ README
+ Smarty.addons.php
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ BUGS
+ INSTALL
+ NEWS: update everything to 1.3.1
+
+2001-03-03 Monte Ohrt <monte@ispi.net>
+
+ * Smarty_Compiler.class.php
+ Smarty.class.php: fixed bug with cached insert tags
+
+2001-03-02 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php
+ Smarty_Compiler.class.php:
+ fix cache fuctions with separated compiled class
+
+ * FAQ
+ NEWS
+ docs.sgml: update changelog
+
+2001-03-02 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty_Compiler.class.php: Added 'first' and 'last' section properties.
+
+2001-03-02 Monte Ohrt <monte@ispi.net>
+
+ * TODO: remove compiling separation TODO
+
+ * Smarty_Compiler.class.php
+ Smarty.addons.php
+ Smarty.class.php: update function headers
+
+ * templates/index.tpl
+ NEWS
+ Smarty.class.php
+ Smarty_Compiler.class.php
+ index.php: split out compiling code for faster execution
+
+ * Smarty.class.php: fixed a few warning messages
+
+ * Smarty.addons.php
+ Smarty.class.php
+ docs.sgml
+ NEWS: added fetch, unregister mod/fun, updated docs
+
+2001-03-01 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.addons.php: added "int" to available list
+
+ * docs.sgml
+ FAQ
+ Smarty.class.php: update FAQ, add math functions & update documetation
+
+ * index.php
+ Smarty.addons.php
+ Smarty.class.php
+ docs.sgml: fixed literal tags and other optional delimiters
+
+2001-02-26 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty.class.php:
+ Added index_prev, index_next section properties and ability to
+ index by them.
+
+ * NEWS
+ Smarty.addons.php
+ Smarty.class.php: Reverting the plugins patch - needs more thought.
+
+ * Smarty.class.php: Fixing plugin loading.
+
+2001-02-23 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.addons.php
+ Smarty.class.php
+ plugins/standard.plugin.php
+ NEWS: Added plugin functionality.
+
+2001-02-22 Monte Ohrt <monte@ispi.net>
+
+ * docs.sgml
+ templates/index.tpl
+ NEWS
+ README
+ Smarty.class.php: fixed issue with php tags executed in literal blocks
+
+2001-02-21 Monte Ohrt <monte@ispi.net>
+
+ * NEWS: update changelog for LGPL change
+
+ * Smarty.class.php
+ docs.sgml
+ README
+ Smarty.addons.php: updated version numbers to 1.3.0
+
+ * NEWS
+ templates/index.tpl: update changelog, rearrange index.tpl file
+
+2001-02-21 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty.class.php: *** empty log message ***
+
+2001-02-21 Monte Ohrt <monte@ispi.net>
+
+ * docs.sgml: update parameters for is_cached and fetch
+
+2001-02-21 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty.class.php: *** empty log message ***
+
+2001-02-21 Monte Ohrt <monte@ispi.net>
+
+ * NEWS
+ Smarty.addons.php
+ docs.sgml: update docs, remove header function from addons
+
+2001-02-20 Monte Ohrt <monte@ispi.net>
+
+ * FAQ
+ NEWS: update changelog
+
+ * TODO: update todo
+
+ * TODO: update todo list
+
+ * Smarty.class.php: update php tag handling logic
+
+2001-02-19 Monte Ohrt <monte@ispi.net>
+
+ * index.php
+ Config_File.class.php
+ FAQ
+ Smarty.class.php
+ docs.sgml: fixed <?php tag at beginning of files, updated docs
+
+2001-02-19 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.addons.php: *** empty log message ***
+
+2001-02-13 Andrei Zmievski <andrei@php.net>
+
+ * TODO: *** empty log message ***
+
+2001-02-12 Andrei Zmievski <andrei@php.net>
+
+ * templates/index.tpl
+ Smarty.class.php: *** empty log message ***
+
+2001-02-10 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php: remove unneeded preg_match
+
+ * Smarty.class.php: remove comment
+
+ * Smarty.class.php: updated php escape to handle <script language="php">
+
+ * NEWS
+ Smarty.class.php: fix php tag escapement logic
+
+ * NEWS: commit changelog
+
+ * docs.sgml: update header docs
+
+ * docs.sgml
+ Smarty.addons.php
+ Smarty.class.php: added header custom function
+
+2001-02-09 Monte Ohrt <monte@ispi.net>
+
+ * index.php
+ templates/header.tpl
+ templates/index.tpl
+ INSTALL
+ QUICKSTART
+ docs.sgml: update documentation, add examples to test script.
+
+2001-02-08 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php: *** empty log message ***
+
+2001-02-08 Monte Ohrt <monte@ispi.net>
+
+ * COPYING.lib: added COPYING.lib
+
+ * COPYING
+ Config_File.class.php
+ Smarty.addons.php
+ Smarty.class.php
+ docs.sgml: changed license to LGPL for commercial use
+
+ * docs.sgml
+ Smarty.class.php: fix clear_assign syntax error
+
+2001-02-07 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php: added ability to pass array to clear_assign
+
+ * index.php
+ templates/index.tpl
+ docs.sgml:
+ update documentation, remove tests from index file and template
+
+2001-02-07 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty.class.php: Adding file locking.
+
+ * templates/index.tpl
+ Smarty.addons.php
+ Smarty.class.php
+ index.php: More cache work.
+
+2001-02-06 Monte Ohrt <monte@ispi.net>
+
+ * docs.sgml
+ Smarty.class.php:
+ change register_ function names, update documents with tables
+
+2001-02-06 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty.class.php
+ templates/index.tpl: Reworking and optimizing the cache system.
+
+ * Smarty.class.php: Restoring ?> in patterns.
+
+2001-02-05 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php
+ docs.sgml: update cache directory creation logic
+
+2001-02-05 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php: Removing once-only subpattern for now..
+
+ * Smarty.class.php: Fix modifier arg parsing.
+
+2001-02-02 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ Smarty.class.php
+ templates/index.tpl: See changelog.
+
+2001-02-01 Andrei Zmievski <andrei@php.net>
+
+ * README: *** empty log message ***
+
+ * Smarty.class.php: Use 'echo' instead of 'print'.
+
+ * Smarty.addons.php: *** empty log message ***
+
+2001-02-01 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php: rearranged variables at top of script
+
+2001-02-01 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php: Retabbing.
+
+ * templates/index.tpl
+ Smarty.class.php
+ index.php: *** empty log message ***
+
+2001-02-01 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php: update caching logic
+
+ * Smarty.class.php: fixed clear_all_cache bugs
+
+ * Smarty.class.php: fix .cache check
+
+ * docs.sgml
+ FAQ
+ Smarty.class.php: update .che to .cache
+
+ * FAQ
+ Smarty.class.php
+ docs.sgml: updated docs for caching, added clear_all_cache() directive
+
+2001-01-31 Monte Ohrt <monte@ispi.net>
+
+ * index.php
+ templates/index.tpl
+ docs.sgml: upated docs for date_format and html_options
+
+2001-01-31 Andrei Zmievski <andrei@php.net>
+
+ * NEWS: *** empty log message ***
+
+ * Smarty.addons.php
+ index.php: Added ability to pass 'options' attribute to html_options.
+
+ * Smarty.addons.php
+ Smarty.class.php
+ docs.sgml
+ index.php
+ templates/index.tpl
+ Config_File.class.php
+ NEWS
+ README: Reworking, simplifying, and speeding up cache implementation.
+ Fixing the infelicity where you couldn't have '|' and ':' inside
+ quoted modifier arguments.
+
+2001-01-31 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php
+ index.php
+ templates/index.tpl: removed DEBUG lines
+
+2001-01-30 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php: changed default expire to 3600
+
+ * Config_File.class.php
+ NEWS
+ README
+ Smarty.addons.php
+ Smarty.class.php: updated version numbers
+
+ * docs.sgml
+ NEWS
+ Smarty.class.php:
+ added caching, force compile, force cache, misc performance updates
+
+2001-01-30 Andrei Zmievski <andrei@php.net>
+
+ * NEWS: *** empty log message ***
+
+ * Smarty.class.php
+ templates/index.tpl: Remove debug message.
+
+ * Smarty.class.php
+ templates/index.tpl: Fixing the compile directory mayhem...
+
+ * Smarty.class.php:
+ Fix problem with {strip} around {section} and {include}
+
+ * Smarty.addons.php: *** empty log message ***
+
+2001-01-29 Monte Ohrt <monte@ispi.net>
+
+ * FAQ
+ NEWS
+ README
+ Smarty.class.php: fixed PHP_VERSION check, misc doc updates
+
+ * index.php
+ Config_File.class.php
+ NEWS
+ QUICKSTART
+ README
+ Smarty.addons.php
+ Smarty.class.php
+ docs.sgml: updated for 1.2.1 compile_dir changes, misc doc updates
+
+2001-01-26 Monte Ohrt <monte@ispi.net>
+
+ * BUGS
+ README: update BUGS and README files
+
+ * FAQ: updated FAQ
+
+ * Config_File.class.php
+ FAQ
+ NEWS
+ README
+ Smarty.addons.php
+ docs.sgml
+ templates/index.tpl
+ AUTHORS: update again
+
+2001-01-26 Andrei Zmievski <andrei@php.net>
+
+ * docs.sgml
+ NEWS
+ README
+ Smarty.class.php
+ templates/index.tpl: *** empty log message ***
+
+ * Smarty.class.php
+ index.php
+ templates/index.tpl: Added ability to index by key.
+
+2001-01-25 Monte Ohrt <monte@ispi.net>
+
+ * NEWS: update changelog
+
+ * README
+ Smarty.addons.php
+ Smarty.class.php
+ docs.sgml
+ AUTHORS: updated versions to 1.1.0
+
+ * docs.sgml
+ templates/index.tpl
+ Config_File.class.php
+ Smarty.addons.php
+ Smarty.class.php: update copyright notice
+
+ * Config_File.class.php
+ Smarty.addons.php
+ Smarty.class.php
+ docs.sgml: added misc info
+
+2001-01-24 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.addons.php
+ index.php
+ templates/index.tpl
+ Config_File.class.php: initial commit
+
+2001-01-23 Monte Ohrt <monte@ispi.net>
+
+ * docs.sgml: fix typo
+
+2001-01-22 Monte Ohrt <monte@ispi.net>
+
+ * doc.sgm
+ docs.sgml: updated docs, renamed file
+
+ * FAQ: updated FAQ
+
+ * NEWS
+ README: updated Changelog and Readme
+
+ * doc.sgm: updated doc.sgm error
+
+ * AUTHORS
+ COPYING
+ INSTALL
+ NEWS
+ QUICKSTART: misc doc changes, added AUTHORS, COPYING
+
+2001-01-22 Andrei Zmievski <andrei@php.net>
+
+ * NEWS
+ templates/index.tpl: *** empty log message ***
+
+ * Smarty.class.php
+ templates/index.tpl:
+ Fixed bug that wouldn't let you do specify non-array values for 'loop'
+ attribute.
+
+2001-01-22 Monte Ohrt <monte@ispi.net>
+
+ * QUICKSTART: updated QUICKSTART
+
+ * BUGS
+ FAQ
+ INSTALL
+ README
+ doc.sgm: added BUGS and INSTALL, updated docs, FAQ, README
+
+2001-01-21 Monte Ohrt <monte@ispi.net>
+
+ * FAQ
+ doc.sgm: updates to FAQ and docs
+
+2001-01-19 Monte Ohrt <monte@ispi.net>
+
+ * FAQ: initial commit of FAQ
+
+ * QUICKSTART
+ README
+ doc.sgm
+ index.php:
+ updated README, doc.sgm with preg_replace() parameter issue. also removed "./" from index.php file
+
+ * NEWS: initial commit of changelog
+
+ * doc.sgm
+ QUICKSTART: update quickstart text
+
+2001-01-19 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php: Fix the compiled template check.
+
+2001-01-18 Andrei Zmievski <andrei@php.net>
+
+ * doc.sgm: *** empty log message ***
+
+2001-01-18 Monte Ohrt <monte@ispi.net>
+
+ * index.php
+ templates/index.tpl
+ QUICKSTART
+ Smarty.addons.php
+ Smarty.class.php
+ doc.sgm: update changes
+
+2001-01-18 Andrei Zmievski <andrei@php.net>
+
+ * QUICKSTART
+ Smarty.addons.php: *** empty log message ***
+
+2001-01-18 Monte Ohrt <monte@ispi.net>
+
+ * QUICKSTART
+ doc.sgm: add QUICKSTART, update docs for default modifier
+
+ * Smarty.addons.php
+ Smarty.class.php: added default modifier
+
+ * README
+ Smarty.addons.php
+ Smarty.class.php
+ doc.sgm
+ templates/index.tpl: added dislaimers
+
+2001-01-18 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php: *** empty log message ***
+
+2001-01-16 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php
+ templates/index.tpl: Implement 'div by'.
+
+2001-01-12 Monte Ohrt <monte@ispi.net>
+
+ * doc.sgm: update docs
+
+ * doc.sgm: doc changes
+
+ * doc.sgm: update docs
+
+2001-01-12 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php
+ doc.sgm: *** empty log message ***
+
+ * Smarty.class.php: Fix template traversal.
+
+2001-01-11 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php: *** empty log message ***
+
+2001-01-09 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.addons.php
+ Smarty.class.php: *** empty log message ***
+
+2001-01-09 Monte Ohrt <monte@ispi.net>
+
+ * doc.sgm: update manual
+
+2001-01-05 Monte Ohrt <monte@ispi.net>
+
+ * doc.sgm
+ Smarty.addons.php: commit changes
+
+2001-01-04 Monte Ohrt <monte@ispi.net>
+
+ * doc.sgm
+ templates/index.tpl
+ Smarty.class.php: update changes
+
+ * index.php
+ Smarty.addons.php
+ doc.sgm: add documentation
+
+2001-01-02 Monte Ohrt <monte@ispi.net>
+
+ * index.php
+ templates/index.tpl
+ Smarty.addons.php
+ Smarty.class.php: prepend insert_ to insert tag functions
+
+ * Smarty.class.php
+ index.php
+ templates/index.tpl: remove caching logic
+
+ * README
+ Smarty.class.php
+ index.php
+ templates/index.tpl: update changes
+
+2000-12-27 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php
+ templates/header.tpl
+ templates/index.tpl
+ Smarty.addons.php: *** empty log message ***
+
+2000-12-21 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php: Fix access to template variables.
+
+ * Smarty.class.php
+ templates/header.tpl:
+ Added support for passing variables to included files.
+
+2000-12-20 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php:
+ Added support for inserting results of function processing a template.
+
+2000-12-18 Monte Ohrt <monte@ispi.net>
+
+ * Smarty.class.php: added string_format function
+
+ * Smarty.addons.php: update format to string_format
+
+ * README
+ Smarty.addons.php
+ Smarty.class.php: added format addon function
+
+2000-12-13 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.addons.php
+ Smarty.class.php: Fix sectionelse.
+
+2000-12-07 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.addons.php
+ Smarty.class.php
+ templates/index.tpl: *** empty log message ***
+
+2000-12-04 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php
+ templates/index.tpl
+ Smarty.addons.php: *** empty log message ***
+
+2000-11-27 Andrei Zmievski <andrei@php.net>
+
+ * templates/index.tpl
+ Smarty.class.php: *** empty log message ***
+
+2000-11-22 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php
+ templates/index.tpl: *** empty log message ***
+
+2000-11-21 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php
+ templates/index.tpl
+ Smarty.addons.php: *** empty log message ***
+
+2000-11-20 Andrei Zmievski <andrei@php.net>
+
+ * templates/index.tpl
+ Smarty.class.php
+ Smarty.addons.php
+ index.php: *** empty log message ***
+
+ * Smarty.class.php
+ index.php
+ templates/index.tpl: Made sections work mostly.
+
+2000-11-19 Andrei Zmievski <andrei@php.net>
+
+ * index.php
+ templates/index.tpl: *** empty log message ***
+
+2000-11-17 Andrei Zmievski <andrei@php.net>
+
+ * Smarty.class.php
+ Smarty.addons.php: *** empty log message ***
+
+2000-11-15 Monte Ohrt <monte@ispi.net>
+
+ * index.php
+ templates/footer.tpl
+ templates/header.tpl
+ templates/index.tpl: added template files to cvs dir
+
+ * README
+ Smarty.class.php: commit changes
+
+2000-08-08 Monte Ohrt <monte@ispi.net>
+
+ * README
+ Smarty.class.php: update include path bug
+
+ * README: add README file
+
+ * Smarty.class.php: New file.
+
+ * Smarty.class.php: initial import
+
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/FAQ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/FAQ
new file mode 100644
index 00000000..b82d39cf
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/FAQ
@@ -0,0 +1,284 @@
+QUESTION INDEX
+--------------
+
+GENERAL
+
+Q: What is Smarty?
+Q: What's the difference between Smarty and other template engines?
+Q: What do you mean "Compiled PHP Scripts" ?
+Q: Why can't I just use PHPA (http://php-accelerator.co.uk) or Zend Cache?
+Q: Why does smarty have a built in cache? Wouldn't it be better to handle this
+ in a separate class?
+Q: Is Smarty faster than <insert other PHP template engine>?
+Q: How can I be sure to get the best performance from Smarty?
+Q: Do you have a mailing list?
+Q: Can you change the mailing list so reply-to sends to the list and not the
+ user?
+
+TROUBLESHOOTING
+
+Q: Smarty doesn't work.
+Q: I get the following error when running Smarty:
+ Warning: Smarty error: problem creating directory "templates_c/239/239105369"
+ in /path/to/Smarty.class.php on line 542
+Q: I get the following error when running Smarty:
+ Warning: Wrong parameter count for preg_replace() in
+ Smarty.class.php on line 371
+Q: I get this error when passing variables to {include}:
+ Fatal error: Call to undefined function: get_defined_vars() in
+ /path/to/Smarty/templates_c/index.tpl.php on line 8
+Q: I get PHP errors in my {if} tag logic.
+Q: I'm changing my php code and/or templates, and my results are not getting
+ updated.
+Q: I'm running Windows 2000 and I get blank content. My compiled PHP files are
+ also zero length.
+Q: The template goes into an infinite loop when I include included templates
+ that pass local variables
+Q: Javascript is causing Smarty errors in my templates.
+Q: I get "SAFE MODE Restriction in effect. ..."-errors when running smarty.
+
+MISC
+
+Q: Can I use Macromedia's Dreamweaver to edit my templates?
+Q: Dreamweaver is urlencoding the template delimiters when they are in a SRC or
+ HREF link. How do I get around this?
+
+HOWTO
+
+Q: How do I generate different cache files per template based on arguments
+ passed to the page?
+Q: How do I pass a template variable as a parameter? {function param={$varname}}
+ does not work.
+Q: How do I include cached template(s) within a non-cached template?
+
+
+GENERAL
+-------
+
+Q: What is Smarty?
+A: Smarty is a template engine for PHP... but be aware this isn't just another
+ PHP template engine. It's much more than that.
+
+Q: What's the difference between Smarty and other template engines?
+A: Most other template engines for PHP provide basic variable substitution and
+ dynamic block functionality. Smarty takes a step further to be a "smart"
+ template engine, adding features such as configuration files, template
+ functions, variable modifiers (see the docs!) and making all of this
+ functionality as easy as possible to use for both programmers and template
+ designers. Smarty also compiles the templates into PHP scripts, eliminating
+ the need to parse the templates on every invocation, making Smarty extremely
+ scalable and manageable for large application needs.
+
+Q: What do you mean "Compiled PHP Scripts" ?
+A: Smarty reads the template files and creates PHP scripts from them. Once
+ these PHP scripts are created, Smarty executes these, never having to parse
+ the template files again. If you change a template file, Smarty will
+ recreate the PHP script for it. All this is done automatically by Smarty.
+ Template designers never need to mess with the generated PHP scripts or even
+ know of their existance. (NOTE: you can turn off this compile checking step
+ in Smarty for increased performance.)
+
+Q: Why can't I just use PHPA (http://php-accelerator.co.uk) or Zend Cache?
+A: You certainly can, and we highly recommend it! What PHPA does is caches
+ compiled bytecode of your PHP scripts in shared memory or in a file. This
+ speeds up server response and saves the compilation step. Smarty creates PHP
+ scripts, which PHPA will cache nicely. Now, Smarty's built-in cache is
+ something completely different. It caches the _output_ of the template
+ contents. For example, if you have a template that requires several database
+ queries, Smarty can cache this output, saving the need to call the database
+ every time. Smarty and PHPA (or Zend Cache) complement each other nicely. If
+ performance is of the utmost importance, we would recommend using one of
+ these with any PHP application, using Smarty or not. As you can see in the
+ benchmarks, Smartys performance _really_ excels in combination with a PHP
+ accelerator.
+
+Q: Why does Smarty have a built in cache? Wouldn't it be better to handle this
+ in a separate class?
+A: Smarty's caching functionality is tightly integrated with the template
+ engine, making it quite a bit more flexible than a simple caching wrapper.
+ For instance, you can cache select portions of a template page. Let's say
+ you have a polling box on your site. With Smarty, you can leave the poll
+ dynamic and cache the rest of the page. You can also pass templates
+ multiple cache ids, meaning that a template can have several caches
+ depending on URL, cookies, etc.
+
+Q: Is Smarty faster than <insert other PHP template engine>?
+A: See the benchmark page for some performance comparisons. Smarty's approach
+ to templates is a bit different from some languages: it compiles templates
+ into PHP scripts instead of parsing them on each invocation. This usually
+ results in great performance gains, especially with complex templates.
+ Coupled with the built-in caching of Smarty templates, the performance is
+ outstanding.
+
+Q: How can I be sure to get the best performance from Smarty?
+A: Be sure you set $compile_check=false once your templates are initially
+ compiled. This will skip the unneeded step of testing if the template has
+ changed since it was last compiled. If you have complex pages that don't
+ change too often, turn on the caching engine and adjust your application so
+ it doesn't do unnecessary work (like db calls) if a cached page is
+ available. See the documentation for examples.
+
+Q: Do you have a mailing list?
+A: We have a few mailing lists. "general" for you to share your ideas or ask
+ questions, "dev" for those interested in the development efforts of Smarty,
+ and "cvs" for those that would like to track the updates made in the cvs
+ repository.
+
+ send a blank e-mail message to:
+ smarty-general-subscribe@lists.php.net (subscribe to the general list)
+ smarty-general-unsubscribe@lists.php.net (unsubscribe from the general list)
+ smarty-general-digest-subscribe@lists.php.net (subscribe to digest)
+ smarty-general-digest-unsubscribe@lists.php.net (unsubscribe from digest)
+ smarty-dev-subscribe@lists.php.net (subscribe to the dev list)
+ smarty-dev-unsubscribe@lists.php.net (unsubscribe from the dev list)
+ smarty-cvs-subscribe@lists.php.net (subscribe to the cvs list)
+ smarty-cvs-unsubscribe@lists.php.net (unsubscribe from the cvs list)
+ You can also browse the mailing list archives at
+ http://marc.theaimsgroup.com/?l=smarty&r=1&w=2
+
+
+
+Q: Can you change the mailing list so Reply-To sends to the list and not the
+ user?
+A: Yes we could, but no we won't. Use "Reply-All" in your e-mail client to send
+ to the list. http://www.unicom.com/pw/reply-to-harmful.html
+
+TROUBLESHOOTING
+---------------
+
+Q: Smarty doesn't work.
+A: You must be using PHP 4.0.6 or later if you use any version of Smarty
+ past 2.0.1. Read the BUGS file for more info.
+
+Q: I get the following error when running Smarty:
+ Warning: Smarty error: problem creating directory "templates_c/239/239105369"
+ in /path/to/Smarty.class.php on line 542
+A: Your web server user does not have permission to write to the templates_c
+ directory, or is unable to create the templates_c directory. Be sure the
+ templates_c directory exists in the location defined in Smarty.class.php,
+ and the web server user can write to it. If you do not know the web server
+ user, chmod 777 the templates_c directory, reload the page, then check the
+ file ownership of the files created in templates_c. Or, you can check the
+ httpd.conf (usually in /usr/local/apache/conf) file for this setting:
+ User nobody
+ Group nobody
+
+Q: I get the following error when running Smarty: Warning: Wrong parameter
+ count for preg_replace() in Smarty.class.php on line 371
+A: preg_replace had a parameter added in PHP 4.0.2 that Smarty
+ requires. Upgrade to at least 4.0.6 to fix all known PHP issues with
+ Smarty.
+
+Q: I get this error when passing variables to {include}:
+ Fatal error: Call to undefined function: get_defined_vars() in
+ /path/to/Smarty/templates_c/index.tpl.php on line 8
+A: get_defined_vars() was added to PHP 4.0.4. If you plan on passing
+ variables to included templates, you will need PHP 4.0.6 or later.
+
+Q: I get PHP errors in my {if} tag logic.
+A: All conditional qualifiers must be separated by spaces. This syntax will not
+ work: {if $name=="Wilma"} You must instead do this: {if $name == "Wilma"}.
+ The reason for this is syntax ambiguity. Both "==" and "eq" are equivalent
+ in the template parser, so something like {if $nameeq"Wilma"} wouldn't be
+ parsable by the tokenizer.
+
+Q: I'm changing my php code and/or templates, and my results are not getting
+ updated.
+A: This may be the result of your compile or cache settings. If you are
+ changing your php code, your templates will not necessarily get recompiled
+ to reflect the changes. Use $force_compile during develpment to avoid these
+ situations. Also turn off caching during development when you aren't
+ specifically testing it. You can also remove everything from your
+ compile_dir and cache_dir and reload the page to be sure everything gets
+ regenerated.
+
+Q: I'm running Windows 2000 and I get blank content. My compiled PHP files are
+ also zero length.
+A: There seems to be a problem with some W2k machines and exclusive file
+ locking. Comment out the flock() call in _write_file to get around this,
+ although be aware this could possibly cause a problem with simultaneous
+ writes to a file, especially with caching turned on. NOTE: As of Smarty
+ 1.4.0, a workaround was put in place that should solve this.
+
+Q: The template goes into an infinite loop when I include included templates
+ that pass local variables
+A: This was fixed in 1.3.2 (new global attribute)
+
+Q: Javascript is causing Smarty errors in my templates.
+A: Surround your javascript with {literal}{/literal} tags. See the docs.
+
+Q: I get "SAFE MODE Restriction in effect. ..."-errors when running smarty.
+A: Use $smarty->use_sub_dirs = false when running php in safe mode.
+
+MISC
+----
+
+Q: Can I use Macromedia's Dreamweaver to edit my templates?
+A: Certainly. You might want to change your tag delimiters from {} to something
+ that resembles valid HTML, like <!--{ }--> or <{ }> or something similar.
+ This way the editor won't view the template tags as errors.
+
+Q: Dreamweaver is urlencoding the template delimiters when they are in a SRC or
+ HREF link. How do I get around this?
+A: In Edit - Properties - Rewrite HTML you can specify if Dreamweaver should
+ change special letters to %-equivalent or not. The default is on which
+ produces this error.
+
+HOWTO
+-----
+
+Q: How do I generate different cache files per template based on arguments
+ passed to the page?
+A: Use your $REQUEST_URI as the cache_id when fetching the page:
+
+ global $REQUEST_URI; // if not already present
+ $smarty->display('index.tpl',$REQUEST_URI);
+
+ This will create a separate cache file for each unique URL when you call
+ index.tpl. See the documentation for display() and fetch()
+
+Q: How do I pass a template variable as a parameter? {function param={$varname}}
+ does not work.
+A: {function param=$varname} (You cannot nest template delimiters.)
+
+Q: How do I include cached template(s) within a non-cached template?
+A: One way to do it:
+
+ $smarty->caching = true;
+ $tpl1 = $smarty->fetch("internal1.tpl");
+ $tpl2 = $smarty->fetch("internal2.tpl");
+ $tpl3 = $smarty->fetch("internal3.tpl");
+
+ $smarty->assign("tpl1_contents",$tpl1);
+ $smarty->assign("tpl2_contents",$tpl2);
+ $smarty->assign("tpl3_contents",$tpl3);
+
+ $smarty->caching = false;
+ $smarty->display('index.tpl');
+
+ index.tpl
+ ---------
+
+ <table>
+ <tr>
+ <td>{$tpl1_contents}</td>
+ <td>{$tpl2_contents}</td>
+ <td>{$tpl3_contents}</td>
+ </tr>
+ </table>
+
+
+
+
+ Another approach:
+
+ You could write a custom insert function to fetch your internal
+ templates:
+
+ <table>
+ <tr>
+ <td>{insert name=fetch_tpl tpl="internal1.tpl"}</td>
+ <td>{insert name=fetch_tpl tpl="internal2.tpl"}</td>
+ <td>{insert name=fetch_tpl tpl="internal3.tpl"}</td>
+ </tr>
+ </table>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/INSTALL b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/INSTALL
new file mode 100644
index 00000000..0df4341b
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/INSTALL
@@ -0,0 +1,29 @@
+REQUIREMENTS:
+
+Smarty requires PHP 4.0.6 or later.
+See the on-line documentation for complete install instructions.
+
+INSTALLATION (quick):
+
+* copy the files under the libs/ directory to a directory that is in your PHP
+ include_path, or set the SMARTY_DIR constant and put them in this directory.
+ (if you upgrade from versions before 2.5.0 be aware that up to Smarty 2.4.2
+ all necessary files where in the distribution's root directory, but are now
+ in libs/.)
+
+* for each application using Smarty, create a "templates", "configs", and a
+ "templates_c" directory, be sure to set the appropriate directory settings in
+ Smarty for them. If they are located in the same directory as your
+ application, they shouldn't need to be modified. Be sure the "templates_c"
+ directory is writable by your web server user (usually nobody). chown
+ nobody:nobody templates_c; chmod 700 templates_c You can also chmod 777 this
+ directory, but be aware of security issues for multi-user systems. If you are
+ using Smarty's built-in caching, create a "cache" directory and also chown
+ nobody:nobody.
+
+* setup your php and template files. A good working example is in the on-line
+ documentation.
+
+* TECHNICAL NOTE: If you do not have access to the php.ini file, you can change
+ non-server settings (such as your include_path) with the ini_set() command.
+ example: ini_set("include_path",".:/usr/local/lib/php");
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/NEWS b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/NEWS
new file mode 100644
index 00000000..76302980
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/NEWS
@@ -0,0 +1,733 @@
+Version 2.6.0 (Nov 19, 2003)
+----------------------------
+
+ - move Smarty::quote_replace() to Smarty_Compiler::_quote_replace() (messju)
+ - remove import of of attributes of {include_php} to php's namespace.
+ use $params[name] instead (messju)
+
+Version 2.6.0-RC3 (Nov 13, 2003)
+--------------------------------
+
+ - fix handling of $var.key inside [] (messju)
+ - fix handling of assign inside {insert}-tags (messju)
+ - fix handling if [...] inside triple-quotes in config-files (messju)
+ - fix handling of simple-math-operators inside modifiers (Dominik, messju)
+ - fix handling of trailing-slashes in open_basedir in
+ smarty_core_create_dir_structure() (packman, messju)
+
+Version 2.6.0-RC2 (Oct 8, 2003)
+-------------------------------
+
+ - apply modifiers only once to section-loop and foreach-from attrs (messju)
+ - remove use of _smarty_cached_paths-files (messju)
+ - remove Smarty::_plugin_implementation_exists() - use is_callable() (messju)
+ - ignore {strip}/{/strip) inside {strip}-blocks (messju)
+ - fixed removal of leading/trailing newlines in {strip}-blocks (messju)
+ - fixed proper escaping of " and ' with escape:javascript (messju)
+ - fixed bug in traversal of $smarty->plugins_dir-array. now the
+ first matching plugin is taken (messju)
+ - moved {strip} back into the compiler (messju)
+ - fixed config_load: handling of section-attribute and use of
+ multiple config-files in one template (atu, messju)
+
+Version 2.6.0-RC1 (August 11, 2003)
+-----------------------------------
+
+ - fixed status-header for cache_modified_check under cgi-sapi (messju)
+ - added optional parameter $cache_attrs to register_function() and
+ register_block(). $cache_attrs is an array containing attribute-
+ names that should be cached on calls to functions that have
+ $cacheable set to false. (messju)
+ - enabled registration of class-methods as callbacks for the register_*-
+ functions (use: array('classname', 'method_name')) as callback) (messju)
+ - added filepath caching (Monte)
+ - added optional assign-attribute to {capture}-tag (messju)
+ - added $cacheable-parameter to register_compiler_function() (messju)
+ - added $cacheable-parameter with default=true to register_function()
+ and register_block() (messju)
+ - add math speedup to core (Dominik, Monte)
+ - fix newlines for tags without template output (Monte)
+ - added config-option "request_use_auto_globals" to make auto-globals be
+ used as request vars instead of HTTP_*_VARS (messju)
+ - speed up config_load, simplify compiling (Monte)
+ - added block-methods for registered objects (Bharat Mediratta, messju)
+ - ignore one char resource names like c:foo.tpl (Monte)
+ - added default_resource_type feature (Monte)
+ - fix bug where config file starts with hidden section (boots, Monte)
+ - add discrete error checking pertaining to $cache_dir
+ and $compile_dir, their existance and writability (Monte)
+ - fixed behaviour of start=... for {counter} (messju)
+ - fixed assign for {counter} (messju)
+ - added params vdir, hdir and inner to html_table to allow looping
+ over the data in various directions (messju)
+ - allow spaces in literal tags (Paul Lockaby, Monte)
+ - speed up compiled templates, hardcode plugin filepaths
+ instead of dynamically calculate at runtime. (Monte)
+ - abstract many core components from Smarty.class.php,
+ speeding up core class instantiation (Monte)
+ - fixed bug in _create_dir_structure() when used with open_basedir-
+ restriction and relative paths (messju)
+ - use DIRECTORY_SEPARATOR exclusively, keep DIR_SEP for BC (Monte)
+ - changed "link" to "href" in html_image. "link" is still working
+ but deprecated (messju)
+ - html_image always renders an alt-tag now (default alt="") (messju)
+ - fixed assign attribute for multiple counters (messju)
+ - added simple math operators to variables (Monte)
+ - enabled array(&$obj. 'source', 'timestamp', 'secure', 'trusted')
+ as callback for register_resource() (messju);
+ - enabled array(&$obj, 'method') as callback for
+ $default_template_handler_func (messju)
+ - remove unnecessary close/open tags from compiled templates
+ (Monte)
+ - fixed errornous creation of '//' in image_path in html_image (messju)
+ - fix escapement of special chars for key vals in debug
+ console (Monte)
+ - fixed debug timing logic for config_load (Tom Sommer, Monte)
+ - all in-code doc comments converted to phpDocumentor format (Greg)
+ - moved strip from smarty core to plugin (Monte)
+ - moved config_load from smarty core to plugin (Monte)
+ - added &$repeat-parameter to block-functions (messju)
+ - enabled hex-constants in function.math.php (messju)
+ - enabled hex-constants (0x...) as function-attributes, inside if-statements
+ and as modifier-parameters (messju)
+ - fixed bug with passing $smarty as reference in Smarty.compiler.class
+ (messju)
+ - corrected output with {strip} and PHP tag newlines (Monte)
+ - added possibility to register function-callbacks as "array(&$obj, 'method)"
+ this affects register_function(), -block, -compiler_function, -modifier,
+ -prefilter, -postfilter, -outputfilter-functions() and $cache_handler_func
+ (messju)
+ - added <labels> to html_checkboxes and html_radios (Philippe, messju)
+ - added "labels"-options to turn off labels in html_checkboxes and _radios
+ (messju)
+
+Version 2.5.0 (April 11, 2003)
+------------------------------
+
+ - fixed bug with default modifier when passing integer 0
+ (Monte)
+ - change backtic syntax from $`foo` to `$foo` (Monte)
+ - recognize $foo[][] syntax inside embedded quotes without
+ backtics (Monte)
+ - name=123 is passed as an integer (not a string) to plugins now (messju)
+ - $length is now propagated to sub-values in debug_print_var (messju)
+
+Version 2.5.0-RC2 (March 26, 2003)
+----------------------------------
+
+ - made clear_cache() ignore compile_id, when clearing cache-groups (this
+ is when no $tpl_file is supplied) (messju)
+ - made onmouseout XHTML-compliant in function.popup.php (messju)
+ - applied local-var-naming-scheme to fetch() (messju)
+ - renamed $localvars to $_localvars in cache-file-handling-functions,
+ added _get_auto_id()-function (messju)
+ - swapped compile_id and cache_id in read_cache_file and write_cache_file
+ (messju)
+ - reverted patch for cache-file-handling (messju)
+ - made html_radios and html_checkboxes accept "selected" instead
+ of "checked" optionally. (messju)
+ - made compile_id ignored in clear_cache, made order of
+ auto_file_name $cache_id.$compile_id again, applied the the new
+ variable-naming-scheme for cache_file_handing functions (messju)
+ - removed notice of undefined var in _rm_auto() (messju)
+ - added warning message when an array is passed as
+ the "checked" value of html_radios (Monte)
+ - fixed errormessage in _compile_smarty_ref() (messju)
+ - updated docs for html_image "name" -> "file" (messju)
+ - fixed bug with html_options-optgroups (Nichlas Löfdahl, messju)
+ - cleaned up calls to readdir() (messju)
+ - fixed bug with passing multiple modifiers to a parameter
+ (Monte)
+ - updated docs for html_checkboxes, html_options and html_radios (messju)
+ - fixed wrong default "name" attribute for html_options (messju)
+ - html_checkboxes now expect the options as attribute "options" instead
+ of "checkboxes. html_radios expect "options" instead of "radios".
+ cleaned up indentiation (messju)
+ - fixed too greedy str_replace in trimwhitespace outputfilter (messju)
+ - html_checkboxes and html_radios passthru all unknown paramters now
+ additionally their output is now XHTML compliant (messju)
+ - html_options passthru all unknown paramters now (messju)
+ - fix link functionality of html_image, also make
+ output XHTML compatible (Hinrich Donner, Monte)
+ - append "@" to default modifier vars/args
+ supress possible warnings (Monte)
+ - fix problem with escaped double quotes (Monte)
+ - fix html_radios to not return an array (Monte)
+ - fixed length in modifier.truncate.php (messju)
+ - fixed handling of '$'-signs in trimwhitespace outputfilter (messju)
+ - fix bug that makes config files recompile every time
+ (Nagger, Monte)
+ - add dpi functionality to html_image, change "name"
+ parameter to "file" (Thomas Shulz, Monte)
+ - fix height/width parameter index in html_image (Gerard,
+ Monte)
+ - get rid of unsetting name and script attributes
+ to insert tag (Thomas Schulz, Monte)
+ - changed argument order of string_format modifier back,
+ was right in the first place (Monte)
+
+Version 2.5.0-RC1 (March 5, 2003)
+---------------------------------
+
+ - fixed notice in popup function (Nagger, Monte)
+ - fix "once" var compiling for include_php (Monte)
+ - added nl2br modifier to distribution (Monte)
+ - added html_image to distribution (Monte)
+ - added cat modifier to distribution (Monte)
+ - added html_table to distribution (Monte)
+ - added << >> <> support to if statments (SMK, Monte)
+ - fix _assign_smarty_interface to not overwrite keys
+ other than 'request' (Jerome Poudevigne, Monte)
+ - added html_checkboxes to distribution (Christopher Kvarme, Monte)
+ - added html_radios to distribution (Christopher Kvarme, Monte)
+ - fixed string_format modifier args (wrong order) (Paul
+ Lockaby, Monte)
+ - use tmp file for file writes, avoid file lock race (Monte)
+ - support syntax "$`smarty.config.foo`.tpl" for embedded
+ vars in quotes, and allow full dollar var syntax (Monte)
+ - add $smarty.config.varname variable for accessing config vars (Paul
+ Lockaby, Monte)
+ - silence PHP warnings in function.fetch.php (Eduardo,
+ Monte)
+ - added get_config_vars(), same basic functionality as
+ get_template_vars() (Monte)
+ - update get_template_vars() to be able to get
+ individual vars (Monte)
+ - fix minor logic in _fetch_template_info (Dennis Gearon,
+ Monte)
+ - fix cache groups with compile_id set (Monte)
+ - add support for merging appended vars (messju, Monte)
+ - allow null as function attribute value
+ (André Rabold, Monte)
+ - support $foo->bar[index] syntax (Monte)
+ - add get_registered_object function (messju, Monte)
+ - treat unrecognized param attribute syntax as string (Monte)
+ - support $smarty.const.$foo syntax (messju, Monte)
+ - remove E_NOTICE warnings from debug.tpl,
+ escape modifier (Kanstantin, Monte)
+ - don't count non-ascii chars in count_words modifier
+ (Kanstantin, Monte)
+ - clean up param calls to _parse_var and _parse_attrs (Monte)
+ - define $template_source var, elude possible warning
+ (Monte)
+ - fix syntax problem with evaluating PHP constants (Monte)
+ - add @ and === as valid if statement tokens (Monte)
+ - enable error messages for config_load errors,
+ use $this->config_class for loading class name (Monte)
+ - fix html_options to not escape already escaped entities (Monte)
+ - send Last-Modified header on cache creation (Monte)
+ - check strict syntax of function attributes (Monte)
+ - dropped support for modifers on object parameters,
+ added support for objects as modifier parameters (Monte)
+ - fixed bug with decimal numbers in if statements (Monte)
+
+Version 2.4.2 (Feb 11, 2003)
+----------------------------
+ - support embedded variables in objects (Monte)
+ - fix bug with objects with no properties (M Mohr, Monte)
+ - support full dollar var syntax in quoted text (Monte)
+ - fixed bug in $smarty.const.FOO introduced in 2.4.1 (M
+ Mohr, Monte)
+
+Version 2.4.1 (Feb 6, 2003)
+---------------------------
+
+ - ignore case in IF statements (Rainer Collet, Monte)
+ - treat undefined constants as null (Ferdinand Beyer, Monte)
+ - fix problem with inserts and nested fetches
+ (Rainer Collet, Monte)
+ - added support for passing params to include_php
+ (Tim Riley, Monte)
+ - added support for math operators in if statements (Monte)
+ - added support for $foo->bar[$x].blah syntax (Monte)
+
+Version 2.4.0 (Feb 2, 2003)
+---------------------------
+
+ - fix known problems with php tag handling in templates
+ (recursion, echoing xml tags) (Monte)
+ - add support for object registration (Monte)
+ - add debug template to secure_dir, add template_dir
+ to secure_dir by default (Ferdinand Beyer, Monte)
+ - added support for assigned object access (Monte)
+ - fixed bug with directories named '0' (Frank Bauer, Monte)
+ - add javascript parameter to escape modifier (Monte)
+ - added calling function line numbers to syntax error
+ messages in compiler (Monte)
+ - added support for modifiers to function calls (Monte)
+ - support return value for custom functions
+ instead of echoing (but echo still works) (Monte)
+ - added direct access to constants
+ via $smarty.const.FOO (Monte)
+ - added support for passing modifiers
+ to static values (Monte)
+ - fix up regex code in compiler, more accurate and
+ maintainable (Monte)
+ - added day_value_format to html_select_date (Marcus
+ Bointon, Monte)
+ - assigned variables are no longer in global
+ namespace, saving extract() calls and speeding
+ up fetch() and display() linearly with no. of
+ assigned variables (Monte)
+ - added trimwhitespace output filter to dist. (Monte)
+ - fix popup function to allow newlines in text (Monte)
+ - escape html entities in html_options (Monte)
+ - fixed bug with label for html_options (Monte)
+ - added config_load API function (Monte)
+ - added caching to config file loading (Monte)
+ - added "extra" parameter to mailto function (Monte,
+ Massimiliano Perantoni)
+ - added mailto plugin to dist. (Monte)
+
+Version 2.3.1 (Nov 19, 2002)
+----------------------------
+
+ - added optgroup support to html_options (Monte, Robert
+ Amos)
+ - set mtime on compile files so they match source
+ files (Monte, Peter Bowen)
+ - added proper support for open_basedir setting
+ (Monte, Alessandro Astarita)
+ - added strip variable modifier, updated docs (Monte)
+ - fixed access to $smarty.x variables as arrays. (Andrei)
+ - fixed errors with example setup docs (Monte, Matthew
+ Hagerty)
+ - added textformat block function (Monte)
+
+Version 2.3.0 (Aug 7, 2002)
+---------------------------
+
+ - added assign_by_ref() and append_by_ref() functions
+ (Bob Silva, Monte)
+ - changed default warning type for plugin errors from
+ E_USER_WARNING to E_USER_ERROR (Monte)
+ - added $all_extra, $hour_extra, $minute_extra,
+ $second_extra and $meridian_extra parameters to
+ html_select_time function (Rainer Collet, Monte)
+ - update debug console to print objects (Simon Willison,
+ Monte)
+ - fix Config_File class to not error when there are no
+ sections (Peter Kmet, Monte)
+ - add default modifier logic (Monte)
+ - updated popup_init to be xhtml compliant (Tom Oram, Monte)
+ - fix filename bug with windows (Gary Loescher, Monte)
+ - add ability to supply expire time in seconds when clearing
+ cache or compile files (Monte)
+ - add {debug} plugin to distribution (Monte)
+ - fixed bug with insert tags, loading from "script" attribute
+ when caching is enabled (Monte)
+ - fix bug with debug_tpl file path with Windows (.SMK., Monte)
+ - fix append() function with string/array problem (Monte)
+
+Version 2.2.0 (July 11, 2002)
+-----------------------------
+
+ - make debug.tpl work with any delimiter (Monte)
+ - change logic in assign() and append() to test var names
+ against != '' instead of empty() (Monte)
+ - fix PHP notice in append() function (Monte)
+ - allow $plugins_dir to be an array of directories
+ (Andreas Kossmeier, Monte)
+ - move debug.tpl to SMARTY_DIR, add to constructor (Monte)
+ - fixed warning message in function.assign_debug_info (Monte)
+ - fixed $template_dir, $compile_dir, $cache_dir, $config_dir,
+ $plugin_dir to respect include_path (Monte)
+ - fixed warning message with output filter array (Monte)
+ - add optional 2nd parameter to date_format, used as
+ the default date if the passed date is empty (Monte)
+ - gave $reset a default value in cycle plugin (Monte)
+ - fixed warnings with html_select_date and timestamp
+ functions (Monte)
+ - added support for sub directory exlusion format (Monte)
+ - added support for grouping by cache_id, compile_id
+ and segments thereof (Monte)
+ - changed cache and compile files to human readable
+ format (Monte)
+ - remove overlib.js file from distribution (Monte)
+ - fixed bug with 304 Not Modified response sending
+ content (Monte)
+ - fixed cycle function to respect delimiter after
+ initial setting (Monte)
+ - update $GLOBALS references to work properly with
+ track_globals settings (Michal Prinke, Monte)
+ - fixed bug in math function with call to assign
+ (Grigory V. Kareev, Monte)
+ - optimized for loops with count() function calls (Monte)
+ - add month_value_format attribute to html_select_date
+ plugin (Gary Loescher, Monte)
+ - made it possible to use simple variables inside [] for
+ indexing. (Andrei)
+ - added "once" attribute to {include_php}. (Monte)
+
+Version 2.1.1
+-------------
+ - added cycle function. (Monte)
+ - fixed bug with resource testing, and include_path. (Monte)
+ - fixed a bug with register_outputfilter function. (Monte)
+
+Version 2.1.0
+-------------
+
+ - introduced output filters. (Andrei)
+ - changed the way filters are loaded, added load_filter()
+ API function and $autoload_filters variable. (Andrei)
+ - added caching logic for expire times per cache file
+ (Norbert Rocher, Monte)
+ - fixed html_select_date when field separator is "/"
+ (Roberto Berto, Monte)
+ - added YYYY-MM-DD format support to html_select_date
+ (Jan Rosier, Monte)
+ - fixed cache_lifetime logic bug, also made -1 = never
+ expire (Monte)
+ - fixed directory separator issue for Windows. (Andrei)
+ - added ability to use simple variables as array indices or
+ object properties. (Andrei)
+ - added ability to unregister pre/postfilters plugins at
+ runtime. (Andrei)
+ - added 'htmlall' attribute to escape modifier. (Monte)
+ - added template_exists() API function. (Andrei)
+ - fixed a problem with using dynamic values for 'file'
+ attribute of {include_php} tag. (Andrei)
+ - added $smarty.template variable. (Andrei)
+ - fixed several plugins that would not work if the plugin
+ directory was not the default one. (Andrei)
+ - implemented support for block functions. (Andrei)
+ - made it possible to assign variables in pre/postfilter
+ plugins. (Andrei)
+
+Version 2.0.1
+-------------
+ - rename plugin .make_timestamp.php to shared.make_timestamp.php.
+ (Monte)
+ - changed crc32() generated values, replace '-' with 'N'. (Monte)
+ - added support for +/- N syntax in html_select_date year values.
+ (Monte)
+ - fixed behavior of inserts with script attribute. (Andrei)
+ - fixed bug with $smarty.cookies and $smarty.server. (Andrei)
+ - wordwrap and indent are missing from 2.0 release, now fixed.
+ (Monte)
+ - removed show_info_header and show_info_include variables. (Monte)
+
+Version 2.0.0
+-------------
+ - added "eval" function plugin for evaluating variables as
+ templates. (Monte)
+ - removed $tpl_file_ext class variable, no longer used. (Monte)
+ - added "hex" and "hexentity" escape types to escape modifier.
+ (Monte)
+ - removed dependency on PEAR. (Andrei)
+ - update popup_init to accept src attribute. (Monte, Duncan Forrest)
+ - implemented several optimizations, speeding up Smarty
+ significantly in most cases. (Andrei,Monte)
+ - implemented plugin architecture. (Andrei)
+ - added wordwrap and indent modifiers. (Monte)
+ - added support for 'If-Modified-Since' headers for cached content.
+ (Monte)
+ - removed insert_tag_check class variable, no longer needed. (Monte)
+ - optimized cache fetches by scanning for insert tags only if they
+ exist. (Monte)
+ - fixed bugs in overlib. (Monte, Duncan Forrest)
+ - fixed a problem with compile_id usage. (Andrei)
+ - fixed problem with using assigned vars with {include_php ...}
+ filepath. (Monte)
+
+Version 1.5.2
+-------------
+ - added Smarty object as fifth argument for template resource functions.
+ (Monte)
+ - fixed a bug with incorrectly combined cache and compile id in
+ clear_cache(). (Andrei)
+ - fixed bug in smarty_make_timestamp introduced in PHP 4.1.0. (Monte)
+ - fixed bug with cached insert debug timing. (Monte)
+ - added 'script' attribute to {insert..} which specifies the script that
+ the insert function can be found in. (Andrei)
+ - added default template function handler. (Monte)
+
+Version 1.5.1
+-------------
+ - removed error message from the generic _read_file() method, the caller
+ should take care of that. (Andrei)
+ - fixed a bug with incorrectly combined cache and compile id. (Andrei)
+
+Version 1.5.0
+-------------
+ - added include_php built-in function, documented. (Monte)
+ - added trusted_dir functionality, documented. (Monte)
+ - consolidated secure_dir tests to one function. (Monte)
+ - prepended _smarty_ to variable names in fetch() class function to avoid
+ namespace conflicts. (Monte)
+ - introduced $compile_id class variable that can be used to set persistent
+ compile identifier across multiple display calls, documented. (Andrei)
+ - fixed bug with concatenated null cache and compile identifiers. (Andrei)
+ - added $smarty.section.* syntax for accessing section properties,
+ documented. (Andrei)
+ - added custom cache handling function ability, documented. (Monte)
+ - added assign attribute to include, include_php, insert, fetch, math, and
+ counter functions, documented. (Monte)
+ - fixed bug with fetch testing for local file when http address. (Monte)
+ - fixed bug with counter and skipval setting. (Monte)
+ - made {config_load ...} merge globals from each config file only once per
+ scope, thus avoiding several problems. (Andrei)
+ - added {foreach ...} tag that can be used to iterate through
+ non-sequential and associative arrays, documented. (Andrei)
+ - speeded up section property access a bit. (Andrei)
+ - removed $smarty variable from storage used by normal template variables,
+ to prevent any problems. (Andrei)
+ - fixed a bug that could cause parse error with quotes inside literal
+ blocks. (Andrei, Alexander Belonosov)
+ - added 'field_array' attribute to html_select_time function, documented.
+ (Andrei, Michael Caplan)
+ - documented {section} "max" attribute. (Monte)
+ - fixed notice message in Smarty_Compiler.class.php. (Monte)
+ - fixed bug with clear_cache introduced in 1.4.6, third parameter should
+ default to null. (Monte)
+ - updated Config_File class to support '\' path separator in OS/2. (Monte,
+ Francesco Cipriani)
+ - removed secure_ext setting (not used). (Monte)
+ - made cache reading process more efficient. (Monte)
+ - fixed bug, is_cached() now supports new 1.4.6 caching behavior. (Monte)
+ - update FAQ with mailing list Reply-To header FAQ. (Monte)
+ - supress error messages for fopen(), fix cache to regenerate if cache
+ file is not available (i.e. cluster race condition). (Monte)
+ - added index key example to QUICKSTART guide. (Monte)
+
+Version 1.4.6
+-------------
+ - fixed bug with {assign ...} when passing an empty value. (Monte)
+ - add more warning message fixes. (Monte, Tara Johnson)
+ - documentation updates. (Monte)
+ - update fetch function to give proper warning when fetching a non-readable
+ or non-existant file. (Monte)
+ - fixed problem with newline at the end of included templates (Monte, Andrei)
+ - added feature to regenerate cache if compile_check is enabled and an
+ involved template or config file gets modified. (Monte)
+ - added DEBUG execution times to included files: REQUIRES updated debug.tpl
+ file! (Monte)
+ - added support for hidden config variables that cannot be read by
+ templates. (Andrei)
+ - added execution time to DEBUG console, total and inserts. (Monte)
+ - fixed bug where DEBUG console would not appear with cached content. (Monte)
+ - added support for postfilter functions that are applied to compiled
+ template right after compilation. (Andrei)
+ - fixed the name of clear_compile_tpl() API function to clear_compiled_tpl.
+ (Andrei)
+ - added fix for removing comments so that the line numbers are reported
+ correctly in case of errors. (patch from Anders Janson)
+ - made html_options output xhtml compatible code. (Monte, Arnaud Limbourg)
+
+Version 1.4.5
+-------------
+ - update FAQ with index of questions at the top
+ - update overlib to 3.50, adjust addon code so that the overlib.js
+ file isn't modified, and not using the mini one. (Monte)
+ - added many more options to html_select_date. (Alexander Skwar, Andrei)
+ - added support for generating different compiled templates from the same
+ source template. (Hans-Peter Oeri, Andrei)
+ - modified Smarty to pass itself to insert functions as the second
+ parameter. (Andrei)
+ - modified Smarty to pass itself to prefilter functions as the second
+ parameter. (Andrei)
+ - fixed syntax error when including a non-existant template with security
+ enabled. (Monte)
+ - fixed comments handling to allow commenting out template blocks. (Andrei)
+ - implemented named capture buffers, with results accessible via
+ $smarty.capture.<name>. (Andrei)
+ - added ability to index arrays directly by numbers. (Andrei)
+ - fixed bug with SMARTY_DIR not prepended to Config_File include. (Monte)
+
+Version 1.4.4
+-------------
+ - fixed problem with including insecure templates with security enabled.
+ (Monte)
+ - numerous documentation updates. (Monte)
+ - added ENT_QUOTES to escapement of html. (Monte, Sam Beckwith)
+ - implemented access to request variables via auto-assigned $smarty
+ template variable. (Andrei)
+ - fixed a bug with parsing function arguments inside {if} tags if a comma
+ was present. (Andrei)
+ - updated debug console with config file vars. (Monte)
+ - added SMARTY_DIR constant as an alternative to relying on include_path.
+ (Monte)
+ - added popup_init and popup functions (requires overlib.js). (Monte)
+ - updated debug console with config file vars. (Monte)
+ - added debugging url control. (Monte)
+ - added 'quotes' type to escape modifier. (Monte, Mike Krus)
+ - added 'total' and 'iteration' section properties. (Andrei)
+ - added 'start', 'max', and 'step' section attributes/properties. (Andrei)
+ - fixed a bug with security checking of functions inside {if} tags.
+ (Andrei)
+ - fixed a bug in Config_File that would incorrectly booleanize values that
+ weren't really booleans. (Andrei)
+
+Version 1.4.3
+-------------
+ - added regex_replace modifier, documented. (Monte)
+ - added debugging console feature and custom function assign_debug_info,
+ documented. (Monte)
+ - added 'scope' attribute for {config_load}, 'global' is now deprecated but
+ is still supported. (Andrei)
+ - reduced template symbol table pollution by moving config array into the
+ class itself. (Andrei)
+ - fixed a bug with passing quoted arguments to modifiers inside {if}
+ statements. (Andrei, Sam Beckwith)
+ - added security features for third party template editing, documented
+ (Monte)
+ - added assign custom function, documented. (Monte)
+ - fixed bug with template header using version instead of _version. (Monte)
+ - fixed a problem with putting $ followed by numbers inside {strip} and
+ {/strip} tags. (Andrei)
+ - fixed Config_File class to allow empty config paths (defaults to current
+ directory). (Andrei)
+
+Version 1.4.2
+-------------
+ - move $version to internal variable, remove from docs. (Monte)
+ - cleaned up compiled templates global scope by moving some variables into
+ the class itself. (Andrei)
+ - fixed a bug that would not allow referring to a section in the including
+ file from the included file. (Andrei)
+ - configs directory missing from 1.4.1 release, added back in. (Monte)
+ - added windows include_path setup instructions to FAQ & QUICKSTART.
+ (Monte)
+
+Version 1.4.1
+-------------
+ - fix LOCK_EX logic for all windows platforms (Monte)
+ - fixed indexing by section properties with the new syntax. (Andrei)
+ - updated Smarty to use absolute paths when requiring/including Smarty
+ components. (Andrei, John Lim)
+
+Version 1.4.0
+-------------
+ - added {capture}{/capture} function, documented (Monte)
+ - added {counter} function, documented (Monte)
+
+Version 1.4.0b2
+---------------
+ - fixed issue in Config_File.class with referencing blank sections (Andrei)
+ - fixed problem with passing variables to included files (Andrei)
+ - fixed resource path recognition for windows (Monte)
+
+Version 1.4.0b1
+---------------
+ - added "componentized templates" tip into documentation (Monte)
+ - added {php}{/php} tags for embedding php code into templates (Monte)
+ - changed default value of $show_info_header to false (Monte)
+ - implemented '->' syntax for accessing properties of objects passed to the
+ template. (Andrei)
+ - allowed custom functions to receive Smarty object as the second
+ parameter; this can be used to dynamically change template variables, for
+ example. (Andrei)
+ - added custom compiler functions support, register_compiler_function() and
+ unregister_compiler_function() API functions. (Andrei, Ivo Jansch).
+ - updated GLOBAL_ASSIGN to take SCRIPT_NAME from HTTP_SERVER_VARS
+ instead of global variable. You can also assign several variables
+ in one shot with an array. (Monte, Roman Neuhauser)
+ - added template prefilters, register_prefilter() and
+ unregister_prefilter() API functions. (Monte)
+ - added RELEASE_NOTES file to distribution. (Monte)
+ - moved CREDITS out of manual into its own file. (Monte)
+ - added register_resource() and unregister_resource() API functions. (Monte)
+ - changed the syntax of indexing template variables, thus supporting
+ structures of arbitrary complexity; supplied fix_vars.php script to fix
+ old syntax. (Andrei)
+ - added $insert_tag_check to speed up cached pages if {insert ...} is not
+ used. (Monte)
+ - added $compiler_class variable to allow specifying a different compiler
+ class. (Andrei)
+ - changed Smarty to compile templates at runtime, allowing for arbitrary
+ template resources. (Monte)
+ - added fix for LOCK_EX under Windows and changed a couple of file
+ permissions for security. (Monte, Fernando Nunes)
+ - allow arbitrary date strings to date_format, html_select_date and
+ html_select_time (Monte)
+
+Version 1.3.2
+-------------
+ - fixed a bug that caused some nested includes to loop infinitely. (Andrei)
+ - added optional HTML header to output. (Monte)
+ - significantly improved config_load performance. (Andrei)
+ - added format attribute to math function. (Monte)
+ - added html_select_time custom function. (Andrei)
+ - fixed minor PHP warning when attempting to unset an unset variable
+ (Monte)
+ - added count_characters, count_words, count_sentences, count_paragraphs
+ modifiers (Monte)
+
+Version 1.3.1pl1
+--------------
+ - bug fix, recovered missing _syntax_error function (Monte)
+
+Version 1.3.1
+-------------
+ - document first, last, index_prev, index_next (Monte)
+ - added 'first' and 'last' section properties. (Andrei)
+ - split out compiling code to separate class for faster template execution
+ time (Monte)
+ - fixed a couple of minor PHP warnings (Monte)
+ - added and documented unregister_modifier() and unregister_function() API
+ calls. (Monte)
+ - added and documented 'fetch' and 'math' functions. (Monte)
+ - added ability to index looped variables by section properties, e.g.
+ $foo.index_prev/bar. (Andrei)
+ - added index_prev and index_next section properties. (Andrei)
+ - fixed issue with php executing in literal blocks. (Monte)
+
+Version 1.3.0
+-------------
+ - moved license from GPL to LGPL (Monte)
+ - implemented workaround for PHP "feature" that eats carriage returns
+ if the PHP tag is at the end of the line. (Andrei)
+ - removed $allow_php, added $php_handling logic (Monte)
+ - added file locking to prevent reader/writer problem. (Andrei)
+ - made Smarty catch unimplemented modifiers and custom functions and output
+ error messages during compilation instead of failing during run time.
+ (Andrei)
+ - removed short-tags at the top of the smarty scripts (Monte)
+ - added register_function() and register_modifier() API calls to make
+ registering stuff easier. (Andrei)
+ - added template results caching capability. (Monte, Andrei)
+ - added optional 'options' attribute to html_options custom function
+ that allows passing associative arrays for values/output. (Andrei)
+ - modifier arguments can now contain '|' and ':' characters inside quoted
+ strings. (Andrei)
+
+Version 1.2.2
+-------------
+ - fixed bug that would not respect nested template directories and would
+ put all compiled files into top-level one. (Andrei)
+ - fixed bug using $PHP_VERSION instead of environment var PHP_VERSION.
+ (Monte)
+ - a couple small warning fixes. (Monte)
+
+Version 1.2.1
+-------------
+ - added $compile_dir, removed $compile_dir_ext, simplified usage. (Monte)
+ - added tips & tricks chapter to documentation. (Monte)
+ - misc documentation updates. (Monte)
+
+Version 1.2.0
+-------------
+ - updated documentation (Monte)
+ - added file and line number information to syntax error messages. (Andrei)
+ - added ability to index template vars by a key. (Andrei)
+
+Version 1.1.0
+-------------
+ - misc documentation changes, official stable release
+
+Version 1.0b
+------------
+ - fixed the bug that prevented using non-array values for 'loop' attribute.
+ (Andrei)
+ - many misc documentation changes & additions (Monte)
+
+Version 1.0a
+------------
+ - fixed bug that caused templates to recompile every time (Monte)
+
+Version 1.0
+------------
+ - initial release
+
+/* vim: set et tw=64 ft=changelog: */
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/README b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/README
new file mode 100644
index 00000000..db3cf4e5
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/README
@@ -0,0 +1,80 @@
+NAME:
+
+ Smarty - the PHP compiling template engine
+
+VERSION: 2.5.0
+
+AUTHORS:
+
+ Monte Ohrt <monte@ispi.net>
+ Andrei Zmievski <andrei@php.net>
+
+MAILING LISTS:
+
+ We have a few mailing lists. "general" for you to share your ideas or ask
+ questions, "dev" for those interested in the development efforts of Smarty,
+ and "cvs" for those that would like to track the updates made in the cvs
+ repository.
+
+ send a blank e-mail message to:
+ smarty-general-subscribe@lists.php.net (subscribe to the general list)
+ smarty-general-unsubscribe@lists.php.net (unsubscribe from the general list)
+ smarty-general-digest-subscribe@lists.php.net (subscribe to digest)
+ smarty-general-digest-unsubscribe@lists.php.net (unsubscribe from digest)
+ smarty-dev-subscribe@lists.php.net (subscribe to the dev list)
+ smarty-dev-unsubscribe@lists.php.net (unsubscribe from the dev list)
+ smarty-cvs-subscribe@lists.php.net (subscribe to the cvs list)
+ smarty-cvs-unsubscribe@lists.php.net (unsubscribe from the cvs list)
+ You can also browse the mailing list archives at
+ http://marc.theaimsgroup.com/?l=smarty&r=1&w=2
+
+SYNOPSIS:
+
+ require("Smarty.class.php");
+
+ $smarty = new Smarty;
+
+ $smarty->assign("Title","My Homepage");
+ $smarty->assign("Names",array("John","Gary","Gregg","James"));
+
+ $smarty->display("index.tpl");
+
+
+DESCRIPTION:
+
+ What is Smarty?
+
+ Smarty is a template engine for PHP. Many other template engines for PHP
+ provide basic variable substitution and dynamic block functionality.
+ Smarty takes a step further to be a "smart" template engine, adding
+ features such as configuration files, template functions, and variable
+ modifiers, and making all of this functionality as easy as possible to
+ use for both programmers and template designers. Smarty also converts
+ the templates into PHP scripts, eliminating the need to parse the
+ templates on every invocation. This makes Smarty extremely scalable and
+ manageable for large application needs.
+
+ Some of Smarty's features:
+
+ * it is extremely fast
+ * no template parsing overhead, only compiles once.
+ * it is smart about recompiling only the template files that have
+ changed.
+ * the template language is remarkably extensible via the plugin
+ architecture.
+ * configurable template delimiter tag syntax, so you can use
+ {}, {{}}, <!--{}-->, or whatever you like.
+ * built-in caching of template output.
+ * arbitrary template sources (filesystem, databases, etc.)
+ * template if/elseif/else/endif constructs are passed to the PHP parser,
+ so the if syntax can be as simple or as complex as you like.
+ * unlimited nesting of sections, conditionals, etc. allowed
+ * it is possible to embed PHP code right in your template files,
+ although not recommended and doubtfully needed since the engine
+ is so customizable.
+ * and many more.
+
+COPYRIGHT:
+ Copyright (c) 2001,2002 ispi of Lincoln, Inc. All rights reserved.
+ This software is released under the GNU Lesser General Public License.
+ Please read the disclaimer at the top of the Smarty.class.php file.
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/RELEASE_NOTES b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/RELEASE_NOTES
new file mode 100644
index 00000000..7fa1b4b1
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/RELEASE_NOTES
@@ -0,0 +1,423 @@
+2.5.0
+-----
+
+Very minor adjustments since RC2, see the NEWS file for details.
+
+2.5.0-RC2
+---------
+
+Many fixes since the RC1 release. This one is as close to production quality as
+they come, so this will be the last release before 2.5.0. The SGML documentation
+files have also been removed from the tarball. If you want them, get them from
+the CVS repository.
+
+2.5.0-RC1
+---------
+
+Release Candidate 1. All $smarty vars can now be dynamic, such as
+$smarty.get.$foo. A new class function get_function_object() gets you a
+reference to an assigned object, useful within your own custom functions.
+append() can now merge as well as append with a third optional attribute. A new
+class function get_config_vars() was added, and get_template_vars() can now be
+used to get individual vars. Full variable syntax is now supported within
+double quotes via a backtick (`) syntax. Files created by smarty are now
+written to a tmp file then renamed to avoid file lock retention. html_radios,
+html_checkboxes, html_table, html_image, nl2br functions added, see the NEWS
+file for full details.
+
+2.4.2
+-----
+Another point release. Added support for dynamic object reference syntax
+($foo->$bar), support for full variable syntax within quotes ("$foo[0].bar"),
+and other minor fixes. See the NEWS file for full details.
+
+2.4.1
+-----
+
+This is basically a point release, cleaning up a few things caught
+in the 2.4.0 release. See the NEWS file for full details.
+
+2.4.0
+-----
+
+Smarty now supports the ability to access objects within the templates. Two
+methods are available, one which closely follows Smartys conventions, and
+another that follows more traditional object syntax for those familiar with
+PHP.
+
+The internal compiling engine has also undergone some major work. The regex
+parsing was rewritten to be much more strict, more secure and more
+maintainable. Config files are now compiled, which can speed up pages quite a
+bit that use config files extensively. Assigned variables are no longer
+extracted to PHP namespace, saving an extract call for every template. There is
+now support for applying modifiers to static values and functions. You can now
+access constants with $smarty.const.VAR. See the NEWS file for complete
+changes.
+
+2.3.1
+-----
+
+The mtime on compiled files will now match the source files, in the case where
+the source file may not get the current timestamp, recompiling will still work
+as expected. Proper support for open_basedir has been added, so Smarty should
+work correctly in safe mode. Added a few new features such as textformat block
+function, strip variable modifier and optgroup support for html_options. Also
+other minor bug fixes, see the Change Log.
+
+2.3.0
+-----
+
+Smarty now has a {debug} template function that brings up the debugging console
+right where {debug} is called, regardless of $debugging settings. This works a
+little different than turning on $debugging in the sense that it shows all the
+template variables available at the time {debug} is called, including local
+scope vars. It does not show the templates names however, since this
+executed during runtime of the template.
+
+You can now supply an expire time when clearing cache or compile files. This is
+mostly useful for removing stale files via the API.
+
+Plugins now stop execution upon error, instead of outputting a warning and
+continuing.
+
+Two new API functions, assign_by_ref() and append_by_ref() were added. They
+allow assigning template variables by reference. This can make a significant
+performance gain, especially if you are assigning large arrays of data. PHP 5.0
+will do this implicitly, so these functions are basically workarounds.
+
+Several misc bug fixes, see the Change Log for information.
+
+
+2.2.0
+-----
+
+Smarty now allows an array of paths for the $plugin_dir class variable. The
+directories will be searched in the order they are given, so for efficiency keep
+the most-used plugins at the top. Also, absolute paths to the plugin directories are
+more efficient than relying on the PHP include_path.
+
+Cache files can now be grouped with the cache_id. See the documentation under
+the new "Caching" section for details. compile_id also respects the same
+grouping syntax. The cache/compile file structure changed, so be sure to clear
+out all your cache and compile files when upgrading Smarty. Also if you are
+using PHP-accelerator, restart apache. I've seen some quirky things happen if
+the phpa files do not get cleared (known issue with phpa and parent
+class-member changes, so just clear 'em.)
+
+Smarty now correctly respects the PHP include_path for $template_dir, $compile_dir,
+$cache_dir, $config_dir and $plugin_dir. Be aware that relying on the
+include_path is an overhead, try to use absolute pathnames when possible
+(or relative to working directory.)
+
+Documentation has been updated and rearranged a bit. Most notably, the
+installation instructions are completely revamped, and a new Caching section
+explains Smarty's caching in detail along with the new grouping functionality.
+
+Many misc. bug fixes and enhancements, see the full ChangeLog (NEWS file) for
+details.
+
+2.1.1
+-----
+
+There was a bug with template paths and the include_path, this has been fixed.
+Also register_outputfilter() did not work, this is fixed. A new template
+function named "cycle" has been added to the distribution, nice for cycling
+through a list (or array) of values.
+
+2.1.0
+-----
+
+This release has quite a few new features and fixes. Most notable are the
+introduction of block functions, so you can write plugins that work on a block
+of text with {func}{/func} notation. Also output filters were added, so you can
+apply a function against the output of your templates. This differs from the
+postfilter function, which works on the compiled template at compile time, and
+output filters work on the template output at runtime.
+
+Many other features and bug fixes are noted in the NEWS file.
+
+
+2.0.1
+-----
+
+This is a point release, fixing a few bugs and cleaning things up. A plugin
+was renamed, the dash "-" was removed from compiled template and cached file
+names. If you're upgrading, you might want to clear them out first. See the
+ChangeLog for details.
+
+2.0.0
+-----
+
+This release is a huge milestone for Smarty. Most notable new things are a
+plugin architecture, removal of PEAR dependency, and optimizations that
+drastically improve the performance of Smarty in most cases.
+
+The plugin architecture allows modifiers, custom functions, compiler functions,
+prefilters, postfilters, resources, and insert functions to be added by
+simply dropping a file into the plugins directory. Once dropped in, they are
+automatically registered by the template engine. This makes user-contributed
+plugins easy to manage, as well as the internal workings of Smarty easy to
+control and customize. This new architecture depends on the __FILE__ constant,
+which contains the full path to the executing script. Some older versions of
+PHP incorrectly gave the script name and not the full filesystem path. Be sure
+your version of PHP populates __FILE__ correctly. If you use custom template
+resource functions, the format of these changed with the plugin architecture.
+Be sure to update your functions accordingly. See the template resource section
+of the documentation.
+
+The PEAR dependancy was removed from Smarty. The Config_File class that comes
+with Smarty was actually what needed PEAR for error handling which Smarty didn't
+use, but now everything is self-contained.
+
+Performance improvements are graphed on the benchmark page, you will see that
+overall performance has been sped up by as much as 80% in some cases.
+
+Smarty-cached pages now support If-Modified-Since headers, meaning that if a
+cached template page has not changed since the last request, a "304 Not
+Modified" header will be sent instead of resending the same page. This is
+disabled by default, change the setting of $cache_modified_check.
+
+
+1.5.2
+-----
+
+Mostly bug fixes, added a default template resource handler.
+
+
+1.5.1
+-----
+
+Critical bug fix release. If you use caching, you'll need to upgrade.
+
+
+1.5.0
+-----
+
+Several feature enhancements were made to this version, most notably the
+{foreach ...} command which is an alternative to {section ...} with an easier
+syntax for looping through a single array of values. Several functions were
+enhanced so that the output can be automatically assigned to a template
+variable instead of displayed (assign attribute). Cache files can now be
+controlled with a custom function as an alternative to the built-in file based
+method. Many code cleanups and bug fixed went into this release as well.
+
+
+1.4.6
+-----
+
+The behavior with caching and compile_check has been slightly enhanced. If
+caching is enabled AND compile_check is enabled, the cache will immediately get
+regenerated if _any_ involved template or config file is updated. This imposes
+a slight performance hit because it must check all the files for changes, so be
+sure to run live sites with caching enabled and compile_check disabled for best
+performance. If you update a template or config file, simply turn on
+compile_check, load the page, then turn it back off. This will update the cache
+file with the new content. This is accomplished by maintaining a list of
+included/loaded templates and config files at the beginning of the cache file.
+Therefore it is advisable to remove all cache files after upgrading to 1.4.6
+(although not absolutely necessary, old cache files will regenerate)
+
+The debug console now has script timing and array values printed. You MUST
+update your debug.tpl file with this version of Smarty. Also, the new debug.tpl
+will not work with older versions of Smarty.
+
+
+1.4.5
+-----
+
+Mostly bug fixes and minor improvements. Added compile id for separate compiled
+versions of the same script. The directory format and filename convention for
+the files in templates_c has changed, so you may want to remove all of the
+existing ones before you upgrade.
+
+
+1.4.4
+-----
+
+A few bug fixes, new section looping attributes and properties, debugging
+console function for control via URL, and overLib integration and access
+to request variables from within the template.
+
+
+1.4.3
+-----
+
+This release has a few bug fixes and several enhancements. Smarty now supports
+template security for third-party template editing. These features disallow the
+ability for someone to execute commands or PHP code from the template language.
+Smarty also now has a built-in debugging console, which is a javascript pop-up
+window that displays all the included template names and assigned variables.
+
+
+1.4.2
+-----
+
+This was mostly one bug fix with variable scoping within included templates
+and a few documentation changes and updates. See the ChangeLog file for full
+details.
+
+
+1.4.1
+-----
+
+It seems that the EX_LOCK logic from the previous release didn't fix all the
+problems with windows platforms. Hopefully this one does. It basically
+disables file locking on windows, so there is a potential that two programs
+could write over the same file at the same time, fyi.
+
+The reset is minor bug fixes, please refer to the ChangeLog file.
+
+
+1.4.0
+-----
+
+IMPORTANT NOTICE
+
+Smarty now has a new syntax for accessing elements within section loops. The
+new syntax is easier to use and nicely handles data structures of any
+complexity. Consequently, this breaks the old syntax.
+
+Here is an example of the syntax change:
+
+old syntax:
+{$sec1/sec2/sec3/customer.phone}
+
+new syntax:
+{$customer[$sec1][$sec2][$sec3].phone}
+
+The section names used to come first, followed by the variable name. Now the
+variable name always comes first, followed by the section names in brackets.
+You can access variable indexes anywhere, depending on how you passed the
+variables in.
+
+To fix your current templates, we have provided a script that will adjust the
+syntax for you. Located in misc/fix_vars.php, run this script from the the
+command line, giving each template as an argument. Be sure to use absolute
+pathnames, or pathnames relative to the executing script. Probably the easiest
+way to do this is to copy the fix_vars.php script into your template directory
+and run 'php -q fix_vars.php *.tpl' Be sure you have proper write permission,
+and backup your scripts first to be safe! The examples in the 1.4.0
+documentation have been updated to reflect the changes.
+
+cd /path/to/templates
+cp /path/to/fix_vars.php .
+find . -name "*.tpl" -exec php -q ./fix_vars.php {} \;
+
+NEW AND IMPROVED COMPILATION PROCESS
+
+Smarty 1.4.0 also has a new compilation process. Instead of compiling all the
+templates up front, it now compiles them at runtime. This has several
+advantages. First of all, there is no longer a need to have a single template
+directory. You can now have arbitrary template sources, such as multiple
+directories or even database calls. This also speeds the performance of Smarty
+when $compile_check is enabled, since it is only checking the template that is
+being executed instead of everything found in the template directory. The
+$tpl_file_ext is no longer needed, but kept for backward compatability.
+Templates can now be named anything you like with any extension.
+
+MINOR FIXES
+
+A workaround for LOCK_EX on Windows systems was added, and changed a couple of
+file permissions for better security on public servers.
+
+$show_info_header is now defaulted to false instead of true. This header causes
+problems when displaying content other than HTML, so now you must explicitly
+set this flag to true to show the header information (or change the default in
+your copy of Smarty.)
+
+Documentation is written in docbook format. I updated the docbook -> HTML
+generating software & style-sheets, and consequently the examples are no longer
+in a different background color. If anyone wants to contribute a better
+stylesheet or help with documentation, drop me a line. <monte@ispi.net>
+
+CHANGES/ENHANCEMENTS/UPDATES
+
+date_format, html_select_date and html_select_time used to require a unix
+timestamp as the format of the date passed into the template. Smarty is now a
+bit smarter at this. It will take a unix timestamp, a mysql timestamp, or any
+date string that is parsable by strtotime, such as 10/01/2001 or 2001-10-01,
+etc. Just give some formats a try and see what works.
+
+Smarty now has template prefilters, meaning that you can run your templates
+through custom functions before they are compiled. This is good for things like
+removing unwanted comments, keeping an eye on words or functionality people are
+putting in templates, translating XML -> HTML, etc. See the register_prefilter
+documentation for more info.
+
+Another addition are the so-called compiler functions. These are custom
+functions registered by the user that are executed at compilation time of the
+template. They can be used to inject PHP code or time-sensitive static content
+into the compiled template.
+
+The run-time custom functions are now passed the Smarty object as the second
+parameter. This can be used, for example, to assign or clear template variables
+from inside the custom function.
+
+clear_compile_dir() was added for clearing out compiled versions of your
+templates. Not something normally needed, but you may have a need for this if
+you have $compile_check set to false and you periodically update templates via
+some automated process. As of 1.4.0, uncompiled templates _always_ get
+compiled regardless of $compile_check setting, although they won't be checked
+for recompile if $compile_check is set to false.
+
+You can now refer to properties of objects assigned from PHP by using the '->'
+symbol and specifying the property name after it, e.g. $foo->bar.
+
+{php}{/php} tags were added to embed php into the templates. Not normally
+needed, but some circumstances may call for it. Check out the "componentized
+templates" tip in the documentation for an example.
+
+{capture}{/capture} and {counter} functions were added. See the documentation
+for a complete description and examples.
+
+UPGRADE NOTES
+
+The format of the files created in the $compile_dir are now a bit different.
+The compiled template filename is the template resource name url-encoded.
+Therefore, all compiled files are now in the top directory of $compile_dir.
+This was done to make way for arbitrary template resources. Each compiled
+template also has a header that states what template resource was used to
+create it. From a unix command prompt, you can use "head -2 *" to see the first
+two lines of each file.
+
+When upgrading to 1.4.0, you will want to clear out all your old files in the
+$compile_dir. If you have $compile_check set to false and the compiled template
+does not yet exist, it will compile it regardless of this setting. This way you
+can clear out the $compile_dir and not worry about setting $compile_check to
+true to get the inital compilation under way.
+
+
+1.3.2
+-----
+
+Smarty now has (an optional) header prepended to the output of the Smarty
+templates. This displays the Smarty version and the date/time when the page was
+generated. This is useful for debugging your cache routines, and purely
+informational so there is evidence that the page was generated by Smarty. Set
+$show_info_header to false to disable it.
+
+{config_load ...} performance was tuned by placing the loaded variables into a
+global array, so basically a config file is read from the file system and
+placed into a php array structure only once, no matter how many times it is
+called in any of the templates. The scope of the loaded variables has changed a
+bit as well. Variables loaded by config_load used to be treated as global
+variables, meaning that parent templates (templates that included the current
+template) could see them. Now the default behavior is such that loaded
+variables are only visible by the current template and child templates (all
+templates included after the {config_load ...} is called.) To mimic the
+original behavior, provide the attribute "global=yes" like so: {config_load
+file="mystuff.conf" global=yes}. Now when you load in mystuff.conf, the
+variables will be visible to parent templates (merged with any existing config
+variables.)
+
+A formatting attribute was added to the {math ...} function, adding the ability
+to control the format of the output. Use the same formatting syntax as the PHP
+function sprintf().
+
+{html_select_time ...} was added, a custom function that works much like
+{html_select_date ...} except it displays time elements instead of dates.
+
+A few custom modifiers were added: count_characters, count_words,
+count_sentences, count_paragraphs. All pretty self-explanatory.
+
+/* vim: set et: */
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/TODO b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/TODO
new file mode 100644
index 00000000..183dd7ae
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/TODO
@@ -0,0 +1,12 @@
+* handle asp style tags in $php_handler
+* support implementations of prefiltes, mods, and others as class methods.
+* ability to concatenate values/strings together
+* fix all E_NOTICE warnings
+* make simple math easier
+* caching all but parts of the template
+* change plugins so $smarty variable always comes first
+* get cache ttl with function call
+FIX: make inserts use normal functions before plugins
+UPD: change it so that if template comes from some resource,
+ that resource stays as the default, no need to specify it
+ in includes.
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/Config_File.class.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/Config_File.class.php
new file mode 100644
index 00000000..2b99af21
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/Config_File.class.php
@@ -0,0 +1,365 @@
+<?php
+
+/**
+ * Config_File class.
+ *
+ * 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
+ *
+ * You may contact the author of Config_File by e-mail at:
+ * {@link andrei@php.net}
+ *
+ * The latest version of Config_File can be obtained from:
+ * http://smarty.php.net/
+ *
+ * @link http://smarty.php.net/
+ * @version 2.6.0
+ * @copyright Copyright: 2001-2003 ispi of Lincoln, Inc.
+ * @author Andrei Zmievski <andrei@php.net>
+ * @access public
+ * @package Smarty
+ */
+
+/* $Id: Config_File.class.php,v 1.1 2005/10/17 18:37:39 jeichorn Exp $ */
+/**
+ * Config file reading class
+ * @package Smarty
+ */
+class Config_File {
+ /**#@+
+ * Options
+ * @var boolean
+ */
+ /**
+ * Controls whether variables with the same name overwrite each other.
+ */
+ var $overwrite = true;
+
+ /**
+ * Controls whether config values of on/true/yes and off/false/no get
+ * converted to boolean values automatically.
+ */
+ var $booleanize = true;
+
+ /**
+ * Controls whether hidden config sections/vars are read from the file.
+ */
+ var $read_hidden = true;
+
+ /**
+ * Controls whether or not to fix mac or dos formatted newlines.
+ * If set to true, \r or \r\n will be changed to \n.
+ */
+ var $fix_newlines = true;
+ /**#@-*/
+
+ /** @access private */
+ var $_config_path = "";
+ var $_config_data = array();
+ /**#@-*/
+
+ /**
+ * Constructs a new config file class.
+ *
+ * @param string $config_path (optional) path to the config files
+ */
+ function Config_File($config_path = NULL)
+ {
+ if (isset($config_path))
+ $this->set_path($config_path);
+ }
+
+
+ /**
+ * Set the path where configuration files can be found.
+ *
+ * @param string $config_path path to the config files
+ */
+ function set_path($config_path)
+ {
+ if (!empty($config_path)) {
+ if (!is_string($config_path) || !file_exists($config_path) || !is_dir($config_path)) {
+ $this->_trigger_error_msg("Bad config file path '$config_path'");
+ return;
+ }
+ if(substr($config_path, -1) != DIRECTORY_SEPARATOR) {
+ $config_path .= DIRECTORY_SEPARATOR;
+ }
+
+ $this->_config_path = $config_path;
+ }
+ }
+
+
+ /**
+ * Retrieves config info based on the file, section, and variable name.
+ *
+ * @param string $file_name config file to get info for
+ * @param string $section_name (optional) section to get info for
+ * @param string $var_name (optional) variable to get info for
+ * @return string|array a value or array of values
+ */
+ function &get($file_name, $section_name = NULL, $var_name = NULL)
+ {
+ if (empty($file_name)) {
+ $this->_trigger_error_msg('Empty config file name');
+ return;
+ } else {
+ $file_name = $this->_config_path . $file_name;
+ if (!isset($this->_config_data[$file_name]))
+ $this->load_file($file_name, false);
+ }
+
+ if (!empty($var_name)) {
+ if (empty($section_name)) {
+ return $this->_config_data[$file_name]["vars"][$var_name];
+ } else {
+ if(isset($this->_config_data[$file_name]["sections"][$section_name]["vars"][$var_name]))
+ return $this->_config_data[$file_name]["sections"][$section_name]["vars"][$var_name];
+ else
+ return array();
+ }
+ } else {
+ if (empty($section_name)) {
+ return (array)$this->_config_data[$file_name]["vars"];
+ } else {
+ if(isset($this->_config_data[$file_name]["sections"][$section_name]["vars"]))
+ return (array)$this->_config_data[$file_name]["sections"][$section_name]["vars"];
+ else
+ return array();
+ }
+ }
+ }
+
+
+ /**
+ * Retrieves config info based on the key.
+ *
+ * @param $file_name string config key (filename/section/var)
+ * @return string|array same as get()
+ * @uses get() retrieves information from config file and returns it
+ */
+ function &get_key($config_key)
+ {
+ list($file_name, $section_name, $var_name) = explode('/', $config_key, 3);
+ $result = &$this->get($file_name, $section_name, $var_name);
+ return $result;
+ }
+
+ /**
+ * Get all loaded config file names.
+ *
+ * @return array an array of loaded config file names
+ */
+ function get_file_names()
+ {
+ return array_keys($this->_config_data);
+ }
+
+
+ /**
+ * Get all section names from a loaded file.
+ *
+ * @param string $file_name config file to get section names from
+ * @return array an array of section names from the specified file
+ */
+ function get_section_names($file_name)
+ {
+ $file_name = $this->_config_path . $file_name;
+ if (!isset($this->_config_data[$file_name])) {
+ $this->_trigger_error_msg("Unknown config file '$file_name'");
+ return;
+ }
+
+ return array_keys($this->_config_data[$file_name]["sections"]);
+ }
+
+
+ /**
+ * Get all global or section variable names.
+ *
+ * @param string $file_name config file to get info for
+ * @param string $section_name (optional) section to get info for
+ * @return array an array of variables names from the specified file/section
+ */
+ function get_var_names($file_name, $section = NULL)
+ {
+ if (empty($file_name)) {
+ $this->_trigger_error_msg('Empty config file name');
+ return;
+ } else if (!isset($this->_config_data[$file_name])) {
+ $this->_trigger_error_msg("Unknown config file '$file_name'");
+ return;
+ }
+
+ if (empty($section))
+ return array_keys($this->_config_data[$file_name]["vars"]);
+ else
+ return array_keys($this->_config_data[$file_name]["sections"][$section]["vars"]);
+ }
+
+
+ /**
+ * Clear loaded config data for a certain file or all files.
+ *
+ * @param string $file_name file to clear config data for
+ */
+ function clear($file_name = NULL)
+ {
+ if ($file_name === NULL)
+ $this->_config_data = array();
+ else if (isset($this->_config_data[$file_name]))
+ $this->_config_data[$file_name] = array();
+ }
+
+
+ /**
+ * Load a configuration file manually.
+ *
+ * @param string $file_name file name to load
+ * @param boolean $prepend_path whether current config path should be
+ * prepended to the filename
+ */
+ function load_file($file_name, $prepend_path = true)
+ {
+ if ($prepend_path && $this->_config_path != "")
+ $config_file = $this->_config_path . $file_name;
+ else
+ $config_file = $file_name;
+
+ ini_set('track_errors', true);
+ $fp = @fopen($config_file, "r");
+ if (!is_resource($fp)) {
+ $this->_trigger_error_msg("Could not open config file '$config_file'");
+ return false;
+ }
+
+ $contents = fread($fp, filesize($config_file));
+ fclose($fp);
+
+ if($this->fix_newlines) {
+ // fix mac/dos formatted newlines
+ $contents = preg_replace('!\r\n?!',"\n",$contents);
+ }
+
+ $config_data = array();
+
+ /* replace all multi-line values by placeholders */
+ if (preg_match_all('/"""(.*)"""/Us', $contents, $match)) {
+ $_triple_quotes = $match[1];
+ $_i = 0;
+ $contents = preg_replace('/""".*"""/Use', '"\x1b\x1b\x1b".$_i++."\x1b\x1b\x1b"', $contents);
+ } else {
+ $_triple_quotes = null;
+ }
+
+ /* Get global variables first. */
+ if ($contents{0} != '[' && preg_match("/^(.*?)(\n\[|\Z)/s", $contents, $match))
+ $config_data["vars"] = $this->_parse_config_block($match[1], $_triple_quotes);
+
+ /* Get section variables. */
+ $config_data["sections"] = array();
+ preg_match_all("/^\[(.*?)\]/m", $contents, $match);
+ foreach ($match[1] as $section) {
+ if ($section{0} == '.' && !$this->read_hidden)
+ continue;
+ if (preg_match("/\[".preg_quote($section, '/')."\](.*?)(\n\[|\Z)/s", $contents, $match))
+ if ($section{0} == '.')
+ $section = substr($section, 1);
+ $config_data["sections"][$section]["vars"] = $this->_parse_config_block($match[1], $_triple_quotes);
+ }
+
+ $this->_config_data[$config_file] = $config_data;
+
+ return true;
+ }
+
+ /**#@+ @access private */
+ /**
+ * @var string $config_block
+ */
+ function _parse_config_block($config_block, $triple_quotes)
+ {
+ $vars = array();
+
+ /* First we grab the multi-line values. */
+ if (preg_match_all("/^([^=\n]+)=\s*\x1b\x1b\x1b(\d+)\x1b\x1b\x1b\s*$/ms", $config_block, $match, PREG_SET_ORDER)) {
+ for ($i = 0; $i < count($match); $i++) {
+ $this->_set_config_var($vars, trim($match[$i][1]), $triple_quotes[$match[$i][2]], false);
+ }
+ $config_block = preg_replace("/^[^=\n]+=\s*\x1b\x1b\x1b\d+\x1b\x1b\x1b\s*$/ms", "", $config_block);
+ }
+
+
+ $config_lines = preg_split("/\n+/", $config_block);
+
+ foreach ($config_lines as $line) {
+ if (preg_match("/^\s*(\.?\w+)\s*=(.*)/", $line, $match)) {
+ $var_value = preg_replace('/^([\'"])(.*)\1$/', '\2', trim($match[2]));
+ $this->_set_config_var($vars, trim($match[1]), $var_value, $this->booleanize);
+ }
+ }
+
+ return $vars;
+ }
+
+ /**
+ * @param array &$container
+ * @param string $var_name
+ * @param mixed $var_value
+ * @param boolean $booleanize determines whether $var_value is converted to
+ * to true/false
+ */
+ function _set_config_var(&$container, $var_name, $var_value, $booleanize)
+ {
+ if ($var_name{0} == '.') {
+ if (!$this->read_hidden)
+ return;
+ else
+ $var_name = substr($var_name, 1);
+ }
+
+ if (!preg_match("/^[a-zA-Z_]\w*$/", $var_name)) {
+ $this->_trigger_error_msg("Bad variable name '$var_name'");
+ return;
+ }
+
+ if ($booleanize) {
+ if (preg_match("/^(on|true|yes)$/i", $var_value))
+ $var_value = true;
+ else if (preg_match("/^(off|false|no)$/i", $var_value))
+ $var_value = false;
+ }
+
+ if (!isset($container[$var_name]) || $this->overwrite)
+ $container[$var_name] = $var_value;
+ else {
+ settype($container[$var_name], 'array');
+ $container[$var_name][] = $var_value;
+ }
+ }
+
+ /**
+ * @uses trigger_error() creates a PHP warning/error
+ * @param string $error_msg
+ * @param integer $error_type one of
+ */
+ function _trigger_error_msg($error_msg, $error_type = E_USER_WARNING)
+ {
+ trigger_error("Config_File error: $error_msg", $error_type);
+ }
+ /**#@-*/
+}
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/Smarty.class.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/Smarty.class.php
new file mode 100644
index 00000000..1909acab
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/Smarty.class.php
@@ -0,0 +1,2010 @@
+<?php
+
+/**
+ * Project: Smarty: the PHP compiling template engine
+ * File: Smarty.class.php
+ *
+ * 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
+ *
+ * For questions, help, comments, discussion, etc., please join the
+ * Smarty mailing list. Send a blank e-mail to
+ * smarty-general-subscribe@lists.php.net
+ *
+ * You may contact the authors of Smarty by e-mail at:
+ * monte@ispi.net
+ * andrei@php.net
+ *
+ * Or, write to:
+ * Monte Ohrt
+ * Director of Technology, ispi
+ * 237 S. 70th suite 220
+ * Lincoln, NE 68510
+ *
+ * The latest version of Smarty can be obtained from:
+ * http://smarty.php.net/
+ *
+ * @link http://smarty.php.net/
+ * @copyright 2001-2003 ispi of Lincoln, Inc.
+ * @author Monte Ohrt <monte@ispi.net>
+ * @author Andrei Zmievski <andrei@php.net>
+ * @package Smarty
+ * @version 2.6.0
+ */
+
+/* $Id: Smarty.class.php,v 1.1 2005/10/17 18:37:39 jeichorn Exp $ */
+
+/**
+ * DIR_SEP isn't used anymore, but third party apps might
+ */
+if(!defined('DIR_SEP')) {
+ define('DIR_SEP', DIRECTORY_SEPARATOR);
+}
+
+/**
+ * set SMARTY_DIR to absolute path to Smarty library files.
+ * if not defined, include_path will be used. Sets SMARTY_DIR only if user
+ * application has not already defined it.
+ */
+
+if (!defined('SMARTY_DIR')) {
+ define('SMARTY_DIR', dirname(__FILE__) . DIRECTORY_SEPARATOR);
+}
+
+define('SMARTY_PHP_PASSTHRU', 0);
+define('SMARTY_PHP_QUOTE', 1);
+define('SMARTY_PHP_REMOVE', 2);
+define('SMARTY_PHP_ALLOW', 3);
+
+/**
+ * @package Smarty
+ */
+class Smarty
+{
+ /**#@+
+ * Smarty Configuration Section
+ */
+
+ /**
+ * The name of the directory where templates are located.
+ *
+ * @var string
+ */
+ var $template_dir = 'templates';
+
+ /**
+ * The directory where compiled templates are located.
+ *
+ * @var string
+ */
+ var $compile_dir = 'templates_c';
+
+ /**
+ * The directory where config files are located.
+ *
+ * @var string
+ */
+ var $config_dir = 'configs';
+
+ /**
+ * An array of directories searched for plugins.
+ *
+ * @var array
+ */
+ var $plugins_dir = array('plugins');
+
+ /**
+ * If debugging is enabled, a debug console window will display
+ * when the page loads (make sure your browser allows unrequested
+ * popup windows)
+ *
+ * @var boolean
+ */
+ var $debugging = false;
+
+ /**
+ * This is the path to the debug console template. If not set,
+ * the default one will be used.
+ *
+ * @var string
+ */
+ var $debug_tpl = '';
+
+ /**
+ * This determines if debugging is enable-able from the browser.
+ * <ul>
+ * <li>NONE => no debugging control allowed</li>
+ * <li>URL => enable debugging when SMARTY_DEBUG is found in the URL.</li>
+ * </ul>
+ * @link http://www.foo.dom/index.php?SMARTY_DEBUG
+ * @var string
+ */
+ var $debugging_ctrl = 'NONE';
+
+ /**
+ * This tells Smarty whether to check for recompiling or not. Recompiling
+ * does not need to happen unless a template or config file is changed.
+ * Typically you enable this during development, and disable for
+ * production.
+ *
+ * @var boolean
+ */
+ var $compile_check = true;
+
+ /**
+ * This forces templates to compile every time. Useful for development
+ * or debugging.
+ *
+ * @var boolean
+ */
+ var $force_compile = false;
+
+ /**
+ * This enables template caching.
+ * <ul>
+ * <li>0 = no caching</li>
+ * <li>1 = use class cache_lifetime value</li>
+ * <li>2 = use cache_lifetime in cache file</li>
+ * </ul>
+ * @var integer
+ */
+ var $caching = 0;
+
+ /**
+ * The name of the directory for cache files.
+ *
+ * @var string
+ */
+ var $cache_dir = 'cache';
+
+ /**
+ * This is the number of seconds cached content will persist.
+ * <ul>
+ * <li>0 = always regenerate cache</li>
+ * <li>-1 = never expires</li>
+ * </ul>
+ *
+ * @var integer
+ */
+ var $cache_lifetime = 3600;
+
+ /**
+ * Only used when $caching is enabled. If true, then If-Modified-Since headers
+ * are respected with cached content, and appropriate HTTP headers are sent.
+ * This way repeated hits to a cached page do not send the entire page to the
+ * client every time.
+ *
+ * @var boolean
+ */
+ var $cache_modified_check = false;
+
+ /**
+ * This determines how Smarty handles "<?php ... ?>" tags in templates.
+ * possible values:
+ * <ul>
+ * <li>SMARTY_PHP_PASSTHRU -> print tags as plain text</li>
+ * <li>SMARTY_PHP_QUOTE -> escape tags as entities</li>
+ * <li>SMARTY_PHP_REMOVE -> remove php tags</li>
+ * <li>SMARTY_PHP_ALLOW -> execute php tags</li>
+ * </ul>
+ *
+ * @var integer
+ */
+ var $php_handling = SMARTY_PHP_PASSTHRU;
+
+ /**
+ * This enables template security. When enabled, many things are restricted
+ * in the templates that normally would go unchecked. This is useful when
+ * untrusted parties are editing templates and you want a reasonable level
+ * of security. (no direct execution of PHP in templates for example)
+ *
+ * @var boolean
+ */
+ var $security = false;
+
+ /**
+ * This is the list of template directories that are considered secure. This
+ * is used only if {@link $security} is enabled. One directory per array
+ * element. {@link $template_dir} is in this list implicitly.
+ *
+ * @var array
+ */
+ var $secure_dir = array();
+
+ /**
+ * These are the security settings for Smarty. They are used only when
+ * {@link $security} is enabled.
+ *
+ * @var array
+ */
+ var $security_settings = array(
+ 'PHP_HANDLING' => false,
+ 'IF_FUNCS' => array('array', 'list',
+ 'isset', 'empty',
+ 'count', 'sizeof',
+ 'in_array', 'is_array',
+ 'true','false'),
+ 'INCLUDE_ANY' => false,
+ 'PHP_TAGS' => false,
+ 'MODIFIER_FUNCS' => array('count'),
+ 'ALLOW_CONSTANTS' => false
+ );
+
+ /**
+ * This is an array of directories where trusted php scripts reside.
+ * {@link $security} is disabled during their inclusion/execution.
+ *
+ * @var array
+ */
+ var $trusted_dir = array();
+
+ /**
+ * The left delimiter used for the template tags.
+ *
+ * @var string
+ */
+ var $left_delimiter = '{';
+
+ /**
+ * The right delimiter used for the template tags.
+ *
+ * @var string
+ */
+ var $right_delimiter = '}';
+
+ /**
+ * The order in which request variables are registered, similar to
+ * variables_order in php.ini E = Environment, G = GET, P = POST,
+ * C = Cookies, S = Server
+ *
+ * @var string
+ */
+ var $request_vars_order = "EGPCS";
+
+ /**
+ * Indicates wether $HTTP_*_VARS[] (request_use_auto_globals=false)
+ * are uses as request-vars or $_*[]-vars. note: if
+ * request_use_auto_globals is true, then $request_vars_order has
+ * no effect, but the php-ini-value "gpc_order"
+ *
+ * @var boolean
+ */
+ var $request_use_auto_globals = false;
+
+ /**
+ * Set this if you want different sets of compiled files for the same
+ * templates. This is useful for things like different languages.
+ * Instead of creating separate sets of templates per language, you
+ * set different compile_ids like 'en' and 'de'.
+ *
+ * @var string
+ */
+ var $compile_id = null;
+
+ /**
+ * This tells Smarty whether or not to use sub dirs in the cache/ and
+ * templates_c/ directories. sub directories better organized, but
+ * may not work well with PHP safe mode enabled.
+ *
+ * @var boolean
+ *
+ */
+ var $use_sub_dirs = true;
+
+ /**
+ * This is a list of the modifiers to apply to all template variables.
+ * Put each modifier in a separate array element in the order you want
+ * them applied. example: <code>array('escape:"htmlall"');</code>
+ *
+ * @var array
+ */
+ var $default_modifiers = array();
+
+ /**
+ * This is the resource type to be used when not specified
+ * at the beginning of the resource path. examples:
+ * $smarty->display('file:index.tpl');
+ * $smarty->display('db:index.tpl');
+ * $smarty->display('index.tpl'); // will use default resource type
+ * {include file="file:index.tpl"}
+ * {include file="db:index.tpl"}
+ * {include file="index.tpl"} {* will use default resource type *}
+ *
+ * @var array
+ */
+ var $default_resource_type = 'file';
+
+ /**
+ * The function used for cache file handling. If not set, built-in caching is used.
+ *
+ * @var null|string function name
+ */
+ var $cache_handler_func = null;
+
+ /**
+ * These are the variables from the globals array that are
+ * assigned to all templates automatically. This isn't really
+ * necessary any more, you can use the $smarty var to access them
+ * directly.
+ *
+ * @var array
+ */
+ var $global_assign = array('HTTP_SERVER_VARS' => array('SCRIPT_NAME'));
+
+ /**
+ * The value of "undefined". Leave it alone :-)
+ *
+ * @var null
+ */
+ var $undefined = null;
+
+ /**
+ * This indicates which filters are automatically loaded into Smarty.
+ *
+ * @var array array of filter names
+ */
+ var $autoload_filters = array();
+
+ /**#@+
+ * @var boolean
+ */
+ /**
+ * This tells if config file vars of the same name overwrite each other or not.
+ * if disabled, same name variables are accumulated in an array.
+ */
+ var $config_overwrite = true;
+
+ /**
+ * This tells whether or not to automatically booleanize config file variables.
+ * If enabled, then the strings "on", "true", and "yes" are treated as boolean
+ * true, and "off", "false" and "no" are treated as boolean false.
+ */
+ var $config_booleanize = true;
+
+ /**
+ * This tells whether hidden sections [.foobar] are readable from the
+ * tempalates or not. Normally you would never allow this since that is
+ * the point behind hidden sections: the application can access them, but
+ * the templates cannot.
+ */
+ var $config_read_hidden = false;
+
+ /**
+ * This tells whether or not automatically fix newlines in config files.
+ * It basically converts \r (mac) or \r\n (dos) to \n
+ */
+ var $config_fix_newlines = true;
+ /**#@-*/
+
+ /**
+ * If a template cannot be found, this PHP function will be executed.
+ * Useful for creating templates on-the-fly or other special action.
+ *
+ * @var string function name
+ */
+ var $default_template_handler_func = '';
+
+ /**
+ * The file that contains the compiler class. This can a full
+ * pathname, or relative to the php_include path.
+ *
+ * @var string
+ */
+ var $compiler_file = 'Smarty_Compiler.class.php';
+
+ /**
+ * The class used for compiling templates.
+ *
+ * @var string
+ */
+ var $compiler_class = 'Smarty_Compiler';
+
+ /**
+ * The class used to load config vars.
+ *
+ * @var string
+ */
+ var $config_class = 'Config_File';
+
+/**#@+
+ * END Smarty Configuration Section
+ * There should be no need to touch anything below this line.
+ * @access private
+ */
+ /**
+ * error messages. true/false
+ *
+ * @var boolean
+ */
+ var $_error_msg = false;
+
+ /**
+ * where assigned template vars are kept
+ *
+ * @var array
+ */
+ var $_tpl_vars = array();
+
+ /**
+ * stores run-time $smarty.* vars
+ *
+ * @var null|array
+ */
+ var $_smarty_vars = null;
+
+ /**
+ * keeps track of sections
+ *
+ * @var array
+ */
+ var $_sections = array();
+
+ /**
+ * keeps track of foreach blocks
+ *
+ * @var array
+ */
+ var $_foreach = array();
+
+ /**
+ * keeps track of tag hierarchy
+ *
+ * @var array
+ */
+ var $_tag_stack = array();
+
+ /**
+ * configuration object
+ *
+ * @var Config_file
+ */
+ var $_conf_obj = null;
+
+ /**
+ * loaded configuration settings
+ *
+ * @var array
+ */
+ var $_config = array(array('vars' => array(), 'files' => array()));
+
+ /**
+ * md5 checksum of the string 'Smarty'
+ *
+ * @var string
+ */
+ var $_smarty_md5 = 'f8d698aea36fcbead2b9d5359ffca76f';
+
+ /**
+ * Smarty version number
+ *
+ * @var string
+ */
+ var $_version = '2.6.0';
+
+ /**
+ * current template inclusion depth
+ *
+ * @var integer
+ */
+ var $_inclusion_depth = 0;
+
+ /**
+ * for different compiled templates
+ *
+ * @var string
+ */
+ var $_compile_id = null;
+
+ /**
+ * text in URL to enable debug mode
+ *
+ * @var string
+ */
+ var $_smarty_debug_id = 'SMARTY_DEBUG';
+
+ /**
+ * debugging information for debug console
+ *
+ * @var array
+ */
+ var $_smarty_debug_info = array();
+
+ /**
+ * info that makes up a cache file
+ *
+ * @var array
+ */
+ var $_cache_info = array();
+
+ /**
+ * default file permissions
+ *
+ * @var integer
+ */
+ var $_file_perms = 0644;
+
+ /**
+ * default dir permissions
+ *
+ * @var integer
+ */
+ var $_dir_perms = 0771;
+
+ /**
+ * registered objects
+ *
+ * @var array
+ */
+ var $_reg_objects = array();
+
+ /**
+ * table keeping track of plugins
+ *
+ * @var array
+ */
+ var $_plugins = array(
+ 'modifier' => array(),
+ 'function' => array(),
+ 'block' => array(),
+ 'compiler' => array(),
+ 'prefilter' => array(),
+ 'postfilter' => array(),
+ 'outputfilter' => array(),
+ 'resource' => array(),
+ 'insert' => array());
+
+
+ /**
+ * cache serials
+ *
+ * @var array
+ */
+ var $_cache_serials = array();
+
+ /**
+ * name of optional cache include file
+ *
+ * @var string
+ */
+ var $_cache_include = null;
+
+ /**
+ * indicate if the current code is used in a compiled
+ * include
+ *
+ * @var string
+ */
+ var $_cache_including = false;
+
+ /**#@-*/
+ /**
+ * The class constructor.
+ *
+ * @uses $global_assign uses {@link assign()} to assign each corresponding
+ * value from $GLOBALS to the template vars
+ */
+ function Smarty()
+ {
+ foreach ($this->global_assign as $key => $var_name) {
+ if (is_array($var_name)) {
+ foreach ($var_name as $var) {
+ if (isset($GLOBALS[$key][$var])) {
+ $this->assign($var, $GLOBALS[$key][$var]);
+ } else {
+ $this->assign($var, $this->undefined);
+ }
+ }
+ } else {
+ if (isset($GLOBALS[$var_name])) {
+ $this->assign($var_name, $GLOBALS[$var_name]);
+ } else {
+ $this->assign($var_name, $this->undefined);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * assigns values to template variables
+ *
+ * @param array|string $tpl_var the template variable name(s)
+ * @param mixed $value the value to assign
+ */
+ function assign($tpl_var, $value = null)
+ {
+ if (is_array($tpl_var)){
+ foreach ($tpl_var as $key => $val) {
+ if ($key != '') {
+ $this->_tpl_vars[$key] = $val;
+ }
+ }
+ } else {
+ if ($tpl_var != '')
+ $this->_tpl_vars[$tpl_var] = $value;
+ }
+ }
+
+ /**
+ * assigns values to template variables by reference
+ *
+ * @param string $tpl_var the template variable name
+ * @param mixed $value the referenced value to assign
+ */
+ function assign_by_ref($tpl_var, &$value)
+ {
+ if ($tpl_var != '')
+ $this->_tpl_vars[$tpl_var] = &$value;
+ }
+
+ /**
+ * appends values to template variables
+ *
+ * @param array|string $tpl_var the template variable name(s)
+ * @param mixed $value the value to append
+ */
+ function append($tpl_var, $value=null, $merge=false)
+ {
+ if (is_array($tpl_var)) {
+ // $tpl_var is an array, ignore $value
+ foreach ($tpl_var as $_key => $_val) {
+ if ($_key != '') {
+ if(!@is_array($this->_tpl_vars[$_key])) {
+ settype($this->_tpl_vars[$_key],'array');
+ }
+ if($merge && is_array($_val)) {
+ foreach($_val as $_mkey => $_mval) {
+ $this->_tpl_vars[$_key][$_mkey] = $_mval;
+ }
+ } else {
+ $this->_tpl_vars[$_key][] = $_val;
+ }
+ }
+ }
+ } else {
+ if ($tpl_var != '' && isset($value)) {
+ if(!@is_array($this->_tpl_vars[$tpl_var])) {
+ settype($this->_tpl_vars[$tpl_var],'array');
+ }
+ if($merge && is_array($value)) {
+ foreach($value as $_mkey => $_mval) {
+ $this->_tpl_vars[$tpl_var][$_mkey] = $_mval;
+ }
+ } else {
+ $this->_tpl_vars[$tpl_var][] = $value;
+ }
+ }
+ }
+ }
+
+ /**
+ * appends values to template variables by reference
+ *
+ * @param string $tpl_var the template variable name
+ * @param mixed $value the referenced value to append
+ */
+ function append_by_ref($tpl_var, &$value, $merge=false)
+ {
+ if ($tpl_var != '' && isset($value)) {
+ if(!@is_array($this->_tpl_vars[$tpl_var])) {
+ settype($this->_tpl_vars[$tpl_var],'array');
+ }
+ if ($merge && is_array($value)) {
+ foreach($value as $_key => $_val) {
+ $this->_tpl_vars[$tpl_var][$_key] = &$value[$_key];
+ }
+ } else {
+ $this->_tpl_vars[$tpl_var][] = &$value;
+ }
+ }
+ }
+
+
+ /**
+ * clear the given assigned template variable.
+ *
+ * @param string $tpl_var the template variable to clear
+ */
+ function clear_assign($tpl_var)
+ {
+ if (is_array($tpl_var))
+ foreach ($tpl_var as $curr_var)
+ unset($this->_tpl_vars[$curr_var]);
+ else
+ unset($this->_tpl_vars[$tpl_var]);
+ }
+
+
+ /**
+ * Registers custom function to be used in templates
+ *
+ * @param string $function the name of the template function
+ * @param string $function_impl the name of the PHP function to register
+ */
+ function register_function($function, $function_impl, $cacheable=true, $cache_attrs=null)
+ {
+ $this->_plugins['function'][$function] =
+ array($function_impl, null, null, false, $cacheable, $cache_attrs);
+
+ }
+
+ /**
+ * Unregisters custom function
+ *
+ * @param string $function name of template function
+ */
+ function unregister_function($function)
+ {
+ unset($this->_plugins['function'][$function]);
+ }
+
+ /**
+ * Registers object to be used in templates
+ *
+ * @param string $object name of template object
+ * @param object &$object_impl the referenced PHP object to register
+ * @param null|array $allowed list of allowed methods (empty = all)
+ * @param boolean $smarty_args smarty argument format, else traditional
+ * @param null|array $block_functs list of methods that are block format
+ */
+ function register_object($object, &$object_impl, $allowed = array(), $smarty_args = true, $block_methods = array())
+ {
+ settype($allowed, 'array');
+ settype($smarty_args, 'boolean');
+ $this->_reg_objects[$object] =
+ array(&$object_impl, $allowed, $smarty_args, $block_methods);
+ }
+
+ /**
+ * Unregisters object
+ *
+ * @param string $object name of template object
+ */
+ function unregister_object($object)
+ {
+ unset($this->_reg_objects[$object]);
+ }
+
+
+ /**
+ * Registers block function to be used in templates
+ *
+ * @param string $block name of template block
+ * @param string $block_impl PHP function to register
+ */
+ function register_block($block, $block_impl, $cacheable=true, $cache_attrs=null)
+ {
+ $this->_plugins['block'][$block] =
+ array($block_impl, null, null, false, $cacheable, $cache_attrs);
+ }
+
+ /**
+ * Unregisters block function
+ *
+ * @param string $block name of template function
+ */
+ function unregister_block($block)
+ {
+ unset($this->_plugins['block'][$block]);
+ }
+
+ /**
+ * Registers compiler function
+ *
+ * @param string $function name of template function
+ * @param string $function_impl name of PHP function to register
+ */
+ function register_compiler_function($function, $function_impl, $cacheable=true)
+ {
+ $this->_plugins['compiler'][$function] =
+ array($function_impl, null, null, false, $cacheable);
+ }
+
+ /**
+ * Unregisters compiler function
+ *
+ * @param string $function name of template function
+ */
+ function unregister_compiler_function($function)
+ {
+ unset($this->_plugins['compiler'][$function]);
+ }
+
+ /**
+ * Registers modifier to be used in templates
+ *
+ * @param string $modifier name of template modifier
+ * @param string $modifier_impl name of PHP function to register
+ */
+ function register_modifier($modifier, $modifier_impl)
+ {
+ $this->_plugins['modifier'][$modifier] =
+ array($modifier_impl, null, null, false);
+ }
+
+ /**
+ * Unregisters modifier
+ *
+ * @param string $modifier name of template modifier
+ */
+ function unregister_modifier($modifier)
+ {
+ unset($this->_plugins['modifier'][$modifier]);
+ }
+
+ /**
+ * Registers a resource to fetch a template
+ *
+ * @param string $type name of resource
+ * @param array $functions array of functions to handle resource
+ */
+ function register_resource($type, $functions)
+ {
+ if (count($functions)==4) {
+ $this->_plugins['resource'][$type] =
+ array($functions, false);
+
+ } elseif (count($functions)==5) {
+ $this->_plugins['resource'][$type] =
+ array(array(array(&$functions[0], $functions[1])
+ ,array(&$functions[0], $functions[2])
+ ,array(&$functions[0], $functions[3])
+ ,array(&$functions[0], $functions[4]))
+ ,false);
+
+ } else {
+ $this->trigger_error("malformed function-list for '$type' in register_resource");
+
+ }
+ }
+
+ /**
+ * Unregisters a resource
+ *
+ * @param string $type name of resource
+ */
+ function unregister_resource($type)
+ {
+ unset($this->_plugins['resource'][$type]);
+ }
+
+ /**
+ * Registers a prefilter function to apply
+ * to a template before compiling
+ *
+ * @param string $function name of PHP function to register
+ */
+ function register_prefilter($function)
+ {
+ $_name = (is_array($function)) ? $function[1] : $function;
+ $this->_plugins['prefilter'][$_name]
+ = array($function, null, null, false);
+ }
+
+ /**
+ * Unregisters a prefilter function
+ *
+ * @param string $function name of PHP function
+ */
+ function unregister_prefilter($function)
+ {
+ unset($this->_plugins['prefilter'][$function]);
+ }
+
+ /**
+ * Registers a postfilter function to apply
+ * to a compiled template after compilation
+ *
+ * @param string $function name of PHP function to register
+ */
+ function register_postfilter($function)
+ {
+ $_name = (is_array($function)) ? $function[1] : $function;
+ $this->_plugins['postfilter'][$_name]
+ = array($function, null, null, false);
+ }
+
+ /**
+ * Unregisters a postfilter function
+ *
+ * @param string $function name of PHP function
+ */
+ function unregister_postfilter($function)
+ {
+ unset($this->_plugins['postfilter'][$function]);
+ }
+
+ /**
+ * Registers an output filter function to apply
+ * to a template output
+ *
+ * @param string $function name of PHP function
+ */
+ function register_outputfilter($function)
+ {
+ $_name = (is_array($function)) ? $function[1] : $function;
+ $this->_plugins['outputfilter'][$_name]
+ = array($function, null, null, false);
+ }
+
+ /**
+ * Unregisters an outputfilter function
+ *
+ * @param string $function name of PHP function
+ */
+ function unregister_outputfilter($function)
+ {
+ unset($this->_plugins['outputfilter'][$function]);
+ }
+
+ /**
+ * load a filter of specified type and name
+ *
+ * @param string $type filter type
+ * @param string $name filter name
+ */
+ function load_filter($type, $name)
+ {
+ switch ($type) {
+ case 'output':
+ $_params = array('plugins' => array(array($type . 'filter', $name, null, null, false)));
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.load_plugins.php');
+ smarty_core_load_plugins($_params, $this);
+ break;
+
+ case 'pre':
+ case 'post':
+ if (!isset($this->_plugins[$type . 'filter'][$name]))
+ $this->_plugins[$type . 'filter'][$name] = false;
+ break;
+ }
+ }
+
+ /**
+ * clear cached content for the given template and cache id
+ *
+ * @param string $tpl_file name of template file
+ * @param string $cache_id name of cache_id
+ * @param string $compile_id name of compile_id
+ * @param string $exp_time expiration time
+ * @return boolean
+ */
+ function clear_cache($tpl_file = null, $cache_id = null, $compile_id = null, $exp_time = null)
+ {
+
+ if (!isset($compile_id))
+ $compile_id = $this->compile_id;
+
+ if (!isset($tpl_file))
+ $compile_id = null;
+
+ $_auto_id = $this->_get_auto_id($cache_id, $compile_id);
+
+ if (!empty($this->cache_handler_func)) {
+ return call_user_func_array($this->cache_handler_func,
+ array('clear', &$this, &$dummy, $tpl_file, $cache_id, $compile_id, $exp_time));
+ } else {
+ $_params = array('auto_base' => $this->cache_dir,
+ 'auto_source' => $tpl_file,
+ 'auto_id' => $_auto_id,
+ 'exp_time' => $exp_time);
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.rm_auto.php');
+ return smarty_core_rm_auto($_params, $this);
+ }
+
+ }
+
+
+ /**
+ * clear the entire contents of cache (all templates)
+ *
+ * @param string $exp_time expire time
+ * @return boolean results of {@link smarty_core_rm_auto()}
+ */
+ function clear_all_cache($exp_time = null)
+ {
+ if (!empty($this->cache_handler_func)) {
+ $dummy = null;
+ call_user_func_array($this->cache_handler_func,
+ array('clear', &$this, &$dummy, null, null, null, $exp_time));
+ } else {
+ $_params = array('auto_base' => $this->cache_dir,
+ 'auto_source' => null,
+ 'auto_id' => null,
+ 'exp_time' => $exp_time);
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.rm_auto.php');
+ return smarty_core_rm_auto($_params, $this);
+ }
+ }
+
+
+ /**
+ * test to see if valid cache exists for this template
+ *
+ * @param string $tpl_file name of template file
+ * @param string $cache_id
+ * @param string $compile_id
+ * @return string|false results of {@link _read_cache_file()}
+ */
+ function is_cached($tpl_file, $cache_id = null, $compile_id = null)
+ {
+ if (!$this->caching)
+ return false;
+
+ if (!isset($compile_id))
+ $compile_id = $this->compile_id;
+
+ $_params = array(
+ 'tpl_file' => $tpl_file,
+ 'cache_id' => $cache_id,
+ 'compile_id' => $compile_id
+ );
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.read_cache_file.php');
+ return smarty_core_read_cache_file($_params, $this);
+ }
+
+
+ /**
+ * clear all the assigned template variables.
+ *
+ */
+ function clear_all_assign()
+ {
+ $this->_tpl_vars = array();
+ }
+
+ /**
+ * clears compiled version of specified template resource,
+ * or all compiled template files if one is not specified.
+ * This function is for advanced use only, not normally needed.
+ *
+ * @param string $tpl_file
+ * @param string $compile_id
+ * @param string $exp_time
+ * @return boolean results of {@link smarty_core_rm_auto()}
+ */
+ function clear_compiled_tpl($tpl_file = null, $compile_id = null, $exp_time = null)
+ {
+ if (!isset($compile_id)) {
+ $compile_id = $this->compile_id;
+ }
+ $_params = array('auto_base' => $this->compile_dir,
+ 'auto_source' => $tpl_file,
+ 'auto_id' => $compile_id,
+ 'exp_time' => $exp_time,
+ 'extensions' => array('.inc', '.php'));
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.rm_auto.php');
+ return smarty_core_rm_auto($_params, $this);
+ }
+
+ /**
+ * Checks whether requested template exists.
+ *
+ * @param string $tpl_file
+ * @return boolean
+ */
+ function template_exists($tpl_file)
+ {
+ $_params = array('resource_name' => $tpl_file, 'quiet'=>true, 'get_source'=>false);
+ return $this->_fetch_resource_info($_params);
+ }
+
+ /**
+ * Returns an array containing template variables
+ *
+ * @param string $name
+ * @param string $type
+ * @return array
+ */
+ function &get_template_vars($name=null)
+ {
+ if(!isset($name)) {
+ return $this->_tpl_vars;
+ }
+ if(isset($this->_tpl_vars[$name])) {
+ return $this->_tpl_vars[$name];
+ }
+ }
+
+ /**
+ * Returns an array containing config variables
+ *
+ * @param string $name
+ * @param string $type
+ * @return array
+ */
+ function &get_config_vars($name=null)
+ {
+ if(!isset($name) && is_array($this->_config[0])) {
+ return $this->_config[0]['vars'];
+ } else if(isset($this->_config[0]['vars'][$name])) {
+ return $this->_config[0]['vars'][$name];
+ }
+ }
+
+ /**
+ * trigger Smarty error
+ *
+ * @param string $error_msg
+ * @param integer $error_type
+ */
+ function trigger_error($error_msg, $error_type = E_USER_WARNING)
+ {
+ trigger_error("Smarty error: $error_msg", $error_type);
+ }
+
+
+ /**
+ * executes & displays the template results
+ *
+ * @param string $resource_name
+ * @param string $cache_id
+ * @param string $compile_id
+ */
+ function display($resource_name, $cache_id = null, $compile_id = null)
+ {
+ $this->fetch($resource_name, $cache_id, $compile_id, true);
+ }
+
+ /**
+ * executes & returns or displays the template results
+ *
+ * @param string $resource_name
+ * @param string $cache_id
+ * @param string $compile_id
+ * @param boolean $display
+ */
+ function fetch($resource_name, $cache_id = null, $compile_id = null, $display = false)
+ {
+ static $_cache_info = array();
+
+ $_smarty_old_error_level = $this->debugging ? error_reporting() : error_reporting(error_reporting() & ~E_NOTICE);
+
+ if (!$this->debugging && $this->debugging_ctrl == 'URL'
+ && @strstr($GLOBALS['HTTP_SERVER_VARS']['QUERY_STRING'], $this->_smarty_debug_id)) {
+ // enable debugging from URL
+ $this->debugging = true;
+ }
+
+ if ($this->debugging) {
+ // capture time for debugging info
+ $_params = array();
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php');
+ $_debug_start_time = smarty_core_get_microtime($_params, $this);
+ $this->_smarty_debug_info[] = array('type' => 'template',
+ 'filename' => $resource_name,
+ 'depth' => 0);
+ $_included_tpls_idx = count($this->_smarty_debug_info) - 1;
+ }
+
+ if (!isset($compile_id)) {
+ $compile_id = $this->compile_id;
+ }
+
+ $this->_compile_id = $compile_id;
+ $this->_inclusion_depth = 0;
+
+ if ($this->caching) {
+ // save old cache_info, initialize cache_info
+ array_push($_cache_info, $this->_cache_info);
+ $this->_cache_info = array();
+ $_params = array(
+ 'tpl_file' => $resource_name,
+ 'cache_id' => $cache_id,
+ 'compile_id' => $compile_id,
+ 'results' => null
+ );
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.read_cache_file.php');
+ if (smarty_core_read_cache_file($_params, $this)) {
+ $_smarty_results = $_params['results'];
+ if (@count($this->_cache_info['insert_tags'])) {
+ $_params = array('plugins' => $this->_cache_info['insert_tags']);
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.load_plugins.php');
+ smarty_core_load_plugins($_params, $this);
+ $_params = array('results' => $_smarty_results);
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.process_cached_inserts.php');
+ $_smarty_results = smarty_core_process_cached_inserts($_params, $this);
+ }
+ if (@count($this->_cache_info['cache_serials'])) {
+ $_params = array('results' => $_smarty_results);
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.process_compiled_include.php');
+ $_smarty_results = smarty_core_process_compiled_include($_params, $this);
+ }
+
+
+ if ($display) {
+ if ($this->debugging)
+ {
+ // capture time for debugging info
+ $_params = array();
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php');
+ $this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $_debug_start_time;
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.display_debug_console.php');
+ $_smarty_results .= smarty_core_display_debug_console($_params, $this);
+ }
+ if ($this->cache_modified_check) {
+ $_last_modified_date = @substr($GLOBALS['HTTP_SERVER_VARS']['HTTP_IF_MODIFIED_SINCE'], 0, strpos($GLOBALS['HTTP_SERVER_VARS']['HTTP_IF_MODIFIED_SINCE'], 'GMT') + 3);
+ $_gmt_mtime = gmdate('D, d M Y H:i:s', $this->_cache_info['timestamp']).' GMT';
+ if (@count($this->_cache_info['insert_tags']) == 0
+ && !$this->_cache_serials
+ && $_gmt_mtime == $_last_modified_date) {
+ if (php_sapi_name()=='cgi')
+ header("Status: 304 Not Modified");
+ else
+ header("HTTP/1.1 304 Not Modified");
+
+ } else {
+ header("Last-Modified: ".$_gmt_mtime);
+ echo $_smarty_results;
+ }
+ } else {
+ echo $_smarty_results;
+ }
+ error_reporting($_smarty_old_error_level);
+ // restore initial cache_info
+ $this->_cache_info = array_pop($_cache_info);
+ return true;
+ } else {
+ error_reporting($_smarty_old_error_level);
+ // restore initial cache_info
+ $this->_cache_info = array_pop($_cache_info);
+ return $_smarty_results;
+ }
+ } else {
+ $this->_cache_info['template'][$resource_name] = true;
+ if ($this->cache_modified_check) {
+ header("Last-Modified: ".gmdate('D, d M Y H:i:s', time()).' GMT');
+ }
+ }
+ }
+
+ // load filters that are marked as autoload
+ if (count($this->autoload_filters)) {
+ foreach ($this->autoload_filters as $_filter_type => $_filters) {
+ foreach ($_filters as $_filter) {
+ $this->load_filter($_filter_type, $_filter);
+ }
+ }
+ }
+
+ $_smarty_compile_path = $this->_get_compile_path($resource_name);
+
+ // if we just need to display the results, don't perform output
+ // buffering - for speed
+ $_cache_including = $this->_cache_including;
+ $this->_cache_including = false;
+ if ($display && !$this->caching && count($this->_plugins['outputfilter']) == 0) {
+ if ($this->_is_compiled($resource_name, $_smarty_compile_path)
+ || $this->_compile_resource($resource_name, $_smarty_compile_path))
+ {
+ include($_smarty_compile_path);
+ }
+ } else {
+ ob_start();
+ if ($this->_is_compiled($resource_name, $_smarty_compile_path)
+ || $this->_compile_resource($resource_name, $_smarty_compile_path))
+ {
+ include($_smarty_compile_path);
+ }
+ $_smarty_results = ob_get_contents();
+ ob_end_clean();
+
+ foreach ((array)$this->_plugins['outputfilter'] as $_output_filter) {
+ $_smarty_results = call_user_func_array($_output_filter[0], array($_smarty_results, &$this));
+ }
+ }
+
+ if ($this->caching) {
+ $_params = array('tpl_file' => $resource_name,
+ 'cache_id' => $cache_id,
+ 'compile_id' => $compile_id,
+ 'results' => $_smarty_results);
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.write_cache_file.php');
+ smarty_core_write_cache_file($_params, $this);
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.process_cached_inserts.php');
+ $_smarty_results = smarty_core_process_cached_inserts($_params, $this);
+
+ if ($this->_cache_serials) {
+ // strip nocache-tags from output
+ $_smarty_results = preg_replace('!(\{/?nocache\:[0-9a-f]{32}#\d+\})!s'
+ ,''
+ ,$_smarty_results);
+ }
+ // restore initial cache_info
+ $this->_cache_info = array_pop($_cache_info);
+ }
+ $this->_cache_including = $_cache_including;
+
+ if ($display) {
+ if (isset($_smarty_results)) { echo $_smarty_results; }
+ if ($this->debugging) {
+ // capture time for debugging info
+ $_params = array();
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php');
+ $this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = (smarty_core_get_microtime($_params, $this) - $_debug_start_time);
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.display_debug_console.php');
+ echo smarty_core_display_debug_console($_params, $this);
+ }
+ error_reporting($_smarty_old_error_level);
+ return;
+ } else {
+ error_reporting($_smarty_old_error_level);
+ if (isset($_smarty_results)) { return $_smarty_results; }
+ }
+ }
+
+ /**
+ * load configuration values
+ *
+ * @param string $file
+ * @param string $section
+ * @param string $scope
+ */
+ function config_load($file, $section = null, $scope = 'global')
+ {
+ require_once($this->_get_plugin_filepath('function', 'config_load'));
+ smarty_function_config_load(array('file' => $file, 'section' => $section, 'scope' => $scope), $this);
+ }
+
+ /**
+ * return a reference to a registered object
+ *
+ * @param string $name
+ * @return object
+ */
+ function &get_registered_object($name) {
+ if (!isset($this->_reg_objects[$name]))
+ $this->_trigger_fatal_error("'$name' is not a registered object");
+
+ if (!is_object($this->_reg_objects[$name][0]))
+ $this->_trigger_fatal_error("registered '$name' is not an object");
+
+ return $this->_reg_objects[$name][0];
+ }
+
+ /**
+ * clear configuration values
+ *
+ * @param string $var
+ */
+ function clear_config($var = null)
+ {
+ if(!isset($var)) {
+ // clear all values
+ $this->_config = array(array('vars' => array(),
+ 'files' => array()));
+ } else {
+ unset($this->_config[0]['vars'][$var]);
+ }
+ }
+
+ /**
+ * get filepath of requested plugin
+ *
+ * @param string $type
+ * @param string $name
+ * @return string|false
+ */
+ function _get_plugin_filepath($type, $name)
+ {
+ $_params = array('type' => $type, 'name' => $name);
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.assemble_plugin_filepath.php');
+ return smarty_core_assemble_plugin_filepath($_params, $this);
+ }
+
+ /**
+ * test if resource needs compiling
+ *
+ * @param string $resource_name
+ * @param string $compile_path
+ * @return boolean
+ */
+ function _is_compiled($resource_name, $compile_path)
+ {
+ if (!$this->force_compile && file_exists($compile_path)) {
+ if (!$this->compile_check) {
+ // no need to check compiled file
+ return true;
+ } else {
+ // get file source and timestamp
+ $_params = array('resource_name' => $resource_name, 'get_source'=>false);
+ if (!$this->_fetch_resource_info($_params, $this)) {
+ return false;
+ }
+ if ($_params['resource_timestamp'] <= filemtime($compile_path)) {
+ // template not expired, no recompile
+ return true;
+ } else {
+ // compile template
+ return false;
+ }
+ }
+ } else {
+ // compiled template does not exist, or forced compile
+ return false;
+ }
+ }
+
+ /**
+ * compile the template
+ *
+ * @param string $resource_name
+ * @param string $compile_path
+ * @return boolean
+ */
+ function _compile_resource($resource_name, $compile_path)
+ {
+
+ $_params = array('resource_name' => $resource_name);
+ if (!$this->_fetch_resource_info($_params)) {
+ return false;
+ }
+
+ $_source_content = $_params['source_content'];
+ $_resource_timestamp = $_params['resource_timestamp'];
+ $_cache_include = substr($compile_path, 0, -4).'.inc';
+
+ if ($this->_compile_source($resource_name, $_source_content, $_compiled_content, $_cache_include)) {
+ // if a _cache_serial was set, we also have to write an include-file:
+ if ($this->_cache_include_info) {
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.write_compiled_include.php');
+ smarty_core_write_compiled_include(array_merge($this->_cache_include_info, array('compiled_content'=>$_compiled_content)), $this);
+ }
+
+ $_params = array('compile_path'=>$compile_path, 'compiled_content' => $_compiled_content, 'resource_timestamp' => $_resource_timestamp);
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.write_compiled_resource.php');
+ smarty_core_write_compiled_resource($_params, $this);
+
+ return true;
+ } else {
+ $this->trigger_error($smarty_compiler->_error_msg);
+ return false;
+ }
+
+ }
+
+ /**
+ * compile the given source
+ *
+ * @param string $resource_name
+ * @param string $source_content
+ * @param string $compiled_content
+ * @return boolean
+ */
+ function _compile_source($resource_name, &$source_content, &$compiled_content, $cache_include_path=null)
+ {
+ if (file_exists(SMARTY_DIR . $this->compiler_file)) {
+ require_once(SMARTY_DIR . $this->compiler_file);
+ } else {
+ // use include_path
+ require_once($this->compiler_file);
+ }
+
+
+ $smarty_compiler = new $this->compiler_class;
+
+ $smarty_compiler->template_dir = $this->template_dir;
+ $smarty_compiler->compile_dir = $this->compile_dir;
+ $smarty_compiler->plugins_dir = $this->plugins_dir;
+ $smarty_compiler->config_dir = $this->config_dir;
+ $smarty_compiler->force_compile = $this->force_compile;
+ $smarty_compiler->caching = $this->caching;
+ $smarty_compiler->php_handling = $this->php_handling;
+ $smarty_compiler->left_delimiter = $this->left_delimiter;
+ $smarty_compiler->right_delimiter = $this->right_delimiter;
+ $smarty_compiler->_version = $this->_version;
+ $smarty_compiler->security = $this->security;
+ $smarty_compiler->secure_dir = $this->secure_dir;
+ $smarty_compiler->security_settings = $this->security_settings;
+ $smarty_compiler->trusted_dir = $this->trusted_dir;
+ $smarty_compiler->_reg_objects = &$this->_reg_objects;
+ $smarty_compiler->_plugins = &$this->_plugins;
+ $smarty_compiler->_tpl_vars = &$this->_tpl_vars;
+ $smarty_compiler->default_modifiers = $this->default_modifiers;
+ $smarty_compiler->compile_id = $this->_compile_id;
+ $smarty_compiler->_config = $this->_config;
+ $smarty_compiler->request_use_auto_globals = $this->request_use_auto_globals;
+
+ $smarty_compiler->_cache_serial = null;
+ $smarty_compiler->_cache_include = $cache_include_path;
+
+
+ $_results = $smarty_compiler->_compile_file($resource_name, $source_content, $compiled_content);
+
+ if ($smarty_compiler->_cache_serial) {
+ $this->_cache_include_info = array(
+ 'cache_serial'=>$smarty_compiler->_cache_serial
+ ,'plugins_code'=>$smarty_compiler->_plugins_code
+ ,'include_file_path' => $cache_include_path);
+
+ } else {
+ $this->_cache_include_info = null;
+
+ }
+
+ return $_results;
+ }
+
+ /**
+ * Get the compile path for this resource
+ *
+ * @param string $resource_name
+ * @return string results of {@link _get_auto_filename()}
+ */
+ function _get_compile_path($resource_name)
+ {
+ return $this->_get_auto_filename($this->compile_dir, $resource_name,
+ $this->_compile_id) . '.php';
+ }
+
+ /**
+ * fetch the template info. Gets timestamp, and source
+ * if get_source is true
+ *
+ * sets $source_content to the source of the template, and
+ * $resource_timestamp to its time stamp
+ * @param string $resource_name
+ * @param string $source_content
+ * @param integer $resource_timestamp
+ * @param boolean $get_source
+ * @param boolean $quiet
+ * @return boolean
+ */
+
+ function _fetch_resource_info(&$params)
+ {
+ if(!isset($params['get_source'])) { $params['get_source'] = true; }
+ if(!isset($params['quiet'])) { $params['quiet'] = false; }
+
+ $_return = false;
+ $_params = array('resource_name' => $params['resource_name']) ;
+ if (isset($params['resource_base_path']))
+ $_params['resource_base_path'] = $params['resource_base_path'];
+
+ if ($this->_parse_resource_name($_params)) {
+ $_resource_type = $_params['resource_type'];
+ $_resource_name = $_params['resource_name'];
+ switch ($_resource_type) {
+ case 'file':
+ if ($params['get_source']) {
+ $params['source_content'] = $this->_read_file($_resource_name);
+ }
+ $params['resource_timestamp'] = filemtime($_resource_name);
+ $_return = is_file($_resource_name);
+ break;
+
+ default:
+ // call resource functions to fetch the template source and timestamp
+ if ($params['get_source']) {
+ $_source_return = isset($this->_plugins['resource'][$_resource_type]) &&
+ call_user_func_array($this->_plugins['resource'][$_resource_type][0][0],
+ array($_resource_name, &$params['source_content'], &$this));
+ } else {
+ $_source_return = true;
+ }
+
+ $_timestamp_return = isset($this->_plugins['resource'][$_resource_type]) &&
+ call_user_func_array($this->_plugins['resource'][$_resource_type][0][1],
+ array($_resource_name, &$params['resource_timestamp'], &$this));
+
+ $_return = $_source_return && $_timestamp_return;
+ break;
+ }
+ }
+
+ if (!$_return) {
+ // see if we can get a template with the default template handler
+ if (!empty($this->default_template_handler_func)) {
+ if (!is_callable($this->default_template_handler_func)) {
+ $this->trigger_error("default template handler function \"$this->default_template_handler_func\" doesn't exist.");
+ } else {
+ $_return = call_user_func_array(
+ $this->default_template_handler_func,
+ array($_params['resource_type'], $_params['resource_name'], &$params['source_content'], &$params['resource_timestamp'], &$this));
+ }
+ }
+ }
+
+ if (!$_return) {
+ if (!$params['quiet']) {
+ $this->trigger_error('unable to read resource: "' . $params['resource_name'] . '"');
+ }
+ } else if ($_return && $this->security) {
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.is_secure.php');
+ if (!smarty_core_is_secure($_params, $this)) {
+ if (!$params['quiet'])
+ $this->trigger_error('(secure mode) accessing "' . $params['resource_name'] . '" is not allowed');
+ $params['source_content'] = null;
+ $params['resource_timestamp'] = null;
+ return false;
+ }
+ }
+ return $_return;
+ }
+
+
+ /**
+ * parse out the type and name from the resource
+ *
+ * @param string $resource_base_path
+ * @param string $resource_name
+ * @param string $resource_type
+ * @param string $resource_name
+ * @return boolean
+ */
+
+ function _parse_resource_name(&$params)
+ {
+
+ // split tpl_path by the first colon
+ $_resource_name_parts = explode(':', $params['resource_name'], 2);
+
+ if (count($_resource_name_parts) == 1) {
+ // no resource type given
+ $params['resource_type'] = $this->default_resource_type;
+ $params['resource_name'] = $_resource_name_parts[0];
+ } else {
+ if(strlen($_resource_name_parts[0]) == 1) {
+ // 1 char is not resource type, but part of filepath
+ $params['resource_type'] = $this->default_resource_type;
+ $params['resource_name'] = $params['resource_name'];
+ } else {
+ $params['resource_type'] = $_resource_name_parts[0];
+ $params['resource_name'] = $_resource_name_parts[1];
+ }
+ }
+
+ if ($params['resource_type'] == 'file') {
+ if (!preg_match("/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/", $params['resource_name'])) {
+ // relative pathname to $params['resource_base_path']
+ // use the first directory where the file is found
+ if (isset($params['resource_base_path'])) {
+ $_resource_base_path = (array)$params['resource_base_path'];
+ } else {
+ $_resource_base_path = (array)$this->template_dir;
+ $_resource_base_path[] = '.';
+ }
+ foreach ($_resource_base_path as $_curr_path) {
+ $_fullpath = $_curr_path . DIRECTORY_SEPARATOR . $params['resource_name'];
+ if (file_exists($_fullpath) && is_file($_fullpath)) {
+ $params['resource_name'] = $_fullpath;
+ return true;
+ }
+ // didn't find the file, try include_path
+ $_params = array('file_path' => $_fullpath);
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_include_path.php');
+ if(smarty_core_get_include_path($_params, $this)) {
+ $params['resource_name'] = $_params['new_file_path'];
+ return true;
+ }
+ }
+ return false;
+ }
+ } elseif (empty($this->_plugins['resource'][$params['resource_type']])) {
+ $_params = array('type' => $params['resource_type']);
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.load_resource_plugin.php');
+ smarty_core_load_resource_plugin($_params, $this);
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Handle modifiers
+ *
+ * @param string|null $modifier_name
+ * @param array|null $map_array
+ * @return string result of modifiers
+ */
+ function _run_mod_handler()
+ {
+ $_args = func_get_args();
+ list($_modifier_name, $_map_array) = array_splice($_args, 0, 2);
+ list($_func_name, $_tpl_file, $_tpl_line) =
+ $this->_plugins['modifier'][$_modifier_name];
+
+ $_var = $_args[0];
+ foreach ($_var as $_key => $_val) {
+ $_args[0] = $_val;
+ $_var[$_key] = call_user_func_array($_func_name, $_args);
+ }
+ return $_var;
+ }
+
+ /**
+ * Remove starting and ending quotes from the string
+ *
+ * @param string $string
+ * @return string
+ */
+ function _dequote($string)
+ {
+ if (($string{0} == "'" || $string{0} == '"') &&
+ $string{strlen($string)-1} == $string{0})
+ return substr($string, 1, -1);
+ else
+ return $string;
+ }
+
+
+ /**
+ * read in a file from line $start for $lines.
+ * read the entire file if $start and $lines are null.
+ *
+ * @param string $filename
+ * @param integer $start
+ * @param integer $lines
+ * @return string
+ */
+ function _read_file($filename, $start=null, $lines=null)
+ {
+ if (!($fd = @fopen($filename, 'r'))) {
+ return false;
+ }
+ flock($fd, LOCK_SH);
+ if ($start == null && $lines == null) {
+ // read the entire file
+ $contents = fread($fd, filesize($filename));
+ } else {
+ if ( $start > 1 ) {
+ // skip the first lines before $start
+ for ($loop=1; $loop < $start; $loop++) {
+ fgets($fd, 65536);
+ }
+ }
+ if ( $lines == null ) {
+ // read the rest of the file
+ while (!feof($fd)) {
+ $contents .= fgets($fd, 65536);
+ }
+ } else {
+ // read up to $lines lines
+ for ($loop=0; $loop < $lines; $loop++) {
+ $contents .= fgets($fd, 65536);
+ if (feof($fd)) {
+ break;
+ }
+ }
+ }
+ }
+ fclose($fd);
+ return $contents;
+ }
+
+ /**
+ * get a concrete filename for automagically created content
+ *
+ * @param string $auto_base
+ * @param string $auto_source
+ * @param string $auto_id
+ * @return string
+ * @staticvar string|null
+ * @staticvar string|null
+ */
+ function _get_auto_filename($auto_base, $auto_source = null, $auto_id = null)
+ {
+ $_compile_dir_sep = $this->use_sub_dirs ? DIRECTORY_SEPARATOR : '^';
+
+ if(@is_dir($auto_base)) {
+ $_return = $auto_base . DIRECTORY_SEPARATOR;
+ } else {
+ // auto_base not found, try include_path
+ $_params = array('file_path' => $auto_base);
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_include_path.php');
+ smarty_core_get_include_path($_params, $this);
+ $_return = isset($_params['new_file_path']) ? $_params['new_file_path'] . DIRECTORY_SEPARATOR : null;
+ }
+
+ if(isset($auto_id)) {
+ // make auto_id safe for directory names
+ $auto_id = str_replace('%7C',$_compile_dir_sep,(urlencode($auto_id)));
+ // split into separate directories
+ $_return .= $auto_id . $_compile_dir_sep;
+ }
+
+ if(isset($auto_source)) {
+ // make source name safe for filename
+ $_filename = urlencode(basename($auto_source));
+ $_crc32 = crc32($auto_source) . $_compile_dir_sep;
+ // prepend %% to avoid name conflicts with
+ // with $params['auto_id'] names
+ $_crc32 = '%%' . substr($_crc32,0,3) . $_compile_dir_sep . '%%' . $_crc32;
+ $_return .= $_crc32 . $_filename;
+ }
+
+ return $_return;
+ }
+
+ /**
+ * unlink a file, possibly using expiration time
+ *
+ * @param string $resource
+ * @param integer $exp_time
+ */
+ function _unlink($resource, $exp_time = null)
+ {
+ if(isset($exp_time)) {
+ if(time() - @filemtime($resource) >= $exp_time) {
+ return @unlink($resource);
+ }
+ } else {
+ return @unlink($resource);
+ }
+ }
+
+ /**
+ * returns an auto_id for auto-file-functions
+ *
+ * @param string $cache_id
+ * @param string $compile_id
+ * @return string|null
+ */
+ function _get_auto_id($cache_id=null, $compile_id=null) {
+ if (isset($cache_id))
+ return (isset($compile_id)) ? $cache_id . '|' . $compile_id : $cache_id;
+ elseif(isset($compile_id))
+ return $compile_id;
+ else
+ return null;
+ }
+
+ /**
+ * trigger Smarty plugin error
+ *
+ * @param string $error_msg
+ * @param string $tpl_file
+ * @param integer $tpl_line
+ * @param string $file
+ * @param integer $line
+ * @param integer $error_type
+ */
+ function _trigger_fatal_error($error_msg, $tpl_file = null, $tpl_line = null,
+ $file = null, $line = null, $error_type = E_USER_ERROR)
+ {
+ if(isset($file) && isset($line)) {
+ $info = ' ('.basename($file).", line $line)";
+ } else {
+ $info = null;
+ }
+ if (isset($tpl_line) && isset($tpl_file)) {
+ trigger_error("Smarty error: [in " . $tpl_file . " line " .
+ $tpl_line . "]: $error_msg$info", $error_type);
+ } else {
+ trigger_error("Smarty error: $error_msg$info", $error_type);
+ }
+ }
+
+
+ /**
+ * callback function for preg_replace, to call a non-cacheable block
+ * @return string
+ */
+ function _process_compiled_include_callback($match) {
+ $_func = '_smarty_tplfunc_'.$match[2].'_'.$match[3];
+ ob_start();
+ $_func($this);
+ $_ret = ob_get_contents();
+ ob_end_clean();
+ return $_ret;
+ }
+
+
+ /**
+ * called for included templates
+ *
+ * @param string $_smarty_include_tpl_file
+ * @param string $_smarty_include_vars
+ */
+
+ // $_smarty_include_tpl_file, $_smarty_include_vars
+
+ function _smarty_include($params)
+ {
+ if ($this->debugging) {
+ $_params = array();
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php');
+ $debug_start_time = smarty_core_get_microtime($_params, $this);
+ $this->_smarty_debug_info[] = array('type' => 'template',
+ 'filename' => $params['smarty_include_tpl_file'],
+ 'depth' => ++$this->_inclusion_depth);
+ $included_tpls_idx = count($this->_smarty_debug_info) - 1;
+ }
+
+ $this->_tpl_vars = array_merge($this->_tpl_vars, $params['smarty_include_vars']);
+
+ // config vars are treated as local, so push a copy of the
+ // current ones onto the front of the stack
+ array_unshift($this->_config, $this->_config[0]);
+
+ $_smarty_compile_path = $this->_get_compile_path($params['smarty_include_tpl_file']);
+
+
+ if ($this->_is_compiled($params['smarty_include_tpl_file'], $_smarty_compile_path)
+ || $this->_compile_resource($params['smarty_include_tpl_file'], $_smarty_compile_path))
+ {
+ include($_smarty_compile_path);
+ }
+
+ // pop the local vars off the front of the stack
+ array_shift($this->_config);
+
+ $this->_inclusion_depth--;
+
+ if ($this->debugging) {
+ // capture time for debugging info
+ $_params = array();
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php');
+ $this->_smarty_debug_info[$included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $debug_start_time;
+ }
+
+ if ($this->caching) {
+ $this->_cache_info['template'][$params['smarty_include_tpl_file']] = true;
+ }
+ }
+
+
+ /**
+ * get or set an array of cached attributes for function that is
+ * not cacheable
+ * @return array
+ */
+ function &_smarty_cache_attrs($cache_serial, $count) {
+ $_cache_attrs =& $this->_cache_info['cache_attrs'][$cache_serial][$count];
+
+ if ($this->_cache_including) {
+ /* return next set of cache_attrs */
+ $_return =& current($_cache_attrs);
+ next($_cache_attrs);
+ return $_return;
+
+ } else {
+ /* add a reference to a new set of cache_attrs */
+ $_cache_attrs[] = array();
+ return $_cache_attrs[count($_cache_attrs)-1];
+
+ }
+
+ }
+
+
+ /**
+ * wrapper for include() retaining $this
+ * @return mixed
+ */
+ function _include($filename, $once=false, $params=null)
+ {
+ if ($once) {
+ return include_once($filename);
+ } else {
+ return include($filename);
+ }
+ }
+
+
+ /**
+ * wrapper for eval() retaining $this
+ * @return mixed
+ */
+ function _eval($code, $params=null)
+ {
+ return eval($code);
+ }
+ /**#@-*/
+
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/Smarty_Compiler.class.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/Smarty_Compiler.class.php
new file mode 100644
index 00000000..263591fc
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/Smarty_Compiler.class.php
@@ -0,0 +1,2123 @@
+<?php
+
+/**
+ * Project: Smarty: the PHP compiling template engine
+ * File: Smarty_Compiler.class.php
+ *
+ * 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
+ *
+ * You may contact the authors of Smarty by e-mail at:
+ * monte@ispi.net
+ * andrei@php.net
+ *
+ * Or, write to:
+ * Monte Ohrt
+ * Director of Technology, ispi
+ * 237 S. 70th suite 220
+ * Lincoln, NE 68510
+ *
+ * The latest version of Smarty can be obtained from:
+ * http://smarty.php.net/
+ *
+ * @link http://smarty.php.net/
+ * @author Monte Ohrt <monte@ispi.net>
+ * @author Andrei Zmievski <andrei@php.net>
+ * @version 2.6.0
+ * @copyright 2001-2003 ispi of Lincoln, Inc.
+ * @package Smarty
+ */
+
+/* $Id: Smarty_Compiler.class.php,v 1.1 2005/10/17 18:37:39 jeichorn Exp $ */
+
+/**
+ * Template compiling class
+ * @package Smarty
+ */
+class Smarty_Compiler extends Smarty {
+
+ // internal vars
+ /**#@+
+ * @access private
+ */
+ var $_sectionelse_stack = array(); // keeps track of whether section had 'else' part
+ var $_foreachelse_stack = array(); // keeps track of whether foreach had 'else' part
+ var $_literal_blocks = array(); // keeps literal template blocks
+ var $_php_blocks = array(); // keeps php code blocks
+ var $_current_file = null; // the current template being compiled
+ var $_current_line_no = 1; // line number for error messages
+ var $_capture_stack = array(); // keeps track of nested capture buffers
+ var $_plugin_info = array(); // keeps track of plugins to load
+ var $_init_smarty_vars = false;
+ var $_permitted_tokens = array('true','false','yes','no','on','off','null');
+ var $_db_qstr_regexp = null; // regexps are setup in the constructor
+ var $_si_qstr_regexp = null;
+ var $_qstr_regexp = null;
+ var $_func_regexp = null;
+ var $_var_bracket_regexp = null;
+ var $_dvar_guts_regexp = null;
+ var $_dvar_regexp = null;
+ var $_cvar_regexp = null;
+ var $_svar_regexp = null;
+ var $_avar_regexp = null;
+ var $_mod_regexp = null;
+ var $_var_regexp = null;
+ var $_parenth_param_regexp = null;
+ var $_func_call_regexp = null;
+ var $_obj_ext_regexp = null;
+ var $_obj_start_regexp = null;
+ var $_obj_params_regexp = null;
+ var $_obj_call_regexp = null;
+ var $_cacheable_state = 0;
+ var $_cache_attrs_count = 0;
+ var $_nocache_count = 0;
+ var $_cache_serial = null;
+ var $_cache_include = null;
+
+ var $_strip_depth = 0;
+ var $_additional_newline = "\n";
+
+ /**#@-*/
+ /**
+ * The class constructor.
+ */
+ function Smarty_Compiler()
+ {
+ // matches double quoted strings:
+ // "foobar"
+ // "foo\"bar"
+ $this->_db_qstr_regexp = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"';
+
+ // matches single quoted strings:
+ // 'foobar'
+ // 'foo\'bar'
+ $this->_si_qstr_regexp = '\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'';
+
+ // matches single or double quoted strings
+ $this->_qstr_regexp = '(?:' . $this->_db_qstr_regexp . '|' . $this->_si_qstr_regexp . ')';
+
+ // matches bracket portion of vars
+ // [0]
+ // [foo]
+ // [$bar]
+ $this->_var_bracket_regexp = '\[\$?[\w\.]+\]';
+
+ // matches $ vars (not objects):
+ // $foo
+ // $foo.bar
+ // $foo.bar.foobar
+ // $foo[0]
+ // $foo[$bar]
+ // $foo[5][blah]
+ // $foo[5].bar[$foobar][4]
+ $this->_dvar_math_regexp = '[\+\-\*\/\%]';
+ $this->_dvar_math_var_regexp = '[\$\w\.\+\-\*\/\%\d\>\[\]]';
+ $this->_dvar_num_var_regexp = '\-?\d+(?:\.\d+)?' . $this->_dvar_math_var_regexp;
+ $this->_dvar_guts_regexp = '\w+(?:' . $this->_var_bracket_regexp
+ . ')*(?:\.\$?\w+(?:' . $this->_var_bracket_regexp . ')*)*(?:' . $this->_dvar_math_regexp . '(?:\-?\d+(?:\.\d+)?|' . $this->_dvar_math_var_regexp . ')*)?';
+ $this->_dvar_regexp = '\$' . $this->_dvar_guts_regexp;
+
+ // matches config vars:
+ // #foo#
+ // #foobar123_foo#
+ $this->_cvar_regexp = '\#\w+\#';
+
+ // matches section vars:
+ // %foo.bar%
+ $this->_svar_regexp = '\%\w+\.\w+\%';
+
+ // matches all valid variables (no quotes, no modifiers)
+ $this->_avar_regexp = '(?:' . $this->_dvar_regexp . '|'
+ . $this->_cvar_regexp . '|' . $this->_svar_regexp . ')';
+
+ // matches valid variable syntax:
+ // $foo
+ // $foo
+ // #foo#
+ // #foo#
+ // "text"
+ // "text"
+ $this->_var_regexp = '(?:' . $this->_avar_regexp . '|' . $this->_qstr_regexp . ')';
+
+ // matches valid object call (no objects allowed in parameters):
+ // $foo->bar
+ // $foo->bar()
+ // $foo->bar("text")
+ // $foo->bar($foo, $bar, "text")
+ // $foo->bar($foo, "foo")
+ // $foo->bar->foo()
+ // $foo->bar->foo->bar()
+ $this->_obj_ext_regexp = '\->(?:\$?' . $this->_dvar_guts_regexp . ')';
+ $this->_obj_params_regexp = '\((?:\w+|'
+ . $this->_var_regexp . '(?:\s*,\s*(?:(?:\w+|'
+ . $this->_var_regexp . ')))*)?\)';
+ $this->_obj_start_regexp = '(?:' . $this->_dvar_regexp . '(?:' . $this->_obj_ext_regexp . ')+)';
+ $this->_obj_call_regexp = '(?:' . $this->_obj_start_regexp . '(?:' . $this->_obj_params_regexp . ')?)';
+
+ // matches valid modifier syntax:
+ // |foo
+ // |@foo
+ // |foo:"bar"
+ // |foo:$bar
+ // |foo:"bar":$foobar
+ // |foo|bar
+ // |foo:$foo->bar
+ $this->_mod_regexp = '(?:\|@?\w+(?::(?>-?\w+|'
+ . $this->_obj_call_regexp . '|' . $this->_avar_regexp . '|' . $this->_qstr_regexp .'))*)';
+
+ // matches valid function name:
+ // foo123
+ // _foo_bar
+ $this->_func_regexp = '[a-zA-Z_]\w*';
+
+ // matches valid registered object:
+ // foo->bar
+ $this->_reg_obj_regexp = '[a-zA-Z_]\w*->[a-zA-Z_]\w*';
+
+ // matches valid parameter values:
+ // true
+ // $foo
+ // $foo|bar
+ // #foo#
+ // #foo#|bar
+ // "text"
+ // "text"|bar
+ // $foo->bar
+ $this->_param_regexp = '(?:\s*(?:' . $this->_obj_call_regexp . '|'
+ . $this->_var_regexp . '|\w+)(?>' . $this->_mod_regexp . '*)\s*)';
+
+ // matches valid parenthesised function parameters:
+ //
+ // "text"
+ // $foo, $bar, "text"
+ // $foo|bar, "foo"|bar, $foo->bar($foo)|bar
+ $this->_parenth_param_regexp = '(?:\((?:\w+|'
+ . $this->_param_regexp . '(?:\s*,\s*(?:(?:\w+|'
+ . $this->_param_regexp . ')))*)?\))';
+
+ // matches valid function call:
+ // foo()
+ // foo_bar($foo)
+ // _foo_bar($foo,"bar")
+ // foo123($foo,$foo->bar(),"foo")
+ $this->_func_call_regexp = '(?:' . $this->_func_regexp . '\s*(?:'
+ . $this->_parenth_param_regexp . '))';
+ }
+
+ /**
+ * compile a resource
+ *
+ * sets $compiled_content to the compiled source
+ * @param string $resource_name
+ * @param string $source_content
+ * @param string $compiled_content
+ * @return true
+ */
+ function _compile_file($resource_name, $source_content, &$compiled_content)
+ {
+
+ if ($this->security) {
+ // do not allow php syntax to be executed unless specified
+ if ($this->php_handling == SMARTY_PHP_ALLOW &&
+ !$this->security_settings['PHP_HANDLING']) {
+ $this->php_handling = SMARTY_PHP_PASSTHRU;
+ }
+ }
+
+ $this->_load_filters();
+
+ $this->_current_file = $resource_name;
+ $this->_current_line_no = 1;
+ $ldq = preg_quote($this->left_delimiter, '!');
+ $rdq = preg_quote($this->right_delimiter, '!');
+
+ // run template source through prefilter functions
+ if (count($this->_plugins['prefilter']) > 0) {
+ foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) {
+ if ($prefilter === false) continue;
+ if ($prefilter[3] || is_callable($prefilter[0])) {
+ $source_content = call_user_func_array($prefilter[0],
+ array($source_content, &$this));
+ $this->_plugins['prefilter'][$filter_name][3] = true;
+ } else {
+ $this->_trigger_fatal_error("[plugin] prefilter '$filter_name' is not implemented");
+ }
+ }
+ }
+
+ /* Annihilate the comments. */
+ $source_content = preg_replace("!({$ldq})\*(.*?)\*({$rdq})!se",
+ "'\\1*'.str_repeat(\"\n\", substr_count('\\2', \"\n\")) .'*\\3'",
+ $source_content);
+
+ /* Pull out the literal blocks. */
+ preg_match_all("!{$ldq}\s*literal\s*{$rdq}(.*?){$ldq}\s*/literal\s*{$rdq}!s", $source_content, $_match);
+ $this->_literal_blocks = $_match[1];
+ $source_content = preg_replace("!{$ldq}\s*literal\s*{$rdq}(.*?){$ldq}\s*/literal\s*{$rdq}!s",
+ $this->_quote_replace($this->left_delimiter.'literal'.$this->right_delimiter), $source_content);
+
+ /* Pull out the php code blocks. */
+ preg_match_all("!{$ldq}php{$rdq}(.*?){$ldq}/php{$rdq}!s", $source_content, $_match);
+ $this->_php_blocks = $_match[1];
+ $source_content = preg_replace("!{$ldq}php{$rdq}(.*?){$ldq}/php{$rdq}!s",
+ $this->_quote_replace($this->left_delimiter.'php'.$this->right_delimiter), $source_content);
+
+ /* Gather all template tags. */
+ preg_match_all("!{$ldq}\s*(.*?)\s*{$rdq}!s", $source_content, $_match);
+ $template_tags = $_match[1];
+ /* Split content by template tags to obtain non-template content. */
+ $text_blocks = preg_split("!{$ldq}.*?{$rdq}!s", $source_content);
+
+ /* loop through text blocks */
+ for ($curr_tb = 0, $for_max = count($text_blocks); $curr_tb < $for_max; $curr_tb++) {
+ /* match anything resembling php tags */
+ if (preg_match_all('!(<\?(?:\w+|=)?|\?>|language\s*=\s*[\"\']?php[\"\']?)!is', $text_blocks[$curr_tb], $sp_match)) {
+ /* replace tags with placeholders to prevent recursive replacements */
+ $sp_match[1] = array_unique($sp_match[1]);
+ usort($sp_match[1], '_smarty_sort_length');
+ for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) {
+ $text_blocks[$curr_tb] = str_replace($sp_match[1][$curr_sp],'%%%SMARTYSP'.$curr_sp.'%%%',$text_blocks[$curr_tb]);
+ }
+ /* process each one */
+ for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) {
+ if ($this->php_handling == SMARTY_PHP_PASSTHRU) {
+ /* echo php contents */
+ $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', '<?php echo \''.str_replace("'", "\'", $sp_match[1][$curr_sp]).'\'; ?>'."\n", $text_blocks[$curr_tb]);
+ } else if ($this->php_handling == SMARTY_PHP_QUOTE) {
+ /* quote php tags */
+ $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', htmlspecialchars($sp_match[1][$curr_sp]), $text_blocks[$curr_tb]);
+ } else if ($this->php_handling == SMARTY_PHP_REMOVE) {
+ /* remove php tags */
+ $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', '', $text_blocks[$curr_tb]);
+ } else {
+ /* SMARTY_PHP_ALLOW, but echo non php starting tags */
+ $sp_match[1][$curr_sp] = preg_replace('%(<\?(?!php|=|$))%i', '<?php echo \'\\1\'?>'."\n", $sp_match[1][$curr_sp]);
+ $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', $sp_match[1][$curr_sp], $text_blocks[$curr_tb]);
+ }
+ }
+ }
+ }
+
+ /* Compile the template tags into PHP code. */
+ $compiled_tags = array();
+ for ($i = 0, $for_max = count($template_tags); $i < $for_max; $i++) {
+ $this->_current_line_no += substr_count($text_blocks[$i], "\n");
+ $compiled_tags[] = $this->_compile_tag($template_tags[$i]);
+ $this->_current_line_no += substr_count($template_tags[$i], "\n");
+ }
+
+ $compiled_content = '';
+
+ /* Interleave the compiled contents and text blocks to get the final result. */
+ for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) {
+ if ($compiled_tags[$i] == '') {
+ // tag result empty, remove first newline from following text block
+ $text_blocks[$i+1] = preg_replace('!^(\r\n|\r|\n)!', '', $text_blocks[$i+1]);
+ }
+ $compiled_content .= $text_blocks[$i].$compiled_tags[$i];
+ }
+ $compiled_content .= $text_blocks[$i];
+
+ /* Reformat data between 'strip' and '/strip' tags, removing spaces, tabs and newlines. */
+ if (preg_match_all("!{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}!s", $compiled_content, $_match)) {
+ $strip_tags = $_match[0];
+ $strip_tags_modified = preg_replace("!{$ldq}/?strip{$rdq}|[\t ]+$|^[\t ]+!m", '', $strip_tags);
+ $strip_tags_modified = preg_replace('![\r\n]+!m', '', $strip_tags_modified);
+ for ($i = 0, $for_max = count($strip_tags); $i < $for_max; $i++)
+ $compiled_content = preg_replace("!{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}!s",
+ $this->_quote_replace($strip_tags_modified[$i]),
+ $compiled_content, 1);
+ }
+
+ // remove \n from the end of the file, if any
+ if (($_len=strlen($compiled_content)) && ($compiled_content{$_len - 1} == "\n" )) {
+ $compiled_content = substr($compiled_content, 0, -1);
+ }
+
+ if (!empty($this->_cache_serial)) {
+ $compiled_content = "<?php \$this->_cache_serials['".$this->_cache_include."'] = '".$this->_cache_serial."'; ?>" . $compiled_content;
+ }
+
+ // remove unnecessary close/open tags
+ $compiled_content = preg_replace('!\?>\n?<\?php!', '', $compiled_content);
+
+ // run compiled template through postfilter functions
+ if (count($this->_plugins['postfilter']) > 0) {
+ foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) {
+ if ($postfilter === false) continue;
+ if ($postfilter[3] || is_callable($postfilter[0])) {
+ $compiled_content = call_user_func_array($postfilter[0],
+ array($compiled_content, &$this));
+ $this->_plugins['postfilter'][$filter_name][3] = true;
+ } else {
+ $this->_trigger_fatal_error("Smarty plugin error: postfilter '$filter_name' is not implemented");
+ }
+ }
+ }
+
+ // put header at the top of the compiled template
+ $template_header = "<?php /* Smarty version ".$this->_version.", created on ".strftime("%Y-%m-%d %H:%M:%S")."\n";
+ $template_header .= " compiled from ".strtr(urlencode($resource_name), array('%2F'=>'/', '%3A'=>':'))." */ ?>\n";
+
+ /* Emit code to load needed plugins. */
+ $this->_plugins_code = '';
+ if (count($this->_plugin_info)) {
+ $_plugins_params = "array('plugins' => array(";
+ foreach ($this->_plugin_info as $plugin_type => $plugins) {
+ foreach ($plugins as $plugin_name => $plugin_info) {
+ $_plugins_params .= "array('$plugin_type', '$plugin_name', '$plugin_info[0]', $plugin_info[1], ";
+ $_plugins_params .= $plugin_info[2] ? 'true),' : 'false),';
+ }
+ }
+ $_plugins_params .= '))';
+ $plugins_code = "<?php require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.load_plugins.php');\nsmarty_core_load_plugins($_plugins_params, \$this); ?>\n";
+ $template_header .= $plugins_code;
+ $this->_plugin_info = array();
+ $this->_plugins_code = $plugins_code;
+ }
+
+ if ($this->_init_smarty_vars) {
+ $template_header .= "<?php require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.assign_smarty_interface.php');\nsmarty_core_assign_smarty_interface(null, \$this); ?>\n";
+ $this->_init_smarty_vars = false;
+ }
+
+ $compiled_content = $template_header . $compiled_content;
+
+ return true;
+ }
+
+ /**
+ * Compile a template tag
+ *
+ * @param string $template_tag
+ * @return string
+ */
+ function _compile_tag($template_tag)
+ {
+ /* Matched comment. */
+ if ($template_tag{0} == '*' && $template_tag{strlen($template_tag) - 1} == '*')
+ return '';
+
+ /* Split tag into two three parts: command, command modifiers and the arguments. */
+ if(! preg_match('/^(?:(' . $this->_obj_call_regexp . '|' . $this->_var_regexp
+ . '|\/?' . $this->_reg_obj_regexp . '|\/?' . $this->_func_regexp . ')(' . $this->_mod_regexp . '*))
+ (?:\s+(.*))?$
+ /xs', $template_tag, $match)) {
+ $this->_syntax_error("unrecognized tag: $template_tag", E_USER_ERROR, __FILE__, __LINE__);
+ }
+
+ $tag_command = $match[1];
+ $tag_modifier = isset($match[2]) ? $match[2] : null;
+ $tag_args = isset($match[3]) ? $match[3] : null;
+
+ if (preg_match('!^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '$!', $tag_command)) {
+ /* tag name is a variable or object */
+ $_return = $this->_parse_var_props($tag_command . $tag_modifier, $this->_parse_attrs($tag_args));
+ if(isset($_tag_attrs['assign'])) {
+ return "<?php \$this->assign('" . $this->_dequote($_tag_attrs['assign']) . "', $_return ); ?>\n";
+ } else {
+ return "<?php echo $_return; ?>" . $this->_additional_newline;
+ }
+ }
+
+ /* If the tag name is a registered object, we process it. */
+ if (preg_match('!^\/?' . $this->_reg_obj_regexp . '$!', $tag_command)) {
+ return $this->_compile_registered_object_tag($tag_command, $this->_parse_attrs($tag_args), $tag_modifier);
+ }
+
+ switch ($tag_command) {
+ case 'include':
+ return $this->_compile_include_tag($tag_args);
+
+ case 'include_php':
+ return $this->_compile_include_php_tag($tag_args);
+
+ case 'if':
+ return $this->_compile_if_tag($tag_args);
+
+ case 'else':
+ return '<?php else: ?>';
+
+ case 'elseif':
+ return $this->_compile_if_tag($tag_args, true);
+
+ case '/if':
+ return '<?php endif; ?>';
+
+ case 'capture':
+ return $this->_compile_capture_tag(true, $tag_args);
+
+ case '/capture':
+ return $this->_compile_capture_tag(false);
+
+ case 'ldelim':
+ return $this->left_delimiter;
+
+ case 'rdelim':
+ return $this->right_delimiter;
+
+ case 'section':
+ array_push($this->_sectionelse_stack, false);
+ return $this->_compile_section_start($tag_args);
+
+ case 'sectionelse':
+ $this->_sectionelse_stack[count($this->_sectionelse_stack)-1] = true;
+ return "<?php endfor; else: ?>";
+
+ case '/section':
+ if (array_pop($this->_sectionelse_stack))
+ return "<?php endif; ?>";
+ else
+ return "<?php endfor; endif; ?>";
+
+ case 'foreach':
+ array_push($this->_foreachelse_stack, false);
+ return $this->_compile_foreach_start($tag_args);
+ break;
+
+ case 'foreachelse':
+ $this->_foreachelse_stack[count($this->_foreachelse_stack)-1] = true;
+ return "<?php endforeach; unset(\$_from); else: ?>";
+
+ case '/foreach':
+ if (array_pop($this->_foreachelse_stack))
+ return "<?php endif; ?>";
+ else
+ return "<?php endforeach; unset(\$_from); endif; ?>";
+
+ case 'strip':
+ case '/strip':
+ if ($tag_command{0}=='/') {
+ if (--$this->_strip_depth==0) { /* outermost closing {/strip} */
+ $this->_additional_newline = "\n";
+ return $this->left_delimiter.$tag_command.$this->right_delimiter;
+ }
+ } else {
+ if ($this->_strip_depth++==0) { /* outermost opening {strip} */
+ $this->_additional_newline = "";
+ return $this->left_delimiter.$tag_command.$this->right_delimiter;
+ }
+ }
+ return '';
+
+ case 'literal':
+ list (,$literal_block) = each($this->_literal_blocks);
+ $this->_current_line_no += substr_count($literal_block, "\n");
+ return "<?php echo '".str_replace("'", "\'", str_replace("\\", "\\\\", $literal_block))."'; ?>" . $this->_additional_newline;
+
+ case 'php':
+ if ($this->security && !$this->security_settings['PHP_TAGS']) {
+ $this->_syntax_error("(secure mode) php tags not permitted", E_USER_WARNING, __FILE__, __LINE__);
+ return;
+ }
+ list (,$php_block) = each($this->_php_blocks);
+ $this->_current_line_no += substr_count($php_block, "\n");
+ return '<?php '.$php_block.' ?>';
+
+ case 'insert':
+ return $this->_compile_insert_tag($tag_args);
+
+ default:
+ if ($this->_compile_compiler_tag($tag_command, $tag_args, $output)) {
+ return $output;
+ } else if ($this->_compile_block_tag($tag_command, $tag_args, $tag_modifier, $output)) {
+ return $output;
+ } else {
+ return $this->_compile_custom_tag($tag_command, $tag_args, $tag_modifier);
+ }
+ }
+ }
+
+
+ /**
+ * compile the custom compiler tag
+ *
+ * sets $output to the compiled custom compiler tag
+ * @param string $tag_command
+ * @param string $tag_args
+ * @param string $output
+ * @return boolean
+ */
+ function _compile_compiler_tag($tag_command, $tag_args, &$output)
+ {
+ $found = false;
+ $have_function = true;
+
+ /*
+ * First we check if the compiler function has already been registered
+ * or loaded from a plugin file.
+ */
+ if (isset($this->_plugins['compiler'][$tag_command])) {
+ $found = true;
+ $plugin_func = $this->_plugins['compiler'][$tag_command][0];
+ if (!is_callable($plugin_func)) {
+ $message = "compiler function '$tag_command' is not implemented";
+ $have_function = false;
+ }
+ }
+ /*
+ * Otherwise we need to load plugin file and look for the function
+ * inside it.
+ */
+ else if ($plugin_file = $this->_get_plugin_filepath('compiler', $tag_command)) {
+ $found = true;
+
+ include_once $plugin_file;
+
+ $plugin_func = 'smarty_compiler_' . $tag_command;
+ if (!is_callable($plugin_func)) {
+ $message = "plugin function $plugin_func() not found in $plugin_file\n";
+ $have_function = false;
+ } else {
+ $this->_plugins['compiler'][$tag_command] = array($plugin_func, null, null, null, true);
+ }
+ }
+
+ /*
+ * True return value means that we either found a plugin or a
+ * dynamically registered function. False means that we didn't and the
+ * compiler should now emit code to load custom function plugin for this
+ * tag.
+ */
+ if ($found) {
+ if ($have_function) {
+ $output = call_user_func_array($plugin_func, array($tag_args, &$this));
+ if($output != '') {
+ $output = '<?php ' . $this->_push_cacheable_state('compiler', $tag_command)
+ . $output
+ . $this->_pop_cacheable_state('compiler', $tag_command) . ' ?>';
+ }
+ } else {
+ $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+
+ /**
+ * compile block function tag
+ *
+ * sets $output to compiled block function tag
+ * @param string $tag_command
+ * @param string $tag_args
+ * @param string $tag_modifier
+ * @param string $output
+ * @return boolean
+ */
+ function _compile_block_tag($tag_command, $tag_args, $tag_modifier, &$output)
+ {
+ if ($tag_command{0} == '/') {
+ $start_tag = false;
+ $tag_command = substr($tag_command, 1);
+ } else
+ $start_tag = true;
+
+ $found = false;
+ $have_function = true;
+
+ /*
+ * First we check if the block function has already been registered
+ * or loaded from a plugin file.
+ */
+ if (isset($this->_plugins['block'][$tag_command])) {
+ $found = true;
+ $plugin_func = $this->_plugins['block'][$tag_command][0];
+ if (!is_callable($plugin_func)) {
+ $message = "block function '$tag_command' is not implemented";
+ $have_function = false;
+ }
+ }
+ /*
+ * Otherwise we need to load plugin file and look for the function
+ * inside it.
+ */
+ else if ($plugin_file = $this->_get_plugin_filepath('block', $tag_command)) {
+ $found = true;
+
+ include_once $plugin_file;
+
+ $plugin_func = 'smarty_block_' . $tag_command;
+ if (!function_exists($plugin_func)) {
+ $message = "plugin function $plugin_func() not found in $plugin_file\n";
+ $have_function = false;
+ } else {
+ $this->_plugins['block'][$tag_command] = array($plugin_func, null, null, null, true);
+
+ }
+ }
+
+ if (!$found) {
+ return false;
+ } else if (!$have_function) {
+ $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);
+ return true;
+ }
+
+ /*
+ * Even though we've located the plugin function, compilation
+ * happens only once, so the plugin will still need to be loaded
+ * at runtime for future requests.
+ */
+ $this->_add_plugin('block', $tag_command);
+
+ if ($start_tag) {
+ $output = '<?php ' . $this->_push_cacheable_state('block', $tag_command);
+ $attrs = $this->_parse_attrs($tag_args);
+ $arg_list = $this->_compile_arg_list('block', $tag_command, $attrs, $_cache_attrs='');
+ $output .= "$_cache_attrs\$_params = \$this->_tag_stack[] = array('$tag_command', array(".implode(',', $arg_list).')); ';
+ $output .= $this->_compile_plugin_call('block', $tag_command).'($_params[1], null, $this, $_block_repeat=true); unset($_params);';
+ $output .= 'while ($_block_repeat) { ob_start(); ?>';
+ } else {
+ $output = '<?php $this->_block_content = ob_get_contents(); ob_end_clean(); ';
+ $_out_tag_text = $this->_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], $this->_block_content, $this, $_block_repeat=false)';
+ if ($tag_modifier != '') {
+ $this->_parse_modifiers($_out_tag_text, $tag_modifier);
+ }
+ $output .= 'echo '.$_out_tag_text.'; } ';
+ $output .= " array_pop(\$this->_tag_stack); " . $this->_pop_cacheable_state('block', $tag_command) . '?>';
+ }
+
+ return true;
+ }
+
+
+ /**
+ * compile custom function tag
+ *
+ * @param string $tag_command
+ * @param string $tag_args
+ * @param string $tag_modifier
+ * @return string
+ */
+ function _compile_custom_tag($tag_command, $tag_args, $tag_modifier)
+ {
+ $this->_add_plugin('function', $tag_command);
+
+ $_cacheable_state = $this->_push_cacheable_state('function', $tag_command);
+ $attrs = $this->_parse_attrs($tag_args);
+ $arg_list = $this->_compile_arg_list('function', $tag_command, $attrs, $_cache_attrs='');
+
+ $_return = $this->_compile_plugin_call('function', $tag_command).'(array('.implode(',', $arg_list)."), \$this)";
+ if($tag_modifier != '') {
+ $this->_parse_modifiers($_return, $tag_modifier);
+ }
+
+ if($_return != '') {
+ $_return = '<?php ' . $_cacheable_state . $_cache_attrs . 'echo ' . $_return . ';'
+ . $this->_pop_cacheable_state('function', $tag_command) . "?>" . $this->_additional_newline;
+ }
+
+ return $_return;
+ }
+
+ /**
+ * compile a registered object tag
+ *
+ * @param string $tag_command
+ * @param array $attrs
+ * @param string $tag_modifier
+ * @return string
+ */
+ function _compile_registered_object_tag($tag_command, $attrs, $tag_modifier)
+ {
+ if ($tag_command{0} == '/') {
+ $start_tag = false;
+ $tag_command = substr($tag_command, 1);
+ } else {
+ $start_tag = true;
+ }
+
+ list($object, $obj_comp) = explode('->', $tag_command);
+
+ $arg_list = array();
+ if(count($attrs)) {
+ $_assign_var = false;
+ foreach ($attrs as $arg_name => $arg_value) {
+ if($arg_name == 'assign') {
+ $_assign_var = $arg_value;
+ unset($attrs['assign']);
+ continue;
+ }
+ if (is_bool($arg_value))
+ $arg_value = $arg_value ? 'true' : 'false';
+ $arg_list[] = "'$arg_name' => $arg_value";
+ }
+ }
+
+ if($this->_reg_objects[$object][2]) {
+ // smarty object argument format
+ $args = "array(".implode(',', (array)$arg_list)."), \$this";
+ } else {
+ // traditional argument format
+ $args = implode(',', array_values($attrs));
+ if (empty($args)) {
+ $args = 'null';
+ }
+ }
+
+ $prefix = '';
+ $postfix = '';
+ $newline = '';
+ if(!is_object($this->_reg_objects[$object][0])) {
+ $this->_trigger_fatal_error("registered '$object' is not an object");
+ } elseif(!empty($this->_reg_objects[$object][1]) && !in_array($obj_comp, $this->_reg_objects[$object][1])) {
+ $this->_trigger_fatal_error("'$obj_comp' is not a registered component of object '$object'");
+ } elseif(method_exists($this->_reg_objects[$object][0], $obj_comp)) {
+ // method
+ if(in_array($obj_comp, $this->_reg_objects[$object][3])) {
+ // block method
+ if ($start_tag) {
+ $prefix = "\$this->_tag_stack[] = array('$obj_comp', $args); ";
+ $prefix .= "\$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], null, \$this, \$_block_repeat=true); ";
+ $prefix .= "while (\$_block_repeat) { ob_start();";
+ $return = null;
+ $postfix = '';
+ } else {
+ $prefix = "\$this->_obj_block_content = ob_get_contents(); ob_end_clean(); ";
+ $return = "\$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], \$this->_obj_block_content, \$this, \$_block_repeat=false)";
+ $postfix = "} array_pop(\$this->_tag_stack);";
+ }
+ } else {
+ // non-block method
+ $return = "\$this->_reg_objects['$object'][0]->$obj_comp($args)";
+ }
+ } else {
+ // property
+ $return = "\$this->_reg_objects['$object'][0]->$obj_comp";
+ }
+
+ if($return != null) {
+ if($tag_modifier != '') {
+ $this->_parse_modifiers($return, $tag_modifier);
+ }
+
+ if(!empty($_assign_var)) {
+ $output = "\$this->assign('" . $this->_dequote($_assign_var) ."', $return);";
+ } else {
+ $output = 'echo ' . $return . ';';
+ $newline = $this->_additional_newline;
+ }
+ } else {
+ $output = '';
+ }
+
+ return '<?php ' . $prefix . $output . $postfix . "?>" . $newline;
+ }
+
+ /**
+ * Compile {insert ...} tag
+ *
+ * @param string $tag_args
+ * @return string
+ */
+ function _compile_insert_tag($tag_args)
+ {
+ $attrs = $this->_parse_attrs($tag_args);
+ $name = $this->_dequote($attrs['name']);
+
+ if (empty($name)) {
+ $this->_syntax_error("missing insert name", E_USER_ERROR, __FILE__, __LINE__);
+ }
+
+ if (!empty($attrs['script'])) {
+ $delayed_loading = true;
+ } else {
+ $delayed_loading = false;
+ }
+
+ foreach ($attrs as $arg_name => $arg_value) {
+ if (is_bool($arg_value))
+ $arg_value = $arg_value ? 'true' : 'false';
+ $arg_list[] = "'$arg_name' => $arg_value";
+ }
+
+ $this->_add_plugin('insert', $name, $delayed_loading);
+
+ $_params = "array('args' => array(".implode(', ', (array)$arg_list)."))";
+
+ return "<?php require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.run_insert_handler.php');\necho smarty_core_run_insert_handler($_params, \$this); ?>" . $this->_additional_newline;
+ }
+
+ /**
+ * Compile {include ...} tag
+ *
+ * @param string $tag_args
+ * @return string
+ */
+ function _compile_include_tag($tag_args)
+ {
+ $attrs = $this->_parse_attrs($tag_args);
+ $arg_list = array();
+
+ if (empty($attrs['file'])) {
+ $this->_syntax_error("missing 'file' attribute in include tag", E_USER_ERROR, __FILE__, __LINE__);
+ }
+
+ foreach ($attrs as $arg_name => $arg_value) {
+ if ($arg_name == 'file') {
+ $include_file = $arg_value;
+ continue;
+ } else if ($arg_name == 'assign') {
+ $assign_var = $arg_value;
+ continue;
+ }
+ if (is_bool($arg_value))
+ $arg_value = $arg_value ? 'true' : 'false';
+ $arg_list[] = "'$arg_name' => $arg_value";
+ }
+
+ $output = '<?php ';
+
+ if (isset($assign_var)) {
+ $output .= "ob_start();\n";
+ }
+
+ $output .=
+ "\$_smarty_tpl_vars = \$this->_tpl_vars;\n";
+
+
+ $_params = "array('smarty_include_tpl_file' => " . $include_file . ", 'smarty_include_vars' => array(".implode(',', (array)$arg_list)."))";
+ $output .= "\$this->_smarty_include($_params);\n" .
+ "\$this->_tpl_vars = \$_smarty_tpl_vars;\n" .
+ "unset(\$_smarty_tpl_vars);\n";
+
+ if (isset($assign_var)) {
+ $output .= "\$this->assign(" . $assign_var . ", ob_get_contents()); ob_end_clean();\n";
+ }
+
+ $output .= ' ?>';
+
+ return $output;
+
+ }
+
+ /**
+ * Compile {include ...} tag
+ *
+ * @param string $tag_args
+ * @return string
+ */
+ function _compile_include_php_tag($tag_args)
+ {
+ $attrs = $this->_parse_attrs($tag_args);
+
+ if (empty($attrs['file'])) {
+ $this->_syntax_error("missing 'file' attribute in include_php tag", E_USER_ERROR, __FILE__, __LINE__);
+ }
+
+ $assign_var = (empty($attrs['assign'])) ? '' : $this->_dequote($attrs['assign']);
+ $once_var = (empty($attrs['once']) || $attrs['once']=='false') ? 'false' : 'true';
+
+ foreach($attrs as $arg_name => $arg_value) {
+ if($arg_name != 'file' AND $arg_name != 'once' AND $arg_name != 'assign') {
+ if(is_bool($arg_value))
+ $arg_value = $arg_value ? 'true' : 'false';
+ $arg_list[] = "'$arg_name' => $arg_value";
+ }
+ }
+
+ $_params = "array('smarty_file' => " . $attrs['file'] . ", 'smarty_assign' => '$assign_var', 'smarty_once' => $once_var, 'smarty_include_vars' => array(".implode(',', (array)$arg_list)."))";
+
+ return "<?php require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.smarty_include_php.php');\nsmarty_core_smarty_include_php($_params, \$this); ?>" . $this->_additional_newline;
+ }
+
+
+ /**
+ * Compile {section ...} tag
+ *
+ * @param string $tag_args
+ * @return string
+ */
+ function _compile_section_start($tag_args)
+ {
+ $attrs = $this->_parse_attrs($tag_args);
+ $arg_list = array();
+
+ $output = '<?php ';
+ $section_name = $attrs['name'];
+ if (empty($section_name)) {
+ $this->_syntax_error("missing section name", E_USER_ERROR, __FILE__, __LINE__);
+ }
+
+ $output .= "if (isset(\$this->_sections[$section_name])) unset(\$this->_sections[$section_name]);\n";
+ $section_props = "\$this->_sections[$section_name]";
+
+ foreach ($attrs as $attr_name => $attr_value) {
+ switch ($attr_name) {
+ case 'loop':
+ $output .= "{$section_props}['loop'] = is_array(\$_loop=$attr_value) ? count(\$_loop) : max(0, (int)\$_loop); unset(\$_loop);\n";
+ break;
+
+ case 'show':
+ if (is_bool($attr_value))
+ $show_attr_value = $attr_value ? 'true' : 'false';
+ else
+ $show_attr_value = "(bool)$attr_value";
+ $output .= "{$section_props}['show'] = $show_attr_value;\n";
+ break;
+
+ case 'name':
+ $output .= "{$section_props}['$attr_name'] = $attr_value;\n";
+ break;
+
+ case 'max':
+ case 'start':
+ $output .= "{$section_props}['$attr_name'] = (int)$attr_value;\n";
+ break;
+
+ case 'step':
+ $output .= "{$section_props}['$attr_name'] = ((int)$attr_value) == 0 ? 1 : (int)$attr_value;\n";
+ break;
+
+ default:
+ $this->_syntax_error("unknown section attribute - '$attr_name'", E_USER_ERROR, __FILE__, __LINE__);
+ break;
+ }
+ }
+
+ if (!isset($attrs['show']))
+ $output .= "{$section_props}['show'] = true;\n";
+
+ if (!isset($attrs['loop']))
+ $output .= "{$section_props}['loop'] = 1;\n";
+
+ if (!isset($attrs['max']))
+ $output .= "{$section_props}['max'] = {$section_props}['loop'];\n";
+ else
+ $output .= "if ({$section_props}['max'] < 0)\n" .
+ " {$section_props}['max'] = {$section_props}['loop'];\n";
+
+ if (!isset($attrs['step']))
+ $output .= "{$section_props}['step'] = 1;\n";
+
+ if (!isset($attrs['start']))
+ $output .= "{$section_props}['start'] = {$section_props}['step'] > 0 ? 0 : {$section_props}['loop']-1;\n";
+ else {
+ $output .= "if ({$section_props}['start'] < 0)\n" .
+ " {$section_props}['start'] = max({$section_props}['step'] > 0 ? 0 : -1, {$section_props}['loop'] + {$section_props}['start']);\n" .
+ "else\n" .
+ " {$section_props}['start'] = min({$section_props}['start'], {$section_props}['step'] > 0 ? {$section_props}['loop'] : {$section_props}['loop']-1);\n";
+ }
+
+ $output .= "if ({$section_props}['show']) {\n";
+ if (!isset($attrs['start']) && !isset($attrs['step']) && !isset($attrs['max'])) {
+ $output .= " {$section_props}['total'] = {$section_props}['loop'];\n";
+ } else {
+ $output .= " {$section_props}['total'] = min(ceil(({$section_props}['step'] > 0 ? {$section_props}['loop'] - {$section_props}['start'] : {$section_props}['start']+1)/abs({$section_props}['step'])), {$section_props}['max']);\n";
+ }
+ $output .= " if ({$section_props}['total'] == 0)\n" .
+ " {$section_props}['show'] = false;\n" .
+ "} else\n" .
+ " {$section_props}['total'] = 0;\n";
+
+ $output .= "if ({$section_props}['show']):\n";
+ $output .= "
+ for ({$section_props}['index'] = {$section_props}['start'], {$section_props}['iteration'] = 1;
+ {$section_props}['iteration'] <= {$section_props}['total'];
+ {$section_props}['index'] += {$section_props}['step'], {$section_props}['iteration']++):\n";
+ $output .= "{$section_props}['rownum'] = {$section_props}['iteration'];\n";
+ $output .= "{$section_props}['index_prev'] = {$section_props}['index'] - {$section_props}['step'];\n";
+ $output .= "{$section_props}['index_next'] = {$section_props}['index'] + {$section_props}['step'];\n";
+ $output .= "{$section_props}['first'] = ({$section_props}['iteration'] == 1);\n";
+ $output .= "{$section_props}['last'] = ({$section_props}['iteration'] == {$section_props}['total']);\n";
+
+ $output .= "?>";
+
+ return $output;
+ }
+
+
+ /**
+ * Compile {foreach ...} tag.
+ *
+ * @param string $tag_args
+ * @return string
+ */
+ function _compile_foreach_start($tag_args)
+ {
+ $attrs = $this->_parse_attrs($tag_args);
+ $arg_list = array();
+
+ if (empty($attrs['from'])) {
+ $this->_syntax_error("missing 'from' attribute", E_USER_ERROR, __FILE__, __LINE__);
+ }
+
+ if (empty($attrs['item'])) {
+ $this->_syntax_error("missing 'item' attribute", E_USER_ERROR, __FILE__, __LINE__);
+ }
+
+ $from = $attrs['from'];
+ $item = $this->_dequote($attrs['item']);
+ if (isset($attrs['name']))
+ $name = $attrs['name'];
+
+ $output = '<?php ';
+ if (isset($name)) {
+ $output .= "if (isset(\$this->_foreach[$name])) unset(\$this->_foreach[$name]);\n";
+ $foreach_props = "\$this->_foreach[$name]";
+ }
+
+ $key_part = '';
+
+ foreach ($attrs as $attr_name => $attr_value) {
+ switch ($attr_name) {
+ case 'key':
+ $key = $this->_dequote($attrs['key']);
+ $key_part = "\$this->_tpl_vars['$key'] => ";
+ break;
+
+ case 'name':
+ $output .= "{$foreach_props}['$attr_name'] = $attr_value;\n";
+ break;
+ }
+ }
+
+ if (isset($name)) {
+ $output .= "{$foreach_props}['total'] = count(\$_from = (array)$from);\n";
+ $output .= "{$foreach_props}['show'] = {$foreach_props}['total'] > 0;\n";
+ $output .= "if ({$foreach_props}['show']):\n";
+ $output .= "{$foreach_props}['iteration'] = 0;\n";
+ $output .= " foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n";
+ $output .= " {$foreach_props}['iteration']++;\n";
+ $output .= " {$foreach_props}['first'] = ({$foreach_props}['iteration'] == 1);\n";
+ $output .= " {$foreach_props}['last'] = ({$foreach_props}['iteration'] == {$foreach_props}['total']);\n";
+ } else {
+ $output .= "if (count(\$_from = (array)$from)):\n";
+ $output .= " foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n";
+ }
+ $output .= '?>';
+
+ return $output;
+ }
+
+
+ /**
+ * Compile {capture} .. {/capture} tags
+ *
+ * @param boolean $start true if this is the {capture} tag
+ * @param string $tag_args
+ * @return string
+ */
+
+ function _compile_capture_tag($start, $tag_args = '')
+ {
+ $attrs = $this->_parse_attrs($tag_args);
+
+ if ($start) {
+ if (isset($attrs['name']))
+ $buffer = $attrs['name'];
+ else
+ $buffer = "'default'";
+
+ if (isset($attrs['assign']))
+ $assign = $attrs['assign'];
+ else
+ $assign = null;
+ $output = "<?php ob_start(); ?>";
+ $this->_capture_stack[] = array($buffer, $assign);
+ } else {
+ list($buffer, $assign) = array_pop($this->_capture_stack);
+ $output = "<?php \$this->_smarty_vars['capture'][$buffer] = ob_get_contents(); ";
+ if (isset($assign)) {
+ $output .= " \$this->assign($assign, ob_get_contents());";
+ }
+ $output .= "ob_end_clean(); ?>";
+ }
+
+ return $output;
+ }
+
+ /**
+ * Compile {if ...} tag
+ *
+ * @param string $tag_args
+ * @param boolean $elseif if true, uses elseif instead of if
+ * @return string
+ */
+ function _compile_if_tag($tag_args, $elseif = false)
+ {
+
+ /* Tokenize args for 'if' tag. */
+ preg_match_all('/(?>
+ ' . $this->_obj_call_regexp . '(?:' . $this->_mod_regexp . '*)? | # valid object call
+ ' . $this->_var_regexp . '(?:' . $this->_mod_regexp . '*)? | # var or quoted string
+ \-?0[xX][0-9a-fA-F]+|\-?\d+(?:\.\d+)?|\.\d+|!==|===|==|!=|<>|<<|>>|<=|>=|\&\&|\|\||\(|\)|,|\!|\^|=|\&|\~|<|>|\||\%|\+|\-|\/|\*|\@ | # valid non-word token
+ \b\w+\b | # valid word token
+ \S+ # anything else
+ )/x', $tag_args, $match);
+
+ $tokens = $match[0];
+
+ // make sure we have balanced parenthesis
+ $token_count = array_count_values($tokens);
+ if(isset($token_count['(']) && $token_count['('] != $token_count[')']) {
+ $this->_syntax_error("unbalanced parenthesis in if statement", E_USER_ERROR, __FILE__, __LINE__);
+ }
+
+ $is_arg_stack = array();
+
+ for ($i = 0; $i < count($tokens); $i++) {
+
+ $token = &$tokens[$i];
+
+ switch (strtolower($token)) {
+ case '!':
+ case '%':
+ case '!==':
+ case '==':
+ case '===':
+ case '>':
+ case '<':
+ case '!=':
+ case '<>':
+ case '<<':
+ case '>>':
+ case '<=':
+ case '>=':
+ case '&&':
+ case '||':
+ case '|':
+ case '^':
+ case '&':
+ case '~':
+ case ')':
+ case ',':
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '@':
+ break;
+
+ case 'eq':
+ $token = '==';
+ break;
+
+ case 'ne':
+ case 'neq':
+ $token = '!=';
+ break;
+
+ case 'lt':
+ $token = '<';
+ break;
+
+ case 'le':
+ case 'lte':
+ $token = '<=';
+ break;
+
+ case 'gt':
+ $token = '>';
+ break;
+
+ case 'ge':
+ case 'gte':
+ $token = '>=';
+ break;
+
+ case 'and':
+ $token = '&&';
+ break;
+
+ case 'or':
+ $token = '||';
+ break;
+
+ case 'not':
+ $token = '!';
+ break;
+
+ case 'mod':
+ $token = '%';
+ break;
+
+ case '(':
+ array_push($is_arg_stack, $i);
+ break;
+
+ case 'is':
+ /* If last token was a ')', we operate on the parenthesized
+ expression. The start of the expression is on the stack.
+ Otherwise, we operate on the last encountered token. */
+ if ($tokens[$i-1] == ')')
+ $is_arg_start = array_pop($is_arg_stack);
+ else
+ $is_arg_start = $i-1;
+ /* Construct the argument for 'is' expression, so it knows
+ what to operate on. */
+ $is_arg = implode(' ', array_slice($tokens, $is_arg_start, $i - $is_arg_start));
+
+ /* Pass all tokens from next one until the end to the
+ 'is' expression parsing function. The function will
+ return modified tokens, where the first one is the result
+ of the 'is' expression and the rest are the tokens it
+ didn't touch. */
+ $new_tokens = $this->_parse_is_expr($is_arg, array_slice($tokens, $i+1));
+
+ /* Replace the old tokens with the new ones. */
+ array_splice($tokens, $is_arg_start, count($tokens), $new_tokens);
+
+ /* Adjust argument start so that it won't change from the
+ current position for the next iteration. */
+ $i = $is_arg_start;
+ break;
+
+ default:
+ if(preg_match('!^' . $this->_func_regexp . '$!', $token) ) {
+ // function call
+ if($this->security &&
+ !in_array($token, $this->security_settings['IF_FUNCS'])) {
+ $this->_syntax_error("(secure mode) '$token' not allowed in if statement", E_USER_ERROR, __FILE__, __LINE__);
+ }
+ } elseif(preg_match('!^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '(?:' . $this->_mod_regexp . '*)$!', $token)) {
+ // object or variable
+ $token = $this->_parse_var_props($token);
+ } elseif(is_numeric($token)) {
+ // number, skip it
+ } else {
+ $this->_syntax_error("unidentified token '$token'", E_USER_ERROR, __FILE__, __LINE__);
+ }
+ break;
+ }
+ }
+
+ if ($elseif)
+ return '<?php elseif ('.implode(' ', $tokens).'): ?>';
+ else
+ return '<?php if ('.implode(' ', $tokens).'): ?>';
+ }
+
+
+ function _compile_arg_list($type, $name, $attrs, &$cache_code) {
+ $arg_list = array();
+
+ if (isset($type) && isset($name)
+ && isset($this->_plugins[$type])
+ && isset($this->_plugins[$type][$name])
+ && empty($this->_plugins[$type][$name][4])
+ && is_array($this->_plugins[$type][$name][5])
+ ) {
+ /* we have a list of parameters that should be cached */
+ $_cache_attrs = $this->_plugins[$type][$name][5];
+ $_count = $this->_cache_attrs_count++;
+ $cache_code = "\$_cache_attrs =& \$this->_smarty_cache_attrs('$this->_cache_serial','$_count');";
+
+ } else {
+ /* no parameters are cached */
+ $_cache_attrs = null;
+ }
+
+ foreach ($attrs as $arg_name => $arg_value) {
+ if (is_bool($arg_value))
+ $arg_value = $arg_value ? 'true' : 'false';
+ if (is_null($arg_value))
+ $arg_value = 'null';
+ if ($_cache_attrs && in_array($arg_name, $_cache_attrs)) {
+ $arg_list[] = "'$arg_name' => (\$this->_cache_including) ? \$_cache_attrs['$arg_name'] : (\$_cache_attrs['$arg_name']=$arg_value)";
+ } else {
+ $arg_list[] = "'$arg_name' => $arg_value";
+ }
+ }
+ return $arg_list;
+ }
+
+ /**
+ * Parse is expression
+ *
+ * @param string $is_arg
+ * @param array $tokens
+ * @return array
+ */
+ function _parse_is_expr($is_arg, $tokens)
+ {
+ $expr_end = 0;
+ $negate_expr = false;
+
+ if (($first_token = array_shift($tokens)) == 'not') {
+ $negate_expr = true;
+ $expr_type = array_shift($tokens);
+ } else
+ $expr_type = $first_token;
+
+ switch ($expr_type) {
+ case 'even':
+ if (@$tokens[$expr_end] == 'by') {
+ $expr_end++;
+ $expr_arg = $tokens[$expr_end++];
+ $expr = "!(($is_arg / $expr_arg) % " . $this->_parse_var_props($expr_arg) . ")";
+ } else
+ $expr = "!($is_arg % 2)";
+ break;
+
+ case 'odd':
+ if (@$tokens[$expr_end] == 'by') {
+ $expr_end++;
+ $expr_arg = $tokens[$expr_end++];
+ $expr = "(($is_arg / $expr_arg) % ". $this->_parse_var_props($expr_arg) . ")";
+ } else
+ $expr = "($is_arg % 2)";
+ break;
+
+ case 'div':
+ if (@$tokens[$expr_end] == 'by') {
+ $expr_end++;
+ $expr_arg = $tokens[$expr_end++];
+ $expr = "!($is_arg % " . $this->_parse_var_props($expr_arg) . ")";
+ } else {
+ $this->_syntax_error("expecting 'by' after 'div'", E_USER_ERROR, __FILE__, __LINE__);
+ }
+ break;
+
+ default:
+ $this->_syntax_error("unknown 'is' expression - '$expr_type'", E_USER_ERROR, __FILE__, __LINE__);
+ break;
+ }
+
+ if ($negate_expr) {
+ $expr = "!($expr)";
+ }
+
+ array_splice($tokens, 0, $expr_end, $expr);
+
+ return $tokens;
+ }
+
+
+ /**
+ * Parse attribute string
+ *
+ * @param string $tag_args
+ * @return array
+ */
+ function _parse_attrs($tag_args)
+ {
+
+ /* Tokenize tag attributes. */
+ preg_match_all('/(?:' . $this->_obj_call_regexp . '|' . $this->_qstr_regexp . ' | (?>[^"\'=\s]+)
+ )+ |
+ [=]
+ /x', $tag_args, $match);
+ $tokens = $match[0];
+
+ $attrs = array();
+ /* Parse state:
+ 0 - expecting attribute name
+ 1 - expecting '='
+ 2 - expecting attribute value (not '=') */
+ $state = 0;
+
+ foreach ($tokens as $token) {
+ switch ($state) {
+ case 0:
+ /* If the token is a valid identifier, we set attribute name
+ and go to state 1. */
+ if (preg_match('!^\w+$!', $token)) {
+ $attr_name = $token;
+ $state = 1;
+ } else
+ $this->_syntax_error("invalid attribute name: '$token'", E_USER_ERROR, __FILE__, __LINE__);
+ break;
+
+ case 1:
+ /* If the token is '=', then we go to state 2. */
+ if ($token == '=') {
+ $state = 2;
+ } else
+ $this->_syntax_error("expecting '=' after attribute name '$last_token'", E_USER_ERROR, __FILE__, __LINE__);
+ break;
+
+ case 2:
+ /* If token is not '=', we set the attribute value and go to
+ state 0. */
+ if ($token != '=') {
+ /* We booleanize the token if it's a non-quoted possible
+ boolean value. */
+ if (preg_match('!^(on|yes|true)$!', $token)) {
+ $token = 'true';
+ } else if (preg_match('!^(off|no|false)$!', $token)) {
+ $token = 'false';
+ } else if ($token == 'null') {
+ $token = 'null';
+ } else if (preg_match('!^-?([0-9]+|0[xX][0-9a-fA-F]+)$!', $token)) {
+ /* treat integer literally */
+ } else if (!preg_match('!^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '(?:' . $this->_mod_regexp . ')*$!', $token)) {
+ /* treat as a string, double-quote it escaping quotes */
+ $token = '"'.addslashes($token).'"';
+ }
+
+ $attrs[$attr_name] = $token;
+ $state = 0;
+ } else
+ $this->_syntax_error("'=' cannot be an attribute value", E_USER_ERROR, __FILE__, __LINE__);
+ break;
+ }
+ $last_token = $token;
+ }
+
+ if($state != 0) {
+ if($state == 1) {
+ $this->_syntax_error("expecting '=' after attribute name '$last_token'", E_USER_ERROR, __FILE__, __LINE__);
+ } else {
+ $this->_syntax_error("missing attribute value", E_USER_ERROR, __FILE__, __LINE__);
+ }
+ }
+
+ $this->_parse_vars_props($attrs);
+
+ return $attrs;
+ }
+
+ /**
+ * compile multiple variables and section properties tokens into
+ * PHP code
+ *
+ * @param array $tokens
+ */
+ function _parse_vars_props(&$tokens)
+ {
+ foreach($tokens as $key => $val) {
+ $tokens[$key] = $this->_parse_var_props($val);
+ }
+ }
+
+ /**
+ * compile single variable and section properties token into
+ * PHP code
+ *
+ * @param string $val
+ * @param string $tag_attrs
+ * @return string
+ */
+ function _parse_var_props($val)
+ {
+ $val = trim($val);
+
+ if(preg_match('!^(' . $this->_obj_call_regexp . '|' . $this->_dvar_regexp . ')(' . $this->_mod_regexp . '*)$!', $val, $match)) {
+ // $ variable or object
+ $return = $this->_parse_var($match[1]);
+ if($match[2] != '') {
+ $this->_parse_modifiers($return, $match[2]);
+ }
+ return $return;
+ }
+ elseif(preg_match('!^' . $this->_db_qstr_regexp . '(?:' . $this->_mod_regexp . '*)$!', $val)) {
+ // double quoted text
+ preg_match('!^(' . $this->_db_qstr_regexp . ')('. $this->_mod_regexp . '*)$!', $val, $match);
+ $return = $this->_expand_quoted_text($match[1]);
+ if($match[2] != '') {
+ $this->_parse_modifiers($return, $match[2]);
+ }
+ return $return;
+ }
+ elseif(preg_match('!^' . $this->_si_qstr_regexp . '(?:' . $this->_mod_regexp . '*)$!', $val)) {
+ // single quoted text
+ preg_match('!^(' . $this->_si_qstr_regexp . ')('. $this->_mod_regexp . '*)$!', $val, $match);
+ if($match[2] != '') {
+ $this->_parse_modifiers($match[1], $match[2]);
+ return $match[1];
+ }
+ }
+ elseif(preg_match('!^' . $this->_cvar_regexp . '(?:' . $this->_mod_regexp . '*)$!', $val)) {
+ // config var
+ return $this->_parse_conf_var($val);
+ }
+ elseif(preg_match('!^' . $this->_svar_regexp . '(?:' . $this->_mod_regexp . '*)$!', $val)) {
+ // section var
+ return $this->_parse_section_prop($val);
+ }
+ elseif(!in_array($val, $this->_permitted_tokens) && !is_numeric($val)) {
+ // literal string
+ return $this->_expand_quoted_text('"' . $val .'"');
+ }
+ return $val;
+ }
+
+ /**
+ * expand quoted text with embedded variables
+ *
+ * @param string $var_expr
+ * @return string
+ */
+ function _expand_quoted_text($var_expr)
+ {
+ // if contains unescaped $, expand it
+ if(preg_match_all('%(?:\`(?<!\\\\)\$' . $this->_dvar_guts_regexp . '\`)|(?:(?<!\\\\)\$\w+(\[[a-zA-Z0-9]+\])*)%', $var_expr, $_match)) {
+ $_match = $_match[0];
+ rsort($_match);
+ reset($_match);
+ foreach($_match as $_var) {
+ $var_expr = str_replace ($_var, '".(' . $this->_parse_var(str_replace('`','',$_var)) . ')."', $var_expr);
+ }
+ $_return = preg_replace('%\.""|(?<!\\\\)""\.%', '', $var_expr);
+ } else {
+ $_return = $var_expr;
+ }
+ // replace double quoted literal string with single quotes
+ $_return = preg_replace('!^"([\s\w]+)"$!',"'\\1'",$_return);
+ return $_return;
+ }
+
+ /**
+ * parse variable expression into PHP code
+ *
+ * @param string $var_expr
+ * @param string $output
+ * @return string
+ */
+ function _parse_var($var_expr)
+ {
+ $_has_math = false;
+ $_math_vars = preg_split('!('.$this->_dvar_math_regexp.'|'.$this->_qstr_regexp.')!', $var_expr, -1, PREG_SPLIT_DELIM_CAPTURE);
+
+ if(count($_math_vars) > 1) {
+ $_first_var = "";
+ $_complete_var = "";
+ // simple check if there is any math, to stop recursion (due to modifiers with "xx % yy" as parameter)
+ foreach($_math_vars as $_k => $_math_var) {
+ $_math_var = $_math_vars[$_k];
+
+ if(!empty($_math_var) || is_numeric($_math_var)) {
+ // hit a math operator, so process the stuff which came before it
+ if(preg_match('!^' . $this->_dvar_math_regexp . '$!', $_math_var)) {
+ $_has_math = true;
+ if(!empty($_complete_var) || is_numeric($_complete_var)) {
+ $_output .= $this->_parse_var($_complete_var);
+ }
+
+ // just output the math operator to php
+ $_output .= $_math_var;
+
+ if(empty($_first_var))
+ $_first_var = $_complete_var;
+
+ $_complete_var = "";
+ } else {
+ // fetch multiple -> (like $foo->bar->baz ) which wouldn't get fetched else, because it would only get $foo->bar and treat the ->baz as "-" ">baz" then
+ for($_i = $_k + 1; $_i <= count($_math_vars); $_i += 2) {
+ // fetch -> because it gets splitted at - and move it back together
+ if( /* prevent notice */ (isset($_math_vars[$_i]) && isset($_math_vars[$_i+1])) && ($_math_vars[$_i] === '-' && $_math_vars[$_i+1]{0} === '>')) {
+ $_math_var .= $_math_vars[$_i].$_math_vars[$_i+1];
+ $_math_vars[$_i] = $_math_vars[$_i+1] = '';
+ } else {
+ break;
+ }
+ }
+ $_complete_var .= $_math_var;
+ }
+ }
+ }
+ if($_has_math) {
+ if(!empty($_complete_var) || is_numeric($_complete_var))
+ $_output .= $this->_parse_var($_complete_var, true);
+
+ // get the modifiers working (only the last var from math + modifier is left)
+ $var_expr = $_complete_var;
+ }
+ }
+
+ // prevent cutting of first digit in the number (we _definitly_ got a number if the first char is a digit)
+ if(is_numeric($var_expr{0}))
+ $_var_ref = $var_expr;
+ else
+ $_var_ref = substr($var_expr, 1);
+
+ if(!$_has_math) {
+ // get [foo] and .foo and ->foo and (...) pieces
+ preg_match_all('!(?:^\w+)|' . $this->_obj_params_regexp . '|(?:' . $this->_var_bracket_regexp . ')|->\$?\w+|\.\$?\w+|\S+!', $_var_ref, $match);
+
+ $_indexes = $match[0];
+ $_var_name = array_shift($_indexes);
+
+ /* Handle $smarty.* variable references as a special case. */
+ if ($_var_name == 'smarty') {
+ /*
+ * If the reference could be compiled, use the compiled output;
+ * otherwise, fall back on the $smarty variable generated at
+ * run-time.
+ */
+ if (($smarty_ref = $this->_compile_smarty_ref($_indexes)) !== null) {
+ $_output = $smarty_ref;
+ } else {
+ $_var_name = substr(array_shift($_indexes), 1);
+ $_output = "\$this->_smarty_vars['$_var_name']";
+ }
+ } elseif(is_numeric($_var_name) && is_numeric($var_expr{0})) {
+ // because . is the operator for accessing arrays thru inidizes we need to put it together again for floating point numbers
+ if(count($_indexes) > 0)
+ {
+ $_var_name .= implode("", $_indexes);
+ $_indexes = array();
+ }
+ $_output = $_var_name;
+ } else {
+ $_output = "\$this->_tpl_vars['$_var_name']";
+ }
+
+ foreach ($_indexes as $_index) {
+ if ($_index{0} == '[') {
+ $_index = substr($_index, 1, -1);
+ if (is_numeric($_index)) {
+ $_output .= "[$_index]";
+ } elseif ($_index{0} == '$') {
+ if (strpos($_index, '.') !== false) {
+ $_output .= '[' . $this->_parse_var($_index) . ']';
+ } else {
+ $_output .= "[\$this->_tpl_vars['" . substr($_index, 1) . "']]";
+ }
+ } else {
+ $_var_parts = explode('.', $_index);
+ $_var_section = $_var_parts[0];
+ $_var_section_prop = isset($_var_parts[1]) ? $_var_parts[1] : 'index';
+ $_output .= "[\$this->_sections['$_var_section']['$_var_section_prop']]";
+ }
+ } else if ($_index{0} == '.') {
+ if ($_index{1} == '$')
+ $_output .= "[\$this->_tpl_vars['" . substr($_index, 2) . "']]";
+ else
+ $_output .= "['" . substr($_index, 1) . "']";
+ } else if (substr($_index,0,2) == '->') {
+ if(substr($_index,2,2) == '__') {
+ $this->_syntax_error('call to internal object members is not allowed', E_USER_ERROR, __FILE__, __LINE__);
+ } elseif($this->security && substr($_index, 2, 1) == '_') {
+ $this->_syntax_error('(secure) call to private object member is not allowed', E_USER_ERROR, __FILE__, __LINE__);
+ } elseif ($_index{2} == '$') {
+ if ($this->security) {
+ $this->_syntax_error('(secure) call to dynamic object member is not allowed', E_USER_ERROR, __FILE__, __LINE__);
+ } else {
+ $_output .= '->{(($_var=$this->_tpl_vars[\''.substr($_index,3).'\']) && substr($_var,0,2)!=\'__\') ? $_var : $this->trigger_error("cannot access property \\"$_var\\"")}';
+ }
+ } else {
+ $_output .= $_index;
+ }
+ } elseif ($_index{0} == '(') {
+ $_index = $this->_parse_parenth_args($_index);
+ $_output .= $_index;
+ } else {
+ $_output .= $_index;
+ }
+ }
+ }
+
+ return $_output;
+ }
+
+ /**
+ * parse arguments in function call parenthesis
+ *
+ * @param string $parenth_args
+ * @return string
+ */
+ function _parse_parenth_args($parenth_args)
+ {
+ preg_match_all('!' . $this->_param_regexp . '!',$parenth_args, $match);
+ $match = $match[0];
+ rsort($match);
+ reset($match);
+ $orig_vals = $match;
+ $this->_parse_vars_props($match);
+ return str_replace($orig_vals, $match, $parenth_args);
+ }
+
+ /**
+ * parse configuration variable expression into PHP code
+ *
+ * @param string $conf_var_expr
+ */
+ function _parse_conf_var($conf_var_expr)
+ {
+ $parts = explode('|', $conf_var_expr, 2);
+ $var_ref = $parts[0];
+ $modifiers = isset($parts[1]) ? $parts[1] : '';
+
+ $var_name = substr($var_ref, 1, -1);
+
+ $output = "\$this->_config[0]['vars']['$var_name']";
+
+ $this->_parse_modifiers($output, $modifiers);
+
+ return $output;
+ }
+
+ /**
+ * parse section property expression into PHP code
+ *
+ * @param string $section_prop_expr
+ * @return string
+ */
+ function _parse_section_prop($section_prop_expr)
+ {
+ $parts = explode('|', $section_prop_expr, 2);
+ $var_ref = $parts[0];
+ $modifiers = isset($parts[1]) ? $parts[1] : '';
+
+ preg_match('!%(\w+)\.(\w+)%!', $var_ref, $match);
+ $section_name = $match[1];
+ $prop_name = $match[2];
+
+ $output = "\$this->_sections['$section_name']['$prop_name']";
+
+ $this->_parse_modifiers($output, $modifiers);
+
+ return $output;
+ }
+
+
+ /**
+ * parse modifier chain into PHP code
+ *
+ * sets $output to parsed modified chain
+ * @param string $output
+ * @param string $modifier_string
+ */
+ function _parse_modifiers(&$output, $modifier_string)
+ {
+ preg_match_all('!\|(@?\w+)((?>:(?:'. $this->_qstr_regexp . '|[^|]+))*)!', '|' . $modifier_string, $_match);
+ list(, $_modifiers, $modifier_arg_strings) = $_match;
+
+ for ($_i = 0, $_for_max = count($_modifiers); $_i < $_for_max; $_i++) {
+ $_modifier_name = $_modifiers[$_i];
+
+ if($_modifier_name == 'smarty') {
+ // skip smarty modifier
+ continue;
+ }
+
+ preg_match_all('!:(' . $this->_qstr_regexp . '|[^:]+)!', $modifier_arg_strings[$_i], $_match);
+ $_modifier_args = $_match[1];
+
+ if ($_modifier_name{0} == '@') {
+ $_map_array = false;
+ $_modifier_name = substr($_modifier_name, 1);
+ } else {
+ $_map_array = true;
+ }
+
+ $this->_add_plugin('modifier', $_modifier_name);
+ if (empty($this->_plugins['modifier'][$_modifier_name])
+ && !$this->_get_plugin_filepath('modifier', $_modifier_name)
+ && function_exists($_modifier_name)) {
+ if ($this->security && !in_array($_modifier_name, $this->security_settings['MODIFIER_FUNCS'])) {
+ $this->_trigger_fatal_error("[plugin] (secure mode) modifier '$_modifier_name' is not allowed" , $_tpl_file, $_tpl_line, __FILE__, __LINE__);
+ } else {
+ $this->_plugins['modifier'][$_modifier_name] = array($_modifier_name, null, null, false);
+ }
+ }
+
+ $this->_parse_vars_props($_modifier_args);
+
+ if($_modifier_name == 'default') {
+ // supress notifications of default modifier vars and args
+ if($output{0} == '$') {
+ $output = '@' . $output;
+ }
+ if(isset($_modifier_args[0]) && $_modifier_args[0]{0} == '$') {
+ $_modifier_args[0] = '@' . $_modifier_args[0];
+ }
+ }
+ if (count($_modifier_args) > 0)
+ $_modifier_args = ', '.implode(', ', $_modifier_args);
+ else
+ $_modifier_args = '';
+
+ if ($_map_array) {
+ $output = "((is_array(\$_tmp=$output)) ? \$this->_run_mod_handler('$_modifier_name', true, \$_tmp$_modifier_args) : " . $this->_compile_plugin_call('modifier', $_modifier_name) . "(\$_tmp$_modifier_args))";
+
+ } else {
+
+ $output = $this->_compile_plugin_call('modifier', $_modifier_name)."($output$_modifier_args)";
+
+ }
+ }
+ }
+
+
+ /**
+ * add plugin
+ *
+ * @param string $type
+ * @param string $name
+ * @param boolean? $delayed_loading
+ */
+ function _add_plugin($type, $name, $delayed_loading = null)
+ {
+ if (!isset($this->_plugin_info[$type])) {
+ $this->_plugin_info[$type] = array();
+ }
+ if (!isset($this->_plugin_info[$type][$name])) {
+ $this->_plugin_info[$type][$name] = array($this->_current_file,
+ $this->_current_line_no,
+ $delayed_loading);
+ }
+ }
+
+
+ /**
+ * Compiles references of type $smarty.foo
+ *
+ * @param string $indexes
+ * @return string
+ */
+ function _compile_smarty_ref(&$indexes)
+ {
+ /* Extract the reference name. */
+ $_ref = substr($indexes[0], 1);
+ foreach($indexes as $_index_no=>$_index) {
+ if ($_index{0} != '.' && $_index_no<2 || !preg_match('!^(\.|\[|->)!', $_index)) {
+ $this->_syntax_error('$smarty' . implode('', array_slice($indexes, 0, 2)) . ' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__);
+ }
+ }
+
+ switch ($_ref) {
+ case 'now':
+ $compiled_ref = 'time()';
+ $_max_index = 1;
+ break;
+
+ case 'foreach':
+ case 'section':
+ array_shift($indexes);
+ $_var = $this->_parse_var_props(substr($indexes[0], 1));
+ if ($_ref == 'foreach')
+ $compiled_ref = "\$this->_foreach[$_var]";
+ else
+ $compiled_ref = "\$this->_sections[$_var]";
+ break;
+
+ case 'get':
+ $compiled_ref = ($this->request_use_auto_globals) ? '$_GET' : "\$GLOBALS['HTTP_GET_VARS']";
+ break;
+
+ case 'post':
+ $compiled_ref = ($this->request_use_auto_globals) ? '$_POST' : "\$GLOBALS['HTTP_POST_VARS']";
+ break;
+
+ case 'cookies':
+ $compiled_ref = ($this->request_use_auto_globals) ? '$_COOKIE' : "\$GLOBALS['HTTP_COOKIE_VARS']";
+ break;
+
+ case 'env':
+ $compiled_ref = ($this->request_use_auto_globals) ? '$_ENV' : "\$GLOBALS['HTTP_ENV_VARS']";
+ break;
+
+ case 'server':
+ $compiled_ref = ($this->request_use_auto_globals) ? '$_SERVER' : "\$GLOBALS['HTTP_SERVER_VARS']";
+ break;
+
+ case 'session':
+ $compiled_ref = ($this->request_use_auto_globals) ? '$_SESSION' : "\$GLOBALS['HTTP_SESSION_VARS']";
+ break;
+
+ /*
+ * These cases are handled either at run-time or elsewhere in the
+ * compiler.
+ */
+ case 'request':
+ if ($this->request_use_auto_globals) {
+ $compiled_ref = '$_REQUEST';
+ break;
+ } else {
+ $this->_init_smarty_vars = true;
+ }
+ return null;
+
+ case 'capture':
+ return null;
+
+ case 'template':
+ $compiled_ref = "'$this->_current_file'";
+ $_max_index = 1;
+ break;
+
+ case 'version':
+ $compiled_ref = "'$this->_version'";
+ $_max_index = 1;
+ break;
+
+ case 'const':
+ array_shift($indexes);
+ $_val = $this->_parse_var_props(substr($indexes[0],1));
+ $compiled_ref = '@constant(' . $_val . ')';
+ $_max_index = 1;
+ break;
+
+ case 'config':
+ $compiled_ref = "\$this->_config[0]['vars']";
+ $_max_index = 2;
+ break;
+
+ default:
+ $this->_syntax_error('$smarty.' . $_ref . ' is an unknown reference', E_USER_ERROR, __FILE__, __LINE__);
+ break;
+ }
+
+ if (isset($_max_index) && count($indexes) > $_max_index) {
+ $this->_syntax_error('$smarty' . implode('', $indexes) .' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__);
+ }
+
+ array_shift($indexes);
+ return $compiled_ref;
+ }
+
+ /**
+ * compiles call to plugin of type $type with name $name
+ * returns a string containing the function-name or method call
+ * without the paramter-list that would have follow to make the
+ * call valid php-syntax
+ *
+ * @param string $type
+ * @param string $name
+ * @return string
+ */
+ function _compile_plugin_call($type, $name) {
+ if (isset($this->_plugins[$type][$name])) {
+ /* plugin loaded */
+ if (is_array($this->_plugins[$type][$name][0])) {
+ return ((is_object($this->_plugins[$type][$name][0][0])) ?
+ "\$this->_plugins['$type']['$name'][0][0]->" /* method callback */
+ : (string)($this->_plugins[$type][$name][0][0]).'::' /* class callback */
+ ). $this->_plugins[$type][$name][0][1];
+
+ } else {
+ /* function callback */
+ return $this->_plugins[$type][$name][0];
+
+ }
+ } else {
+ /* plugin not loaded -> auto-loadable-plugin */
+ return 'smarty_'.$type.'_'.$name;
+
+ }
+ }
+
+ /**
+ * load pre- and post-filters
+ */
+ function _load_filters()
+ {
+ if (count($this->_plugins['prefilter']) > 0) {
+ foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) {
+ if ($prefilter === false) {
+ unset($this->_plugins['prefilter'][$filter_name]);
+ $_params = array('plugins' => array(array('prefilter', $filter_name, null, null, false)));
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.load_plugins.php');
+ smarty_core_load_plugins($_params, $this);
+ }
+ }
+ }
+ if (count($this->_plugins['postfilter']) > 0) {
+ foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) {
+ if ($postfilter === false) {
+ unset($this->_plugins['postfilter'][$filter_name]);
+ $_params = array('plugins' => array(array('postfilter', $filter_name, null, null, false)));
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.load_plugins.php');
+ smarty_core_load_plugins($_params, $this);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Quote subpattern references
+ *
+ * @param string $string
+ * @return string
+ */
+ function _quote_replace($string)
+ {
+ return preg_replace('![\\$]\d!', '\\\\\\0', $string);
+ }
+
+ /**
+ * display Smarty syntax error
+ *
+ * @param string $error_msg
+ * @param integer $error_type
+ * @param string $file
+ * @param integer $line
+ */
+ function _syntax_error($error_msg, $error_type = E_USER_ERROR, $file=null, $line=null)
+ {
+ if(isset($file) && isset($line)) {
+ $info = ' ('.basename($file).", line $line)";
+ } else {
+ $info = null;
+ }
+ trigger_error('Smarty: [in ' . $this->_current_file . ' line ' .
+ $this->_current_line_no . "]: syntax error: $error_msg$info", $error_type);
+ }
+
+
+ /**
+ * check if the compilation changes from cacheable to
+ * non-cacheable state with the beginning of the current
+ * plugin. return php-code to reflect the transition.
+ * @return string
+ */
+ function _push_cacheable_state($type, $name) {
+ $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4];
+ if ($_cacheable
+ || 0<$this->_cacheable_state++) return '';
+ if (!isset($this->_cache_serial)) $this->_cache_serial = md5(uniqid('Smarty'));
+ $_ret = 'if ($this->caching) { echo \'{nocache:'
+ . $this->_cache_serial . '#' . $this->_nocache_count
+ . '}\';}';
+ return $_ret;
+ }
+
+
+ /**
+ * check if the compilation changes from non-cacheable to
+ * cacheable state with the end of the current plugin return
+ * php-code to reflect the transition.
+ * @return string
+ */
+ function _pop_cacheable_state($type, $name) {
+ $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4];
+ if ($_cacheable
+ || --$this->_cacheable_state>0) return '';
+ return 'if ($this->caching) { echo \'{/nocache:'
+ . $this->_cache_serial . '#' . ($this->_nocache_count++)
+ . '}\';}';
+ }
+
+}
+
+/**
+ * compare to values by their string length
+ *
+ * @access private
+ * @param string $a
+ * @param string $b
+ * @return 0|-1|1
+ */
+function _smarty_sort_length($a, $b)
+{
+ if($a == $b)
+ return 0;
+
+ if(strlen($a) == strlen($b))
+ return ($a > $b) ? -1 : 1;
+
+ return (strlen($a) > strlen($b)) ? -1 : 1;
+}
+
+
+/* vim: set et: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.assemble_plugin_filepath.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.assemble_plugin_filepath.php
new file mode 100644
index 00000000..4c40ae90
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.assemble_plugin_filepath.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * assemble filepath of requested plugin
+ *
+ * @param string $type
+ * @param string $name
+ * @return string|false
+ */
+function smarty_core_assemble_plugin_filepath($params, &$smarty)
+{
+
+ $_plugin_filename = $params['type'] . '.' . $params['name'] . '.php';
+ $_return = false;
+
+ foreach ((array)$smarty->plugins_dir as $_plugin_dir) {
+
+ $_plugin_filepath = $_plugin_dir . DIRECTORY_SEPARATOR . $_plugin_filename;
+
+ // see if path is relative
+ if (!preg_match("/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/", $_plugin_dir)) {
+ $_relative_paths[] = $_plugin_dir;
+ // relative path, see if it is in the SMARTY_DIR
+ if (@is_readable(SMARTY_DIR . $_plugin_filepath)) {
+ $_return = SMARTY_DIR . $_plugin_filepath;
+ break;
+ }
+ }
+ // try relative to cwd (or absolute)
+ if (@is_readable($_plugin_filepath)) {
+ $_return = $_plugin_filepath;
+ break;
+ }
+ }
+
+ if($_return === false) {
+ // still not found, try PHP include_path
+ if(isset($_relative_paths)) {
+ foreach ((array)$_relative_paths as $_plugin_dir) {
+
+ $_plugin_filepath = $_plugin_dir . DIRECTORY_SEPARATOR . $_plugin_filename;
+
+ $_params = array('file_path' => $_plugin_filepath);
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_include_path.php');
+ if(smarty_core_get_include_path($_params, $smarty)) {
+ return $_params['new_file_path'];
+ }
+ }
+ }
+ }
+
+ return $_return;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.assign_smarty_interface.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.assign_smarty_interface.php
new file mode 100644
index 00000000..500ba9a9
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.assign_smarty_interface.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty assign_smarty_interface core plugin
+ *
+ * Type: core<br>
+ * Name: assign_smarty_interface<br>
+ * Purpose: assign the $smarty interface variable
+ * @param array Format: null
+ * @param Smarty
+ */
+function smarty_core_assign_smarty_interface($params, &$smarty)
+{
+ if (isset($smarty->_smarty_vars) && isset($smarty->_smarty_vars['request'])) {
+ return;
+ }
+
+ $_globals_map = array('g' => 'HTTP_GET_VARS',
+ 'p' => 'HTTP_POST_VARS',
+ 'c' => 'HTTP_COOKIE_VARS',
+ 's' => 'HTTP_SERVER_VARS',
+ 'e' => 'HTTP_ENV_VARS');
+
+ $_smarty_vars_request = array();
+
+ foreach (preg_split('!!', strtolower($smarty->request_vars_order)) as $_c) {
+ if (isset($_globals_map[$_c])) {
+ $_smarty_vars_request = array_merge($_smarty_vars_request, $GLOBALS[$_globals_map[$_c]]);
+ }
+ }
+ $_smarty_vars_request = @array_merge($_smarty_vars_request, $GLOBALS['HTTP_SESSION_VARS']);
+
+ $smarty->_smarty_vars['request'] = $_smarty_vars_request;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.create_dir_structure.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.create_dir_structure.php
new file mode 100644
index 00000000..b57d50ea
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.create_dir_structure.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * create full directory structure
+ *
+ * @param string $dir
+ */
+
+// $dir
+
+function smarty_core_create_dir_structure($params, &$smarty)
+{
+ if (!file_exists($params['dir'])) {
+ $_open_basedir_ini = ini_get('open_basedir');
+
+ if (DIRECTORY_SEPARATOR=='/') {
+ /* unix-style paths */
+ $_dir = $params['dir'];
+ $_dir_parts = preg_split('!/+!', $_dir, -1, PREG_SPLIT_NO_EMPTY);
+ $_new_dir = ($_dir{0}=='/') ? '/' : getcwd().'/';
+ if($_use_open_basedir = !empty($_open_basedir_ini)) {
+ $_open_basedirs = explode(':', $_open_basedir_ini);
+ }
+
+ } else {
+ /* other-style paths */
+ $_dir = str_replace('\\','/', $params['dir']);
+ $_dir_parts = preg_split('!/+!', $_dir, -1, PREG_SPLIT_NO_EMPTY);
+ if (preg_match('!^((//)|([a-zA-Z]:/))!', $_dir, $_root_dir)) {
+ /* leading "//" for network volume, or "[letter]:/" for full path */
+ $_new_dir = $_root_dir[1];
+ /* remove drive-letter from _dir_parts */
+ if (isset($_root_dir[3])) array_shift($_dir_parts);
+
+ } else {
+ $_new_dir = str_replace('\\', '/', getcwd()).'/';
+
+ }
+
+ if($_use_open_basedir = !empty($_open_basedir_ini)) {
+ $_open_basedirs = explode(';', str_replace('\\', '/', $_open_basedir_ini));
+ }
+
+ }
+
+ /* all paths use "/" only from here */
+ foreach ($_dir_parts as $_dir_part) {
+ $_new_dir .= $_dir_part;
+
+ if ($_use_open_basedir) {
+ // do not attempt to test or make directories outside of open_basedir
+ $_make_new_dir = false;
+ foreach ($_open_basedirs as $_open_basedir) {
+ if (substr($_new_dir, 0, strlen($_open_basedir)) == $_open_basedir) {
+ $_make_new_dir = true;
+ break;
+ }
+ }
+ } else {
+ $_make_new_dir = true;
+ }
+
+ if ($_make_new_dir && !file_exists($_new_dir) && !@mkdir($_new_dir, $smarty->_dir_perms) && !is_dir($_new_dir)) {
+ $smarty->trigger_error("problem creating directory '" . $_new_dir . "'");
+ return false;
+ }
+ $_new_dir .= '/';
+ }
+ }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.display_debug_console.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.display_debug_console.php
new file mode 100644
index 00000000..252c4478
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.display_debug_console.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty debug_console function plugin
+ *
+ * Type: core<br>
+ * Name: display_debug_console<br>
+ * Purpose: display the javascript debug console window
+ * @param array Format: null
+ * @param Smarty
+ */
+function smarty_core_display_debug_console($params, &$smarty)
+{
+ // we must force compile the debug template in case the environment
+ // changed between separate applications.
+
+ if(empty($smarty->debug_tpl)) {
+ // set path to debug template from SMARTY_DIR
+ $smarty->debug_tpl = SMARTY_DIR . 'debug.tpl';
+ if($smarty->security && is_file($smarty->debug_tpl)) {
+ $smarty->secure_dir[] = dirname(realpath($smarty->debug_tpl));
+ }
+ }
+
+ $_ldelim_orig = $smarty->left_delimiter;
+ $_rdelim_orig = $smarty->right_delimiter;
+
+ $smarty->left_delimiter = '{';
+ $smarty->right_delimiter = '}';
+
+ $_compile_id_orig = $smarty->_compile_id;
+ $smarty->_compile_id = null;
+
+ $_compile_path = $smarty->_get_compile_path($smarty->debug_tpl);
+ if ($smarty->_compile_resource($smarty->debug_tpl, $_compile_path))
+ {
+ ob_start();
+ $smarty->_include($_compile_path);
+ $_results = ob_get_contents();
+ ob_end_clean();
+ } else {
+ $_results = '';
+ }
+
+ $smarty->_compile_id = $_compile_id_orig;
+
+ $smarty->left_delimiter = $_ldelim_orig;
+ $smarty->right_delimiter = $_rdelim_orig;
+
+ return $_results;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.get_include_path.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.get_include_path.php
new file mode 100644
index 00000000..855eed30
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.get_include_path.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Get path to file from include_path
+ *
+ * @param string $file_path
+ * @param string $new_file_path
+ * @return boolean
+ * @staticvar array|null
+ */
+
+// $file_path, &$new_file_path
+
+function smarty_core_get_include_path(&$params, &$smarty)
+{
+ static $_path_array = null;
+
+ if(!isset($_path_array)) {
+ $_ini_include_path = ini_get('include_path');
+
+ if(strstr($_ini_include_path,';')) {
+ // windows pathnames
+ $_path_array = explode(';',$_ini_include_path);
+ } else {
+ $_path_array = explode(':',$_ini_include_path);
+ }
+ }
+ foreach ($_path_array as $_include_path) {
+ if (file_exists($_include_path . DIRECTORY_SEPARATOR . $params['file_path'])) {
+ $params['new_file_path'] = $_include_path . DIRECTORY_SEPARATOR . $params['file_path'];
+ return true;
+ }
+ }
+ return false;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.get_microtime.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.get_microtime.php
new file mode 100644
index 00000000..3c998a71
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.get_microtime.php
@@ -0,0 +1,23 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Get seconds and microseconds
+ * @return double
+ */
+function smarty_core_get_microtime($params, &$smarty)
+{
+ $mtime = microtime();
+ $mtime = explode(" ", $mtime);
+ $mtime = (double)($mtime[1]) + (double)($mtime[0]);
+ return ($mtime);
+}
+
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.get_php_resource.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.get_php_resource.php
new file mode 100644
index 00000000..5279ad21
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.get_php_resource.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Retrieves PHP script resource
+ *
+ * sets $php_resource to the returned resource
+ * @param string $resource
+ * @param string $resource_type
+ * @param $php_resource
+ * @return boolean
+ */
+
+function smarty_core_get_php_resource(&$params, &$smarty)
+{
+
+ $params['resource_base_path'] = $smarty->trusted_dir;
+ $smarty->_parse_resource_name($params, $smarty);
+
+ /*
+ * Find out if the resource exists.
+ */
+
+ if ($params['resource_type'] == 'file') {
+ $_readable = false;
+ if(file_exists($params['resource_name']) && is_readable($params['resource_name'])) {
+ $_readable = true;
+ } else {
+ // test for file in include_path
+ $_params = array('file_path' => $params['resource_name']);
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_include_path.php');
+ if(smarty_core_get_include_path($_params, $smarty)) {
+ $_include_path = $_params['new_file_path'];
+ $_readable = true;
+ }
+ }
+ } else if ($params['resource_type'] != 'file') {
+ $_template_source = null;
+ $_readable = is_callable($smarty->_plugins['resource'][$params['resource_type']][0][0])
+ && call_user_func_array($smarty->_plugins['resource'][$params['resource_type']][0][0],
+ array($params['resource_name'], &$_template_source, &$smarty));
+ }
+
+ /*
+ * Set the error function, depending on which class calls us.
+ */
+ if (method_exists($smarty, '_syntax_error')) {
+ $_error_funcc = '_syntax_error';
+ } else {
+ $_error_funcc = 'trigger_error';
+ }
+
+ if ($_readable) {
+ if ($smarty->security) {
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.is_trusted.php');
+ if (!smarty_core_is_trusted($params, $smarty)) {
+ $smarty->$_error_funcc('(secure mode) ' . $params['resource_type'] . ':' . $params['resource_name'] . ' is not trusted');
+ return false;
+ }
+ }
+ } else {
+ $smarty->$_error_funcc($params['resource_type'] . ':' . $params['resource_name'] . ' is not readable');
+ return false;
+ }
+
+ if ($params['resource_type'] == 'file') {
+ $params['php_resource'] = $params['resource_name'];
+ } else {
+ $params['php_resource'] = $_template_source;
+ }
+ return true;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.is_secure.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.is_secure.php
new file mode 100644
index 00000000..d6358208
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.is_secure.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * determines if a resource is secure or not.
+ *
+ * @param string $resource_type
+ * @param string $resource_name
+ * @return boolean
+ */
+
+// $resource_type, $resource_name
+
+function smarty_core_is_secure($params, &$smarty)
+{
+ static $check_template_dir = true;
+
+ if (!$smarty->security || $smarty->security_settings['INCLUDE_ANY']) {
+ return true;
+ }
+
+ $_smarty_secure = false;
+ if ($params['resource_type'] == 'file') {
+ if($check_template_dir) {
+ if (!in_array($smarty->template_dir, $smarty->secure_dir))
+ // add template_dir to secure_dir array
+ array_unshift($smarty->secure_dir, $smarty->template_dir);
+ $check_template_dir = false;
+ }
+ if (!empty($smarty->secure_dir)) {
+ $_rp = realpath($params['resource_name']);
+ foreach ((array)$smarty->secure_dir as $curr_dir) {
+ if ( !empty($curr_dir) && is_readable ($curr_dir)) {
+ $_cd = realpath($curr_dir);
+ if (strncmp($_rp, $_cd, strlen($_cd)) == 0
+ && $_rp{strlen($_cd)} == DIRECTORY_SEPARATOR ) {
+ $_smarty_secure = true;
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ // resource is not on local file system
+ $_smarty_secure = call_user_func_array(
+ $smarty->_plugins['resource'][$params['resource_type']][0][2],
+ array($params['resource_name'], &$_smarty_secure, &$smarty));
+ }
+
+ return $_smarty_secure;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.is_trusted.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.is_trusted.php
new file mode 100644
index 00000000..478d3d30
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.is_trusted.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**#@+
+ * @access private
+ */
+/**
+ * determines if a resource is trusted or not
+ *
+ * @param string $resource_type
+ * @param string $resource_name
+ * @return boolean
+ */
+
+ // $resource_type, $resource_name
+
+function smarty_core_is_trusted($params, &$smarty)
+{
+ $_smarty_trusted = false;
+ if ($params['resource_type'] == 'file') {
+ if (!empty($smarty->trusted_dir)) {
+ $_rp = realpath($params['resource_name']);
+ foreach ((array)$smarty->trusted_dir as $curr_dir) {
+ if (!empty($curr_dir) && is_readable ($curr_dir)) {
+ $_cd = realpath($curr_dir);
+ if (strncmp($_rp, $_cd, strlen($_cd)) == 0
+ && $_rp{strlen($_cd)} == DIRECTORY_SEPARATOR ) {
+ $_smarty_trusted = true;
+ break;
+ }
+ }
+ }
+ }
+
+ } else {
+ // resource is not on local file system
+ $_smarty_trusted = call_user_func_array($smarty->_plugins['resource'][$params['resource_type']][0][3],
+ array($params['resource_name'], $smarty));
+ }
+
+ return $_smarty_trusted;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.load_plugins.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.load_plugins.php
new file mode 100644
index 00000000..6f412ec9
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.load_plugins.php
@@ -0,0 +1,125 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Load requested plugins
+ *
+ * @param array $plugins
+ */
+
+// $plugins
+
+function smarty_core_load_plugins($params, &$smarty)
+{
+
+ foreach ($params['plugins'] as $_plugin_info) {
+ list($_type, $_name, $_tpl_file, $_tpl_line, $_delayed_loading) = $_plugin_info;
+ $_plugin = &$smarty->_plugins[$_type][$_name];
+
+ /*
+ * We do not load plugin more than once for each instance of Smarty.
+ * The following code checks for that. The plugin can also be
+ * registered dynamically at runtime, in which case template file
+ * and line number will be unknown, so we fill them in.
+ *
+ * The final element of the info array is a flag that indicates
+ * whether the dynamically registered plugin function has been
+ * checked for existence yet or not.
+ */
+ if (isset($_plugin)) {
+ if (empty($_plugin[3])) {
+ if (!is_callable($_plugin[0])) {
+ $smarty->_trigger_fatal_error("[plugin] $_type '$_name' is not implemented", $_tpl_file, $_tpl_line, __FILE__, __LINE__);
+ } else {
+ $_plugin[1] = $_tpl_file;
+ $_plugin[2] = $_tpl_line;
+ $_plugin[3] = true;
+ if (!isset($_plugin[4])) $_plugin[4] = true; /* cacheable */
+ }
+ }
+ continue;
+ } else if ($_type == 'insert') {
+ /*
+ * For backwards compatibility, we check for insert functions in
+ * the symbol table before trying to load them as a plugin.
+ */
+ $_plugin_func = 'insert_' . $_name;
+ if (function_exists($_plugin_func)) {
+ $_plugin = array($_plugin_func, $_tpl_file, $_tpl_line, true, false);
+ continue;
+ }
+ }
+
+ $_plugin_file = $smarty->_get_plugin_filepath($_type, $_name);
+
+ if (! $_found = ($_plugin_file != false)) {
+ $_message = "could not load plugin file '$_type.$_name.php'\n";
+ }
+
+ /*
+ * If plugin file is found, it -must- provide the properly named
+ * plugin function. In case it doesn't, simply output the error and
+ * do not fall back on any other method.
+ */
+ if ($_found) {
+ include_once $_plugin_file;
+
+ $_plugin_func = 'smarty_' . $_type . '_' . $_name;
+ if (!function_exists($_plugin_func)) {
+ $smarty->_trigger_fatal_error("[plugin] function $_plugin_func() not found in $_plugin_file", $_tpl_file, $_tpl_line, __FILE__, __LINE__);
+ continue;
+ }
+ }
+ /*
+ * In case of insert plugins, their code may be loaded later via
+ * 'script' attribute.
+ */
+ else if ($_type == 'insert' && $_delayed_loading) {
+ $_plugin_func = 'smarty_' . $_type . '_' . $_name;
+ $_found = true;
+ }
+
+ /*
+ * Plugin specific processing and error checking.
+ */
+ if (!$_found) {
+ if ($_type == 'modifier') {
+ /*
+ * In case modifier falls back on using PHP functions
+ * directly, we only allow those specified in the security
+ * context.
+ */
+ if ($smarty->security && !in_array($_name, $smarty->security_settings['MODIFIER_FUNCS'])) {
+ $_message = "(secure mode) modifier '$_name' is not allowed";
+ } else {
+ if (!function_exists($_name)) {
+ $_message = "modifier '$_name' is not implemented";
+ } else {
+ $_plugin_func = $_name;
+ $_found = true;
+ }
+ }
+ } else if ($_type == 'function') {
+ /*
+ * This is a catch-all situation.
+ */
+ $_message = "unknown tag - '$_name'";
+ }
+ }
+
+ if ($_found) {
+ $smarty->_plugins[$_type][$_name] = array($_plugin_func, $_tpl_file, $_tpl_line, true, true);
+ } else {
+ // output error
+ $smarty->_trigger_fatal_error('[plugin] ' . $_message, $_tpl_file, $_tpl_line, __FILE__, __LINE__);
+ }
+ }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.load_resource_plugin.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.load_resource_plugin.php
new file mode 100644
index 00000000..8a084f1b
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.load_resource_plugin.php
@@ -0,0 +1,74 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * load a resource plugin
+ *
+ * @param string $type
+ */
+
+// $type
+
+function smarty_core_load_resource_plugin($params, &$smarty)
+{
+ /*
+ * Resource plugins are not quite like the other ones, so they are
+ * handled differently. The first element of plugin info is the array of
+ * functions provided by the plugin, the second one indicates whether
+ * all of them exist or not.
+ */
+
+ $_plugin = &$smarty->_plugins['resource'][$params['type']];
+ if (isset($_plugin)) {
+ if (!$_plugin[1] && count($_plugin[0])) {
+ $_plugin[1] = true;
+ foreach ($_plugin[0] as $_plugin_func) {
+ if (!is_callable($_plugin_func)) {
+ $_plugin[1] = false;
+ break;
+ }
+ }
+ }
+
+ if (!$_plugin[1]) {
+ $smarty->_trigger_fatal_error("[plugin] resource '" . $params['type'] . "' is not implemented", null, null, __FILE__, __LINE__);
+ }
+
+ return;
+ }
+
+ $_plugin_file = $smarty->_get_plugin_filepath('resource', $params['type']);
+ $_found = ($_plugin_file != false);
+
+ if ($_found) { /*
+ * If the plugin file is found, it -must- provide the properly named
+ * plugin functions.
+ */
+ include_once($_plugin_file);
+
+ /*
+ * Locate functions that we require the plugin to provide.
+ */
+ $_resource_ops = array('source', 'timestamp', 'secure', 'trusted');
+ $_resource_funcs = array();
+ foreach ($_resource_ops as $_op) {
+ $_plugin_func = 'smarty_resource_' . $params['type'] . '_' . $_op;
+ if (!function_exists($_plugin_func)) {
+ $smarty->_trigger_fatal_error("[plugin] function $_plugin_func() not found in $_plugin_file", null, null, __FILE__, __LINE__);
+ return;
+ } else {
+ $_resource_funcs[] = $_plugin_func;
+ }
+ }
+
+ $smarty->_plugins['resource'][$params['type']] = array($_resource_funcs, true);
+ }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.process_cached_inserts.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.process_cached_inserts.php
new file mode 100644
index 00000000..42c32698
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.process_cached_inserts.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Replace cached inserts with the actual results
+ *
+ * @param string $results
+ * @return string
+ */
+function smarty_core_process_cached_inserts($params, &$smarty)
+{
+ preg_match_all('!'.$smarty->_smarty_md5.'{insert_cache (.*)}'.$smarty->_smarty_md5.'!Uis',
+ $params['results'], $match);
+ list($cached_inserts, $insert_args) = $match;
+
+ for ($i = 0, $for_max = count($cached_inserts); $i < $for_max; $i++) {
+ if ($smarty->debugging) {
+ $_params = array();
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php');
+ $debug_start_time = smarty_core_get_microtime($_params, $smarty);
+ }
+
+ $args = unserialize($insert_args[$i]);
+ $name = $args['name'];
+
+ if (isset($args['script'])) {
+ $_params = array('resource_name' => $smarty->_dequote($args['script']));
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_php_resource.php');
+ if(!smarty_core_get_php_resource($_params, $smarty)) {
+ return false;
+ }
+ $resource_type = $_params['resource_type'];
+ $php_resource = $_params['php_resource'];
+
+
+ if ($resource_type == 'file') {
+ $smarty->_include($php_resource, true);
+ } else {
+ $smarty->_eval($php_resource);
+ }
+ }
+
+ $function_name = $smarty->_plugins['insert'][$name][0];
+ if (empty($args['assign'])) {
+ $replace = $function_name($args, $smarty);
+ } else {
+ $smarty->assign($args['assign'], $function_name($args, $smarty));
+ $replace = '';
+ }
+
+ $params['results'] = str_replace($cached_inserts[$i], $replace, $params['results']);
+ if ($smarty->debugging) {
+ $_params = array();
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php');
+ $smarty->_smarty_debug_info[] = array('type' => 'insert',
+ 'filename' => 'insert_'.$name,
+ 'depth' => $smarty->_inclusion_depth,
+ 'exec_time' => smarty_core_get_microtime($_params, $smarty) - $debug_start_time);
+ }
+ }
+
+ return $params['results'];
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.process_compiled_include.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.process_compiled_include.php
new file mode 100644
index 00000000..52ecc642
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.process_compiled_include.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Replace nocache-tags by results of the corresponding non-cacheable
+ * functions and return it
+ *
+ * @param string $compiled_tpl
+ * @param string $cached_source
+ * @return string
+ */
+
+function smarty_core_process_compiled_include($params, &$smarty)
+{
+ $_cache_including = $smarty->_cache_including;
+ $smarty->_cache_including = true;
+
+ $_return = $params['results'];
+ foreach ($smarty->_cache_serials as $_include_file_path=>$_cache_serial) {
+ $_return = preg_replace_callback('!(\{nocache\:('.$_cache_serial.')#(\d+)\})!s',
+ array(&$smarty, '_process_compiled_include_callback'),
+ $_return);
+ }
+ $smarty->_cache_including = $_cache_including;
+ return $_return;
+}
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.read_cache_file.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.read_cache_file.php
new file mode 100644
index 00000000..60ec924e
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.read_cache_file.php
@@ -0,0 +1,111 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * read a cache file, determine if it needs to be
+ * regenerated or not
+ *
+ * @param string $tpl_file
+ * @param string $cache_id
+ * @param string $compile_id
+ * @param string $results
+ * @return boolean
+ */
+
+// $tpl_file, $cache_id, $compile_id, &$results
+
+function smarty_core_read_cache_file(&$params, &$smarty)
+{
+ static $content_cache = array();
+
+ if ($smarty->force_compile) {
+ // force compile enabled, always regenerate
+ return false;
+ }
+
+ if (isset($content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']])) {
+ list($params['results'], $smarty->_cache_info) = $content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']];
+ return true;
+ }
+
+ if (!empty($smarty->cache_handler_func)) {
+ // use cache_handler function
+ call_user_func_array($smarty->cache_handler_func,
+ array('read', &$smarty, &$params['results'], $params['tpl_file'], $params['cache_id'], $params['compile_id'], null));
+ } else {
+ // use local cache file
+ $_auto_id = $smarty->_get_auto_id($params['cache_id'], $params['compile_id']);
+ $_cache_file = $smarty->_get_auto_filename($smarty->cache_dir, $params['tpl_file'], $_auto_id);
+ $params['results'] = $smarty->_read_file($_cache_file);
+ }
+
+ if (empty($params['results'])) {
+ // nothing to parse (error?), regenerate cache
+ return false;
+ }
+
+ $cache_split = explode("\n", $params['results'], 2);
+ $cache_header = $cache_split[0];
+
+ $_cache_info = unserialize($cache_header);
+
+ if ($smarty->caching == 2 && isset ($_cache_info['expires'])){
+ // caching by expiration time
+ if ($_cache_info['expires'] > -1 && (time() > $_cache_info['expires'])) {
+ // cache expired, regenerate
+ return false;
+ }
+ } else {
+ // caching by lifetime
+ if ($smarty->cache_lifetime > -1 && (time() - $_cache_info['timestamp'] > $smarty->cache_lifetime)) {
+ // cache expired, regenerate
+ return false;
+ }
+ }
+
+ if ($smarty->compile_check) {
+ $_params = array('get_source' => false, 'quiet'=>true);
+ foreach (array_keys($_cache_info['template']) as $_template_dep) {
+ $_params['resource_name'] = $_template_dep;
+ if (!$smarty->_fetch_resource_info($_params) || $_cache_info['timestamp'] < $_params['resource_timestamp']) {
+ // template file has changed, regenerate cache
+ return false;
+ }
+ }
+
+ if (isset($_cache_info['config'])) {
+ $_params = array('resource_base_path' => $smarty->config_dir, 'get_source' => false, 'quiet'=>true);
+ foreach (array_keys($_cache_info['config']) as $_config_dep) {
+ $_params['resource_name'] = $_config_dep;
+ if (!$smarty->_fetch_resource_info($_params) || $_cache_info['timestamp'] < $_params['resource_timestamp']) {
+ // config file has changed, regenerate cache
+ return false;
+ }
+ }
+ }
+ }
+
+ foreach ($_cache_info['cache_serials'] as $_include_file_path=>$_cache_serial) {
+ if (empty($smarty->_cache_serials[$_include_file_path])) {
+ $smarty->_include($_include_file_path, true);
+ }
+
+ if ($smarty->_cache_serials[$_include_file_path] != $_cache_serial) {
+ /* regenerate */
+ return false;
+ }
+ }
+ $params['results'] = $cache_split[1];
+ $content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']] = array($params['results'], $_cache_info);
+
+ $smarty->_cache_info = $_cache_info;
+ return true;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.rm_auto.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.rm_auto.php
new file mode 100644
index 00000000..d3cbfe28
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.rm_auto.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * delete an automagically created file by name and id
+ *
+ * @param string $auto_base
+ * @param string $auto_source
+ * @param string $auto_id
+ * @param integer $exp_time
+ * @return boolean
+ */
+
+// $auto_base, $auto_source = null, $auto_id = null, $exp_time = null
+
+function smarty_core_rm_auto($params, &$smarty)
+{
+ if (!@is_dir($params['auto_base']))
+ return false;
+
+ if(!isset($params['auto_id']) && !isset($params['auto_source'])) {
+ $_params = array(
+ 'dirname' => $params['auto_base'],
+ 'level' => 0,
+ 'exp_time' => $params['exp_time']
+ );
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.rmdir.php');
+ $_res = smarty_core_rmdir($_params, $smarty);
+ } else {
+ $_tname = $smarty->_get_auto_filename($params['auto_base'], $params['auto_source'], $params['auto_id']);
+
+ if(isset($params['auto_source'])) {
+ if (isset($params['extensions'])) {
+ $_res = false;
+ foreach ((array)$params['extensions'] as $_extension)
+ $_res |= $smarty->_unlink($_tname.$_extension, $params['exp_time']);
+ } else {
+ $_res = $smarty->_unlink($_tname, $params['exp_time']);
+ }
+ } elseif ($smarty->use_sub_dirs) {
+ $_params = array(
+ 'dirname' => $_tname,
+ 'level' => 1,
+ 'exp_time' => $params['exp_time']
+ );
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.rmdir.php');
+ $_res = smarty_core_rmdir($_params, $smarty);
+ } else {
+ // remove matching file names
+ $_handle = opendir($params['auto_base']);
+ $_res = true;
+ while (false !== ($_filename = readdir($_handle))) {
+ if($_filename == '.' || $_filename == '..') {
+ continue;
+ } elseif (substr($params['auto_base'] . DIRECTORY_SEPARATOR . $_filename, 0, strlen($_tname)) == $_tname) {
+ $_res &= (bool)$smarty->_unlink($params['auto_base'] . DIRECTORY_SEPARATOR . $_filename, $params['exp_time']);
+ }
+ }
+ }
+ }
+
+ return $_res;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.rmdir.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.rmdir.php
new file mode 100644
index 00000000..f149469d
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.rmdir.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * delete a dir recursively (level=0 -> keep root)
+ * WARNING: no tests, it will try to remove what you tell it!
+ *
+ * @param string $dirname
+ * @param integer $level
+ * @param integer $exp_time
+ * @return boolean
+ */
+
+// $dirname, $level = 1, $exp_time = null
+
+function smarty_core_rmdir($params, &$smarty)
+{
+ if(!isset($params['level'])) { $params['level'] = 1; }
+ if(!isset($params['exp_time'])) { $params['exp_time'] = null; }
+
+ if($_handle = @opendir($params['dirname'])) {
+
+ while (false !== ($_entry = readdir($_handle))) {
+ if ($_entry != '.' && $_entry != '..') {
+ if (@is_dir($params['dirname'] . DIRECTORY_SEPARATOR . $_entry)) {
+ $_params = array(
+ 'dirname' => $params['dirname'] . DIRECTORY_SEPARATOR . $_entry,
+ 'level' => $params['level'] + 1,
+ 'exp_time' => $params['exp_time']
+ );
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.rmdir.php');
+ smarty_core_rmdir($_params, $smarty);
+ }
+ else {
+ $smarty->_unlink($params['dirname'] . DIRECTORY_SEPARATOR . $_entry, $params['exp_time']);
+ }
+ }
+ }
+ closedir($_handle);
+ }
+
+ if ($params['level']) {
+ return @rmdir($params['dirname']);
+ }
+ return (bool)$_handle;
+
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.run_insert_handler.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.run_insert_handler.php
new file mode 100644
index 00000000..a40f8b24
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.run_insert_handler.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Handle insert tags
+ *
+ * @param array $args
+ * @return string
+ */
+function smarty_core_run_insert_handler($params, &$smarty)
+{
+
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php');
+ if ($smarty->debugging) {
+ $_params = array();
+ $_debug_start_time = smarty_core_get_microtime($_params, $smarty);
+ }
+
+ if ($smarty->caching) {
+ $_arg_string = serialize($params['args']);
+ $_name = $params['args']['name'];
+ if (!isset($smarty->_cache_info['insert_tags'][$_name])) {
+ $smarty->_cache_info['insert_tags'][$_name] = array('insert',
+ $_name,
+ $smarty->_plugins['insert'][$_name][1],
+ $smarty->_plugins['insert'][$_name][2],
+ !empty($params['args']['script']) ? true : false);
+ }
+ return $smarty->_smarty_md5."{insert_cache $_arg_string}".$smarty->_smarty_md5;
+ } else {
+ if (isset($params['args']['script'])) {
+ $_params = array('resource_name' => $smarty->_dequote($params['args']['script']));
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_php_resource.php');
+ if(!smarty_core_get_php_resource($_params, $smarty)) {
+ return false;
+ }
+
+ if ($_params['resource_type'] == 'file') {
+ $smarty->_include($_params['php_resource'], true);
+ } else {
+ $smarty->_eval($_params['php_resource']);
+ }
+ unset($params['args']['script']);
+ }
+
+ $_funcname = $smarty->_plugins['insert'][$params['args']['name']][0];
+ $_content = $_funcname($params['args'], $smarty);
+ if ($smarty->debugging) {
+ $_params = array();
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php');
+ $smarty->_smarty_debug_info[] = array('type' => 'insert',
+ 'filename' => 'insert_'.$params['args']['name'],
+ 'depth' => $smarty->_inclusion_depth,
+ 'exec_time' => smarty_core_get_microtime($_params, $smarty) - $_debug_start_time);
+ }
+
+ if (!empty($params['args']["assign"])) {
+ $smarty->assign($params['args']["assign"], $_content);
+ } else {
+ return $_content;
+ }
+ }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.smarty_include_php.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.smarty_include_php.php
new file mode 100644
index 00000000..9efc46ac
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.smarty_include_php.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * called for included php files within templates
+ *
+ * @param string $smarty_file
+ * @param string $smarty_assign variable to assign the included template's
+ * output into
+ * @param boolean $smarty_once uses include_once if this is true
+ * @param array $smarty_include_vars associative array of vars from
+ * {include file="blah" var=$var}
+ */
+
+// $file, $assign, $once, $_smarty_include_vars
+
+function smarty_core_smarty_include_php($params, &$smarty)
+{
+ $_params = array('resource_name' => $params['smarty_file']);
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_php_resource.php');
+ smarty_core_get_php_resource($_params, $smarty);
+ $_smarty_resource_type = $_params['resource_type'];
+ $_smarty_php_resource = $_params['php_resource'];
+
+ if (!empty($params['smarty_assign'])) {
+ ob_start();
+ if ($_smarty_resource_type == 'file') {
+ $smarty->_include($_smarty_php_resource, $params['smarty_once'], $params['smarty_include_vars']);
+ } else {
+ $smarty->_eval($_smarty_php_resource, $params['smarty_include_vars']);
+ }
+ $smarty->assign($params['smarty_assign'], ob_get_contents());
+ ob_end_clean();
+ } else {
+ if ($_smarty_resource_type == 'file') {
+ $smarty->_include($_smarty_php_resource, $params['smarty_once'], $params['smarty_include_vars']);
+ } else {
+ $smarty->_eval($_smarty_php_resource, $params['smarty_include_vars']);
+ }
+ }
+}
+
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.write_cache_file.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.write_cache_file.php
new file mode 100644
index 00000000..47f1b8ec
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.write_cache_file.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Prepend the cache information to the cache file
+ * and write it
+ *
+ * @param string $tpl_file
+ * @param string $cache_id
+ * @param string $compile_id
+ * @param string $results
+ * @return true|null
+ */
+
+ // $tpl_file, $cache_id, $compile_id, $results
+
+function smarty_core_write_cache_file($params, &$smarty)
+{
+
+ // put timestamp in cache header
+ $smarty->_cache_info['timestamp'] = time();
+ if ($smarty->cache_lifetime > -1){
+ // expiration set
+ $smarty->_cache_info['expires'] = $smarty->_cache_info['timestamp'] + $smarty->cache_lifetime;
+ } else {
+ // cache will never expire
+ $smarty->_cache_info['expires'] = -1;
+ }
+
+ // collapse {nocache...}-tags
+ $params['results'] = preg_replace('!((\{nocache\:([0-9a-f]{32})#(\d+)\})'
+ .'.*'
+ .'{/nocache\:\\3#\\4\})!Us'
+ ,'\\2'
+ ,$params['results']);
+ $smarty->_cache_info['cache_serials'] = $smarty->_cache_serials;
+
+ // prepend the cache header info into cache file
+ $params['results'] = serialize($smarty->_cache_info)."\n".$params['results'];
+
+ if (!empty($smarty->cache_handler_func)) {
+ // use cache_handler function
+ call_user_func_array($smarty->cache_handler_func,
+ array('write', &$smarty, &$params['results'], $params['tpl_file'], $params['cache_id'], $params['compile_id'], null));
+ } else {
+ // use local cache file
+
+ if(!@is_writable($smarty->cache_dir)) {
+ // cache_dir not writable, see if it exists
+ if(!@is_dir($smarty->cache_dir)) {
+ $smarty->trigger_error('the $cache_dir \'' . $smarty->cache_dir . '\' does not exist, or is not a directory.', E_USER_ERROR);
+ return false;
+ }
+ $smarty->trigger_error('unable to write to $cache_dir \'' . realpath($smarty->cache_dir) . '\'. Be sure $cache_dir is writable by the web server user.', E_USER_ERROR);
+ return false;
+ }
+
+ $_auto_id = $smarty->_get_auto_id($params['cache_id'], $params['compile_id']);
+ $_cache_file = $smarty->_get_auto_filename($smarty->cache_dir, $params['tpl_file'], $_auto_id);
+ $_params = array('filename' => $_cache_file, 'contents' => $params['results'], 'create_dirs' => true);
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.write_file.php');
+ smarty_core_write_file($_params, $smarty);
+ return true;
+ }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.write_compiled_include.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.write_compiled_include.php
new file mode 100644
index 00000000..4124f355
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.write_compiled_include.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Extract non-cacheable parts out of compiled template and write it
+ *
+ * @param string $compile_path
+ * @param string $template_compiled
+ * @param integer $template_timestamp
+ * @return boolean
+ */
+
+function smarty_core_write_compiled_include($params, &$smarty)
+{
+ $_tag_start = 'if \(\$this->caching\) \{ echo \'\{nocache\:('.$params['cache_serial'].')#(\d+)\}\';\}';
+ $_tag_end = 'if \(\$this->caching\) \{ echo \'\{/nocache\:(\\2)#(\\3)\}\';\}';
+
+ preg_match_all('!('.$_tag_start.'(.*)'.$_tag_end.')!Us',
+ $params['compiled_content'], $_match_source, PREG_SET_ORDER);
+
+ // no nocache-parts found: done
+ if (count($_match_source)==0) return;
+
+ // convert the matched php-code to functions
+ $_include_compiled = "<?php /* funky header here */\n\n";
+
+ $_compile_path = $params['include_file_path'];
+
+ $smarty->_cache_serials[$_compile_path] = $params['cache_serial'];
+ $_include_compiled .= "\$this->_cache_serials['".$_compile_path."'] = '".$params['cache_serial']."';\n\n?>";
+
+ $_include_compiled .= $params['plugins_code'];
+ $_include_compiled .= "<?php";
+ for ($_i = 0, $_for_max = count($_match_source); $_i < $_for_max; $_i++) {
+ $_match =& $_match_source[$_i];
+ $_include_compiled .= "
+function _smarty_tplfunc_$_match[2]_$_match[3](&\$this)
+{
+$_match[4]
+}
+
+";
+ }
+ $_include_compiled .= "\n\n?>\n";
+
+ $_params = array('filename' => $_compile_path,
+ 'contents' => $_include_compiled, 'create_dirs' => true);
+
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.write_file.php');
+ smarty_core_write_file($_params, $smarty);
+ return true;
+}
+
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.write_compiled_resource.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.write_compiled_resource.php
new file mode 100644
index 00000000..cd5cfb56
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.write_compiled_resource.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * write the compiled resource
+ *
+ * @param string $compile_path
+ * @param string $compiled_content
+ * @param integer $resource_timestamp
+ * @return true
+ */
+function smarty_core_write_compiled_resource($params, &$smarty)
+{
+ if(!@is_writable($smarty->compile_dir)) {
+ // compile_dir not writable, see if it exists
+ if(!@is_dir($smarty->compile_dir)) {
+ $smarty->trigger_error('the $compile_dir \'' . $smarty->compile_dir . '\' does not exist, or is not a directory.', E_USER_ERROR);
+ return false;
+ }
+ $smarty->trigger_error('unable to write to $compile_dir \'' . realpath($smarty->compile_dir) . '\'. Be sure $compile_dir is writable by the web server user.', E_USER_ERROR);
+ return false;
+ }
+
+ $_params = array('filename' => $params['compile_path'], 'contents' => $params['compiled_content'], 'create_dirs' => true);
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.write_file.php');
+ smarty_core_write_file($_params, $smarty);
+ touch($params['compile_path'], $params['resource_timestamp']);
+ return true;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.write_file.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.write_file.php
new file mode 100644
index 00000000..534a3828
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/core/core.write_file.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * write out a file to disk
+ *
+ * @param string $filename
+ * @param string $contents
+ * @param boolean $create_dirs
+ * @return boolean
+ */
+function smarty_core_write_file($params, &$smarty)
+{
+ $_dirname = dirname($params['filename']);
+
+ if ($params['create_dirs']) {
+ $_params = array('dir' => $_dirname);
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.create_dir_structure.php');
+ smarty_core_create_dir_structure($_params, $smarty);
+ }
+
+ // write to tmp file, then rename it to avoid
+ // file locking race condition
+ $_tmp_file = $_dirname . DIRECTORY_SEPARATOR . uniqid('');
+
+ if (!($fd = @fopen($_tmp_file, 'w'))) {
+ $smarty->trigger_error("problem writing temporary file '$_tmp_file'");
+ return false;
+ }
+
+ fwrite($fd, $params['contents']);
+ fclose($fd);
+ if(file_exists($params['filename'])) {
+ @unlink($params['filename']);
+ }
+ @rename($_tmp_file, $params['filename']);
+ @chmod($params['filename'], $smarty->_file_perms);
+
+ return true;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/debug.tpl b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/debug.tpl
new file mode 100644
index 00000000..ab717db7
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/debug.tpl
@@ -0,0 +1,64 @@
+{* Smarty *}
+
+{* debug.tpl, last updated version 2.0.1 *}
+
+{assign_debug_info}
+
+{if isset($_smarty_debug_output) and $_smarty_debug_output eq "html"}
+ <table border=0 width=100%>
+ <tr bgcolor=#cccccc><th colspan=2>Smarty Debug Console</th></tr>
+ <tr bgcolor=#cccccc><td colspan=2><b>included templates & config files (load time in seconds):</b></td></tr>
+ {section name=templates loop=$_debug_tpls}
+ <tr bgcolor={if %templates.index% is even}#eeeeee{else}#fafafa{/if}><td colspan=2><tt>{section name=indent loop=$_debug_tpls[templates].depth}&nbsp;&nbsp;&nbsp;{/section}<font color={if $_debug_tpls[templates].type eq "template"}brown{elseif $_debug_tpls[templates].type eq "insert"}black{else}green{/if}>{$_debug_tpls[templates].filename|escape:html}</font>{if isset($_debug_tpls[templates].exec_time)} <font size=-1><i>({$_debug_tpls[templates].exec_time|string_format:"%.5f"}){if %templates.index% eq 0} (total){/if}</i></font>{/if}</tt></td></tr>
+ {sectionelse}
+ <tr bgcolor=#eeeeee><td colspan=2><tt><i>no templates included</i></tt></td></tr>
+ {/section}
+ <tr bgcolor=#cccccc><td colspan=2><b>assigned template variables:</b></td></tr>
+ {section name=vars loop=$_debug_keys}
+ <tr bgcolor={if %vars.index% is even}#eeeeee{else}#fafafa{/if}><td valign=top><tt><font color=blue>{ldelim}${$_debug_keys[vars]}{rdelim}</font></tt></td><td nowrap><tt><font color=green>{$_debug_vals[vars]|@debug_print_var}</font></tt></td></tr>
+ {sectionelse}
+ <tr bgcolor=#eeeeee><td colspan=2><tt><i>no template variables assigned</i></tt></td></tr>
+ {/section}
+ <tr bgcolor=#cccccc><td colspan=2><b>assigned config file variables (outer template scope):</b></td></tr>
+ {section name=config_vars loop=$_debug_config_keys}
+ <tr bgcolor={if %config_vars.index% is even}#eeeeee{else}#fafafa{/if}><td valign=top><tt><font color=maroon>{ldelim}#{$_debug_config_keys[config_vars]}#{rdelim}</font></tt></td><td><tt><font color=green>{$_debug_config_vals[config_vars]|@debug_print_var}</font></tt></td></tr>
+ {sectionelse}
+ <tr bgcolor=#eeeeee><td colspan=2><tt><i>no config vars assigned</i></tt></td></tr>
+ {/section}
+ </table>
+</BODY></HTML>
+{else}
+<SCRIPT language=javascript>
+ if( self.name == '' ) {ldelim}
+ var title = 'Console';
+ {rdelim}
+ else {ldelim}
+ var title = 'Console_' + self.name;
+ {rdelim}
+ _smarty_console = window.open("",title.value,"width=680,height=600,resizable,scrollbars=yes");
+ _smarty_console.document.write("<HTML><TITLE>Smarty Debug Console_"+self.name+"</TITLE><BODY bgcolor=#ffffff>");
+ _smarty_console.document.write("<table border=0 width=100%>");
+ _smarty_console.document.write("<tr bgcolor=#cccccc><th colspan=2>Smarty Debug Console</th></tr>");
+ _smarty_console.document.write("<tr bgcolor=#cccccc><td colspan=2><b>included templates & config files (load time in seconds):</b></td></tr>");
+ {section name=templates loop=$_debug_tpls}
+ _smarty_console.document.write("<tr bgcolor={if %templates.index% is even}#eeeeee{else}#fafafa{/if}><td colspan=2><tt>{section name=indent loop=$_debug_tpls[templates].depth}&nbsp;&nbsp;&nbsp;{/section}<font color={if $_debug_tpls[templates].type eq "template"}brown{elseif $_debug_tpls[templates].type eq "insert"}black{else}green{/if}>{$_debug_tpls[templates].filename|escape:html|escape:javascript}</font>{if isset($_debug_tpls[templates].exec_time)} <font size=-1><i>({$_debug_tpls[templates].exec_time|string_format:"%.5f"}){if %templates.index% eq 0} (total){/if}</i></font>{/if}</tt></td></tr>");
+ {sectionelse}
+ _smarty_console.document.write("<tr bgcolor=#eeeeee><td colspan=2><tt><i>no templates included</i></tt></td></tr>");
+ {/section}
+ _smarty_console.document.write("<tr bgcolor=#cccccc><td colspan=2><b>assigned template variables:</b></td></tr>");
+ {section name=vars loop=$_debug_keys}
+ _smarty_console.document.write("<tr bgcolor={if %vars.index% is even}#eeeeee{else}#fafafa{/if}><td valign=top><tt><font color=blue>{ldelim}${$_debug_keys[vars]}{rdelim}</font></tt></td><td nowrap><tt><font color=green>{$_debug_vals[vars]|@debug_print_var|escape:javascript}</font></tt></td></tr>");
+ {sectionelse}
+ _smarty_console.document.write("<tr bgcolor=#eeeeee><td colspan=2><tt><i>no template variables assigned</i></tt></td></tr>");
+ {/section}
+ _smarty_console.document.write("<tr bgcolor=#cccccc><td colspan=2><b>assigned config file variables (outer template scope):</b></td></tr>");
+ {section name=config_vars loop=$_debug_config_keys}
+ _smarty_console.document.write("<tr bgcolor={if %config_vars.index% is even}#eeeeee{else}#fafafa{/if}><td valign=top><tt><font color=maroon>{ldelim}#{$_debug_config_keys[config_vars]}#{rdelim}</font></tt></td><td><tt><font color=green>{$_debug_config_vals[config_vars]|@debug_print_var|escape:javascript}</font></tt></td></tr>");
+ {sectionelse}
+ _smarty_console.document.write("<tr bgcolor=#eeeeee><td colspan=2><tt><i>no config vars assigned</i></tt></td></tr>");
+ {/section}
+ _smarty_console.document.write("</table>");
+ _smarty_console.document.write("</BODY></HTML>");
+ _smarty_console.document.close();
+</SCRIPT>
+{/if}
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/block.strip.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/block.strip.php
new file mode 100644
index 00000000..a25df360
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/block.strip.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {strip}{/strip} block plugin
+ *
+ * Type: block function<br>
+ * Name: strip<br>
+ * Purpose: strip unwanted white space from text<br>
+ * @link http://smarty.php.net/manual/en/language.function.strip.php {strip}
+ * (Smarty online manual)
+ * @param array unused, no parameters for this block
+ * @param string content of {strip}{/strip} tags
+ * @param Smarty clever method emulation
+ * @return string $content stripped of whitespace
+ */
+function smarty_block_strip($params, $content, &$this)
+{
+ /* Reformat data between 'strip' and '/strip' tags, removing spaces, tabs and newlines. */
+ $_strip_search = array(
+ "![\t ]+$|^[\t ]+!m", // remove leading/trailing space chars
+ '%[\r\n]+%m'); // remove CRs and newlines
+ $_strip_replace = array(
+ '',
+ '');
+ return preg_replace($_strip_search, $_strip_replace, $content);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/block.textformat.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/block.textformat.php
new file mode 100644
index 00000000..f3462c21
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/block.textformat.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {textformat}{/textformat} block plugin
+ *
+ * Type: block function<br>
+ * Name: textformat<br>
+ * Purpose: format text a certain way with preset styles
+ * or custom wrap/indent settings<br>
+ * @link http://smarty.php.net/manual/en/language.function.textformat.php {textformat}
+ * (Smarty online manual)
+ * @param array
+ * <pre>
+ * Params: style: string (email)
+ * indent: integer (0)
+ * wrap: integer (80)
+ * wrap_char string ("\n")
+ * indent_char: string (" ")
+ * wrap_boundary: boolean (true)
+ * </pre>
+ * @param string contents of the block
+ * @param Smarty clever simulation of a method
+ * @return string string $content re-formatted
+ */
+function smarty_block_textformat($params, $content, &$smarty)
+{
+ $style = null;
+ $indent = 0;
+ $indent_first = 0;
+ $indent_char = ' ';
+ $wrap = 80;
+ $wrap_char = "\n";
+ $wrap_cut = false;
+ $assign = null;
+
+ if($content == null) {
+ return true;
+ }
+
+ extract($params);
+
+ if($style == 'email') {
+ $wrap = 72;
+ }
+
+ // split into paragraphs
+ $paragraphs = preg_split('![\r\n][\r\n]!',$content);
+ $output = '';
+
+ foreach($paragraphs as $paragraph) {
+ if($paragraph == '') {
+ continue;
+ }
+ // convert mult. spaces & special chars to single space
+ $paragraph = preg_replace(array('!\s+!','!(^\s+)|(\s+$)!'),array(' ',''),$paragraph);
+ // indent first line
+ if($indent_first > 0) {
+ $paragraph = str_repeat($indent_char,$indent_first) . $paragraph;
+ }
+ // wordwrap sentences
+ $paragraph = wordwrap($paragraph, $wrap - $indent, $wrap_char, $wrap_cut);
+ // indent lines
+ if($indent > 0) {
+ $paragraph = preg_replace('!^!m',str_repeat($indent_char,$indent),$paragraph);
+ }
+ $output .= $paragraph . $wrap_char . $wrap_char;
+ }
+
+ if($assign != null) {
+ $smarty->assign($assign,$output);
+ } else {
+ return $output;
+ }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.assign.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.assign.php
new file mode 100644
index 00000000..c04be8bc
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.assign.php
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {assign} function plugin
+ *
+ * Type: function<br>
+ * Name: assign<br>
+ * Purpose: assign a value to a template variable
+ * @link http://smarty.php.net/manual/en/language.custom.functions.php#LANGUAGE.FUNCTION.ASSIGN {assign}
+ * (Smarty online manual)
+ * @param array Format: array('var' => variable name, 'value' => value to assign)
+ * @param Smarty
+ */
+function smarty_function_assign($params, &$smarty)
+{
+ extract($params);
+
+ if (empty($var)) {
+ $smarty->trigger_error("assign: missing 'var' parameter");
+ return;
+ }
+
+ if (!in_array('value', array_keys($params))) {
+ $smarty->trigger_error("assign: missing 'value' parameter");
+ return;
+ }
+
+ $smarty->assign($var, $value);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.assign_debug_info.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.assign_debug_info.php
new file mode 100644
index 00000000..59ddaa16
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.assign_debug_info.php
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {assign_debug_info} function plugin
+ *
+ * Type: function<br>
+ * Name: assign_debug_info<br>
+ * Purpose: assign debug info to the template<br>
+ * @param array unused in this plugin, this plugin uses {@link Smarty::$_config},
+ * {@link Smarty::$_tpl_vars} and {@link Smarty::$_smarty_debug_info}
+ * @param Smarty
+ */
+function smarty_function_assign_debug_info($params, &$smarty)
+{
+ $assigned_vars = $smarty->_tpl_vars;
+ ksort($assigned_vars);
+ if (@is_array($smarty->_config[0])) {
+ $config_vars = $smarty->_config[0];
+ ksort($config_vars);
+ $smarty->assign("_debug_config_keys", array_keys($config_vars));
+ $smarty->assign("_debug_config_vals", array_values($config_vars));
+ }
+
+ $included_templates = $smarty->_smarty_debug_info;
+
+ $smarty->assign("_debug_keys", array_keys($assigned_vars));
+ $smarty->assign("_debug_vals", array_values($assigned_vars));
+
+ $smarty->assign("_debug_tpls", $included_templates);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.config_load.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.config_load.php
new file mode 100644
index 00000000..d9d65b95
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.config_load.php
@@ -0,0 +1,130 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {config_load} function plugin
+ *
+ * Type: function<br>
+ * Name: config_load<br>
+ * Purpose: load config file vars
+ * @link http://smarty.php.net/manual/en/language.function.config.load.php {config_load}
+ * (Smarty online manual)
+ * @param array Format:
+ * <pre>
+ * array('file' => required config file name,
+ * 'section' => optional config file section to load
+ * 'scope' => local/parent/global
+ * 'global' => overrides scope, setting to parent if true)
+ * </pre>
+ * @param Smarty
+ */
+function smarty_function_config_load($params, &$smarty)
+{
+ if ($smarty->debugging) {
+ $_params = array();
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php');
+ $_debug_start_time = smarty_core_get_microtime($_params, $smarty);
+ }
+
+ $_file = isset($params['file']) ? $smarty->_dequote($params['file']) : null;
+ $_section = isset($params['section']) ? $smarty->_dequote($params['section']) : null;
+ $_scope = isset($params['scope']) ? $smarty->_dequote($params['scope']) : 'global';
+ $_global = isset($params['global']) ? $smarty->_dequote($params['global']) : false;
+
+ if (!isset($_file) || strlen($_file) == 0) {
+ $smarty->_syntax_error("missing 'file' attribute in config_load tag", E_USER_ERROR, __FILE__, __LINE__);
+ }
+
+ if (isset($_scope)) {
+ if ($_scope != 'local' &&
+ $_scope != 'parent' &&
+ $_scope != 'global') {
+ $smarty->_syntax_error("invalid 'scope' attribute value", E_USER_ERROR, __FILE__, __LINE__);
+ }
+ } else {
+ if ($_global) {
+ $_scope = 'parent';
+ } else {
+ $_scope = 'local';
+ }
+ }
+
+ if(@is_dir($smarty->config_dir)) {
+ $_config_dir = $smarty->config_dir;
+ } else {
+ // config_dir not found, try include_path
+ $_params = array('file_path' => $smarty->config_dir);
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_include_path.php');
+ smarty_core_get_include_path($_params, $smarty);
+ $_config_dir = $_params['new_file_path'];
+ }
+
+ $_file_path = $_config_dir . DIRECTORY_SEPARATOR . $_file;
+ if (isset($_section))
+ $_compile_file = $smarty->_get_compile_path($_file_path.'|'.$_section);
+ else
+ $_compile_file = $smarty->_get_compile_path($_file_path);
+
+ if($smarty->force_compile
+ || !file_exists($_compile_file)
+ || ($smarty->compile_check
+ && !$smarty->_is_compiled($_file_path, $_compile_file))) {
+ // compile config file
+ if(!is_object($smarty->_conf_obj)) {
+ require_once SMARTY_DIR . $smarty->config_class . '.class.php';
+ $smarty->_conf_obj = new $smarty->config_class($_config_dir);
+ $smarty->_conf_obj->overwrite = $smarty->config_overwrite;
+ $smarty->_conf_obj->booleanize = $smarty->config_booleanize;
+ $smarty->_conf_obj->read_hidden = $smarty->config_read_hidden;
+ $smarty->_conf_obj->fix_newlines = $smarty->config_fix_newlines;
+ $smarty->_conf_obj->set_path = $_config_dir;
+ }
+ $_config_vars = array_merge($smarty->_conf_obj->get($_file),
+ $smarty->_conf_obj->get($_file, $_section));
+ if(function_exists('var_export')) {
+ $_output = '<?php $_config_vars = ' . var_export($_config_vars, true) . '; ?>';
+ } else {
+ $_output = '<?php $_config_vars = unserialize(\'' . strtr(serialize($_config_vars),array('\''=>'\\\'', '\\'=>'\\\\')) . '\'); ?>';
+ }
+ $_params = (array('compile_path' => $_compile_file, 'compiled_content' => $_output, 'resource_timestamp' => filemtime($_file_path)));
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.write_compiled_resource.php');
+ smarty_core_write_compiled_resource($_params, $smarty);
+ } else {
+ include($_compile_file);
+ }
+
+ if ($smarty->caching) {
+ $smarty->_cache_info['config'][$_file] = true;
+ }
+
+ $smarty->_config[0]['vars'] = @array_merge($smarty->_config[0]['vars'], $_config_vars);
+ $smarty->_config[0]['files'][$_file] = true;
+
+ if ($_scope == 'parent') {
+ $smarty->_config[1]['vars'] = @array_merge($smarty->_config[1]['vars'], $_config_vars);
+ $smarty->_config[1]['files'][$_file] = true;
+ } else if ($_scope == 'global') {
+ for ($i = 1, $for_max = count($smarty->_config); $i < $for_max; $i++) {
+ $smarty->_config[$i]['vars'] = @array_merge($smarty->_config[$i]['vars'], $_config_vars);
+ $smarty->_config[$i]['files'][$_file] = true;
+ }
+ }
+
+ if ($smarty->debugging) {
+ $_params = array();
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.get_microtime.php');
+ $smarty->_smarty_debug_info[] = array('type' => 'config',
+ 'filename' => $_file.' ['.$_section.'] '.$_scope,
+ 'depth' => $smarty->_inclusion_depth,
+ 'exec_time' => smarty_core_get_microtime($_params, $smarty) - $_debug_start_time);
+ }
+
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.counter.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.counter.php
new file mode 100644
index 00000000..8d17d2bb
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.counter.php
@@ -0,0 +1,88 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {counter} function plugin
+ *
+ * Type: function<br>
+ * Name: counter<br>
+ * Purpose: print out a counter value
+ * @link http://smarty.php.net/manual/en/language.function.counter.php {counter}
+ * (Smarty online manual)
+ * @param array parameters
+ * @param Smarty
+ * @return string|null
+ */
+function smarty_function_counter($params, &$smarty)
+{
+ static $counters = array();
+
+ extract($params);
+
+ if (!isset($name)) {
+ if(isset($id)) {
+ $name = $id;
+ } else {
+ $name = "default";
+ }
+ }
+
+ if (!isset($counters[$name])) {
+ $counters[$name] = array(
+ 'start'=>1,
+ 'skip'=>1,
+ 'direction'=>'up',
+ 'count'=>1
+ );
+ }
+ $counter =& $counters[$name];
+
+ if (isset($start)) {
+ $counter['start'] = $counter['count'] = $start;
+ }
+
+ if (!empty($assign)) {
+ $counter['assign'] = $assign;
+ }
+
+ if (isset($counter['assign'])) {
+ $smarty->assign($counter['assign'], $counter['count']);
+ }
+
+ if (isset($print)) {
+ $print = (bool)$print;
+ } else {
+ $print = empty($counter['assign']);
+ }
+
+ if ($print) {
+ $retval = $counter['count'];
+ } else {
+ $retval = null;
+ }
+
+ if (isset($skip)) {
+ $counter['skip'] = $skip;
+ }
+
+ if (isset($direction)) {
+ $counter['direction'] = $direction;
+ }
+
+ if ($counter['direction'] == "down")
+ $counter['count'] -= $counter['skip'];
+ else
+ $counter['count'] += $counter['skip'];
+
+ return $retval;
+
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.cycle.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.cycle.php
new file mode 100644
index 00000000..c2e899d0
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.cycle.php
@@ -0,0 +1,119 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {cycle} function plugin
+ *
+ * Type: function<br>
+ * Name: cycle<br>
+ * Date: May 3, 2002<br>
+ * Purpose: cycle through given values<br>
+ * Input:
+ * - name = name of cycle (optional)
+ * - values = comma separated list of values to cycle,
+ * or an array of values to cycle
+ * (this can be left out for subsequent calls)
+ * - reset = boolean - resets given var to true
+ * - print = boolean - print var or not. default is true
+ * - advance = boolean - whether or not to advance the cycle
+ * - delimiter = the value delimiter, default is ","
+ * - assign = boolean, assigns to template var instead of
+ * printed.
+ *
+ * Examples:<br>
+ * <pre>
+ * {cycle values="#eeeeee,#d0d0d0d"}
+ * {cycle name=row values="one,two,three" reset=true}
+ * {cycle name=row}
+ * </pre>
+ * @link http://smarty.php.net/manual/en/language.function.cycle.php {cycle}
+ * (Smarty online manual)
+ * @author Monte Ohrt <monte@ispi.net>
+ * @author credit to Mark Priatel <mpriatel@rogers.com>
+ * @author credit to Gerard <gerard@interfold.com>
+ * @author credit to Jason Sweat <jsweat_php@yahoo.com>
+ * @version 1.3
+ * @param array
+ * @param Smarty
+ * @return string|null
+ */
+function smarty_function_cycle($params, &$smarty)
+{
+ static $cycle_vars;
+
+ extract($params);
+
+ if (empty($name)) {
+ $name = 'default';
+ }
+
+ if (!isset($print)) {
+ $print = true;
+ }
+
+ if (!isset($advance)) {
+ $advance = true;
+ }
+
+ if (!isset($reset)) {
+ $reset = false;
+ }
+
+ if (!in_array('values', array_keys($params))) {
+ if(!isset($cycle_vars[$name]['values'])) {
+ $smarty->trigger_error("cycle: missing 'values' parameter");
+ return;
+ }
+ } else {
+ if(isset($cycle_vars[$name]['values'])
+ && $cycle_vars[$name]['values'] != $values ) {
+ $cycle_vars[$name]['index'] = 0;
+ }
+ $cycle_vars[$name]['values'] = $values;
+ }
+
+ if (isset($delimiter)) {
+ $cycle_vars[$name]['delimiter'] = $delimiter;
+ } elseif (!isset($cycle_vars[$name]['delimiter'])) {
+ $cycle_vars[$name]['delimiter'] = ',';
+ }
+
+ if(!is_array($cycle_vars[$name]['values'])) {
+ $cycle_array = explode($cycle_vars[$name]['delimiter'],$cycle_vars[$name]['values']);
+ } else {
+ $cycle_array = $cycle_vars[$name]['values'];
+ }
+
+ if(!isset($cycle_vars[$name]['index']) || $reset ) {
+ $cycle_vars[$name]['index'] = 0;
+ }
+
+ if (isset($assign)) {
+ $print = false;
+ $smarty->assign($assign, $cycle_array[$cycle_vars[$name]['index']]);
+ }
+
+ if($print) {
+ $retval = $cycle_array[$cycle_vars[$name]['index']];
+ } else {
+ $retval = null;
+ }
+
+ if($advance) {
+ if ( $cycle_vars[$name]['index'] >= count($cycle_array) -1 ) {
+ $cycle_vars[$name]['index'] = 0;
+ } else {
+ $cycle_vars[$name]['index']++;
+ }
+ }
+
+ return $retval;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.debug.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.debug.php
new file mode 100644
index 00000000..5fe02f30
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.debug.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {debug} function plugin
+ *
+ * Type: function<br>
+ * Name: debug<br>
+ * Date: July 1, 2002<br>
+ * Purpose: popup debug window
+ * @link http://smarty.php.net/manual/en/language.function.debug.php {debug}
+ * (Smarty online manual)
+ * @author Monte Ohrt <monte@ispi.net>
+ * @version 1.0
+ * @param array
+ * @param Smarty
+ * @return string output from {@link Smarty::_generate_debug_output()}
+ */
+function smarty_function_debug($params, &$smarty)
+{
+ if($params['output']) {
+ $smarty->assign('_smarty_debug_output',$params['output']);
+ }
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.display_debug_console.php');
+ return smarty_core_display_debug_console(null, $smarty);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.eval.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.eval.php
new file mode 100644
index 00000000..e6943876
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.eval.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {eval} function plugin
+ *
+ * Type: function<br>
+ * Name: eval<br>
+ * Purpose: evaluate a template variable as a template<br>
+ * @link http://smarty.php.net/manual/en/language.function.eval.php {eval}
+ * (Smarty online manual)
+ * @param array
+ * @param Smarty
+ */
+function smarty_function_eval($params, &$smarty)
+{
+
+ if (!isset($params['var'])) {
+ $smarty->trigger_error("eval: missing 'var' parameter");
+ return;
+ }
+
+ if($params['var'] == '') {
+ return;
+ }
+
+ $smarty->_compile_source('evaluated template', $params['var'], $_var_compiled);
+
+ ob_start();
+ $smarty->_eval('?>' . $_var_compiled);
+ $_contents = ob_get_contents();
+ ob_end_clean();
+
+ if (!empty($params['assign'])) {
+ $smarty->assign($params['assign'], $_contents);
+ } else {
+ return $_contents;
+ }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.fetch.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.fetch.php
new file mode 100644
index 00000000..082c3483
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.fetch.php
@@ -0,0 +1,217 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {fetch} plugin
+ *
+ * Type: function<br>
+ * Name: fetch<br>
+ * Purpose: fetch file, web or ftp data and display results
+ * @link http://smarty.php.net/manual/en/language.function.fetch.php {fetch}
+ * (Smarty online manual)
+ * @param array
+ * @param Smarty
+ * @return string|null if the assign parameter is passed, Smarty assigns the
+ * result to a template variable
+ */
+function smarty_function_fetch($params, &$smarty)
+{
+ if (empty($params['file'])) {
+ $smarty->_trigger_fatal_error("[plugin] parameter 'file' cannot be empty");
+ return;
+ }
+
+ if ($smarty->security && !preg_match('!^(http|ftp)://!i', $params['file'])) {
+ $_params = array('resource_type' => 'file', 'resource_name' => $params['file']);
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.is_secure.php');
+ if(!smarty_core_is_secure($_params, $smarty)) {
+ $smarty->_trigger_fatal_error('[plugin] (secure mode) fetch \'' . $params['file'] . '\' is not allowed');
+ return;
+ }
+
+ // fetch the file
+ if($fp = @fopen($params['file'],'r')) {
+ while(!feof($fp)) {
+ $content .= fgets ($fp,4096);
+ }
+ fclose($fp);
+ } else {
+ $smarty->_trigger_fatal_error('[plugin] fetch cannot read file \'' . $params['file'] . '\'');
+ return;
+ }
+ } else {
+ // not a local file
+ if(preg_match('!^http://!i',$params['file'])) {
+ // http fetch
+ if($uri_parts = parse_url($params['file'])) {
+ // set defaults
+ $host = $server_name = $uri_parts['host'];
+ $timeout = 30;
+ $accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*";
+ $agent = "Smarty Template Engine ".$smarty->_version;
+ $referer = "";
+ $uri = !empty($uri_parts['path']) ? $uri_parts['path'] : '/';
+ $uri .= !empty($uri_parts['query']) ? '?' . $uri_parts['query'] : '';
+ $_is_proxy = false;
+ if(empty($uri_parts['port'])) {
+ $port = 80;
+ } else {
+ $port = $uri_parts['port'];
+ }
+ if(empty($uri_parts['user'])) {
+ $user = '';
+ }
+ // loop through parameters, setup headers
+ foreach($params as $param_key => $param_value) {
+ switch($param_key) {
+ case "file":
+ case "assign":
+ case "assign_headers":
+ break;
+ case "user":
+ if(!empty($param_value)) {
+ $user = $param_value;
+ }
+ break;
+ case "pass":
+ if(!empty($param_value)) {
+ $pass = $param_value;
+ }
+ break;
+ case "accept":
+ if(!empty($param_value)) {
+ $accept = $param_value;
+ }
+ break;
+ case "header":
+ if(!empty($param_value)) {
+ if(!preg_match('![\w\d-]+: .+!',$param_value)) {
+ $smarty->_trigger_fatal_error("[plugin] invalid header format '".$param_value."'");
+ return;
+ } else {
+ $extra_headers[] = $param_value;
+ }
+ }
+ break;
+ case "proxy_host":
+ if(!empty($param_value)) {
+ $proxy_host = $param_value;
+ }
+ break;
+ case "proxy_port":
+ if(!preg_match('!\D!', $param_value)) {
+ $proxy_port = (int) $param_value;
+ } else {
+ $smarty->_trigger_fatal_error("[plugin] invalid value for attribute '".$param_key."'");
+ return;
+ }
+ break;
+ case "agent":
+ if(!empty($param_value)) {
+ $agent = $param_value;
+ }
+ break;
+ case "referer":
+ if(!empty($param_value)) {
+ $referer = $param_value;
+ }
+ break;
+ case "timeout":
+ if(!preg_match('!\D!', $param_value)) {
+ $timeout = (int) $param_value;
+ } else {
+ $smarty->_trigger_fatal_error("[plugin] invalid value for attribute '".$param_key."'");
+ return;
+ }
+ break;
+ default:
+ $smarty->_trigger_fatal_error("[plugin] unrecognized attribute '".$param_key."'");
+ return;
+ }
+ }
+ if(!empty($proxy_host) && !empty($proxy_port)) {
+ $_is_proxy = true;
+ $fp = fsockopen($proxy_host,$proxy_port,$errno,$errstr,$timeout);
+ } else {
+ $fp = fsockopen($server_name,$port,$errno,$errstr,$timeout);
+ }
+
+ if(!$fp) {
+ $smarty->_trigger_fatal_error("[plugin] unable to fetch: $errstr ($errno)");
+ return;
+ } else {
+ if($_is_proxy) {
+ fputs($fp, 'GET ' . $params['file'] . " HTTP/1.0\r\n");
+ } else {
+ fputs($fp, "GET $uri HTTP/1.0\r\n");
+ }
+ if(!empty($host)) {
+ fputs($fp, "Host: $host\r\n");
+ }
+ if(!empty($accept)) {
+ fputs($fp, "Accept: $accept\r\n");
+ }
+ if(!empty($agent)) {
+ fputs($fp, "User-Agent: $agent\r\n");
+ }
+ if(!empty($referer)) {
+ fputs($fp, "Referer: $referer\r\n");
+ }
+ if(isset($extra_headers) && is_array($extra_headers)) {
+ foreach($extra_headers as $curr_header) {
+ fputs($fp, $curr_header."\r\n");
+ }
+ }
+ if(!empty($user) && !empty($pass)) {
+ fputs($fp, "Authorization: BASIC ".base64_encode("$user:$pass")."\r\n");
+ }
+
+ $content = '';
+ fputs($fp, "\r\n");
+ while(!feof($fp)) {
+ $content .= fgets($fp,4096);
+ }
+ fclose($fp);
+ $csplit = split("\r\n\r\n",$content,2);
+
+ $content = $csplit[1];
+
+ if(!empty($params['assign_headers'])) {
+ $smarty->assign($params['assign_headers'],split("\r\n",$csplit[0]));
+ }
+ }
+ } else {
+ $smarty->_trigger_fatal_error("[plugin] unable to parse URL, check syntax");
+ return;
+ }
+ } else {
+ // ftp fetch
+ if($fp = @fopen($params['file'],'r')) {
+ while(!feof($fp)) {
+ $content .= fgets ($fp,4096);
+ }
+ fclose($fp);
+ } else {
+ $smarty->_trigger_fatal_error('[plugin] fetch cannot read file \'' . $params['file'] .'\'');
+ return;
+ }
+ }
+
+ }
+
+
+ if (!empty($params['assign'])) {
+ $smarty->assign($params['assign'],$content);
+ } else {
+ return $content;
+ }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_checkboxes.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_checkboxes.php
new file mode 100644
index 00000000..6b32c594
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_checkboxes.php
@@ -0,0 +1,135 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_checkboxes} function plugin
+ *
+ * File: function.html_checkboxes.php<br>
+ * Type: function<br>
+ * Name: html_checkboxes<br>
+ * Date: 24.Feb.2003<br>
+ * Purpose: Prints out a list of checkbox input types<br>
+ * Input:<br>
+ * - name (optional) - string default "checkbox"
+ * - values (required) - array
+ * - options (optional) - associative array
+ * - checked (optional) - array default not set
+ * - separator (optional) - ie <br> or &nbsp;
+ * - output (optional) - without this one the buttons don't have names
+ * Examples:
+ * <pre>
+ * {html_checkboxes values=$ids output=$names}
+ * {html_checkboxes values=$ids name='box' separator='<br>' output=$names}
+ * {html_checkboxes values=$ids checked=$checked separator='<br>' output=$names}
+ * </pre>
+ * @link http://smarty.php.net/manual/en/language.function.html.checkboxes.php {html_checkboxes}
+ * (Smarty online manual)
+ * @author Christopher Kvarme <christopher.kvarme@flashjab.com>
+ * @author credits to Monte Ohrt <monte@ispi.net>
+ * @version 1.0
+ * @param array
+ * @param Smarty
+ * @return string
+ * @uses smarty_function_escape_special_chars()
+ */
+function smarty_function_html_checkboxes($params, &$smarty)
+{
+ require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');
+
+ $name = 'checkbox';
+ $values = null;
+ $options = null;
+ $selected = null;
+ $separator = '';
+ $labels = true;
+ $output = null;
+
+ $extra = '';
+
+ foreach($params as $_key => $_val) {
+ switch($_key) {
+ case 'name':
+ case 'separator':
+ $$_key = $_val;
+ break;
+
+ case 'labels':
+ $$_key = (bool)$_val;
+ break;
+
+ case 'options':
+ $$_key = (array)$_val;
+ break;
+
+ case 'values':
+ case 'output':
+ $$_key = array_values((array)$_val);
+ break;
+
+ case 'checked':
+ case 'selected':
+ $selected = array_values((array)$_val);
+ break;
+
+ case 'checkboxes':
+ $smarty->trigger_error('html_checkboxes: the use of the "checkboxes" attribute is deprecated, use "options" instead', E_USER_WARNING);
+ $options = (array)$_val;
+ break;
+
+ default:
+ if(!is_array($_val)) {
+ $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"';
+ } else {
+ $smarty->trigger_error("html_checkboxes: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+ }
+ break;
+ }
+ }
+
+ if (!isset($options) && !isset($values))
+ return ''; /* raise error here? */
+
+ settype($selected, 'array');
+ $_html_result = '';
+
+ if (is_array($options)) {
+
+ foreach ($options as $_key=>$_val)
+ $_html_result .= smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels);
+
+
+ } else {
+ foreach ($values as $_i=>$_key) {
+ $_val = isset($output[$_i]) ? $output[$_i] : '';
+ $_html_result .= smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels);
+ }
+
+ }
+
+ return $_html_result;
+
+}
+
+function smarty_function_html_checkboxes_output($name, $value, $output, $selected, $extra, $separator, $labels) {
+ $_output = '';
+ if ($labels) $_output .= '<label>';
+ $_output .= '<input type="checkbox" name="'
+ . smarty_function_escape_special_chars($name) . '[]" value="'
+ . smarty_function_escape_special_chars($value) . '"';
+
+ if (in_array($value, $selected)) {
+ $_output .= ' checked="checked"';
+ }
+ $_output .= $extra . ' />' . $output;
+ if ($labels) $_output .= '</label>';
+ $_output .= $separator . "\n";
+
+ return $_output;
+}
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_image.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_image.php
new file mode 100644
index 00000000..5ddbe4a1
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_image.php
@@ -0,0 +1,143 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_image} function plugin
+ *
+ * Type: function<br>
+ * Name: html_image<br>
+ * Date: Feb 24, 2003<br>
+ * Purpose: format HTML tags for the image<br>
+ * Input:<br>
+ * - file = file (and path) of image (required)
+ * - border = border width (optional, default 0)
+ * - height = image height (optional, default actual height)
+ * - image =image width (optional, default actual width)
+ * - basedir = base directory for absolute paths, default
+ * is environment variable DOCUMENT_ROOT
+ *
+ * Examples: {html_image file="images/masthead.gif"}
+ * Output: <img src="images/masthead.gif" border=0 width=400 height=23>
+ * @link http://smarty.php.net/manual/en/language.function.html.image.php {html_image}
+ * (Smarty online manual)
+ * @author Monte Ohrt <monte@ispi.net>
+ * @author credits to Duda <duda@big.hu> - wrote first image function
+ * in repository, helped with lots of functionality
+ * @version 1.0
+ * @param array
+ * @param Smarty
+ * @return string
+ * @uses smarty_function_escape_special_chars()
+ */
+function smarty_function_html_image($params, &$smarty)
+{
+ require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');
+
+ $alt = '';
+ $file = '';
+ $border = 0;
+ $height = '';
+ $width = '';
+ $extra = '';
+ $prefix = '';
+ $suffix = '';
+ $basedir = isset($GLOBALS['HTTP_SERVER_VARS']['DOCUMENT_ROOT'])
+ ? $GLOBALS['HTTP_SERVER_VARS']['DOCUMENT_ROOT'] : '';
+ if(strstr($GLOBALS['HTTP_SERVER_VARS']['HTTP_USER_AGENT'], 'Mac')) {
+ $dpi_default = 72;
+ } else {
+ $dpi_default = 96;
+ }
+
+ foreach($params as $_key => $_val) {
+ switch($_key) {
+ case 'file':
+ case 'border':
+ case 'height':
+ case 'width':
+ case 'dpi':
+ case 'basedir':
+ $$_key = $_val;
+ break;
+
+ case 'alt':
+ if(!is_array($_val)) {
+ $$_key = smarty_function_escape_special_chars($_val);
+ } else {
+ $smarty->trigger_error("html_image: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+ }
+ break;
+
+ case 'link':
+ case 'href':
+ $prefix = '<a href="' . $_val . '">';
+ $suffix = '</a>';
+ break;
+
+ default:
+ if(!is_array($_val)) {
+ $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"';
+ } else {
+ $smarty->trigger_error("html_image: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+ }
+ break;
+ }
+ }
+
+ if (empty($file)) {
+ $smarty->trigger_error("html_image: missing 'file' parameter", E_USER_NOTICE);
+ return;
+ }
+
+ if (substr($file,0,1) == '/') {
+ $_image_path = $basedir . $file;
+ } else {
+ $_image_path = $file;
+ }
+
+ if(!isset($params['width']) || !isset($params['height'])) {
+ if(!$_image_data = @getimagesize($_image_path)) {
+ if(!file_exists($_image_path)) {
+ $smarty->trigger_error("html_image: unable to find '$_image_path'", E_USER_NOTICE);
+ return;
+ } else if(!is_readable($_image_path)) {
+ $smarty->trigger_error("html_image: unable to read '$_image_path'", E_USER_NOTICE);
+ return;
+ } else {
+ $smarty->trigger_error("html_image: '$_image_path' is not a valid image file", E_USER_NOTICE);
+ return;
+ }
+ }
+ $_params = array('resource_type' => 'file', 'resource_name' => $_image_path);
+ require_once(SMARTY_DIR . 'core' . DIRECTORY_SEPARATOR . 'core.is_secure.php');
+ if(!$smarty->security && !smarty_core_is_secure($_params, $smarty)) {
+ $smarty->trigger_error("html_image: (secure) '$_image_path' not in secure directory", E_USER_NOTICE);
+ return;
+ }
+
+ if(!isset($params['width'])) {
+ $width = $_image_data[0];
+ }
+ if(!isset($params['height'])) {
+ $height = $_image_data[1];
+ }
+
+ }
+
+ if(isset($params['dpi'])) {
+ $_resize = $dpi_default/$params['dpi'];
+ $width = round($width * $_resize);
+ $height = round($height * $_resize);
+ }
+
+ return $prefix . '<img src="'.$file.'" alt="'.$alt.'" border="'.$border.'" width="'.$width.'" height="'.$height.'"'.$extra.' />' . $suffix;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_options.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_options.php
new file mode 100644
index 00000000..dfc38c83
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_options.php
@@ -0,0 +1,118 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_options} function plugin
+ *
+ * Type: function<br>
+ * Name: html_options<br>
+ * Input:<br>
+ * - name (optional) - string default "select"
+ * - values (required if no options supplied) - array
+ * - options (required if no values supplied) - associative array
+ * - selected (optional) - string default not set
+ * - output (required if not options supplied) - array
+ * Purpose: Prints the list of <option> tags generated from
+ * the passed parameters
+ * @link http://smarty.php.net/manual/en/language.function.html.options.php {html_image}
+ * (Smarty online manual)
+ * @param array
+ * @param Smarty
+ * @return string
+ * @uses smarty_function_escape_special_chars()
+ */
+function smarty_function_html_options($params, &$smarty)
+{
+ require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');
+
+ $name = null;
+ $values = null;
+ $options = null;
+ $selected = array();
+ $output = null;
+
+ $extra = '';
+
+ foreach($params as $_key => $_val) {
+ switch($_key) {
+ case 'name':
+ $$_key = (string)$_val;
+ break;
+
+ case 'options':
+ $$_key = (array)$_val;
+ break;
+
+ case 'selected':
+ case 'values':
+ case 'output':
+ $$_key = array_values((array)$_val);
+ break;
+
+ default:
+ if(!is_array($_val)) {
+ $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"';
+ } else {
+ $smarty->trigger_error("html_options: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+ }
+ break;
+ }
+ }
+
+ if (!isset($options) && !isset($values))
+ return ''; /* raise error here? */
+
+ $_html_result = '';
+
+ if (is_array($options)) {
+
+ foreach ($options as $_key=>$_val)
+ $_html_result .= smarty_function_html_options_optoutput($_key, $_val, $selected);
+
+ } else {
+
+ foreach ((array)$values as $_i=>$_key) {
+ $_val = isset($output[$_i]) ? $output[$_i] : '';
+ $_html_result .= smarty_function_html_options_optoutput($_key, $_val, $selected);
+ }
+
+ }
+
+ if(!empty($name)) {
+ $_html_result = '<select name="' . $name . '"' . $extra . '>' . "\n" . $_html_result . '</select>' . "\n";
+ }
+
+ return $_html_result;
+
+}
+
+function smarty_function_html_options_optoutput($key, $value, $selected) {
+ if(!is_array($value)) {
+ $_html_result = '<option label="' . smarty_function_escape_special_chars($value) . '" value="' .
+ smarty_function_escape_special_chars($key) . '"';
+ if (in_array($key, $selected))
+ $_html_result .= ' selected="selected"';
+ $_html_result .= '>' . smarty_function_escape_special_chars($value) . '</option>' . "\n";
+ } else {
+ $_html_result = smarty_function_html_options_optgroup($key, $value, $selected);
+ }
+ return $_html_result;
+}
+
+function smarty_function_html_options_optgroup($key, $values, $selected) {
+ $optgroup_html = '<optgroup label="' . smarty_function_escape_special_chars($key) . '">' . "\n";
+ foreach ($values as $key => $value) {
+ $optgroup_html .= smarty_function_html_options_optoutput($key, $value, $selected);
+ }
+ $optgroup_html .= "</optgroup>\n";
+ return $optgroup_html;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_radios.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_radios.php
new file mode 100644
index 00000000..f5052391
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_radios.php
@@ -0,0 +1,138 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_radios} function plugin
+ *
+ * File: function.html_radios.php<br>
+ * Type: function<br>
+ * Name: html_radios<br>
+ * Date: 24.Feb.2003<br>
+ * Purpose: Prints out a list of radio input types<br>
+ * Input:<br>
+ * - name (optional) - string default "radio"
+ * - values (required) - array
+ * - options (optional) - associative array
+ * - checked (optional) - array default not set
+ * - separator (optional) - ie <br> or &nbsp;
+ * - output (optional) - without this one the buttons don't have names
+ * Examples:
+ * <pre>
+ * {html_radios values=$ids output=$names}
+ * {html_radios values=$ids name='box' separator='<br>' output=$names}
+ * {html_radios values=$ids checked=$checked separator='<br>' output=$names}
+ * </pre>
+ * @link http://smarty.php.net/manual/en/language.function.html.radios.php {html_radios}
+ * (Smarty online manual)
+ * @author Christopher Kvarme <christopher.kvarme@flashjab.com>
+ * @author credits to Monte Ohrt <monte@ispi.net>
+ * @version 1.0
+ * @param array
+ * @param Smarty
+ * @return string
+ * @uses smarty_function_escape_special_chars()
+ */
+function smarty_function_html_radios($params, &$smarty)
+{
+ require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');
+
+ $name = 'radio';
+ $values = null;
+ $options = null;
+ $selected = null;
+ $separator = '';
+ $labels = true;
+ $output = null;
+ $extra = '';
+
+ foreach($params as $_key => $_val) {
+ switch($_key) {
+ case 'name':
+ case 'separator':
+ $$_key = (string)$_val;
+ break;
+
+ case 'checked':
+ case 'selected':
+ if(is_array($_val)) {
+ $smarty->trigger_error('html_radios: the "' . $_key . '" attribute cannot be an array', E_USER_WARNING);
+ } else {
+ $selected = (string)$_val;
+ }
+ break;
+
+ case 'labels':
+ $$_key = (bool)$_val;
+ break;
+
+ case 'options':
+ $$_key = (array)$_val;
+ break;
+
+ case 'values':
+ case 'output':
+ $$_key = array_values((array)$_val);
+ break;
+
+ case 'radios':
+ $smarty->trigger_error('html_radios: the use of the "radios" attribute is deprecated, use "options" instead', E_USER_WARNING);
+ $options = (array)$_val;
+ break;
+
+
+ default:
+ if(!is_array($_val)) {
+ $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"';
+ } else {
+ $smarty->trigger_error("html_radios: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+ }
+ break;
+ }
+ }
+
+ if (!isset($options) && !isset($values))
+ return ''; /* raise error here? */
+
+ $_html_result = '';
+
+ if (isset($options) && is_array($options)) {
+
+ foreach ((array)$options as $_key=>$_val)
+ $_html_result .= smarty_function_html_radios_output($name, $_key, $_val, $selected, $extra, $separator, $labels);
+
+ } else {
+
+ foreach ((array)$values as $_i=>$_key) {
+ $_val = isset($output[$_i]) ? $output[$_i] : '';
+ $_html_result .= smarty_function_html_radios_output($name, $_key, $_val, $selected, $extra, $separator, $labels);
+ }
+
+ }
+
+ return $_html_result;
+
+}
+
+function smarty_function_html_radios_output($name, $value, $output, $selected, $extra, $separator, $labels) {
+ $_output = '';
+ if ($labels) $_output .= '<label>';
+ $_output .= '<input type="radio" name="'
+ . smarty_function_escape_special_chars($name) . '" value="'
+ . smarty_function_escape_special_chars($value) . '"';
+
+ if ($value==$selected) {
+ $_output .= ' checked="checked"';
+ }
+ $_output .= $extra . ' />' . $output;
+ if ($labels) $_output .= '</label>';
+ $_output .= $separator . "\n";
+
+ return $_output;
+}
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_select_date.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_select_date.php
new file mode 100644
index 00000000..a607f555
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_select_date.php
@@ -0,0 +1,243 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {html_select_date} plugin
+ *
+ * Type: function<br>
+ * Name: html_select_date<br>
+ * Purpose: Prints the dropdowns for date selection.
+ *
+ * ChangeLog:<br>
+ * - 1.0 initial release
+ * - 1.1 added support for +/- N syntax for begin
+ * and end year values. (Monte)
+ * - 1.2 added support for yyyy-mm-dd syntax for
+ * time value. (Jan Rosier)
+ * - 1.3 added support for choosing format for
+ * month values (Gary Loescher)
+ * - 1.3.1 added support for choosing format for
+ * day values (Marcus Bointon)
+ * @link http://smarty.php.net/manual/en/language.function.html.select.date.php {html_select_date}
+ * (Smarty online manual)
+ * @version 1.3
+ * @author Andrei Zmievski
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_html_select_date($params, &$smarty)
+{
+ require_once $smarty->_get_plugin_filepath('shared','make_timestamp');
+ require_once $smarty->_get_plugin_filepath('function','html_options');
+ /* Default values. */
+ $prefix = "Date_";
+ $start_year = strftime("%Y");
+ $end_year = $start_year;
+ $display_days = true;
+ $display_months = true;
+ $display_years = true;
+ $month_format = "%B";
+ /* Write months as numbers by default GL */
+ $month_value_format = "%m";
+ $day_format = "%02d";
+ /* Write day values using this format MB */
+ $day_value_format = "%d";
+ $year_as_text = false;
+ /* Display years in reverse order? Ie. 2000,1999,.... */
+ $reverse_years = false;
+ /* Should the select boxes be part of an array when returned from PHP?
+ e.g. setting it to "birthday", would create "birthday[Day]",
+ "birthday[Month]" & "birthday[Year]". Can be combined with prefix */
+ $field_array = null;
+ /* <select size>'s of the different <select> tags.
+ If not set, uses default dropdown. */
+ $day_size = null;
+ $month_size = null;
+ $year_size = null;
+ /* Unparsed attributes common to *ALL* the <select>/<input> tags.
+ An example might be in the template: all_extra ='class ="foo"'. */
+ $all_extra = null;
+ /* Separate attributes for the tags. */
+ $day_extra = null;
+ $month_extra = null;
+ $year_extra = null;
+ /* Order in which to display the fields.
+ "D" -> day, "M" -> month, "Y" -> year. */
+ $field_order = 'MDY';
+ /* String printed between the different fields. */
+ $field_separator = "\n";
+ $time = time();
+
+
+ extract($params);
+
+ // If $time is not in format yyyy-mm-dd
+ if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $time)) {
+ // then $time is empty or unix timestamp or mysql timestamp
+ // using smarty_make_timestamp to get an unix timestamp and
+ // strftime to make yyyy-mm-dd
+ $time = strftime('%Y-%m-%d', smarty_make_timestamp($time));
+ }
+ // Now split this in pieces, which later can be used to set the select
+ $time = explode("-", $time);
+
+ // make syntax "+N" or "-N" work with start_year and end_year
+ if (preg_match('!^(\+|\-)\s*(\d+)$!', $end_year, $match)) {
+ if ($match[1] == '+') {
+ $end_year = strftime('%Y') + $match[2];
+ } else {
+ $end_year = strftime('%Y') - $match[2];
+ }
+ }
+ if (preg_match('!^(\+|\-)\s*(\d+)$!', $start_year, $match)) {
+ if ($match[1] == '+') {
+ $start_year = strftime('%Y') + $match[2];
+ } else {
+ $start_year = strftime('%Y') - $match[2];
+ }
+ }
+
+ $field_order = strtoupper($field_order);
+
+ $html_result = $month_result = $day_result = $year_result = "";
+
+ if ($display_months) {
+ $month_names = array();
+ $month_values = array();
+
+ for ($i = 1; $i <= 12; $i++) {
+ $month_names[] = strftime($month_format, mktime(0, 0, 0, $i, 1, 2000));
+ $month_values[] = strftime($month_value_format, mktime(0, 0, 0, $i, 1, 2000));
+ }
+
+ $month_result .= '<select name=';
+ if (null !== $field_array){
+ $month_result .= '"' . $field_array . '[' . $prefix . 'Month]"';
+ } else {
+ $month_result .= '"' . $prefix . 'Month"';
+ }
+ if (null !== $month_size){
+ $month_result .= ' size="' . $month_size . '"';
+ }
+ if (null !== $month_extra){
+ $month_result .= ' ' . $month_extra;
+ }
+ if (null !== $all_extra){
+ $month_result .= ' ' . $all_extra;
+ }
+ $month_result .= '>'."\n";
+
+ $month_result .= smarty_function_html_options(array('output' => $month_names,
+ 'values' => $month_values,
+ 'selected' => $month_values[$time[1]-1],
+ 'print_result' => false),
+ $smarty);
+
+ $month_result .= '</select>';
+ }
+
+ if ($display_days) {
+ $days = array();
+ for ($i = 1; $i <= 31; $i++) {
+ $days[] = sprintf($day_format, $i);
+ $day_values[] = sprintf($day_value_format, $i);
+ }
+
+ $day_result .= '<select name=';
+ if (null !== $field_array){
+ $day_result .= '"' . $field_array . '[' . $prefix . 'Day]"';
+ } else {
+ $day_result .= '"' . $prefix . 'Day"';
+ }
+ if (null !== $day_size){
+ $day_result .= ' size="' . $day_size . '"';
+ }
+ if (null !== $all_extra){
+ $day_result .= ' ' . $all_extra;
+ }
+ if (null !== $day_extra){
+ $day_result .= ' ' . $day_extra;
+ }
+ $day_result .= '>'."\n";
+ $day_result .= smarty_function_html_options(array('output' => $days,
+ 'values' => $day_values,
+ 'selected' => $time[2],
+ 'print_result' => false),
+ $smarty);
+ $day_result .= '</select>';
+ }
+
+ if ($display_years) {
+ if (null !== $field_array){
+ $year_name = $field_array . '[' . $prefix . 'Year]';
+ } else {
+ $year_name = $prefix . 'Year';
+ }
+ if ($year_as_text) {
+ $year_result .= '<input type="text" name="' . $year_name . '" value="' . $time[0] . '" size="4" maxlength="4"';
+ if (null !== $all_extra){
+ $year_result .= ' ' . $all_extra;
+ }
+ if (null !== $year_extra){
+ $year_result .= ' ' . $year_extra;
+ }
+ $year_result .= '>';
+ } else {
+ $years = range((int)$start_year, (int)$end_year);
+ if ($reverse_years) {
+ rsort($years, SORT_NUMERIC);
+ }
+
+ $year_result .= '<select name="' . $year_name . '"';
+ if (null !== $year_size){
+ $year_result .= ' size="' . $year_size . '"';
+ }
+ if (null !== $all_extra){
+ $year_result .= ' ' . $all_extra;
+ }
+ if (null !== $year_extra){
+ $year_result .= ' ' . $year_extra;
+ }
+ $year_result .= '>'."\n";
+ $year_result .= smarty_function_html_options(array('output' => $years,
+ 'values' => $years,
+ 'selected' => $time[0],
+ 'print_result' => false),
+ $smarty);
+ $year_result .= '</select>';
+ }
+ }
+
+ // Loop thru the field_order field
+ for ($i = 0; $i <= 2; $i++){
+ $c = substr($field_order, $i, 1);
+ switch ($c){
+ case 'D':
+ $html_result .= $day_result;
+ break;
+
+ case 'M':
+ $html_result .= $month_result;
+ break;
+
+ case 'Y':
+ $html_result .= $year_result;
+ break;
+ }
+ // Add the field seperator
+ if($i != 2) {
+ $html_result .= $field_separator;
+ }
+ }
+
+ return $html_result;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_select_time.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_select_time.php
new file mode 100644
index 00000000..4643136b
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_select_time.php
@@ -0,0 +1,163 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_select_time} function plugin
+ *
+ * Type: function<br>
+ * Name: html_select_time<br>
+ * Purpose: Prints the dropdowns for time selection
+ * @link http://smarty.php.net/manual/en/language.function.html.select.time.php {html_select_time}
+ * (Smarty online manual)
+ * @param array
+ * @param Smarty
+ * @return string
+ * @uses smarty_make_timestamp()
+ */
+function smarty_function_html_select_time($params, &$smarty)
+{
+ require_once $smarty->_get_plugin_filepath('shared','make_timestamp');
+ require_once $smarty->_get_plugin_filepath('function','html_options');
+ /* Default values. */
+ $prefix = "Time_";
+ $time = time();
+ $display_hours = true;
+ $display_minutes = true;
+ $display_seconds = true;
+ $display_meridian = true;
+ $use_24_hours = true;
+ $minute_interval = 1;
+ $second_interval = 1;
+ /* Should the select boxes be part of an array when returned from PHP?
+ e.g. setting it to "birthday", would create "birthday[Hour]",
+ "birthday[Minute]", "birthday[Seconds]" & "birthday[Meridian]".
+ Can be combined with prefix. */
+ $field_array = null;
+ $all_extra = null;
+ $hour_extra = null;
+ $minute_extra = null;
+ $second_extra = null;
+ $meridian_extra = null;
+
+ extract($params);
+
+ $time = smarty_make_timestamp($time);
+
+ $html_result = '';
+
+ if ($display_hours) {
+ $hours = $use_24_hours ? range(0, 23) : range(1, 12);
+ $hour_fmt = $use_24_hours ? '%H' : '%I';
+ for ($i = 0, $for_max = count($hours); $i < $for_max; $i++)
+ $hours[$i] = sprintf('%02d', $hours[$i]);
+ $html_result .= '<select name=';
+ if (null !== $field_array) {
+ $html_result .= '"' . $field_array . '[' . $prefix . 'Hour]"';
+ } else {
+ $html_result .= '"' . $prefix . 'Hour"';
+ }
+ if (null !== $hour_extra){
+ $html_result .= ' ' . $hour_extra;
+ }
+ if (null !== $all_extra){
+ $html_result .= ' ' . $all_extra;
+ }
+ $html_result .= '>'."\n";
+ $html_result .= smarty_function_html_options(array('output' => $hours,
+ 'values' => $hours,
+ 'selected' => strftime($hour_fmt, $time),
+ 'print_result' => false),
+ $smarty);
+ $html_result .= "</select>\n";
+ }
+
+ if ($display_minutes) {
+ $all_minutes = range(0, 59);
+ for ($i = 0, $for_max = count($all_minutes); $i < $for_max; $i+= $minute_interval)
+ $minutes[] = sprintf('%02d', $all_minutes[$i]);
+ $selected = intval(floor(strftime('%M', $time) / $minute_interval) * $minute_interval);
+ $html_result .= '<select name=';
+ if (null !== $field_array) {
+ $html_result .= '"' . $field_array . '[' . $prefix . 'Minute]"';
+ } else {
+ $html_result .= '"' . $prefix . 'Minute"';
+ }
+ if (null !== $minute_extra){
+ $html_result .= ' ' . $minute_extra;
+ }
+ if (null !== $all_extra){
+ $html_result .= ' ' . $all_extra;
+ }
+ $html_result .= '>'."\n";
+
+ $html_result .= smarty_function_html_options(array('output' => $minutes,
+ 'values' => $minutes,
+ 'selected' => $selected,
+ 'print_result' => false),
+ $smarty);
+ $html_result .= "</select>\n";
+ }
+
+ if ($display_seconds) {
+ $all_seconds = range(0, 59);
+ for ($i = 0, $for_max = count($all_seconds); $i < $for_max; $i+= $second_interval)
+ $seconds[] = sprintf('%02d', $all_seconds[$i]);
+ $selected = intval(floor(strftime('%S', $time) / $second_interval) * $second_interval);
+ $html_result .= '<select name=';
+ if (null !== $field_array) {
+ $html_result .= '"' . $field_array . '[' . $prefix . 'Second]"';
+ } else {
+ $html_result .= '"' . $prefix . 'Second"';
+ }
+
+ if (null !== $second_extra){
+ $html_result .= ' ' . $second_extra;
+ }
+ if (null !== $all_extra){
+ $html_result .= ' ' . $all_extra;
+ }
+ $html_result .= '>'."\n";
+
+ $html_result .= smarty_function_html_options(array('output' => $seconds,
+ 'values' => $seconds,
+ 'selected' => $selected,
+ 'print_result' => false),
+ $smarty);
+ $html_result .= "</select>\n";
+ }
+
+ if ($display_meridian && !$use_24_hours) {
+ $html_result .= '<select name=';
+ if (null !== $field_array) {
+ $html_result .= '"' . $field_array . '[' . $prefix . 'Meridian]"';
+ } else {
+ $html_result .= '"' . $prefix . 'Meridian"';
+ }
+
+ if (null !== $meridian_extra){
+ $html_result .= ' ' . $meridian_extra;
+ }
+ if (null !== $all_extra){
+ $html_result .= ' ' . $all_extra;
+ }
+ $html_result .= '>'."\n";
+
+ $html_result .= smarty_function_html_options(array('output' => array('AM', 'PM'),
+ 'values' => array('am', 'pm'),
+ 'selected' => strtolower(strftime('%p', $time)),
+ 'print_result' => false),
+ $smarty);
+ $html_result .= "</select>\n";
+ }
+
+ return $html_result;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_table.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_table.php
new file mode 100644
index 00000000..ece9c8c5
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.html_table.php
@@ -0,0 +1,113 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_table} function plugin
+ *
+ * Type: function<br>
+ * Name: html_table<br>
+ * Date: Feb 17, 2003<br>
+ * Purpose: make an html table from an array of data<br>
+ * Input:<br>
+ * - loop = array to loop through
+ * - cols = number of columns
+ * - rows = number of rows
+ * - table_attr = table attributes
+ * - tr_attr = table row attributes (arrays are cycled)
+ * - td_attr = table cell attributes (arrays are cycled)
+ * - trailpad = value to pad trailing cells with
+ * - vdir = vertical direction (default: "down", means top-to-bottom)
+ * - hdir = horizontal direction (default: "right", means left-to-right)
+ * - inner = inner loop (default "cols": print $loop line by line,
+ * $loop will be printed column by column otherwise)
+ *
+ *
+ * Examples:
+ * <pre>
+ * {table loop=$data}
+ * {table loop=$data cols=4 tr_attr='"bgcolor=red"'}
+ * {table loop=$data cols=4 tr_attr=$colors}
+ * </pre>
+ * @author Monte Ohrt <monte@ispi.net>
+ * @version 1.0
+ * @link http://smarty.php.net/manual/en/language.function.html.table.php {html_table}
+ * (Smarty online manual)
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_html_table($params, &$smarty)
+{
+ $table_attr = 'border="1"';
+ $tr_attr = '';
+ $td_attr = '';
+ $cols = 3;
+ $rows = 3;
+ $trailpad = '&nbsp;';
+ $vdir = 'down';
+ $hdir = 'right';
+ $inner = 'cols';
+
+ extract($params);
+
+ if (!isset($loop)) {
+ $smarty->trigger_error("html_table: missing 'loop' parameter");
+ return;
+ }
+
+ $loop_count = count($loop);
+ if (empty($params['rows'])) {
+ /* no rows specified */
+ $rows = ceil($loop_count/$cols);
+ } elseif (empty($params['cols'])) {
+ if (!empty($params['rows'])) {
+ /* no cols specified, but rows */
+ $cols = ceil($loop_count/$rows);
+ }
+ }
+
+ $output = "<table $table_attr>\n";
+
+ for ($r=0; $r<$rows; $r++) {
+ $output .= "<tr" . smarty_function_html_table_cycle('tr', $tr_attr, $r) . ">\n";
+ $rx = ($vdir == 'down') ? $r*$cols : ($rows-1-$r)*$cols;
+
+ for ($c=0; $c<$cols; $c++) {
+ $x = ($hdir == 'right') ? $rx+$c : $rx+$cols-1-$c;
+ if ($inner!='cols') {
+ /* shuffle x to loop over rows*/
+ $x = floor($x/$cols) + ($x%$cols)*$rows;
+ }
+
+ if ($x<$loop_count) {
+ $output .= "<td" . smarty_function_html_table_cycle('td', $td_attr, $c) . ">" . $loop[$x] . "</td>\n";
+ } else {
+ $output .= "<td" . smarty_function_html_table_cycle('td', $td_attr, $c) . ">$trailpad</td>\n";
+ }
+ }
+ $output .= "</tr>\n";
+ }
+ $output .= "</table>\n";
+
+ return $output;
+}
+
+function smarty_function_html_table_cycle($name, $var, $no) {
+ if(!is_array($var)) {
+ $ret = $var;
+ } else {
+ $ret = $var[$no % count($var)];
+ }
+
+ return ($ret) ? ' '.$ret : '';
+}
+
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.mailto.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.mailto.php
new file mode 100644
index 00000000..9273ba39
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.mailto.php
@@ -0,0 +1,140 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {mailto} function plugin
+ *
+ * Type: function<br>
+ * Name: mailto<br>
+ * Date: May 21, 2002
+ * Purpose: automate mailto address link creation, and optionally
+ * encode them.<br>
+ * Input:<br>
+ * - address = e-mail address
+ * - text = (optional) text to display, default is address
+ * - encode = (optional) can be one of:
+ * * none : no encoding (default)
+ * * javascript : encode with javascript
+ * * hex : encode with hexidecimal (no javascript)
+ * - cc = (optional) address(es) to carbon copy
+ * - bcc = (optional) address(es) to blind carbon copy
+ * - subject = (optional) e-mail subject
+ * - newsgroups = (optional) newsgroup(s) to post to
+ * - followupto = (optional) address(es) to follow up to
+ * - extra = (optional) extra tags for the href link
+ *
+ * Examples:
+ * <pre>
+ * {mailto address="me@domain.com"}
+ * {mailto address="me@domain.com" encode="javascript"}
+ * {mailto address="me@domain.com" encode="hex"}
+ * {mailto address="me@domain.com" subject="Hello to you!"}
+ * {mailto address="me@domain.com" cc="you@domain.com,they@domain.com"}
+ * {mailto address="me@domain.com" extra='class="mailto"'}
+ * </pre>
+ * @link http://smarty.php.net/manual/en/language.function.mailto.php {mailto}
+ * (Smarty online manual)
+ * @version 1.2
+ * @author Monte Ohrt <monte@ispi.net>
+ * @author credits to Jason Sweat (added cc, bcc and subject functionality)
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_mailto($params, &$smarty)
+{
+ $extra = '';
+ extract($params);
+
+ if (empty($address)) {
+ $smarty->trigger_error("mailto: missing 'address' parameter");
+ return;
+ }
+
+ if (empty($text)) {
+ $text = $address;
+ }
+
+ // netscape and mozilla do not decode %40 (@) in BCC field (bug?)
+ // so, don't encode it.
+
+ $mail_parms = array();
+ if (!empty($cc)) {
+ $mail_parms[] = 'cc='.str_replace('%40','@',rawurlencode($cc));
+ }
+
+ if (!empty($bcc)) {
+ $mail_parms[] = 'bcc='.str_replace('%40','@',rawurlencode($bcc));
+ }
+
+ if (!empty($subject)) {
+ $mail_parms[] = 'subject='.rawurlencode($subject);
+ }
+
+ if (!empty($newsgroups)) {
+ $mail_parms[] = 'newsgroups='.rawurlencode($newsgroups);
+ }
+
+ if (!empty($followupto)) {
+ $mail_parms[] = 'followupto='.str_replace('%40','@',rawurlencode($followupto));
+ }
+
+ $mail_parm_vals = '';
+ for ($i=0; $i<count($mail_parms); $i++) {
+ $mail_parm_vals .= (0==$i) ? '?' : '&';
+ $mail_parm_vals .= $mail_parms[$i];
+ }
+ $address .= $mail_parm_vals;
+
+ if (empty($encode)) {
+ $encode = 'none';
+ } elseif (!in_array($encode,array('javascript','hex','none')) ) {
+ $smarty->trigger_error("mailto: 'encode' parameter must be none, javascript or hex");
+ return;
+ }
+
+ if ($encode == 'javascript' ) {
+ $string = 'document.write(\'<a href="mailto:'.$address.'" '.$extra.'>'.$text.'</a>\');';
+
+ for ($x=0; $x < strlen($string); $x++) {
+ $js_encode .= '%' . bin2hex($string[$x]);
+ }
+
+ return '<script type="text/javascript" language="javascript">eval(unescape(\''.$js_encode.'\'))</script>';
+
+ } elseif ($encode == 'hex') {
+
+ preg_match('!^(.*)(\?.*)$!',$address,$match);
+ if(!empty($match[2])) {
+ $smarty->trigger_error("mailto: hex encoding does not work with extra attributes. Try javascript.");
+ return;
+ }
+ for ($x=0; $x < strlen($address); $x++) {
+ if(preg_match('!\w!',$address[$x])) {
+ $address_encode .= '%' . bin2hex($address[$x]);
+ } else {
+ $address_encode .= $address[$x];
+ }
+ }
+ for ($x=0; $x < strlen($text); $x++) {
+ $text_encode .= '&#x' . bin2hex($text[$x]).';';
+ }
+
+ return '<a href="mailto:'.$address_encode.'" '.$extra.'>'.$text_encode.'</a>';
+
+ } else {
+ // no encoding
+ return '<a href="mailto:'.$address.'" '.$extra.'>'.$text.'</a>';
+
+ }
+
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.math.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.math.php
new file mode 100644
index 00000000..d2b5d829
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.math.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {math} function plugin
+ *
+ * Type: function<br>
+ * Name: math<br>
+ * Purpose: handle math computations in template<br>
+ * @link http://smarty.php.net/manual/en/language.function.math.php {math}
+ * (Smarty online manual)
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_math($params, &$smarty)
+{
+ // be sure equation parameter is present
+ if (empty($params['equation'])) {
+ $smarty->trigger_error("math: missing equation parameter");
+ return;
+ }
+
+ $equation = $params['equation'];
+
+ // make sure parenthesis are balanced
+ if (substr_count($equation,"(") != substr_count($equation,")")) {
+ $smarty->trigger_error("math: unbalanced parenthesis");
+ return;
+ }
+
+ // match all vars in equation, make sure all are passed
+ preg_match_all("!\!(0x)([a-zA-Z][a-zA-Z0-9_]*)!",$equation, $match);
+ $allowed_funcs = array('int','abs','ceil','cos','exp','floor','log','log10',
+ 'max','min','pi','pow','rand','round','sin','sqrt','srand','tan');
+ foreach($match[2] as $curr_var) {
+ if (!in_array($curr_var,array_keys($params)) && !in_array($curr_var, $allowed_funcs)) {
+ $smarty->trigger_error("math: parameter $curr_var not passed as argument");
+ return;
+ }
+ }
+
+ foreach($params as $key => $val) {
+ if ($key != "equation" && $key != "format" && $key != "assign") {
+ // make sure value is not empty
+ if (strlen($val)==0) {
+ $smarty->trigger_error("math: parameter $key is empty");
+ return;
+ }
+ if (!is_numeric($val)) {
+ $smarty->trigger_error("math: parameter $key: is not numeric");
+ return;
+ }
+ $equation = preg_replace("/\b$key\b/",$val, $equation);
+ }
+ }
+
+ eval("\$smarty_math_result = ".$equation.";");
+
+ if (empty($params['format'])) {
+ if (empty($params['assign'])) {
+ return $smarty_math_result;
+ } else {
+ $smarty->assign($params['assign'],$smarty_math_result);
+ }
+ } else {
+ if (empty($params['assign'])){
+ printf($params['format'],$smarty_math_result);
+ } else {
+ $smarty->assign($params['assign'],sprintf($params['format'],$smarty_math_result));
+ }
+ }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.popup.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.popup.php
new file mode 100644
index 00000000..0eb4fcb3
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.popup.php
@@ -0,0 +1,87 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {popup} function plugin
+ *
+ * Type: function<br>
+ * Name: popup<br>
+ * Purpose: make text pop up in windows via overlib
+ * @link http://smarty.php.net/manual/en/language.function.popup.php {popup}
+ * (Smarty online manual)
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_popup($params, &$smarty)
+{
+ extract($params);
+
+ if (empty($text) && !isset($inarray) && empty($function)) {
+ $smarty->trigger_error("overlib: attribute 'text' or 'inarray' or 'function' required");
+ return false;
+ }
+
+ if (empty($trigger)) { $trigger = "onmouseover"; }
+
+ $retval = $trigger . '="return overlib(\''.preg_replace(array("!'!","![\r\n]!"),array("\'",'\r'),$text).'\'';
+ if ($sticky) { $retval .= ",STICKY"; }
+ if (!empty($caption)) { $retval .= ",CAPTION,'".str_replace("'","\'",$caption)."'"; }
+ if (!empty($fgcolor)) { $retval .= ",FGCOLOR,'$fgcolor'"; }
+ if (!empty($bgcolor)) { $retval .= ",BGCOLOR,'$bgcolor'"; }
+ if (!empty($textcolor)) { $retval .= ",TEXTCOLOR,'$textcolor'"; }
+ if (!empty($capcolor)) { $retval .= ",CAPCOLOR,'$capcolor'"; }
+ if (!empty($closecolor)) { $retval .= ",CLOSECOLOR,'$closecolor'"; }
+ if (!empty($textfont)) { $retval .= ",TEXTFONT,'$textfont'"; }
+ if (!empty($captionfont)) { $retval .= ",CAPTIONFONT,'$captionfont'"; }
+ if (!empty($closefont)) { $retval .= ",CLOSEFONT,'$closefont'"; }
+ if (!empty($textsize)) { $retval .= ",TEXTSIZE,$textsize"; }
+ if (!empty($captionsize)) { $retval .= ",CAPTIONSIZE,$captionsize"; }
+ if (!empty($closesize)) { $retval .= ",CLOSESIZE,$closesize"; }
+ if (!empty($width)) { $retval .= ",WIDTH,$width"; }
+ if (!empty($height)) { $retval .= ",HEIGHT,$height"; }
+ if (!empty($left)) { $retval .= ",LEFT"; }
+ if (!empty($right)) { $retval .= ",RIGHT"; }
+ if (!empty($center)) { $retval .= ",CENTER"; }
+ if (!empty($above)) { $retval .= ",ABOVE"; }
+ if (!empty($below)) { $retval .= ",BELOW"; }
+ if (isset($border)) { $retval .= ",BORDER,$border"; }
+ if (isset($offsetx)) { $retval .= ",OFFSETX,$offsetx"; }
+ if (isset($offsety)) { $retval .= ",OFFSETY,$offsety"; }
+ if (!empty($fgbackground)) { $retval .= ",FGBACKGROUND,'$fgbackground'"; }
+ if (!empty($bgbackground)) { $retval .= ",BGBACKGROUND,'$bgbackground'"; }
+ if (!empty($closetext)) { $retval .= ",CLOSETEXT,'".str_replace("'","\'",$closetext)."'"; }
+ if (!empty($noclose)) { $retval .= ",NOCLOSE"; }
+ if (!empty($status)) { $retval .= ",STATUS,'".str_replace("'","\'",$status)."'"; }
+ if (!empty($autostatus)) { $retval .= ",AUTOSTATUS"; }
+ if (!empty($autostatuscap)) { $retval .= ",AUTOSTATUSCAP"; }
+ if (isset($inarray)) { $retval .= ",INARRAY,'$inarray'"; }
+ if (isset($caparray)) { $retval .= ",CAPARRAY,'$caparray'"; }
+ if (!empty($capicon)) { $retval .= ",CAPICON,'$capicon'"; }
+ if (!empty($snapx)) { $retval .= ",SNAPX,$snapx"; }
+ if (!empty($snapy)) { $retval .= ",SNAPY,$snapy"; }
+ if (isset($fixx)) { $retval .= ",FIXX,$fixx"; }
+ if (isset($fixy)) { $retval .= ",FIXY,$fixy"; }
+ if (!empty($background)) { $retval .= ",BACKGROUND,'$background'"; }
+ if (!empty($padx)) { $retval .= ",PADX,$padx"; }
+ if (!empty($pady)) { $retval .= ",PADY,$pady"; }
+ if (!empty($fullhtml)) { $retval .= ",FULLHTML"; }
+ if (!empty($frame)) { $retval .= ",FRAME,'$frame'"; }
+ if (isset($timeout)) { $retval .= ",TIMEOUT,$timeout"; }
+ if (!empty($function)) { $retval .= ",FUNCTION,'$function'"; }
+ if (isset($delay)) { $retval .= ",DELAY,$delay"; }
+ if (!empty($hauto)) { $retval .= ",HAUTO"; }
+ if (!empty($vauto)) { $retval .= ",VAUTO"; }
+ $retval .= ');" onmouseout="nd();"';
+
+ return $retval;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.popup_init.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.popup_init.php
new file mode 100644
index 00000000..e06de696
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.popup_init.php
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {popup_init} function plugin
+ *
+ * Type: function<br>
+ * Name: popup_init<br>
+ * Purpose: initialize overlib
+ * @link http://smarty.php.net/manual/en/language.function.popup.init.php {popup_init}
+ * (Smarty online manual)
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_popup_init($params, &$smarty)
+{
+ $zindex = 1000;
+
+ if (!empty($params['zindex'])) {
+ $zindex = $params['zindex'];
+ }
+
+ if (!empty($params['src'])) {
+ return '<div id="overDiv" style="position:absolute; visibility:hidden; z-index:'.$zindex.';"></div>' . "\n"
+ . '<script type="text/javascript" language="JavaScript" src="'.$params['src'].'"></script>' . "\n";
+ } else {
+ $smarty->trigger_error("popup_init: missing src parameter");
+ }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.var_dump.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.var_dump.php
new file mode 100644
index 00000000..382032c1
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/function.var_dump.php
@@ -0,0 +1,20 @@
+<?php
+/** @package Smarty
+* @subpackage plugins */
+
+/**
+ * Smarty plugin
+ * -------------------------------------------------------------
+ * Type: function
+ * Name: assign
+ * Purpose: assign a value to a template variable
+ * -------------------------------------------------------------
+ */
+function smarty_function_var_dump($params, &$smarty)
+{
+ var_dump('<pre>',$params,'</pre>');
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.capitalize.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.capitalize.php
new file mode 100644
index 00000000..464d5f84
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.capitalize.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty capitalize modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: capitalize<br>
+ * Purpose: capitalize words in the string
+ * @link http://smarty.php.net/manual/en/language.modifiers.php#LANGUAGE.MODIFIER.CAPITALIZE
+ * capitalize (Smarty online manual)
+ * @param string
+ * @return string
+ */
+function smarty_modifier_capitalize($string)
+{
+ return ucwords($string);
+}
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.cat.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.cat.php
new file mode 100644
index 00000000..176ee7ae
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.cat.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty cat modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: cat<br>
+ * Date: Feb 24, 2003
+ * Purpose: catenate a value to a variable
+ * Input: string to catenate
+ * Example: {$var|cat:"foo"}
+ * @link http://smarty.php.net/manual/en/language.modifier.cat.php cat
+ * (Smarty online manual)
+ * @author Monte Ohrt <monte@ispi.net>
+ * @version 1.0
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_cat($string, $cat)
+{
+ return $string . $cat;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.count_characters.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.count_characters.php
new file mode 100644
index 00000000..2fb7c898
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.count_characters.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty count_characters modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: count_characteres<br>
+ * Purpose: count the number of characters in a text
+ * @link http://smarty.php.net/manual/en/language.modifier.count.characters.php
+ * count_characters (Smarty online manual)
+ * @param string
+ * @param boolean include whitespace in the character count
+ * @return integer
+ */
+function smarty_modifier_count_characters($string, $include_spaces = false)
+{
+ if ($include_spaces)
+ return(strlen($string));
+
+ return preg_match_all("/[^\s]/",$string, $match);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.count_paragraphs.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.count_paragraphs.php
new file mode 100644
index 00000000..5f6278fe
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.count_paragraphs.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty count_paragraphs modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: count_paragraphs<br>
+ * Purpose: count the number of paragraphs in a text
+ * @link http://smarty.php.net/manual/en/language.modifier.count.paragraphs.php
+ * count_paragraphs (Smarty online manual)
+ * @param string
+ * @return integer
+ */
+function smarty_modifier_count_paragraphs($string)
+{
+ // count \r or \n characters
+ return count(preg_split('/[\r\n]+/', $string));
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.count_sentences.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.count_sentences.php
new file mode 100644
index 00000000..2f3ba65e
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.count_sentences.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty count_sentences modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: count_sentences
+ * Purpose: count the number of sentences in a text
+ * @link http://smarty.php.net/manual/en/language.modifier.count.paragraphs.php
+ * count_sentences (Smarty online manual)
+ * @param string
+ * @return integer
+ */
+function smarty_modifier_count_sentences($string)
+{
+ // find periods with a word before but not after.
+ return preg_match_all('/[^\s]\.(?!\w)/', $string, $match);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.count_words.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.count_words.php
new file mode 100644
index 00000000..a686e4b4
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.count_words.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty count_words modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: count_words<br>
+ * Purpose: count the number of words in a text
+ * @link http://smarty.php.net/manual/en/language.modifier.count.words.php
+ * count_words (Smarty online manual)
+ * @param string
+ * @return integer
+ */
+function smarty_modifier_count_words($string)
+{
+ // split text by ' ',\r,\n,\f,\t
+ $split_array = preg_split('/\s+/',$string);
+ // count matches that contain alphanumerics
+ $word_count = preg_grep('/[a-zA-Z0-9\\x80-\\xff]/', $split_array);
+
+ return count($word_count);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.date_format.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.date_format.php
new file mode 100644
index 00000000..ab7e9045
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.date_format.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Include the {@link shared.make_timestamp.php} plugin
+ */
+require_once $smarty->_get_plugin_filepath('shared','make_timestamp');
+/**
+ * Smarty date_format modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: date_format<br>
+ * Purpose: format datestamps via strftime<br>
+ * Input:<br>
+ * - string: input date string
+ * - format: strftime format for output
+ * - default_date: default date if $string is empty
+ * @link http://smarty.php.net/manual/en/language.modifier.date.format.php
+ * date_format (Smarty online manual)
+ * @param string
+ * @param string
+ * @param string
+ * @return string|void
+ * @uses smarty_make_timestamp()
+ */
+function smarty_modifier_date_format($string, $format="%b %e, %Y", $default_date=null)
+{
+ if($string != '') {
+ return strftime($format, smarty_make_timestamp($string));
+ } elseif (isset($default_date) && $default_date != '') {
+ return strftime($format, smarty_make_timestamp($default_date));
+ } else {
+ return;
+ }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.debug_print_var.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.debug_print_var.php
new file mode 100644
index 00000000..3158df00
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.debug_print_var.php
@@ -0,0 +1,57 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty debug_print_var modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: debug_print_var<br>
+ * Purpose: formats variable contents for display in the console
+ * @link http://smarty.php.net/manual/en/language.modifier.debug.print.var.php
+ * debug_print_var (Smarty online manual)
+ * @param array|object
+ * @param integer
+ * @param integer
+ * @return string
+ */
+function smarty_modifier_debug_print_var($var, $depth = 0, $length = 40)
+{
+ $_replace = array("\n"=>'<i>&#92;n</i>', "\r"=>'<i>&#92;r</i>', "\t"=>'<i>&#92;t</i>');
+ if (is_array($var)) {
+ $results = "<b>Array (".count($var).")</b>";
+ foreach ($var as $curr_key => $curr_val) {
+ $return = smarty_modifier_debug_print_var($curr_val, $depth+1, $length);
+ $results .= "<br>".str_repeat('&nbsp;', $depth*2)."<b>".strtr($curr_key, $_replace)."</b> =&gt; $return";
+ }
+ return $results;
+ } else if (is_object($var)) {
+ $object_vars = get_object_vars($var);
+ $results = "<b>".get_class($var)." Object (".count($object_vars).")</b>";
+ foreach ($object_vars as $curr_key => $curr_val) {
+ $return = smarty_modifier_debug_print_var($curr_val, $depth+1, $length);
+ $results .= "<br>".str_repeat('&nbsp;', $depth*2)."<b>$curr_key</b> =&gt; $return";
+ }
+ return $results;
+ } else {
+ if (empty($var) && $var != "0") {
+ return '<i>empty</i>';
+ }
+ if (strlen($var) > $length ) {
+ $results = substr($var, 0, $length-3).'...';
+ } else {
+ $results = $var;
+ }
+ $results = htmlspecialchars($results);
+ $results = strtr($results, $_replace);
+ return $results;
+ }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.default.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.default.php
new file mode 100644
index 00000000..4f1f800a
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.default.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty default modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: default<br>
+ * Purpose: designate default value for empty variables
+ * @link http://smarty.php.net/manual/en/language.modifier.default.php
+ * default (Smarty online manual)
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_default($string, $default = '')
+{
+ if (!isset($string) || $string === '')
+ return $default;
+ else
+ return $string;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.escape.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.escape.php
new file mode 100644
index 00000000..dc5ebc6f
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.escape.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty escape modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: escape<br>
+ * Purpose: Escape the string according to escapement type
+ * @link http://smarty.php.net/manual/en/language.modifier.escape.php
+ * escape (Smarty online manual)
+ * @param string
+ * @param html|htmlall|url|quotes|hex|hexentity|javascript
+ * @return string
+ */
+function smarty_modifier_escape($string, $esc_type = 'html')
+{
+ switch ($esc_type) {
+ case 'html':
+ return htmlspecialchars($string, ENT_QUOTES);
+
+ case 'htmlall':
+ return htmlentities($string, ENT_QUOTES);
+
+ case 'url':
+ return urlencode($string);
+
+ case 'quotes':
+ // escape unescaped single quotes
+ return preg_replace("%(?<!\\\\)'%", "\\'", $string);
+
+ case 'hex':
+ // escape every character into hex
+ $return = '';
+ for ($x=0; $x < strlen($string); $x++) {
+ $return .= '%' . bin2hex($string[$x]);
+ }
+ return $return;
+
+ case 'hexentity':
+ $return = '';
+ for ($x=0; $x < strlen($string); $x++) {
+ $return .= '&#x' . bin2hex($string[$x]) . ';';
+ }
+ return $return;
+
+ case 'javascript':
+ // escape quotes and backslashes and newlines
+ return strtr($string, array('\\'=>'\\\\',"'"=>"\\'",'"'=>'\\"',"\r"=>'\\r',"\n"=>'\\n'));
+
+ default:
+ return $string;
+ }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.htmlentities.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.htmlentities.php
new file mode 100644
index 00000000..72dcf7de
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.htmlentities.php
@@ -0,0 +1,18 @@
+<?php
+/** @package Smarty
+* @subpackage plugins */
+
+/**
+ * Smarty plugin
+ * -------------------------------------------------------------
+ * Type: modifier
+ * Name: upper
+ * Purpose: convert string to uppercase
+ * -------------------------------------------------------------
+ */
+function smarty_modifier_htmlentities($string)
+{
+ return htmlentities($string);
+}
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.indent.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.indent.php
new file mode 100644
index 00000000..4a8b81c7
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.indent.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty indent modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: indent<br>
+ * Purpose: indent lines of text
+ * @link http://smarty.php.net/manual/en/language.modifier.indent.php
+ * indent (Smarty online manual)
+ * @param string
+ * @param integer
+ * @param string
+ * @return string
+ */
+function smarty_modifier_indent($string,$chars=4,$char=" ")
+{
+ return preg_replace('!^!m',str_repeat($char,$chars),$string);
+}
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.lower.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.lower.php
new file mode 100644
index 00000000..fecb7168
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.lower.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty lower modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: lower<br>
+ * Purpose: convert string to lowercase
+ * @link http://smarty.php.net/manual/en/language.modifier.lower.php
+ * lower (Smarty online manual)
+ * @param string
+ * @return string
+ */
+function smarty_modifier_lower($string)
+{
+ return strtolower($string);
+}
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.nl2br.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.nl2br.php
new file mode 100644
index 00000000..2a5f238b
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.nl2br.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty plugin
+ *
+ * Type: modifier<br>
+ * Name: nl2br<br>
+ * Date: Feb 26, 2003
+ * Purpose: convert \r\n, \r or \n to <<br>>
+ * Input:<br>
+ * - contents = contents to replace
+ * - preceed_test = if true, includes preceeding break tags
+ * in replacement
+ * Example: {$text|nl2br}
+ * @link http://smarty.php.net/manual/en/language.modifier.nl2br.php
+ * nl2br (Smarty online manual)
+ * @version 1.0
+ * @author Monte Ohrt <monte@ispi.net>
+ * @param string
+ * @return string
+ */
+function smarty_modifier_nl2br($string)
+{
+ return nl2br($string);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.rawurlencode.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.rawurlencode.php
new file mode 100644
index 00000000..d2d5e813
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.rawurlencode.php
@@ -0,0 +1,18 @@
+<?php
+/** @package Smarty
+* @subpackage plugins */
+
+/**
+ * Smarty plugin
+ * -------------------------------------------------------------
+ * Type: modifier
+ * Name: rawurlencode
+ * Purpose: encode string for use in PDFdefaultConverter TOC
+ * -------------------------------------------------------------
+ */
+function smarty_modifier_rawurlencode($string)
+{
+ return rawurlencode($string);
+}
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.regex_replace.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.regex_replace.php
new file mode 100644
index 00000000..a467dfba
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.regex_replace.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty regex_replace modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: regex_replace<br>
+ * Purpose: regular epxression search/replace
+ * @link http://smarty.php.net/manual/en/language.modifier.regex.replace.php
+ * regex_replace (Smarty online manual)
+ * @param string
+ * @param string|array
+ * @param string|array
+ * @return string
+ */
+function smarty_modifier_regex_replace($string, $search, $replace)
+{
+ return preg_replace($search, $replace, $string);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.replace.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.replace.php
new file mode 100644
index 00000000..590e11b4
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.replace.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty replace modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: replace<br>
+ * Purpose: simple search/replace
+ * @link http://smarty.php.net/manual/en/language.modifier.replace.php
+ * replace (Smarty online manual)
+ * @param string
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_replace($string, $search, $replace)
+{
+ return str_replace($search, $replace, $string);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.spacify.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.spacify.php
new file mode 100644
index 00000000..bcc5f941
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.spacify.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty spacify modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: spacify<br>
+ * Purpose: add spaces between characters in a string
+ * @link http://smarty.php.net/manual/en/language.modifier.spacify.php
+ * spacify (Smarty online manual)
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_spacify($string, $spacify_char = ' ')
+{
+ return implode($spacify_char,
+ preg_split('//', $string, -1, PREG_SPLIT_NO_EMPTY));
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.string_format.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.string_format.php
new file mode 100644
index 00000000..49903137
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.string_format.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty string_format modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: string_format<br>
+ * Purpose: format strings via sprintf
+ * @link http://smarty.php.net/manual/en/language.modifier.string.format.php
+ * string_format (Smarty online manual)
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_string_format($string, $format)
+{
+ return sprintf($format, $string);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.strip.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.strip.php
new file mode 100644
index 00000000..fc675582
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.strip.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty strip modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: strip<br>
+ * Purpose: Replace all repeated spaces, newlines, tabs
+ * with a single space or supplied replacement string.<br>
+ * Example: {$var|strip} {$var|strip:"&nbsp;"}
+ * Date: September 25th, 2002
+ * @link http://smarty.php.net/manual/en/language.modifier.strip.php
+ * strip (Smarty online manual)
+ * @author Monte Ohrt <monte@ispi.net>
+ * @version 1.0
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_strip($text, $replace = ' ')
+{
+ return preg_replace('!\s+!', $replace, $text);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.strip_tags.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.strip_tags.php
new file mode 100644
index 00000000..516a87fc
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.strip_tags.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty strip_tags modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: strip_tags<br>
+ * Purpose: strip html tags from text
+ * @link http://smarty.php.net/manual/en/language.modifier.strip.tags.php
+ * strip_tags (Smarty online manual)
+ * @param string
+ * @param boolean
+ * @return string
+ */
+function smarty_modifier_strip_tags($string, $replace_with_space = true)
+{
+ if ($replace_with_space)
+ return preg_replace('!<[^>]*?>!', ' ', $string);
+ else
+ return strip_tags($string);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.truncate.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.truncate.php
new file mode 100644
index 00000000..775a20e8
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.truncate.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty truncate modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: truncate<br>
+ * Purpose: Truncate a string to a certain length if necessary,
+ * optionally splitting in the middle of a word, and
+ * appending the $etc string.
+ * @link http://smarty.php.net/manual/en/language.modifier.truncate.php
+ * truncate (Smarty online manual)
+ * @param string
+ * @param integer
+ * @param string
+ * @param boolean
+ * @return string
+ */
+function smarty_modifier_truncate($string, $length = 80, $etc = '...',
+ $break_words = false)
+{
+ if ($length == 0)
+ return '';
+
+ if (strlen($string) > $length) {
+ $length -= strlen($etc);
+ if (!$break_words)
+ $string = preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, $length+1));
+
+ return substr($string, 0, $length).$etc;
+ } else
+ return $string;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.upper.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.upper.php
new file mode 100644
index 00000000..899f6bb9
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.upper.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty upper modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: upper<br>
+ * Purpose: convert string to uppercase
+ * @link http://smarty.php.net/manual/en/language.modifier.upper.php
+ * upper (Smarty online manual)
+ * @param string
+ * @return string
+ */
+function smarty_modifier_upper($string)
+{
+ return strtoupper($string);
+}
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.wordwrap.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.wordwrap.php
new file mode 100644
index 00000000..fe4407fc
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/modifier.wordwrap.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty wordwrap modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: wordwrap<br>
+ * Purpose: wrap a string of text at a given length
+ * @link http://smarty.php.net/manual/en/language.modifier.wordwrap.php
+ * wordwrap (Smarty online manual)
+ * @param string
+ * @param integer
+ * @param string
+ * @param boolean
+ * @return string
+ */
+function smarty_modifier_wordwrap($string,$length=80,$break="\n",$cut=false)
+{
+ return wordwrap($string,$length,$break,$cut);
+}
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/outputfilter.trimwhitespace.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/outputfilter.trimwhitespace.php
new file mode 100644
index 00000000..1fa5fe17
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/outputfilter.trimwhitespace.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty trimwhitespace outputfilter plugin
+ *
+ * File: outputfilter.trimwhitespace.php<br>
+ * Type: outputfilter<br>
+ * Name: trimwhitespace<br>
+ * Date: Jan 25, 2003<br>
+ * Purpose: trim leading white space and blank lines from
+ * template source after it gets interpreted, cleaning
+ * up code and saving bandwidth. Does not affect
+ * <<PRE>></PRE> and <SCRIPT></SCRIPT> blocks.<br>
+ * Install: Drop into the plugin directory, call
+ * <code>$smarty->load_filter('output','trimwhitespace');</code>
+ * from application.
+ * @author Monte Ohrt <monte@ispi.net>
+ * @author Contributions from Lars Noschinski <lars@usenet.noschinski.de>
+ * @version 1.3
+ * @param string
+ * @param Smarty
+ */
+ function smarty_outputfilter_trimwhitespace($source, &$smarty)
+ {
+ // Pull out the script blocks
+ preg_match_all("!<script[^>]+>.*?</script>!is", $source, $match);
+ $_script_blocks = $match[0];
+ $source = preg_replace("!<script[^>]+>.*?</script>!is",
+ '@@@SMARTY:TRIM:SCRIPT@@@', $source);
+
+ // Pull out the pre blocks
+ preg_match_all("!<pre>.*?</pre>!is", $source, $match);
+ $_pre_blocks = $match[0];
+ $source = preg_replace("!<pre>.*?</pre>!is",
+ '@@@SMARTY:TRIM:PRE@@@', $source);
+
+ // Pull out the textarea blocks
+ preg_match_all("!<textarea[^>]+>.*?</textarea>!is", $source, $match);
+ $_textarea_blocks = $match[0];
+ $source = preg_replace("!<textarea[^>]+>.*?</textarea>!is",
+ '@@@SMARTY:TRIM:TEXTAREA@@@', $source);
+
+ // remove all leading spaces, tabs and carriage returns NOT
+ // preceeded by a php close tag.
+ $source = trim(preg_replace('/((?<!\?>)\n)[\s]+/m', '\1', $source));
+
+ // replace script blocks
+ smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:SCRIPT@@@",$_script_blocks, $source);
+
+ // replace pre blocks
+ smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:PRE@@@",$_pre_blocks, $source);
+
+ // replace textarea blocks
+ smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:TEXTAREA@@@",$_textarea_blocks, $source);
+
+ return $source;
+ }
+
+function smarty_outputfilter_trimwhitespace_replace($search_str, $replace, &$subject) {
+ $_len = strlen($search_str);
+ $_pos = 0;
+ for ($_i=0, $_count=count($replace); $_i<$_count; $_i++)
+ if (($_pos=strpos($subject, $search_str, $_pos))!==false)
+ $subject = substr_replace($subject, $replace[$_i], $_pos, $_len);
+ else
+ break;
+
+}
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/shared.escape_special_chars.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/shared.escape_special_chars.php
new file mode 100644
index 00000000..72b8a48c
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/shared.escape_special_chars.php
@@ -0,0 +1,30 @@
+<?php
+/**
+ * Smarty shared plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * escape_special_chars common function
+ *
+ * Function: smarty_function_escape_special_chars<br>
+ * Purpose: used by other smarty functions to escape
+ * special chars except for already escaped ones
+ * @param string
+ * @return string
+ */
+function smarty_function_escape_special_chars($string)
+{
+ if(!is_array($string)) {
+ $string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string);
+ $string = htmlspecialchars($string);
+ $string = str_replace(array('%%%SMARTY_START%%%','%%%SMARTY_END%%%'), array('&',';'), $string);
+ }
+ return $string;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/shared.make_timestamp.php b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/shared.make_timestamp.php
new file mode 100644
index 00000000..25c7f5c8
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/libs/plugins/shared.make_timestamp.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Smarty shared plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Function: smarty_make_timestamp<br>
+ * Purpose: used by other smarty functions to make a timestamp
+ * from a string.
+ * @param string
+ * @return string
+ */
+function smarty_make_timestamp($string)
+{
+ if(empty($string)) {
+ $string = "now";
+ }
+ $time = strtotime($string);
+ if (is_numeric($time) && $time != -1)
+ return $time;
+
+ // is mysql timestamp format of YYYYMMDDHHMMSS?
+ if (preg_match('/^\d{14}$/', $string)) {
+ $time = mktime(substr($string,8,2),substr($string,10,2),substr($string,12,2),
+ substr($string,4,2),substr($string,6,2),substr($string,0,4));
+
+ return $time;
+ }
+
+ // couldn't recognize it, try to return a time
+ $time = (int) $string;
+ if ($time > 0)
+ return $time;
+ else
+ return time();
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/misc/smarty_icon.README b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/misc/smarty_icon.README
new file mode 100644
index 00000000..bea956fc
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/misc/smarty_icon.README
@@ -0,0 +1,6 @@
+Feel free to put the smarty icon on your site.
+You can cut-and-paste the following code, be sure
+to adjust the path to the image:
+
+<a href="http://smarty.php.net/">
+<img src="smarty_icon.gif" border="0" height="31" width="88" /></a>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/misc/smarty_icon.gif b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/misc/smarty_icon.gif
new file mode 100644
index 00000000..5d519699
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/Smarty-2.6.0/misc/smarty_icon.gif
Binary files differ
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/TutorialHighlightParser.inc b/buildscripts/PhpDocumentor/phpDocumentor/TutorialHighlightParser.inc
new file mode 100644
index 00000000..ff7160ce
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/TutorialHighlightParser.inc
@@ -0,0 +1,491 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2004 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+/**
+ * Source Code Highlighting
+ *
+ * The classes in this file are responsible for the dynamic @example, and
+ * <programlisting role="tutorial"> tags output. Using the
+ * WordParser, the phpDocumentor_TutorialHighlightParser
+ * retrieves PHP tokens one by one from the array generated by
+ * {@link WordParser} source retrieval functions
+ * and then highlights them individually.
+ *
+ * It accomplishes this highlighting through the assistance of methods in
+ * the output Converter passed to its parse() method, and then returns the
+ * fully highlighted source as a string
+ * @tutorial tags.example.pkg, tags.filesource.pkg
+ * @package phpDocumentor
+ * @subpackage Parsers
+ * @since 1.3.0
+ */
+
+/**
+ * Highlights source code using {@link parse()}
+ * @package phpDocumentor
+ * @subpackage Parsers
+ */
+class phpDocumentor_TutorialHighlightParser extends Parser
+{
+ /**#@+ @access private */
+ /**
+ * Highlighted source is built up in this string
+ * @var string
+ */
+ var $_output;
+ /**
+ * contents of the current source code line as it is parsed
+ * @var string
+ */
+ var $_line;
+ /**
+ * Used to retrieve highlighted tokens
+ * @var Converter a descendant of Converter
+ */
+ var $_converter;
+ /**
+ * Path to file being highlighted, if this is from a @filesource tag
+ * @var false|string full path
+ */
+ var $_filesourcepath;
+ /**
+ * @var array
+ */
+ var $eventHandlers = array(
+ TUTORIAL_EVENT_NOEVENTS => 'defaultHandler',
+ TUTORIAL_EVENT_ITAG => 'defaultHandler',
+ TUTORIAL_EVENT_ATTRIBUTE => 'attrHandler',
+ TUTORIAL_EVENT_OPENTAG => 'defaultHandler',
+ TUTORIAL_EVENT_CLOSETAG => 'defaultHandler',
+ TUTORIAL_EVENT_ENTITY => 'defaultHandler',
+ TUTORIAL_EVENT_COMMENT => 'defaultHandler',
+ TUTORIAL_EVENT_SINGLEQUOTE => 'defaultHandler',
+ TUTORIAL_EVENT_DOUBLEQUOTE => 'defaultHandler',
+ );
+ /**#@-*/
+
+ /**
+ * @uses Converter::SourceLine() encloses {@link $_line} in a
+ * converter-specific format
+ */
+ function newLineNum()
+ {
+ $this->_line .= $this->_converter->flushHighlightCache();
+ $this->_output .= $this->_converter->SourceLine($this->_pv_curline + 1, $this->_line, $this->_path);
+ $this->_line = '';
+ }
+
+ /**
+ * Start the parsing at a certain line number
+ */
+ function setLineNum($num)
+ {
+ $this->_wp->linenum = $num;
+ }
+
+ /**
+ * Parse a new file
+ *
+ * The parse() method is a do...while() loop that retrieves tokens one by
+ * one from the {@link $_event_stack}, and uses the token event array set up
+ * by the class constructor to call event handlers.
+ *
+ * The event handlers each process the tokens passed to them, and use the
+ * {@link _addoutput()} method to append the processed tokens to the
+ * {@link $_line} variable. The word parser calls {@link newLineNum()}
+ * every time a line is reached.
+ *
+ * In addition, the event handlers use special linking functions
+ * {@link _link()} and its cousins (_classlink(), etc.) to create in-code
+ * hyperlinks to the documentation for source code elements that are in the
+ * source code.
+ *
+ * @uses setupStates() initialize parser state variables
+ * @uses configWordParser() pass $parse_data to prepare retrieval of tokens
+ * @param string
+ * @param Converter
+ * @param false|string full path to file with @filesource tag, if this
+ * is a @filesource parse
+ * @param false|integer starting line number from {@}source linenum}
+ * @staticvar integer used for recursion limiting if a handler for
+ * an event is not found
+ * @return bool
+ */
+ function parse ($parse_data, &$converter, $filesourcepath = false, $linenum = false)
+ {
+ static $endrecur = 0;
+ $parse_data = str_replace(array("\r\n", "\t"), array("\n", ' '), $parse_data);
+ $this->_converter = &$converter;
+ $converter->startHighlight();
+ $this->_path = $filesourcepath;
+ $this->setupStates($parse_data);
+
+ $this->configWordParser(TUTORIAL_EVENT_NOEVENTS);
+ if ($linenum !== false) $this->setLineNum($linenum);
+ // initialize variables so E_ALL error_reporting doesn't complain
+ $pevent = 0;
+ $word = 0;
+
+ do
+ {
+ $lpevent = $pevent;
+ $pevent = $this->_event_stack->getEvent();
+ if ($lpevent != $pevent)
+ {
+ $this->_last_pevent = $lpevent;
+ $this->configWordParser($pevent);
+ }
+ $this->_wp->setWhitespace(true);
+
+ $dbg_linenum = $this->_wp->linenum;
+ $dbg_pos = $this->_wp->getPos();
+ $this->_pv_last_word = $word;
+ $this->_pv_curline = $this->_wp->linenum;
+ $word = $this->_wp->getWord();
+
+ if (0)//PHPDOCUMENTOR_DEBUG == true)
+ {
+ echo "LAST: ";
+ echo "|" . $this->_pv_last_word;
+ echo "|\n";
+ echo "PEVENT: " . $this->getParserEventName($pevent) . "\n";
+ echo "LASTPEVENT: " . $this->getParserEventName($this->_last_pevent) . "\n";
+// echo "LINE: ".$this->_line."\n";
+// echo "OUTPUT: ".$this->_output."\n";
+ echo $dbg_linenum.'-'.$dbg_pos . ": ";
+ echo '|'.htmlspecialchars($word);
+ echo "|\n";
+ echo "-------------------\n\n\n";
+ flush();
+ }
+ if (isset($this->eventHandlers[$pevent]))
+ {
+ $handle = $this->eventHandlers[$pevent];
+ $this->$handle($word, $pevent);
+ } else
+ {
+ debug('WARNING: possible error, no handler for event number '.$pevent);
+ if ($endrecur++ == 25)
+ {
+ die("FATAL ERROR, recursion limit reached");
+ }
+ }
+ } while (!($word === false));
+ if (strlen($this->_line)) $this->newLineNum();
+ return $this->_output;
+ }
+
+ /**#@+
+ * Event Handlers
+ *
+ * All Event Handlers use {@link checkEventPush()} and
+ * {@link checkEventPop()} to set up the event stack and parser state.
+ * @access private
+ * @param string|array token value
+ * @param integer parser event from {@link Parser.inc}
+ */
+ /**
+ * Most tokens only need highlighting, and this method handles them
+ */
+ function defaultHandler($word, $pevent)
+ {
+ if ($word == "\n") {
+ $this->newLineNum();
+ return;
+ }
+ if ($this->checkEventPush($word, $pevent)) {
+ $this->_wp->backupPos($word);
+ return;
+ }
+ $this->_addoutput($word);
+ $this->checkEventPop($word, $pevent);
+ }
+
+ /**
+ * Most tokens only need highlighting, and this method handles them
+ */
+ function attrHandler($word, $pevent)
+ {
+ if ($word == "\n") {
+ $this->newLineNum();
+ return;
+ }
+ if ($e = $this->checkEventPush($word, $pevent)) {
+ if ($e == TUTORIAL_EVENT_SINGLEQUOTE || $e == TUTORIAL_EVENT_DOUBLEQUOTE) {
+ $this->_addoutput($word);
+ }
+ return;
+ }
+ if ($this->checkEventPop($word, $pevent)) {
+ $this->_wp->backupPos($word);
+ return;
+ }
+ $this->_addoutput($word);
+ }
+
+ /**#@+
+ * Output Methods
+ * @access private
+ */
+ /**
+ * This method adds output to {@link $_line}
+ *
+ * If a string with variables like "$test this" is present, then special
+ * handling is used to allow processing of the variable in context.
+ * @see _flush_save()
+ */
+ function _addoutput($word, $preformatted = false)
+ {
+ $type =
+ array(
+ TUTORIAL_EVENT_ATTRIBUTE => 'attribute',
+ TUTORIAL_EVENT_SINGLEQUOTE => 'attributevalue',
+ TUTORIAL_EVENT_DOUBLEQUOTE => 'attributevalue',
+ TUTORIAL_EVENT_CLOSETAG => 'closetag',
+ TUTORIAL_EVENT_ENTITY => 'entity',
+ TUTORIAL_EVENT_ITAG => 'itag',
+ TUTORIAL_EVENT_OPENTAG => 'opentag',
+ TUTORIAL_EVENT_COMMENT => 'comment',
+ );
+ $a = $this->_event_stack->getEvent();
+ if (in_array($a, array_keys($type))) {
+ $this->_line .= $this->_converter->highlightTutorialSource($type[$a], $word);
+ } else {
+ $this->_line .= $this->_converter->flushHighlightCache();
+ $this->_line .= $word;
+ }
+ }
+ /**#@-*/
+
+ /**
+ * tell the parser's WordParser {@link $wp} to set up tokens to parse words by.
+ * tokens are word separators. In English, a space or punctuation are examples of tokens.
+ * In PHP, a token can be a ;, a parenthesis, or even the word "function"
+ * @param $value integer an event number
+ * @see WordParser
+ */
+
+ function configWordParser($e)
+ {
+ $this->_wp->setSeperator($this->tokens[($e + 100)]);
+ }
+ /**
+ * this function checks whether parameter $word is a token for pushing a new event onto the Event Stack.
+ * @return mixed returns false, or the event number
+ */
+
+ function checkEventPush($word,$pevent)
+ {
+ $e = false;
+ if (isset($this->pushEvent[$pevent]))
+ {
+ if (isset($this->pushEvent[$pevent][strtolower($word)]))
+ $e = $this->pushEvent[$pevent][strtolower($word)];
+ }
+ if ($e)
+ {
+ $this->_event_stack->pushEvent($e);
+ return $e;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * this function checks whether parameter $word is a token for popping the current event off of the Event Stack.
+ * @return mixed returns false, or the event number popped off of the stack
+ */
+
+ function checkEventPop($word,$pevent)
+ {
+ if (!isset($this->popEvent[$pevent])) return false;
+ if (in_array(strtolower($word),$this->popEvent[$pevent]))
+ {
+ return $this->_event_stack->popEvent();
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Initialize all parser state variables
+ * @param boolean true if we are highlighting an inline {@}source} tag's
+ * output
+ * @param false|string name of class we are going to start from
+ * @uses $_wp sets to a new {@link phpDocumentor_HighlightWordParser}
+ */
+ function setupStates($parsedata)
+ {
+ $this->_output = '';
+ $this->_line = '';
+ unset($this->_wp);
+ $this->_wp = new WordParser;
+ $this->_wp->setup($parsedata);
+ $this->_event_stack = new EventStack;
+ $this->_event_stack->popEvent();
+ $this->_event_stack->pushEvent(TUTORIAL_EVENT_NOEVENTS);
+ $this->_pv_linenum = null;
+ $this->_pv_next_word = false;
+ }
+
+ /**
+ * Initialize the {@link $tokenpushEvent, $wordpushEvent} arrays
+ */
+ function phpDocumentor_TutorialHighlightParser()
+ {
+ $this->allowableInlineTags = $GLOBALS['_phpDocumentor_inline_tutorial_tags_allowed'];
+ $this->inlineTagHandlers = array('*' => 'handleDefaultInlineTag');
+ $this->tokens[STATE_TUTORIAL_NOEVENTS] = array("\n",'{@', '<!--', '</', '<', '&');
+ $this->tokens[STATE_TUTORIAL_ITAG] = array("\n","}");
+ $this->tokens[STATE_TUTORIAL_OPENTAG] = array("\n","\t"," ", '>', '/>');
+ $this->tokens[STATE_TUTORIAL_CLOSETAG] = array("\n",'>');
+ $this->tokens[STATE_TUTORIAL_COMMENT] = array("\n",'-->');
+ $this->tokens[STATE_TUTORIAL_ENTITY] = array("\n",';');
+ $this->tokens[STATE_TUTORIAL_ATTRIBUTE] = array("\n",'"',"'",'>','/>');
+ $this->tokens[STATE_TUTORIAL_DOUBLEQUOTE] = array("\n",'"','&','{@');
+ $this->tokens[STATE_TUTORIAL_SINGLEQUOTE] = array("\n","'",'&','{@');
+/**************************************************************/
+
+ $this->pushEvent[TUTORIAL_EVENT_NOEVENTS] =
+ array(
+ "{@" => TUTORIAL_EVENT_ITAG,
+ '<' => TUTORIAL_EVENT_OPENTAG,
+ '</' => TUTORIAL_EVENT_CLOSETAG,
+ '&' => TUTORIAL_EVENT_ENTITY,
+ '<!--' => TUTORIAL_EVENT_COMMENT,
+ );
+/**************************************************************/
+
+ $this->pushEvent[TUTORIAL_EVENT_OPENTAG] =
+ array(
+ " " => TUTORIAL_EVENT_ATTRIBUTE,
+ "\n" => TUTORIAL_EVENT_ATTRIBUTE,
+ );
+/**************************************************************/
+
+ $this->pushEvent[TUTORIAL_EVENT_ATTRIBUTE] =
+ array(
+ "'" => TUTORIAL_EVENT_SINGLEQUOTE,
+ '"' => TUTORIAL_EVENT_DOUBLEQUOTE,
+ );
+/**************************************************************/
+
+ $this->pushEvent[TUTORIAL_EVENT_SINGLEQUOTE] =
+ array(
+ '&' => TUTORIAL_EVENT_ENTITY,
+ '{@' => TUTORIAL_EVENT_ITAG,
+ );
+/**************************************************************/
+
+ $this->pushEvent[TUTORIAL_EVENT_DOUBLEQUOTE] =
+ array(
+ '&' => TUTORIAL_EVENT_ENTITY,
+ '{@' => TUTORIAL_EVENT_ITAG,
+ );
+/**************************************************************/
+
+ $this->popEvent[TUTORIAL_EVENT_ENTITY] = array(';');
+/**************************************************************/
+
+ $this->popEvent[TUTORIAL_EVENT_SINGLEQUOTE] = array("'");
+/**************************************************************/
+
+ $this->popEvent[TUTORIAL_EVENT_DOUBLEQUOTE] = array('"');
+/**************************************************************/
+
+ $this->popEvent[TUTORIAL_EVENT_OPENTAG] = array('>', '/>');
+/**************************************************************/
+
+ $this->popEvent[TUTORIAL_EVENT_CLOSETAG] = array('>');
+/**************************************************************/
+
+ $this->popEvent[TUTORIAL_EVENT_COMMENT] = array('-->');
+/**************************************************************/
+
+ $this->popEvent[TUTORIAL_EVENT_ATTRIBUTE] = array('>','/>');
+/**************************************************************/
+
+ $this->popEvent[TUTORIAL_EVENT_ITAG] = array('}');
+/**************************************************************/
+ }
+
+ function getParserEventName ($value)
+ {
+ $lookup = array(
+ TUTORIAL_EVENT_NOEVENTS => "TUTORIAL_EVENT_NOEVENTS",
+ TUTORIAL_EVENT_ITAG => "TUTORIAL_EVENT_ITAG",
+ TUTORIAL_EVENT_OPENTAG => "TUTORIAL_EVENT_OPENTAG",
+ TUTORIAL_EVENT_ATTRIBUTE => "TUTORIAL_EVENT_ATTRIBUTE",
+ TUTORIAL_EVENT_CLOSETAG => "TUTORIAL_EVENT_CLOSETAG",
+ TUTORIAL_EVENT_ENTITY => "TUTORIAL_EVENT_ENTITY",
+ TUTORIAL_EVENT_COMMENT => "TUTORIAL_EVENT_COMMENT",
+ TUTORIAL_EVENT_SINGLEQUOTE => "TUTORIAL_EVENT_SINGLEQUOTE",
+ TUTORIAL_EVENT_DOUBLEQUOTE => "TUTORIAL_EVENT_DOUBLEQUOTE",
+ );
+ if (isset($lookup[$value]))
+ return $lookup[$value];
+ else return $value;
+ }
+}
+
+
+/** starting state */
+define("TUTORIAL_EVENT_NOEVENTS" , 1);
+/** currently in starting state */
+define("STATE_TUTORIAL_NOEVENTS" , 101);
+
+/** used when an {@}inline tag} is found */
+define("TUTORIAL_EVENT_ITAG" , 2);
+/** currently parsing an {@}inline tag} */
+define("STATE_TUTORIAL_ITAG" , 102);
+
+/** used when an open <tag> is found */
+define("TUTORIAL_EVENT_OPENTAG" , 3);
+/** currently parsing an open <tag> */
+define("STATE_TUTORIAL_OPENTAG" , 103);
+
+/** used when a <tag attr="attribute"> is found */
+define("TUTORIAL_EVENT_ATTRIBUTE" , 4);
+/** currently parsing an open <tag> */
+define("STATE_TUTORIAL_ATTRIBUTE" , 104);
+
+/** used when a close </tag> is found */
+define("TUTORIAL_EVENT_CLOSETAG" , 5);
+/** currently parsing a close </tag> */
+define("STATE_TUTORIAL_CLOSETAG" , 105);
+
+/** used when an &entity; is found */
+define("TUTORIAL_EVENT_ENTITY" , 6);
+/** currently parsing an &entity; */
+define("STATE_TUTORIAL_ENTITY" , 106);
+
+/** used when a <!-- comment --> is found */
+define("TUTORIAL_EVENT_COMMENT" , 7);
+/** currently parsing a <!-- comment --> */
+define("STATE_TUTORIAL_COMMENT" , 107);
+
+/** used when a <!-- comment --> is found */
+define("TUTORIAL_EVENT_SINGLEQUOTE" , 8);
+/** currently parsing a <!-- comment --> */
+define("STATE_TUTORIAL_SINGLEQUOTE" , 108);
+
+/** used when a <!-- comment --> is found */
+define("TUTORIAL_EVENT_DOUBLEQUOTE" , 9);
+/** currently parsing a <!-- comment --> */
+define("STATE_TUTORIAL_DOUBLEQUOTE" , 109);
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/WordParser.inc b/buildscripts/PhpDocumentor/phpDocumentor/WordParser.inc
new file mode 100644
index 00000000..e0853370
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/WordParser.inc
@@ -0,0 +1,325 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * @author Joshua Eichorn <jeichorn@phpdoc.org>
+ * @version $Id: WordParser.inc,v 1.1 2005/10/17 18:36:57 jeichorn Exp $
+ * @package phpDocumentor
+ * @subpackage WordParsers
+ */
+/**
+ * Retrieves tokens from source code for use by the Parser
+ * @see Parser
+ * @author Joshua Eichorn <jeichorn@phpdoc.org>
+ * @version $Id: WordParser.inc,v 1.1 2005/10/17 18:36:57 jeichorn Exp $
+ * @package phpDocumentor
+ * @subpackage WordParsers
+ */
+class WordParser
+{
+ /*
+ New lines around the world
+ Macintosh: \r
+ Unix : \n
+ Windows : \r\n
+ */
+
+ /**#@+
+ * @access private
+ */
+ /**
+ * List of text that separates tokens, used to retrieve tokens
+ * @var array
+ */
+ var $wordseperators = array();
+
+ /**
+ * Position within input of the cursor pointing to the next text to be
+ * retrieved as a token
+ * @var integer
+ */
+ var $pos = 0;
+
+ /**
+ * Size of the input source code
+ * @var integer
+ */
+ var $size;
+
+ /**
+ * Source code
+ * @var string
+ */
+ var $data;
+
+ var $cache;
+ /**
+ * Current line number
+ * @var integer
+ */
+ var $linenum = 0;
+ /**
+ * Position the cursor was at the last time line numbers were counted, used
+ * to guarantee that line numbers are incremented
+ * @var integer
+ */
+ var $linenumpos = 0;
+
+ /**
+ * Used for {@}source} tag, contains currently parsed function source
+ * @var string
+ */
+ var $source = '';
+ /**
+ * flag, determines whether tokens are added to {@link $source}
+ * @var boolean
+ */
+ var $getsource = false;
+
+ /**
+ * If true, then white space is returned as a part of tokens, otherwise
+ * tokens are trimmed
+ * @var boolean
+ */
+ var $returnWhiteSpace = false;
+ /**#@-*/
+
+ /**
+ * Initialize the WordParser
+ * @param string source code
+ */
+ function setup(&$input)
+ {
+ $this->size = strlen($input);
+ $this->data = & $input;
+ $this->pos = 0;
+ $this->linenum = 0;
+ $this->linenumpos = 0;
+ $this->cache = array();
+ //$this->run = 0;
+ //$this->word = WORD_PARSER_RET_WORD;
+ }
+
+ /**
+ * Retrieve source code for the last function/method
+ * @return string
+ */
+ function getSource()
+ {
+ $source = $this->source;
+ $this->source = '';
+ $this->getsource = false;
+ return $source;
+ }
+
+ /**
+ * Used to tell the WordParser to start retrieving source code
+ * @access private
+ */
+ function retrievesource($word = '')
+ {
+ $this->source = $word;
+ $this->getsource = true;
+ }
+
+ /**
+ * Retrieve a token from the token list
+ *
+ * The {@link Parser} class relies upon this method to retrieve the next
+ * token. The {@link $wordseperators} array is a collection of strings
+ * that delineate tokens for the current parser state. $wordseperators
+ * is set by the parser with a call to {@link Parser::configWordParser()}
+ * every time a new parser state is reached.
+ *
+ * For example, while parsing the source code for a class, the word
+ * <code>var</code> is a token, and <code>global</code> is not,
+ * but inside a function, the reverse is true. The parser state
+ * {@link PARSER_STATE_CLASS} has a token list that includes whitespace,
+ * code delimiters like ; and {}, and comment/DocBlock indicators
+ *
+ * If the whitespace option has been turned off using
+ * {@link setWhitespace()}, then no whitespace is returned with tokens
+ *
+ * {@internal
+ * In the first segment of the function, the code attempts to find the next
+ * token. A cache is used to speed repetitious tasks. The $tpos variable
+ * is used to hold the position of the next token. $npos is used to
+ * hold the end of the token, and so $npos - $tpos will give the length
+ * of the token. This is used to allow tokens that contain whitespace,
+ * should that option be desired.
+ *
+ * {@link $data} is of course the string containing the PHP code to be
+ * parsed, and {@link $pos} is the cursor, or current location within the
+ * parsed data.
+ * }}
+ * @return string|false the next token, an empty string if there are no
+ * token separators in the $wordseperators array,
+ * or false if the end of input has been reached
+ */
+ function getWord()
+ {
+ //$st = $this->mtime();
+ if ($this->size == $this->pos)
+ {
+ return false;
+ }
+
+ // assume, for starting, that the token is from $this->pos to the end
+ $npos = $this->size;
+ if (is_array($this->wordseperators))
+ {
+ //$this->wordseperators = array();
+ foreach($this->wordseperators as $sep)
+ {
+ // cache is set if this separator has been tested
+ if (isset($this->cache[$sep]))
+ $tpos = $this->cache[$sep];
+ else
+ $tpos = false;
+ if ($tpos < $this->pos || !is_int($tpos))
+ {
+ // find the position of the next token separator
+ $tpos = strpos($this->data,$sep,$this->pos);
+ }
+
+ // was a token separator found that is closer to the current
+ // location?
+ if ( ($tpos < $npos) && !($tpos === false))
+ {
+ //echo trim($sep) . "=$tpos\n";
+ // set the length of the token to be from $this->pos to
+ // the next token separator
+ $npos = $tpos;
+ $seplen = strlen($sep);
+ }
+ else if (!($tpos === false))
+ {
+ $this->cache[$sep] = $tpos;
+ }
+ }
+ } else {
+ // no token separators, tell the parser to choose a new state
+ return "";
+ }
+
+ $len = $npos - $this->pos;
+ if ($len == 0)
+ {
+ $len = $seplen;
+ }
+
+ //$st3 = $this->mtime();
+ $word = substr($this->data,$this->pos,$len);
+
+ // Change random other os newlines to the unix one
+ if ($word == "\r" || $word == "\r\n")
+ {
+ $word = "\n";
+ }
+
+ if ($this->linenumpos <= $this->pos)
+ {
+ $this->linenumpos = $this->pos + $len;
+ $this->linenum += count(explode("\n",$word)) - 1;
+ }
+
+ if ($this->getsource)
+ {
+ $this->source .= $word;
+ }
+ $this->pos = $this->pos + $len;
+ //$this->word = WORD_PARSER_RET_SEP;
+
+ // Things like // commenats rely on the newline to find their end so im going to have to return them
+ // never return worthless white space /t ' '
+ if ($this->returnWhiteSpace == false)
+ {
+ if (strlen(trim($word)) == 0 && $word != "\n")
+ {
+ $word = $this->getWord();
+ }
+ }
+ //$this->time3 = $this->time3 + ($this->mtime() - $st3);
+ //$this->time = $this->time + ($this->mtime() - $st);
+ return $word;
+ }
+
+
+ /**
+ * Returns the current pointer position, or 1 character after the end of the word
+ */
+ function getPos()
+ {
+ return $this->pos;
+ }
+
+ /**
+ * Unused
+ *
+ * {@source}
+ * @param integer starting position
+ * @param integer length of block to retrieve
+ */
+ function getBlock($start,$len)
+ {
+ return substr($this->data,$start,$len);
+ }
+
+ /**
+ * @uses $wordseperators
+ * @param array array of strings that separate tokens
+ */
+ function setSeperator(&$seps)
+ {
+ $this->wordseperators = &$seps;
+ }
+
+ /**
+ * Set the internal cursor within the source code
+ * @param integer
+ */
+ function setPos($pos)
+ {
+ $this->pos = $pos;
+ }
+
+ /**
+ * Backup to the previous token so that it can be retrieved again in a new
+ * context.
+ *
+ * Occasionally, a word will be passed to an event handler that should be
+ * handled by another event handler. This method allows that to happen.
+ * @param string token to back up to
+ */
+ function backupPos($word)
+ {
+ if ($this->getsource) $this->source = substr($this->source,0,strlen($this->source) - 1);
+ $this->pos = $this->pos - strlen($word);
+ }
+
+ /**
+ * set parser to return or strip whitespace
+ * @param boolean
+ */
+ function setWhitespace($val = false)
+ {
+ $this->returnWhiteSpace = $val;
+ }
+}
+?>
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/XMLpackagePageParser.inc b/buildscripts/PhpDocumentor/phpDocumentor/XMLpackagePageParser.inc
new file mode 100644
index 00000000..59a3f557
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/XMLpackagePageParser.inc
@@ -0,0 +1,554 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * @package phpDocumentor
+ * @subpackage Parsers
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.2
+ */
+/** when <programlisting> is found */
+define('PHPDOCUMENTOR_PDP_EVENT_PROGRAMLISTING', 600);
+/** when <programlisting> is found */
+define('PHPDOCUMENTOR_PDP_STATE_PROGRAMLISTING', 700);
+/** when a DocBook <tag> is found */
+define('PHPDOCUMENTOR_PDP_EVENT_TAG', 601);
+/** when a DocBook <tag> is found */
+define('PHPDOCUMENTOR_PDP_STATE_TAG', 701);
+/** when <![CDATA[ ]]> is found */
+define('PHPDOCUMENTOR_PDP_EVENT_CDATA', 602);
+/** when <![CDATA[ ]]> is found */
+define('PHPDOCUMENTOR_PDP_STATE_CDATA', 702);
+/** when tag attributes name="value" are found */
+define('PHPDOCUMENTOR_PDP_EVENT_ATTRIBUTES', 603);
+/** when tag attributes name="value" are found */
+define('PHPDOCUMENTOR_PDP_STATE_ATTRIBUTES', 703);
+/** when tag attributes name="value" are found */
+define('PHPDOCUMENTOR_PDP_EVENT_ENTITY', 604);
+/** when tag attributes name="value" are found */
+define('PHPDOCUMENTOR_PDP_STATE_ENTITY', 704);
+
+/**
+ * Used to parse XML DocBook-based tutorials
+ * @package phpDocumentor
+ * @subpackage Parsers
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @since 1.2
+ */
+class XMLPackagePageParser extends Parser
+{
+ /** @var array */
+ var $eventHandlers = array(
+ PHPDOCUMENTOR_PDP_EVENT_TAG => 'handleTag',
+ PHPDOCUMENTOR_PDP_EVENT_ATTRIBUTES => 'handleAttributes',
+ PHPDOCUMENTOR_PDP_EVENT_CDATA => 'handleCData',
+ PARSER_EVENT_NOEVENTS => 'defaultHandler',
+ PARSER_EVENT_COMMENTBLOCK => 'ignoreHandler',
+ PARSER_EVENT_OUTPHP => 'ignoreHandler',
+ PARSER_EVENT_QUOTE => 'handleQuote',
+ PHPDOCUMENTOR_PDP_EVENT_ENTITY => 'handleEntity',
+ );
+
+ /**
+ * @var array
+ */
+ var $pars = array();
+
+ var $refsect1id = false;
+ var $refsect2id = false;
+ var $refsect3id = false;
+ /**
+ * @var array the tag stack
+ */
+ var $context;
+ /**#@+ @access private */
+ var $_gettoc = false;
+ var $_toc = array();
+ var $_cursection = 0;
+ /**#@-*/
+ /**
+ * Set up the wordparser
+ *
+ * {@source}
+ * @uses ObjectWordParser
+ */
+ function XMLPackagePageParser()
+ {
+ $this->wp = new ObjectWordParser(true);
+ }
+ /**
+ * Parse a new file
+ *
+ * @param string $parse_data
+ * @param array $tutorial for format, see {@link Io::getTutorials()}
+ * @staticvar integer used for recursion limiting if a handler for an event is not found
+ * @return bool
+ * @uses parserTutorial using {@link Publisher::PublishEvent()}, a new tutorial
+ * is created from the file parsed, and passed to the
+ * Intermediate Parser
+ */
+ function parse ($parse_data, $tutorial)
+ {
+ $tempparse = new ppageParser;
+ $parse_data = $tempparse->parse($parse_data,true,$tutorial['package'],$tutorial['subpackage'],
+ basename($tutorial['path']),$tutorial['category'], $tutorial['path']);
+ unset($tempparse);
+ static $endrecur = 0;
+ if (!is_array($parse_data) || count($parse_data) == 0)
+ {
+ return false;
+ }
+ $this->setupStates();
+
+ // initialize variables so E_ALL error_reporting doesn't complain
+ $pevent = 0;
+ $word = 0;
+ $this->p_vars['start'] = true;
+ $this->p_vars['event_stack'] = new EventStack;
+
+ $this->wp->setup($parse_data,false);
+ $this->wp->setWhitespace(true);
+ $this->context = array();
+ if (isset($this->curtag)) unset($this->curtag);
+
+ do
+ {
+ $lpevent = $pevent;
+ $pevent = $this->p_vars['event_stack']->getEvent();
+ if ($lpevent != $pevent)
+ {
+ $this->p_vars['last_pevent'] = $lpevent;
+ }
+
+ if ($this->p_vars['last_pevent'] != $pevent)
+ {
+ // its a new event so the word parser needs to be reconfigured
+ $this->configWordParser($pevent);
+ }
+
+
+ $this->p_vars['last_word'] = $word;
+ $word = $this->wp->getWord();
+
+ if (0)//PHPDOCUMENTOR_DEBUG == true)
+ {
+ echo "----------------\n";
+ echo "LAST: |" . $this->p_vars['last_word'] . "|\n";
+// echo "INDEX: ".$this->p_vars['curpar']."\n";
+ echo "PEVENT: " . $this->getParserEventName($pevent) . "\n";
+ echo "LASTPEVENT: " . $this->getParserEventName($this->p_vars['last_pevent']) . "\n";
+ echo $this->wp->getPos() . " WORD: |$word|\n\n";
+// echo '"'.$this->p_vars['quote_data']."\"\n";
+ }
+ if (isset($this->eventHandlers[$pevent]))
+ {
+ $handle = $this->eventHandlers[$pevent];
+ if ($word !== false) $this->$handle($word, $pevent);
+ } else
+ {
+ debug('WARNING: possible error, no XMLPackagePageParser handler for event number '.$pevent);
+ if ($endrecur++ == 25)
+ {
+ die("FATAL ERROR, recursion limit reached");
+ }
+ }
+ $this->p_vars['start'] = false;
+ } while (!($word === false));
+ if (count($this->_toc) && isset($this->p_vars['toc']))
+ {
+ $a = $this->curtag->getTOC($this->p_vars['toc']);
+ $a->setTOC($this->_toc);
+ $a->setPath($tutorial['path']);
+ $this->curtag->setTOC($this->p_vars['toc'],$a);
+ }
+ $this->PublishEvent(PHPDOCUMENTOR_EVENT_TUTORIAL,new parserTutorial($this->curtag, $tutorial));
+ return $this->curtag;
+ }
+
+ /**#@+
+ * @access private
+ * @param string|parserInlineTag token
+ * @param integer parser event
+ */
+ function defaultHandler($word, $pevent)
+ {
+ if (is_string($word) && $this->checkEventPush($word, $pevent))
+ {
+ return;
+ }
+ }
+
+ function ignoreHandler($word, $pevent)
+ {
+ $this->checkEventPop($word, $pevent);
+ }
+
+ /**
+ * handler for QUOTE.
+ * this handler recognizes strings defined with double quotation marks (") and handles them correctly
+ * in any place that they legally appear in php code
+ */
+
+ function handleQuote($word, $pevent)
+ {
+ if ($this->p_flags['reset_quote_data'] === true)
+ {
+ $this->p_flags['reset_quote_data'] = false;
+ $this->p_vars['quote_data'] = "";
+ }
+ if (!is_object($word)) $this->checkEventPush( $word, $pevent);
+ if ($word != "\"")
+ {
+ if (is_object($word))
+ {
+ $this->p_vars['quote_data'] = $word;
+ }
+ else
+ {
+ if (!is_object($this->p_vars['quote_data']))
+ $this->p_vars['quote_data'] .= $word;
+ }
+ }
+ if (!is_object($word))
+ {
+ if ($word == '>')
+ {
+ if (is_object($this->p_vars['quote_data'])) $this->p_vars['quote_data'] = '{@id '.$this->p_vars['quote_data']->id.'}';
+ addErrorDie(PDERROR_UNTERMINATED_ATTRIB,$this->curtag->name,$this->p_vars['attrname'],$this->p_vars['quote_data']);
+ }
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->p_flags['reset_quote_data'] = true;
+ }
+ }
+ }
+
+ /**
+ * Handles all XML DocBook tags
+ */
+ function handleTag($word, $pevent)
+ {
+ if (isset($this->curtag) && $this->curtag->hasTitle() && $this->_gettoc && $this->_gettoc->name == $this->curtag->name)
+ {
+ if (isset($this->_toc[$this->_cursection]))
+ {
+ $this->_toc[$this->_cursection]['title'] = $this->curtag->_title;
+ $this->_cursection++;
+ }
+ $this->_gettoc = false;
+ }
+ if ($this->p_vars['last_word'] == '<')
+ { // get tag name
+ $this->p_flags['begin_tag'] = true;
+ array_push($this->context,$word);
+// if (isset($this->curtag)) debug("pushed ".$this->curtag->name);
+ if (isset($this->curtag))
+ {
+ array_push($this->pars,$this->curtag);
+ }
+ $this->curtag = new parserXMLDocBookTag($word);
+ } elseif ($this->p_vars['last_word'] == '</' || $word == '/>')
+ {
+ $tag = array_pop($this->context);
+ if ($word == '/>') {
+ // all is OK
+ $this->checkEventPop($word, $pevent);
+ $word = $tag;
+ }
+ if ($tag != $word)
+ {
+ addErrorDie(PDERROR_UNMATCHED_TUTORIAL_TAG,$tag,$word,$this->curtag->getString());
+ }
+ if (in_array($this->curtag->name, array('refentry', 'refsect1', 'refsect2', 'refsect3')))
+ {
+ if (!isset($this->curtag->_id))
+ {
+ $title = '';
+ if (isset($this->curtag->_title))
+ {
+ $title = $this->curtag->_title->getString();
+ }
+ addWarning(PDERROR_NO_DOCBOOK_ID, $this->curtag->name, $title);
+ }
+ }
+ $this->p_flags['begin_tag'] = false;
+ $curtag = @array_pop($this->pars);
+// debug("popped $tag ".$curtag->name.' I am '.$this->curtag->name);
+ if ($curtag)
+ {
+ if ($this->curtag->name == 'refsect1') $this->refsect1id = false;
+ if ($this->curtag->name == 'refsect2') $this->refsect2id = false;
+ if ($this->curtag->name == 'refsect3') $this->refsect3id = false;
+ $curtag->add($this->curtag);
+// debug("added ".$this->curtag->name." to ".$curtag->name.' '.$curtag->id);
+ $this->curtag = $curtag;
+ } else
+ {
+// debug("here");
+ }
+ } elseif (is_string($word))
+ {
+ if (!($e = $this->checkEventPush($word, $pevent)))
+ {
+ if ($this->checkEventPop($word, $pevent))
+ {
+ if ($this->p_flags['begin_tag'])
+ {
+ $this->p_vars['event_stack']->pushEvent(PHPDOCUMENTOR_PDP_EVENT_TAG);
+ $this->p_vars['event_stack']->pushEvent(PHPDOCUMENTOR_PDP_EVENT_CDATA);
+ $this->p_vars['last_tag'] = array_pop($this->context);
+ array_push($this->context,$this->p_vars['last_tag']);
+ $this->p_flags['in_cdata'] = false;
+ }
+ return;
+ }
+ } else
+ {
+ $this->p_flags['start_attr'] = true;
+ $this->p_flags['end_attr'] = false;
+ }
+ } else addErrorDie(PDERROR_CANT_HAVE_INLINE_IN_TAGNAME);
+ }
+
+ /**
+ * Handle CData sections
+ */
+ function handleCData($word, $pevent)
+ {
+ if ($this->curtag->name == 'refentry' && phpDocumentor_get_class($word) == 'parsertocinlinetag')
+ {
+ $this->p_vars['toc'] = $this->curtag->getTOC();
+ }
+ if (is_string($word) && !$this->p_flags['in_cdata'])
+ {
+ if ($this->checkEventPop($word, $pevent))
+ {
+ return;
+ }
+ if ($this->checkEventPush($word, $pevent))
+ {
+ return;
+ }
+ }
+ if ($word == '<![CDATA[')
+ {
+ $this->curtag->startCData();
+ $this->p_flags['in_cdata'] = true;
+ } elseif ($this->p_flags['in_cdata'] && $word == ']]>')
+ {
+ $this->curtag->endCData();
+ $this->p_flags['in_cdata'] = false;
+ } else
+ {
+ if ($this->p_flags['in_cdata'])
+ $this->curtag->addCData($word);
+ else
+ $this->curtag->add($word);
+ }
+ }
+
+ /**
+ * Handle Entities like &rdquo;
+ */
+ function handleEntity($word, $pevent)
+ {
+ if (!$word)
+ {
+ if (!isset($this->p_vars['entity_name']))
+ $this->p_vars['entity_name'] = '';
+ addErrorDie(PDERROR_UNTERMINATED_ENTITY,$this->p_vars['entity_name']);
+ }
+ $e = $this->checkEventPop($word, $pevent);
+ if ($word && !$e) $this->p_vars['entity_name'] = $word;
+ if ($e)
+ {
+ $entity = new parserEntity($this->p_vars['entity_name']);
+ unset($this->p_vars['entity_name']);
+ $this->curtag->add($entity);
+ }
+ }
+
+ /**
+ * Handle Tag attributes name="value"
+ */
+ function handleAttributes($word, $pevent)
+ {
+ if ($this->checkEventPush($word, $pevent)) return;
+ if ($word == '=')
+ {
+ $this->p_flags['start_attr'] = false;
+ $this->p_vars['end_attr'] = true;
+ } else
+ {
+ if ($this->p_flags['start_attr'])
+ {
+ $this->p_vars['attrname'] = $word;
+ } else
+ {
+ if (isset($this->p_vars['attrname']))
+ {
+ $value = $this->p_vars['quote_data'];
+ if (phpDocumentor_get_class($value) == 'parseridinlinetag')
+ { // "inherit" the parent section's id, so
+ // <refsect1 id="{@id test"}> <!-- id is 'test' -->
+ // ...
+ // <refsect2 id="{@id me}"> <!-- id is 'test.me' -->
+ // ...
+ // <refsect3 id="{@id out}"> <!-- id is 'test.me.out' -->
+ // <example id="{@id withexample}"> <!-- id is 'test.me.out.withexample' -->
+ $a = ($this->refsect1id ? $this->refsect1id . '.' : '');
+ $a .= ($this->refsect2id ? $this->refsect2id . '.' : '');
+ $a .= ($this->refsect3id ? $this->refsect3id . '.' : '');
+ if ($this->curtag->name == 'refsect1')
+ {
+ $this->refsect1id = $value->id;
+ }
+ if ($this->curtag->name == 'refsect2')
+ {
+ $this->refsect2id = $value->id;
+ }
+ if ($this->curtag->name == 'refsect3')
+ {
+ $this->refsect3id = $value->id;
+ }
+// debug($value->id.' is now '.$a.$value->id);
+ $value->id = $a . $value->id;
+ if ($value->id != '')
+ {
+ if (isset($this->_toc[$this->_cursection]))
+ {
+ $this->_cursection++;
+ }
+ $this->_toc[$this->_cursection]['id'] = $value;
+ $this->_toc[$this->_cursection]['tag'] = new parserXMLDocBookTag($this->curtag->name);
+// debug("set gettoc to ".$this->curtag->name .' '. $value->id);
+ $this->_gettoc = $this->curtag;
+ }
+ }
+ $this->curtag->addAttribute($this->p_vars['attrname'],$value);
+ unset($this->p_vars['attrname']);
+ $this->p_flags['end_attr'] = false;
+ }
+ }
+ }
+ if (is_string($word) && $this->checkEventPop($word, $pevent))
+ {
+ $this->p_flags['start_attr'] = true;
+ $this->p_flags['end_attr'] = false;
+ $this->wp->setPos($this->wp->getPos() - strlen($word));
+ }
+ }
+ /**#@-*/
+
+ /**
+ * setup the parser tokens, and the pushEvent/popEvent arrays
+ * @see $tokens, $pushEvent, $popEvent
+ */
+
+ function setupStates()
+ {
+ $this->_gettoc = false;
+ $this->_toc = array();
+ $this->_cursection = 0;
+ if (isset($this->p_vars['toc'])) unset($this->p_vars['toc']);
+
+ $this->tokens[STATE_NOEVENTS] = array('</','<','<!--','<?');
+ $this->tokens[STATE_COMMENTBLOCK] = array('-->');
+ $this->tokens[STATE_OUTPHP] = array('?>');
+ $this->tokens[STATE_QUOTE] = array("\\\"","\\\\","\"",'>');
+ $this->tokens[STATE_ESCAPE] = false;// this tells the word parser to just cycle
+ $this->tokens[PHPDOCUMENTOR_PDP_STATE_TAG] = array('>',' ','/>');
+ $this->tokens[PHPDOCUMENTOR_PDP_STATE_CDATA] = array('&','<!--','</','<![CDATA[','<',']]>');
+ $this->tokens[PHPDOCUMENTOR_PDP_STATE_ATTRIBUTES] = array('=','>','/>','"');
+ $this->tokens[PHPDOCUMENTOR_PDP_STATE_ENTITY] = array(';');
+
+ // For each event word to event mapings
+ $this->pushEvent[PARSER_EVENT_NOEVENTS] =
+ array(
+ "<" => PHPDOCUMENTOR_PDP_EVENT_TAG,
+ "</" => PHPDOCUMENTOR_PDP_EVENT_TAG,
+ '<!--' => PARSER_EVENT_COMMENTBLOCK,
+ '<?' => PARSER_EVENT_OUTPHP,
+ '&' => PHPDOCUMENTOR_PDP_EVENT_ENTITY,
+ );
+##########################
+
+ $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_TAG] =
+ array(
+ ' ' => PHPDOCUMENTOR_PDP_EVENT_ATTRIBUTES,
+ );
+
+ $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_TAG] = array(">","/>");
+##########################
+ $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_ATTRIBUTES] =
+ array(
+ '"' => PARSER_EVENT_QUOTE,
+ );
+
+ $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_ATTRIBUTES] = array(">","/>");
+##########################
+
+ $this->popEvent[PARSER_EVENT_COMMENTBLOCK] = array("-->");
+##########################
+ $this->pushEvent[PARSER_EVENT_QUOTE] =
+ array(
+ "\\" => PARSER_EVENT_ESCAPE
+ );
+ $this->popEvent[PARSER_EVENT_QUOTE] = array("\"");
+##########################
+
+ $this->popEvent[PARSER_EVENT_OUTPHP] = array("?>");
+##########################
+
+ $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_ENTITY] = array(";");
+##########################
+
+ $this->pushEvent[PHPDOCUMENTOR_PDP_EVENT_CDATA] =
+ array(
+ "<" => PHPDOCUMENTOR_PDP_EVENT_TAG,
+ '<!--' => PARSER_EVENT_COMMENTBLOCK,
+ '<?' => PARSER_EVENT_OUTPHP,
+ '&' => PHPDOCUMENTOR_PDP_EVENT_ENTITY,
+ );
+ $this->popEvent[PHPDOCUMENTOR_PDP_EVENT_CDATA] = array("</");
+ }
+
+ /**
+ * debugging function
+ *
+ * {@source}
+ * @static
+ */
+ function getParserEventName ($value)
+ {
+ $lookup = array(
+ PARSER_EVENT_NOEVENTS => "PARSER_EVENT_NOEVENTS",
+ PHPDOCUMENTOR_PDP_EVENT_TAG => "PHPDOCUMENTOR_PDP_EVENT_TAG",
+ PHPDOCUMENTOR_PDP_EVENT_ATTRIBUTES => "PHPDOCUMENTOR_PDP_EVENT_ATTRIBUTES",
+ PHPDOCUMENTOR_PDP_EVENT_CDATA => "PHPDOCUMENTOR_PDP_EVENT_CDATA",
+ PHPDOCUMENTOR_PDP_EVENT_LIST => "PHPDOCUMENTOR_PDP_EVENT_LIST",
+ PARSER_EVENT_QUOTE => "PARSER_EVENT_QUOTE",
+ PHPDOCUMENTOR_PDP_EVENT_ENTITY => "PHPDOCUMENTOR_PDP_EVENT_ENTITY",
+ );
+ if (isset($lookup[$value]))
+ return $lookup[$value];
+ else return $value;
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/clone.inc.php b/buildscripts/PhpDocumentor/phpDocumentor/clone.inc.php
new file mode 100644
index 00000000..fbc308ef
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/clone.inc.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * Clone an object in PHP 4
+ * @param object
+ * @return object
+ */
+function phpDocumentor_clone($obj)
+{
+ return $obj;
+}
+
+?> \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/clone5.inc.php b/buildscripts/PhpDocumentor/phpDocumentor/clone5.inc.php
new file mode 100644
index 00000000..20919a99
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/clone5.inc.php
@@ -0,0 +1,14 @@
+<?php
+
+/**
+ * Clone an object in PHP 5
+ * @param object
+ * @return object
+ * @ignore
+ */
+function phpDocumentor_clone($obj)
+{
+ return clone $obj;
+}
+
+?> \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/common.inc.php b/buildscripts/PhpDocumentor/phpDocumentor/common.inc.php
new file mode 100644
index 00000000..787afd67
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/common.inc.php
@@ -0,0 +1,244 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * Common variables/functions used by other files in phpDocumentor
+ * @package phpDocumentor
+ * @filesource
+ */
+/** phpDocumentor version */
+if ('@VER@' != '@'.'VER@')
+{
+ define("PHPDOCUMENTOR_VER","@VER@");
+} else {
+ define("PHPDOCUMENTOR_VER","1.3.0RC4");
+}
+/** phpDocumentor version */
+define("PHPDOCUMENTOR_WEBSITE","http://www.phpdoc.org");
+define('SMART_PATH_DELIMITER', DIRECTORY_SEPARATOR ); // set the correct path delimiter
+define('tokenizer_ext', extension_loaded('tokenizer') && version_compare(phpversion(),"4.3.0",">="));
+// we just replace all the \ with / so that we can just operate on /
+define('PATH_DELIMITER', '/' ); // set the correct path delimiter
+define('PHPDOCUMENTOR_WINDOWS',substr(PHP_OS, 0, 3) == 'WIN');
+define('_IN_PHP5', phpversion() == '5.0.0RC1-dev' || phpversion() == '5.0.0RC2-dev' ||
+ version_compare(phpversion(), '5.0.0', 'ge'));
+if (/*@donotremove@*/0)
+{
+ if (_IN_PHP5) {
+ require_once 'PhpDocumentor/phpDocumentor/clone5.inc.php';
+ } else {
+ require_once 'PhpDocumentor/phpDocumentor/clone.inc.php';
+ }
+} else {
+ if (_IN_PHP5) {
+ require_once dirname(__FILE__) . '/clone5.inc.php';
+ } else {
+ require_once dirname(__FILE__) . '/clone.inc.php';
+ }
+}
+if (isset($_SERVER['argv'])) {
+ $argv = $_SERVER['argv'];
+ $argc = $_SERVER['argc'];
+}
+
+/** used in phpdoc.php and new_phpdoc.php */
+function phpDocumentor_ConfigFileList($directory)
+{
+ $ret = array();
+ if (@is_dir($directory))
+ {
+ $ret = array();
+ $d = @dir($directory); // thanks to Jason E Sweat (jsweat@users.sourceforge.net) for fix
+ while($d && $entry=$d->read())
+ {
+ $getentry = false;
+ if (strcmp($entry,".") != 0 && strcmp($entry,"..") != 0)
+ {
+ if (substr($entry,0,1) != ".") $getentry = true;
+ }
+ if ($getentry == true)
+ {
+ if (strpos($entry,'.ini'))
+ if (is_file($directory . PATH_DELIMITER . $entry))
+ {
+ $ret[] = str_replace('.ini','',$entry);
+ }
+ }
+ }
+ if ($d) $d->close();
+ } else
+ {
+ }
+ return $ret;
+}
+
+
+/**
+ * Parse an .ini file
+ *
+ * Works like {@link parse_ini_file}, except it will take a section like:
+ *
+ * <pre>
+ * [MYVAR]
+ * value1
+ * value2
+ * value3
+ * </pre>
+ *
+ * and return an associative array(MYVAR => array(value1, value2, value3))
+ * @return array
+ * @param string full path to the ini file
+ * @param boolean add an associative index for each section [in brackets]
+ */
+function phpDocumentor_parse_ini_file($filename, $process_sections = false)
+{
+ $ini_array = array();
+ $sec_name = "";
+ $lines = @file($filename);
+ if( !$lines) return $lines;
+ foreach($lines as $line)
+ {
+ // code by Greg Beaver, ignore comments
+ if ($line[0] == ';') continue;
+ $line = trim($line);
+
+ if($line == "")
+ {
+ continue;
+ }
+ if($line[0] == "[" && $line[strlen($line) - 1] == "]")
+ {
+ $sec_name = substr($line, 1, strlen($line) - 2);
+ } else
+ {
+ if (strpos($line,"="))
+ {
+ $pos = strpos($line, "=");
+ $property = trim(substr($line, 0, $pos));
+ // code by Greg Beaver
+ if (substr($property, 0, 1) == '"' && substr($property, -1) == '"') {
+ $property = stripcslashes(substr($property,1,count($property) - 2));
+ }
+ $value = trim(substr($line, $pos + 1));
+ if ($value == 'false') $value = false;
+ if ($value == 'true') $value = true;
+ if (substr($value, 0, 1) == '"' && substr($value,-1) == '"')
+ {
+ $value = stripcslashes(substr($value,1,count($value) - 2));
+ }
+ // done additions
+
+ if($process_sections)
+ {
+ if ($sec_name != '')
+ $ini_array[$sec_name][$property] = $value;
+ else
+ $ini_array[$property] = $value;
+ } else
+ {
+ $ini_array[$property] = $value;
+ }
+ } else
+ {
+ // code by Greg Beaver
+ if (trim($line[0]) == ';') continue;
+ if($process_sections)
+ {
+ $ini_array[$sec_name][] = trim($line);
+ }
+ // done additions
+ }
+ }
+ }
+ return $ini_array;
+}
+
+
+if (!function_exists('array_key_exists'))
+{
+/** @ignore */
+function array_key_exists($key, $search)
+{
+ foreach($search as $keys => $nul)
+ {
+ if ($key == $keys) return true;
+ }
+ return false;
+}
+}
+if (!function_exists('is_a'))
+{
+/** @ignore */
+function is_a($classname, $classquery)
+{
+ $father = get_parent_class($classname);
+ if (strtolower($father) == strtolower($classquery))
+ {
+ return true;
+ } elseif (!empty($father))
+ {
+ return is_a($father, $classquery);
+ } else
+ {
+ return false;
+ }
+}
+}
+
+
+/** Debugging output */
+function debug($s)
+{
+ echo "$s\n";
+}
+
+/**
+ * Returns a formatted var_dump for debugging purposes.
+ * @param string $s string to display
+ * @param mixed $v variable to display with var_dump()
+ * @param mixed $v... unlimited number of additional variables to display with var_dump()
+ */
+function fancy_debug($s,$v)
+{
+ if (isset($GLOBALS['dont_debug']) && $GLOBALS['dont_debug']) return;
+ debug($s."\n\n</pre><blockquote><pre>");
+ var_dump($v);
+ if (func_num_args()>2)
+ {
+ for($i=2;$i<func_num_args();$i++)
+ {
+ $a = func_get_arg($i);
+// debug(" ");
+ var_dump($a);
+ }
+ }
+ debug("</pre></blockquote><pre>\n\n");
+}
+
+/**
+ * Returns a lower-cased version of get_class for PHP 5
+ *
+ * get_class() returns case as declared in the file in PHP 5
+ */
+function phpDocumentor_get_class($object)
+{
+ return strtolower(get_class($object));
+}
+
+?> \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/find_phpdoc.php b/buildscripts/PhpDocumentor/phpDocumentor/find_phpdoc.php
new file mode 100644
index 00000000..f2bec5b4
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/find_phpdoc.php
@@ -0,0 +1,32 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * Utility file: used to find location of phpDocumentor
+ * @filesource
+ * @package phpDocumentor
+ * @subpackage setup
+ */
+/**
+ * Dummy value
+ */
+@include('');
+// value used to test whether include worked
+return 6;
+?> \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/phpDocumentorTParser.inc b/buildscripts/PhpDocumentor/phpDocumentor/phpDocumentorTParser.inc
new file mode 100644
index 00000000..b5c5c733
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/phpDocumentorTParser.inc
@@ -0,0 +1,2615 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * @package phpDocumentor
+ * @subpackage Parsers
+ * @author Gregory Beaver <cellog@users.sourceforge.net>
+ * @version $Revision: 1.2 $
+ */
+/**
+ * Tokenizer-based parser for PHP source code
+ * @package phpDocumentor
+ * @subpackage Parsers
+ * @author Gregory Beaver <cellog@users.sourceforge.net>
+ * @version $Revision: 1.2 $
+ */
+class phpDocumentorTParser extends Parser
+{
+ /**#@+
+ * @access private
+ */
+ /**
+ * @var EventStack
+ */
+ var $_event_stack;
+ /**
+ * last event triggered before the current event
+ * @var integer
+ */
+ var $_last_pevent;
+ /**
+ * last word parsed
+ * @var integer
+ */
+ var $_last_word;
+ /**
+ * full path of the currently parsed file
+ * @var string
+ */
+ var $_path;
+ /**#@-*/
+ /**#@+
+ * Parser Variables
+ * @access private
+ */
+ var $_pv_class;
+ var $_pv_cur_class;
+ var $_pv_define;
+ var $_pv_define_name;
+ var $_pv_define_value;
+ var $_pv_define_params_data;
+ var $_pv_dtype;
+ var $_pv_docblock;
+ var $_pv_dtemplate;
+ var $_pv_func;
+ var $_pv_findglobal;
+ var $_pv_global_name;
+ var $_pv_global_val;
+ var $_pv_globals;
+ var $_pv_global_count;
+ var $_pv_include_params_data;
+ var $_pv_include_name;
+ var $_pv_include_value;
+ var $_pv_linenum;
+ var $_pv_periodline;
+ var $_pv_paren_count = 0;
+ var $_pv_statics;
+ var $_pv_static_count;
+ var $_pv_static_val;
+ var $_pv_quote_data;
+ var $_pv_function_data;
+ var $_pv_var;
+ var $_pv_varname;
+ var $_pv_var_value;
+ /**#@-*/
+ /**#@+
+ * Parser Flags
+ * @access private
+ */
+ var $_pf_definename_isset = false;
+ var $_pf_includename_isset = false;
+ var $_pf_get_source = false;
+ var $_pf_getting_source = false;
+ var $_pf_internal = false;
+ var $_pf_in_class = false;
+ var $_pf_in_define = false;
+ var $_pf_in_global = false;
+ var $_pf_in_include = false;
+ var $_pf_in_var = false;
+ var $_pf_funcparam_val = false;
+ var $_pf_quote_active = false;
+ var $_pf_reset_quote_data = true;
+ var $_pf_useperiod = false;
+ var $_pf_set_var_value = false;
+ var $_pf_var_equals = false;
+ /**#@-*/
+ /**
+ * relative path of the parsed file from the base parse directory
+ * @var string
+ */
+ var $source_location;
+ var $eventHandlers = array(
+ PARSER_EVENT_ARRAY => 'handleArray',
+ PARSER_EVENT_VAR_ARRAY => 'handleArray',
+ PARSER_EVENT_VAR_ARRAY_COMMENT => 'handleVarArrayComment',
+ PARSER_EVENT_CLASS => 'handleClass',
+ PARSER_EVENT_COMMENT => 'handleComment',
+ PARSER_EVENT_DOCBLOCK_TEMPLATE => 'handleDocBlockTemplate',
+ PARSER_EVENT_END_DOCBLOCK_TEMPLATE => 'handleEndDocBlockTemplate',
+ PARSER_EVENT_LOGICBLOCK => 'handleLogicBlock',
+ PARSER_EVENT_NOEVENTS => 'defaultHandler',
+ PARSER_EVENT_OUTPHP => 'defaultHandler',
+ PARSER_EVENT_DEFINE => 'handleDefine',
+ PARSER_EVENT_DEFINE_PARAMS => 'handleDefineParams',
+ PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS => 'handleDefineParamsParenthesis',
+ PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS => 'handleIncludeParamsParenthesis',
+ PARSER_EVENT_DOCBLOCK => 'handleDocBlock',
+ PARSER_EVENT_TAGS => 'handleTags',
+ PARSER_EVENT_DESC => 'handleDesc',
+ PARSER_EVENT_DOCKEYWORD => 'handleTag',
+ PARSER_EVENT_DOCKEYWORD_EMAIL => 'handleDockeywordEmail',
+ PARSER_EVENT_EOFQUOTE => 'handleHereDoc',
+ PARSER_EVENT_FUNCTION => 'handleFunction',
+ PARSER_EVENT_FUNCTION_PARAMS => 'handleFunctionParams',
+ PARSER_EVENT_FUNC_GLOBAL => 'handleFuncGlobal',
+ PARSER_EVENT_DEFINE_GLOBAL => 'handleGlobal',
+ PARSER_EVENT_GLOBAL_VALUE => 'handleGlobalValue',
+ PARSER_EVENT_INLINE_DOCKEYWORD => 'handleInlineDockeyword',
+ PARSER_EVENT_INCLUDE => 'handleInclude',
+ PARSER_EVENT_INCLUDE_PARAMS => 'handleIncludeParams',
+ PARSER_EVENT_QUOTE => 'handleQuote',
+ PARSER_EVENT_PHPCODE => 'handlePhpCode',
+ PARSER_EVENT_SINGLEQUOTE => 'handleSingleQuote',
+ PARSER_EVENT_STATIC_VAR => 'handleStaticVar',
+ PARSER_EVENT_STATIC_VAR_VALUE => 'handleStaticValue',
+ PARSER_EVENT_VAR => 'handleVar',
+ PARSER_EVENT_ACCESS_MODIFIER => 'handleAccessModifier',
+ PARSER_EVENT_IMPLEMENTS => 'handleImplements',
+ PARSER_EVENT_CLASS_CONSTANT => 'handleClassConstant',
+ );
+
+ var $inlineTagHandlers = array(
+ '*' => 'handleDefaultInlineTag',
+ 'link' => 'handleLinkInlineTag',
+ );
+
+ function phpDocumentorTParser()
+ {
+ $this->allowableTags = $GLOBALS['_phpDocumentor_tags_allowed'];
+ $this->allowableInlineTags = $GLOBALS['_phpDocumentor_inline_doc_tags_allowed'];
+ $this->subscribe(PHPDOCUMENTOR_EVENT_NEWLINENUM,$GLOBALS['phpDocumentor_errors']);
+ $this->subscribe(PHPDOCUMENTOR_EVENT_NEWFILE,$GLOBALS['phpDocumentor_errors']);
+ $this->tagHandlers['author'] = 'authorTagHandler';
+ $this->tagHandlers['filesource'] = 'filesourceTagHandler';
+ $this->setupEventStates();
+ }
+
+ /**
+ * Parse a new file
+ *
+ * @param string $parse_data
+ * @param string $path
+ * @param int $base number of directories to drop off the bottom when creating names using path
+ * @staticvar integer used for recursion limiting if a handler for an event is not found
+ * @return bool
+ */
+ function parse (&$parse_data, $path, $base = 0, $packages = false)
+ {
+ global $_phpDocumentor_options;
+ static $endrecur = 0;
+ $this->setupStates();
+ if (strlen($parse_data) == 0)
+ {
+ return false;
+ }
+
+ $this->configWordParser($parse_data);
+ // initialize variables so E_ALL error_reporting doesn't complain
+ $pevent = 0;
+ $word = 0;
+
+ $page = new ParserPage;
+ $page->setSource($this->_wp->getFileSource());
+ $page->setPath($path);
+ $this->_path = $path;
+ $page->setPackageOutput($packages);
+ $page->setFile(basename($path));
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWFILE,basename($path));
+ //$name = str_replace("/","_",dirname($path)) . "_" . array_shift(explode(".",$page->getFile()));
+ // fc@fc.clever-soft.com 11/29/2001
+ $name = str_replace(PATH_DELIMITER,"_",dirname($path)) . "_" . str_replace(".","_",$page->getFile());
+ $tmp = explode("_",$name);
+ $name = str_replace(':','_',implode("_",array_slice($tmp,$base)));
+ // if base is '', drive letter is present in windows
+
+ $page->setName($name);
+ $temploc = $_phpDocumentor_options['Program_Root'] . PATH_DELIMITER. implode(PATH_DELIMITER,
+ array_slice(explode(PATH_DELIMITER,$path),$base));
+
+ if ($temploc == $_phpDocumentor_options['Program_Root'] . PATH_DELIMITER) $temploc .= $path;
+
+ $this->source_location = $source_location = $temploc;
+ $page->setSourceLocation($source_location);
+
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_PAGE,$page);
+ unset($page);
+ do
+ {
+ $lpevent = $pevent;
+ $pevent = $this->_event_stack->getEvent();
+ if ($lpevent != $pevent)
+ {
+ $this->_last_pevent = $lpevent;
+ }
+
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE,($pevent + 100));
+
+ $this->_pv_last_word = $word;
+ $word = $this->_wp->getWord();
+ if (isset($this->_pv_findglobal) && $word == $this->_pv_findglobal)
+ {
+ $this->_last_pevent = $pevent;
+ $this->_event_stack->pushEvent($pevent = PARSER_EVENT_DEFINE_GLOBAL);
+ }
+ // in wordparser, have to keep track of lines
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWLINENUM, $this->_wp->linenum);
+ if ($this->_pf_get_source)
+ {
+ if ($word[0] == T_FUNCTION)
+ {
+ $this->_wp->retrievesource($word);
+ $this->_pf_get_source = false;
+ $this->_pf_getting_source = true;
+ }
+ }
+
+ if (0)//PHPDOCUMENTOR_DEBUG == true)
+ {
+ echo "LAST: ";
+ if (is_array($this->_pv_last_word))
+ {
+ echo token_name($this->_pv_last_word[0]). ' => |'.htmlspecialchars($this->_pv_last_word[1]);
+ } else echo "|" . $this->_pv_last_word;
+ echo "|\n";
+ echo "PEVENT: " . $this->getParserEventName($pevent) . "\n";
+ echo "LASTPEVENT: " . $this->getParserEventName($this->_last_pevent) . "\n";
+ echo $this->_wp->getPos() . ": ";
+ if (is_array($word))
+ {
+ echo token_name($word[0]).' => |'.htmlspecialchars($word[1]);
+ } else echo '|'.htmlspecialchars($word);
+ echo "|\n-------------------\n\n\n";
+ }
+ if (0)//$this->_pf_getting_source && ($pevent == PARSER_EVENT_DOCBLOCK) || ($pevent == PARSER_EVENT_NOEVENTS))
+ {
+ addError(PDERROR_SOURCE_TAG_FUNCTION_NOT_FOUND);
+ // throw away source
+ $this->_wp->getSource();
+ }
+ if (isset($this->eventHandlers[$pevent]))
+ {
+ $handle = $this->eventHandlers[$pevent];
+ $this->$handle($word, $pevent);
+ } else
+ {
+ debug('WARNING: possible error, no handler for event number '.$pevent);
+ if ($endrecur++ == 25)
+ {
+ die("FATAL ERROR, recursion limit reached");
+ }
+ }
+ } while (!($word === false));
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE,PHPDOCUMENTOR_EVENT_END_PAGE);
+ }
+
+ /**#@+
+ * @access private
+ */
+ /**
+ * handler for COMMENT
+ */
+ function handleComment($word, $pevent)
+ {
+ $this->_wp->backupPos();
+ $this->_event_stack->popEvent();
+ }
+ /**
+ * handler for PHPCODE.
+ * this handler recognizes the <code><?</code> php processor directive, and begins parsing php code
+ */
+
+ function handlePhpCode($word, $pevent)
+ {
+ $e = $this->checkEventPush( $word, $pevent);
+ if (isset($this->_pv_findglobal) && $e)
+ {
+ if ($e != PARSER_EVENT_DEFINE_GLOBAL && $e != PARSER_EVENT_ARRAY && $e != PARSER_EVENT_QUOTE && $e != PARSER_EVENT_SINGLEQUOTE && $e != PARSER_EVENT_COMMENT && $e != PARSER_EVENT_COMMENTBLOCK)
+ {
+ addError(PDERROR_GLOBAL_NOT_FOUND,$this->_pv_findglobal);
+ $this->_wp->findGlobal(false);
+ unset($this->_pv_findglobal);
+ }
+ }
+ }
+
+ /**
+ * handler for FUNC_GLOBAL.
+ * this handler recognizes "global $var1, $var2" declarations in a function, and parses them
+ */
+
+ function handleFuncGlobal($word, $pevent)
+ {
+ if ($this->checkEventPop($word, $pevent))
+ {
+ return;
+ }
+ if (!$this->checkEventPush($word, $pevent))
+ {
+ if ($word == ',')
+ { // another variable
+ $this->_pv_global_count++;
+ } else
+ {
+ if (!isset($this->_pv_globals[$this->_pv_global_count]))
+ $this->_pv_globals[$this->_pv_global_count] = '';
+// if (!empty($this->_pv_globals[$this->_pv_global_count])) $this->_pv_global_count++;
+ if (is_array($word)) $word = $word[1];
+ $this->_pv_globals[$this->_pv_global_count] .= $word;
+ }
+ }
+ }
+
+ /**
+ * handler for STATIC_VAR.
+ * this handler recognizes "static $var1, $var2 = 6" declarations in a function, and parses them
+ */
+
+ function handleStaticVar($word, $pevent)
+ {
+ if ($this->checkEventPop($word, $pevent))
+ {
+ $this->_pv_static_count++;
+ return;
+ }
+ if (!$this->checkEventPush($word, $pevent))
+ {
+ if ($word == ',')
+ {
+ $this->_pv_static_count++;
+ return;
+ }
+ if (!isset($this->_pv_statics[$this->_pv_static_count]))
+ $this->_pv_statics[$this->_pv_static_count] = '';
+ if (!empty($this->_pv_statics[$this->_pv_static_count])) $this->_pv_static_count++;
+ if (is_array($word)) $word = $word[1];
+ $this->_pv_statics[$this->_pv_static_count] = $word;
+ }
+ }
+
+ /**
+ * handler for STATIC_VAR_VALUE.
+ * this handler parses the 6 in "static $var1, $var2 = 6"
+ */
+
+ function handleStaticValue($word, $pevent)
+ {
+ if ($this->checkEventPush($word, $pevent))
+ {
+ return;
+ }
+ if (!isset($this->_pv_static_val[$this->_pv_static_count])) $this->_pv_static_val[$this->_pv_static_count] = '';
+ if ($this->_last_pevent == PARSER_EVENT_QUOTE)
+ {
+ $this->_pv_static_val[$this->_pv_static_count] .= $this->_pv_quote_data;
+ unset($this->_pv_quote_data);
+ }
+ if ($this->_last_pevent == PARSER_EVENT_ARRAY)
+ {
+ $this->_pv_static_val[$this->_pv_static_count] .= $this->_pv_function_data;
+ $this->_pv_function_data = '';
+ }
+ if ($this->checkEventPop($word, $pevent))
+ {
+ $this->_pv_static_val[$this->_pv_static_count] = trim($this->_pv_static_val[$this->_pv_static_count]);
+ $this->_wp->backupPos($word);
+ return;
+ } else
+ {
+ if (is_array($word)) $word = $word[1];
+ $this->_pv_static_val[$this->_pv_static_count] .= $word;
+ }
+ }
+
+ /**
+ * handler for LOGICBLOCK
+ *
+ * Logic Blocks are the stuff between { and } in a function/method. A
+ * logic block can clearly contain other logic blocks, as in:
+ *
+ * <code>
+ * function test($a)
+ * {
+ * if (testcondition)
+ * { // nested logic block
+ * }
+ * }
+ * </code>
+ *
+ * So, the exit portion of the logic block handler must check to see if the
+ * logic block being exited is the top-level, and it does this by retrieving
+ * the last event from the stack. If it is a function (and not a logic block)
+ * then it backs up the word parser so that the function will exit properly.
+ *
+ * {@source 11}
+ */
+
+ function handleLogicBlock($word, $pevent)
+ {
+ $a = $this->checkEventPush( $word, $pevent);
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $e = $this->_event_stack->popEvent();
+ $this->_event_stack->pushEvent($e);
+ if ($e == PARSER_EVENT_FUNCTION)
+ {
+ $this->_wp->backupPos();
+ }
+ }
+ }
+
+ /**
+ * handler for FUNCTION.
+ * this handler recognizes function declarations, and parses them. The body
+ * of the function is parsed by handleLogicBlock()
+ * @see handleLogicBlock()
+ */
+
+ function handleFunction($word, $pevent)
+ {
+ if ($e = $this->checkEventPush( $word, $pevent))
+ {
+ $this->_pv_function_data = '';
+ if ($e == PARSER_EVENT_FUNCTION_PARAMS && !is_object($this->_pv_func))
+ {
+ addErrorDie(PDERROR_FUNCTION_HAS_NONAME);
+ }
+ if ($e == PARSER_EVENT_COMMENT || $e == PARSER_EVENT_COMMENTBLOCK || $e == PARSER_EVENT_FUNCTION_PARAMS) return;
+ }
+
+ if (!isset($this->_pv_func)) $this->_pv_func = false;
+ if (! is_object($this->_pv_func))
+ {
+ $this->_pv_globals = array();
+ $this->_pv_global_count = $this->_pv_static_count = 0;
+ if ($this->_pf_in_class)
+ {
+ $this->_pv_func = new parserMethod($this->_pv_cur_class);
+ } else
+ {
+ $this->_pv_func = new parserFunction;
+ }
+ if (isset($this->_accessModifiers))
+ {
+ $this->_pv_func->setModifiers($this->_accessModifiers);
+ unset($this->_accessModifiers);
+ }
+ $this->_pv_func->setLineNumber($this->_wp->linenum + 1);
+ if (is_string($word) && $word == '&')
+ $this->_pv_func->setReturnsReference();
+ if (is_array($word) && $word[0] == T_STRING)
+ $this->_pv_func->setName($word[1]);
+ } else
+ {
+ if ($this->_pv_func->getReturnsReference())
+ {
+ if (is_array($word) && $word[0] == T_STRING)
+ {
+ $this->_pv_func->setName($word[1]);
+ }
+ }
+ }
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->_pv_func->setEndLineNumber($this->_wp->linenum + 1);
+ $this->_pv_func->addGlobals($this->_pv_globals);
+ $this->_pv_func->addStatics($this->_pv_statics,$this->_pv_static_val);
+ $this->_pv_globals = array();
+ $this->_pv_global_count = 0;
+ if ($this->_pf_getting_source)
+ {
+ $x = $this->_wp->getSource();
+ $this->_pv_func->addSource($x);
+ $this->_pf_get_source = false;
+ $this->_pf_getting_source = false;
+ }
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_FUNCTION,$this->_pv_func);
+ $this->_pv_func = false;
+ unset($this->_pv_quote_data); // subtle bug fixed by this, sometimes string
+ // from function body was picked up
+ // by the next function as a default value
+ // for a parameter!
+ }
+ }
+
+ /**
+ * Helper function for {@link handleFunctionParams()}
+ *
+ * This function adds a new parameter to the parameter list
+ */
+ function endFunctionParam($word)
+ {
+ if (isset($this->_pv_quote_data))
+ {
+ $this->_pv_function_data .= $this->_pv_quote_data;
+ unset($this->_pv_quote_data);
+ }
+ if (isset($this->_pv_function_param))
+ {
+ $this->_pv_func->addParam($this->_pv_function_param,$this->_pv_function_data,
+ $this->_pf_funcparam_val, $this->_pv_function_param_type);
+ unset($this->_pv_function_param);
+ $this->_pv_function_data = '';
+ $this->_pf_funcparam_val = false;
+ $this->_pv_function_param_type = null;
+ }
+ }
+ /**
+ * handler for FUNCTION_PARAMS.
+ * this handler recognizes the parameters of a function within parentheses like function(param, param = default_value)
+ * and parses them
+ * @see endFunctionParam()
+ */
+
+ function handleFunctionParams($word, $pevent)
+ {
+ //echo $this->wp->getPos() . ": word=|$word|\t\t\tlastword=|".$this->_pv_last_word."|\n";
+ //echo "function_param = '".$this->_pv_function_param."'\n";
+ //echo "function_data = '".$this->_pv_function_data."'\n";
+ $e1 = $this->checkEventPush( $word, $pevent);
+
+ if (!$e1)
+ {
+ if ($word == ',' || $this->checkEventPop($word,$pevent))
+ {
+ $this->endFunctionParam($word);
+ } elseif ($word == '=')
+ {
+ $this->_pf_funcparam_val = true;
+ } else
+ {
+ if ($this->_pf_funcparam_val)
+ {
+ if (isset($this->_pv_quote_data))
+ {
+ $this->_pv_function_data .= $this->_pv_quote_data;
+ unset($this->_pv_quote_data);
+ }
+ if (is_array($word)) $word = $word[1];
+ $this->_pv_function_data .= $word;
+ } else
+ {
+ if (!isset($this->_pv_function_param)) $this->_pv_function_param = '';
+ if (is_array($word))
+ {
+ if ($word[0] == T_STRING)
+ {
+ $this->_pv_function_param_type = $word[1];
+ return;
+ }
+ $word = $word[1];
+ }
+ $this->_pv_function_param .= $word;
+ }
+ }
+ } elseif ($e1 == PARSER_EVENT_ARRAY)
+ {
+ $this->_wp->setWhiteSpace(true);
+ }
+ }
+
+ /**
+ * handler for ARRAY.
+ * this event handler parses arrays in default values of function and var definitions
+ */
+
+ function handleArray($word, $pevent)
+ {
+ $e = $this->checkEventPush( $word, $pevent);
+ if ($e) return;
+
+ if (!isset($this->_pv_function_data) || (isset($this->_pv_function_data) && empty($this->_pv_function_data)))
+ {
+ $this->_pv_function_data = "array";
+ }
+
+ if ($word == '(' && $this->_pv_paren_count++)
+ { // need extra parentheses help
+ $this->_event_stack->pushEvent($pevent);
+ }
+ if (is_array($word))
+ {
+ $this->_pv_function_data .= $word[1];
+ } else
+ $this->_pv_function_data .= $word;
+ //echo "function_data = |$this->_pv_function_data|\n";
+
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->_pv_paren_count--;
+ $this->_wp->setWhiteSpace(false);
+ }
+ }
+
+ /**
+ * handler for HEREDOC in a function logic block.
+ * this handler recognizes function declarations, and parses them. The body
+ * of the function is parsed by handleLogicBlock()
+ * @see handleLogicBlock()
+ */
+
+ function handleHereDoc($word, $pevent)
+ {
+ if (is_array($this->_pv_last_word) && $this->_pv_last_word[0] == T_START_HEREDOC)
+ {
+ $save = $word;
+ if (is_array($word)) $word = $word[1];
+ $this->_pv_quote_data = $this->_pv_last_word[1] . $word;
+ $this->_pf_quote_active = true;
+ } elseif (!$this->_pf_quote_active)
+ {
+ $this->_pv_quote_data = $this->_pv_last_word[1];
+ $this->_event_stack->popEvent();
+ $this->_wp->backupPos();
+ return;
+ }
+ $save = $word;
+ if (is_array($word)) $word = $word[1];
+ $this->_pv_quote_data .= $word;
+ if ($this->checkEventPop($save, $pevent))
+ {
+ $this->_pf_quote_active = false;
+ }
+ }
+
+ /**
+ * handler for QUOTE.
+ * this handler recognizes strings defined with double quotation marks (")
+ * and single quotation marks and handles them correctly
+ * in any place that they legally appear in php code
+ */
+
+ function handleQuote($word, $pevent)
+ {
+ if ($this->_pv_last_word == '"' || $this->_pv_last_word == "'" && $this->_last_pevent != PARSER_EVENT_QUOTE)
+ {
+ $save = $word;
+ if (is_array($word)) $word = $word[1];
+ $this->_pv_quote_data = $this->_pv_last_word . $word;
+ $this->_pf_quote_active = true;
+ $this->checkEventPop($save, $pevent);
+ } elseif (!$this->_pf_quote_active)
+ {
+ $this->_pv_quote_data = $this->_pv_last_word[1];
+ $this->_event_stack->popEvent();
+ $this->_wp->backupPos();
+ return;
+ }
+ $save = $word;
+ if (is_array($word)) $word = $word[1];
+ $this->_pv_quote_data .= $word;
+ if ($this->checkEventPop($save, $pevent))
+ {
+ $this->_pf_quote_active = false;
+ }
+ }
+
+ /**
+ * handler for INCLUDE.
+ * this handler recognizes include/require/include_once/include_once statements, and publishes the
+ * data to Render
+ */
+
+ function handleInclude($word, $pevent)
+ {
+ if (!$this->_pf_in_include)
+ {
+ $this->_pv_linenum = $this->_wp->linenum;
+ }
+ $this->_pf_in_include = true;
+ $a = $this->checkEventPush( $word, $pevent);
+ if (!$this->_pf_includename_isset)
+ {
+ $this->_pf_includename_isset = true;
+ $w = $this->_pv_last_word;
+ if (is_array($w)) $w = $w[1];
+ $this->_pv_include_name = $w;
+ if ($a)
+ $this->_pv_include_value = '';
+ else
+ {
+ if (is_array($word)) $word = $word[1];
+ $this->_pv_include_value = $word;
+ }
+ unset($this->_pv_quote_data);
+ } else
+ {
+ if (!$a)
+ {
+ if (empty($this->_pv_include_params_data))
+ {
+ if ($word != ';')
+ {
+ if (is_array($word)) $word = $word[1];
+ $this->_pv_include_value .= $word;
+ }
+ }
+ } else
+ {
+ $this->_pv_include_params_data = '';
+ }
+ }
+
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->_pv_include = new parserInclude;
+ $this->_pv_include->setLineNumber($this->_pv_linenum + 1);
+ $this->_pf_in_include = false;
+ $this->_pv_include->setName($this->_pv_include_name);
+ $this->_pv_include->setValue($this->_pv_include_value);
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_INCLUDE,$this->_pv_include);
+ $this->_pf_includename_isset = false;
+ unset($this->_pv_include);
+ unset($this->_pv_include_name);
+ unset($this->_pv_include_value);
+ unset($this->_pv_include_params_data);
+ }
+ }
+
+ /**
+ * handler for INCLUDE_PARAMS.
+ * this handler parses the contents of ( ) in include/require/include_once/include_once statements
+ */
+
+ function handleIncludeParams($word, $pevent)
+ {
+ $e = $this->checkEventPush( $word, $pevent);
+ if ($e == PARSER_EVENT_COMMENT) return;
+
+ if(!isset($this->_pv_include_params_data)) $this->_pv_include_params_data = '';
+
+ if ($this->checkEventPop($word,$pevent))
+ {
+ if (!empty($this->_pv_include_params_data))
+ $this->_pv_include_value = $this->_pv_include_params_data;
+ else
+ {
+ $w = $this->_pv_last_word;
+ if (is_array($w)) $w = $w[1];
+ $this->_pv_include_value = $w;
+ }
+ }
+ if (is_array($word)) $word = $word[1];
+ $this->_pv_include_params_data .= $word;
+ }
+
+ /**
+ * handler for INCLUDE_PARAMS_PARENTHESIS.
+ * this handler takes all parenthetical statements within file in:
+ * include statement include(file), and handles them properly
+ */
+
+ function handleIncludeParamsParenthesis($word, $pevent)
+ {
+ $this->checkEventPush( $word, $pevent);
+ $this->checkEventPop( $word, $pevent);
+ if (is_array($word)) $word = $word[1];
+ $this->_pv_include_params_data .= $word;
+ }
+
+ /**
+ * handler for DEFINE.
+ * handles define(constant, value); statements
+ */
+
+ function handleDefine($word, $pevent)
+ {
+ if (!$this->_pf_in_define)
+ {
+ $this->_pv_linenum = $this->_wp->linenum + 1;
+ }
+ $this->_pf_in_define = true;
+ $this->checkEventPush( $word, $pevent);
+
+ $this->_pf_definename_isset = false;
+ $this->_pv_define_params_data = '';
+ unset($this->_pv_quote_data);
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->_pf_in_define = false;
+ $this->_pv_define = new parserDefine;
+ $this->_pv_define->setLineNumber($this->_pv_linenum);
+ $this->_pv_define->setName($this->_pv_define_name);
+ $this->_pv_define->setValue($this->_pv_define_value);
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_DEFINE,$this->_pv_define);
+ $this->_pf_definename_isset = false;
+ unset($this->_pv_define);
+ unset($this->_pv_define_name);
+ unset($this->_pv_define_value);
+ $this->_pf_in_define = false;
+ $this->_pv_define_params_data = '';
+ }
+ }
+
+ /**
+ * handler for DEFINE_PARAMS.
+ * handles the parsing of constant and value in define(constant, value);
+ */
+
+ function handleDefineParams($word, $pevent)
+ {
+ $e = $this->checkEventPush( $word, $pevent);
+ if ($e && $e != PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS) return;
+
+ if(!isset($this->_pv_define_params_data)) $this->_pv_define_params_data = '';
+
+ if ($this->checkEventPop($word,$pevent))
+ {
+ if ($this->_last_pevent == PARSER_EVENT_QUOTE ||
+ $this->_last_pevent == PARSER_EVENT_EOFQUOTE)
+ {
+ $this->_pv_define_params_data .= $this->_pv_quote_data;
+ unset($this->_pv_quote_data);
+ }
+ if (is_array($word)) $word = $word[1];
+ if (!empty($this->_pv_define_params_data))
+ {
+ //echo $this->_pv_define_params_data."\n";
+ $this->_pv_define_value = $this->_pv_define_params_data;
+ }
+ else
+ {
+ $w = $this->_pv_last_word;
+ if (is_array($this->_pv_last_word)) $w = $this->_pv_last_word[1];
+ if (!empty($w))
+ {
+ $this->_pv_define_value = $w;
+ }
+ else
+ {
+ $this->_pv_define_value = "";
+ switch ($w) {
+ case 0:
+ $this->_pv_define_value = "0";
+ break;
+ case null:
+ $this->_pv_define_value = "null";
+ break;
+ case "":
+ $this->_pv_define_value = "";
+ break;
+ }
+ }
+ }
+ }
+ if ($this->_pf_definename_isset)
+ {
+ if (is_array($word)) $word = $word[1];
+ $this->_pv_define_params_data .= $word;
+ } else
+ {
+ if ($word != ",")
+ {
+ if (is_array($word)) $word = $word[1];
+ $this->_pv_define_params_data .= $word;
+ } else
+ {
+ if (substr($this->_pv_define_params_data,0,1) ==
+ substr($this->_pv_define_params_data,strlen($this->_pv_define_params_data) - 1) &&
+ in_array(substr($this->_pv_define_params_data,0,1),array('"',"'")))
+ { // remove leading and ending quotation marks if there are only two
+ $a = substr($this->_pv_define_params_data,0,1);
+ $b = substr($this->_pv_define_params_data,1,strlen($this->_pv_define_params_data) - 2);
+ if (strpos($b,$a) === false)
+ {
+ $this->_pv_define_params_data = $b;
+ }
+ }
+ $this->_pf_definename_isset = true;
+ $this->_pv_define_name = $this->_pv_define_params_data;
+ $this->_pv_define_params_data = '';
+ }
+ }
+ }
+
+ /**
+ * handler for DEFINE_PARAMS_PARENTHESIS.
+ * this handler takes all parenthetical statements within constant or value in:
+ * define(constant, value) of a define statement, and handles them properly
+ */
+
+ function handleDefineParamsParenthesis($word, $pevent)
+ {
+ $e = $this->checkEventPush( $word, $pevent);
+ $this->checkEventPop( $word, $pevent);
+ if ($this->_last_pevent == PARSER_EVENT_QUOTE)
+ {
+ $this->_pv_define_params_data .= $this->_pv_quote_data;
+ unset($this->_pv_quote_data);
+ }
+ if (is_array($word)) $word = $word[1];
+ $this->_pv_define_params_data .= $word;
+ }
+
+ /**
+ * handler for IMPLEMENTS.
+ * this handler parses a class statement's implements clause (PHP 5)
+ */
+
+ function handleImplements($word, $pevent)
+ {
+ if ($this->checkEventPop($word, $pevent))
+ {
+ $this->_wp->backupPos();
+ return;
+ }
+ if (is_array($word) && $word[0] == T_STRING)
+ {
+ $this->_pv_class->addImplements($word[1]);
+ }
+ }
+
+ /**
+ * handler for ACCESS_MODIFIER.
+ * this handler parses public/private/protected/static/abstract PHP 5 modifiers
+ */
+
+ function handleAccessModifier($word, $pevent)
+ {
+ if (!isset($this->_accessModifiers))
+ {
+ $this->_accessModifiers = array();
+ }
+ $this->_wp->backupPos();
+ $this->_event_stack->popEvent();
+ if ($word[0] == T_VARIABLE) {
+ // this is a PHP5-style variable with no "var"
+ $this->_event_stack->pushEvent(PARSER_EVENT_VAR);
+ }
+ $this->_accessModifiers[] = strtolower($this->_pv_last_word[1]);
+ }
+
+ /**
+ * handler for CLASS.
+ * this handler parses a class/interface statement
+ */
+
+ function handleClass($word, $pevent)
+ {
+ if (!$this->_pf_in_class)
+ {
+ $this->_pf_in_class = true;
+ if ($this->_pv_last_word[0] == T_INTERFACE)
+ {
+ $this->_pf_interface = true;
+ } else
+ {
+ $this->_pf_interface = false;
+ }
+ }
+ $a = $this->checkEventPush( $word, $pevent);
+
+ if (!isset($this->_pv_class)) $this->_pv_class = false;
+ if (!is_subclass_of($this->_pv_class,"parserBase"))
+ {
+ $this->_pv_class = new parserClass;
+ if (isset($this->_accessModifiers))
+ {
+ $this->_pv_class->setModifiers($this->_accessModifiers);
+ unset($this->_accessModifiers);
+ }
+ if ($this->_pf_interface)
+ {
+ $this->_pv_class->setInterface();
+ }
+ $this->_pv_class->setLineNumber($this->_wp->linenum + 1);
+ $this->_pv_class->setname($word[1]);
+ $this->_pv_cur_class = $word[1];
+ $this->_pv_class->setSourceLocation($this->source_location);
+ }
+
+ if (is_array($this->_pv_last_word) && $this->_pv_last_word[0] == T_EXTENDS)
+ {
+ // I don't know why I am so nice, this fixes 1150809
+ if ($word[1] == $this->_pv_class->getName()) {
+ addErrorDie(PDERROR_CANNOT_EXTEND_SELF, $word[1]);
+ }
+ $this->_pv_class->setExtends($word[1]);
+ }
+
+ if ($word == "{")
+ {
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_CLASS,$this->_pv_class);
+ }
+ //echo $this->wp->getPos() . ": |$word|\n";
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->_pv_class->setEndLineNumber($this->_wp->linenum + 1);
+ $this->_pf_in_class = $this->_pf_interface = false;
+ // throw an event when class is done
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE,STATE_END_CLASS);
+ $this->_pv_class = false;
+ }
+ }
+
+ /**
+ * handler for VAR_ARRAY_COMMENT
+ * if parsing a default value, add the comment to the text
+ */
+ function handleVarArrayComment($word, $pevent)
+ {
+ $this->_pv_function_data .= $this->_pv_last_word[1];
+ return $this->handleComment($word, $pevent);
+ }
+
+ /**
+ * handler for VAR.
+ * handle a var $varname = default_value; or var $varname; statement in a class definition
+ */
+
+ function handleVar($word, $pevent)
+ {
+ if (!$this->_pf_in_var)
+ {
+ $this->_pf_set_var_value = false;
+ $this->_pv_var_value = '';
+ $this->_pv_linenum = $this->_wp->linenum + 1;
+ }
+ $this->_pf_in_var = true;
+ //echo $word."\n";
+ $e = $this->checkEventPush( $word, $pevent);
+
+ if (!isset($this->_pv_var)) $this->_pv_var = false;
+ if ($word == '=' || $word == ';' || $word == ',')
+ {
+ $this->_wp->setWhitespace(true);
+ $this->_pf_var_equals = true;
+ $this->_pv_var = new parserVar($this->_pv_cur_class);
+ $this->_pv_var->setName($this->_pv_varname);
+ }
+ if ($this->_last_pevent == PARSER_EVENT_VAR_ARRAY)
+ {
+ if (isset($this->_pv_function_data))
+ $this->_pv_var->setValue($this->_pv_function_data);
+ $this->_pf_set_var_value = true;
+ unset($this->_pv_function_data);
+ } elseif ($this->_pf_var_equals && $word != ';' && $word != '=' && $word != ',' && !$e)
+ {
+ if (is_array($word)) $word = $word[1];
+ $this->_pv_var_value .= $word;
+ }
+ if ($word == ',')
+ {
+ if (!$this->_pf_set_var_value)
+ $this->_pv_var->setValue($this->_pv_var_value);
+ $this->_pf_set_var_value = false;
+ unset($this->_pv_var_value);
+ $this->_pv_var->setEndLineNumber($this->_wp->linenum + 1);
+ $this->_pv_var->setLineNumber($this->_pv_linenum);
+ if (isset($this->_accessModifiers))
+ {
+ $this->_pv_var->setModifiers($this->_accessModifiers);
+ unset($this->_accessModifiers);
+ }
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_VAR,$this->_pv_var);
+ unset($this->_pv_var);
+ $this->_pf_in_var = false;
+ $this->_pf_var_equals = false;
+ $this->_pv_varname = '';
+ return;
+ }
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->_wp->setWhitespace(false);
+ if (!$this->_pf_set_var_value)
+ $this->_pv_var->setValue($this->_pv_var_value);
+ $this->_pf_set_var_value = false;
+ unset($this->_pv_var_value);
+ $this->_pv_var->setEndLineNumber($this->_wp->linenum + 1);
+ $this->_pv_var->setLineNumber($this->_pv_linenum);
+ if (isset($this->_accessModifiers))
+ {
+ $this->_pv_var->setModifiers($this->_accessModifiers);
+ unset($this->_accessModifiers);
+ }
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_VAR,$this->_pv_var);
+ unset($this->_pv_var);
+ $this->_pf_in_var = false;
+ $this->_pf_var_equals = false;
+ $this->_pv_varname = '';
+ return;
+ }
+ if ($word[0] == T_VARIABLE)
+ {
+ $this->_pv_varname = $word[1];
+ }
+
+ }
+
+ /**
+ * handler for CLASS_CONSTANT.
+ * handle a const constname = default_value; statement in a class definition
+ */
+
+ function handleClassConstant($word, $pevent)
+ {
+ if (!$this->_pf_in_const)
+ {
+ $this->_pf_set_const_value = false;
+ $this->_pv_const_value = '';
+ $this->_pv_linenum = $this->_wp->linenum + 1;
+ }
+ $this->_pf_in_const = true;
+ //echo $word."\n";
+ $e = $this->checkEventPush( $word, $pevent);
+
+ if (!isset($this->_pv_const)) $this->_pv_const = false;
+ if ($word == '=' || $word == ';' || $word == ',')
+ {
+ $this->_wp->setWhitespace(true);
+ $this->_pf_const_equals = true;
+ $this->_pv_const = new parserConst($this->_pv_cur_class);
+ $this->_pv_const->setName($this->_pv_constname);
+ }
+ if ($this->_last_pevent == PARSER_EVENT_VAR_ARRAY)
+ {
+ if (isset($this->_pv_function_data))
+ $this->_pv_const->setValue($this->_pv_function_data);
+ $this->_pf_set_const_value = true;
+ unset($this->_pv_function_data);
+ } elseif ($this->_pf_const_equals && $word != ';' && $word != '=' && $word != ',' && !$e)
+ {
+ if (is_array($word)) $word = $word[1];
+ $this->_pv_const_value .= $word;
+ }
+ if ($word == ',')
+ {
+ if (!$this->_pf_set_const_value)
+ {
+ $this->_pv_const->setValue($this->_pv_const_value);
+ }
+ $this->_pf_set_const_value = false;
+ unset($this->_pv_const_value);
+ $this->_pv_const->setEndLineNumber($this->_wp->linenum + 1);
+ $this->_pv_const->setLineNumber($this->_pv_linenum);
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_CONST,$this->_pv_const);
+ unset($this->_pv_const);
+ $this->_pf_in_const = false;
+ $this->_pf_const_equals = false;
+ $this->_pv_constname = '';
+ return;
+ }
+ if ($this->checkEventPop($word,$pevent))
+ {
+ $this->_wp->setWhitespace(false);
+ if (!$this->_pf_set_const_value)
+ $this->_pv_const->setValue($this->_pv_const_value);
+ $this->_pf_set_const_value = false;
+ unset($this->_pv_const_value);
+ $this->_pv_const->setEndLineNumber($this->_wp->linenum + 1);
+ $this->_pv_const->setLineNumber($this->_pv_linenum);
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_VAR,$this->_pv_const);
+ unset($this->_pv_const);
+ $this->_pf_in_const = false;
+ $this->_pf_const_equals = false;
+ $this->_pv_constname = '';
+ return;
+ }
+ if ($word[0] == T_STRING && !$this->_pf_const_equals)
+ {
+ $this->_pv_constname = $word[1];
+ }
+
+ }
+
+ /**
+ * Handler for the {@tutorial phpDocumentor.howto.pkg#using.command-line.javadocdesc}
+ * command-line switch DocBlocks.
+ */
+ function JavaDochandleDocblock($word, $pevent)
+ {
+ $this->commonDocBlock($word, $pevent, 'handleJavaDocDesc');
+ }
+
+ /**
+ * Handler for normal DocBlocks
+ */
+ function handleDocBlock($word, $pevent)
+ {
+ $this->commonDocBlock($word, $pevent, 'handleDesc');
+ }
+
+ /**
+ * Common DocBlock Handler for both JavaDoc-format and normal DocBlocks
+ */
+ function commonDocBlock($word, $pevent, $deschandler)
+ {
+ $this->_wp->backupPos();
+ $this->_event_stack->popEvent();
+ $word = $this->_pv_last_word[1];
+ $dtype = '_pv_docblock';
+ if (strpos($word,'/**') !== 0)
+ { // not a docblock
+// $this->_wp->backupPos();
+ $this->_event_stack->pushEvent(PARSER_EVENT_COMMENT);
+ return;
+ }
+ if ($word == '/**#@-*/')
+ { // stop using docblock template
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_NEWSTATE,PHPDOCUMENTOR_EVENT_END_DOCBLOCK_TEMPLATE);
+ unset($this->_pv_dtemplate);
+ return;
+ }
+ if (strpos($word,'/**#@+') === 0)
+ { // docblock template definition
+ $dtype = '_pv_dtemplate';
+ // strip /**#@+ and */
+ $word = substr($word,6).'*';
+ $word = trim(substr($word,0,strlen($word) - 3));
+ if (strlen($word) && $word{0} != '*') {
+ $word = "* $word";
+ }
+ } else
+ {
+ // strip /** and */
+ $word = substr($word,2);
+ $word = substr($word,0,strlen($word) - 2);
+ }
+ $lines = explode("\n",trim($word));
+ $go = count($lines);
+ for($i=0;$i<$go;$i++)
+ {
+ if (substr(trim($lines[$i]),0,1) != '*') unset($lines[$i]);
+ else
+ $lines[$i] = substr(trim($lines[$i]),1); // remove leading "* "
+ }
+ // remove empty lines
+ $lines = explode("\n",trim(join("\n",$lines)));
+ for($i = 0;$i<count($lines);$i++)
+ {
+ if (substr(trim($lines[$i]),0,1) == '@' && substr(trim($lines[$i]),0,2) != '@ ')
+ {
+ $tagindex = $i;
+ $i = count($lines);
+ }
+ }
+ if (isset($tagindex))
+ {
+ $tags = array_slice($lines,$tagindex);
+ $desc = array_slice($lines,0,$tagindex);
+ } else
+ {
+ $tags = array();
+ $desc = $lines;
+ }
+// var_dump($desc,$tags);
+ $this->$dtype = new parserDocBlock;
+ $this->$dtype->setLineNumber($this->_wp->_docblock_linenum + 1);
+ $this->$dtype->setEndLineNumber($this->_wp->linenum);
+ $this->_pv_dtype = $dtype;
+ $this->$deschandler($desc);
+ $this->handleTags($tags);
+ if ($dtype == '_pv_docblock')
+ {
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_DOCBLOCK,$this->$dtype);
+ $this->$dtype = new parserDocBlock();
+ } else
+ {
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_DOCBLOCK_TEMPLATE,$this->$dtype);
+ }
+ }
+
+ /**
+ * Handles JavaDoc descriptions
+ */
+ function handleJavaDocDesc($desc)
+ {
+ unset($this->_pv_periodline);
+ $this->_pf_useperiod = false;
+ foreach($desc as $i => $line)
+ {
+ $line = trim($line);
+ if (!isset($this->_pv_periodline) && substr($line,strlen($line) - 1) == '.')
+ {
+ $this->_pv_periodline = $i;
+ $this->_pf_useperiod = true;
+ }
+ }
+ if (!isset($this->_pv_periodline)) $this->_pv_periodline = 0;
+
+ $dtype = $this->_pv_dtype;
+ if ($dtype == '_pv_docblock')
+ {
+ $save = $desc;
+ // strip leading <p>
+ if (strpos($desc[0],'<p>') === 0) $desc[0] = substr($desc[0],3);
+ $sdesc = new parserDesc;
+ $desci = '';
+ for($i = 0; ($i <= $this->_pv_periodline) && ($i < count($desc)); $i++)
+ {
+ if (strpos($desc[$i],'.') !== false)
+ {
+ $desci .= substr($desc[$i],0,strpos($desc[$i],'.') + 1);
+ } else
+ {
+ $desci .= $desc[$i];
+ }
+ $desci .= "\n";
+ }
+ $sdesc->add($this->getInlineTags($desci));
+ $desc = $save;
+
+ $my_desc = new parserDesc;
+ if (isset($this->_pv_dtemplate))
+ {
+ // copy template values if not overridden
+ if (!$this->_pv_docblock->getExplicitPackage())
+ {
+ if ($p = $this->_pv_dtemplate->getKeyword('package'))
+ {
+ $this->_pv_docblock->addKeyword('package',$p);
+ $this->_pv_docblock->setExplicitPackage();
+ }
+ if ($p = $this->_pv_dtemplate->getKeyword('category'))
+ {
+ $this->_pv_docblock->addKeyword('category',$p);
+ $this->_pv_docblock->setExplicitCategory();
+ }
+ if ($p = $this->_pv_dtemplate->getKeyword('subpackage'))
+ {
+ $this->_pv_docblock->addKeyword('subpackage',$p);
+ }
+ }
+ $tags = $this->_pv_dtemplate->listTags();
+ foreach($tags as $tag)
+ {
+ $this->_pv_docblock->addTag($tag);
+ }
+ if (!count($this->_pv_docblock->params)) $this->_pv_docblock->params = $this->_pv_dtemplate->params;
+ $my_desc->add($this->_pv_dtemplate->desc);
+ }
+// echo "i = ".$this->_pv_periodline."; i < " . count($desc) . "\n";
+ $desci = '';
+ for($i = 0; $i < count($desc); $i++)
+ {
+ // the line will not be set if it doesn't start with a *
+ if (isset($desc[$i]))
+ {
+ $desci .= $desc[$i]."\n";
+ }
+ }
+ $my_desc->add($this->getInlineTags($desci));
+ } else
+ {
+ $sdesc = new parserDesc;
+ $save = $desc;
+ // strip leading <p>
+ if (strpos($desc[0],'<p>') === 0) $desc[0] = substr($desc[0],3);
+ $desci = '';
+ for($i = 0; ($i <= $this->_pv_periodline) && ($i < count($desc)); $i++)
+ {
+ if (strpos($desc[$i],'.') !== false)
+ {
+ $desci .= substr($desc[$i],0,strpos($desc[$i],'.') + 1);
+ } else
+ {
+ $desci .= $desc[$i];
+ }
+ $desci .= "\n";
+ }
+ $sdesc->add($this->getInlineTags($desci));
+ $desc = $save;
+
+ $my_desc = new parserDesc;
+ $desci = '';
+ for($i=0; $i < count($desc); $i++)
+ {
+ if (isset($desc[$i]))
+ $desci .= $desci[$i]."\n";
+ }
+ $my_desc->add($this->getInlineTags($desci));
+ }
+
+ if ($this->_pf_internal)
+ {
+ addError(PDERROR_INTERNAL_NOT_CLOSED);
+ $this->_pf_internal = false;
+ }
+ $this->$dtype->setShortDesc($sdesc);
+ $this->$dtype->setDesc($my_desc);
+ unset($my_desc);
+// var_dump($this->$dtype);
+// exit;
+ }
+
+ /**
+ * Process the Long Description of a DocBlock
+ * @param array array of lines containing the description with leading
+ * asterisk "*" stripped off.
+ */
+ function handleDesc($desc)
+ {
+ unset($this->_pv_periodline);
+ $this->_pf_useperiod = false;
+ foreach($desc as $i => $line)
+ {
+ $line = trim($line);
+ if (!isset($this->_pv_periodline) && substr($line,strlen($line) - 1) == '.')
+ {
+ $this->_pv_periodline = $i;
+ $this->_pf_useperiod = true;
+ }
+ }
+ if (!isset($this->_pv_periodline)) $this->_pv_periodline = 0;
+ if ($this->_pv_periodline > 3)
+ {
+ $this->_pf_useperiod = false;
+ } else
+ {
+ for($i = 0; $i < $this->_pv_periodline; $i++)
+ {
+ if (strlen($desc[$i]) == 0 && isset($desc[$i - 1]) && strlen($desc[$i - 1]))
+ {
+ $this->_pv_periodline = $i;
+ }
+ }
+ }
+ for($i=0;$i <= $this->_pv_periodline && $i < count($desc);$i++)
+ {
+ if (!strlen(trim($desc[$i]))) $this->_pf_useperiod = false;
+ }
+ // figure out the shortdesc
+ if ($this->_pf_useperiod === false)
+ {
+ // use the first non blank line for short desc
+ for($i = 0; $i < count($desc); $i++)
+ {
+ if (strlen($desc[$i]) > 0)
+ {
+ $this->_pv_periodline = $i;
+ $i = count($desc);
+ }
+ }
+
+ // check to see if we are going to use a blank line to end the shortdesc
+ // this can only be in the first 4 lines
+ if (count($desc) > 4)
+ {
+ $max = 4;
+ } else {
+ $max = count($desc);
+ }
+
+ for($i = $this->_pv_periodline; $i < $max; $i++)
+ {
+ if (strlen(trim($desc[$i])) == 0)
+ {
+ $this->_pv_periodline = $i;
+ $i = $max;
+ }
+ }
+ }
+
+ $dtype = $this->_pv_dtype;
+ if ($dtype == '_pv_docblock')
+ {
+ $sdesc = new parserDesc;
+ $desci = '';
+ for($i = 0; ($i <= $this->_pv_periodline) && ($i < count($desc)); $i++)
+ {
+ $desci .= $desc[$i]."\n";
+ }
+ $sdesc->add($this->getInlineTags($desci));
+ $this->_pv_periodline++;
+
+ $my_desc = new parserDesc;
+ if (isset($this->_pv_dtemplate))
+ {
+ // copy template values if not overridden
+ if (!$this->_pv_docblock->getExplicitPackage())
+ {
+ if ($p = $this->_pv_dtemplate->getKeyword('package'))
+ {
+ $this->_pv_docblock->addKeyword('package',$p);
+ $this->_pv_docblock->setExplicitPackage();
+ }
+ if ($p = $this->_pv_dtemplate->getKeyword('category'))
+ {
+ $this->_pv_docblock->addKeyword('category',$p);
+ $this->_pv_docblock->setExplicitCategory();
+ }
+ if ($p = $this->_pv_dtemplate->getKeyword('subpackage'))
+ {
+ $this->_pv_docblock->addKeyword('subpackage',$p);
+ }
+ }
+ $tags = $this->_pv_dtemplate->listTags();
+ foreach($tags as $tag)
+ {
+ $this->_pv_docblock->addTag($tag);
+ }
+ if (!count($this->_pv_docblock->params)) $this->_pv_docblock->params = $this->_pv_dtemplate->params;
+ $my_desc->add($this->_pv_dtemplate->sdesc);
+ $my_desc->add($this->_pv_dtemplate->desc);
+ }
+// echo "i = ".$this->_pv_periodline."; i < " . count($desc) . "\n";
+ $desci = '';
+ for($i = $this->_pv_periodline; $i < count($desc); $i++)
+ {
+ // the line will not be set if it doesn't start with a *
+ if (isset($desc[$i]))
+ $desci .= $desc[$i]."\n";
+ }
+ $my_desc->add($this->getInlineTags($desci));
+ } else
+ { // this is a docblock template
+ $sdesc = new parserDesc;
+ $desci = '';
+ for($i = 0; ($i <= $this->_pv_periodline) && ($i < count($desc)); $i++)
+ {
+ if (isset($desc[$i]))
+ $desci .= $desc[$i]."\n";
+ }
+ $sdesc->add($this->getInlineTags($desci));
+ $this->_pv_periodline++;
+
+ $my_desc = new parserDesc;
+ $desci = '';
+ for($i=$this->_pv_periodline; $i < count($desc); $i++)
+ {
+ if (isset($desc[$i]))
+ $desci .= $desc[$i]."\n";
+ }
+ $my_desc->add($this->getInlineTags($desci));
+ }
+ if ($this->_pf_internal)
+ {
+ addError(PDERROR_INTERNAL_NOT_CLOSED);
+ $this->_pf_internal = false;
+ }
+ $this->$dtype->setShortDesc($sdesc);
+ $this->$dtype->setDesc($my_desc);
+ unset($my_desc);
+// var_dump($this->$dtype);
+// exit;
+ }
+
+ /**
+ * Process the tags of a DocBlock
+ * @param array array of lines that contain all @tags
+ */
+ function handleTags($tags)
+ {
+ $newtags = array();
+ $curtag = '';
+ for($i=0;$i < count($tags);$i++)
+ {
+ if (strpos(trim($tags[$i]),'@') === 0) $tags[$i] = ltrim($tags[$i]);
+ if (substr($tags[$i],0,1) == '@' && substr($tags[$i],0,2) != '@ ')
+ { // start a new tag
+ if (!empty($curtag))
+ {
+ $newtags[] = $curtag;
+ }
+ $curtag = $tags[$i];
+ } else $curtag .= "\n".$tags[$i];
+ }
+ if (!empty($curtag)) $newtags[] = $curtag;
+ foreach($newtags as $tag)
+ {
+ $x = explode(' ',str_replace("\t",' ',$tag));
+ $tagname = substr(array_shift($x),1);
+ $restoftag = $x;
+ if (isset($this->tagHandlers[$tagname]))
+ $handle = $this->tagHandlers[$tagname];
+ else
+ $handle = $this->tagHandlers['*'];
+ $this->$handle($tagname,$restoftag);
+ }
+ }
+
+ /**
+ * Process all inline tags in text, and convert them to their abstract
+ * object representations.
+ * @param string|array complete code to search for inline tags, if an
+ * array, it's an array of strings
+ * @return parserStringWithInlineTags
+ */
+ function getInlineTags($value)
+ {
+ if (is_array($value)) $value = join("\n",$value);
+ global $_phpDocumentor_setting;
+ $priv = (isset($_phpDocumentor_setting['parseprivate']) && $_phpDocumentor_setting['parseprivate'] == 'on');
+ $a = new parserStringWithInlineTags();
+ if (!$priv && $this->_pf_internal)
+ {
+ if ($x = strpos($value,'}}'))
+ {
+ $x = strrpos($value,'}}');
+ $value = substr($value,$x + 1);
+ $this->_pf_internal = false;
+ } else $value = '';
+ } elseif ($this->_pf_internal)
+ {
+ if ($x = strpos($value,'}}'))
+ {
+ $x = strrpos($value,'}}');
+ $value = substr($value,0,$x) . substr($value,$x+2);
+ }
+ }
+ $save = $value;
+ $value = explode('{@',$value);
+ $newval = array();
+ $a->add($value[0]);
+ for($i=1;$i<count($value);$i++)
+ {
+ if (!$priv && $this->_pf_internal)
+ { // ignore anything between {@internal and }}
+ if (strpos($value[$i],'}}') !== false)
+ {
+ $x = strrpos($value[$i],'}}');
+ $value[$i] = substr($value[$i],$x + 1);
+ $this->_pf_internal = false;
+ if (!$value[$i]) continue;
+ $a->add($value[$i]);
+ continue;
+ } else continue;
+ }
+ if (substr($value[$i],0,1) == '}')
+ {
+ $a->add('{@'.substr($value[$i],1));
+ } elseif (substr($value[$i],0,2) == '*}')
+ { // used for inserting */ in code examples
+ $a->add('*/'.substr($value[$i],2));
+ } else
+ {
+ $save = $value[$i];
+ $value[$i] = split("[\t ]",str_replace("\t",' ',$value[$i]));
+ $word = trim(array_shift($value[$i]));
+ $val = join(' ',$value[$i]);
+ if (trim($word) == 'internal')
+ {
+ $this->_pf_internal = true;
+ $value[$i] = substr($save,strlen('internal') + 1);
+ if (strpos($value[$i],'}}') !== false)
+ {
+ $x = strrpos($value[$i],'}}');
+ // strip internal and cycle as if it were normal text.
+ $startval = substr($value[$i],0,$x - 1);
+ if ($priv) $a->add($startval);
+ $value[$i] = substr($value[$i],$x + 1);
+ if (!$value[$i]) $value[$i] = '';
+ $this->_pf_internal = false;
+ $a->add($value[$i]);
+ continue;
+ } elseif ($priv) $a->add($value[$i]);
+ continue;
+ }
+ if (in_array(str_replace('}','',trim($word)),$this->allowableInlineTags))
+ {
+ if (strpos($word,'}'))
+ {
+ $res = substr($word,strpos($word, '}'));
+ $word = str_replace('}','',trim($word));
+ $val = $res.$val;
+ }
+ if ($word == 'source')
+ {
+ $this->_pf_get_source = true;
+ }
+ $val = explode('}',$val);
+ if (count($val) == 1)
+ {
+ addError(PDERROR_UNTERMINATED_INLINE_TAG,$word,'',$save);
+ }
+ $rest = $val;
+ $val = array_shift($rest);
+ $rest = join('}',$rest);
+ if (isset($this->inlineTagHandlers[$word]))
+ $handle = $this->inlineTagHandlers[$word];
+ else
+ $handle = $this->inlineTagHandlers['*'];
+ $val = $this->$handle($word,$val);
+ $a->add($val);
+ if ($this->_pf_internal)
+ {
+ if (strpos($rest,'}}') !== false)
+ {
+ $value[$i] = $rest;
+ $x = strrpos($value[$i],'}}');
+ $startval = substr($value[$i],0,$x - 1);
+ if ($priv) $a->add($startval);
+ $value[$i] = substr($value[$i],$x + 1);
+ if (!$value[$i]) $value[$i] = '';
+ $this->_pf_internal = false;
+ $a->add($value[$i]);
+ } else $a->add($rest);
+ } else $a->add($rest);
+ } else
+ {
+ $val = $word.' '.$val;
+ $a->add('{@'.$val);
+ }
+ }
+ }
+ return $a;
+ }
+ /**#@-*/
+ /**#@+
+ * @param string name of the tag
+ * @param string any parameters passed to the inline tag
+ * @access private
+ */
+ /**
+ * Most inline tags require no special processing
+ *
+ */
+ function handleDefaultInlineTag($name, $value)
+ {
+ $tag = 'parser'.ucfirst($name).'InlineTag';
+ return new $tag($value,$value);
+ }
+
+ /**
+ * Handle the inline {@}link} tag
+ * @tutorial tags.inlinelink.pkg
+ */
+ function handleLinkInlineTag($name, $value)
+ {
+ // support hyperlinks of any protocol
+ if (is_numeric(strpos($value,'://')) || (strpos(trim($value),'mailto:') === 0))
+ {
+ $value = str_replace('\\,', '###commanana####', $value);
+ if (strpos($value,','))
+ {
+ $val = new parserLinkInlineTag($value,$value);
+ } elseif (strpos(trim($value),' '))
+ { // if there is more than 1 parameter, the stuff after the space is the hyperlink text
+ $i1 = strpos(trim($value),' ') + 1;
+ $link = substr(trim($value),0,$i1 - 1);
+ $text = substr(trim($value),$i1);
+ $val = new parserLinkInlineTag($link,$text);
+ } else
+ {
+ $val = new parserLinkInlineTag($value,$value);
+ }
+ } else
+ {
+ $value = str_replace('\\,', '###commanana####', $value);
+ if (!strpos($value,','))
+ {
+ $testp = explode('#',$value);
+ if (count($testp) - 1)
+ $val = new parserLinkInlineTag($value,$testp[1]);
+ else
+ $val = new parserLinkInlineTag($value,$value);
+ } else
+ $val = new parserLinkInlineTag($value,$value);
+ }
+ return $val;
+ }
+
+ /**#@-*/
+ /**#@+
+ * @access private
+ * @param string name of tag
+ * @param array all words in the tag that were separated by a space ' '
+ */
+ /**
+ * Most tags only need the value as a string
+ * @uses getInlineTags() all tag handlers check their values for inline tags
+ */
+ function defaultTagHandler($name, $value)
+ {
+ $dtype = $this->_pv_dtype;
+ $this->$dtype->addKeyword($name,$this->getInlineTags(join(' ',$value)));
+ }
+
+ /**
+ * @tutorial tags.example.pkg
+ * @uses parserDocBlock::addExample()
+ */
+ function exampleTagHandler($name, $value)
+ {
+ $dtype = $this->_pv_dtype;
+ $this->$dtype->addExample($this->getInlineTags(join(' ',$value)), $this->_path);
+ }
+
+ /**
+ * @tutorial tags.filesource.pkg
+ * @uses phpDocumentorTWordParser::getFileSource() retrieves the source for
+ * use in the @filesource tag
+ */
+ function filesourceTagHandler($name, $value)
+ {
+ $dtype = $this->_pv_dtype;
+ $this->$dtype->addFileSource($this->_path, $this->_wp->getFileSource());
+ }
+
+ /**
+ * @tutorial tags.uses.pkg
+ */
+ function usesTagHandler($name, $value)
+ {
+ $dtype = $this->_pv_dtype;
+ $seel = '';
+ while ($seel == '' && count($value))
+ {
+ $seel = array_shift($value);
+ }
+ $this->$dtype->addUses($this->getInlineTags($seel), $this->getInlineTags(join(' ',$value)));
+ }
+
+ /**
+ * @tutorial tags.author.pkg
+ */
+ function authorTagHandler($name, $value)
+ {
+ $dtype = $this->_pv_dtype;
+ $value = join(' ',$value);
+ if ((strpos($value,'<') !== false) && (strpos($value,'>') !== false))
+ {
+ $email = substr($value,strpos($value,'<') + 1,strpos($value,'>') - strpos($value,'<') - 1);
+ $value = str_replace('<'.$email.'>','<{@link mailto:'.$email.' ' .
+ $email . '}>',$value);
+ }
+ $this->$dtype->addKeyword('author',$this->getInlineTags($value));
+ }
+
+ /**
+ * @tutorial tags.package.pkg
+ */
+ function packageTagHandler($name, $value)
+ {
+ if (count($value) && empty($value[0]))
+ {
+ $found = false;
+ for($i=0;$i<count($value) && !strlen($value[$i]);$i++);
+ array_splice($value,0,$i);
+ }
+ $this->defaultTagHandler($name, $value);
+ $dtype = $this->_pv_dtype;
+ $this->$dtype->setExplicitPackage();
+ }
+
+ /**
+ * @tutorial tags.category.pkg
+ */
+ function categoryTagHandler($name, $value)
+ {
+ if (count($value) && empty($value[0]))
+ {
+ $found = false;
+ for($i=0;$i<count($value) && !strlen($value[$i]);$i++);
+ array_splice($value,0,$i);
+ }
+ $this->defaultTagHandler($name, $value);
+ $dtype = $this->_pv_dtype;
+ $this->$dtype->setExplicitCategory();
+ }
+
+ /**
+ * @tutorial tags.global.pkg
+ */
+ function globalTagHandler($name, $value)
+ {
+ $info = $this->retrieveType($value, true);
+ if (!$info) addErrorDie(PDERROR_MALFORMED_TAG, '@global');
+ $type = $info['type'];
+ $var = $info['var'];
+ $desc = $info['desc'];
+ $dtype = $this->_pv_dtype;
+ if (!$var && empty($desc))
+ {
+ if ($type{0} == '$') addError(PDERROR_MALFORMED_GLOBAL_TAG);
+ return $this->$dtype->addFuncGlobal($type,new parserStringWithInlineTags);
+ }
+ if ($var)
+ { // global define
+ $this->_pv_global_type = $type;
+ if (!empty($desc)) $var .= ' '.$desc;
+ $this->findGlobal(trim($var));
+ } elseif (!empty($desc))
+ { // function global
+ if ($type{0} == '$') addError(PDERROR_MALFORMED_GLOBAL_TAG);
+ $this->$dtype->addFuncGlobal($type,$this->getInlineTags($desc));
+ } else
+ {
+ addError(PDERROR_MALFORMED_GLOBAL_TAG);
+ }
+ }
+
+ /**
+ * @tutorial tags.staticvar.pkg
+ */
+ function staticvarTagHandler($name, $value)
+ {
+ $info = $this->retrieveType($value, true);
+ if (!$info) addErrorDie(PDERROR_MALFORMED_TAG, '@staticvar');
+ $type = $info['type'];
+ $var = $info['var'];
+ $desc = $info['desc'];
+ $dtype = $this->_pv_dtype;
+ if (!$var && empty($desc))
+ {
+ $this->$dtype->addStaticVar(null,$type,new parserStringWithInlineTags);
+ } else
+ {
+ if ($var)
+ {
+ $this->$dtype->addStaticVar($var,$type,$this->getInlineTags($desc));
+ } else
+ {
+ $this->$dtype->addStaticVar(null,$type,$this->getInlineTags($desc));
+ }
+ }
+ }
+
+ /**
+ * @tutorial tags.param.pkg
+ */
+ function paramTagHandler($name, $value)
+ {
+ $info = $this->retrieveType($value, true);
+ //if (!$info) addErrorDie(PDERROR_MALFORMED_TAG, '@param');
+ if (!$info) { addError(PDERROR_MALFORMED_TAG, '@param'); return; }
+ $type = $info['type'];
+ $var = $info['var'];
+ $desc = $info['desc'];
+ $dtype = $this->_pv_dtype;
+ if (!$var && empty($desc))
+ {
+ $this->$dtype->addParam(null,$type,new parserStringWithInlineTags);
+ } else
+ {
+ if ($var)
+ {
+ $this->$dtype->addParam($var,$type,$this->getInlineTags($desc));
+ } else
+ {
+ $this->$dtype->addParam(null,$type,$this->getInlineTags($desc));
+ }
+ }
+ }
+
+ /**
+ * @tutorial tags.return.pkg
+ */
+ function returnTagHandler($name, $value)
+ {
+ $info = $this->retrieveType($value, true);
+ //if (!$info) addErrorDie(PDERROR_MALFORMED_TAG, '@return');
+ if (!$info) { addError(PDERROR_MALFORMED_TAG, '@return'); return; }
+ $type = $info['type'];
+ $desc = $info['desc'];
+ $dtype = $this->_pv_dtype;
+ $this->$dtype->addReturn($type,$this->getInlineTags($desc));
+ }
+
+ /**
+ * @tutorial tags.var.pkg
+ */
+ function varTagHandler($name, $value)
+ {
+ $info = $this->retrieveType($value, true);
+ if (!$info) addErrorDie(PDERROR_MALFORMED_TAG, '@var');
+ $type = $info['type'];
+ $desc = $info['desc'];
+ $dtype = $this->_pv_dtype;
+ $this->$dtype->addVar($type,$this->getInlineTags($desc));
+ }
+ /**#@-*/
+ /**#@+
+ * @access private
+ */
+
+ /**
+ * Retrieve the type portion of a @tag type description
+ *
+ * Tags like @param, @return and @var all have a PHP type portion in their
+ * description. Since the type may contain the expression "object blah"
+ * where blah is a classname, it makes parsing out the type field complex.
+ *
+ * Even more complicated is the case where a tag variable can contain
+ * multiple types, such as object blah|object blah2|false, and so this
+ * method handles these cases.
+ * @param array array of words that were separated by spaces
+ * @param boolean flag to determine whether to check for the end of a
+ * type is defined by a $varname
+ * @return array Format: array('type' => string, 'var' =>
+ * false|string variable name, 'desc' => rest
+ * of the tag)
+ */
+ function retrieveType($value, $checkforvar = false)
+ {
+ if (!count($value)) return false;
+ $result = array();
+ $types = '';
+ // remove empty entries resulting from extra spaces between @tag and type
+ $this->_removeWhiteSpace($value, 0);
+ $index = 0;
+ if (trim($value[0]) == 'object')
+ {
+ $types .= array_shift($value).' ';
+ $this->_removeWhiteSpace($value, 0);
+ if (!count($value))
+ { // was just passed "object"
+ $result = array('type' => rtrim($types),'desc' => '');
+ if ($checkforvar) $result['var'] = false;
+ return $result;
+ }
+ if ($value[0]{0} == '$' || substr($value[0],0,2) == '&$')
+ { // was just passed "object" and the next thing is a variable name
+ $result['var'] = $value[0];
+ $result['type'] = 'object';
+ array_shift($value);
+ $result['desc'] = join(' ', $value);
+ return $result;
+ }
+ }
+ $done = false;
+ do
+ { // this loop checks for type|type|type and for
+ // type|object classname|type|object classname2
+ if (strpos($value[0], '|'))
+ {
+ $temptypes = explode('|', $value[0]);
+ while(count($temptypes))
+ {
+ $type = array_shift($temptypes);
+ $types .= $type;
+ if (count($temptypes)) $types .= '|';
+ }
+ if (trim($type) == 'object')
+ {
+ $types .= ' ';
+ $this->_removeWhiteSpace($value,0);
+ } else $done = true;
+ array_shift($value);
+ if (isset ($value[0]) && strlen($value[0]) && ($value[0]{0} == '$' || substr($value[0],0,2) == '&$'))
+ { // was just passed "object" and the next thing is a variable name
+ $result['var'] = $value[0];
+ $result['type'] = $types;
+ array_shift($value);
+ $result['desc'] = join(' ', $value);
+ return $result;
+ }
+ } else
+ {
+ $types .= $value[0];
+ array_shift($value);
+ $done = true;
+ }
+ } while (!$done && count($value));
+ $result['type'] = rtrim($types);
+ $this->_removeWhiteSpace($value,0);
+ if ($checkforvar)
+ {
+ if (!count($value))
+ {
+ $result['var'] = false;
+ } else
+ {
+ if (substr($value[0],0,1) == '$' || substr($value[0],0,2) == '&$')
+ {
+ $result['var'] = $value[0];
+ array_shift($value);
+ } else $result['var'] = false;
+ }
+ }
+ $result['desc'] = join(' ',$value);
+ return $result;
+ }
+
+ /**
+ * @param array array of string
+ * @param integer index to seek non-whitespace to
+ */
+ function _removeWhiteSpace(&$value, $index)
+ {
+ if (count($value) > $index && empty($value[$index]))
+ {
+ $found = false;
+ for($i=$index; $i<count($value) && !strlen($value[$i]); $i++);
+ array_splice($value, $index, $i - $index);
+ }
+ }
+
+ /**
+ * Retrieve all the tokens that represent the definition of the global
+ * variable.
+ *
+ * {@source}
+ */
+ function findGlobal($name)
+ {
+ $tokens = token_get_all('<?php '.$name);
+ $tokens = array_slice($tokens,1);
+ $this->_wp->findGlobal($tokens);
+ $this->_pv_findglobal = $name;
+ }
+
+ /**
+ * handler for DEFINE_GLOBAL
+ */
+ function handleGlobal($word, $pevent)
+ {
+ if (isset($this->_pv_findglobal))
+ {
+ $this->_pv_global_name = $this->_pv_findglobal;
+ unset($this->_pv_findglobal);
+ }
+ if (!$this->_pf_in_global)
+ {
+ $this->_pv_linenum = $this->_wp->linenum + 1;
+ }
+ $this->_pf_in_global = true;
+ if($this->checkEventPush($word, $pevent))
+ {
+ $this->_wp->setWhitespace(true);
+ }
+ if ($this->checkEventPop($word, $pevent))
+ {
+ $this->_pf_in_global = false;
+ $a = new parserGlobal;
+ $a->setDataType($this->_pv_global_type);
+ $this->_pv_global_type = '';
+ $a->setLineNumber($this->_pv_linenum);
+ $a->setName($this->_pv_global_name);
+ if (isset($this->_pv_global_val))
+ $a->setValue(trim($this->_pv_global_val));
+ $this->publishEvent(PHPDOCUMENTOR_EVENT_GLOBAL,$a);
+ unset($this->_pv_global_val);
+ unset($this->_pv_global_type);
+ }
+ }
+
+ /**
+ * handler for GLOBAL_VALUE
+ */
+ function handleGlobalValue($word, $pevent)
+ {
+ if ($this->checkEventPush($word, $pevent)) return;
+ $this->_wp->setWhitespace(true);
+ if (!isset($this->_pv_global_val)) $this->_pv_global_val = '';
+ if ($this->_last_pevent == PARSER_EVENT_ARRAY)
+ {
+ $this->_pv_global_val .= $this->_pv_function_data;
+ $this->_pv_function_data = '';
+ }
+ if ($this->_last_pevent == PARSER_EVENT_QUOTE ||
+ $this->_last_pevent == PARSER_EVENT_EOFQUOTE)
+ {
+ $this->_pv_global_val .= $this->_pv_quote_data;
+ unset($this->_pv_quote_data);
+ }
+ if ($this->checkEventPop($word, $pevent))
+ {
+ $this->_wp->setWhitespace(false);
+ $this->_wp->backupPos();
+ return;
+ }
+ if (is_array($word)) $word = $word[1];
+ $this->_pv_global_val .= $word;
+ }
+
+ /**#@-*/
+ /**
+ * this function checks whether parameter $word is a token for pushing a new event onto the Event Stack.
+ * @return mixed returns false, or the event number
+ */
+
+ function checkEventPush($word,$pevent)
+ {
+ if (is_array($word) && $word[0] == T_STRING) $word = $word[1];
+ if (is_array($word))
+ {
+ $pushEvent = &$this->tokenpushEvent;
+ $word = $word[0];
+ } else
+ {
+ $pushEvent = &$this->wordpushEvent;
+ $word = strtolower($word);
+ }
+ $e = false;
+ if (isset($pushEvent[$pevent]))
+ {
+ if (isset($pushEvent[$pevent][$word]))
+ $e = $pushEvent[$pevent][$word];
+ }
+ if ($e)
+ {
+ $this->_event_stack->pushEvent($e);
+ return $e;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * this function checks whether parameter $word is a token for popping the current event off of the Event Stack.
+ * @return mixed returns false, or the event number popped off of the stack
+ */
+
+ function checkEventPop($word,$pevent)
+ {
+ if (is_array($word) && $word[0] == T_STRING) $word = $word[1];
+ if (is_array($word))
+ {
+ $popEvent = &$this->tokenpopEvent;
+ $word = $word[0];
+ } else
+ {
+ $popEvent = &$this->wordpopEvent;
+ $word = strtolower($word);
+ }
+ if (!isset($popEvent[$pevent])) return false;
+ if (in_array($word,$popEvent[$pevent]))
+ {
+ return $this->_event_stack->popEvent();
+ } else {
+ return false;
+ }
+ }
+
+ function getToken($word)
+ {
+ if (is_array($word)) return $word[0];
+ return false;
+ }
+
+ /**
+ * setup the parser tokens, and the pushEvent/popEvent arrays
+ * @see $tokens, $pushEvent, $popEvent
+ */
+
+ function setupStates()
+ {
+ unset($this->_wp);
+ $this->_wp = new phpDocumentorTWordParser;
+ $this->_pv_class = null;
+ $this->_pv_cur_class = null;
+ $this->_pv_define = null;
+ $this->_pv_define_name = null;
+ $this->_pv_define_value = null;
+ $this->_pv_define_params_data = null;
+ $this->_pv_dtype = null;
+ $this->_pv_docblock = null;
+ $this->_pv_dtemplate = null;
+ $this->_pv_func = null;
+ $this->_pv_findglobal = null;
+ $this->_pv_global_name = null;
+ $this->_pv_global_val = null;
+ $this->_pv_globals = null;
+ $this->_pv_global_count = null;
+ $this->_pv_include_params_data = null;
+ $this->_pv_include_name = null;
+ $this->_pv_include_value = null;
+ $this->_pv_linenum = null;
+ $this->_pv_periodline = null;
+ $this->_pv_paren_count = 0;
+ $this->_pv_statics = null;
+ $this->_pv_static_count = null;
+ $this->_pv_static_val = null;
+ $this->_pv_quote_data = null;
+ $this->_pv_function_data = null;
+ $this->_pv_var = null;
+ $this->_pv_varname = null;
+ $this->_pv_const = null;
+ $this->_pv_constname = null;
+ $this->_pv_function_param_type = null;
+ $this->_pf_definename_isset = false;
+ $this->_pf_includename_isset = false;
+ $this->_pf_get_source = false;
+ $this->_pf_getting_source = false;
+ $this->_pf_in_class = false;
+ $this->_pf_in_define = false;
+ $this->_pf_in_global = false;
+ $this->_pf_in_include = false;
+ $this->_pf_in_var = false;
+ $this->_pf_in_const = false;
+ $this->_pf_funcparam_val = false;
+ $this->_pf_quote_active = false;
+ $this->_pf_reset_quote_data = true;
+ $this->_pf_useperiod = false;
+ $this->_pf_var_equals = false;
+ $this->_pf_const_equals = false;
+ $this->_event_stack = new EventStack;
+ }
+
+ /**
+ * Creates the state arrays
+ */
+ function setupEventStates()
+ {
+ if (!defined('T_DOC_COMMENT'))
+ {
+ define('T_DOC_COMMENT', T_DOC_COMMENT);
+ }
+/**************************************************************/
+
+ $this->wordpushEvent[PARSER_EVENT_LOGICBLOCK] =
+ array(
+ "{" => PARSER_EVENT_LOGICBLOCK,
+ '"' => PARSER_EVENT_QUOTE,
+ );
+ $this->tokenpushEvent[PARSER_EVENT_LOGICBLOCK] =
+ array(
+ T_GLOBAL => PARSER_EVENT_FUNC_GLOBAL,
+ T_STATIC => PARSER_EVENT_STATIC_VAR,
+ T_START_HEREDOC => PARSER_EVENT_EOFQUOTE,
+ T_CURLY_OPEN => PARSER_EVENT_LOGICBLOCK,
+ T_DOLLAR_OPEN_CURLY_BRACES => PARSER_EVENT_LOGICBLOCK,
+ );
+
+ $this->wordpopEvent[PARSER_EVENT_LOGICBLOCK] = array("}");
+ $this->tokenpopEvent[PARSER_EVENT_LOGICBLOCK] = array(T_CURLY_OPEN);
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_NOEVENTS] =
+ array(
+ T_OPEN_TAG => PARSER_EVENT_PHPCODE,
+ );
+
+/**************************************************************/
+
+ $this->tokenpopEvent[PARSER_EVENT_EOFQUOTE] = array(T_END_HEREDOC);
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_PHPCODE] =
+ array(
+ T_FUNCTION => PARSER_EVENT_FUNCTION,
+ T_ABSTRACT => PARSER_EVENT_ACCESS_MODIFIER,
+ T_CLASS => PARSER_EVENT_CLASS,
+ T_INTERFACE => PARSER_EVENT_CLASS,
+ T_INCLUDE_ONCE => PARSER_EVENT_INCLUDE,
+ T_INCLUDE => PARSER_EVENT_INCLUDE,
+ T_REQUIRE => PARSER_EVENT_INCLUDE,
+ T_REQUIRE_ONCE => PARSER_EVENT_INCLUDE,
+ T_COMMENT => PARSER_EVENT_DOCBLOCK,
+ T_DOC_COMMENT => PARSER_EVENT_DOCBLOCK,
+// "/**#@+" => PARSER_EVENT_DOCBLOCK_TEMPLATE,
+// "/**#@-*/" => PARSER_EVENT_END_DOCBLOCK_TEMPLATE,
+ T_CLOSE_TAG => PARSER_EVENT_OUTPHP,
+ );
+ $this->wordpushEvent[PARSER_EVENT_PHPCODE] =
+ array(
+ "define" => PARSER_EVENT_DEFINE,
+ );
+/**************************************************************/
+
+ $this->tokenpopEvent[PARSER_EVENT_OUTPHP] = array(T_OPEN_TAG);
+/**************************************************************/
+
+ $this->wordpushEvent[PARSER_EVENT_FUNCTION] =
+ array(
+ '{' => PARSER_EVENT_LOGICBLOCK,
+ '(' => PARSER_EVENT_FUNCTION_PARAMS,
+ );
+ $this->tokenpushEvent[PARSER_EVENT_FUNCTION] =
+ array(
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_COMMENT,
+ );
+
+ $this->wordpopEvent[PARSER_EVENT_FUNCTION] = array("}",';');
+/**************************************************************/
+
+ $this->wordpopEvent[PARSER_EVENT_QUOTE] = array('"');
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_FUNCTION_PARAMS] =
+ array(
+ T_CONSTANT_ENCAPSED_STRING => PARSER_EVENT_QUOTE,
+ T_ARRAY => PARSER_EVENT_ARRAY,
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_COMMENT,
+ );
+ $this->wordpushEvent[PARSER_EVENT_FUNCTION_PARAMS] =
+ array(
+ '"' => PARSER_EVENT_QUOTE,
+ "'" => PARSER_EVENT_QUOTE,
+ );
+ $this->wordpopEvent[PARSER_EVENT_FUNCTION_PARAMS] = array(")");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_ARRAY] =
+ array(
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_COMMENT,
+ );
+ $this->wordpopEvent[PARSER_EVENT_ARRAY] = array(")");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_VAR_ARRAY] =
+ array(
+ T_COMMENT => PARSER_EVENT_VAR_ARRAY_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_VAR_ARRAY_COMMENT,
+ );
+ $this->wordpopEvent[PARSER_EVENT_VAR_ARRAY] = array(")");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_FUNC_GLOBAL] =
+ array(
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_COMMENT,
+ );
+
+ $this->wordpopEvent[PARSER_EVENT_FUNC_GLOBAL] = array(";");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_STATIC_VAR] =
+ array(
+ T_CONSTANT_ENCAPSED_STRING => PARSER_EVENT_QUOTE,
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_COMMENT,
+ );
+ $this->wordpushEvent[PARSER_EVENT_STATIC_VAR] =
+ array(
+ "=" => PARSER_EVENT_STATIC_VAR_VALUE,
+ );
+ $this->wordpopEvent[PARSER_EVENT_STATIC_VAR] = array(";");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_STATIC_VAR_VALUE] =
+ array(
+ T_CONSTANT_ENCAPSED_STRING => PARSER_EVENT_QUOTE,
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_COMMENT,
+ T_ARRAY => PARSER_EVENT_ARRAY,
+ );
+ $this->wordpushEvent[PARSER_EVENT_STATIC_VAR_VALUE] =
+ array(
+ '"' => PARSER_EVENT_QUOTE,
+ "'" => PARSER_EVENT_QUOTE,
+ );
+ $this->wordpopEvent[PARSER_EVENT_STATIC_VAR_VALUE] = array(";",",");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_DEFINE] =
+ array(
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_COMMENT,
+ T_CONSTANT_ENCAPSED_STRING => PARSER_EVENT_QUOTE,
+ );
+ $this->wordpushEvent[PARSER_EVENT_DEFINE] =
+ array(
+ "(" => PARSER_EVENT_DEFINE_PARAMS,
+ );
+ $this->wordpopEvent[PARSER_EVENT_DEFINE] = array(";");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_INCLUDE] =
+ array(
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_COMMENT,
+ );
+ $this->wordpushEvent[PARSER_EVENT_INCLUDE] =
+ array(
+ "(" => PARSER_EVENT_INCLUDE_PARAMS,
+ );
+ $this->wordpopEvent[PARSER_EVENT_INCLUDE] = array(";");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_DEFINE_PARAMS] =
+ array(
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_COMMENT,
+ T_START_HEREDOC => PARSER_EVENT_EOFQUOTE,
+ );
+ $this->wordpushEvent[PARSER_EVENT_DEFINE_PARAMS] =
+ array(
+ "(" => PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS,
+ '"' => PARSER_EVENT_QUOTE,
+ "'" => PARSER_EVENT_QUOTE,
+ );
+ $this->wordpopEvent[PARSER_EVENT_DEFINE_PARAMS] = array(")");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_INCLUDE_PARAMS] =
+ array(
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_COMMENT,
+ );
+ $this->wordpushEvent[PARSER_EVENT_INCLUDE_PARAMS] =
+ array(
+ "(" => PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS,
+ );
+ $this->wordpopEvent[PARSER_EVENT_INCLUDE_PARAMS] = array(")");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS] =
+ array(
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_COMMENT,
+ );
+ $this->wordpushEvent[PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS] =
+ array(
+ "(" => PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS,
+ '"' => PARSER_EVENT_QUOTE,
+ "'" => PARSER_EVENT_QUOTE,
+ );
+ $this->wordpopEvent[PARSER_EVENT_DEFINE_PARAMS_PARENTHESIS] = array(")");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS] =
+ array(
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_COMMENT,
+ );
+ $this->wordpushEvent[PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS] =
+ array(
+ "(" => PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS,
+ );
+ $this->wordpopEvent[PARSER_EVENT_INCLUDE_PARAMS_PARENTHESIS] = array(")");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_VAR] =
+ array(
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_COMMENT,
+ T_ARRAY => PARSER_EVENT_VAR_ARRAY,
+ );
+ $this->wordpopEvent[PARSER_EVENT_VAR] = array(";");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_CLASS_CONSTANT] =
+ array(
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_COMMENT,
+ T_ARRAY => PARSER_EVENT_VAR_ARRAY,
+ );
+ $this->wordpopEvent[PARSER_EVENT_CLASS_CONSTANT] = array(";");
+/**************************************************************/
+
+ $this->wordpopEvent[PARSER_EVENT_IMPLEMENTS] = array('{');
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_CLASS] =
+ array(
+ T_ABSTRACT => PARSER_EVENT_ACCESS_MODIFIER,
+ T_PUBLIC => PARSER_EVENT_ACCESS_MODIFIER,
+ T_PRIVATE => PARSER_EVENT_ACCESS_MODIFIER,
+ T_PROTECTED => PARSER_EVENT_ACCESS_MODIFIER,
+ T_STATIC => PARSER_EVENT_ACCESS_MODIFIER,
+ T_IMPLEMENTS => PARSER_EVENT_IMPLEMENTS,
+ T_CONST => PARSER_EVENT_CLASS_CONSTANT,
+ T_FUNCTION => PARSER_EVENT_FUNCTION,
+ T_VAR => PARSER_EVENT_VAR,
+ T_COMMENT => PARSER_EVENT_DOCBLOCK,
+ T_DOC_COMMENT => PARSER_EVENT_DOCBLOCK,
+ T_CLOSE_TAG => PARSER_EVENT_OUTPHP,
+ );
+ $this->wordpopEvent[PARSER_EVENT_CLASS] = array("}");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_DEFINE_GLOBAL] =
+ array(
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_COMMENT,
+ );
+ $this->wordpushEvent[PARSER_EVENT_DEFINE_GLOBAL] =
+ array(
+ "=" => PARSER_EVENT_GLOBAL_VALUE,
+ );
+ $this->wordpopEvent[PARSER_EVENT_DEFINE_GLOBAL] = array(";");
+/**************************************************************/
+
+ $this->tokenpushEvent[PARSER_EVENT_GLOBAL_VALUE] =
+ array(
+ T_ARRAY => PARSER_EVENT_ARRAY,
+ T_COMMENT => PARSER_EVENT_COMMENT,
+ T_DOC_COMMENT => PARSER_EVENT_COMMENT,
+ T_START_HEREDOC => PARSER_EVENT_EOFQUOTE,
+ );
+ $this->wordpushEvent[PARSER_EVENT_GLOBAL_VALUE] =
+ array(
+ '"' => PARSER_EVENT_QUOTE,
+ "'" => PARSER_EVENT_QUOTE,
+ );
+ $this->wordpopEvent[PARSER_EVENT_GLOBAL_VALUE] = array(";");
+ }
+
+ function configWordParser(&$data)
+ {
+ $this->_wp->setup($data);
+ $this->_wp->setWhitespace(false);
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/phpDocumentorTWordParser.inc b/buildscripts/PhpDocumentor/phpDocumentor/phpDocumentorTWordParser.inc
new file mode 100644
index 00000000..36538408
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/phpDocumentorTWordParser.inc
@@ -0,0 +1,311 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+/**
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @package phpDocumentor
+ * @subpackage WordParsers
+ * @since 1.2
+ */
+/**
+ * Like WordParser, but expects an array of tokens from the tokenizer instead
+ * of a string.
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @package phpDocumentor
+ * @subpackage WordParsers
+ * @since 1.2
+ */
+class phpDocumentorTWordParser extends WordParser
+{
+ /**#@+
+ * @access private
+ */
+ /**
+ * tokenized array from {@link token_get_all()}
+ * @var array
+ */
+ var $_all;
+ /**
+ * List of tokens that can contain a newline
+ * @var array
+ */
+ var $_nl_check = array(
+ T_WHITESPACE,
+ T_ENCAPSED_AND_WHITESPACE,
+ T_COMMENT,
+ T_DOC_COMMENT,
+ T_OPEN_TAG,
+ T_CLOSE_TAG,
+ T_INLINE_HTML);
+ /**
+ * @var array
+ */
+ var $_global_search;
+ /**
+ * current source line number (relative)
+ * @var integer
+ */
+ var $_sourceline;
+ /**
+ * Source of the entire file, parsed into arrays of tokens on each line
+ * @var array
+ */
+ var $_file_source = array();
+ /**
+ * Line number the last comment was on
+ * @var integer
+ */
+ var $_docblock_linenum;
+ /**#@-*/
+
+ /**
+ * Uses {@link token_get_all()} to tokenize the source code.
+ * {@internal
+ * Also, it divides the source tokens into separate lines for use by
+ * the @filesource tag.
+ *
+ * {@source}}}
+ * @var string source code
+ */
+ function setup(&$input)
+ {
+ $input = rtrim(ltrim($input, "\r\n"));
+ $this->data = &$input;
+ // fix php warnings on invalid source code
+ $this->_all = @token_get_all($input);
+ $this->_file_source = array();
+ $this->addFileSource($this->_all);
+ $this->_sourceline = 0;
+ $this->pos = 0;
+ $this->linenum = 0;
+ }
+
+ /**
+ * @return array
+ */
+ function getSource()
+ {
+ $source = $this->source;
+ $this->source = array();
+ $this->getsource = false;
+ return $source;
+ }
+
+ /**
+ * @return array source code tokens split up by line number
+ */
+ function getFileSource()
+ {
+ return $this->_file_source;
+ }
+
+ /**
+ * Begin retrieving source code
+ * @access private
+ * @param string word to add the beginning of source code
+ */
+ function retrievesource($word = '')
+ {
+ $this->source = array(array($word));
+ $this->_sourceline = 0;
+ $this->getsource = true;
+ }
+
+ /**
+ * Utility function to determine whether two tokens from the tokenizer are equal
+ * @static
+ */
+ function tokenEquals($a, $b)
+ {
+ if (is_array($a)) $a = $a[1];
+ if (is_array($b)) $b = $b[1];
+ return $a == $b;
+ }
+
+ /**
+ * Utility function to convert a series of tokens into a string
+ * @static
+ */
+ function concatTokens($a)
+ {
+ $b = '';
+ foreach($a as $c)
+ {
+ if (is_array($c)) $c = $c[1];
+ $b .= $c;
+ }
+ return $b;
+ }
+
+ /**
+ * Retrieve a token for the phpDocumentorTParser
+ * {@internal
+ * This method adds source code to the array for a function to be returned
+ * to a {@}source} tag, and will return the token unless it is T_WHITESPACE
+ * and {@link $returnWhiteSpace} is false.
+ *
+ * The global variable search is more complicated than it is in the
+ * WordParser, as we have to compare an array of tokens to each other, and
+ * that is what this code does}}
+ * @return string|array token from tokenizer
+ */
+ function getWord()
+ {
+ if (!isset($this->_all[$this->pos])) return false;
+ $oldlinenum = $this->linenum;
+ $word = $this->_all[$this->pos++];
+ // if we're looking for a global variable declaration, then this section
+ // will search the upcoming tokens to see if they match the tokens
+ // that define the global variable
+ if (isset($this->_global_search))
+ {
+ $pos = $this->pos;
+ $gpos = 0;
+ $found = false;
+ if ($this->tokenEquals($word,$this->_global_search[$gpos++]))
+ {
+ $found = true;
+ for(;$gpos<count($this->_global_search);$gpos++,$pos++)
+ {
+ if (!$this->tokenEquals($this->_global_search[$gpos],$this->_all[$pos])) $found = false;
+ }
+ }
+ if ($found)
+ {
+ $a = $this->concatTokens($this->_global_search);
+ $this->pos += count($this->_global_search) - 1;
+ unset($this->_global_search);
+ return $a;
+ }
+ }
+ if ($this->getsource)
+ {
+ $this->addSource($word);
+ }
+ if (is_array($word))
+ {
+ if (in_array($word[0],$this->_nl_check))
+ {
+ $this->linenum += substr_count($word[1],"\n");
+ }
+ if ($word[0] == T_WHITESPACE && !$this->returnWhiteSpace) return $this->getWord();
+ // seeing if we can get line numbers out of the beast
+ }
+ if (is_array($word) && $word[0] == T_COMMENT) $this->_docblock_linenum = $oldlinenum;
+ return $word;
+ }
+
+ /**
+ * Wrapper for {@link addSource()} used to retrieve the entire source code
+ * organized by line number in setup()
+ * @param array full file source code
+ */
+ function addFileSource($word)
+ {
+ $this->_sourceline = 0;
+ foreach($word as $token)
+ {
+ $this->addSource($token, true);
+ }
+// var_dump($this->_file_source);
+ }
+
+ /**
+ * Generate source token arrays organized by line number
+ *
+ * This code will split up tokens that contain "\n" and add them to the
+ * source code as separate tokens on different lines.
+ * @param array|string token to add
+ * @param boolean true if this should be added to {@link $_file_source}
+ * @param array|string next token, for lookahead splitting
+ * @uses _set_sars()
+ */
+ function addSource($word, $file = false)
+ {
+ if (is_array($word))
+ {
+ $lines = str_replace("\r", '', explode("\n",$word[1]));
+ foreach($lines as $i => $line)
+ {
+ $this->_set_sars($file, array($word[0],$line));
+ if ($i < count($lines) - 1)
+ {
+ // increment sourceline
+ $this->_sourceline++;
+ }
+ }
+ } else $this->_set_sars($file, $word);
+ }
+
+ /**
+ * Add tokens to source code
+ *
+ * {@source}
+ * @access private
+ * @param boolean true if this is file source, otherwise it is function source
+ * @param string|array token to add
+ */
+ function _set_sars($type,$word)
+ {
+ if ($type)
+ {
+ $this->_file_source[$this->_sourceline][] = $word;
+ } else
+ {
+ $this->source[$this->_sourceline][] = $word;
+ }
+ }
+
+ /**
+ * Tell the phpDocumentorTWordParser to return the entire global variable
+ * if it is found.
+ * @uses $_global_search
+ * @param array tokens that represent the global variable definition
+ */
+ function findGlobal($tokens)
+ {
+ if (!$tokens)
+ {
+ unset($this->_global_search);
+ } else
+ $this->_global_search = $tokens;
+ }
+
+ function backupPos()
+ {
+ $this->pos--;
+ $word = $this->_all[$this->pos];
+ if ($this->getsource)
+ {
+ unset($this->source[$this->_sourceline][count($this->source[$this->_sourceline]) - 1]);
+ if (empty($this->source[$this->_sourceline])) unset($this->source[$this->_sourceline]);
+ else $this->source[$this->_sourceline] = array_values($this->source[$this->_sourceline]);
+ }
+ if (is_array($word))
+ {
+ if ($word[0] == T_WHITESPACE && !$this->returnWhiteSpace) return $this->getWord();
+ // seeing if we can get line numbers out of the beast
+ if (in_array($word[0],$this->_nl_check))
+ {
+ $this->linenum -= substr_count($word[1],"\n");
+ }
+ }
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/phpDocumentor/phpdoc.inc b/buildscripts/PhpDocumentor/phpDocumentor/phpdoc.inc
new file mode 100644
index 00000000..4eef3870
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpDocumentor/phpdoc.inc
@@ -0,0 +1,45 @@
+<?php
+/**
+ * @package phpDocumentor
+ */
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+
+
+// set up include path so we can find all files, no matter what
+$a = explode('/',str_replace('\\','/',dirname(realpath(__FILE__))));
+array_pop($a);
+$GLOBALS['_phpDocumentor_install_dir'] = join('/',$a);
+// add my directory to the include path, and make it first, should fix any errors
+if (substr(PHP_OS, 0, 3) == 'WIN')
+ini_set('include_path',$GLOBALS['_phpDocumentor_install_dir'].';'.ini_get('include_path'));
+else
+ini_set('include_path',$GLOBALS['_phpDocumentor_install_dir'].':'.ini_get('include_path'));
+
+/**
+ * All command-line handling from previous version has moved to here
+ *
+ * Many settings also moved to phpDocumentor.ini
+ */
+include("phpDocumentor/Setup.inc.php");
+
+$phpdoc = new phpDocumentor_setup;
+$phpdoc->readCommandLineSettings();
+$phpdoc->setupConverters();
+$phpdoc->createDocs();
+?>
diff --git a/buildscripts/PhpDocumentor/phpdoc b/buildscripts/PhpDocumentor/phpdoc
new file mode 100644
index 00000000..725b5aaf
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpdoc
@@ -0,0 +1,52 @@
+#!/bin/sh
+PHP=`which php`
+exec $PHP -C -q -d output_buffering=1 $0 $@
+<?php
+//
+// PhpDoc, a program for creating javadoc style documentation from php code
+// Copyright (C) 2000-2001 Joshua Eichorn
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+//
+// Copyright 2000-2003 Joshua Eichorn
+// Email jeichorn@phpdoc.org
+// Web http://phpdoc.org/
+// Mirror http://phpdocu.sourceforge.net/
+// Project http://sourceforge.net/projects/phpdocu/
+//
+
+ob_end_clean(); // make output from autofind php code disapear
+
+/**
+ * PHP auto documentor, like javadoc
+ * If you get an error uses this as a shell script then its been dosified
+ * @author Joshua Eichorn
+ * @version 1.3.0
+ * @copyright Joshua Eichorn
+ */
+/**
+ * utility: determine whether we're in PEAR or not
+ */
+$test = @include("phpDocumentor/find_phpdoc.php");
+if ($test == 6) // find_phpdoc.php returns 6
+{
+ include("phpDocumentor/phpdoc.inc");
+} else
+{
+ echo "Error: phpDocumentor not found\n";
+}
+?>
diff --git a/buildscripts/PhpDocumentor/phpdoc.php b/buildscripts/PhpDocumentor/phpdoc.php
new file mode 100644
index 00000000..2217db98
--- /dev/null
+++ b/buildscripts/PhpDocumentor/phpdoc.php
@@ -0,0 +1,469 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<?php
+/**
+ * Web Interface to phpDocumentor
+ * @see new_phpdoc.php
+ * @filesource
+ * @deprecated in favor of docbuilder (see {@link docbuilder/config.php})
+ * @package phpDocumentor
+ */
+//
+//
+// An HTML interface for Joshua Eichorn's phpDocumentor
+// Author: Juan Pablo Morales <ju-moral@uniandes.edu.co>
+// Joshua Eichorn <jeichorn@phpdoc.org>
+// Gregory Beaver <cellog@users.sourceforge.net>
+//
+// phpDocumentor, a program for creating javadoc style documentation from php code
+// Copyright (C) 2000-2002 Joshua Eichorn
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+//
+// Copyleft 2001 Juan Pablo Morales
+
+// set up include path so we can find all files, no matter what
+$GLOBALS['_phpDocumentor_install_dir'] = dirname(realpath(__FILE__));
+// add my directory to the include path, and make it first, should fix any errors
+if (substr(PHP_OS, 0, 3) == 'WIN')
+ini_set('include_path',$GLOBALS['_phpDocumentor_install_dir'].';'.ini_get('include_path'));
+else
+ini_set('include_path',$GLOBALS['_phpDocumentor_install_dir'].':'.ini_get('include_path'));
+
+/**
+* common file information
+*/
+include_once("phpDocumentor/common.inc.php");
+if (!function_exists('version_compare'))
+{
+ print "phpDocumentor requires PHP version 4.1.0 or greater to function";
+ exit;
+}
+
+// find the .ini directory by parsing phpDocumentor.ini and extracting _phpDocumentor_options[userdir]
+$ini = phpDocumentor_parse_ini_file($_phpDocumentor_install_dir . PATH_DELIMITER . 'phpDocumentor.ini', true);
+if (isset($ini['_phpDocumentor_options']['userdir']))
+ $configdir = $ini['_phpDocumentor_options']['userdir'];
+else
+ $configdir = $_phpDocumentor_install_dir . '/user';
+
+// allow the user to change this at runtime
+if (!empty($_REQUEST['altuserdir'])) $configdir = $_REQUEST['altuserdir'];
+?>
+<html>
+ <head>
+ <title>
+ Form to submit to phpDocumentor v<?php print PHPDOCUMENTOR_VER; ?>
+ </title>
+ <?php if(!isset($_GET['submit']) || !empty($_REQUEST['altuserdir'])) {
+?>
+<script type="text/javascript" language="Javascript">
+/**
+ Creates some global variables
+*/
+function initializate() {
+ //
+ //The "platform independent" newLine
+ //
+ //Taken from http://developer.netscape.com/docs/manuals/communicator/jsref/brow1.htm#1010426
+if (navigator.appVersion.lastIndexOf('Win') != -1)
+ $newLine="\r\n";
+ else
+ $newLine="\n";
+/* for($a=0;$a<document.dataForm.elements.length;$a++) {
+ alert("The name is '"+document.dataForm.elements[$a].name+"' "+$a);
+ }
+*/
+}
+/**Adds the contents of the help box as a directory
+*/
+function addDirectory($object) {
+ $object.value = prepareString($object.value)+document.helpForm.fileName.value;
+}
+/**Adds the contents of the converter box to the converters list
+*/
+function addConverter($object) {
+ $object.value = prepareString($object.value)+document.dataForm.ConverterSetting.value;
+}
+/**Adds the contents of the help box as a file to the given control
+*/
+function addFile($object) {
+ $object.value = prepareString($object.value)+document.helpForm.fileName.value;
+}
+/**Takes a given string and leaves it ready to add a new string
+ That is, puts the comma and the new line if needed
+*/
+function prepareString($myString) {
+ //First verify that a comma is not at the end
+ if($myString.lastIndexOf(",") >= $myString.length-2) {
+ //We have a comma at the end
+ return $myString;
+ }
+ if($myString.length > 0) {
+ $myString+=","+$newLine;
+ }
+ return $myString;
+}
+/**Do the validation needed before sending the from and return a truth value indicating if the form can be sent
+*/
+ function validate() {
+ //Take out all newLines and change them by nothing
+ //This could be done by using javascript function's replacebut that was implemented only until Navigator 4.0 and so it is better to use more backward compatible functions like substr
+ document.dataForm.elements[0].value= stripNewLines(document.dataForm.elements[0].value);
+ document.dataForm.elements[1].value= stripNewLines(document.dataForm.elements[1].value);
+ document.dataForm.elements[2].value= stripNewLines(document.dataForm.elements[2].value);
+ document.dataForm.elements[3].value= stripNewLines(document.dataForm.elements[3].value);
+ document.dataForm.elements[4].value= stripNewLines(document.dataForm.elements[4].value);
+ document.dataForm.elements[5].value= stripNewLines(document.dataForm.elements[5].value);
+ document.dataForm.elements[6].value= stripNewLines(document.dataForm.elements[6].value);
+ document.dataForm.elements[7].value= stripNewLines(document.dataForm.elements[7].value);
+ //By returning true we are allowing the form to be submitted
+ return true;
+ }
+/**Takes a string and removes all the ocurrences of new lines
+Could have been implemented a lot easier with replace but it's not very backwards compatible
+*/
+ function stripNewLines($myString) {
+ return myReplace($myString,$newLine,'');
+ }
+ function myReplace($string,$text,$by) {
+ // Replaces text with by in string
+ var $strLength = $string.length, $txtLength = $text.length;
+ if (($strLength == 0) || ($txtLength == 0)) return $string;
+
+ var $i = $string.indexOf($text);
+ if ((!$i) && ($text != $string.substring(0,$txtLength))) return $string;
+ if ($i == -1) return $string;
+
+ var $newstr = $string.substring(0,$i) + $by;
+
+ if ($i+$txtLength < $strLength)
+ $newstr += myReplace($string.substring($i+$txtLength,$strLength),$text,$by);
+
+ return $newstr;
+ }
+</script><?php } ?>
+ </head>
+ <?php
+ //Find out if we are submitting and if we are, send it
+ // This code originally by Joshua Eichorn on phpdoc.php
+ //
+ if(isset($_GET['submit']) && empty($_REQUEST['altuserdir'])) {
+ echo "<body bgcolor=\"#ffffff\">";
+ echo "<h1>Parsing Files ...</h1>";
+ flush();
+ echo "<pre>\n";
+ /** phpdoc.inc */
+ include("phpDocumentor/phpdoc.inc");
+ echo "</pre>\n";
+ echo "<h1>Operation Completed!!</h1>";
+ } else {
+ ?>
+ <body bgcolor="#ffffff" onload="javascript:initializate()">
+ <h1>
+ Form to submit to phpDocumentor v<?php print PHPDOCUMENTOR_VER; ?>
+ </h1>
+ <form name="dataForm" action="phpdoc.php" method="GET" onsubmit=
+ "return validate()">
+ <div align="center">
+ <table cellpadding="0" cellspacing="0" border="0" width="80%"
+ bgcolor="#000000">
+ <tr>
+ <td>
+ <table cellpadding="0" cellspacing="1" border="0" width=
+ "100%">
+ <tr>
+ <td bgcolor="#ff6633">
+ <b>Use a pre-created config file for form values.</b>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#CCCCCC">
+ Normally, phpDocumentor uses the form values from this form to set up parsing. In version 1.2,
+ phpDocumentor allows you to "save" form values in configuration files so that you can replicate
+ common complicated documentation tasks with only one time. Just choose a config file below or create a
+ new one and refresh this page to choose it.<hr /><b>change config directory:</b><input size="20" type="text" name="altuserdir" value=""><?php if (!empty($_REQUEST['altuserdir'])) print '<br><i>changed to <b>"'.$_REQUEST['altuserdir'].'"</b></i>'; ?>
+ <b>Choose a config:</b> <select name="setting[useconfig]">
+ <option value="" <?php if (empty($_REQUEST['altuserdir'])) print 'selected'; ?>>don't use config file</option>
+ <?php
+ $dirs = array();
+ $dirs = phpDocumentor_ConfigFileList($configdir);
+ $path = '';
+ $sel = ' selected';
+ if (!empty($_REQUEST['altuserdir'])) $path = $configdir . PATH_DELIMITER;
+ else $sel = '';
+ foreach($dirs as $configfile)
+ {
+ print '<option value="'.$path.$configfile.'"'.$sel.'>'.$configfile.".ini</option>\n";
+ $sel = '';
+ }
+ ?>
+ </select><input type="SUBMIT" value=
+ "Go" name="submitButton"><br>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#ffdddd">
+ <b>Generated Documentation Title</b>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#eeeeee">
+ Choose a title for the generated documentation<br>
+ <input type="TEXT" name="setting[title]" size=
+ "80" value="Generated Documentation"><br>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#ff6633">
+ <b>Default Package Name</b>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#cccccc">
+ Choose a name for the default package<br>
+ <input type="TEXT" name="setting[defaultpackagename]" size=
+ "80" value="default"><br>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#ffdddd">
+ <b>Target</b>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#eeeeee">
+ Target is the directory where
+ the output produced by phpDocumentor will reside<br>
+ <input type="TEXT" name="setting[target]" size=
+ "80"><br>
+ <a href=
+ "javascript:addDirectory(document.dataForm.elements[5])">
+ Add the directory in the help box</a>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#ffdddd">
+ <b>Custom Tags</b>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#eeeeee">
+ Custom Tags is a comma-separated list of tags
+ you want phpDocumentor to include as valid tags
+ in this parse. An example would be "value, size"
+ to allow @value and @size tags.
+ <input type="TEXT" name="setting[customtags]" size=
+ "80"><br>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#ff6633">
+ <b>Packages to parse</b>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#CCCCCC">
+ The parameter packages is a group of comma
+ separated names of abstract packages that will
+ be processed by phpDocumentor. All package names must be
+ separated by commas.<br>
+<textarea rows="3" cols="80" name=
+"setting[packageoutput]"></textarea> <br>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#ffdddd">
+ <b>Files to parse</b>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#eeeeee">
+ This is a group of comma-separated names of php files
+ or tutorials that will be processed by phpDocumentor.<br>
+<textarea rows="6" cols="80" name=
+"setting[filename]"></textarea> <br>
+ <a href=
+ "javascript:addFile(document.dataForm.elements[8])">
+ Add the file in the help box</a>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#ff6633">
+ <b>Directory to parse</b>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#CCCCCC">
+ This is a group of comma-separated directories where php files
+ or tutorials are found that will be processed by phpDocumentor.
+ phpDocumentor automatically parses subdirectories<br>
+<textarea rows="6" cols="80" name="setting[directory]"></textarea> <br>
+ <a href=
+ "javascript:addDirectory(document.dataForm.elements[9])">
+ Add the directory in the help box</a>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#ffdddd">
+ <b>Output Information</b>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#eeeeee">
+ <br>
+ Output Information is a comma-separated list of <b>Outputformat:Converter:Templates</b>
+ to apply to the output. The Converters must be classes descended from Converter
+ defined in the phpDocumentor files, or parsing will not work. Outputformat
+ may be HTML, XML, PDF, or CHM (case-sensitive) in version 1.2. There is only one Converter
+ for both CHM and PDF, <b>default</b>. There are 2 HTML Converters,
+ <b>frames</b> and <b>Smarty</b>. <b>frames templates</b> may be any of:<br><br>
+ <b>default, l0l33t, phpdoc.de, phphtmllib, phpedit, DOM/default, DOM/l0l33t, or DOM/phpdoc.de</b>.
+ <b>Smarty templates</b> may be any of:<br><br>
+ <b>default or PHP</b>.
+ <br>
+ There is only 1 template for all other Converters, <b>default</b>
+ <br>Output type:Converter name:template name <input type=
+ "TEXT" name="setting[output]" value=
+ "HTML:Smarty:default" size="80"><br>
+ <select name="ConverterSetting">
+ <option value="HTML:frames:default">HTML:frames:default</option>
+ <option value="HTML:frames:l0l33t">HTML:frames:l0l33t</option>
+ <option value="HTML:frames:phpdoc.de">HTML:frames:phpdoc.de</option>
+ <option value="HTML:frames:phphtmllib">HTML:frames:phphtmllib</option>
+ <option value="HTML:frames:phpedit">HTML:frames:phpedit</option>
+ <option value="HTML:frames:DOM/default">HTML:frames:DOM/default</option>
+ <option value="HTML:frames:DOM/l0l33t">HTML:frames:DOM/l0l33t</option>
+ <option value="HTML:frames:DOM/phpdoc.de">HTML:frames:DOM/phpdoc.de</option>
+ <option value="HTML:Smarty:default" SELECTED>HTML:Smarty:default</option>
+ <option value="HTML:Smarty:PHP">HTML:Smarty:PHP</option>
+ <option value="PDF:default:default">PDF:default:default</option>
+ <option value="CHM:default:default">CHM:default:default</option>
+ <option value="XML:DocBook/peardoc2:default">XML:DocBook/peardoc2:default</option>
+</select><br>
+ <a href=
+ "javascript:addConverter(document.dataForm.elements[10])">
+ Add the converter in the help box</a>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#ff6633">
+ <b>Files to ignore</b>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#CCCCCC">
+ A list of files (full path or filename), and patterns
+ to ignore. Patterns may use wildcards * and ?. To
+ ignore all subdirectories named "test" for example,
+ using "test/" To ignore all files and directories
+ with test in their name use "*test*"
+<textarea rows="6" cols="80" name="setting[ignore]"></textarea> <br>
+ <a href=
+ "javascript:addDirectory(document.dataForm.elements[12])">
+ Add the directory in the help box</a>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#ff6633">
+ <b>Parse @access private</b>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#CCCCCC">
+ The parameter Parse @access private tells phpDocumentor
+ whether to parse elements with an "@access private" tag in their docblock<br>
+ <input type="checkbox" name="setting[parseprivate]" value="on">Parse private <br>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#ff6633">
+ <b>JavaDoc-compliant Description parsing.</b>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#CCCCCC">
+ Normally, phpDocumentor uses several rules to determine the short description. This switch
+ asks phpDocumentor to simply search for the first period (.) and use it to delineate the short
+ description. In addition, the short description will not be separated from the long description<br>
+ <input type="checkbox" name="setting[javadocdesc]" value="on">JavaDoc-compliant Description <br>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ <input type="HIDDEN" name="interface" value="web"> <input type=
+ "HIDDEN" name="submit" value="true"> <input type="SUBMIT" value=
+ "Send Form" name="submitButton">
+ </div>
+ </form>
+ <br>
+ <br>
+ <div align="center">
+ <table cellpadding="0" cellspacing="0" border="0" width="80%" bgcolor=
+ "#000000">
+ <tr>
+ <td>
+ <table cellpadding="0" cellspacing="1" border="0" width=
+ "100%">
+ <tr>
+ <td bgcolor="#ffdddd">
+ <b>A little help</b>
+ </td>
+ </tr>
+ <tr>
+ <td bgcolor="#eeeeee">
+ Since remember long path is not that easy here is a
+ little file control to view names of files that can
+ the be aggregated to the different properties
+ <form name="helpForm" action="" method="get"
+ enctype="multipart/form-data">
+ <input size="80" type="file" name="fileName">
+ </form>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <br>
+ <b>Web-Interface Author:</b>
+ <p>
+ Juan Pablo Morales<br>
+ <a href=
+ "mailto:ju-moral@uniandes.edu.co">ju-moral@uniandes.edu.co</a><br>
+ Gregory Beaver<br>
+ <a href=
+ "mailto:cellog@users.sourceforge.net">cellog@users.sourceforge.net</a>, all post-0.3.0 modifications
+ </p>
+ <p>
+ If you have any problems with phpDocumentor, please visit the website: <a
+ href='http://phpdocu.sourceforge.net'>phpdocu.sourceforge.net</a> and
+ submit a bug
+ </p>
+ <!-- Created: Tue Jun 26 18:52:40 MEST 2001 -->
+ <!-- hhmts start -->
+<pre>
+Last modified: $Date: 2005/10/17 18:15:16 $
+Revision: $Revision: 1.1 $
+</pre>
+ <!-- hhmts end -->
+ <?php } //End the else that prints all code
+ ?>
+ </body>
+</html>
+
diff --git a/buildscripts/PhpDocumentor/poweredbyphpdoc.gif b/buildscripts/PhpDocumentor/poweredbyphpdoc.gif
new file mode 100644
index 00000000..80e47255
--- /dev/null
+++ b/buildscripts/PhpDocumentor/poweredbyphpdoc.gif
Binary files differ
diff --git a/buildscripts/PhpDocumentor/scripts/add_cvs.php b/buildscripts/PhpDocumentor/scripts/add_cvs.php
new file mode 100644
index 00000000..2dfcd656
--- /dev/null
+++ b/buildscripts/PhpDocumentor/scripts/add_cvs.php
@@ -0,0 +1,153 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+/**
+ * CVS file adding iterator
+ *
+ * This file iterates over a directory, and adds everything to CVS that is
+ * found, ignoring any error messages, until all files in each directory
+ * and subdirectory have been added to cvs. It then commits the files to cvs
+ * @package phpDocumentor
+ * @author Greg Beaver <cellog@users.sourceforge.net>
+ * @copyright Copyright 2003, Greg Beaver
+ * @version 1.0
+ */
+/**#@+
+ * phpDocumentor include files. If you don't have phpDocumentor, go get it!
+ * Your php life will be changed forever
+ */
+$dir = realpath(dirname(__FILE__).'/..');
+require_once("$dir/phpDocumentor/common.inc.php");
+require_once("$dir/phpDocumentor/Io.inc");
+/**#@-*/
+
+/**
+* Physical location on this computer of the package to parse
+* @global string $cvsadd_directory
+*/
+$cvsadd_directory = realpath('.');
+/**
+* Comma-separated list of files and directories to ignore
+*
+* This uses wildcards * and ? to remove extra files/directories that are
+* not part of the package or release
+* @global string $ignore
+*/
+$ignore = array('CVS/');
+
+/******************************************************************************
+* Don't change anything below here unless you're adventuresome *
+*******************************************************************************/
+
+/**
+ * @global Io $files
+ */
+$files = new Io;
+
+$allfiles = $files->dirList($cvsadd_directory);
+/**#@+
+ * Sorting functions for the file list
+ * @param string
+ * @param string
+ */
+function sortfiles($a, $b)
+{
+ return strnatcasecmp($a['file'],$b['file']);
+}
+
+function mystrucsort($a, $b)
+{
+ if (is_numeric($a) && is_string($b)) return 1;
+ if (is_numeric($b) && is_string($a)) return -1;
+ if (is_numeric($a) && is_numeric($b))
+ {
+ if ($a > $b) return 1;
+ if ($a < $b) return -1;
+ if ($a == $b) return 0;
+ }
+ return strnatcasecmp($a,$b);
+}
+/**#@-*/
+
+$struc = array();
+foreach($allfiles as $file)
+{
+ if ($files->checkIgnore(basename($file),dirname($file),$ignore, false))
+ {
+// print 'Ignoring '.$file."<br>\n";
+ continue;
+ }
+ $path = substr(dirname($file),strlen(str_replace('\\','/',realpath($cvsadd_directory)))+1);
+ if (!$path) $path = '/';
+ $file = basename($file);
+ $ext = array_pop(explode('.',$file));
+ if (strlen($ext) == strlen($file)) $ext = '';
+ $struc[$path][] = array('file' => $file,'ext' => $ext);
+}
+uksort($struc,'strnatcasecmp');
+foreach($struc as $key => $ind)
+{
+ usort($ind,'sortfiles');
+ $struc[$key] = $ind;
+}
+$tempstruc = $struc;
+$struc = array('/' => $tempstruc['/']);
+$bv = 0;
+foreach($tempstruc as $key => $ind)
+{
+ $save = $key;
+ if ($key != '/')
+ {
+ $struc['/'] = setup_dirs($struc['/'], explode('/',$key), $tempstruc[$key]);
+ }
+}
+uksort($struc['/'],'mystrucsort');
+/**
+ * Recursively add files to cvs
+ * @param array the sorted directory structure
+ */
+function addToCVS($struc)
+{
+ foreach($struc as $dir => $files)
+ {
+ if ($dir === '/')
+ {
+ print 'processing '.$dir . "\n";
+ addToCVS($struc[$dir]);
+ return;
+ } else
+ {
+ if (!isset($files['file']))
+ {
+ print 'adding '.$dir . "\n";
+ system('cvs add '.$dir);
+ chdir($dir);
+ addToCVS($files);
+ chdir('..');
+ } else
+ {
+ print 'adding '.$files['file'] . "\n";
+ system('cvs add '.$files['file']);
+ system('cvs commit -m "" '.$files['file']);
+ }
+ }
+ }
+}
+addToCVS($struc);
+print "\n".'done';
+?> \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/scripts/create_examples.php b/buildscripts/PhpDocumentor/scripts/create_examples.php
new file mode 100644
index 00000000..d8b3b8ff
--- /dev/null
+++ b/buildscripts/PhpDocumentor/scripts/create_examples.php
@@ -0,0 +1,66 @@
+<?php
+//
+// +------------------------------------------------------------------------+
+// | phpDocumentor |
+// +------------------------------------------------------------------------+
+// | Copyright (c) 2000-2003 Joshua Eichorn, Gregory Beaver |
+// | Email jeichorn@phpdoc.org, cellog@phpdoc.org |
+// | Web http://www.phpdoc.org |
+// | Mirror http://phpdocu.sourceforge.net/ |
+// | PEAR http://pear.php.net/package-info.php?pacid=137 |
+// +------------------------------------------------------------------------+
+// | This source file is subject to version 3.00 of the PHP License, |
+// | that is available at http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +------------------------------------------------------------------------+
+//
+// ./phpdoc -d /home/jeichorn/phpdoc -dn phpDocumentor -ti "phpDocumentor generated docs" -td templates/DOM/l0l33t -t /tmp/phpdoc_DOM_l0l33t
+/**
+* This file creates example documentation output of all templates.
+* @package phpDocumentor
+*/
+
+/**
+* Directory the output should go to.
+* Change this variable to an output directory on your computer
+* @global string $output_directory
+*/
+$output_directory = "/tmp";
+/**
+* default package name, used to change all non-included files to this package
+* @global string $base_package
+*/
+$base_package = "phpDocumentor";
+/**
+* Title of the generated documentation
+* @global string $title
+*/
+$title = "phpDocumentor Generated Documentation";
+/**
+* location of the files to parse. Change to a location on your computer
+* @global string $parse_directory
+*/
+$parse_directory = "/home/jeichorn/phpdoc";
+
+/**
+* directories to output examples into.
+* @global array $output
+*/
+$output = array(
+ $output_directory.'/docs/phpdoc_default' => 'HTML:default:default',
+ $output_directory.'/docs/phpdoc_l0l33t' => 'HTML:default:l0l33t',
+ $output_directory.'/docs/phpdoc_phpdoc_de' => 'HTML:default:phpdoc.de',
+ $output_directory.'/docs/phpdoc_DOM_default' => 'HTML:default:DOM/default',
+ $output_directory.'/docs/phpdoc_DOM_l0l33t' => 'HTML:default:DOM/l0l33t',
+ $output_directory.'/docs/phpdoc_DOM_phpdoc_de' => 'HTML:default:DOM/phpdoc.de',
+ $output_directory.'/docs/phpdoc_smarty_default' => 'HTML:Smarty:default'
+ $output_directory.'/docs/phpdoc_pdf_default' => 'PDF:default:default'
+ $output_directory.'/docs/phpdoc_chm_default' => 'CHM:default:default'
+ );
+
+foreach($output as $output => $template)
+{
+ passthru("./phpdoc -d /home/jeichorn/phpdoc -dn $base_package -ti \"$title\" -td $template -t $output");
+}
diff --git a/buildscripts/PhpDocumentor/scripts/create_package.xml.php b/buildscripts/PhpDocumentor/scripts/create_package.xml.php
new file mode 100644
index 00000000..2ef0fd2c
--- /dev/null
+++ b/buildscripts/PhpDocumentor/scripts/create_package.xml.php
@@ -0,0 +1,204 @@
+<?php
+set_time_limit(0);
+require_once('PEAR/PackageFileManager.php');
+PEAR::setErrorHandling(PEAR_ERROR_DIE);
+$test = new PEAR_PackageFileManager;
+
+$packagedir = dirname(dirname(__FILE__));
+
+$e = $test->setOptions(
+array('baseinstalldir' => 'PhpDocumentor',
+'version' => '1.3.0RC4',
+'packagedirectory' => $packagedir,
+'state' => 'beta',
+'filelistgenerator' => 'cvs',
+'notes' => 'PHP 5 support and more, fix bugs
+
+This will be the last release in the 1.x series. 2.0 is next
+
+Features added to this release include:
+
+ * Full PHP 5 support, phpDocumentor both runs in and parses Zend Engine 2
+ language constructs. Note that you must be running phpDocumentor in
+ PHP 5 in order to parse PHP 5 code
+ * XML:DocBook/peardoc2:default converter now beautifies the source using
+ PEAR\'s XML_Beautifier if available
+ * inline {@example} tag - this works just like {@source} except that
+ it displays the contents of another file. In tutorials, it works
+ like <programlisting>
+ * customizable README/INSTALL/CHANGELOG files
+ * phpDocumentor tries to run .ini files out of the current directory
+ first, to allow you to put them anywhere you want to
+ * multi-national characters are now allowed in package/subpackage names
+ * images in tutorials with the <graphic> tag
+ * un-modified output with <programlisting role="html">
+ * html/xml source highlighting with <programlisting role="tutorial">
+
+From both Windows and Unix, both the command-line version
+of phpDocumentor and the web interface will work
+out of the box by using command phpdoc - guaranteed :)
+
+WARNING: in order to use the web interface through PEAR, you must set your
+data_dir to a subdirectory of your document root.
+
+$ pear config-set data_dir /path/to/public_html/pear
+
+on Windows with default apache setup, it might be
+
+C:\> pear config-set data_dir "C:\Program Files\Apache\htdocs\pear"
+
+After this, install/upgrade phpDocumentor
+
+$ pear upgrade phpDocumentor
+
+and you can browse to:
+
+http://localhost/pear/PhpDocumentor/
+
+for the web interface
+
+------
+WARNING: The PDF Converter will not work in PHP5. The PDF library that it relies upon
+segfaults with the simplest of files. Generation still works great in PHP4
+------
+
+- WARNING: phpDocumentor installs phpdoc in the
+ scripts directory, and this will conflict with PHPDoc,
+ you can\'t have both installed at the same time
+- Switched to Smarty 2.6.0, now it will work in PHP 5. Other
+ changes made to the code to make it work in PHP 5, including parsing
+ of private/public/static/etc. access modifiers
+- fixed these bugs:
+ [ not entered ] XMLDocBookpeardoc2 beautifier removes comments
+ [ 896444 ] Bad line numbers
+ [ 937235 ] duplicated /** after abstract method declaration
+ [ 962319 ] Define : don\'t show the assigned value
+ [ 977674 ] Parser error
+ [ 989258 ] wrong interfaces parsing
+ [ 1150809 ] Infinite loop when class extends itself
+ [ 1151196 ] PHP Fatal error: Cannot re-assign $this
+ [ 1151650 ] UTF8 decoding for DocBook packages
+ [ 1152781 ] PHP_NOTICE: Uninitialized string offset in ParserDescCleanup
+ [ 1153593 ] string id="...." in tutorials
+ [ 1164253 ] Inherited Class Constants are not displayed
+ [ 1171583 ] CHM wrong filesource
+ [ 1180200 ] HighlightParser does not handle Heredoc Blocks.
+ [ 1202772 ] missing parentheses in Parser.inc line 946
+ [ 1203445 ] Call to a member function on a non-object in Parser.inc
+ [ 1203451 ] array to string conversion notice in InlineTags.inc
+- fixed these bugs reported in PEAR:
+ Bug #2288: Webfrontend ignores more than one dir in "Files to ignore"
+ Bug #5011: PDF generation warning on uksort
+',
+'package' => 'PhpDocumentor',
+'dir_roles' => array(
+ 'Documentation' => 'doc',
+ 'Documentation/tests' => 'test',
+ 'docbuilder' => 'data',
+ 'HTML_TreeMenu-1.1.2' => 'data',
+ 'tutorials' => 'doc',
+ 'phpDocumentor/Converters/CHM/default/templates/default/templates_c' => 'data',
+ 'phpDocumentor/Converters/PDF/default/templates/default/templates_c' => 'data',
+ 'phpDocumentor/Converters/HTML/frames/templates/default/templates_c' => 'data',
+ 'phpDocumentor/Converters/HTML/frames/templates/l0l33t/templates_c' => 'data',
+ 'phpDocumentor/Converters/HTML/frames/templates/phpdoc.de/templates_c' => 'data',
+ 'phpDocumentor/Converters/HTML/frames/templates/phphtmllib/templates_c' => 'data',
+ 'phpDocumentor/Converters/HTML/frames/templates/phpedit/templates_c' => 'data',
+ 'phpDocumentor/Converters/HTML/frames/templates/earthli/templates_c' => 'data',
+ 'phpDocumentor/Converters/HTML/frames/templates/DOM/default/templates_c' => 'data',
+ 'phpDocumentor/Converters/HTML/frames/templates/DOM/l0l33t/templates_c' => 'data',
+ 'phpDocumentor/Converters/HTML/frames/templates/DOM/phpdoc.de/templates_c' => 'data',
+ 'phpDocumentor/Converters/HTML/frames/templates/DOM/phphtmllib/templates_c' => 'data',
+ 'phpDocumentor/Converters/HTML/frames/templates/DOM/earthli/templates_c' => 'data',
+ 'phpDocumentor/Converters/HTML/Smarty/templates/default/templates_c' => 'data',
+ 'phpDocumentor/Converters/HTML/Smarty/templates/PHP/templates_c' => 'data',
+ 'phpDocumentor/Converters/HTML/Smarty/templates/HandS/templates_c' => 'data',
+ 'phpDocumentor/Converters/XML/DocBook/peardoc2/templates/default/templates_c' => 'data',
+ ),
+'simpleoutput' => true,
+'exceptions' =>
+ array(
+ 'index.html' => 'data',
+ 'README' => 'doc',
+ 'ChangeLog' => 'doc',
+ 'PHPLICENSE.txt' => 'doc',
+ 'poweredbyphpdoc.gif' => 'data',
+ 'INSTALL' => 'doc',
+ 'FAQ' => 'doc',
+ 'Authors' => 'doc',
+ 'Release-1.2.0beta1' => 'doc',
+ 'Release-1.2.0beta2' => 'doc',
+ 'Release-1.2.0beta3' => 'doc',
+ 'Release-1.2.0rc1' => 'doc',
+ 'Release-1.2.0rc2' => 'doc',
+ 'Release-1.2.0' => 'doc',
+ 'Release-1.2.1' => 'doc',
+ 'Release-1.2.2' => 'doc',
+ 'Release-1.2.3' => 'doc',
+ 'Release-1.2.3.1' => 'doc',
+ 'Release-1.3.0' => 'doc',
+ 'pear-phpdoc' => 'script',
+ 'pear-phpdoc.bat' => 'script',
+ 'HTML_TreeMenu-1.1.2/TreeMenu.php' => 'php',
+ 'phpDocumentor/Smarty-2.6.0/libs/debug.tpl' => 'php',
+ 'new_phpdoc.php' => 'data',
+ 'phpdoc.php' => 'data',
+ ),
+'ignore' =>
+ array('package.xml',
+ "$packagedir/phpdoc",
+ 'phpdoc.bat',
+ 'LICENSE',
+ '*templates/PEAR/*',
+ 'phpDocumentor/Smarty-2.5.0/*',
+ '*CSV*',
+ 'makedocs.ini',
+ 'publicweb-PEAR-1.2.1.patch.txt',
+ ),
+'installas' =>
+ array('pear-phpdoc' => 'phpdoc',
+ 'pear-phpdoc.bat' => 'phpdoc.bat',
+ 'user/pear-makedocs.ini' => 'user/makedocs.ini',
+ ),
+'installexceptions' => array('pear-phpdoc' => '/', 'pear-phpdoc.bat' => '/', 'scripts/makedoc.sh' => '/'),
+));
+if (PEAR::isError($e)) {
+ echo $e->getMessage();
+ exit;
+}
+$test->addPlatformException('pear-phpdoc.bat', 'windows');
+$test->addDependency('php', '4.1.0', 'ge', 'php');
+// optional dep for peardoc2 converter
+$test->addDependency('XML_Beautifier', '1.1', 'ge', 'pkg', true);
+// replace @PHP-BIN@ in this file with the path to php executable! pretty neat
+$test->addReplacement('pear-phpdoc', 'pear-config', '@PHP-BIN@', 'php_bin');
+$test->addReplacement('pear-phpdoc.bat', 'pear-config', '@PHP-BIN@', 'php_bin');
+$test->addReplacement('pear-phpdoc.bat', 'pear-config', '@BIN-DIR@', 'bin_dir');
+$test->addReplacement('pear-phpdoc.bat', 'pear-config', '@PEAR-DIR@', 'php_dir');
+$test->addReplacement('pear-phpdoc.bat', 'pear-config', '@DATA-DIR@', 'data_dir');
+$test->addReplacement('docbuilder/includes/utilities.php', 'pear-config', '@DATA-DIR@', 'data_dir');
+$test->addReplacement('docbuilder/builder.php', 'pear-config', '@DATA-DIR@', 'data_dir');
+$test->addReplacement('docbuilder/file_dialog.php', 'pear-config', '@DATA-DIR@', 'data_dir');
+$test->addReplacement('docbuilder/file_dialog.php', 'pear-config', '@WEB-DIR@', 'data_dir');
+$test->addReplacement('docbuilder/actions.php', 'pear-config', '@WEB-DIR@', 'data_dir');
+$test->addReplacement('docbuilder/top.php', 'pear-config', '@DATA-DIR@', 'data_dir');
+$test->addReplacement('docbuilder/config.php', 'pear-config', '@DATA-DIR@', 'data_dir');
+$test->addReplacement('docbuilder/config.php', 'pear-config', '@WEB-DIR@', 'data_dir');
+$test->addReplacement('phpDocumentor/Setup.inc.php', 'pear-config', '@DATA-DIR@', 'data_dir');
+$test->addReplacement('phpDocumentor/Converter.inc', 'pear-config', '@DATA-DIR@', 'data_dir');
+$test->addReplacement('phpDocumentor/common.inc.php', 'package-info', '@VER@', 'version');
+$test->addReplacement('phpDocumentor/IntermediateParser.inc', 'package-info', '@VER@', 'version');
+$test->addReplacement('user/pear-makedocs.ini', 'pear-config', '@PEAR-DIR@', 'php_dir');
+$test->addReplacement('user/pear-makedocs.ini', 'pear-config', '@DOC-DIR@', 'doc_dir');
+$test->addReplacement('user/pear-makedocs.ini', 'package-info', '@VER@', 'version');
+$test->addRole('inc', 'php');
+$test->addRole('sh', 'script');
+if (isset($_GET['make'])) {
+ $test->writePackageFile();
+} else {
+ $test->debugPackageFile();
+}
+if (!isset($_GET['make'])) {
+ echo '<a href="' . $_SERVER['PHP_SELF'] . '?make=1">Make this file</a>';
+}
+?> \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/scripts/makedoc.sh b/buildscripts/PhpDocumentor/scripts/makedoc.sh
new file mode 100644
index 00000000..83c3bcc0
--- /dev/null
+++ b/buildscripts/PhpDocumentor/scripts/makedoc.sh
@@ -0,0 +1,94 @@
+#!/bin/bash
+# $Id: makedoc.sh,v 1.1 2005/10/17 18:37:43 jeichorn Exp $
+
+#/**
+# * makedoc - PHPDocumentor script to save your settings
+# *
+# * Put this file inside your PHP project homedir, edit its variables and run whenever you wants to
+# * re/make your project documentation.
+# *
+# * The version of this file is the version of PHPDocumentor it is compatible.
+# *
+# * It simples run phpdoc with the parameters you set in this file.
+# * NOTE: Do not add spaces after bash variables.
+# *
+# * @copyright makedoc.sh is part of PHPDocumentor project {@link http://freshmeat.net/projects/phpdocu/} and its LGPL
+# * @author Roberto Berto <darkelder (inside) users (dot) sourceforge (dot) net>
+# * @version Release-1.1.0
+# */
+
+
+##############################
+# should be edited
+##############################
+
+#/**
+# * title of generated documentation, default is 'Generated Documentation'
+# *
+# * @var string TITLE
+# */
+TITLE="Your Project Documentation"
+
+#/**
+# * name to use for the default package. If not specified, uses 'default'
+# *
+# * @var string PACKAGES
+# */
+PACKAGES="yourProject"
+
+#/**
+# * name of a directory(s) to parse directory1,directory2
+# * $PWD is the directory where makedoc.sh
+# *
+# * @var string PATH_PROJECT
+# */
+PATH_PROJECT=$PWD
+
+#/**
+# * path of PHPDoc executable
+# *
+# * @var string PATH_PHPDOC
+# */
+PATH_PHPDOC=~/phpdoc/phpdoc
+
+#/**
+# * where documentation will be put
+# *
+# * @var string PATH_DOCS
+# */
+PATH_DOCS=$PWD/docs
+
+#/**
+# * what outputformat to use (html/pdf)
+# *
+# * @var string OUTPUTFORMAT
+# */
+OUTPUTFORMAT=HTML
+
+#/**
+# * converter to be used
+# *
+# * @var string CONVERTER
+# */
+CONVERTER=Smarty
+
+#/**
+# * template to use
+# *
+# * @var string TEMPLATE
+# */
+TEMPLATE=default
+
+#/**
+# * parse elements marked as private
+# *
+# * @var bool (on/off) PRIVATE
+# */
+PRIVATE=off
+
+# make documentation
+$PATH_PHPDOC -d $PATH_PROJECT -t $PATH_DOCS -ti "$TITLE" -dn $PACKAGES \
+-o $OUTPUTFORMAT:$CONVERTER:$TEMPLATE -pp $PRIVATE
+
+
+# vim: set expandtab :
diff --git a/buildscripts/PhpDocumentor/scripts/tokenizer_test.php b/buildscripts/PhpDocumentor/scripts/tokenizer_test.php
new file mode 100644
index 00000000..2b5ca25e
--- /dev/null
+++ b/buildscripts/PhpDocumentor/scripts/tokenizer_test.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * @package tests
+ */
+/**
+$fp = fopen("../phpDocumentor/Converter.inc","r");
+$file = fread($fp,filesize("../phpDocumentor/Converter.inc"));
+fclose($fp);
+*/
+$file = "
+<?php
+ function &newSmarty()
+ {
+ if (!isset(\$this->package_index))
+ foreach(\$this->all_packages as \$key => \$val)
+ {
+ if (isset(\$this->pkg_elements[\$key]))
+ {
+ if (!isset(\$start)) \$start = \$key;
+ \$this->package_index[] = array('link' => \"li_\$key.html\", 'title' => \$key);
+ }
+ }
+ \$templ = new Smarty;
+ \$templ->template_dir = \$this->smarty_dir . PATH_DELIMITER . 'templates';
+ \$templ->compile_dir = \$this->smarty_dir . PATH_DELIMITER . 'templates_c';
+ \$templ->config_dir = \$this->smarty_dir . PATH_DELIMITER . 'configs';
+ \$templ->assign(\"packageindex\",\$this->package_index);
+ \$templ->assign(\"phpdocversion\",PHPDOCUMENTOR_VER);
+ \$templ->assign(\"phpdocwebsite\",PHPDOCUMENTOR_WEBSITE);
+ \$templ->assign(\"package\",\$this->package);
+ \$templ->assign(\"subdir\",'');
+ return \$templ;
+ }
+?>
+";
+$tokens = token_get_all($file);
+
+$nl_check = array(T_WHITESPACE,T_ENCAPSED_AND_WHITESPACE,T_COMMENT,T_DOC_COMMENT,T_OPEN_TAG,T_CLOSE_TAG,T_INLINE_HTML);
+print '<pre>';
+$line = 0;
+foreach($tokens as $key => $val)
+{
+ if (is_array($val))
+ {
+ // seeing if we can get line numbers out of the beast
+ if (in_array($val[0],$nl_check))
+ {
+ $line+=substr_count($val[1],"\n");
+ }
+ echo token_name($val[0])." => ".htmlentities($val[1])."\n";
+ }
+ else
+ {
+ echo "*** $val\n";
+ }
+}
+echo "$line\n";
+print '</pre>';
+?>
diff --git a/buildscripts/PhpDocumentor/user/default.ini b/buildscripts/PhpDocumentor/user/default.ini
new file mode 100644
index 00000000..4915f607
--- /dev/null
+++ b/buildscripts/PhpDocumentor/user/default.ini
@@ -0,0 +1,98 @@
+;; phpDocumentor parse configuration file
+;;
+;; This file is designed to cut down on repetitive typing on the command-line or web interface
+;; You can copy this file to create a number of configuration files that can be used with the
+;; command-line switch -c, as in phpdoc -c default.ini or phpdoc -c myini.ini. The web
+;; interface will automatically generate a list of .ini files that can be used.
+;;
+;; default.ini is used to generate the online manual at http://www.phpdoc.org/docs
+;;
+;; ALL .ini files must be in the user subdirectory of phpDocumentor with an extension of .ini
+;;
+;; Copyright 2002, Greg Beaver <cellog@users.sourceforge.net>
+;;
+;; WARNING: do not change the name of any command-line parameters, phpDocumentor will ignore them
+
+[Parse Data]
+;; title of all the documentation
+;; legal values: any string
+title = phpDocumentor 1.3.0 Manual
+
+;; parse files that start with a . like .bash_profile
+;; legal values: true, false
+hidden = false
+
+;; show elements marked @access private in documentation by setting this to on
+;; legal values: on, off
+parseprivate = off
+
+;; parse with javadoc-like description (first sentence is always the short description)
+;; legal values: on, off
+javadocdesc = off
+
+;; add any custom @tags separated by commas here
+;; legal values: any legal tagname separated by commas.
+;customtags = mytag1,mytag2
+
+;; This is only used by the XML:DocBook/peardoc2 converter
+defaultcategoryname = Documentation
+
+;; what is the main package?
+;; legal values: alphanumeric string plus - and _
+defaultpackagename = phpDocumentor
+
+;; output any parsing information? set to on for cron jobs
+;; legal values: on
+;quiet = on
+
+;; parse a PEAR-style repository. Do not turn this on if your project does
+;; not have a parent directory named "pear"
+;; legal values: on/off
+;pear = on
+
+;; where should the documentation be written?
+;; legal values: a legal path
+target = /home/cellog/output
+
+;; Which files should be parsed out as special documentation files, such as README,
+;; INSTALL and CHANGELOG? This overrides the default files found in
+;; phpDocumentor.ini (this file is not a user .ini file, but the global file)
+readmeinstallchangelog = README, INSTALL, CHANGELOG, NEWS, FAQ, LICENSE
+
+;; limit output to the specified packages, even if others are parsed
+;; legal values: package names separated by commas
+;packageoutput = package1,package2
+
+;; comma-separated list of files to parse
+;; legal values: paths separated by commas
+;filename = /path/to/file1,/path/to/file2,fileincurrentdirectory
+
+;; comma-separated list of directories to parse
+;; legal values: directory paths separated by commas
+;directory = /path1,/path2,.,..,subdirectory
+;directory = /home/jeichorn/cvs/pear
+directory = /home/cellog/phpdoc
+
+;; template base directory (the equivalent directory of <installdir>/phpDocumentor)
+;templatebase = /path/to/my/templates
+
+;; directory to find any example files in through @example and {@example} tags
+;examplesdir = /path/to/my/templates
+
+;; comma-separated list of files, directories or wildcards ? and * (any wildcard) to ignore
+;; legal values: any wildcard strings separated by commas
+;ignore = /path/to/ignore*,*list.php,myfile.php,subdirectory/
+ignore = templates_c/,*HTML/default/*,spec/
+
+;; comma-separated list of Converters to use in outputformat:Convertername:templatedirectory format
+;; legal values: HTML:frames:default,HTML:frames:l0l33t,HTML:frames:phpdoc.de,HTML:frames:phphtmllib,
+;; HTML:frames:earthli,
+;; HTML:frames:DOM/default,HTML:frames:DOM/l0l33t,HTML:frames:DOM/phpdoc.de,
+;; HTML:frames:DOM/phphtmllib,HTML:frames:DOM/earthli
+;; HTML:Smarty:default,HTML:Smarty:PHP,HTML:Smarty:HandS
+;; PDF:default:default,CHM:default:default,XML:DocBook/peardoc2:default
+output=HTML:frames:earthli,HTML:frames:default,HTML:frames:l0l33t,HTML:frames:phpdoc.de,HTML:frames:phphtmllib,HTML:frames:DOM/default,HTML:frames:DOM/l0l33t,HTML:frames:DOM/phpdoc.de,HTML:frames:DOM/earthli,HTML:frames:DOM/phphtmllib,HTML:frames:phpedit,HTML:Smarty:default,HTML:Smarty:PHP,HTML:Smarty:HandS,CHM:default:default,PDF:default:default
+
+;; turn this option on if you want highlighted source code for every file
+;; legal values: on/off
+sourcecode = on \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/user/demo.ini b/buildscripts/PhpDocumentor/user/demo.ini
new file mode 100644
index 00000000..edf0a353
--- /dev/null
+++ b/buildscripts/PhpDocumentor/user/demo.ini
@@ -0,0 +1,78 @@
+;; phpDocumentor demonstration parse configuration file
+;;
+;; RUN THIS FILE FROM THE INSTALL DIRECTORY
+;; CHANGE HERE:
+
+;; where should the documentation be written?
+;; legal values: a legal path
+target = /home/CelloG/output
+
+;; DONT CHANGE BELOW HERE
+;;
+;; This file is designed to cut down on repetitive typing on the command-line or web interface
+;; You can copy this file to create a number of configuration files that can be used with the
+;; command-line switch -c, as in phpdoc -c default.ini or phpdoc -c myini.ini. The web
+;; interface will automatically generate a list of .ini files that can be used.
+;;
+;; ALL .ini files must be in the user subdirectory of phpDocumentor with an extension of .ini
+;;
+;; Copyright 2002, Greg Beaver <cellog@users.sourceforge.net>
+;;
+;; WARNING: do not change the
+
+[Parse Data]
+;; title of all the documentation
+;; legal values: any string
+title = Generated Documentation
+
+;; parse files that start with a . like .bash_profile
+;; legal values: true, false
+hidden = false
+
+;; show elements marked @access private in documentation by setting this to on
+;; legal values: on, off
+parseprivate = off
+
+;; parse with javadoc-like description (first sentence is always the short description)
+;; legal values: on, off
+javadocdesc = off
+
+target=/dev/null
+
+;; add any custom @tags separated by commas here
+;; legal values: any legal tagname separated by commas.
+;customtags = mytag1,mytag2
+
+;; what is the main package?
+;; legal values: alphanumeric string plus - and _
+defaultpackagename = phpDocumentor
+
+;; output any parsing information? set to on for cron jobs
+;; legal values: on
+;quiet = on
+
+;; limit output to the specified packages, even if others are parsed
+;; legal values: package names separated by commas
+;packageoutput = package1,package2
+
+;; comma-separated list of files to parse
+;; legal values: paths separated by commas
+;filename = /path/to/file1,/path/to/file2,fileincurrentdirectory
+filename = test.php
+
+;; comma-separated list of directories to parse
+;; legal values: directory paths separated by commas
+;directory = /path1,/path2,.,..,subdirectory
+;directory = /home/jeichorn/cvs/pear
+;directory = .
+
+;; comma-separated list of files, directories or wildcards ? and * (any wildcard) to ignore
+;; legal values: any wildcard strings separated by commas
+;ignore = /path/to/ignore*,*list.php,myfile.php,subdirectory/
+ignore = templates_c/,*HTML/default/*,spec/
+
+;; comma-separated list of Converters to use in outputformat:Convertername:templatedirectory format
+;; legal values: HTML:frames:default,HTML:frames:l0l33t,HTML:frames:phpdoc.de,HTML:frames:phphtmllib
+;; HTML:frames:phpedit,HTML:frames:DOM/default,HTML:frames:DOM/l0l33t,HTML:frames:DOM/phpdoc.de
+;; HTML:Smarty:default,HTML:Smarty:PHP,PDF:default:default,CHM:default:default,XML:DocBook:default
+output=HTML:frames:default,HTML:frames:l0l33t,HTML:frames:phpdoc.de,HTML:frames:phphtmllib,HTML:frames:DOM/default,HTML:frames:DOM/l0l33t,HTML:frames:DOM/phpdoc.de,HTML:frames:phpedit,HTML:Smarty:default,HTML:Smarty:HandS,HTML:Smarty:PHP,PDF:default:default,XML:DocBook/peardoc2:default,CHM:default:default \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/user/error.ini b/buildscripts/PhpDocumentor/user/error.ini
new file mode 100644
index 00000000..cb8d4ca5
--- /dev/null
+++ b/buildscripts/PhpDocumentor/user/error.ini
@@ -0,0 +1,82 @@
+;; phpDocumentor parse configuration file
+;;
+;; This file is designed to cut down on repetitive typing on the command-line or web interface
+;; You can copy this file to create a number of configuration files that can be used with the
+;; command-line switch -c, as in phpdoc -c default.ini or phpdoc -c myini.ini. The web
+;; interface will automatically generate a list of .ini files that can be used.
+;;
+;; ALL .ini files must be in the user subdirectory of phpDocumentor with an extension of .ini
+;;
+;; Copyright 2002, Greg Beaver <cellog@users.sourceforge.net>
+;;
+;; WARNING: do not change the name of any command-line parameters, phpDocumentor will halt
+
+[Parse Data]
+;; title of all the documentation
+;; legal values: any string
+title = SlateLib Manual
+
+;; parse files that start with a . like .bash_profile
+;; legal values: true, false
+hidden = false
+
+;; show elements marked @access private in documentation by setting this to on
+;; legal values: on, off
+parseprivate = on
+
+;; parse with javadoc-like description (first sentence is always the short description)
+;; legal values: on, off
+javadocdesc = off
+
+;; add any custom @tags separated by commas here
+;; legal values: any legal tagname separated by commas.
+;customtags = mytag1,mytag2
+
+;; This is only used by the XML:DocBook/peardoc2 converter
+defaultcategoryname = Documentation
+
+;; what is the main package?
+;; legal values: alphanumeric string plus - and _
+defaultpackagename = junk
+
+;; output any parsing information? set to on for cron jobs
+;; legal values: on
+;quiet = on
+
+;; parse a PEAR-style repository. Do not turn this on if your project does
+;; not have a parent directory named "pear"
+;; legal values: on/off
+;pear = on
+
+;; where should the documentation be written?
+;; legal values: a legal path
+target = /tmp/docs
+
+;; limit output to the specified packages, even if others are parsed
+;; legal values: package names separated by commas
+;packageoutput = package1,package2
+
+;; comma-separated list of files to parse
+;; legal values: paths separated by commas
+;filename = /path/to/file1,/path/to/file2,fileincurrentdirectory
+
+;; comma-separated list of directories to parse
+;; legal values: directory paths separated by commas
+;directory = /path1,/path2,.,..,subdirectory
+;directory = /home/jeichorn/cvs/pear
+directory = /home/jeichorn/cvs/slatelib
+
+;; comma-separated list of files, directories or wildcards ? and * (any wildcard) to ignore
+;; legal values: any wildcard strings separated by commas
+;ignore = /path/to/ignore*,*list.php,myfile.php,subdirectory/
+ignore =
+
+;; comma-separated list of Converters to use in outputformat:Convertername:templatedirectory format
+;; legal values: HTML:frames:default,HTML:frames:l0l33t,HTML:frames:phpdoc.de,HTML:frames:phphtmllib
+;; HTML:frames:DOM/default,HTML:frames:DOM/l0l33t,HTML:frames:DOM/phpdoc.de,HTML:Smarty:default
+;; HTML:Smarty:PHP,PDF:default:default,CHM:default:default,XML:DocBook/peardoc2:default
+output=HTML:Smarty:default,HTML:Smarty:PHP
+
+;; turn this option on if you want highlighted source code for every file
+;; legal values: on/off
+sourcecode = on
diff --git a/buildscripts/PhpDocumentor/user/pear-makedocs.ini b/buildscripts/PhpDocumentor/user/pear-makedocs.ini
new file mode 100644
index 00000000..750cf48f
--- /dev/null
+++ b/buildscripts/PhpDocumentor/user/pear-makedocs.ini
@@ -0,0 +1,71 @@
+;; phpDocumentor parse configuration file
+;;
+;; This file is designed to cut down on repetitive typing on the command-line or web interface
+;; You can copy this file to create a number of configuration files that can be used with the
+;; command-line switch -c, as in phpdoc -c default.ini or phpdoc -c myini.ini. The web
+;; interface will automatically generate a list of .ini files that can be used.
+;;
+;; ALL .ini files must be in the user subdirectory of phpDocumentor with an extension of .ini
+;;
+;; Copyright 2002, Greg Beaver <cellog@users.sourceforge.net>
+;;
+;; WARNING: do not change the
+
+[Parse Data]
+;; title of all the documentation
+;; legal values: any string
+title = phpDocumentor Manual
+
+;; parse files that start with a . like .bash_profile
+;; legal values: true, false
+hidden = false
+
+;; show elements marked @access private in documentation by setting this to on
+;; legal values: on, off
+parseprivate = off
+
+;; parse with javadoc-like description (first sentence is always the short description)
+;; legal values: on, off
+javadocdesc = off
+
+;; add any custom @tags separated by commas here
+;; legal values: any legal tagname separated by commas.
+;customtags = mytag1,mytag2
+
+;; what is the main package?
+;; legal values: alphanumeric string plus - and _
+defaultpackagename = phpDocumentor
+
+;; output any parsing information? set to on for cron jobs
+;; legal values: on
+;quiet = on
+
+;; where should the documentation be written?
+;; legal values: a legal path
+target = @DOC-DIR@/PhpDocumentor/Documentation/new
+
+;; limit output to the specified packages, even if others are parsed
+;; legal values: package names separated by commas
+;packageoutput = package1,package2
+
+;; comma-separated list of files to parse
+;; legal values: paths separated by commas
+;filename = /path/to/file1,/path/to/file2,fileincurrentdirectory
+filename = @DOC-DIR@/PhpDocumentor/README,@DOC-DIR@/PhpDocumentor/ChangeLog,@DOC-DIR@/PhpDocumentor/Release-@VER@,@DOC-DIR@/PhpDocumentor/FAQ
+;; comma-separated list of directories to parse
+;; legal values: directory paths separated by commas
+;directory = /path1,/path2,.,..,subdirectory
+;directory = /home/jeichorn/cvs/pear
+directory = @PEAR-DIR@/PhpDocumentor,@DOC-DIR@/PhpDocumentor/tutorials
+
+releaseinstallchangelog = Release-@VER@,ChangeLog,README,FAQ
+
+;; comma-separated list of files, directories or wildcards ? and * (any wildcard) to ignore
+;; legal values: any wildcard strings separated by commas
+;ignore = /path/to/ignore*,*list.php,myfile.php,subdirectory/
+
+;; comma-separated list of Converters to use in outputformat:Convertername:templatedirectory format
+;; legal values: HTML:frames:default,HTML:frames:l0l33t,HTML:frames:phpdoc.de,HTML:frames:phphtmllib
+;; HTML:frames:DOM/default,HTML:frames:DOM/l0l33t,HTML:frames:DOM/phpdoc.de,HTML:Smarty:default
+;; HTML:Smarty:PHP,HTML:Smarty:HandS,PDF:default:default,CHM:default:default,XML:DocBook/peardoc2:default
+output=HTML:Smarty:HandS \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/user/prado.ini b/buildscripts/PhpDocumentor/user/prado.ini
new file mode 100644
index 00000000..f009f873
--- /dev/null
+++ b/buildscripts/PhpDocumentor/user/prado.ini
@@ -0,0 +1,79 @@
+;; phpDocumentor demonstration parse configuration file
+;;
+;; RUN THIS FILE FROM THE INSTALL DIRECTORY
+;; CHANGE HERE:
+
+;; where should the documentation be written?
+;; legal values: a legal path
+target = d:/wwwroot/prado3-doc
+
+;; DONT CHANGE BELOW HERE
+;;
+;; This file is designed to cut down on repetitive typing on the command-line or web interface
+;; You can copy this file to create a number of configuration files that can be used with the
+;; command-line switch -c, as in phpdoc -c default.ini or phpdoc -c myini.ini. The web
+;; interface will automatically generate a list of .ini files that can be used.
+;;
+;; ALL .ini files must be in the user subdirectory of phpDocumentor with an extension of .ini
+;;
+;; Copyright 2002, Greg Beaver <cellog@users.sourceforge.net>
+;;
+;; WARNING: do not change the
+
+[Parse Data]
+;; title of all the documentation
+;; legal values: any string
+title = PRADO 3.0.1 API Manual
+
+;; parse files that start with a . like .bash_profile
+;; legal values: true, false
+hidden = false
+
+;; show elements marked @access private in documentation by setting this to on
+;; legal values: on, off
+parseprivate = off
+
+;; parse with javadoc-like description (first sentence is always the short description)
+;; legal values: on, off
+javadocdesc = off
+
+target=d:/wwwroot/prado3-doc/manual
+
+;; add any custom @tags separated by commas here
+;; legal values: any legal tagname separated by commas.
+;customtags = mytag1,mytag2
+
+;; what is the main package?
+;; legal values: alphanumeric string plus - and _
+defaultpackagename = default
+
+;; output any parsing information? set to on for cron jobs
+;; legal values: on
+;quiet = on
+
+;; limit output to the specified packages, even if others are parsed
+;; legal values: package names separated by commas
+;packageoutput = package1,package2
+
+;; comma-separated list of files to parse
+;; legal values: paths separated by commas
+;filename = /path/to/file1,/path/to/file2,fileincurrentdirectory
+;filename =
+
+;; comma-separated list of directories to parse
+;; legal values: directory paths separated by commas
+directory = D:/wwwroot/prado3-doc/prado-3.0.1/framework
+;directory = /home/jeichorn/cvs/pear
+;directory = .
+
+;; comma-separated list of files, directories or wildcards ? and * (any wildcard) to ignore
+;; legal values: any wildcard strings separated by commas
+;ignore = /path/to/ignore*,*list.php,myfile.php,subdirectory/
+ignore = templates_c/,*HTML/default/*,spec/,*pradolite.php,*3rdParty/*,*Javascripts/*
+
+;; comma-separated list of Converters to use in outputformat:Convertername:templatedirectory format
+;; legal values: HTML:frames:default,HTML:frames:l0l33t,HTML:frames:phpdoc.de,HTML:frames:phphtmllib
+;; HTML:frames:phpedit,HTML:frames:DOM/default,HTML:frames:DOM/l0l33t,HTML:frames:DOM/phpdoc.de
+;; HTML:Smarty:default,HTML:Smarty:PHP,PDF:default:default,CHM:default:default,XML:DocBook:default
+;;output=HTML:frames:default,CHM:default:default
+output=HTML:Smarty:PradoSoft \ No newline at end of file
diff --git a/buildscripts/PhpDocumentor/user/testdocbook.ini b/buildscripts/PhpDocumentor/user/testdocbook.ini
new file mode 100644
index 00000000..8de48fc0
--- /dev/null
+++ b/buildscripts/PhpDocumentor/user/testdocbook.ini
@@ -0,0 +1,74 @@
+;; phpDocumentor parse configuration file
+;;
+;; This file is designed to cut down on repetitive typing on the command-line or web interface
+;; You can copy this file to create a number of configuration files that can be used with the
+;; command-line switch -c, as in phpdoc -c default.ini or phpdoc -c myini.ini. The web
+;; interface will automatically generate a list of .ini files that can be used.
+;;
+;; ALL .ini files must be in the user subdirectory of phpDocumentor with an extension of .ini
+;;
+;; Copyright 2002, Greg Beaver <cellog@users.sourceforge.net>
+;;
+;; WARNING: do not change the
+
+[Parse Data]
+;; title of all the documentation
+;; legal values: any string
+title = Generated Documentation
+
+;; parse files that start with a . like .bash_profile
+;; legal values: true, false
+hidden = false
+
+;; show elements marked @access private in documentation by setting this to on
+;; legal values: on, off
+parseprivate = off
+
+pear=on
+
+;; parse with javadoc-like description (first sentence is always the short description)
+;; legal values: on, off
+javadocdesc = off
+
+;; add any custom @tags separated by commas here
+;; legal values: any legal tagname separated by commas.
+;customtags = mytag1,mytag2
+
+;; what is the main package?
+;; legal values: alphanumeric string plus - and _
+defaultpackagename = PEAR_PackageFileManager
+
+defaultcategoryname = pear
+
+;; output any parsing information? set to on for cron jobs
+;; legal values: on
+;quiet = on
+
+;; where should the documentation be written?
+;; legal values: a legal path
+target = /home/cellog/peardoc/en/package
+
+;; limit output to the specified packages, even if others are parsed
+;; legal values: package names separated by commas
+;packageoutput = package1,package2
+
+;; comma-separated list of files to parse
+;; legal values: paths separated by commas
+;filename = /path/to/file1,/path/to/file2,fileincurrentdirectory
+
+;; comma-separated list of directories to parse
+;; legal values: directory paths separated by commas
+;directory = /path1,/path2,.,..,subdirectory
+directory = /home/cellog/pear/PEAR_PackageFileManager
+;directory = /home/CelloG/phpdoc
+
+;; comma-separated list of files, directories or wildcards ? and * (any wildcard) to ignore
+;; legal values: any wildcard strings separated by commas
+;ignore = /path/to/ignore*,*list.php,myfile.php,subdirectory/
+ignore = examples/
+
+;; comma-separated list of Converters to use in outputformat:Convertername:templatedirectory format
+;; legal values: HTML:frames:default,HTML:frames:l0l33t,HTML:frames:phpdoc.de,HTML:frames:phphtmllib
+;; HTML:frames:DOM/default,HTML:frames:DOM/l0l33t,HTML:frames:DOM/phpdoc.de,HTML:Smarty:default
+;; HTML:Smarty:PHP,PDF:default:default,CHM:default:default,XML:DocBook:default
+output=XML:DocBook/peardoc2:default
diff --git a/buildscripts/index/api_index.php b/buildscripts/index/api_index.php
index ac2e37a7..c85fa267 100644
--- a/buildscripts/index/api_index.php
+++ b/buildscripts/index/api_index.php
@@ -25,6 +25,7 @@ class api_index
$count = 0;
foreach($files as $file)
{
+ echo " processing $file...\n";
$content = $this->get_details($file, $this->_api);
$doc = new Zend_Search_Lucene_Document();
@@ -86,8 +87,8 @@ class api_index
if(is_file($filepath) && $entry[0] !== '_')
$files[] = realpath($filepath);
}
- return $files;
$d->close();
+ return $files;
}
function get_doc_content($file)
diff --git a/buildscripts/index/search.php b/buildscripts/index/search.php
new file mode 100644
index 00000000..a34363f4
--- /dev/null
+++ b/buildscripts/index/search.php
@@ -0,0 +1,36 @@
+<?php
+
+if(isset($_GET['keyword']))
+ $keyword=trim($_GET['keyword']);
+else
+ $keyword='';
+
+$zend_path=realpath(dirname(__FILE__).'/../../demos/quickstart/protected/index');
+set_include_path(get_include_path().PATH_SEPARATOR.$zend_path);
+require_once('Zend/Search/Lucene.php');
+
+if($keyword!=='')
+{
+ $search=new Zend_Search_Lucene(realpath(dirname(__FILE__)));
+ $results=$search->find(strtolower($keyword));
+ $content='';
+ foreach($results as $entry)
+ $content.="<li><a href=\"{$entry->link}\">{$entry->title}</a></li>\n";
+ if($content!=='')
+ {
+ $count=count($results);
+ $content="<p>Total <b>$count</b> pages matching keyword <b>".htmlentities($keyword)."</b>.\n<ol>\n$content</ol>\n";
+ }
+ else
+ $content="<p>No page matches <b>".htmlentities($keyword)."</b>.</p>";
+}
+else
+ $content="<p>Please specify a keyword to search for.</p>";
+
+$page=file_get_contents(dirname(__FILE__).'/index.html');
+$page=preg_replace('/<!-- content begin -->.*<!-- content end -->/ms',$content,$page);
+if($keyword!=='')
+ $page=preg_replace('/<input type="text" name="keyword"/','<input type="text" name="keyword" value="'.htmlentities($keyword).'"',$page);
+echo $page;
+
+?> \ No newline at end of file
diff --git a/buildscripts/phing/CREDITS b/buildscripts/phing/CREDITS
new file mode 100644
index 00000000..0aff0706
--- /dev/null
+++ b/buildscripts/phing/CREDITS
@@ -0,0 +1,45 @@
+ _________________________
+ P H I N G
+
+ New PHP5 PHING/2 Development
+ ----------------------------
+
+ Hans Lellelid <hans@xmpl.org>
+ David Giffin <david@giffin.org>
+ Michiel Rook <michiel@trendserver.nl>
+ Sebastian Bergmann <sb@sebastian-bergmann.de>
+
+ If you've done work on phing and you are not listed here, please feel free
+ to add yourself.
+
+ Original PHING/1 Development
+ -----------------------------
+
+ Andreas Aderhold <andi@binarycloud.com>
+ Alex Black <enigma@turingstudio.com>
+ Albert Lash <alash@plateauinnovation.com>
+ Charlie Killian <charlie@tizac.com>
+ Manuel Holtgrewe <grin@gmx.net>
+ Andrzej Nowodworski <a.nowodworski@learn.pl>
+ Jason Hines <jason@greenhell.com>
+ Jesse Estevez <jesseestevez@earthlink.net>
+ Andris Spruds <Andris.Spruds@stud.lba.lv>
+ Ronald TAO <ronaldtao@hotmail.com>
+ Yannick Lecaillez <yl@seasonfive.com>
+ Hans Lellelid <hans@xmpl.org>
+
+ Other libraries/contributions
+ ------------------------------
+
+ Apache ANT Project
+ License: Apache 1.1
+ Phing is a port of the Apache ANT project.
+ http://ant.apache.org/
+
+ TAR Manager Class
+ License: LGPL
+ The Tar archive abstraction class
+ (c) Josh Barger <joshb@npt.com>
+ http://phpclasses.upperdesign.com/browse.html/package/529.html
+
+ --$Id: CREDITS,v 1.6 2005/02/03 13:41:52 mrook Exp $
diff --git a/buildscripts/phing/LICENSE b/buildscripts/phing/LICENSE
new file mode 100644
index 00000000..9139d608
--- /dev/null
+++ b/buildscripts/phing/LICENSE
@@ -0,0 +1,1042 @@
+ _________________________
+
+ P H I N G
+
+
+
+
+
+ Please, be sure to read the license header on any one of the phing core
+
+ files. It explains the licensing scheme.
+
+
+
+ Some files in phing are Perl Artistic, Apache, BSD, or just free. See
+
+ "CREDITS" for a list.
+
+
+
+ We've included a copy of the LGPL for convenience.
+
+
+
+
+
+ LGPL LICENSE
+
+ ------------
+
+
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+
+ Version 2.1, February 1999
+
+
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Everyone is permitted to copy and distribute verbatim copies
+
+ of this license document, but changing it is not allowed.
+
+
+
+ [This is the first released version of the Lesser GPL. It also counts
+
+ as the successor of the GNU Library Public License, version 2, hence
+
+ the version number 2.1.]
+
+
+
+ Preamble
+
+
+
+ The licenses for most software are designed to take away your
+
+ freedom to share and change it. By contrast, the GNU General Public
+
+ Licenses are intended to guarantee your freedom to share and change
+
+ free software--to make sure the software is free for all its users.
+
+
+
+ This license, the Lesser General Public License, applies to some
+
+ specially designated software packages--typically libraries--of the
+
+ Free Software Foundation and other authors who decide to use it. You
+
+ can use it too, but we suggest you first think carefully about whether
+
+ this license or the ordinary General Public License is the better
+
+ strategy to use in any particular case, based on the explanations below.
+
+
+
+ When we speak of free software, we are referring to freedom of use,
+
+ not price. Our General Public Licenses are designed to make sure that
+
+ you have the freedom to distribute copies of free software (and charge
+
+ for this service if you wish); that you receive source code or can get
+
+ it if you want it; that you can change the software and use pieces of
+
+ it in new free programs; and that you are informed that you can do
+
+ these things.
+
+
+
+ To protect your rights, we need to make restrictions that forbid
+
+ distributors to deny you these rights or to ask you to surrender these
+
+ rights. These restrictions translate to certain responsibilities for
+
+ you if you distribute copies of the library or if you modify it.
+
+
+
+ For example, if you distribute copies of the library, whether gratis
+
+ or for a fee, you must give the recipients all the rights that we gave
+
+ you. You must make sure that they, too, receive or can get the source
+
+ code. If you link other code with the library, you must provide
+
+ complete object files to the recipients, so that they can relink them
+
+ with the library after making changes to the library and recompiling
+
+ it. And you must show them these terms so they know their rights.
+
+
+
+ We protect your rights with a two-step method: (1) we copyright the
+
+ library, and (2) we offer you this license, which gives you legal
+
+ permission to copy, distribute and/or modify the library.
+
+
+
+ To protect each distributor, we want to make it very clear that
+
+ there is no warranty for the free library. Also, if the library is
+
+ modified by someone else and passed on, the recipients should know
+
+ that what they have is not the original version, so that the original
+
+ author's reputation will not be affected by problems that might be
+
+ introduced by others.
+
+
+
+ Finally, software patents pose a constant threat to the existence of
+
+ any free program. We wish to make sure that a company cannot
+
+ effectively restrict the users of a free program by obtaining a
+
+ restrictive license from a patent holder. Therefore, we insist that
+
+ any patent license obtained for a version of the library must be
+
+ consistent with the full freedom of use specified in this license.
+
+
+
+ Most GNU software, including some libraries, is covered by the
+
+ ordinary GNU General Public License. This license, the GNU Lesser
+
+ General Public License, applies to certain designated libraries, and
+
+ is quite different from the ordinary General Public License. We use
+
+ this license for certain libraries in order to permit linking those
+
+ libraries into non-free programs.
+
+
+
+ When a program is linked with a library, whether statically or using
+
+ a shared library, the combination of the two is legally speaking a
+
+ combined work, a derivative of the original library. The ordinary
+
+ General Public License therefore permits such linking only if the
+
+ entire combination fits its criteria of freedom. The Lesser General
+
+ Public License permits more lax criteria for linking other code with
+
+ the library.
+
+
+
+ We call this license the "Lesser" General Public License because it
+
+ does Less to protect the user's freedom than the ordinary General
+
+ Public License. It also provides other free software developers Less
+
+ of an advantage over competing non-free programs. These disadvantages
+
+ are the reason we use the ordinary General Public License for many
+
+ libraries. However, the Lesser license provides advantages in certain
+
+ special circumstances.
+
+
+
+ For example, on rare occasions, there may be a special need to
+
+ encourage the widest possible use of a certain library, so that it
+
+ becomes a de-facto standard. To achieve this, non-free programs must be
+
+ allowed to use the library. A more frequent case is that a free
+
+ library does the same job as widely used non-free libraries. In this
+
+ case, there is little to gain by limiting the free library to free
+
+ software only, so we use the Lesser General Public License.
+
+
+
+ In other cases, permission to use a particular library in non-free
+
+ programs enables a greater number of people to use a large body of
+
+ free software. For example, permission to use the GNU C Library in
+
+ non-free programs enables many more people to use the whole GNU
+
+ operating system, as well as its variant, the GNU/Linux operating
+
+ system.
+
+
+
+ Although the Lesser General Public License is Less protective of the
+
+ users' freedom, it does ensure that the user of a program that is
+
+ linked with the Library has the freedom and the wherewithal to run
+
+ that program using a modified version of the Library.
+
+
+
+ The precise terms and conditions for copying, distribution and
+
+ modification follow. Pay close attention to the difference between a
+
+ "work based on the library" and a "work that uses the library". The
+
+ former contains code derived from the library, whereas the latter must
+
+ be combined with the library in order to run.
+
+
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+
+
+ 0. This License Agreement applies to any software library or other
+
+ program which contains a notice placed by the copyright holder or
+
+ other authorized party saying it may be distributed under the terms of
+
+ this Lesser General Public License (also called "this License").
+
+ Each licensee is addressed as "you".
+
+
+
+ A "library" means a collection of software functions and/or data
+
+ prepared so as to be conveniently linked with application programs
+
+ (which use some of those functions and data) to form executables.
+
+
+
+ The "Library", below, refers to any such software library or work
+
+ which has been distributed under these terms. A "work based on the
+
+ Library" means either the Library or any derivative work under
+
+ copyright law: that is to say, a work containing the Library or a
+
+ portion of it, either verbatim or with modifications and/or translated
+
+ straightforwardly into another language. (Hereinafter, translation is
+
+ included without limitation in the term "modification".)
+
+
+
+ "Source code" for a work means the preferred form of the work for
+
+ making modifications to it. For a library, complete source code means
+
+ all the source code for all modules it contains, plus any associated
+
+ interface definition files, plus the scripts used to control compilation
+
+ and installation of the library.
+
+
+
+ Activities other than copying, distribution and modification are not
+
+ covered by this License; they are outside its scope. The act of
+
+ running a program using the Library is not restricted, and output from
+
+ such a program is covered only if its contents constitute a work based
+
+ on the Library (independent of the use of the Library in a tool for
+
+ writing it). Whether that is true depends on what the Library does
+
+ and what the program that uses the Library does.
+
+
+
+ 1. You may copy and distribute verbatim copies of the Library's
+
+ complete source code as you receive it, in any medium, provided that
+
+ you conspicuously and appropriately publish on each copy an
+
+ appropriate copyright notice and disclaimer of warranty; keep intact
+
+ all the notices that refer to this License and to the absence of any
+
+ warranty; and distribute a copy of this License along with the
+
+ Library.
+
+
+
+ You may charge a fee for the physical act of transferring a copy,
+
+ and you may at your option offer warranty protection in exchange for a
+
+ fee.
+
+
+
+ 2. You may modify your copy or copies of the Library or any portion
+
+ of it, thus forming a work based on the Library, and copy and
+
+ distribute such modifications or work under the terms of Section 1
+
+ above, provided that you also meet all of these conditions:
+
+
+
+ a) The modified work must itself be a software library.
+
+
+
+ b) You must cause the files modified to carry prominent notices
+
+ stating that you changed the files and the date of any change.
+
+
+
+ c) You must cause the whole of the work to be licensed at no
+
+ charge to all third parties under the terms of this License.
+
+
+
+ d) If a facility in the modified Library refers to a function or a
+
+ table of data to be supplied by an application program that uses
+
+ the facility, other than as an argument passed when the facility
+
+ is invoked, then you must make a good faith effort to ensure that,
+
+ in the event an application does not supply such function or
+
+ table, the facility still operates, and performs whatever part of
+
+ its purpose remains meaningful.
+
+
+
+ (For example, a function in a library to compute square roots has
+
+ a purpose that is entirely well-defined independent of the
+
+ application. Therefore, Subsection 2d requires that any
+
+ application-supplied function or table used by this function must
+
+ be optional: if the application does not supply it, the square
+
+ root function must still compute square roots.)
+
+
+
+ These requirements apply to the modified work as a whole. If
+
+ identifiable sections of that work are not derived from the Library,
+
+ and can be reasonably considered independent and separate works in
+
+ themselves, then this License, and its terms, do not apply to those
+
+ sections when you distribute them as separate works. But when you
+
+ distribute the same sections as part of a whole which is a work based
+
+ on the Library, the distribution of the whole must be on the terms of
+
+ this License, whose permissions for other licensees extend to the
+
+ entire whole, and thus to each and every part regardless of who wrote
+
+ it.
+
+
+
+ Thus, it is not the intent of this section to claim rights or contest
+
+ your rights to work written entirely by you; rather, the intent is to
+
+ exercise the right to control the distribution of derivative or
+
+ collective works based on the Library.
+
+
+
+ In addition, mere aggregation of another work not based on the Library
+
+ with the Library (or with a work based on the Library) on a volume of
+
+ a storage or distribution medium does not bring the other work under
+
+ the scope of this License.
+
+
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+
+ License instead of this License to a given copy of the Library. To do
+
+ this, you must alter all the notices that refer to this License, so
+
+ that they refer to the ordinary GNU General Public License, version 2,
+
+ instead of to this License. (If a newer version than version 2 of the
+
+ ordinary GNU General Public License has appeared, then you can specify
+
+ that version instead if you wish.) Do not make any other change in
+
+ these notices.
+
+
+
+ Once this change is made in a given copy, it is irreversible for
+
+ that copy, so the ordinary GNU General Public License applies to all
+
+ subsequent copies and derivative works made from that copy.
+
+
+
+ This option is useful when you wish to copy part of the code of
+
+ the Library into a program that is not a library.
+
+
+
+ 4. You may copy and distribute the Library (or a portion or
+
+ derivative of it, under Section 2) in object code or executable form
+
+ under the terms of Sections 1 and 2 above provided that you accompany
+
+ it with the complete corresponding machine-readable source code, which
+
+ must be distributed under the terms of Sections 1 and 2 above on a
+
+ medium customarily used for software interchange.
+
+
+
+ If distribution of object code is made by offering access to copy
+
+ from a designated place, then offering equivalent access to copy the
+
+ source code from the same place satisfies the requirement to
+
+ distribute the source code, even though third parties are not
+
+ compelled to copy the source along with the object code.
+
+
+
+ 5. A program that contains no derivative of any portion of the
+
+ Library, but is designed to work with the Library by being compiled or
+
+ linked with it, is called a "work that uses the Library". Such a
+
+ work, in isolation, is not a derivative work of the Library, and
+
+ therefore falls outside the scope of this License.
+
+
+
+ However, linking a "work that uses the Library" with the Library
+
+ creates an executable that is a derivative of the Library (because it
+
+ contains portions of the Library), rather than a "work that uses the
+
+ library". The executable is therefore covered by this License.
+
+ Section 6 states terms for distribution of such executables.
+
+
+
+ When a "work that uses the Library" uses material from a header file
+
+ that is part of the Library, the object code for the work may be a
+
+ derivative work of the Library even though the source code is not.
+
+ Whether this is true is especially significant if the work can be
+
+ linked without the Library, or if the work is itself a library. The
+
+ threshold for this to be true is not precisely defined by law.
+
+
+
+ If such an object file uses only numerical parameters, data
+
+ structure layouts and accessors, and small macros and small inline
+
+ functions (ten lines or less in length), then the use of the object
+
+ file is unrestricted, regardless of whether it is legally a derivative
+
+ work. (Executables containing this object code plus portions of the
+
+ Library will still fall under Section 6.)
+
+
+
+ Otherwise, if the work is a derivative of the Library, you may
+
+ distribute the object code for the work under the terms of Section 6.
+
+ Any executables containing that work also fall under Section 6,
+
+ whether or not they are linked directly with the Library itself.
+
+
+
+ 6. As an exception to the Sections above, you may also combine or
+
+ link a "work that uses the Library" with the Library to produce a
+
+ work containing portions of the Library, and distribute that work
+
+ under terms of your choice, provided that the terms permit
+
+ modification of the work for the customer's own use and reverse
+
+ engineering for debugging such modifications.
+
+
+
+ You must give prominent notice with each copy of the work that the
+
+ Library is used in it and that the Library and its use are covered by
+
+ this License. You must supply a copy of this License. If the work
+
+ during execution displays copyright notices, you must include the
+
+ copyright notice for the Library among them, as well as a reference
+
+ directing the user to the copy of this License. Also, you must do one
+
+ of these things:
+
+
+
+ a) Accompany the work with the complete corresponding
+
+ machine-readable source code for the Library including whatever
+
+ changes were used in the work (which must be distributed under
+
+ Sections 1 and 2 above); and, if the work is an executable linked
+
+ with the Library, with the complete machine-readable "work that
+
+ uses the Library", as object code and/or source code, so that the
+
+ user can modify the Library and then relink to produce a modified
+
+ executable containing the modified Library. (It is understood
+
+ that the user who changes the contents of definitions files in the
+
+ Library will not necessarily be able to recompile the application
+
+ to use the modified definitions.)
+
+
+
+ b) Use a suitable shared library mechanism for linking with the
+
+ Library. A suitable mechanism is one that (1) uses at run time a
+
+ copy of the library already present on the user's computer system,
+
+ rather than copying library functions into the executable, and (2)
+
+ will operate properly with a modified version of the library, if
+
+ the user installs one, as long as the modified version is
+
+ interface-compatible with the version that the work was made with.
+
+
+
+ c) Accompany the work with a written offer, valid for at
+
+ least three years, to give the same user the materials
+
+ specified in Subsection 6a, above, for a charge no more
+
+ than the cost of performing this distribution.
+
+
+
+ d) If distribution of the work is made by offering access to copy
+
+ from a designated place, offer equivalent access to copy the above
+
+ specified materials from the same place.
+
+
+
+ e) Verify that the user has already received a copy of these
+
+ materials or that you have already sent this user a copy.
+
+
+
+ For an executable, the required form of the "work that uses the
+
+ Library" must include any data and utility programs needed for
+
+ reproducing the executable from it. However, as a special exception,
+
+ the materials to be distributed need not include anything that is
+
+ normally distributed (in either source or binary form) with the major
+
+ components (compiler, kernel, and so on) of the operating system on
+
+ which the executable runs, unless that component itself accompanies
+
+ the executable.
+
+
+
+ It may happen that this requirement contradicts the license
+
+ restrictions of other proprietary libraries that do not normally
+
+ accompany the operating system. Such a contradiction means you cannot
+
+ use both them and the Library together in an executable that you
+
+ distribute.
+
+
+
+ 7. You may place library facilities that are a work based on the
+
+ Library side-by-side in a single library together with other library
+
+ facilities not covered by this License, and distribute such a combined
+
+ library, provided that the separate distribution of the work based on
+
+ the Library and of the other library facilities is otherwise
+
+ permitted, and provided that you do these two things:
+
+
+
+ a) Accompany the combined library with a copy of the same work
+
+ based on the Library, uncombined with any other library
+
+ facilities. This must be distributed under the terms of the
+
+ Sections above.
+
+
+
+ b) Give prominent notice with the combined library of the fact
+
+ that part of it is a work based on the Library, and explaining
+
+ where to find the accompanying uncombined form of the same work.
+
+
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+
+ the Library except as expressly provided under this License. Any
+
+ attempt otherwise to copy, modify, sublicense, link with, or
+
+ distribute the Library is void, and will automatically terminate your
+
+ rights under this License. However, parties who have received copies,
+
+ or rights, from you under this License will not have their licenses
+
+ terminated so long as such parties remain in full compliance.
+
+
+
+ 9. You are not required to accept this License, since you have not
+
+ signed it. However, nothing else grants you permission to modify or
+
+ distribute the Library or its derivative works. These actions are
+
+ prohibited by law if you do not accept this License. Therefore, by
+
+ modifying or distributing the Library (or any work based on the
+
+ Library), you indicate your acceptance of this License to do so, and
+
+ all its terms and conditions for copying, distributing or modifying
+
+ the Library or works based on it.
+
+
+
+ 10. Each time you redistribute the Library (or any work based on the
+
+ Library), the recipient automatically receives a license from the
+
+ original licensor to copy, distribute, link with or modify the Library
+
+ subject to these terms and conditions. You may not impose any further
+
+ restrictions on the recipients' exercise of the rights granted herein.
+
+ You are not responsible for enforcing compliance by third parties with
+
+ this License.
+
+
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+
+ infringement or for any other reason (not limited to patent issues),
+
+ conditions are imposed on you (whether by court order, agreement or
+
+ otherwise) that contradict the conditions of this License, they do not
+
+ excuse you from the conditions of this License. If you cannot
+
+ distribute so as to satisfy simultaneously your obligations under this
+
+ License and any other pertinent obligations, then as a consequence you
+
+ may not distribute the Library at all. For example, if a patent
+
+ license would not permit royalty-free redistribution of the Library by
+
+ all those who receive copies directly or indirectly through you, then
+
+ the only way you could satisfy both it and this License would be to
+
+ refrain entirely from distribution of the Library.
+
+
+
+ If any portion of this section is held invalid or unenforceable under any
+
+ particular circumstance, the balance of the section is intended to apply,
+
+ and the section as a whole is intended to apply in other circumstances.
+
+
+
+ It is not the purpose of this section to induce you to infringe any
+
+ patents or other property right claims or to contest validity of any
+
+ such claims; this section has the sole purpose of protecting the
+
+ integrity of the free software distribution system which is
+
+ implemented by public license practices. Many people have made
+
+ generous contributions to the wide range of software distributed
+
+ through that system in reliance on consistent application of that
+
+ system; it is up to the author/donor to decide if he or she is willing
+
+ to distribute software through any other system and a licensee cannot
+
+ impose that choice.
+
+
+
+ This section is intended to make thoroughly clear what is believed to
+
+ be a consequence of the rest of this License.
+
+
+
+ 12. If the distribution and/or use of the Library is restricted in
+
+ certain countries either by patents or by copyrighted interfaces, the
+
+ original copyright holder who places the Library under this License may
+
+ add an explicit geographical distribution limitation excluding those
+
+ countries, so that distribution is permitted only in or among countries
+
+ not thus excluded. In such case, this License incorporates the
+
+ limitation as if written in the body of this License.
+
+
+
+ 13. The Free Software Foundation may publish revised and/or new
+
+ versions of the Lesser General Public License from time to time.
+
+ Such new versions will be similar in spirit to the present version,
+
+ but may differ in detail to address new problems or concerns.
+
+
+
+ Each version is given a distinguishing version number. If the Library
+
+ specifies a version number of this License which applies to it and
+
+ "any later version", you have the option of following the terms and
+
+ conditions either of that version or of any later version published by
+
+ the Free Software Foundation. If the Library does not specify a
+
+ license version number, you may choose any version ever published by
+
+ the Free Software Foundation.
+
+
+
+ 14. If you wish to incorporate parts of the Library into other free
+
+ programs whose distribution conditions are incompatible with these,
+
+ write to the author to ask for permission. For software which is
+
+ copyrighted by the Free Software Foundation, write to the Free
+
+ Software Foundation; we sometimes make exceptions for this. Our
+
+ decision will be guided by the two goals of preserving the free status
+
+ of all derivatives of our free software and of promoting the sharing
+
+ and reuse of software generally.
+
+
+
+ NO WARRANTY
+
+
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+
+ WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+
+ EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+
+ OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+
+ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+
+ LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+
+ THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+
+ WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+
+ AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+
+ FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+
+ CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+
+ LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+
+ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+
+ DAMAGES.
+
+
+
+ END OF TERMS AND CONDITIONS
+
+
+
+ How to Apply These Terms to Your New Libraries
+
+
+
+ If you develop a new library, and you want it to be of the greatest
+
+ possible use to the public, we recommend making it free software that
+
+ everyone can redistribute and change. You can do so by permitting
+
+ redistribution under these terms (or, alternatively, under the terms of the
+
+ ordinary General Public License).
+
+
+
+ To apply these terms, attach the following notices to the library. It is
+
+ safest to attach them to the start of each source file to most effectively
+
+ convey the exclusion of warranty; and each file should have at least the
+
+ "copyright" line and a pointer to where the full notice is found.
+
+
+
+ <one line to give the library's name and a brief idea of what it does.>
+
+ Copyright (C) <year> <name of author>
+
+
+
+ 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
+
+
+
+ Also add information on how to contact you by electronic and paper mail.
+
+
+
+ You should also get your employer (if you work as a programmer) or your
+
+ school, if any, to sign a "copyright disclaimer" for the library, if
+
+ necessary. Here is a sample; alter the names:
+
+
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+
+
+ <signature of Ty Coon>, 1 April 1990
+
+ Ty Coon, President of Vice
+
+
+
+ That's all there is to it!
+
+
+
+ --$Id: LICENSE,v 1.3 2003/11/06 18:18:06 hlellelid Exp $
+
+
+
diff --git a/buildscripts/phing/README b/buildscripts/phing/README
new file mode 100644
index 00000000..c2b64302
--- /dev/null
+++ b/buildscripts/phing/README
@@ -0,0 +1,78 @@
+ _________________________
+ P H I N G
+
+
+
+ What is it?
+ -----------
+
+ Phing is a PHP based build tool. In theory it is kind of like "make"
+ without makes drawbacks and with the full portability and performance
+ of PHP. (PH)pmake (I)s (N)ot (G)numake
+
+ Why?
+ ----
+
+ Why another build tool when there is already make, gnumake, nmake, jam, ant,
+ and others? Because all those tools have limitations that the binarycloud
+ development team could not live with when developing software across
+ different platforms. Make-like tools are inherently shell-based: they
+ evaluate a set of dependencies, then execute commands not unlike what you
+ would issue on a shell.
+
+ This means that you can easily extend these tools by using or writing any
+ program for the OS that you are working on; however, this also means that
+ you limit yourself to the OS, or at least the OS type, such as Unix, that
+ you are working on.
+
+ Makefiles are inherently evil as well. Anybody who has worked on them for
+ any time has run into the dreaded tab problem. "Is my command not executing
+ because I have a space in front of my tab?!!". Tools like Jam took care of
+ this to a great degree, but still have yet another format to use and
+ remember. Of course there is the Java based build tool ant, that is very
+ good approach to what now Phing is. But still based on Java you have to have
+ at least a running JRE installation on your plattfrom.
+ Great for Java projects but we thought this is very consistent way to build
+ a PHP based project. Additionally ant does not support a autoconf tool that
+ writes out proper buildfiles based on some simple rules prior defined in a
+ XML Configuration file.
+
+ Phing is different. Instead of a model where it is extended with shell-based
+ commands, Phing is extended using PHP classes. Instead of writing shell
+ commands, the configuration files are XML-based, calling a target tree where
+ various tasks get executed. Each task is run by an object that implements
+ a particular Task action.
+
+ Of course, this removes some of the expressive power that is inherent in
+ being able to construct a shell command such as
+ % `find . -name foo -exec rm {}`
+ but it gives you the ability to be cross-platform - to work anywhere and
+ everywhere. And if you really need to execute a shell command, Phing has an <exec>
+ task that allows different commands to be executed based on the operating
+ system it is executing on.
+
+ The Latest Version
+ ------------------
+
+ Details of the latest version can be found on the Phing homepage
+ <http://phing.info/>.
+
+ Documentation
+ -------------
+
+ Documentation is available in XHTML format in the docs/ directory. In particular,
+ open the docs/phing_guide/book/index.html in a frames-compatible browser to see the
+ phing user guide.
+
+ For installing see INSTALL.<platform> files in the Phing root.
+
+ Licensing
+ ---------
+
+ This software is licensed under the terms you may find in the file
+ named "LICENSE" in this directory.
+
+ Thanks for using PHING.
+
+
+ --$Id: README,v 1.4 2004/03/20 04:14:35 hlellelid Exp $
diff --git a/buildscripts/phing/bin/pear-phing b/buildscripts/phing/bin/pear-phing
new file mode 100644
index 00000000..bf568c17
--- /dev/null
+++ b/buildscripts/phing/bin/pear-phing
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# ------------------------------------------------------------------------
+# The phing build script for Unix based systems
+# $Id: pear-phing,v 1.3 2003/12/23 19:45:14 hlellelid Exp $
+# ------------------------------------------------------------------------
+
+# Change this to reflect your environment if the default value doesn't work
+PHP_COMMAND="@PHP-BIN@"
+export PHP_COMMAND
+
+# -------------------------------------------------------------------------
+# Do not change anything below this line unless you know what you're doing.
+# -------------------------------------------------------------------------
+
+if (test -z "$PHP_COMMAND") ; then
+ echo "WARNING: PHP_COMMAND environment not set. (Assuming php on PATH)"
+ PHP_COMMAND=php
+ export PHP_COMMAND
+fi
+
+$PHP_COMMAND -d html_errors=off -qC @PEAR-DIR@/phing.php -logger phing.listener.AnsiColorLogger $*
diff --git a/buildscripts/phing/bin/pear-phing.bat b/buildscripts/phing/bin/pear-phing.bat
new file mode 100644
index 00000000..fba90772
--- /dev/null
+++ b/buildscripts/phing/bin/pear-phing.bat
@@ -0,0 +1,44 @@
+@ECHO OFF
+
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+:: The phing build script for Windows based systems
+:: $Id: pear-phing.bat,v 1.4 2005/12/22 13:12:33 hlellelid Exp $
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+::----------------------------------------------------------------------------------
+:: Please set following to PHP's CLI
+:: NOTE: In PHP 4.2.x the PHP-CLI used to be named php-cli.exe.
+:: PHP 4.3.x names it php.exe but stores it in a subdir called /cli/php.exe
+:: E.g. for PHP 4.2 C:\phpdev\php-4.2-Win32\php-cli.exe
+:: for PHP 4.3 C:\phpdev\php-4.3-Win32\cli\php.exe
+
+ SET phpCli=@PHP-BIN@
+
+::---------------------------------------------------------------------------------
+::---------------------------------------------------------------------------------
+:: Do not modify below this line!! (Unless you know what your doing :)
+::---------------------------------------------------------------------------------
+::---------------------------------------------------------------------------------
+
+:: Check existence of php.exe
+IF EXIST "%phpCli%" (
+ SET doNothing=
+) ELSE GOTO :NoPhpCli
+
+"%phpCli%" -d html_errors=off -qC "@PEAR-DIR@\phing.php" %*
+GOTO :EOF
+
+::
+:: php.exe not found error
+GOTO :PAUSE_END
+:NoPhpCli
+ECHO ** ERROR *****************************************************************
+ECHO * Sorry, can't find the php.exe file.
+ECHO * You must edit this file to point to your php.exe (CLI version!)
+ECHO * [Currently set to %phpCli%]
+ECHO **************************************************************************
+
+GOTO :PAUSE_END
+
+:PAUSE_END
+PAUSE \ No newline at end of file
diff --git a/buildscripts/phing/bin/phing b/buildscripts/phing/bin/phing
new file mode 100644
index 00000000..e24c6cfb
--- /dev/null
+++ b/buildscripts/phing/bin/phing
@@ -0,0 +1,75 @@
+#!/bin/sh
+# Shell wrapper for Phing
+# $Id: phing,v 1.2 2006/01/23 21:51:16 mrook Exp $
+#
+# This script will do the following:
+# - check for PHP_COMMAND env, if found, use it.
+# - if not found assume php is on the path
+# - check for PHING_HOME evn, if found use it
+# - if not look for it
+# - check for PHP_CLASSPATH, if found use it
+# - if not found set it using PHING_HOME/classes
+
+if [ -z "$PHING_HOME" ] ; then
+
+ # echo "WARNING: PHING_HOME environment not set. Attempting to guess."
+
+ # try to find PHING
+ if [ -d /opt/phing ] ; then
+ PHING_HOME=/opt/phing
+ fi
+
+ if [ -d "${HOME}/opt/phing" ] ; then
+ PHING_HOME="${HOME}/opt/phing"
+ fi
+
+ if [ -d "/usr/local/phing" ] ; then
+ PHING_HOME="/usr/local/phing"
+ fi
+
+ if [ -d "${HOME}/usr/phing" ] ; then
+ PHING_HOME="${HOME}/usr/phing"
+ fi
+
+ ## resolve links - $0 may be a link to phing's home
+ PRG="$0"
+ progname=`basename "$0"`
+ saveddir=`pwd`
+
+ # need this for relative symlinks
+ dirname_prg=`dirname "$PRG"`
+ cd "$dirname_prg"
+
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+ done
+
+ PHING_HOME=`dirname "$PRG"`/..
+
+ cd "$saveddir"
+
+ # make it fully qualified
+ PHING_HOME=`cd "$PHING_HOME" && pwd`
+
+ # make it available in PHP via getenv("PHING_HOME")
+ export PHING_HOME
+fi
+
+if (test -z "$PHP_COMMAND") ; then
+ # echo "WARNING: PHP_COMMAND environment not set. (Assuming php on PATH)"
+ PHP_COMMAND=php
+ export PHP_COMMAND
+fi
+
+if (test -z "$PHP_CLASSPATH") ; then
+ PHP_CLASSPATH=$PHING_HOME/classes
+ export PHP_CLASSPATH
+fi
+
+$PHP_COMMAND -d html_errors=off -qC $PHING_HOME/bin/phing.php -logger phing.listener.AnsiColorLogger $@
diff --git a/buildscripts/phing/bin/phing.bat b/buildscripts/phing/bin/phing.bat
new file mode 100644
index 00000000..c57c30dd
--- /dev/null
+++ b/buildscripts/phing/bin/phing.bat
@@ -0,0 +1,58 @@
+@echo off
+
+rem *********************************************************************
+rem ** the phing build script for Windows based systems
+rem ** $Id: phing.bat,v 1.5 2003/11/06 14:56:13 hlellelid Exp $
+rem *********************************************************************
+
+rem This script will do the following:
+rem - check for PHP_COMMAND env, if found, use it.
+rem - if not found detect php, if found use it, otherwise err and terminate
+rem - check for PHING_HOME evn, if found use it
+rem - if not found error and leave
+rem - check for PHP_CLASSPATH, if found use it
+rem - if not found set it using PHING_HOME/classes
+
+if "%OS%"=="Windows_NT" @setlocal
+
+rem %~dp0 is expanded pathname of the current script under NT
+set DEFAULT_PHING_HOME=%~dp0..
+
+goto init
+goto cleanup
+
+:init
+
+if "%PHING_HOME%" == "" set PHING_HOME=%DEFAULT_PHING_HOME%
+set DEFAULT_PHING_HOME=
+
+if "%PHP_COMMAND%" == "" goto no_phpcommand
+if "%PHP_CLASSPATH%" == "" goto set_classpath
+
+goto run
+goto cleanup
+
+:run
+%PHP_COMMAND% -d html_errors=off -qC %PHING_HOME%\bin\phing.php %1 %2 %3 %4 %5 %6 %7 %8 %9
+goto cleanup
+
+:no_phpcommand
+REM echo ------------------------------------------------------------------------
+REM echo WARNING: Set environment var PHP_COMMAND to the location of your php.exe
+REM echo executable (e.g. C:\PHP\php.exe). (Assuming php.exe on Path)
+REM echo ------------------------------------------------------------------------
+set PHP_COMMAND=php.exe
+goto init
+
+:err_home
+echo ERROR: Environment var PHING_HOME not set. Please point this
+echo variable to your local phing installation!
+goto cleanup
+
+:set_classpath
+set PHP_CLASSPATH="%PHING_HOME%\classes"
+goto init
+
+:cleanup
+if "%OS%"=="Windows_NT" @endlocal
+REM pause
diff --git a/buildscripts/phing/bin/phing.php b/buildscripts/phing/bin/phing.php
new file mode 100644
index 00000000..880adf41
--- /dev/null
+++ b/buildscripts/phing/bin/phing.php
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * This is the Phing command line launcher. It starts up the system evironment
+ * tests for all important paths and properties and kicks of the main command-
+ * line entry point of phing located in phing.Phing
+ * @version $Revision: 1.7 $
+ */
+
+// Set any INI options for PHP
+// ---------------------------
+
+ini_set('track_errors', 1);
+
+/* set classpath */
+if (getenv('PHP_CLASSPATH')) {
+// define('PHP_CLASSPATH', getenv('PHP_CLASSPATH') . PATH_SEPARATOR . get_include_path());
+ define('PHP_CLASSPATH', realpath(dirname(__FILE__).'/../classes') . PATH_SEPARATOR . get_include_path());
+ ini_set('include_path', PHP_CLASSPATH);
+} else {
+ define('PHP_CLASSPATH', get_include_path());
+}
+
+require_once 'phing/Phing.php';
+
+/* Setup Phing environment */
+Phing::startup();
+
+/*
+ find phing home directory
+ -- if Phing is installed from PEAR this will probably be null,
+ which is fine (I think). Nothing uses phing.home right now.
+*/
+Phing::setProperty('phing.home', getenv('PHING_HOME'));
+
+
+/* polish CLI arguments */
+$args = isset($argv) ? $argv : $_SERVER['argv']; // $_SERVER['argv'] seems not to work when argv is registered (PHP5b4)
+array_shift($args); // 1st arg is script name, so drop it
+
+/* fire main application */
+Phing::fire($args);
+
+/*
+ exit OO system if not already called by Phing
+ -- basically we should not need this due to register_shutdown_function in Phing
+ */
+ Phing::halt(0);
+
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/BuildEvent.php b/buildscripts/phing/classes/phing/BuildEvent.php
new file mode 100644
index 00000000..d4e1ea79
--- /dev/null
+++ b/buildscripts/phing/classes/phing/BuildEvent.php
@@ -0,0 +1,205 @@
+<?php
+/*
+ * $Id: BuildEvent.php,v 1.10 2005/12/22 22:44:46 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/system/lang/EventObject.php';
+
+/**
+ * Encapsulates a build specific event.
+ *
+ * <p>We have three sources of events all handled by this class:
+ *
+ * <ul>
+ * <li>Project level events</li>
+ * <li>Target level events</li>
+ * <li>Task level events</li>
+ * </ul>
+ *
+ * <p> Events are all fired from the project class by creating an event object
+ * using this class and passing it to the listeners.
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.10 $
+ * @package phing
+ */
+class BuildEvent extends EventObject {
+
+ /**
+ * A reference to the project
+ * @var Project
+ */
+ protected $project;
+
+ /**
+ * A reference to the target
+ * @var Target
+ */
+ protected $target;
+
+ /**
+ * A reference to the task
+ *
+ * @var Task
+ */
+ protected $task;
+
+ /**
+ * The message of this event, if the event is a message
+ * @var string
+ * @access private
+ */
+ protected $message = null;
+
+ /**
+ * The priority of the message
+ *
+ * @var string
+ * @see $message
+ * @access private
+ */
+ protected $priority = PROJECT_MSG_VERBOSE;
+
+ /**
+ * The execption that caused the event, if any
+ *
+ * @var object
+ * @access private
+ */
+ protected $exception = null;
+
+ /**
+ * Construct a BuildEvent for a project, task or target source event
+ *
+ * @param object project the project that emitted the event.
+ * @access public
+ */
+ function __construct($source) {
+ parent::__construct($source);
+ if ($source instanceof Project) {
+ $this->project = $source;
+ $this->target = null;
+ $this->task = null;
+ } elseif ($source instanceof Target) {
+ $this->project = $source->getProject();
+ $this->target = $source;
+ $this->task = null;
+ } elseif ($source instanceof Task) {
+ $this->project = $source->getProject();
+ $this->target = $source->getOwningTarget();
+ $this->task = $source;
+ } else {
+ throw new Exception("Can not construct BuildEvent, unknown source given.");
+ }
+ }
+
+ /**
+ * Sets the message with details and the message priority for this event.
+ *
+ * @param string The string message of the event
+ * @param integer The priority this message should have
+ */
+ function setMessage($message, $priority) {
+ $this->message = (string) $message;
+ $this->priority = (int) $priority;
+ }
+
+ /**
+ * Set the exception that was the cause of this event.
+ *
+ * @param Exception The exception that caused the event
+ */
+ function setException($exception) {
+ $this->exception = $exception;
+ }
+
+ /**
+ * Returns the project instance that fired this event.
+ *
+ * The reference to the project instance is set by the constructor if this
+ * event was fired from the project class.
+ *
+ * @return Project The project instance that fired this event
+ */
+ function getProject() {
+ return $this->project;
+ }
+
+ /**
+ * Returns the target instance that fired this event.
+ *
+ * The reference to the target instance is set by the constructor if this
+ * event was fired from the target class.
+ *
+ * @return object The target that fired this event
+ * @access public
+ */
+ function getTarget() {
+ return $this->target;
+ }
+
+ /**
+ * Returns the target instance that fired this event.
+ *
+ * The reference to the task instance is set by the constructor if this
+ * event was fired within a task.
+ *
+ * @return object The task that fired this event
+ * @access public
+ */
+ function getTask() {
+ return $this->task;
+ }
+
+ /**
+ * Returns the logging message. This field will only be set for
+ * "messageLogged" events.
+ *
+ * @return string The log message
+ * @access public
+ */
+ function getMessage() {
+ return $this->message;
+ }
+
+ /**
+ * Returns the priority of the logging message. This field will only
+ * be set for "messageLogged" events.
+ *
+ * @return integer The message priority
+ * @access public
+ */
+ function getPriority() {
+ return $this->priority;
+ }
+
+ /**
+ * Returns the exception that was thrown, if any.
+ * This field will only be set for "taskFinished", "targetFinished", and
+ * "buildFinished" events.
+ *
+ * @see BuildListener::taskFinished()
+ * @see BuildListener::targetFinished()
+ * @see BuildListener::buildFinished()
+ */
+ function getException() {
+ return $this->exception;
+ }
+}
diff --git a/buildscripts/phing/classes/phing/BuildException.php b/buildscripts/phing/classes/phing/BuildException.php
new file mode 100644
index 00000000..8c108130
--- /dev/null
+++ b/buildscripts/phing/classes/phing/BuildException.php
@@ -0,0 +1,100 @@
+<?php
+/*
+ * $Id: BuildException.php,v 1.12 2005/02/27 20:52:07 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * BuildException is for when things go wrong in a build execution.
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @version $Revision: 1.12 $
+ * @package phing
+ */
+class BuildException extends Exception {
+
+ /** location in the xml file */
+ protected $location = null;
+
+ /** The nested "cause" exception. */
+ protected $cause;
+
+ /**
+ * Construct a BuildException.
+ * Supported signatures:
+ * throw new BuildException($causeExc);
+ * throw new BuildException($msg);
+ * throw new Buildexception($causeExc, $loc);
+ * throw new BuildException($msg, $causeExc);
+ * throw new BuildException($msg, $loc);
+ * throw new BuildException($msg, $causeExc, $loc);
+ */
+ function __construct($p1, $p2 = null, $p3 = null) {
+
+ $cause = null;
+ $loc = null;
+ $msg = "";
+
+ if ($p3 !== null) {
+ $cause = $p2;
+ $loc = $p3;
+ $msg = $p1;
+ } elseif ($p2 !== null) {
+ if ($p2 instanceof Exception) {
+ $cause = $p2;
+ $msg = $p1;
+ } elseif ($p2 instanceof Location) {
+ $loc = $p2;
+ if ($p1 instanceof Exception) {
+ $cause = $p1;
+ } else {
+ $msg = $p1;
+ }
+ }
+ } elseif ($p1 instanceof Exception) {
+ $cause = $p1;
+ } else {
+ $msg = $p1;
+ }
+
+ parent::__construct($msg);
+
+ if ($cause !== null) {
+ $this->cause = $cause;
+ $this->message .= " [wrapped: " . $cause->getMessage() ."]";
+ }
+
+ if ($loc !== null) {
+ $this->setLocation($loc);
+ }
+ }
+
+ function getCause() {
+ return $this->cause;
+ }
+
+ function getLocation() {
+ return $this->location;
+ }
+
+ function setLocation($loc) {
+ $this->location = $loc;
+ $this->message = $loc->toString() . ': ' . $this->message;
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/BuildListener.php b/buildscripts/phing/classes/phing/BuildListener.php
new file mode 100644
index 00000000..12a96c7b
--- /dev/null
+++ b/buildscripts/phing/classes/phing/BuildListener.php
@@ -0,0 +1,91 @@
+<?php
+/*
+ * $Id: BuildListener.php,v 1.6 2003/12/22 18:05:38 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * Interface for build listeners.
+ *
+ * Classes that implement a listener must extend this class and (faux)implement
+ * all methods that are decleard as dummies below.
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.6 $
+ * @see BuildEvent
+ * @see Project::addBuildListener()
+ * @package phing
+ */
+interface BuildListener {
+
+ /**
+ * Fired before any targets are started.
+ *
+ * @param BuildEvent The BuildEvent
+ */
+ function buildStarted(BuildEvent $event);
+
+ /**
+ * Fired after the last target has finished.
+ *
+ * @param BuildEvent The BuildEvent
+ * @see BuildEvent::getException()
+ */
+ function buildFinished(BuildEvent $event);
+
+ /**
+ * Fired when a target is started.
+ *
+ * @param BuildEvent The BuildEvent
+ * @see BuildEvent::getTarget()
+ */
+ function targetStarted(BuildEvent $event);
+
+ /**
+ * Fired when a target has finished.
+ *
+ * @param BuildEvent The BuildEvent
+ * @see BuildEvent#getException()
+ */
+ function targetFinished(BuildEvent $event);
+
+ /**
+ * Fired when a task is started.
+ *
+ * @param BuildEvent The BuildEvent
+ * @see BuildEvent::getTask()
+ */
+ function taskStarted(BuildEvent $event);
+
+ /**
+ * Fired when a task has finished.
+ *
+ * @param BuildEvent The BuildEvent
+ * @see BuildEvent::getException()
+ */
+ function taskFinished(BuildEvent $event);
+
+ /**
+ * Fired whenever a message is logged.
+ *
+ * @param BuildEvent The BuildEvent
+ * @see BuildEvent::getMessage()
+ */
+ function messageLogged(BuildEvent $event);
+}
diff --git a/buildscripts/phing/classes/phing/IntrospectionHelper.php b/buildscripts/phing/classes/phing/IntrospectionHelper.php
new file mode 100644
index 00000000..b4300950
--- /dev/null
+++ b/buildscripts/phing/classes/phing/IntrospectionHelper.php
@@ -0,0 +1,542 @@
+<?php
+
+/*
+ * $Id: IntrospectionHelper.php,v 1.19 2005/11/08 20:45:59 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/types/Reference.php';
+include_once 'phing/types/Path.php';
+include_once 'phing/util/StringHelper.php';
+
+/**
+ * Helper class that collects the methods that a task or nested element
+ * holds to set attributes, create nested elements or hold PCDATA
+ * elements.
+ *
+ *<ul>
+ * <li><strong>SMART-UP INLINE DOCS</strong></li>
+ * <li><strong>POLISH-UP THIS CLASS</strong></li>
+ *</ul>
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @copyright © 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.19 $
+ * @package phing
+ */
+class IntrospectionHelper {
+
+
+
+ /**
+ * Holds the attribute setter methods.
+ *
+ * @var array string[]
+ */
+ private $attributeSetters = array();
+
+ /**
+ * Holds methods to create nested elements.
+ *
+ * @var array string[]
+ */
+ private $nestedCreators = array();
+
+ /**
+ * Holds methods to store configured nested elements.
+ *
+ * @var array string[]
+ */
+ private $nestedStorers = array();
+
+ /**
+ * Map from attribute names to nested types.
+ */
+ private $nestedTypes = array();
+
+ /**
+ * New idea in phing: any class can register certain
+ * keys -- e.g. "task.current_file" -- which can be used in
+ * task attributes, if supported. In the build XML these
+ * are referred to like this:
+ * <regexp pattern="\n" replace="%{task.current_file}"/>
+ * In the type/task a listener method must be defined:
+ * function setListeningReplace($slot) {}
+ * @var array string[]
+ */
+ private $slotListeners = array();
+
+ /**
+ * The method to add PCDATA stuff.
+ *
+ * @var string Method name of the addText (redundant?) method, if class supports it :)
+ */
+ private $methodAddText = null;
+
+ /**
+ * The Class that's been introspected.
+ *
+ * @var object
+ * @access private
+ */
+ private $bean;
+
+ /**
+ * The cache of IntrospectionHelper classes instantiated by getHelper().
+ * @var array IntrospectionHelpers[]
+ */
+ private static $helpers = array();
+
+ /**
+ * Factory method for helper objects.
+ *
+ * @param string $class The class to create a Helper for
+ */
+ public static function getHelper($class) {
+ if (!isset(self::$helpers[$class])) {
+ self::$helpers[$class] = new IntrospectionHelper($class);
+ }
+ return self::$helpers[$class];
+ }
+
+ /**
+ * This function constructs a new introspection helper for a specific class.
+ *
+ * This method loads all methods for the specified class and categorizes them
+ * as setters, creators, slot listeners, etc. This way, the setAttribue() doesn't
+ * need to perform any introspection -- either the requested attribute setter/creator
+ * exists or it does not & a BuildException is thrown.
+ *
+ * @param string $bean The classname for this IH.
+ */
+ function __construct($class) {
+
+ $this->bean = new ReflectionClass($class);
+
+ //$methods = get_class_methods($bean);
+ foreach($this->bean->getMethods() as $method) {
+
+ if ($method->isPublic()) {
+
+ // We're going to keep case-insensitive method names
+ // for as long as we're allowed :) It makes it much
+ // easier to map XML attributes to PHP class method names.
+ $name = strtolower($method->getName());
+
+ // There are a few "reserved" names that might look like attribute setters
+ // but should actually just be skipped. (Note: this means you can't ever
+ // have an attribute named "location" or "tasktype" or a nested element named "task".)
+ if ($name === "setlocation" || $name === "settasktype" || $name === "addtask") {
+ continue;
+ }
+
+ if ($name === "addtext") {
+
+ $this->methodAddText = $method;
+
+ } elseif (strpos($name, "setlistening") === 0) {
+
+ // Phing supports something unique called "RegisterSlots"
+ // These are dynamic values that use a basic slot system so that
+ // classes can register to listen to specific slots, and the value
+ // will always be grabbed from the slot (and never set in the project
+ // component). This is useful for things like tracking the current
+ // file being processed by a filter (e.g. AppendTask sets an append.current_file
+ // slot, which can be ready by the XSLTParam type.)
+
+ if (count($method->getParameters()) !== 1) {
+ throw new BuildException($method->getDeclaringClass()->getName()."::".$method->getName()."() must take exactly one parameter.");
+ }
+
+ $this->slotListeners[$name] = $method;
+
+ } elseif (strpos($name, "set") === 0) {
+
+ // A standard attribute setter.
+
+ if (count($method->getParameters()) !== 1) {
+ throw new BuildException($method->getDeclaringClass()->getName()."::".$method->getName()."() must take exactly one parameter.");
+ }
+
+ $this->attributeSetters[$name] = $method;
+
+ } elseif (strpos($name, "create") === 0) {
+
+ if (count($method->getParameters()) > 0) {
+ throw new BuildException($method->getDeclaringClass()->getName()."::".$method->getName()."() may not take any parameters.");
+ }
+
+ // Because PHP doesn't support return types, we are going to do
+ // two things here to guess return type:
+ // 1) parse comments for an explicit value
+ // 2) if that fails, assume that the part of the method after "create"
+ // is the name of the return type (in many cases it is not)
+
+ // This isn't super important -- i.e. we're not instantaiting classes
+ // based on this information. It's more just so that IntrospectionHelper
+ // can keep track of all the nested types -- and provide more helpful
+ // exception messages, etc.
+
+ preg_match('/@return[\s]+([\w]+)/', $method->getDocComment(), $matches);
+ if (!empty($matches[1]) && class_exists($matches[1], false)) {
+ $this->nestedTypes[$name] = $matches[1];
+ } else {
+ // assume that method createEquals() creates object of type "Equals"
+ // (that example would be false, of course)
+ $this->nestedTypes[$name] = $this->getPropertyName($name, "create");
+ }
+
+ $this->nestedCreators[$name] = $method;
+
+ } elseif (strpos($name, "addconfigured") === 0) {
+
+ // *must* use class hints if using addConfigured ...
+
+ // 1 param only
+ $params = $method->getParameters();
+
+ if (count($params) < 1) {
+ throw new BuildException($method->getDeclaringClass()->getName()."::".$method->getName()."() must take at least one parameter.");
+ }
+
+ if (count($params) > 1) {
+ $this->warn($method->getDeclaringClass()->getName()."::".$method->getName()."() takes more than one parameter. (IH only uses the first)");
+ }
+
+ $classname = null;
+
+ if (($hint = $params[0]->getClass()) !== null) {
+ $classname = $hint->getName();
+ }
+
+ if ($classname === null) {
+ throw new BuildException($method->getDeclaringClass()->getName()."::".$method->getName()."() method MUST use a class hint to indicate the class type of parameter.");
+ }
+
+ $this->nestedTypes[$name] = $classname;
+
+ $this->nestedStorers[$name] = $method;
+
+ } elseif (strpos($name, "add") === 0) {
+
+ // *must* use class hints if using add ...
+
+ // 1 param only
+ $params = $method->getParameters();
+ if (count($params) < 1) {
+ throw new BuildException($method->getDeclaringClass()->getName()."::".$method->getName()."() must take at least one parameter.");
+ }
+
+ if (count($params) > 1) {
+ $this->warn($method->getDeclaringClass()->getName()."::".$method->getName()."() takes more than one parameter. (IH only uses the first)");
+ }
+
+ $classname = null;
+
+ if (($hint = $params[0]->getClass()) !== null) {
+ $classname = $hint->getName();
+ }
+
+ // we don't use the classname here, but we need to make sure it exists before
+ // we later try to instantiate a non-existant class
+ if ($classname === null) {
+ throw new BuildException($method->getDeclaringClass()->getName()."::".$method->getName()."() method MUST use a class hint to indicate the class type of parameter.");
+ }
+
+ $this->nestedCreators[$name] = $method;
+ }
+ } // if $method->isPublic()
+ } // foreach
+ }
+
+
+ /** Sets the named attribute. */
+ function setAttribute(Project $project, $element, $attributeName, &$value) {
+
+ // we want to check whether the value we are setting looks like
+ // a slot-listener variable: %{task.current_file}
+ //
+ // slot-listener variables are not like properties, in that they cannot be mixed with
+ // other text values. The reason for this disparity is that properties are only
+ // set when first constructing objects from XML, whereas slot-listeners are always dynamic.
+ //
+ // This is made possible by PHP5 (objects automatically passed by reference) and PHP's loose
+ // typing.
+
+ if (StringHelper::isSlotVar($value)) {
+
+ $as = "setlistening" . strtolower($attributeName);
+
+ if (!isset($this->slotListeners[$as])) {
+ $msg = $this->getElementName($project, $element) . " doesn't support a slot-listening '$attributeName' attribute.";
+ throw new BuildException($msg);
+ }
+
+ $method = $this->slotListeners[$as];
+
+ $key = StringHelper::slotVar($value);
+ $value = Register::getSlot($key); // returns a RegisterSlot object which will hold current value of that register (accessible using getValue())
+
+ } else {
+
+ // Traditional value options
+
+ $as = "set".strtolower($attributeName);
+
+ if (!isset($this->attributeSetters[$as])) {
+ $msg = $this->getElementName($project, $element) . " doesn't support the '$attributeName' attribute.";
+ throw new BuildException($msg);
+ }
+
+ $method = $this->attributeSetters[$as];
+
+ if ($as == "setrefid") {
+ $value = new Reference($value);
+ } else {
+
+ // decode any html entities in string
+ $value = html_entity_decode($value);
+
+ // value is a string representation of a boolean type,
+ // convert it to primitive
+ if (StringHelper::isBoolean($value)) {
+
+ $value = StringHelper::booleanValue($value);
+ }
+
+ // does method expect a PhingFile object? if so, then
+ // pass a project-relative file.
+ $params = $method->getParameters();
+
+ $classname = null;
+
+ if (($hint = $params[0]->getClass()) !== null) {
+ $classname = $hint->getName();
+ }
+
+ // there should only be one param; we'll just assume ....
+ if ($classname !== null) {
+ switch(strtolower($classname)) {
+ case "phingfile":
+ $value = $project->resolveFile($value);
+ break;
+ case "path":
+ $value = new Path($project, $value);
+ break;
+ case "reference":
+ $value = new Reference($value);
+ break;
+ // any other object params we want to support should go here ...
+ }
+
+ } // if hint !== null
+
+ } // if not setrefid
+
+ } // if is slot-listener
+
+ try {
+ $project->log(" -calling setter ".$method->getDeclaringClass()->getName()."::".$method->getName()."()", PROJECT_MSG_DEBUG);
+ $method->invoke($element, $value);
+ } catch(Exception $exc) {
+ throw new BuildException($exc);
+ }
+
+ }
+
+ /** Adds PCDATA areas.*/
+ function addText(Project $project, $element, $text) {
+ if ($this->methodAddText === null) {
+ $msg = $this->getElementName($project, $element)." doesn't support nested text data.";
+ throw new BuildException($msg);
+ }
+ try {
+ $method = $this->methodAddText;
+ $method->invoke($element, $text);
+ } catch (Exception $exc) {
+ throw new BuildException($exc);
+ }
+ }
+
+ /**
+ * Creates a named nested element.
+ *
+ * Valid creators can be in the form createFoo() or addFoo(Bar).
+ * @return object Returns the nested element.
+ * @throws BuildException
+ */
+ function createElement(Project $project, $element, $elementName) {
+
+ $addMethod = "add".strtolower($elementName);
+ $createMethod = "create".strtolower($elementName);
+ $nestedElement = null;
+
+ if (isset($this->nestedCreators[$createMethod])) {
+
+ $method = $this->nestedCreators[$createMethod];
+ try { // try to invoke the creator method on object
+ $project->log(" -calling creator ".$method->getDeclaringClass()->getName()."::".$method->getName()."()", PROJECT_MSG_DEBUG);
+ $nestedElement = $method->invoke($element);
+ } catch (Exception $exc) {
+ throw new BuildException($exc);
+ }
+
+ } elseif (isset($this->nestedCreators[$addMethod])) {
+
+ $method = $this->nestedCreators[$addMethod];
+
+ // project components must use class hints to support the add methods
+
+ try { // try to invoke the adder method on object
+
+ $project->log(" -calling adder ".$method->getDeclaringClass()->getName()."::".$method->getName()."()", PROJECT_MSG_DEBUG);
+ // we've already assured that correct num of params
+ // exist and that method is using class hints
+ $params = $method->getParameters();
+
+ $classname = null;
+
+ if (($hint = $params[0]->getClass()) !== null) {
+ $classname = $hint->getName();
+ }
+
+ // create a new instance of the object and add it via $addMethod
+ $nestedElement = new $classname();
+
+ $method->invoke($element, $nestedElement);
+
+ } catch (Exception $exc) {
+ throw new BuildException($exc);
+ }
+ } else {
+ $msg = $this->getElementName($project, $element) . " doesn't support the '$elementName' creator/adder.";
+ throw new BuildException($msg);
+ }
+
+ if ($nestedElement instanceof ProjectComponent) {
+ $nestedElement->setProject($project);
+ }
+
+ return $nestedElement;
+ }
+
+ /**
+ * Creates a named nested element.
+ * @return void
+ * @throws BuildException
+ */
+ function storeElement($project, $element, $child, $elementName = null) {
+
+ if ($elementName === null) {
+ return;
+ }
+
+ $storer = "addconfigured".strtolower($elementName);
+
+ if (isset($this->nestedStorers[$storer])) {
+
+ $method = $this->nestedStorers[$storer];
+
+ try {
+ $project->log(" -calling storer ".$method->getDeclaringClass()->getName()."::".$method->getName()."()", PROJECT_MSG_DEBUG);
+ $method->invoke($element, $child);
+ } catch (Exception $exc) {
+ throw new BuildException($exc);
+ }
+ }
+
+ }
+
+ /** Does the introspected class support PCDATA? */
+ function supportsCharacters() {
+ return ($this->methodAddText !== null);
+ }
+
+ /** Return all attribues supported by the introspected class. */
+ function getAttributes() {
+ $attribs = array();
+ foreach (array_keys($this->attributeSetters) as $setter) {
+ $attribs[] =$this->getPropertyName($setter, "set");
+ }
+ return $attribs;
+ }
+
+ /** Return all nested elements supported by the introspected class. */
+ function getNestedElements() {
+ return $this->nestedTypes;
+ }
+
+ /**
+ * Get the the name for an element.
+ * When possible the full classnam (phing.tasks.system.PropertyTask) will
+ * be returned. If not available (loaded in taskdefs or typedefs) then the
+ * XML element name will be returned.
+ *
+ * @param Project $project
+ * @param object $element The Task or type element.
+ * @return string Fully qualified class name of element when possible.
+ */
+ function getElementName(Project $project, $element) {
+
+ $taskdefs = $project->getTaskDefinitions();
+ $typedefs = $project->getDataTypeDefinitions();
+
+ // check if class of element is registered with project (tasks & types)
+ // most element types don't have a getTag() method
+ $elClass = get_class($element);
+
+ if (!in_array('getTag', get_class_methods($elClass))) {
+ // loop through taskdefs and typesdefs and see if the class name
+ // matches (case-insensitive) any of the classes in there
+ foreach(array_merge($taskdefs, $typedefs) as $elName => $class) {
+ if (0 === strcasecmp($elClass, StringHelper::unqualify($class))) {
+ return $class;
+ }
+ }
+ return "$elClass (unknown)";
+ } else {
+ // ->getTag() method does exist, so use it
+ $elName = $element->getTag();
+ if (isset($taskdefs[$elName])) {
+ return $taskdefs[$elName];
+ } elseif (isset($typedefs[$elName])) {
+
+ return $typedefs[$elName];
+ } else {
+ return "$elName (unknown)";
+ }
+ }
+ }
+
+ /** extract the name of a property from a method name - subtracting a given prefix. */
+ function getPropertyName($methodName, $prefix) {
+ $start = strlen($prefix);
+ return strtolower(substr($methodName, $start));
+ }
+
+ /**
+ * Prints warning message to screen if -debug was used.
+ */
+ function warn($msg) {
+ if (Phing::getMsgOutputLevel() === PROJECT_MSG_DEBUG) {
+ print("[IntrospectionHelper] " . $msg . "\n");
+ }
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/Phing.php b/buildscripts/phing/classes/phing/Phing.php
new file mode 100644
index 00000000..bb8d67f6
--- /dev/null
+++ b/buildscripts/phing/classes/phing/Phing.php
@@ -0,0 +1,1161 @@
+<?php
+/*
+ * $Id: Phing.php,v 1.51 2006/01/06 15:12:33 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Project.php';
+require_once 'phing/ProjectComponent.php';
+require_once 'phing/Target.php';
+require_once 'phing/Task.php';
+
+include_once 'phing/BuildException.php';
+include_once 'phing/BuildEvent.php';
+
+include_once 'phing/parser/Location.php';
+include_once 'phing/parser/ExpatParser.php';
+include_once 'phing/parser/AbstractHandler.php';
+include_once 'phing/parser/ProjectConfigurator.php';
+include_once 'phing/parser/RootHandler.php';
+include_once 'phing/parser/ProjectHandler.php';
+include_once 'phing/parser/TaskHandler.php';
+include_once 'phing/parser/TargetHandler.php';
+include_once 'phing/parser/DataTypeHandler.php';
+include_once 'phing/parser/NestedElementHandler.php';
+
+include_once 'phing/system/util/Properties.php';
+include_once 'phing/util/StringHelper.php';
+include_once 'phing/system/io/PhingFile.php';
+include_once 'phing/system/io/FileReader.php';
+include_once 'phing/system/util/Register.php';
+
+/**
+ * Entry point into Phing. This class handles the full lifecycle of a build -- from
+ * parsing & handling commandline arguments to assembling the project to shutting down
+ * and cleaning up in the end.
+ *
+ * If you are invoking Phing from an external application, this is still
+ * the class to use. Your applicaiton can invoke the start() method, passing
+ * any commandline arguments or additional properties.
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.51 $
+ * @package phing
+ */
+class Phing {
+
+ /** The default build file name */
+ const DEFAULT_BUILD_FILENAME = "build.xml";
+
+ /** Our current message output status. Follows PROJECT_MSG_XXX */
+ private static $msgOutputLevel = PROJECT_MSG_INFO;
+
+ /** PhingFile that we are using for configuration */
+ private $buildFile = null;
+
+ /** The build targets */
+ private $targets = array();
+
+ /**
+ * Set of properties that are passed in from commandline or invoking code.
+ * @var Properties
+ */
+ private static $definedProps;
+
+ /** Names of classes to add as listeners to project */
+ private $listeners = array();
+
+ private $loggerClassname = null;
+
+ /** The class to handle input (can be only one). */
+ private $inputHandlerClassname;
+
+ /** Indicates if this phing should be run */
+ private $readyToRun = false;
+
+ /** Indicates we should only parse and display the project help information */
+ private $projectHelp = false;
+
+ /** Used by utility function getResourcePath() */
+ private static $importPaths;
+
+ /** System-wide static properties (moved from System) */
+ private static $properties = array();
+
+ /** Static system timer. */
+ private static $timer;
+
+ /** The current Project */
+ private static $currentProject;
+
+ /** Whether to capture PHP errors to buffer. */
+ private static $phpErrorCapture = false;
+
+ /** Array of captured PHP errors */
+ private static $capturedPhpErrors = array();
+
+ /**
+ * Prints the message of the Exception if it's not null.
+ */
+ function printMessage(Exception $t) {
+ print($t->getMessage() . "\n");
+ if (self::getMsgOutputLevel() === PROJECT_MSG_DEBUG) {
+ print($t->getTraceAsString()."\n");
+ if ($t instanceof Exception) {
+ $c = $t->getCause();
+ if ($c !== null) {
+ print("Wrapped exception trace:\n");
+ print($c->getTraceAsString() . "\n");
+ }
+ }
+ } // if output level is DEBUG
+ }
+
+ /**
+ * Entry point allowing for more options from other front ends.
+ *
+ * This method encapsulates the complete build lifecycle.
+ *
+ * @param array &$args The commandline args passed to phing shell script.
+ * @param array $additionalUserProperties Any additional properties to be passed to Phing (alternative front-end might implement this).
+ * These additional properties will be available using the getDefinedProperty() method and will
+ * be added to the project's "user" properties.
+ * @return void
+ * @see execute()
+ * @see runBuild()
+ */
+ public static function start(&$args, $additionalUserProperties = null) {
+
+ try {
+ $m = new Phing();
+ $m->execute($args);
+ } catch (Exception $exc) {
+ $m->printMessage($exc);
+ self::halt(-1); // Parameter error
+ }
+
+ if ($additionalUserProperties !== null) {
+ $keys = $m->additionalUserProperties->keys();
+ while(count($keys)) {
+ $key = array_shift($keys);
+ $property = $m->additionalUserProperties->getProperty($key);
+ $m->setDefinedProperty($key, $property);
+ }
+ }
+
+ try {
+ $m->runBuild();
+ } catch(Exception $exc) {
+ self::halt(1); // Errors occured
+ }
+
+ // everything fine, shutdown
+ self::halt(0); // no errors, everything is cake
+ }
+
+ /**
+ * Making output level a static property so that this property
+ * can be accessed by other parts of the system, enabling
+ * us to display more information -- e.g. backtraces -- for "debug" level.
+ * @return int
+ */
+ public static function getMsgOutputLevel() {
+ return self::$msgOutputLevel;
+ }
+
+ /**
+ * Command line entry point. This method kicks off the building
+ * of a project object and executes a build using either a given
+ * target or the default target.
+ *
+ * @param array $args Command line args.
+ * @return void
+ */
+ public static function fire($args) {
+ self::start($args, null);
+ }
+
+ /**
+ * Setup/initialize Phing environment from commandline args.
+ * @param array $args commandline args passed to phing shell.
+ * @return void
+ */
+ public function execute($args) {
+
+ self::$definedProps = new Properties();
+ $this->searchForThis = null;
+
+ // cycle through given args
+ for ($i = 0, $argcount = count($args); $i < $argcount; ++$i) {
+ // ++$i intentional here, as first param is script name
+ $arg = $args[$i];
+
+ if ($arg == "-help" || $arg == "-h") {
+ $this->printUsage();
+ return;
+ } elseif ($arg == "-version" || $arg == "-v") {
+ $this->printVersion();
+ return;
+ } elseif ($arg == "-quiet" || $arg == "-q") {
+ self::$msgOutputLevel = PROJECT_MSG_WARN;
+ } elseif ($arg == "-verbose") {
+ $this->printVersion();
+ self::$msgOutputLevel = PROJECT_MSG_VERBOSE;
+ } elseif ($arg == "-debug") {
+ $this->printVersion();
+ self::$msgOutputLevel = PROJECT_MSG_DEBUG;
+ } elseif ($arg == "-logfile") {
+ try { // try to set logfile
+ if (!isset($args[$i+1])) {
+ print("You must specify a log file when using the -logfile argument\n");
+ return;
+ } else {
+ $logFile = new PhingFile($args[++$i]);
+ $this->loggerClassname = 'phing.listener.PearLogger';
+ $this->setDefinedProperty('pear.log.name', $logFile->getAbsolutePath());
+ }
+ } catch (IOException $ioe) {
+ print("Cannot write on the specified log file. Make sure the path exists and you have write permissions.\n");
+ throw $ioe;
+ }
+ } elseif ($arg == "-buildfile" || $arg == "-file" || $arg == "-f") {
+ if (!isset($args[$i+1])) {
+ print("You must specify a buildfile when using the -buildfile argument\n");
+ return;
+ } else {
+ $this->buildFile = new PhingFile($args[++$i]);
+ }
+ } elseif ($arg == "-listener") {
+ if (!isset($args[$i+1])) {
+ print("You must specify a listener class when using the -listener argument\n");
+ return;
+ } else {
+ $this->listeners[] = $args[++$i];
+ }
+
+ } elseif (StringHelper::startsWith("-D", $arg)) {
+ $name = substr($arg, 2);
+ $value = null;
+ $posEq = strpos($name, "=");
+ if ($posEq !== false) {
+ $value = substr($name, $posEq+1);
+ $name = substr($name, 0, $posEq);
+ } elseif ($i < count($args)-1) {
+ $value = $args[++$i];
+ }
+ self::$definedProps->setProperty($name, $value);
+ } elseif ($arg == "-logger") {
+ if (!isset($args[$i+1])) {
+ print("You must specify a classname when using the -logger argument\n");
+ return;
+ } else {
+ $this->loggerClassname = $args[++$i];
+ }
+ } elseif ($arg == "-inputhandler") {
+ if ($this->inputHandlerClassname !== null) {
+ throw new BuildException("Only one input handler class may be specified.");
+ }
+ if (!isset($args[$i+1])) {
+ print("You must specify a classname when using the -inputhandler argument\n");
+ return;
+ } else {
+ $this->inputHandlerClassname = $args[++$i];
+ }
+ } elseif ($arg == "-projecthelp" || $arg == "-targets" || $arg == "-list" || $arg == "-l") {
+ // set the flag to display the targets and quit
+ $this->projectHelp = true;
+ } elseif ($arg == "-find") {
+ // eat up next arg if present, default to build.xml
+ if ($i < count($args)-1) {
+ $this->searchForThis = $args[++$i];
+ } else {
+ $this->searchForThis = self::DEFAULT_BUILD_FILENAME;
+ }
+ } elseif (substr($arg,0,1) == "-") {
+ // we don't have any more args
+ print("Unknown argument: $arg\n");
+ $this->printUsage();
+ return;
+ } else {
+ // if it's no other arg, it may be the target
+ array_push($this->targets, $arg);
+ }
+ }
+
+ // if buildFile was not specified on the command line,
+ if ($this->buildFile === null) {
+ // but -find then search for it
+ if ($this->searchForThis !== null) {
+ $this->buildFile = $this->_findBuildFile(self::getProperty("user.dir"), $this->searchForThis);
+ } else {
+ $this->buildFile = new PhingFile(self::DEFAULT_BUILD_FILENAME);
+ }
+ }
+ // make sure buildfile exists
+ if (!$this->buildFile->exists()) {
+ throw new BuildException("Buildfile: " . $this->buildFile->__toString() . " does not exist!");
+ }
+
+ // make sure it's not a directory
+ if ($this->buildFile->isDirectory()) {
+ throw new BuildException("Buildfile: " . $this->buildFile->__toString() . " is a dir!");
+ }
+
+ $this->readyToRun = true;
+ }
+
+ /**
+ * Helper to get the parent file for a given file.
+ *
+ * @param PhingFile $file
+ * @return PhingFile Parent file or null if none
+ */
+ function _getParentFile(PhingFile $file) {
+ $filename = $file->getAbsolutePath();
+ $file = new PhingFile($filename);
+ $filename = $file->getParent();
+
+ if ($filename !== null && self::$msgOutputLevel >= PROJECT_MSG_VERBOSE) {
+ print("Searching in $filename\n");
+ }
+
+ return ($filename === null) ? null : new PhingFile($filename);
+ }
+
+ /**
+ * Search parent directories for the build file.
+ *
+ * Takes the given target as a suffix to append to each
+ * parent directory in search of a build file. Once the
+ * root of the file-system has been reached an exception
+ * is thrown.
+ *
+ * @param string $start Start file path.
+ * @param string $suffix Suffix filename to look for in parents.
+ * @return PhingFile A handle to the build file
+ *
+ * @throws BuildException Failed to locate a build file
+ */
+ function _findBuildFile($start, $suffix) {
+ if (self::$msgOutputLevel >= PROJECT_MSG_INFO) {
+ print("Searching for $suffix ...\n");
+ }
+ $startf = new PhingFile($start);
+ $parent = new PhingFile($startf->getAbsolutePath());
+ $file = new PhingFile($parent, $suffix);
+
+ // check if the target file exists in the current directory
+ while (!$file->exists()) {
+ // change to parent directory
+ $parent = $this->_getParentFile($parent);
+
+ // if parent is null, then we are at the root of the fs,
+ // complain that we can't find the build file.
+ if ($parent === null) {
+ throw new BuildException("Could not locate a build file!");
+ }
+ // refresh our file handle
+ $file = new PhingFile($parent, $suffix);
+ }
+ return $file;
+ }
+
+ /**
+ * Executes the build.
+ * @return void
+ */
+ function runBuild() {
+
+ if (!$this->readyToRun) {
+ return;
+ }
+
+ $project = new Project();
+
+ self::setCurrentProject($project);
+ set_error_handler(array('Phing', 'handlePhpError'));
+
+ $error = null;
+
+ $this->addBuildListeners($project);
+ $this->addInputHandler($project);
+
+ // set this right away, so that it can be used in logging.
+ $project->setUserProperty("phing.file", $this->buildFile->getAbsolutePath());
+
+ try {
+ $project->fireBuildStarted();
+ $project->init();
+ } catch (Exception $exc) {
+ $project->fireBuildFinished($exc);
+ throw $exc;
+ }
+
+ $project->setUserProperty("phing.version", $this->getPhingVersion());
+
+ $e = self::$definedProps->keys();
+ while (count($e)) {
+ $arg = (string) array_shift($e);
+ $value = (string) self::$definedProps->getProperty($arg);
+ $project->setUserProperty($arg, $value);
+ }
+ unset($e);
+
+ $project->setUserProperty("phing.file", $this->buildFile->getAbsolutePath());
+
+ // first use the Configurator to create the project object
+ // from the given build file.
+
+ try {
+ ProjectConfigurator::configureProject($project, $this->buildFile);
+ } catch (Exception $exc) {
+ $project->fireBuildFinished($exc);
+ restore_error_handler();
+ self::unsetCurrentProject();
+ throw $exc;
+ }
+
+ // make sure that we have a target to execute
+ if (count($this->targets) === 0) {
+ $this->targets[] = $project->getDefaultTarget();
+ }
+
+ // execute targets if help param was not given
+ if (!$this->projectHelp) {
+
+ try {
+ $project->executeTargets($this->targets);
+ } catch (Exception $exc) {
+ $project->fireBuildFinished($exc);
+ restore_error_handler();
+ self::unsetCurrentProject();
+ throw $exc;
+ }
+ }
+ // if help is requested print it
+ if ($this->projectHelp) {
+ try {
+ $this->printDescription($project);
+ $this->printTargets($project);
+ } catch (Exception $exc) {
+ $project->fireBuildFinished($exc);
+ restore_error_handler();
+ self::unsetCurrentProject();
+ throw $exc;
+ }
+ }
+
+ // finally {
+ if (!$this->projectHelp) {
+ $project->fireBuildFinished(null);
+ }
+
+ restore_error_handler();
+ self::unsetCurrentProject();
+ }
+
+ /**
+ * Bind any default build listeners to this project.
+ * Currently this means adding the logger.
+ * @param Project $project
+ * @return void
+ */
+ private function addBuildListeners(Project $project) {
+ // Add the default listener
+ $project->addBuildListener($this->createLogger());
+ }
+
+ /**
+ * Creates the InputHandler and adds it to the project.
+ *
+ * @param Project $project the project instance.
+ *
+ * @throws BuildException if a specified InputHandler
+ * class could not be loaded.
+ */
+ private function addInputHandler(Project $project) {
+ if ($this->inputHandlerClassname === null) {
+ $handler = new DefaultInputHandler();
+ } else {
+ try {
+ $clz = Phing::import($this->inputHandlerClassname);
+ $handler = new $clz();
+ if ($project !== null && method_exists($handler, 'setProject')) {
+ $handler->setProject($project);
+ }
+ } catch (Exception $e) {
+ $msg = "Unable to instantiate specified input handler "
+ . "class " . $this->inputHandlerClassname . " : "
+ . $e->getMessage();
+ throw new BuildException($msg);
+ }
+ }
+ $project->setInputHandler($handler);
+ }
+
+ /**
+ * Creates the default build logger for sending build events to the log.
+ * @return BuildListener The created Logger
+ */
+ private function createLogger() {
+ if ($this->loggerClassname !== null) {
+ self::import($this->loggerClassname);
+ // get class name part
+ $classname = self::import($this->loggerClassname);
+ $logger = new $classname;
+ } else {
+ require_once 'phing/listener/DefaultLogger.php';
+ $logger = new DefaultLogger();
+ }
+ $logger->setMessageOutputLevel(self::$msgOutputLevel);
+ return $logger;
+ }
+
+ /**
+ * Sets the current Project
+ * @param Project $p
+ */
+ public static function setCurrentProject($p) {
+ self::$currentProject = $p;
+ }
+
+ /**
+ * Unsets the current Project
+ */
+ public static function unsetCurrentProject() {
+ self::$currentProject = null;
+ }
+
+ /**
+ * Gets the current Project.
+ * @return Project Current Project or NULL if none is set yet/still.
+ */
+ public static function getCurrentProject() {
+ return self::$currentProject;
+ }
+
+ /**
+ * A static convenience method to send a log to the current (last-setup) Project.
+ * If there is no currently-configured Project, then this will do nothing.
+ * @param string $message
+ * @param int $priority PROJECT_MSG_INFO, etc.
+ */
+ public static function log($message, $priority = PROJECT_MSG_INFO) {
+ $p = self::getCurrentProject();
+ if ($p) {
+ $p->log($message, $priority);
+ }
+ }
+
+ /**
+ * Error handler for PHP errors encountered during the build.
+ * This uses the logging for the currently configured project.
+ */
+ public static function handlePhpError($level, $message, $file, $line) {
+
+ // don't want to print supressed errors
+ if (error_reporting() > 0) {
+
+ if (self::$phpErrorCapture) {
+
+ self::$capturedPhpErrors[] = array('message' => $message, 'level' => $level, 'line' => $line, 'file' => $file);
+
+ } else {
+
+ $message = '[PHP Error] ' . $message;
+ $message .= ' [line ' . $line . ' of ' . $file . ']';
+
+ switch ($level) {
+
+ case E_STRICT:
+ case E_NOTICE:
+ case E_USER_NOTICE:
+ self::log($message, PROJECT_MSG_VERBOSE);
+ break;
+ case E_WARNING:
+ case E_USER_WARNING:
+ self::log($message, PROJECT_MSG_WARN);
+ break;
+ case E_ERROR:
+ case E_USER_ERROR:
+ default:
+ self::log($message, PROJECT_MSG_ERR);
+
+ } // switch
+
+ } // if phpErrorCapture
+
+ } // if not @
+
+ }
+
+ /**
+ * Begins capturing PHP errors to a buffer.
+ * While errors are being captured, they are not logged.
+ */
+ public static function startPhpErrorCapture() {
+ self::$phpErrorCapture = true;
+ self::$capturedPhpErrors = array();
+ }
+
+ /**
+ * Stops capturing PHP errors to a buffer.
+ * The errors will once again be logged after calling this method.
+ */
+ public static function stopPhpErrorCapture() {
+ self::$phpErrorCapture = false;
+ }
+
+ /**
+ * Clears the captured errors without affecting the starting/stopping of the capture.
+ */
+ public static function clearCapturedPhpErrors() {
+ self::$capturedPhpErrors = array();
+ }
+
+ /**
+ * Gets any PHP errors that were captured to buffer.
+ * @return array array('message' => message, 'line' => line number, 'file' => file name, 'level' => error level)
+ */
+ public static function getCapturedPhpErrors() {
+ return self::$capturedPhpErrors;
+ }
+
+ /** Prints the usage of how to use this class */
+ function printUsage() {
+ $lSep = self::getProperty("line.separator");
+ $msg = "";
+ $msg .= "phing [options] [target [target2 [target3] ...]]" . $lSep;
+ $msg .= "Options: " . $lSep;
+ $msg .= " -h -help print this message" . $lSep;
+ $msg .= " -l -list list available targets in this project" . $lSep;
+ $msg .= " -v -version print the version information and exit" . $lSep;
+ $msg .= " -q -quiet be extra quiet" . $lSep;
+ $msg .= " -verbose be extra verbose" . $lSep;
+ $msg .= " -debug print debugging information" . $lSep;
+ $msg .= " -logfile <file> use given file for log" . $lSep;
+ $msg .= " -logger <classname> the class which is to perform logging" . $lSep;
+ $msg .= " -f -buildfile <file> use given buildfile" . $lSep;
+ $msg .= " -D<property>=<value> use value for given property" . $lSep;
+ $msg .= " -find <file> search for buildfile towards the root of the" . $lSep;
+ $msg .= " filesystem and use it" . $lSep;
+ //$msg .= " -recursive <file> search for buildfile downwards and use it" . $lSep;
+ $msg .= $lSep;
+ $msg .= "Report bugs to <dev@phing.tigris.org>".$lSep;
+ print($msg);
+ }
+
+ function printVersion() {
+ print(self::getPhingVersion()."\n");
+ }
+
+ function getPhingVersion() {
+ $versionPath = self::getResourcePath("phing/etc/VERSION.TXT");
+ if ($versionPath === null) {
+ $versionPath = self::getResourcePath("etc/VERSION.TXT");
+ }
+ try { // try to read file
+ $buffer = null;
+ $file = new PhingFile($versionPath);
+ $reader = new FileReader($file);
+ $reader->readInto($buffer);
+ $buffer = trim($buffer);
+ //$buffer = "PHING version 1.0, Released 2002-??-??";
+ $phingVersion = $buffer;
+ } catch (IOException $iox) {
+ print("Can't read version information file\n");
+ throw new BuildException("Build failed");
+ }
+ return $phingVersion;
+ }
+
+ /** Print the project description, if any */
+ function printDescription(Project $project) {
+ if ($project->getDescription() !== null) {
+ print($project->getDescription()."\n");
+ }
+ }
+
+ /** Print out a list of all targets in the current buildfile */
+ function printTargets($project) {
+ // find the target with the longest name
+ $maxLength = 0;
+ $targets = $project->getTargets();
+ $targetNames = array_keys($targets);
+ $targetName = null;
+ $targetDescription = null;
+ $currentTarget = null;
+
+ // split the targets in top-level and sub-targets depending
+ // on the presence of a description
+
+ $subNames = array();
+ $topNameDescMap = array();
+
+ foreach($targets as $currentTarget) {
+ $targetName = $currentTarget->getName();
+ $targetDescription = $currentTarget->getDescription();
+
+ // subtargets are targets w/o descriptions
+ if ($targetDescription === null) {
+ $subNames[] = $targetName;
+ } else {
+ // topNames and topDescriptions are handled later
+ // here we store in hash map (for sorting purposes)
+ $topNameDescMap[$targetName] = $targetDescription;
+ if (strlen($targetName) > $maxLength) {
+ $maxLength = strlen($targetName);
+ }
+ }
+ }
+
+ // Sort the arrays
+ sort($subNames); // sort array values, resetting keys (which are numeric)
+ ksort($topNameDescMap); // sort the keys (targetName) keeping key=>val associations
+
+ $topNames = array_keys($topNameDescMap);
+ $topDescriptions = array_values($topNameDescMap);
+
+ $defaultTarget = $project->getDefaultTarget();
+
+ if ($defaultTarget !== null && $defaultTarget !== "") {
+ $defaultName = array();
+ $defaultDesc = array();
+ $defaultName[] = $defaultTarget;
+
+ $indexOfDefDesc = array_search($defaultTarget, $topNames, true);
+ if ($indexOfDefDesc !== false && $indexOfDefDesc >= 0) {
+ $defaultDesc = array();
+ $defaultDesc[] = $topDescriptions[$indexOfDefDesc];
+ }
+
+ $this->_printTargets($defaultName, $defaultDesc, "Default target:", $maxLength);
+
+ }
+ $this->_printTargets($topNames, $topDescriptions, "Main targets:", $maxLength);
+ $this->_printTargets($subNames, null, "Subtargets:", 0);
+ }
+
+ /**
+ * Writes a formatted list of target names with an optional description.
+ *
+ * @param array $names The names to be printed.
+ * Must not be <code>null</code>.
+ * @param array $descriptions The associated target descriptions.
+ * May be <code>null</code>, in which case
+ * no descriptions are displayed.
+ * If non-<code>null</code>, this should have
+ * as many elements as <code>names</code>.
+ * @param string $heading The heading to display.
+ * Should not be <code>null</code>.
+ * @param int $maxlen The maximum length of the names of the targets.
+ * If descriptions are given, they are padded to this
+ * position so they line up (so long as the names really
+ * <i>are</i> shorter than this).
+ */
+ private function _printTargets($names, $descriptions, $heading, $maxlen) {
+ $lSep = self::getProperty("line.separator");
+ $spaces = ' ';
+ while (strlen($spaces) < $maxlen) {
+ $spaces .= $spaces;
+ }
+ $msg = "";
+ $msg .= $heading . $lSep;
+ $msg .= str_repeat("-",79) . $lSep;
+
+ $total = count($names);
+ for($i=0; $i < $total; $i++) {
+ $msg .= " ";
+ $msg .= $names[$i];
+ if (!empty($descriptions)) {
+ $msg .= substr($spaces, 0, $maxlen - strlen($names[$i]) + 2);
+ $msg .= $descriptions[$i];
+ }
+ $msg .= $lSep;
+ }
+ if ($total > 0) {
+ print $msg . $lSep;
+ }
+ }
+
+ /**
+ * Import a dot-path notation class path.
+ * @param string $dotPath
+ * @param mixed $classpath String or object supporting __toString()
+ * @return string The unqualified classname (which can be instantiated).
+ * @throws BuildException - if cannot find the specified file
+ */
+ public static function import($dotPath, $classpath = null) {
+
+ // first check to see that the class specified hasn't already been included.
+ // (this also handles case where this method is called w/ a classname rather than dotpath)
+ $classname = StringHelper::unqualify($dotPath);
+ if (class_exists($classname, false)) {
+ return $classname;
+ }
+
+ $dotClassname = basename($dotPath);
+ $dotClassnamePos = strlen($dotPath) - strlen($dotClassname);
+ $classFile = strtr($dotClassname, '.', DIRECTORY_SEPARATOR) . ".php";
+ $path = substr_replace($dotPath, $classFile, $dotClassnamePos);
+
+ Phing::__import($path, $classpath);
+
+ return $classname;
+ }
+
+ /**
+ * Import a PHP file
+ * @param string $path Path to the PHP file
+ * @param mixed $classpath String or object supporting __toString()
+ * @throws BuildException - if cannot find the specified file
+ */
+ public static function __import($path, $classpath = null) {
+
+ if ($classpath) {
+
+ // Apparently casting to (string) no longer invokes __toString() automatically.
+ if (is_object($classpath)) {
+ $classpath = $classpath->__toString();
+ }
+
+ // classpaths are currently additive, but we also don't want to just
+ // indiscriminantly prepand/append stuff to the include_path. This means
+ // we need to parse current incldue_path, and prepend any
+ // specified classpath locations that are not already in the include_path.
+ //
+ // NOTE: the reason why we do it this way instead of just changing include_path
+ // and then changing it back, is that in many cases applications (e.g. Propel) will
+ // include/require class files from within method calls. This means that not all
+ // necessary files will be included in this import() call, and hence we can't
+ // change the include_path back without breaking those apps. While this method could
+ // be more expensive than switching & switching back (not sure, but maybe), it makes it
+ // possible to write far less expensive run-time applications (e.g. using Propel), which is
+ // really where speed matters more.
+
+ $curr_parts = explode(PATH_SEPARATOR, ini_get('include_path'));
+ $add_parts = explode(PATH_SEPARATOR, $classpath);
+ $new_parts = array_diff($add_parts, $curr_parts);
+ if ($new_parts) {
+ if (self::getMsgOutputLevel() === PROJECT_MSG_DEBUG) {
+ print("Phing::import() prepending new include_path components: " . implode(PATH_SEPARATOR, $new_parts) . "\n");
+ }
+ ini_set('include_path', implode(PATH_SEPARATOR, array_merge($new_parts, $curr_parts)));
+ }
+ }
+
+ $ret = include_once($path);
+
+ if ($ret === false) {
+ $e = new BuildException("Error importing $path");
+ if (self::getMsgOutputLevel() === PROJECT_MSG_DEBUG) {
+ // We can't log this because listeners belong
+ // to projects. We'll just print it -- of course
+ // that isn't very compatible w/ other frontends (but
+ // there aren't any right now, so I'm not stressing)
+ print("Error importing $path\n");
+ print($e->getTraceAsString()."\n");
+ }
+ throw $e;
+ }
+
+ return;
+ }
+
+ /**
+ * Looks on include path for specified file.
+ * @return string File found (null if no file found).
+ */
+ public static function getResourcePath($path) {
+
+ if (self::$importPaths === null) {
+ $paths = ini_get("include_path");
+ self::$importPaths = explode(PATH_SEPARATOR, ini_get("include_path"));
+ }
+
+ $path = str_replace('\\', DIRECTORY_SEPARATOR, $path);
+ $path = str_replace('/', DIRECTORY_SEPARATOR, $path);
+
+ foreach (self::$importPaths as $prefix) {
+ $foo_path = $prefix . DIRECTORY_SEPARATOR . $path;
+ if (file_exists($foo_path)) {
+ return $foo_path;
+ }
+ }
+
+ // Check for the property phing.home
+ $home_dir = self::getProperty('phing.home');
+
+ if ($home_dir)
+ {
+ $home_path = $home_dir . DIRECTORY_SEPARATOR . $path;
+
+ if (file_exists($home_path))
+ {
+ return $home_path;
+ }
+ }
+
+ // If we are using this via PEAR then check for the file in the data dir
+ // This is a bit of a hack, but works better than previous solution of assuming
+ // data_dir is on the include_path.
+ $data_dir = '@DATA-DIR@';
+ if ($data_dir{0} != '@') { // if we're using PEAR then the @ DATA-DIR @ token will have been substituted.
+ $data_path = $data_dir . DIRECTORY_SEPARATOR . $path;
+ if (file_exists($data_path)) {
+ return $data_path;
+ }
+ }
+
+ return null;
+ }
+
+ // -------------------------------------------------------------------------------------------
+ // System-wide methods (moved from System class, which had namespace conflicts w/ PEAR System)
+ // -------------------------------------------------------------------------------------------
+
+ /**
+ * Set System constants which can be retrieved by calling Phing::getProperty($propName).
+ * @return void
+ */
+ private static function setSystemConstants() {
+
+ /*
+ * PHP_OS returns on
+ * WindowsNT4.0sp6 => WINNT
+ * Windows2000 => WINNT
+ * Windows ME => WIN32
+ * Windows 98SE => WIN32
+ * FreeBSD 4.5p7 => FreeBSD
+ * Redhat Linux => Linux
+ * Mac OS X => Darwin
+ */
+ self::setProperty('host.os', PHP_OS);
+
+ // this is used by some tasks too
+ self::setProperty('os.name', PHP_OS);
+
+ // it's still possible this won't be defined,
+ // e.g. if Phing is being included in another app w/o
+ // using the phing.php script.
+ if (!defined('PHP_CLASSPATH')) {
+ define('PHP_CLASSPATH', get_include_path());
+ }
+
+ self::setProperty('php.classpath', PHP_CLASSPATH);
+
+ // try to determine the host filesystem and set system property
+ // used by Fileself::getFileSystem to instantiate the correct
+ // abstraction layer
+
+ switch (strtoupper(PHP_OS)) {
+ case 'WINNT':
+ self::setProperty('host.fstype', 'WINNT');
+ break;
+ case 'WIN32':
+ self::setProperty('host.fstype', 'WIN32');
+ break;
+ default:
+ self::setProperty('host.fstype', 'UNIX');
+ break;
+ }
+
+ self::setProperty('php.version', PHP_VERSION);
+ self::setProperty('user.home', getenv('HOME'));
+ self::setProperty('application.startdir', getcwd());
+ self::setProperty('line.separator', "\n");
+
+ // try to detect machine dependent information
+ $sysInfo = array();
+ if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN' && function_exists("posix_uname")) {
+ $sysInfo = posix_uname();
+ } else {
+ $sysInfo['nodename'] = php_uname('n');
+ $sysInfo['machine']= php_uname('m') ;
+ //this is a not so ideal substition, but maybe better than nothing
+ $sysInfo['domain'] = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : "unknown";
+ $sysInfo['release'] = php_uname('r');
+ $sysInfo['version'] = php_uname('v');
+ }
+
+
+ self::setProperty("host.name", isset($sysInfo['nodename']) ? $sysInfo['nodename'] : "unknown");
+ self::setProperty("host.arch", isset($sysInfo['machine']) ? $sysInfo['machine'] : "unknown");
+ self::setProperty("host.domain",isset($sysInfo['domain']) ? $sysInfo['domain'] : "unknown");
+ self::setProperty("host.os.release", isset($sysInfo['release']) ? $sysInfo['release'] : "unknown");
+ self::setProperty("host.os.version", isset($sysInfo['version']) ? $sysInfo['version'] : "unknown");
+ unset($sysInfo);
+ }
+
+ /**
+ * This gets a property that was set via command line or otherwise passed into Phing.
+ * "Defined" in this case means "externally defined". The reason this method exists is to
+ * provide a public means of accessing commandline properties for (e.g.) logger or listener
+ * scripts. E.g. to specify which logfile to use, PearLogger needs to be able to access
+ * the pear.log.name property.
+ *
+ * @param string $name
+ * @return string value of found property (or null, if none found).
+ */
+ public static function getDefinedProperty($name) {
+ return self::$definedProps->getProperty($name);
+ }
+
+ /**
+ * This sets a property that was set via command line or otherwise passed into Phing.
+ *
+ * @param string $name
+ * @return string value of found property (or null, if none found).
+ */
+ public static function setDefinedProperty($name, $value) {
+ return self::$definedProps->setProperty($name, $value);
+ }
+
+ /**
+ * Returns property value for a System property.
+ * System properties are "global" properties like line.separator,
+ * and user.dir. Many of these correspond to similar properties in Java
+ * or Ant.
+ *
+ * @param string $paramName
+ * @return string Value of found property (or null, if none found).
+ */
+ public static function getProperty($propName) {
+
+ // some properties are detemined on each access
+ // some are cached, see below
+
+ // default is the cached value:
+ $val = isset(self::$properties[$propName]) ? self::$properties[$propName] : null;
+
+ // special exceptions
+ switch($propName) {
+ case 'user.dir':
+ $val = getcwd();
+ break;
+ }
+
+ return $val;
+ }
+
+ /** Retuns reference to all properties*/
+ public static function &getProperties() {
+ return self::$properties;
+ }
+
+ public static function setProperty($propName, $propValue) {
+ $propName = (string) $propName;
+ $oldValue = self::getProperty($propName);
+ self::$properties[$propName] = $propValue;
+ return $oldValue;
+ }
+
+ public static function currentTimeMillis() {
+ list($usec, $sec) = explode(" ",microtime());
+ return ((float)$usec + (float)$sec);
+ }
+
+ /**
+ * Sets the include path based on PHP_CLASSPATH constant (set in phing.php).
+ * @return void
+ */
+ private static function setIncludePaths() {
+ $success = false;
+
+ if (defined('PHP_CLASSPATH')) {
+ $success = ini_set('include_path', PHP_CLASSPATH);
+ } else {
+ // don't do anything, just assume that include_path has been properly set.
+ $success = true;
+ }
+
+ if ($success === false) {
+ print("SYSTEM FAILURE: Could not set PHP include path\n");
+ self::halt(-1);
+ }
+ }
+
+ /**
+ * Sets PHP INI values that Phing needs.
+ * @return void
+ */
+ private static function setIni() {
+ error_reporting(E_ALL);
+ set_time_limit(0);
+ ini_set('magic_quotes_gpc', 'off');
+ ini_set('short_open_tag', 'off');
+ ini_set('default_charset', 'iso-8859-1');
+ ini_set('register_globals', 'off');
+ ini_set('allow_call_time_pass_reference', 'on');
+
+ // should return memory limit in MB
+ $mem_limit = (int) ini_get('memory_limit');
+ if ($mem_limit < 32) {
+ ini_set('memory_limit', '32M'); // nore: this may need to be higher for many projects
+ }
+ }
+
+ /**
+ * Returns reference to Timer object.
+ * @return Timer
+ */
+ public static function getTimer() {
+ if (self::$timer === null) {
+ include_once 'phing/system/util/Timer.php';
+ self::$timer= new Timer();
+ }
+ return self::$timer;
+ }
+
+ /**
+ * Start up Phing.
+ * Sets up the Phing environment -- does NOT initiate the build process.
+ * @return void
+ */
+ public static function startup() {
+
+ register_shutdown_function(array('Phing', 'shutdown'));
+
+ // some init stuff
+ self::getTimer()->start();
+
+ self::setSystemConstants();
+ self::setIncludePaths();
+ self::setIni();
+ }
+
+ /**
+ * Halts the system.
+ * @see shutdown()
+ */
+ public static function halt($code=0) {
+ self::shutdown($code);
+ }
+
+ /**
+ * Stops timers & exits.
+ * @return void
+ */
+ public static function shutdown($exitcode = 0) {
+ //print("[AUTOMATIC SYSTEM SHUTDOWN]\n");
+ self::getTimer()->stop();
+ exit($exitcode); // final point where everything stops
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/Project.php b/buildscripts/phing/classes/phing/Project.php
new file mode 100644
index 00000000..8123d91e
--- /dev/null
+++ b/buildscripts/phing/classes/phing/Project.php
@@ -0,0 +1,966 @@
+<?php
+/*
+ * $Id: Project.php,v 1.29 2006/02/02 20:27:10 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+define('PROJECT_MSG_DEBUG', 4);
+define('PROJECT_MSG_VERBOSE', 3);
+define('PROJECT_MSG_INFO', 2);
+define('PROJECT_MSG_WARN', 1);
+define('PROJECT_MSG_ERR', 0);
+
+include_once 'phing/system/io/PhingFile.php';
+include_once 'phing/util/FileUtils.php';
+include_once 'phing/TaskAdapter.php';
+include_once 'phing/util/StringHelper.php';
+include_once 'phing/BuildEvent.php';
+include_once 'phing/input/DefaultInputHandler.php';
+
+/**
+ * The Phing project class. Represents a completely configured Phing project.
+ * The class defines the project and all tasks/targets. It also contains
+ * methods to start a build as well as some properties and FileSystem
+ * abstraction.
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.29 $
+ * @package phing
+ */
+class Project {
+
+ /** contains the targets */
+ private $targets = array();
+ /** global filterset (future use) */
+ private $globalFilterSet = array();
+ /** all globals filters (future use) */
+ private $globalFilters = array();
+
+ /** Project properties map (usually String to String). */
+ private $properties = array();
+
+ /**
+ * Map of "user" properties (as created in the Ant task, for example).
+ * Note that these key/value pairs are also always put into the
+ * project properties, so only the project properties need to be queried.
+ * Mapping is String to String.
+ */
+ private $userProperties = array();
+
+ /**
+ * Map of inherited "user" properties - that are those "user"
+ * properties that have been created by tasks and not been set
+ * from the command line or a GUI tool.
+ * Mapping is String to String.
+ */
+ private $inheritedProperties = array();
+
+ /** task definitions for this project*/
+ private $taskdefs = array();
+
+ /** type definitions for this project */
+ private $typedefs = array();
+
+ /** holds ref names and a reference to the referred object*/
+ private $references = array();
+
+ /** The InputHandler being used by this project. */
+ private $inputHandler;
+
+ /* -- properties that come in via xml attributes -- */
+
+ /** basedir (PhingFile object) */
+ private $basedir;
+
+ /** the default target name */
+ private $defaultTarget = 'all';
+
+ /** project name (required) */
+ private $name;
+
+ /** project description */
+ private $description;
+
+ /** a FileUtils object */
+ private $fileUtils;
+
+ /** Build listeneers */
+ private $listeners = array();
+
+ /**
+ * Constructor, sets any default vars.
+ */
+ function __construct() {
+ $this->fileUtils = new FileUtils();
+ $this->inputHandler = new DefaultInputHandler();
+ }
+
+ /**
+ * Sets the input handler
+ */
+ public function setInputHandler(InputHandler $handler) {
+ $this->inputHandler = $handler;
+ }
+
+ /**
+ * Retrieves the current input handler.
+ */
+ public function getInputHandler() {
+ return $this->inputHandler;
+ }
+
+ /** inits the project, called from main app */
+ function init() {
+ // set builtin properties
+ $this->setSystemProperties();
+
+ // load default tasks
+ $taskdefs = Phing::getResourcePath("phing/tasks/defaults.properties");
+
+ try { // try to load taskdefs
+ $props = new Properties();
+ $in = new PhingFile((string)$taskdefs);
+
+ if ($in === null) {
+ throw new BuildException("Can't load default task list");
+ }
+ $props->load($in);
+
+ $enum = $props->propertyNames();
+ foreach($enum as $key) {
+ $value = $props->getProperty($key);
+ $this->addTaskDefinition($key, $value);
+ }
+ } catch (IOException $ioe) {
+ throw new BuildException("Can't load default task list");
+ }
+
+ // load default tasks
+ $typedefs = Phing::getResourcePath("phing/types/defaults.properties");
+
+ try { // try to load typedefs
+ $props = new Properties();
+ $in = new PhingFile((string)$typedefs);
+ if ($in === null) {
+ throw new BuildException("Can't load default datatype list");
+ }
+ $props->load($in);
+
+ $enum = $props->propertyNames();
+ foreach($enum as $key) {
+ $value = $props->getProperty($key);
+ $this->addDataTypeDefinition($key, $value);
+ }
+ } catch(IOException $ioe) {
+ throw new BuildException("Can't load default datatype list");
+ }
+ }
+
+ /** returns the global filterset (future use) */
+ function getGlobalFilterSet() {
+ return $this->globalFilterSet;
+ }
+
+ // ---------------------------------------------------------
+ // Property methods
+ // ---------------------------------------------------------
+
+ /**
+ * Sets a property. Any existing property of the same name
+ * is overwritten, unless it is a user property.
+ * @param string $name The name of property to set.
+ * Must not be <code>null</code>.
+ * @param string $value The new value of the property.
+ * Must not be <code>null</code>.
+ * @return void
+ */
+ public function setProperty($name, $value) {
+
+ // command line properties take precedence
+ if (isset($this->userProperties[$name])) {
+ $this->log("Override ignored for user property " . $name, PROJECT_MSG_VERBOSE);
+ return;
+ }
+
+ if (isset($this->properties[$name])) {
+ $this->log("Overriding previous definition of property " . $name, PROJECT_MSG_VERBOSE);
+ }
+
+ $this->log("Setting project property: " . $name . " -> " . $value, PROJECT_MSG_DEBUG);
+ $this->properties[$name] = $value;
+ }
+
+ /**
+ * Sets a property if no value currently exists. If the property
+ * exists already, a message is logged and the method returns with
+ * no other effect.
+ *
+ * @param string $name The name of property to set.
+ * Must not be <code>null</code>.
+ * @param string $value The new value of the property.
+ * Must not be <code>null</code>.
+ * @since 2.0
+ */
+ public function setNewProperty($name, $value) {
+ if (isset($this->properties[$name])) {
+ $this->log("Override ignored for property " . $name, PROJECT_MSG_DEBUG);
+ return;
+ }
+ $this->log("Setting project property: " . $name . " -> " . $value, PROJECT_MSG_DEBUG);
+ $this->properties[$name] = $value;
+ }
+
+ /**
+ * Sets a user property, which cannot be overwritten by
+ * set/unset property calls. Any previous value is overwritten.
+ * @param string $name The name of property to set.
+ * Must not be <code>null</code>.
+ * @param string $value The new value of the property.
+ * Must not be <code>null</code>.
+ * @see #setProperty()
+ */
+ public function setUserProperty($name, $value) {
+ $this->log("Setting ro project property: " . $name . " -> " . $value, PROJECT_MSG_DEBUG);
+ $this->userProperties[$name] = $value;
+ $this->properties[$name] = $value;
+ }
+
+ /**
+ * Sets a user property, which cannot be overwritten by set/unset
+ * property calls. Any previous value is overwritten. Also marks
+ * these properties as properties that have not come from the
+ * command line.
+ *
+ * @param string $name The name of property to set.
+ * Must not be <code>null</code>.
+ * @param string $value The new value of the property.
+ * Must not be <code>null</code>.
+ * @see #setProperty()
+ */
+ public function setInheritedProperty($name, $value) {
+ $this->inheritedProperties[$name] = $value;
+ $this->setUserProperty($name, $value);
+ }
+
+ /**
+ * Sets a property unless it is already defined as a user property
+ * (in which case the method returns silently).
+ *
+ * @param name The name of the property.
+ * Must not be <code>null</code>.
+ * @param value The property value. Must not be <code>null</code>.
+ */
+ private function setPropertyInternal($name, $value) {
+ if (isset($this->userProperties[$name])) {
+ $this->log("Override ignored for user property " . $name, PROJECT_MSG_VERBOSE);
+ return;
+ }
+ $this->properties[$name] = $value;
+ }
+
+ /**
+ * Returns the value of a property, if it is set.
+ *
+ * @param string $name The name of the property.
+ * May be <code>null</code>, in which case
+ * the return value is also <code>null</code>.
+ * @return string The property value, or <code>null</code> for no match
+ * or if a <code>null</code> name is provided.
+ */
+ public function getProperty($name) {
+ if (!isset($this->properties[$name])) {
+ return null;
+ }
+ return $this->properties[$name];
+ }
+
+ /**
+ * Replaces ${} style constructions in the given value with the
+ * string value of the corresponding data types.
+ *
+ * @param value The string to be scanned for property references.
+ * May be <code>null</code>.
+ *
+ * @return the given string with embedded property names replaced
+ * by values, or <code>null</code> if the given string is
+ * <code>null</code>.
+ *
+ * @exception BuildException if the given value has an unclosed
+ * property name, e.g. <code>${xxx</code>
+ */
+ public function replaceProperties($value) {
+ return ProjectConfigurator::replaceProperties($this, $value, $this->properties);
+ }
+
+ /**
+ * Returns the value of a user property, if it is set.
+ *
+ * @param string $name The name of the property.
+ * May be <code>null</code>, in which case
+ * the return value is also <code>null</code>.
+ * @return string The property value, or <code>null</code> for no match
+ * or if a <code>null</code> name is provided.
+ */
+ public function getUserProperty($name) {
+ if (!isset($this->userProperties[$name])) {
+ return null;
+ }
+ return $this->userProperties[$name];
+ }
+
+ /**
+ * Returns a copy of the properties table.
+ * @return array A hashtable containing all properties
+ * (including user properties).
+ */
+ public function getProperties() {
+ return $this->properties;
+ }
+
+ /**
+ * Returns a copy of the user property hashtable
+ * @return a hashtable containing just the user properties
+ */
+ public function getUserProperties() {
+ return $this->userProperties;
+ }
+
+ /**
+ * Copies all user properties that have been set on the command
+ * line or a GUI tool from this instance to the Project instance
+ * given as the argument.
+ *
+ * <p>To copy all "user" properties, you will also have to call
+ * {@link #copyInheritedProperties copyInheritedProperties}.</p>
+ *
+ * @param Project $other the project to copy the properties to. Must not be null.
+ * @return void
+ * @since phing 2.0
+ */
+ public function copyUserProperties(Project $other) {
+ foreach($this->userProperties as $arg => $value) {
+ if (isset($this->inheritedProperties[$arg])) {
+ continue;
+ }
+ $other->setUserProperty($arg, $value);
+ }
+ }
+
+ /**
+ * Copies all user properties that have not been set on the
+ * command line or a GUI tool from this instance to the Project
+ * instance given as the argument.
+ *
+ * <p>To copy all "user" properties, you will also have to call
+ * {@link #copyUserProperties copyUserProperties}.</p>
+ *
+ * @param other the project to copy the properties to. Must not be null.
+ *
+ * @since phing 2.0
+ */
+ public function copyInheritedProperties(Project $other) {
+ foreach($this->userProperties as $arg => $value) {
+ if ($other->getUserProperty($arg) !== null) {
+ continue;
+ }
+ $other->setInheritedProperty($arg, $value);
+ }
+ }
+
+ // ---------------------------------------------------------
+ // END Properties methods
+ // ---------------------------------------------------------
+
+
+ function setDefaultTarget($targetName) {
+ $this->defaultTarget = (string) trim($targetName);
+ }
+
+ function getDefaultTarget() {
+ return (string) $this->defaultTarget;
+ }
+
+ /**
+ * Sets the name of the current project
+ *
+ * @param string name of project
+ * @return void
+ * @access public
+ * @author Andreas Aderhold, andi@binarycloud.com
+ */
+
+ function setName($name) {
+ $this->name = (string) trim($name);
+ $this->setProperty("phing.project.name", $this->name);
+ }
+
+ /**
+ * Returns the name of this project
+ *
+ * @returns string projectname
+ * @access public
+ * @author Andreas Aderhold, andi@binarycloud.com
+ */
+ function getName() {
+ return (string) $this->name;
+ }
+
+ /** Set the projects description */
+ function setDescription($description) {
+ $this->description = (string) trim($description);
+ }
+
+ /** return the description, null otherwise */
+ function getDescription() {
+ return $this->description;
+ }
+
+ /** Set basedir object from xml*/
+ function setBasedir($dir) {
+ if ($dir instanceof PhingFile) {
+ $dir = $dir->getAbsolutePath();
+ }
+
+ $dir = $this->fileUtils->normalize($dir);
+
+ $dir = new PhingFile((string) $dir);
+ if (!$dir->exists()) {
+ throw new BuildException("Basedir ".$dir->getAbsolutePath()." does not exist");
+ }
+ if (!$dir->isDirectory()) {
+ throw new BuildException("Basedir ".$dir->getAbsolutePath()." is not a directory");
+ }
+ $this->basedir = $dir;
+ $this->setPropertyInternal("project.basedir", $this->basedir->getAbsolutePath());
+ $this->log("Project base dir set to: " . $this->basedir->getPath(), PROJECT_MSG_VERBOSE);
+
+ // [HL] added this so that ./ files resolve correctly. This may be a mistake ... or may be in wrong place.
+ chdir($dir->getAbsolutePath());
+ }
+
+ /**
+ * Returns the basedir of this project
+ *
+ * @returns PhingFile Basedir PhingFile object
+ * @access public
+ * @throws BuildException
+ * @author Andreas Aderhold, andi@binarycloud.com
+ */
+ function getBasedir() {
+ if ($this->basedir === null) {
+ try { // try to set it
+ $this->setBasedir(".");
+ } catch (BuildException $exc) {
+ throw new BuildException("Can not set default basedir. ".$exc->getMessage());
+ }
+ }
+ return $this->basedir;
+ }
+
+ /**
+ * Sets system properties and the environment variables for this project.
+ *
+ * @return void
+ */
+ function setSystemProperties() {
+
+ // first get system properties
+ $systemP = array_merge( self::getProperties(), Phing::getProperties() );
+ foreach($systemP as $name => $value) {
+ $this->setPropertyInternal($name, $value);
+ }
+
+ // and now the env vars
+ foreach($_SERVER as $name => $value) {
+ // skip arrays
+ if (is_array($value)) {
+ continue;
+ }
+ $this->setPropertyInternal('env.' . $name, $value);
+ }
+ return true;
+ }
+
+
+ /**
+ * Adds a task definition.
+ * @param string $name Name of tag.
+ * @param string $class The class path to use.
+ * @param string $classpath The classpat to use.
+ */
+ function addTaskDefinition($name, $class, $classpath = null) {
+ $name = $name;
+ $class = $class;
+ if ($class === "") {
+ $this->log("Task $name has no class defined.", PROJECT_MSG_ERR);
+ } elseif (!isset($this->taskdefs[$name])) {
+ Phing::import($class, $classpath);
+ $this->taskdefs[$name] = $class;
+ $this->log(" +Task definiton: $name ($class)", PROJECT_MSG_DEBUG);
+ } else {
+ $this->log("Task $name ($class) already registerd, skipping", PROJECT_MSG_VERBOSE);
+ }
+ }
+
+ function &getTaskDefinitions() {
+ return $this->taskdefs;
+ }
+
+ /**
+ * Adds a data type definition.
+ * @param string $name Name of tag.
+ * @param string $class The class path to use.
+ * @param string $classpath The classpat to use.
+ */
+ function addDataTypeDefinition($typeName, $typeClass, $classpath = null) {
+ if (!isset($this->typedefs[$typeName])) {
+ Phing::import($typeClass, $classpath);
+ $this->typedefs[$typeName] = $typeClass;
+ $this->log(" +User datatype: $typeName ($typeClass)", PROJECT_MSG_DEBUG);
+ } else {
+ $this->log("Type $name ($class) already registerd, skipping", PROJECT_MSG_VERBOSE);
+ }
+ }
+
+ function getDataTypeDefinitions() {
+ return $this->typedefs;
+ }
+
+ /** add a new target to the project */
+ function addTarget($targetName, &$target) {
+ if (isset($this->targets[$targetName])) {
+ throw new BuildException("Duplicate target: $targetName");
+ }
+ $this->addOrReplaceTarget($targetName, $target);
+ }
+
+ function addOrReplaceTarget($targetName, &$target) {
+ $this->log(" +Target: $targetName", PROJECT_MSG_DEBUG);
+ $target->setProject($this);
+ $this->targets[$targetName] = $target;
+ }
+
+ function getTargets() {
+ return $this->targets;
+ }
+
+ /**
+ * Create a new task instance and return reference to it. This method is
+ * sorta factory like. A _local_ instance is created and a reference returned to
+ * that instance. Usually PHP destroys local variables when the function call
+ * ends. But not if you return a reference to that variable.
+ * This is kinda error prone, because if no reference exists to the variable
+ * it is destroyed just like leaving the local scope with primitive vars. There's no
+ * central place where the instance is stored as in other OOP like languages.
+ *
+ * [HL] Well, ZE2 is here now, and this is still working. We'll leave this alone
+ * unless there's any good reason not to.
+ *
+ * @param string $taskType Task name
+ * @returns Task A task object
+ * @throws BuildException
+ * Exception
+ */
+ function createTask($taskType) {
+ try {
+ $cls = "";
+ $tasklwr = strtolower($taskType);
+ foreach ($this->taskdefs as $name => $class) {
+ if (strtolower($name) === $tasklwr) {
+ $cls = StringHelper::unqualify($class);
+ break;
+ }
+ }
+
+ if ($cls === "") {
+ return null;
+ }
+
+ if (!class_exists($cls)) {
+ throw new BuildException("Could not instantiate class $cls, even though a class was specified. (Make sure that the specified class file contains a class with the correct name.)");
+ }
+
+ $o = new $cls();
+
+ if ($o instanceof Task) {
+ $task = $o;
+ } else {
+ $this->log (" (Using TaskAdapter for: $taskType)", PROJECT_MSG_DEBUG);
+ // not a real task, try adapter
+ $taskA = new TaskAdapter();
+ $taskA->setProxy($o);
+ $task = $taskA;
+ }
+ $task->setProject($this);
+ $task->setTaskType($taskType);
+ // set default value, can be changed by the user
+ $task->setTaskName($taskType);
+ $this->log (" +Task: " . $taskType, PROJECT_MSG_DEBUG);
+ } catch (Exception $t) {
+ throw new BuildException("Could not create task of type: " . $taskType, $t);
+ }
+ // everything fine return reference
+ return $task;
+ }
+
+ /**
+ * Create a task instance and return reference to it
+ * See createTask() for explanation how this works
+ *
+ * @param string Type name
+ * @returns object A datatype object
+ * @throws BuildException
+ * Exception
+ */
+ function createDataType($typeName) {
+ try {
+ $cls = "";
+ $typelwr = strtolower($typeName);
+ foreach ($this->typedefs as $name => $class) {
+ if (strtolower($name) === $typelwr) {
+ $cls = StringHelper::unqualify($class);
+ break;
+ }
+ }
+
+ if ($cls === "") {
+ return null;
+ }
+
+ if (!class_exists($cls)) {
+ throw new BuildException("Could not instantiate class $cls, even though a class was specified. (Make sure that the specified class file contains a class with the correct name.)");
+ }
+
+ $type = new $cls();
+ $this->log(" +Type: $typeName", PROJECT_MSG_DEBUG);
+ if (!($type instanceof DataType)) {
+ throw new Exception("$class is not an instance of phing.types.DataType");
+ }
+ if ($type instanceof ProjectComponent) {
+ $type->setProject($this);
+ }
+ } catch (Exception $t) {
+ throw new BuildException("Could not create type: $typeName", $t);
+ }
+ // everything fine return reference
+ return $type;
+ }
+
+ /**
+ * Executes a list of targets
+ *
+ * @param array List of target names to execute
+ * @returns void
+ * @throws BuildException
+ */
+ function executeTargets($targetNames) {
+ foreach($targetNames as $tname) {
+ $this->executeTarget($tname);
+ }
+ }
+
+ /**
+ * Executes a target
+ *
+ * @param string Name of Target to execute
+ * @returns void
+ * @throws BuildException
+ */
+ function executeTarget($targetName) {
+
+ // complain about executing void
+ if ($targetName === null) {
+ throw new BuildException("No target specified");
+ }
+
+ // invoke topological sort of the target tree and run all targets
+ // until targetName occurs.
+ $sortedTargets = $this->_topoSort($targetName, $this->targets);
+
+ $curIndex = (int) 0;
+ $curTarget = null;
+ do {
+ try {
+ $curTarget = $sortedTargets[$curIndex++];
+ $curTarget->performTasks();
+ } catch (BuildException $exc) {
+ $this->log("Execution of target \"".$curTarget->getName()."\" failed for the following reason: ".$exc->getMessage(), PROJECT_MSG_ERR);
+ throw $exc;
+ }
+ } while ($curTarget->getName() !== $targetName);
+ }
+
+
+ function resolveFile($fileName, $rootDir = null) {
+ if ($rootDir === null) {
+ return $this->fileUtils->resolveFile($this->basedir, $fileName);
+ } else {
+ return $this->fileUtils->resolveFile($rootDir, $fileName);
+ }
+ }
+
+ /**
+ * Topologically sort a set of Targets.
+ * @param $root is the (String) name of the root Target. The sort is
+ * created in such a way that the sequence of Targets until the root
+ * target is the minimum possible such sequence.
+ * @param $targets is a array representing a "name to Target" mapping
+ * @return An array of Strings with the names of the targets in
+ * sorted order.
+ */
+ function _topoSort($root, &$targets) {
+
+ $root = (string) $root;
+ $ret = array();
+ $state = array();
+ $visiting = array();
+
+ // We first run a DFS based sort using the root as the starting node.
+ // This creates the minimum sequence of Targets to the root node.
+ // We then do a sort on any remaining unVISITED targets.
+ // This is unnecessary for doing our build, but it catches
+ // circular dependencies or missing Targets on the entire
+ // dependency tree, not just on the Targets that depend on the
+ // build Target.
+
+ $this->_tsort($root, $targets, $state, $visiting, $ret);
+
+ $retHuman = "";
+ for ($i=0, $_i=count($ret); $i < $_i; $i++) {
+ $retHuman .= $ret[$i]->toString()." ";
+ }
+ $this->log("Build sequence for target '$root' is: $retHuman", PROJECT_MSG_VERBOSE);
+
+ $keys = array_keys($targets);
+ while($keys) {
+ $curTargetName = (string) array_shift($keys);
+ if (!isset($state[$curTargetName])) {
+ $st = null;
+ } else {
+ $st = (string) $state[$curTargetName];
+ }
+
+ if ($st === null) {
+ $this->_tsort($curTargetName, $targets, $state, $visiting, $ret);
+ } elseif ($st === "VISITING") {
+ throw new Exception("Unexpected node in visiting state: $curTargetName");
+ }
+ }
+
+ $retHuman = "";
+ for ($i=0,$_i=count($ret); $i < $_i; $i++) {
+ $retHuman .= $ret[$i]->toString()." ";
+ }
+ $this->log("Complete build sequence is: $retHuman", PROJECT_MSG_VERBOSE);
+
+ return $ret;
+ }
+
+ // one step in a recursive DFS traversal of the target dependency tree.
+ // - The array "state" contains the state (VISITED or VISITING or null)
+ // of all the target names.
+ // - The stack "visiting" contains a stack of target names that are
+ // currently on the DFS stack. (NB: the target names in "visiting" are
+ // exactly the target names in "state" that are in the VISITING state.)
+ // 1. Set the current target to the VISITING state, and push it onto
+ // the "visiting" stack.
+ // 2. Throw a BuildException if any child of the current node is
+ // in the VISITING state (implies there is a cycle.) It uses the
+ // "visiting" Stack to construct the cycle.
+ // 3. If any children have not been VISITED, tsort() the child.
+ // 4. Add the current target to the Vector "ret" after the children
+ // have been visited. Move the current target to the VISITED state.
+ // "ret" now contains the sorted sequence of Targets upto the current
+ // Target.
+
+ function _tsort($root, &$targets, &$state, &$visiting, &$ret) {
+ $state[$root] = "VISITING";
+ $visiting[] = $root;
+
+ if (!isset($targets[$root]) || !($targets[$root] instanceof Target)) {
+ $target = null;
+ } else {
+ $target = $targets[$root];
+ }
+
+ // make sure we exist
+ if ($target === null) {
+ $sb = "Target '$root' does not exist in this project.";
+ array_pop($visiting);
+ if (!empty($visiting)) {
+ $parent = (string) $visiting[count($visiting)-1];
+ $sb .= "It is used from target '$parent'.";
+ }
+ throw new BuildException($sb);
+ }
+
+ $deps = $target->getDependencies();
+
+ while($deps) {
+ $cur = (string) array_shift($deps);
+ if (!isset($state[$cur])) {
+ $m = null;
+ } else {
+ $m = (string) $state[$cur];
+ }
+ if ($m === null) {
+ // not been visited
+ $this->_tsort($cur, $targets, $state, $visiting, $ret);
+ } elseif ($m == "VISITING") {
+ // currently visiting this node, so have a cycle
+ throw $this->_makeCircularException($cur, $visiting);
+ }
+ }
+
+ $p = (string) array_pop($visiting);
+ if ($root !== $p) {
+ throw new Exception("Unexpected internal error: expected to pop $root but got $p");
+ }
+
+ $state[$root] = "VISITED";
+ $ret[] = $target;
+ }
+
+ function _makeCircularException($end, $stk) {
+ $sb = "Circular dependency: $end";
+ do {
+ $sb .= " <- ".(string) array_pop($stk);
+ } while($c != $end);
+ return new BuildException($sb);
+ }
+
+ /**
+ * Adds a reference to an object. This method is called when the parser
+ * detects a id="foo" attribute. It passes the id as $name and a reference
+ * to the object assigned to this id as $value
+ */
+ function addReference($name, $object) {
+ if (isset($this->references[$name])) {
+ $this->log("Overriding previous definition of reference to $name", PROJECT_MSG_WARN);
+ }
+ $this->log("Adding reference: $name -> ".get_class($object), PROJECT_MSG_DEBUG);
+ $this->references[$name] = $object;
+ }
+
+ /**
+ * Returns the references array.
+ * @return array
+ */
+ function getReferences() {
+ return $this->references;
+ }
+
+ /**
+ * Returns a specific reference.
+ * @param string $key The reference id/key.
+ * @return object or null if not defined
+ */
+ function getReference($key)
+ {
+ if (isset($this->references[$key])) {
+ return $this->references[$key];
+ }
+ return null; // just to be explicit
+ }
+
+ /**
+ * Abstracting and simplifyling Logger calls for project messages
+ */
+ function log($msg, $level = PROJECT_MSG_INFO) {
+ $this->logObject($this, $msg, $level);
+ }
+
+ function logObject($obj, $msg, $level) {
+ $this->fireMessageLogged($obj, $msg, $level);
+ }
+
+ function addBuildListener(BuildListener $listener) {
+ $this->listeners[] = $listener;
+ }
+
+ function removeBuildListener(BuildListener $listener) {
+ $newarray = array();
+ for ($i=0, $size=count($this->listeners); $i < $size; $i++) {
+ if ($this->listeners[$i] !== $listener) {
+ $newarray[] = $this->listeners[$i];
+ }
+ }
+ $this->listeners = $newarray;
+ }
+
+ function getBuildListeners() {
+ return $this->listeners;
+ }
+
+ function fireBuildStarted() {
+ $event = new BuildEvent($this);
+ foreach($this->listeners as $listener) {
+ $listener->buildStarted($event);
+ }
+ }
+
+ function fireBuildFinished($exception) {
+ $event = new BuildEvent($this);
+ $event->setException($exception);
+ foreach($this->listeners as $listener) {
+ $listener->buildFinished($event);
+ }
+ }
+
+ function fireTargetStarted($target) {
+ $event = new BuildEvent($target);
+ foreach($this->listeners as $listener) {
+ $listener->targetStarted($event);
+ }
+ }
+
+ function fireTargetFinished($target, $exception) {
+ $event = new BuildEvent($target);
+ $event->setException($exception);
+ foreach($this->listeners as $listener) {
+ $listener->targetFinished($event);
+ }
+ }
+
+ function fireTaskStarted($task) {
+ $event = new BuildEvent($task);
+ foreach($this->listeners as $listener) {
+ $listener->taskStarted($event);
+ }
+ }
+
+ function fireTaskFinished($task, $exception) {
+ $event = new BuildEvent($task);
+ $event->setException($exception);
+ foreach($this->listeners as $listener) {
+ $listener->taskFinished($event);
+ }
+ }
+
+ function fireMessageLoggedEvent($event, $message, $priority) {
+ $event->setMessage($message, $priority);
+ foreach($this->listeners as $listener) {
+ $listener->messageLogged($event);
+ }
+ }
+
+ function fireMessageLogged($object, $message, $priority) {
+ $this->fireMessageLoggedEvent(new BuildEvent($object), $message, $priority);
+ }
+}
diff --git a/buildscripts/phing/classes/phing/ProjectComponent.php b/buildscripts/phing/classes/phing/ProjectComponent.php
new file mode 100644
index 00000000..97ef329f
--- /dev/null
+++ b/buildscripts/phing/classes/phing/ProjectComponent.php
@@ -0,0 +1,72 @@
+<?php
+/*
+ * $Id: ProjectComponent.php,v 1.5 2003/12/24 13:02:08 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * Abstract class providing properties and methods common to all
+ * the project components
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.5 $
+ * @package phing
+ */
+abstract class ProjectComponent {
+
+ /**
+ * Holds a reference to the project that a project component
+ * (a task, a target, etc.) belongs to
+ *
+ * @var object A reference to the current project instance
+ */
+ protected $project = null;
+
+ /**
+ * References the project to the current component.
+ *
+ * @param object The reference to the current project
+ * @access public
+ */
+ function setProject($project) {
+ $this->project = $project;
+ }
+
+ /**
+ * Returns a reference to current project
+ *
+ * @return object Reference to current porject object
+ * @access public
+ */
+ function getProject() {
+ return $this->project;
+ }
+
+ /**
+ * Logs a message with the given priority.
+ *
+ * @param string The message to be logged.
+ * @param integer The message's priority at this message should have
+ */
+ public function log($msg, $level = PROJECT_MSG_INFO) {
+ if ($this->project !== null) {
+ $this->project->log($msg, $level);
+ }
+ }
+}
diff --git a/buildscripts/phing/classes/phing/RuntimeConfigurable.php b/buildscripts/phing/classes/phing/RuntimeConfigurable.php
new file mode 100644
index 00000000..a23437fa
--- /dev/null
+++ b/buildscripts/phing/classes/phing/RuntimeConfigurable.php
@@ -0,0 +1,118 @@
+<?php
+/*
+ * $Id: RuntimeConfigurable.php,v 1.6 2003/12/24 12:38:39 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * Wrapper class that holds the attributes of a Task (or elements
+ * nested below that level) and takes care of configuring that element
+ * at runtime.
+ *
+ * <strong>SMART-UP INLINE DOCS</strong>
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.6 $
+ * @package phing
+ */
+class RuntimeConfigurable {
+
+ private $elementTag = null;
+ private $children = array();
+ private $wrappedObject = null;
+ private $attributes = array();
+ private $characters = "";
+
+
+ /** @param proxy The element to wrap. */
+ function __construct($proxy, $elementTag) {
+ $this->wrappedObject = $proxy;
+ $this->elementTag = $elementTag;
+ }
+
+ function setProxy($proxy) {
+ $this->wrappedObject = $proxy;
+ }
+
+ /** Set's the attributes for the wrapped element. */
+ function setAttributes($attributes) {
+ $this->attributes = $attributes;
+ }
+
+ /** Returns the AttributeList of the wrapped element. */
+ function getAttributes() {
+ return $this->attributes;
+ }
+
+ /** Adds child elements to the wrapped element. */
+ function addChild(RuntimeConfigurable $child) {
+ $this->children[] = $child;
+ }
+
+ /** Returns the child with index */
+ function getChild($index) {
+ return $this->children[(int)$index];
+ }
+
+ /** Add characters from #PCDATA areas to the wrapped element. */
+ function addText($data) {
+ $this->characters .= (string) $data;
+ }
+
+ function getElementTag() {
+ return $this->elementTag;
+ }
+
+
+ /** Configure the wrapped element and all children. */
+ function maybeConfigure(Project $project) {
+ $id = null;
+
+ // DataType configured in ProjectConfigurator
+ // if ( is_a($this->wrappedObject, "DataType") )
+ // return;
+
+ if ($this->attributes || $this->characters) {
+ ProjectConfigurator::configure($this->wrappedObject, $this->attributes, $project);
+
+ if (isset($this->attributes["id"])) {
+ $id = $this->attributes["id"];
+ }
+
+ $this->attributes = null;
+
+ if ($this->characters) {
+ ProjectConfigurator::addText($project, $this->wrappedObject, (string) $this->characters);
+ $this->characters="";
+ }
+ if ($id !== null) {
+ $project->addReference($id, $this->wrappedObject);
+ }
+ }
+
+ if ( is_array($this->children) && !empty($this->children) ) {
+ // Configure all child of this object ...
+ foreach($this->children as $child) {
+ $child->maybeConfigure($project);
+ ProjectConfigurator::storeChild($project, $this->wrappedObject, $child->wrappedObject, strtolower($child->getElementTag()));
+ }
+ }
+ }
+}
+
diff --git a/buildscripts/phing/classes/phing/Target.php b/buildscripts/phing/classes/phing/Target.php
new file mode 100644
index 00000000..9aeb9440
--- /dev/null
+++ b/buildscripts/phing/classes/phing/Target.php
@@ -0,0 +1,317 @@
+<?php
+/*
+ * $Id: Target.php,v 1.10 2005/10/04 19:13:44 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/TaskContainer.php';
+
+/**
+ * The Target component. Carries all required target data. Implements the
+ * abstract class {@link TaskContainer}
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright © 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.10 $ $Date: 2005/10/04 19:13:44 $
+ * @access public
+ * @see TaskContainer
+ * @package phing
+ */
+
+class Target implements TaskContainer {
+
+ /** name of target */
+ private $name;
+
+ /** dependencies */
+ private $dependencies = array();
+
+ /** holds objects of children of this target */
+ private $children = array();
+
+ /** the if cond. from xml */
+ private $ifCondition = "";
+
+ /** the unless cond. from xml */
+ private $unlessCondition = "";
+
+ /** description of this target */
+ private $description;
+
+ /** reference to project */
+ private $project;
+
+ /**
+ * References the project to the current component.
+ *
+ * @param Project The reference to the current project
+ */
+ public function setProject(Project $project) {
+ $this->project = $project;
+ }
+
+ /**
+ * Returns reference to current project
+ *
+ * @return Project Reference to current porject object
+ */
+ public function getProject() {
+ return $this->project;
+ }
+
+ /**
+ * Sets the target dependencies from xml
+ *
+ * @param string $depends Comma separated list of targetnames that depend on
+ * this target
+ * @throws BuildException
+ */
+ public function setDepends($depends) {
+ // explode should be faster than strtok
+ $deps = explode(',', $depends);
+ for ($i=0, $size=count($deps); $i < $size; $i++) {
+ $trimmed = trim($deps[$i]);
+ if ($trimmed === "") {
+ throw new BuildException("Syntax Error: Depend attribute for target ".$this->getName()." is malformed.");
+ }
+ $this->addDependency($trimmed);
+ }
+ }
+
+ /**
+ * Adds a singular dependent target name to the list
+ *
+ * @param string The dependency target to add
+ * @access public
+ */
+ public function addDependency($dependency) {
+ $this->dependencies[] = (string) $dependency;
+ }
+
+ /**
+ * Returns reference to indexed array of the dependencies this target has.
+ *
+ * @return array Referece to target dependencoes
+ */
+ public function getDependencies() {
+ return $this->dependencies;
+ }
+
+ /**
+ * Sets the name of the target
+ *
+ * @param string Name of this target
+ */
+ public function setName($name) {
+ $this->name = (string) $name;
+ }
+
+ /**
+ * Returns name of this target.
+ *
+ * @return string The name of the target
+ * @access public
+ */
+ function getName() {
+ return (string) $this->name;
+ }
+
+ /**
+ * Adds a task element to the list of this targets child elements
+ *
+ * @param object The task object to add
+ * @access public
+ */
+ function addTask(Task $task) {
+ $this->children[] = $task;
+ }
+
+ /**
+ * Adds a runtime configurable element to the list of this targets child
+ * elements.
+ *
+ * @param object The RuntimeConfigurabel object
+ * @access public
+ */
+ function addDataType($rtc) {
+ $this->children[] = $rtc;
+ }
+
+ /**
+ * Returns an array of all tasks this target has as childrens.
+ *
+ * The task objects are copied here. Don't use this method to modify
+ * task objects.
+ *
+ * @return array Task[]
+ */
+ public function getTasks() {
+ $tasks = array();
+ for ($i=0,$size=count($this->children); $i < $size; $i++) {
+ $tsk = $this->children[$i];
+ if ($tsk instanceof Task) {
+ // note: we're copying objects here!
+ $tasks[] = clone $tsk;
+ }
+ }
+ return $tasks;
+ }
+
+ /**
+ * Set the if-condition from the XML tag, if any. The property name given
+ * as parameter must be present so the if condition evaluates to true
+ *
+ * @param string The property name that has to be present
+ * @access public
+ */
+ public function setIf($property) {
+ $this->ifCondition = ($property === null) ? "" : $property;
+ }
+
+ /**
+ * Set the unless-condition from the XML tag, if any. The property name
+ * given as parameter must be present so the unless condition evaluates
+ * to true
+ *
+ * @param string The property name that has to be present
+ * @access public
+ */
+ public function setUnless($property) {
+ $this->unlessCondition = ($property === null) ? "" : $property;
+ }
+
+ /**
+ * Sets a textual description of this target.
+ *
+ * @param string The description text
+ */
+ public function setDescription($description) {
+ if ($description !== null && strcmp($description, "") !== 0) {
+ $this->description = (string) $description;
+ } else {
+ $this->description = null;
+ }
+ }
+
+ /**
+ * Returns the description of this target.
+ *
+ * @return string The description text of this target
+ */
+ public function getDescription() {
+ return $this->description;
+ }
+
+ /**
+ * Returns a string representation of this target. In our case it
+ * simply returns the target name field
+ *
+ * @return string The string representation of this target
+ */
+ function toString() {
+ return (string) $this->name;
+ }
+
+ /**
+ * The entry point for this class. Does some checking, then processes and
+ * performs the tasks for this target.
+ *
+ */
+ public function main() {
+ if ($this->testIfCondition() && $this->testUnlessCondition()) {
+ foreach($this->children as $o) {
+ if ($o instanceof Task) {
+ // child is a task
+ $o->perform();
+ } else {
+ // child is a RuntimeConfigurable
+ $o->maybeConfigure($this->project);
+ }
+ }
+ } elseif (!$this->testIfCondition()) {
+ $this->project->log("Skipped target '".$this->name."' because property '".$this->ifCondition."' not set.", PROJECT_MSG_VERBOSE);
+ } else {
+ $this->project->log("Skipped target '".$this->name."' because property '".$this->unlessCondition."' set.", PROJECT_MSG_VERBOSE);
+ }
+ }
+
+ /**
+ * Performs the tasks by calling the main method of this target that
+ * actually executes the tasks.
+ *
+ * This method is for ZE2 and used for proper exception handling of
+ * task exceptions.
+ */
+ public function performTasks() {
+ try {// try to execute this target
+ $this->project->fireTargetStarted($this);
+ $this->main();
+ $this->project->fireTargetFinished($this, $null=null);
+ } catch (Exception $exc) {
+ // log here and rethrow
+ $this->project->fireTargetFinished($this, $exc);
+ throw $exc;
+ }
+ }
+
+ /**
+ * Tests if the property set in ifConfiditon exists.
+ *
+ * @return boolean <code>true</code> if the property specified
+ * in <code>$this->ifCondition</code> exists;
+ * <code>false</code> otherwise
+ */
+ private function testIfCondition() {
+ if ($this->ifCondition === "") {
+ return true;
+ }
+
+ $properties = explode(",", $this->ifCondition);
+
+ $result = true;
+ foreach ($properties as $property) {
+ $test = ProjectConfigurator::replaceProperties($this->getProject(), $property, $this->project->getProperties());
+ $result = $result && ($this->project->getProperty($test) !== null);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Tests if the property set in unlessCondition exists.
+ *
+ * @return boolean <code>true</code> if the property specified
+ * in <code>$this->unlessCondition</code> exists;
+ * <code>false</code> otherwise
+ */
+ private function testUnlessCondition() {
+ if ($this->unlessCondition === "") {
+ return true;
+ }
+
+ $properties = explode(",", $this->unlessCondition);
+
+ $result = true;
+ foreach ($properties as $property) {
+ $test = ProjectConfigurator::replaceProperties($this->getProject(), $property, $this->project->getProperties());
+ $result = $result && ($this->project->getProperty($test) === null);
+ }
+ return $result;
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/Task.php b/buildscripts/phing/classes/phing/Task.php
new file mode 100644
index 00000000..893a82e9
--- /dev/null
+++ b/buildscripts/phing/classes/phing/Task.php
@@ -0,0 +1,266 @@
+<?php
+/*
+ * $Id: Task.php,v 1.11 2005/10/05 20:23:22 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/ProjectComponent.php';
+include_once 'phing/RuntimeConfigurable.php';
+
+/**
+ * The base class for all Tasks.
+ *
+ * Use {@link Project#createTask} to register a new Task.
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright © 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.11 $
+ * @see Project#createTask()
+ * @package phing
+ */
+abstract class Task extends ProjectComponent {
+
+ /** owning Target object */
+ protected $target;
+
+ /** description of the task */
+ protected $description;
+
+ /** internal taskname (req) */
+ protected $taskType;
+
+ /** taskname for logger */
+ protected $taskName;
+
+ /** stored buildfile location */
+ protected $location;
+
+ /** wrapper of the task */
+ protected $wrapper;
+
+ /**
+ * Sets the owning target this task belongs to.
+ *
+ * @param object Reference to owning target
+ * @access public
+ */
+ function setOwningTarget(Target $target) {
+ $this->target = $target;
+ }
+
+ /**
+ * Returns the owning target of this task.
+ *
+ * @return object The target object that owns this task
+ * @access public
+ */
+ function getOwningTarget() {
+ return $this->target;
+ }
+
+ /**
+ * Returns the name of task, used only for log messages
+ *
+ * @return string Name of this task
+ * @access public
+ */
+ function getTaskName() {
+ if ($this->taskName === null) {
+ // if no task name is set, then it's possible
+ // this task was created from within another task. We don't
+ // therefore know the XML tag name for this task, so we'll just
+ // use the class name stripped of "task" suffix. This is only
+ // for log messages, so we don't have to worry much about accuracy.
+ return preg_replace('/task$/i', '', get_class($this));
+ }
+ return $this->taskName;
+ }
+
+ /**
+ * Sets the name of this task for log messages
+ *
+ * @return string A string representing the name of this task for log
+ * @access public
+ */
+ function setTaskName($name) {
+ $this->taskName = (string) $name;
+ }
+
+ /**
+ * Returns the name of the task under which it was invoked,
+ * usually the XML tagname
+ *
+ * @return string The type of this task (XML Tag)
+ */
+ function getTaskType() {
+ return $this->taskType;
+ }
+
+ /**
+ * Sets the type of the task. Usually this is the name of the XML tag
+ *
+ * @param string The type of this task (XML Tag)
+ */
+ function setTaskType($name) {
+ $this->taskType = (string) $name;
+ }
+
+ /**
+ * Returns a name
+ *
+ */
+ protected function getRegisterSlot($slotName) {
+ return Register::getSlot('task.' . $this->getTaskName() . '.' . $slotName);
+ }
+
+ /**
+ * Provides a project level log event to the task.
+ *
+ * @param string The message to log
+ * @param integer The priority of the message
+ * @see BuildEvent
+ * @see BuildListener
+ */
+ function log($msg, $level = PROJECT_MSG_INFO) {
+ $this->project->logObject($this, $msg, $level);
+ }
+
+ /**
+ * Sets a textual description of the task
+ *
+ * @param string The text describing the task
+ */
+ public function setDescription($desc) {
+ $this->description = $desc;
+ }
+
+ /**
+ * Returns the textual description of the task
+ *
+ * @return string The text description of the task
+ */
+ public function getDescription() {
+ return $this->description;
+ }
+
+ /**
+ * Called by the parser to let the task initialize properly.
+ * Should throw a BuildException if something goes wrong with the build
+ *
+ * This is abstract here, but may not be overloaded by subclasses.
+ *
+ * @throws BuildException
+ */
+ public function init() {
+ }
+
+ /**
+ * Called by the project to let the task do it's work. This method may be
+ * called more than once, if the task is invoked more than once. For
+ * example, if target1 and target2 both depend on target3, then running
+ * <em>phing target1 target2</em> will run all tasks in target3 twice.
+ *
+ * Should throw a BuildException if someting goes wrong with the build
+ *
+ * This is abstract here. Must be overloaded by real tasks.
+ *
+ * @access public
+ */
+ abstract function main();
+
+ /**
+ * Returns the location within the buildfile this task occurs. Used
+ * by {@link BuildException} to give detailed error messages.
+ *
+ * @return Location The location object describing the position of this
+ * task within the buildfile.
+ */
+ function getLocation() {
+ return $this->location;
+ }
+
+ /**
+ * Sets the location within the buildfile this task occurs. Called by
+ * the parser to set location information.
+ *
+ * @return object The location object describing the position of this
+ * task within the buildfile.
+ * @access public
+ */
+ function setLocation(Location $location) {
+ $this->location = $location;
+ }
+
+ /**
+ * Returns the wrapper object for runtime configuration
+ *
+ * @return object The wrapper object used by this task
+ * @access public
+ */
+ function getRuntimeConfigurableWrapper() {
+ if ($this->wrapper === null) {
+ $this->wrapper = new RuntimeConfigurable($this, $this->getTaskName());
+ }
+ return $this->wrapper;
+ }
+
+ /**
+ * Sets the wrapper object this task should use for runtime
+ * configurable elements.
+ *
+ * @param object The wrapper object this task should use
+ * @access public
+ */
+ function setRuntimeConfigurableWrapper(RuntimeConfigurable $wrapper) {
+ $this->wrapper = $wrapper;
+ }
+
+ /**
+ * Configure this task if it hasn't been done already.
+ *
+ * @access public
+ */
+ function maybeConfigure() {
+ if ($this->wrapper !== null) {
+ $this->wrapper->maybeConfigure($this->project);
+ }
+ }
+
+ /**
+ * Perfrom this task
+ *
+ * @access public
+ */
+ function perform() {
+
+ try { // try executing task
+ $this->project->fireTaskStarted($this);
+ $this->maybeConfigure();
+ $this->main();
+ $this->project->fireTaskFinished($this, $null=null);
+ } catch (Exception $exc) {
+ if ($exc instanceof BuildException) {
+ if ($exc->getLocation() === null) {
+ $exc->setLocation($this->getLocation());
+ }
+ }
+ $this->project->fireTaskFinished($this, $exc);
+ throw $exc;
+ }
+ }
+}
diff --git a/buildscripts/phing/classes/phing/TaskAdapter.php b/buildscripts/phing/classes/phing/TaskAdapter.php
new file mode 100644
index 00000000..8b84b768
--- /dev/null
+++ b/buildscripts/phing/classes/phing/TaskAdapter.php
@@ -0,0 +1,84 @@
+<?php
+/*
+ * $Id: TaskAdapter.php,v 1.7 2005/10/04 13:52:53 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+
+/**
+ * Use introspection to "adapt" an arbitrary ( not extending Task, but with
+ * similar patterns).
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright © 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.7 $
+ * @package phing
+ */
+class TaskAdapter extends Task {
+
+ /** target object */
+ private $proxy;
+
+ /**
+ * Main entry point.
+ * @return void
+ */
+ function main() {
+
+ if (method_exists($this->proxy, "setProject")) {
+ try { // try to set project
+ $this->proxy->setProject($this->project);
+ } catch (Exception $ex) {
+ $this->log("Error setting project in " . get_class($this->proxy) . PROJECT_MSG_ERR);
+ throw new BuildException($ex);
+ }
+ } else {
+ throw new Exception("Error setting project in class " . get_class($this->proxy));
+ }
+
+ if (method_exists($this->proxy, "main")) {
+ try { //try to call main
+ $this->proxy->main($this->project);
+ } catch (Exception $ex) {
+ $this->log("Error in " . get_class($this->proxy), PROJECT_MSG_ERR);
+ throw new BuildException($ex->getMessage());
+ }
+ } else {
+ throw new BuildException("Your task-like class '" . get_class($this->proxy) ."' does not have a main() method");
+ }
+ }
+
+ /**
+ * Set the target object.
+ * @param object $o
+ * @return void
+ */
+ function setProxy($o) {
+ $this->proxy = $o;
+ }
+
+ /**
+ * Gets the target object.
+ * @return object
+ */
+ function getProxy() {
+ return $this->proxy;
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/TaskContainer.php b/buildscripts/phing/classes/phing/TaskContainer.php
new file mode 100644
index 00000000..2e9eb67a
--- /dev/null
+++ b/buildscripts/phing/classes/phing/TaskContainer.php
@@ -0,0 +1,42 @@
+<?php
+/*
+ * $Id: TaskContainer.php,v 1.5 2005/10/04 19:13:44 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * Abstract interface for objects which can contain tasks (targets)
+ * Used to check if a class can contain tasks (via instanceof)
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright © 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.5 $ $Date: 2005/10/04 19:13:44 $
+ * @access public
+ * @package phing
+ */
+interface TaskContainer {
+
+ /**
+ * Adds a task to this task container. Must be implemented
+ * by derived class
+ *
+ * @param object The task to be added to the container
+ * @access public
+ */
+ function addTask(Task $task);
+}
diff --git a/buildscripts/phing/classes/phing/UnknownElement.php b/buildscripts/phing/classes/phing/UnknownElement.php
new file mode 100644
index 00000000..745130dc
--- /dev/null
+++ b/buildscripts/phing/classes/phing/UnknownElement.php
@@ -0,0 +1,211 @@
+<?php
+/*
+ * $Id: UnknownElement.php,v 1.9 2005/11/08 20:45:59 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+
+/**
+ * Wrapper class that holds all information necessary to create a task
+ * that did not exist when Phing started.
+ *
+ * <em> This has something to do with phing encountering an task XML element
+ * it is not aware of at start time. This is a situation where special steps
+ * need to be taken so that the element is then known.</em>
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.9 $
+ * @package phing
+ */
+class UnknownElement extends Task {
+
+ private $elementName;
+ private $realThing;
+ private $children = array();
+
+ /**
+ * Constructs a UnknownElement object
+ *
+ * @param string The XML element name that is unknown
+ * @access public
+ */
+ function __construct($elementName) {
+ $this->elementName = (string) $elementName;
+ }
+
+ /**
+ * Return the XML element name that this <code>UnnownElement</code>
+ * handles.
+ *
+ * @return string The XML element name that is unknown
+ */
+ public function getTag() {
+ return (string) $this->elementName;
+ }
+
+ /**
+ * Tries to configure the unknown element
+ *
+ * @throws BuildException if the element can not be configured
+ */
+ public function maybeConfigure() {
+
+ $this->realThing = $this->makeObject($this, $this->wrapper);
+ $this->wrapper->setProxy($this->realThing);
+ if ($this->realThing instanceof Task) {
+ $this->realThing->setRuntimeConfigurableWrapper($this->wrapper);
+ }
+
+ $this->handleChildren($this->realThing, $this->wrapper);
+ $this->wrapper->maybeConfigure($this->getProject());
+
+ }
+
+ /**
+ * Called when the real task has been configured for the first time.
+ *
+ * @throws BuildException if the task can not be created
+ */
+ public function main() {
+
+ if ($this->realThing === null) {
+ // plain impossible to get here, maybeConfigure should
+ // have thrown an exception.
+ throw new BuildException("Should not be executing UnknownElement::main() -- task/type: {$this->elementName}");
+ }
+
+ if ($this->realThing instanceof Task) {
+ $this->realThing->main();
+ }
+
+ }
+
+ /**
+ * Add a child element to the unknown element
+ *
+ * @param object The object representing the child element
+ */
+ public function addChild(UnknownElement $child) {
+ $this->children[] = $child;
+ }
+
+ /**
+ * Handle child elemets of the unknown element, if any.
+ *
+ * @param ProjectComponent The parent object the unkown element belongs to
+ * @param object The parent wrapper object
+ */
+ function handleChildren(ProjectComponent $parent, $parentWrapper) {
+
+ if ($parent instanceof TaskAdapter) {
+ $parent = $parent->getProxy();
+ }
+
+ $parentClass = get_class($parent);
+ $ih = IntrospectionHelper::getHelper($parentClass);
+
+ for ($i=0, $childrenCount=count($this->children); $i < $childrenCount; $i++) {
+
+ $childWrapper = $parentWrapper->getChild($i);
+ $child = $this->children[$i];
+ $realChild = null;
+ if ($parent instanceof TaskContainer) {
+ $realChild = $this->makeTask($child, $childWrapper, false);
+ $parent->addTask($realChild);
+ } else {
+ $realChild = $ih->createElement($this->project, $parent, $child->getTag());
+ }
+
+ $childWrapper->setProxy($realChild);
+ if ($realChild instanceof Task) {
+ $realChild->setRuntimeConfigurableWrapper($childWrapper);
+ }
+
+ $child->handleChildren($realChild, $childWrapper);
+ if ($realChild instanceof Task) {
+ $realChild->maybeConfigure();
+ }
+ }
+ }
+
+ /**
+ * Creates a named task or data type. If the real object is a task,
+ * it is configured up to the init() stage.
+ *
+ * @param UnknownElement $ue The unknown element to create the real object for.
+ * Must not be <code>null</code>.
+ * @param RuntimeConfigurable $w Ignored in this implementation.
+ * @return object The Task or DataType represented by the given unknown element.
+ */
+ protected function makeObject(UnknownElement $ue, RuntimeConfigurable $w) {
+ $o = $this->makeTask($ue, $w, true);
+ if ($o === null) {
+ $o = $this->project->createDataType($ue->getTag());
+ }
+ if ($o === null) {
+ throw new BuildException("Could not create task/type: '".$ue->getTag()."'. Make sure that this class has been declared using taskdef / typedef.");
+ }
+ return $o;
+ }
+
+ /**
+ * Create a named task and configure it up to the init() stage.
+ *
+ * @param UnknownElement $ue The unknwon element to create a task from
+ * @param RuntimeConfigurable $w The wrapper object
+ * @param boolean $onTopLevel Whether to treat this task as if it is top-level.
+ * @return Task The freshly created task
+ */
+ protected function makeTask(UnknownElement $ue, RuntimeConfigurable $w, $onTopLevel = false) {
+
+ $task = $this->project->createTask($ue->getTag());
+
+ if ($task === null) {
+ if (!$onTopLevel) {
+ throw new BuildException("Could not create task of type: '".$this->elementName."'. Make sure that this class has been declared using taskdef.");
+ }
+ return null;
+ }
+
+ // used to set the location within the xmlfile so that exceptions can
+ // give detailed messages
+
+ $task->setLocation($this->getLocation());
+ $attrs = $w->getAttributes();
+ if (isset($attrs['id'])) {
+ $this->project->addReference($attrs['id'], $task);
+ }
+
+ // UnknownElement always has an associated target
+ $task->setOwningTarget($this->target);
+
+ $task->init();
+ return $task;
+ }
+
+ /**
+ * Get the name of the task to use in logging messages.
+ *
+ * @return string The task's name
+ */
+ function getTaskName() {
+ return $this->realThing === null ? parent::getTaskName() : $this->realThing->getTaskName();
+ }
+}
diff --git a/buildscripts/phing/classes/phing/filters/BaseFilterReader.php b/buildscripts/phing/classes/phing/filters/BaseFilterReader.php
new file mode 100644
index 00000000..c9f8c619
--- /dev/null
+++ b/buildscripts/phing/classes/phing/filters/BaseFilterReader.php
@@ -0,0 +1,157 @@
+<?php
+
+/*
+ * $Id: BaseFilterReader.php,v 1.8 2004/05/20 02:24:10 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+include_once 'phing/system/io/FilterReader.php';
+include_once 'phing/system/io/StringReader.php';
+
+
+/**
+ * Base class for core filter readers.
+ *
+ * @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
+ * @version $Revision: 1.8 $ $Date: 2004/05/20 02:24:10 $
+ * @access public
+ * @see FilterReader
+ * @package phing.filters
+ */
+class BaseFilterReader extends FilterReader {
+
+ /** Have the parameters passed been interpreted? */
+ protected $initialized = false;
+
+ /** The Phing project this filter is part of. */
+ protected $project = null;
+
+ /**
+ * Constructor used by Phing's introspection mechanism.
+ * The original filter reader is only used for chaining
+ * purposes, never for filtering purposes (and indeed
+ * it would be useless for filtering purposes, as it has
+ * no real data to filter). ChainedReaderHelper uses
+ * this placeholder instance to create a chain of real filters.
+ *
+ * @param Reader $in
+ */
+ function __construct($in = null) {
+ if ($in === null) {
+ $dummy = "";
+ $in = new StringReader($dummy);
+ }
+ parent::__construct($in);
+ }
+
+ /**
+ * Returns the initialized status.
+ *
+ * @return boolean whether or not the filter is initialized
+ */
+ function getInitialized() {
+ return $this->initialized;
+ }
+
+ /**
+ * Sets the initialized status.
+ *
+ * @param boolean $initialized Whether or not the filter is initialized.
+ */
+ function setInitialized($initialized) {
+ $this->initialized = (boolean) $initialized;
+ }
+
+ /**
+ * Sets the project to work with.
+ *
+ * @param object $project The project this filter is part of.
+ * Should not be <code>null</code>.
+ */
+ function setProject(Project $project) {
+ // type check, error must never occur, bad code of it does
+ $this->project = $project;
+ }
+
+ /**
+ * Returns the project this filter is part of.
+ *
+ * @return object The project this filter is part of
+ */
+ function getProject() {
+ return $this->project;
+ }
+
+ /**
+ * Reads characters.
+ *
+ * @param off Offset at which to start storing characters.
+ * @param len Maximum number of characters to read.
+ *
+ * @return Characters read, or -1 if the end of the stream
+ * has been reached
+ *
+ * @throws IOException If an I/O error occurs
+ */
+ function read($len = null) {
+ return $this->in->read($len);
+ }
+
+ /**
+ * Reads a line of text ending with '\n' (or until the end of the stream).
+ * The returned String retains the '\n'.
+ *
+ * @return the line read, or <code>null</code> if the end of the
+ stream has already been reached
+ *
+ * @throws IOException if the underlying reader throws one during
+ * reading
+ */
+ function readLine() {
+ $line = null;
+
+ while ( ($ch = $this->in->read(1)) !== -1 ) {
+ $line .= $ch;
+ if ( $ch === "\n" )
+ break;
+ }
+
+ return $line;
+ }
+
+ /**
+ * Returns whether the end of file has been reached with input stream.
+ * @return boolean
+ */
+ function eof() {
+ return $this->in->eof();
+ }
+
+ /**
+ * Convenience method to support logging in filters.
+ * @param string $msg Message to log.
+ * @param int $level Priority level.
+ */
+ function log($msg, $level = PROJECT_MSG_INFO) {
+ if ($this->project !== null) {
+ $this->project->log("[filter:".get_class($this)."] ".$msg, $level);
+ }
+ }
+}
+
+?>
diff --git a/buildscripts/phing/classes/phing/filters/BaseParamFilterReader.php b/buildscripts/phing/classes/phing/filters/BaseParamFilterReader.php
new file mode 100644
index 00000000..3d767b40
--- /dev/null
+++ b/buildscripts/phing/classes/phing/filters/BaseParamFilterReader.php
@@ -0,0 +1,69 @@
+<?php
+
+/*
+ * $Id: BaseParamFilterReader.php,v 1.5 2005/02/27 20:52:08 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+include_once 'phing/filters/BaseFilterReader.php';
+include_once 'phing/types/Parameterizable.php';
+include_once 'phing/types/Parameter.php';
+
+/**
+ * Base class for core filter readers.
+ *
+ * @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
+ * @copyright © 2003 seasonfive. All rights reserved
+ * @version $Revision: 1.5 $ $Date: 2005/02/27 20:52:08 $
+ * @access public
+ * @see FilterReader
+ * @package phing.filters
+ */
+class BaseParamFilterReader extends BaseFilterReader implements Parameterizable {
+
+ /** The passed in parameter array. */
+ protected $_parameters = array();
+
+ /*
+ * Sets the parameters used by this filter, and sets
+ * the filter to an uninitialized status.
+ *
+ * @param array Array of parameters to be used by this filter.
+ * Should not be <code>null</code>.
+ */
+ function setParameters($parameters) {
+ // type check, error must never occur, bad code of it does
+ if ( !is_array($parameters) ) {
+ throw new Exception("Expected parameters array got something else");
+ }
+
+ $this->_parameters = $parameters;
+ $this->setInitialized(false);
+ }
+
+ /*
+ * Returns the parameters to be used by this filter.
+ *
+ * @return the parameters to be used by this filter
+ */
+ function &getParameters() {
+ return $this->_parameters;
+ }
+}
+
+?>
diff --git a/buildscripts/phing/classes/phing/filters/ChainableReader.php b/buildscripts/phing/classes/phing/filters/ChainableReader.php
new file mode 100644
index 00000000..c7de07c4
--- /dev/null
+++ b/buildscripts/phing/classes/phing/filters/ChainableReader.php
@@ -0,0 +1,42 @@
+<?php
+
+/*
+ * $Id: ChainableReader.php,v 1.2 2003/11/19 05:48:27 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+/**
+ * Interface indicating that a reader may be chained to another one.
+ *
+ * @author Magesh Umasankar
+ */
+interface ChainableReader {
+
+ /**
+ * Returns a reader with the same configuration as this one,
+ * but filtering input from the specified reader.
+ *
+ * @param Reader $rdr the reader which the returned reader should be filtering
+ *
+ * @return Reader A reader with the same configuration as this one, but
+ * filtering input from the specified reader
+ */
+ public function chain(Reader $rdr);
+}
+
+?>
diff --git a/buildscripts/phing/classes/phing/filters/ExpandProperties.php b/buildscripts/phing/classes/phing/filters/ExpandProperties.php
new file mode 100644
index 00000000..dfd98cc8
--- /dev/null
+++ b/buildscripts/phing/classes/phing/filters/ExpandProperties.php
@@ -0,0 +1,82 @@
+<?php
+
+/*
+ * $Id: ExpandProperties.php,v 1.6 2004/07/14 17:14:15 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+require_once 'phing/filters/BaseFilterReader.php';
+include_once 'phing/filters/ChainableReader.php';
+
+/**
+ * Expands Phing Properties, if any, in the data.
+ * <p>
+ * Example:<br>
+ * <pre><expandproperties/></pre>
+ * Or:
+ * <pre><filterreader classname="phing.filters.ExpandProperties'/></pre>
+ *
+ * @author Yannick Lecaillez <yl@seasonfive.com>
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.6 $
+ * @see BaseFilterReader
+ * @package phing.filters
+ */
+class ExpandProperties extends BaseFilterReader implements ChainableReader {
+
+ /**
+ * Returns the filtered stream.
+ * The original stream is first read in fully, and the Phing properties are expanded.
+ *
+ * @return mixed the filtered stream, or -1 if the end of the resulting stream has been reached.
+ *
+ * @exception IOException if the underlying stream throws an IOException
+ * during reading
+ */
+ function read($len = null) {
+
+ $buffer = $this->in->read($len);
+
+ if($buffer === -1) {
+ return -1;
+ }
+
+ $project = $this->getProject();
+ $buffer = ProjectConfigurator::replaceProperties($project, $buffer, $project->getProperties());
+
+ return $buffer;
+ }
+
+ /**
+ * Creates a new ExpandProperties filter using the passed in
+ * Reader for instantiation.
+ *
+ * @param object A Reader object providing the underlying stream.
+ * Must not be <code>null</code>.
+ *
+ * @return object A new filter based on this configuration, but filtering
+ * the specified reader
+ */
+ function chain(Reader $reader) {
+ $newFilter = new ExpandProperties($reader);
+ $newFilter->setProject($this->getProject());
+ return $newFilter;
+ }
+}
+
+?>
diff --git a/buildscripts/phing/classes/phing/filters/HeadFilter.php b/buildscripts/phing/classes/phing/filters/HeadFilter.php
new file mode 100644
index 00000000..84673b4a
--- /dev/null
+++ b/buildscripts/phing/classes/phing/filters/HeadFilter.php
@@ -0,0 +1,161 @@
+<?php
+
+/*
+ * $Id: HeadFilter.php,v 1.6 2004/03/15 14:45:06 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+include_once 'phing/filters/BaseParamFilterReader.php';
+include_once 'phing/filters/ChainableReader.php';
+
+/**
+ * Reads the first <code>n</code> lines of a stream.
+ * (Default is first 10 lines.)
+ * <p>
+ * Example:
+ * <pre><headfilter lines="3"/></pre>
+ * Or:
+ * <pre><filterreader classname="phing.filters.HeadFilter">
+ * <param name="lines" value="3"/>
+ * </filterreader></pre>
+ *
+ * @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
+ * @author hans lellelid, hans@velum.net
+ * @version $Revision: 1.6 $ $Date: 2004/03/15 14:45:06 $
+ * @access public
+ * @see FilterReader
+ * @package phing.filters
+ */
+class HeadFilter extends BaseParamFilterReader implements ChainableReader {
+
+ /**
+ * Parameter name for the number of lines to be returned.
+ */
+ const LINES_KEY = "lines";
+
+ /**
+ * Number of lines currently read in.
+ * @var integer
+ */
+ private $_linesRead = 0;
+
+ /**
+ * Number of lines to be returned in the filtered stream.
+ * @var integer
+ */
+ private $_lines = 10;
+
+ /**
+ * Returns first n lines of stream.
+ * @return the resulting stream, or -1
+ * if the end of the resulting stream has been reached
+ *
+ * @exception IOException if the underlying stream throws an IOException
+ * during reading
+ */
+ function read($len = null) {
+
+ if ( !$this->getInitialized() ) {
+ $this->_initialize();
+ $this->setInitialized(true);
+ }
+
+ // note, if buffer contains fewer lines than
+ // $this->_lines this code will not work.
+
+ if($this->_linesRead < $this->_lines) {
+
+ $buffer = $this->in->read($len);
+
+ if($buffer === -1) {
+ return -1;
+ }
+
+ // now grab first X lines from buffer
+
+ $lines = explode("\n", $buffer);
+
+ $linesCount = count($lines);
+
+ // must account for possibility that the num lines requested could
+ // involve more than one buffer read.
+ $len = ($linesCount > $this->_lines ? $this->_lines - $this->_linesRead : $linesCount);
+ $filtered_buffer = implode("\n", array_slice($lines, 0, $len) );
+ $this->_linesRead += $len;
+
+ return $filtered_buffer;
+
+ }
+
+ return -1; // EOF, since the file is "finished" as far as subsequent filters are concerned.
+ }
+
+ /**
+ * Sets the number of lines to be returned in the filtered stream.
+ *
+ * @param integer $lines the number of lines to be returned in the filtered stream.
+ */
+ function setLines($lines) {
+ $this->_lines = (int) $lines;
+ }
+
+ /**
+ * Returns the number of lines to be returned in the filtered stream.
+ *
+ * @return integer The number of lines to be returned in the filtered stream.
+ */
+ function getLines() {
+ return $this->_lines;
+ }
+
+ /**
+ * Creates a new HeadFilter using the passed in
+ * Reader for instantiation.
+ *
+ * @param object A Reader object providing the underlying stream.
+ * Must not be <code>null</code>.
+ *
+ * @return object A new filter based on this configuration, but filtering
+ * the specified reader.
+ */
+ function chain(Reader $reader) {
+ $newFilter = new HeadFilter($reader);
+ $newFilter->setLines($this->getLines());
+ $newFilter->setInitialized(true);
+ $newFilter->setProject($this->getProject());
+ return $newFilter;
+ }
+
+ /**
+ * Scans the parameters list for the "lines" parameter and uses
+ * it to set the number of lines to be returned in the filtered stream.
+ */
+ private function _initialize() {
+ $params = $this->getParameters();
+ if ( $params !== null ) {
+ for($i = 0, $_i=count($params) ; $i < $_i; $i++) {
+ if ( self::LINES_KEY == $params[$i]->getName() ) {
+ $this->_lines = (int) $params[$i]->getValue();
+ break;
+ }
+ }
+ }
+ }
+}
+
+?>
diff --git a/buildscripts/phing/classes/phing/filters/LineContains.php b/buildscripts/phing/classes/phing/filters/LineContains.php
new file mode 100644
index 00000000..8f3136b7
--- /dev/null
+++ b/buildscripts/phing/classes/phing/filters/LineContains.php
@@ -0,0 +1,258 @@
+<?php
+
+/*
+ * $Id: LineContains.php,v 1.11 2005/02/27 20:52:08 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/filters/BaseParamFilterReader.php';
+include_once 'phing/filters/BaseFilterReader.php';
+include_once 'phing/filters/ChainableReader.php';
+
+/**
+ * Filter which includes only those lines that contain all the user-specified
+ * strings.
+ *
+ * Example:
+ *
+ * <pre><linecontains>
+ * <contains value="foo">
+ * <contains value="bar">
+ * </linecontains></pre>
+ *
+ * Or:
+ *
+ * <pre><filterreader classname="phing.filters.LineContains">
+ * <param type="contains" value="foo"/>
+ * <param type="contains" value="bar"/>
+ * </filterreader></pre>
+ *
+ * This will include only those lines that contain <code>foo</code> and
+ * <code>bar</code>.
+ *
+ * @author Yannick Lecaillez <yl@seasonfive.com>
+ * @author Hans Lellelid <hans@velum.net>
+ * @version $Revision: 1.11 $
+ * @see PhingFilterReader
+ * @package phing.filters
+*/
+class LineContains extends BaseParamFilterReader implements ChainableReader {
+
+ /**
+ * The parameter name for the string to match on.
+ * @var string
+ */
+ const CONTAINS_KEY = "contains";
+
+ /**
+ * Array of Contains objects.
+ * @var array
+ */
+ private $_contains = array();
+
+ /**
+ * [Deprecated]
+ * @var string
+ */
+ private $_line = null;
+
+ /**
+ * Returns all lines in a buffer that contain specified strings.
+ * @return mixed buffer, -1 on EOF
+ */
+ function read($len = null) {
+ if ( !$this->getInitialized() ) {
+ $this->_initialize();
+ $this->setInitialized(true);
+ }
+
+ $buffer = $this->in->read($len);
+
+ if ($buffer === -1) {
+ return -1;
+ }
+
+ $lines = explode("\n", $buffer);
+ $matched = array();
+ $containsSize = count($this->_contains);
+
+ foreach($lines as $line) {
+ for($i = 0 ; $i < $containsSize ; $i++) {
+ $containsStr = $this->_contains[$i]->getValue();
+ if ( strstr($line, $containsStr) === false ) {
+ $line = null;
+ break;
+ }
+ }
+ if($line !== null) {
+ $matched[] = $line;
+ }
+ }
+ $filtered_buffer = implode("\n", $matched);
+ return $filtered_buffer;
+ }
+
+ /**
+ * [Deprecated. For reference only, used to be read() method.]
+ * Returns the next character in the filtered stream, only including
+ * lines from the original stream which contain all of the specified words.
+ *
+ * @return the next character in the resulting stream, or -1
+ * if the end of the resulting stream has been reached
+ *
+ * @exception IOException if the underlying stream throws an IOException
+ * during reading
+ */
+ function readChar() {
+ if ( !$this->getInitialized() ) {
+ $this->_initialize();
+ $this->setInitialized(true);
+ }
+
+ $ch = -1;
+
+ if ( $this->_line !== null ) {
+ $ch = substr($this->_line, 0, 1);
+ if ( strlen($this->_line) === 1 )
+ $this->_line = null;
+ else
+ $this->_line = substr($this->_line, 1);
+ } else {
+ $this->_line = $this->readLine();
+ if ( $this->_line === null ) {
+ $ch = -1;
+ } else {
+ $containsSize = count($this->_contains);
+ for($i = 0 ; $i < $containsSize ; $i++) {
+ $containsStr = $this->_contains[$i]->getValue();
+ if ( strstr($this->_line, $containsStr) === false ) {
+ $this->_line = null;
+ break;
+ }
+ }
+ return $this->readChar();
+ }
+ }
+
+ return $ch;
+ }
+
+ /**
+ * Adds a <code><contains></code> nested element.
+ *
+ * @return Contains The <code>contains</code> element added.
+ * Must not be <code>null</code>.
+ */
+ function createContains() {
+ $num = array_push($this->_contains, new Contains());
+ return $this->_contains[$num-1];
+ }
+
+ /**
+ * Sets the array of words which must be contained within a line read
+ * from the original stream in order for it to match this filter.
+ *
+ * @param array $contains An array of words which must be contained
+ * within a line in order for it to match in this filter.
+ * Must not be <code>null<code>.
+ */
+ function setContains($contains) {
+ // type check, error must never occur, bad code of it does
+ if ( !is_array($contains) ) {
+ throw new Exception("Excpected array got something else");
+ }
+
+ $this->_contains = $contains;
+ }
+
+ /**
+ * Returns the vector of words which must be contained within a line read
+ * from the original stream in order for it to match this filter.
+ *
+ * @return array The array of words which must be contained within a line read
+ * from the original stream in order for it to match this filter. The
+ * returned object is "live" - in other words, changes made to the
+ * returned object are mirrored in the filter.
+ */
+ function getContains() {
+ return $this->_contains;
+ }
+
+ /**
+ * Creates a new LineContains using the passed in
+ * Reader for instantiation.
+ *
+ * @param object A Reader object providing the underlying stream.
+ * Must not be <code>null</code>.
+ *
+ * @return object A new filter based on this configuration, but filtering
+ * the specified reader
+ */
+ function chain(Reader $reader) {
+ $newFilter = new LineContains($reader);
+ $newFilter->setContains($this->getContains());
+ $newFilter->setInitialized(true);
+ $newFilter->setProject($this->getProject());
+ return $newFilter;
+ }
+
+ /**
+ * Parses the parameters to add user-defined contains strings.
+ */
+ private function _initialize() {
+ $params = $this->getParameters();
+ if ( $params !== null ) {
+ foreach($params as $param) {
+ if ( self::CONTAINS_KEY == $param->getType() ) {
+ $cont = new Contains();
+ $cont->setValue($param->getValue());
+ array_push($this->_contains, $cont);
+ break; // because we only support a single contains
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Holds a contains element.
+ */
+class Contains {
+
+ /**
+ * @var string
+ */
+ private $_value;
+
+ /**
+ * Set 'contains' value.
+ * @param string $contains
+ */
+ function setValue($contains) {
+ $this->_value = (string) $contains;
+ }
+
+ /**
+ * Returns 'contains' value.
+ * @return string
+ */
+ function getValue() {
+ return $this->_value;
+ }
+}
+?>
diff --git a/buildscripts/phing/classes/phing/filters/LineContainsRegexp.php b/buildscripts/phing/classes/phing/filters/LineContainsRegexp.php
new file mode 100644
index 00000000..dcbb532c
--- /dev/null
+++ b/buildscripts/phing/classes/phing/filters/LineContainsRegexp.php
@@ -0,0 +1,179 @@
+<?php
+/*
+ * $Id: LineContainsRegexp.php,v 1.8 2005/02/27 20:52:08 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+include_once 'phing/filters/BaseParamFilterReader.php';
+include_once 'phing/types/RegularExpression.php';
+include_once 'phing/filters/ChainableReader.php';
+
+/**
+ * Filter which includes only those lines that contain the user-specified
+ * regular expression matching strings.
+ *
+ * Example:
+ * <pre><linecontainsregexp>
+ * <regexp pattern="foo*">
+ * </linecontainsregexp></pre>
+ *
+ * Or:
+ *
+ * <pre><filterreader classname="phing.filters.LineContainsRegExp">
+ * <param type="regexp" value="foo*"/>
+ * </filterreader></pre>
+ *
+ * This will fetch all those lines that contain the pattern <code>foo</code>
+ *
+ * @author Yannick Lecaillez <yl@seasonfive.com>
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.8 $
+ * @see FilterReader
+ * @package phing.filters
+ */
+class LineContainsRegexp extends BaseParamFilterReader implements ChainableReader {
+
+ /**
+ * Parameter name for regular expression.
+ * @var string
+ */
+ const REGEXP_KEY = "regexp";
+
+ /**
+ * Regular expressions that are applied against lines.
+ * @var array
+ */
+ private $_regexps = array();
+
+ /**
+ * Returns all lines in a buffer that contain specified strings.
+ * @return mixed buffer, -1 on EOF
+ */
+ function read($len = null) {
+
+ if ( !$this->getInitialized() ) {
+ $this->_initialize();
+ $this->setInitialized(true);
+ }
+
+ $buffer = $this->in->read($len);
+
+ if ($buffer === -1) {
+ return -1;
+ }
+
+ $lines = explode("\n", $buffer);
+ $matched = array();
+
+ $regexpsSize = count($this->_regexps);
+ foreach($lines as $line) {
+ for($i = 0 ; $i<$regexpsSize ; $i++) {
+ $regexp = $this->_regexps[$i];
+ $re = $regexp->getRegexp($this->getProject());
+ $matches = $re->matches($line);
+ if ( !$matches ) {
+ $line = null;
+ break;
+ }
+ }
+ if($line !== null) {
+ $matched[] = $line;
+ }
+ }
+ $filtered_buffer = implode("\n", $matched);
+ return $filtered_buffer;
+ }
+
+ /**
+ * Adds a <code>regexp</code> element.
+ *
+ * @return object regExp The <code>regexp</code> element added.
+ */
+ function createRegexp() {
+ $num = array_push($this->_regexps, new RegularExpression());
+ return $this->_regexps[$num-1];
+ }
+
+ /**
+ * Sets the vector of regular expressions which must be contained within
+ * a line read from the original stream in order for it to match this
+ * filter.
+ *
+ * @param regexps An array of regular expressions which must be contained
+ * within a line in order for it to match in this filter. Must not be
+ * <code>null</code>.
+ */
+ function setRegexps($regexps) {
+ // type check, error must never occur, bad code of it does
+ if ( !is_array($regexps) ) {
+ throw new Exception("Excpected an 'array', got something else");
+ }
+ $this->_regexps = $regexps;
+ }
+
+ /**
+ * Returns the array of regular expressions which must be contained within
+ * a line read from the original stream in order for it to match this
+ * filter.
+ *
+ * @return array The array of regular expressions which must be contained within
+ * a line read from the original stream in order for it to match this
+ * filter. The returned object is "live" - in other words, changes made to
+ * the returned object are mirrored in the filter.
+ */
+ function getRegexps() {
+ return $this->_regexps;
+ }
+
+ /**
+ * Creates a new LineContainsRegExp using the passed in
+ * Reader for instantiation.
+ *
+ * @param object A Reader object providing the underlying stream.
+ * Must not be <code>null</code>.
+ *
+ * @return object A new filter based on this configuration, but filtering
+ * the specified reader
+ */
+ function chain(Reader $reader) {
+ $newFilter = new LineContainsRegExp($reader);
+ $newFilter->setRegexps($this->getRegexps());
+ $newFilter->setInitialized(true);
+ $newFilter->setProject($this->getProject());
+ return $newFilter;
+ }
+
+ /**
+ * Parses parameters to add user defined regular expressions.
+ */
+ private function _initialize() {
+ $params = $this->getParameters();
+ if ( $params !== null ) {
+ for($i = 0 ; $i<count($params) ; $i++) {
+ if ( self::REGEXP_KEY === $params[$i]->getType() ) {
+ $pattern = $params[$i]->getValue();
+ $regexp = new RegularExpression();
+ $regexp->setPattern($pattern);
+ array_push($this->_regexps, $regexp);
+ }
+ }
+ }
+ }
+}
+
+?>
diff --git a/buildscripts/phing/classes/phing/filters/PrefixLines.php b/buildscripts/phing/classes/phing/filters/PrefixLines.php
new file mode 100644
index 00000000..a5580f87
--- /dev/null
+++ b/buildscripts/phing/classes/phing/filters/PrefixLines.php
@@ -0,0 +1,142 @@
+<?php
+
+/*
+ * $Id: PrefixLines.php,v 1.6 2004/03/15 14:45:06 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+include_once 'phing/filters/BaseParamFilterReader.php';
+include_once 'phing/filters/ChainableReader.php';
+
+/**
+ * Attaches a prefix to every line.
+ *
+ * Example:
+ * <pre><prefixlines prefix="Foo"/></pre>
+ *
+ * Or:
+ *
+ * <pre><filterreader classname="phing.filters.PrefixLines">
+ * <param name="prefix" value="Foo"/>
+ * </filterreader></pre>
+ *
+ * @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
+ * @author hans lellelid, hans@velum.net
+ * @version $Revision: 1.6 $ $Date: 2004/03/15 14:45:06 $
+ * @access public
+ * @see FilterReader
+ * @package phing.filters
+*/
+class PrefixLines extends BaseParamFilterReader implements ChainableReader {
+
+ /**
+ * Parameter name for the prefix.
+ * @var string
+ */
+ const PREFIX_KEY = "lines";
+
+ /**
+ * The prefix to be used.
+ * @var string
+ */
+ private $_prefix = null;
+
+ /**
+ * Adds a prefix to each line of input stream and returns resulting stream.
+ *
+ * @return mixed buffer, -1 on EOF
+ */
+ function read($len = null) {
+ if ( !$this->getInitialized() ) {
+ $this->_initialize();
+ $this->setInitialized(true);
+ }
+
+ $buffer = $this->in->read($len);
+
+ if ($buffer === -1) {
+ return -1;
+ }
+
+ $lines = explode("\n", $buffer);
+ $filtered = array();
+
+ foreach($lines as $line) {
+ $line = $this->_prefix . $line;
+ $filtered[] = $line;
+ }
+
+ $filtered_buffer = implode("\n", $filtered);
+ return $filtered_buffer;
+ }
+
+ /**
+ * Sets the prefix to add at the start of each input line.
+ *
+ * @param string $prefix The prefix to add at the start of each input line.
+ * May be <code>null</code>, in which case no prefix
+ * is added.
+ */
+ function setPrefix($prefix) {
+ $this->_prefix = (string) $prefix;
+ }
+
+ /**
+ * Returns the prefix which will be added at the start of each input line.
+ *
+ * @return string The prefix which will be added at the start of each input line
+ */
+ function getPrefix() {
+ return $this->_prefix;
+ }
+
+ /**
+ * Creates a new PrefixLines filter using the passed in
+ * Reader for instantiation.
+ *
+ * @param object A Reader object providing the underlying stream.
+ * Must not be <code>null</code>.
+ *
+ * @return object A new filter based on this configuration, but filtering
+ * the specified reader
+ */
+ function chain(Reader $reader) {
+ $newFilter = new PrefixLines($reader);
+ $newFilter->setPrefix($this->getPrefix());
+ $newFilter->setInitialized(true);
+ $newFilter->setProject($this->getProject());
+ return $newFilter;
+ }
+
+ /**
+ * Initializes the prefix if it is available from the parameters.
+ */
+ private function _initialize() {
+ $params = $this->getParameters();
+ if ( $params !== null ) {
+ for($i = 0, $_i=count($params) ; $i < $_i ; $i++) {
+ if ( self::PREFIX_KEY == $params[$i]->getName() ) {
+ $this->_prefix = (string) $params[$i]->getValue();
+ break;
+ }
+ }
+ }
+ }
+}
+
+?>
diff --git a/buildscripts/phing/classes/phing/filters/ReplaceRegexp.php b/buildscripts/phing/classes/phing/filters/ReplaceRegexp.php
new file mode 100644
index 00000000..3c5592e8
--- /dev/null
+++ b/buildscripts/phing/classes/phing/filters/ReplaceRegexp.php
@@ -0,0 +1,129 @@
+<?php
+
+/*
+ * $Id: ReplaceRegexp.php,v 1.5 2003/12/24 12:38:39 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+require_once 'phing/filters/BaseFilterReader.php';
+include_once 'phing/filters/ChainableReader.php';
+include_once 'phing/types/RegularExpression.php';
+
+/**
+ * Performs a regexp find/replace on stream.
+ * <p>
+ * Example:<br>
+ * <pre>
+ * <replaceregexp>
+ * <regexp pattern="\r\n" replace="\n"/>
+ * <regexp pattern="(\w+)\.xml" replace="\1.php" ignoreCase="true"/>
+ * </replaceregexp>
+ * </pre>
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.5 $
+ * @package phing.filters
+ */
+class ReplaceRegexp extends BaseFilterReader implements ChainableReader {
+
+ /**
+ * @var array RegularExpression[]
+ */
+ private $regexps = array();
+
+ /**
+ * Creator method handles nested <regexp> tags.
+ * @return RegularExpression
+ */
+ function createRegexp() {
+ $num = array_push($this->regexps, new RegularExpression());
+ return $this->regexps[$num-1];
+ }
+
+ /**
+ * Sets the current regexps.
+ * (Used when, e.g., cloning/chaining the method.)
+ * @param array RegularExpression[]
+ */
+ function setRegexps($regexps) {
+ $this->regexps = $regexps;
+ }
+
+ /**
+ * Gets the current regexps.
+ * (Used when, e.g., cloning/chaining the method.)
+ * @return array RegularExpression[]
+ */
+ function getRegexps() {
+ return $this->regexps;
+ }
+
+ /**
+ * Returns the filtered stream.
+ * The original stream is first read in fully, and the regex replace is performed.
+ *
+ * @param int $len Required $len for Reader compliance.
+ *
+ * @return mixed The filtered stream, or -1 if the end of the resulting stream has been reached.
+ *
+ * @exception IOException if the underlying stream throws an IOException
+ * during reading
+ */
+ function read($len = null) {
+
+ $buffer = $this->in->read($len);
+
+ if($buffer === -1) {
+ return -1;
+ }
+
+ // perform regex replace here ...
+ foreach($this->regexps as $exptype) {
+ $regexp = $exptype->getRegexp($this->project);
+ try {
+ $buffer = $regexp->replace($buffer);
+ $this->log("Performing regexp replace: /".$regexp->getPattern()."/".$regexp->getReplace()."/g".($regexp->getIgnoreCase() ? 'i' : ''), PROJECT_MSG_VERBOSE);
+ } catch (Exception $e) {
+ // perhaps mismatch in params (e.g. no replace or pattern specified)
+ $this->log("Error performing regexp replace: " . $e->getMessage(), PROJECT_MSG_WARN);
+ }
+ }
+
+ return $buffer;
+ }
+
+ /**
+ * Creates a new ReplaceRegExp filter using the passed in
+ * Reader for instantiation.
+ *
+ * @param Reader $reader A Reader object providing the underlying stream.
+ * Must not be <code>null</code>.
+ *
+ * @return ReplaceRegExp A new filter based on this configuration, but filtering
+ * the specified reader
+ */
+ function chain(Reader $reader) {
+ $newFilter = new ReplaceRegExp($reader);
+ $newFilter->setProject($this->getProject());
+ $newFilter->setRegexps($this->getRegexps());
+ return $newFilter;
+ }
+
+}
+
+?>
diff --git a/buildscripts/phing/classes/phing/filters/ReplaceTokens.php b/buildscripts/phing/classes/phing/filters/ReplaceTokens.php
new file mode 100644
index 00000000..999f734f
--- /dev/null
+++ b/buildscripts/phing/classes/phing/filters/ReplaceTokens.php
@@ -0,0 +1,415 @@
+<?php
+
+/*
+ * $Id: ReplaceTokens.php,v 1.14 2005/06/16 15:09:10 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+include_once 'phing/filters/BaseParamFilterReader.php';
+include_once 'phing/types/TokenSource.php';
+include_once 'phing/filters/ChainableReader.php';
+
+/*
+ * Replaces tokens in the original input with user-supplied values.
+ *
+ * Example:
+ *
+ * <pre><replacetokens begintoken="#" endtoken="#">;
+ * <token key="DATE" value="${TODAY}"/>
+ * </replacetokens></pre>
+ *
+ * Or:
+ *
+ * <pre><filterreader classname="phing.filters.ReplaceTokens">
+ * <param type="tokenchar" name="begintoken" value="#"/>
+ * <param type="tokenchar" name="endtoken" value="#"/>
+ * <param type="token" name="DATE" value="${TODAY}"/>
+ * </filterreader></pre>
+ *
+ * @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
+ * @author hans lellelid, hans@velum.net
+ * @version $Revision: 1.14 $ $Date: 2005/06/16 15:09:10 $
+ * @access public
+ * @see BaseParamFilterReader
+ * @package phing.filters
+ */
+class ReplaceTokens extends BaseParamFilterReader implements ChainableReader {
+
+ /**
+ * Default "begin token" character.
+ * @var string
+ */
+ const DEFAULT_BEGIN_TOKEN = "@";
+
+ /**
+ * Default "end token" character.
+ * @var string
+ */
+ const DEFAULT_END_TOKEN = "@";
+
+ /**
+ * [Deprecated] Data that must be read from, if not null.
+ * @var string
+ */
+ private $_queuedData = null;
+
+ /**
+ * Array to hold the replacee-replacer pairs (String to String).
+ * @var array
+ */
+ private $_tokens = array();
+
+ /**
+ * Array to hold the token sources that make tokens from
+ * different sources available
+ * @var array
+ */
+ private $_tokensources = array();
+
+ /**
+ * Array holding all tokens given directly to the Filter and
+ * those passed via a TokenSource.
+ * @var array
+ */
+ private $_alltokens = null;
+
+ /**
+ * Character marking the beginning of a token.
+ * @var string
+ */
+ private $_beginToken = "@"; // self::DEFAULT_BEGIN_TOKEN;
+
+ /**
+ * Character marking the end of a token.
+ * @var string
+ */
+ private $_endToken = "@"; //self::DEFAULT_END_TOKEN;
+
+ /**
+ * Performs lookup on key and returns appropriate replacement string.
+ * @param array $matches Array of 1 el containing key to search for.
+ * @return string Text with which to replace key or value of key if none is found.
+ * @access private
+ */
+ private function replaceTokenCallback($matches) {
+
+ $key = $matches[1];
+
+ /* Get tokens from tokensource and merge them with the
+ * tokens given directly via build file. This should be
+ * done a bit more elegantly
+ */
+ if ($this->_alltokens === null) {
+ $this->_alltokens = array();
+
+ $count = count($this->_tokensources);
+ for ($i = 0; $i < $count; $i++) {
+ $source = $this->_tokensources[$i];
+ $this->_alltokens = array_merge($this->_alltokens, $source->getTokens());
+ }
+
+
+ $this->_alltokens = array_merge($this->_tokens, $this->_alltokens);
+ }
+
+ $tokens = $this->_alltokens;
+
+ $replaceWith = null;
+ $count = count($tokens);
+
+ for ($i = 0; $i < $count; $i++) {
+ if ($tokens[$i]->getKey() === $key) {
+ $replaceWith = $tokens[$i]->getValue();
+ }
+ }
+
+ if ($replaceWith === null) {
+ $replaceWith = $this->_beginToken . $key . $this->_endToken;
+ $this->log("No token defined for key \"".$this->_beginToken . $key . $this->_endToken."\"");
+ } else {
+ $this->log("Replaced \"".$this->_beginToken . $key . $this->_endToken ."\" with \"".$replaceWith."\"");
+ }
+
+ return $replaceWith;
+ }
+
+ /**
+ * Returns stream with tokens having been replaced with appropriate values.
+ * If a replacement value is not found for a token, the token is left in the stream.
+ *
+ * @return mixed filtered stream, -1 on EOF.
+ */
+ function read($len = null) {
+ if ( !$this->getInitialized() ) {
+ $this->_initialize();
+ $this->setInitialized(true);
+ }
+
+ // read from next filter up the chain
+ $buffer = $this->in->read($len);
+
+ if($buffer === -1) {
+ return -1;
+ }
+
+ // filter buffer
+ $buffer = preg_replace_callback(
+ "/".preg_quote($this->_beginToken)."([\w\.\-:]+?)".preg_quote($this->_endToken)."/",
+ array($this, 'replaceTokenCallback'), $buffer);
+
+ return $buffer;
+ }
+
+ /**
+ * Sets the "begin token" character.
+ *
+ * @param string $beginToken the character used to denote the beginning of a token.
+ */
+ function setBeginToken($beginToken) {
+ $this->_beginToken = (string) $beginToken;
+ }
+
+ /**
+ * Returns the "begin token" character.
+ *
+ * @return string The character used to denote the beginning of a token.
+ */
+ function getBeginToken() {
+ return $this->_beginToken;
+ }
+
+ /**
+ * Sets the "end token" character.
+ *
+ * @param string $endToken the character used to denote the end of a token
+ */
+ function setEndToken($endToken) {
+ $this->_endToken = (string) $endToken;
+ }
+
+ /**
+ * Returns the "end token" character.
+ *
+ * @return the character used to denote the beginning of a token
+ */
+ function getEndToken() {
+ return $this->_endToken;
+ }
+
+ /**
+ * Adds a token element to the map of tokens to replace.
+ *
+ * @return object The token added to the map of replacements.
+ * Must not be <code>null</code>.
+ */
+ function createToken() {
+ $num = array_push($this->_tokens, new Token());
+ return $this->_tokens[$num-1];
+ }
+
+ /**
+ * Adds a token source to the sources of this filter.
+ *
+ * @return object A Reference to the source just added.
+ */
+ function createTokensource() {
+ $num = array_push($this->_tokensources, new TokenSource());
+ return $this->_tokensources[$num-1];
+ }
+
+ /**
+ * Sets the map of tokens to replace.
+ * ; used by ReplaceTokens::chain()
+ *
+ * @param array A map (String->String) of token keys to replacement
+ * values. Must not be <code>null</code>.
+ */
+ function setTokens($tokens) {
+ // type check, error must never occur, bad code of it does
+ if ( !is_array($tokens) ) {
+ throw new Exception("Excpected 'array', got something else");
+ }
+
+ $this->_tokens = $tokens;
+ }
+
+ /**
+ * Returns the map of tokens which will be replaced.
+ * ; used by ReplaceTokens::chain()
+ *
+ * @return array A map (String->String) of token keys to replacement values.
+ */
+ function getTokens() {
+ return $this->_tokens;
+ }
+
+ /**
+ * Sets the tokensources to use; used by ReplaceTokens::chain()
+ *
+ * @param array An array of token sources.
+ */
+ function setTokensources($sources) {
+ // type check
+ if ( !is_array($sources)) {
+ throw new Exception("Exspected 'array', got something else");
+ }
+ $this->_tokensources = $sources;
+ }
+
+ /**
+ * Returns the token sources used by this filter; used by ReplaceTokens::chain()
+ *
+ * @return array
+ */
+ function getTokensources() {
+ return $this->_tokensources;
+ }
+
+ /**
+ * Creates a new ReplaceTokens using the passed in
+ * Reader for instantiation.
+ *
+ * @param object A Reader object providing the underlying stream.
+ * Must not be <code>null</code>.
+ *
+ * @return object A new filter based on this configuration, but filtering
+ * the specified reader
+ */
+ function chain(Reader $reader) {
+ $newFilter = new ReplaceTokens($reader);
+ $newFilter->setProject($this->getProject());
+ $newFilter->setBeginToken($this->getBeginToken());
+ $newFilter->setEndToken($this->getEndToken());
+ $newFilter->setTokens($this->getTokens());
+ $newFilter->setTokensources($this->getTokensources());
+ $newFilter->setInitialized(true);
+ return $newFilter;
+ }
+
+ /**
+ * Initializes tokens and loads the replacee-replacer hashtable.
+ * This method is only called when this filter is used through
+ * a <filterreader> tag in build file.
+ */
+ private function _initialize() {
+ $params = $this->getParameters();
+ if ( $params !== null ) {
+ for($i = 0 ; $i<count($params) ; $i++) {
+ if ( $params[$i] !== null ) {
+ $type = $params[$i]->getType();
+ if ( $type === "tokenchar" ) {
+ $name = $params[$i]->getName();
+ if ( $name === "begintoken" ) {
+ $this->_beginToken = substr($params[$i]->getValue(), 0, 1);
+ } else if ( $name === "endtoken" ) {
+ $this->_endToken = substr($params[$i]->getValue(), 0, 1);
+ }
+ } else if ( $type === "token" ) {
+ $name = $params[$i]->getName();
+ $value = $params[$i]->getValue();
+
+ $tok = new Token();
+ $tok->setKey($name);
+ $tok->setValue($value);
+
+ array_push($this->_tokens, $tok);
+ } else if ( $type === "tokensource" ) {
+ // Store data from nested tags in local array
+ $arr = array(); $subparams = $params[$i]->getParams();
+ $count = count($subparams);
+ for ($i = 0; $i < $count; $i++) {
+ $arr[$subparams[$i]->getName()] = $subparams[$i]->getValue();
+ }
+
+ // Create TokenSource
+ $tokensource = new TokenSource();
+ if (isset($arr["classname"]))
+ $tokensource->setClassname($arr["classname"]);
+
+ // Copy other parameters 1:1 to freshly created TokenSource
+ foreach ($arr as $key => $value) {
+ if (strtolower($key) === "classname")
+ continue;
+ $param = $tokensource->createParam();
+ $param->setName($key);
+ $param->setValue($value);
+ }
+
+ $this->_tokensources[] = $tokensource;
+ }
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Holds a token.
+ */
+class Token {
+
+ /**
+ * Token key.
+ * @var string
+ */
+ private $_key;
+
+ /**
+ * Token value.
+ * @var string
+ */
+ private $_value;
+
+ /**
+ * Sets the token key.
+ *
+ * @param string $key The key for this token. Must not be <code>null</code>.
+ */
+ function setKey($key) {
+ $this->_key = (string) $key;
+ }
+
+ /**
+ * Sets the token value.
+ *
+ * @param string $value The value for this token. Must not be <code>null</code>.
+ */
+ function setValue($value) {
+ $this->_value = (string) $value;
+ }
+
+ /**
+ * Returns the key for this token.
+ *
+ * @return string The key for this token.
+ */
+ function getKey() {
+ return $this->_key;
+ }
+
+ /**
+ * Returns the value for this token.
+ *
+ * @return string The value for this token.
+ */
+ function getValue() {
+ return $this->_value;
+ }
+}
+
+?>
diff --git a/buildscripts/phing/classes/phing/filters/StripLineBreaks.php b/buildscripts/phing/classes/phing/filters/StripLineBreaks.php
new file mode 100644
index 00000000..c5a06129
--- /dev/null
+++ b/buildscripts/phing/classes/phing/filters/StripLineBreaks.php
@@ -0,0 +1,148 @@
+<?php
+
+/*
+ * $Id: StripLineBreaks.php,v 1.8 2004/03/15 14:45:06 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+include_once 'phing/filters/BaseParamFilterReader.php';
+include_once 'phing/filters/ChainableReader.php';
+
+/**
+ * Filter to flatten the stream to a single line.
+ *
+ * Example:
+ *
+ * <pre><striplinebreaks/></pre>
+ *
+ * Or:
+ *
+ * <pre><filterreader classname="phing.filters.StripLineBreaks"/></pre>
+ *
+ * @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
+ * @author hans lellelid, hans@velum.net
+ * @version $Revision: 1.8 $ $Date: 2004/03/15 14:45:06 $
+ * @access public
+ * @see BaseParamFilterReader
+ * @package phing.filters
+ */
+class StripLineBreaks extends BaseParamFilterReader implements ChainableReader {
+
+ /**
+ * Default line-breaking characters.
+ * @var string
+ */
+ const DEFAULT_LINE_BREAKS = "\r\n";
+
+ /**
+ * Parameter name for the line-breaking characters parameter.
+ * @var string
+ */
+ const LINES_BREAKS_KEY = "linebreaks";
+
+ /**
+ * The characters that are recognized as line breaks.
+ * @var string
+ */
+ private $_lineBreaks = "\r\n"; // self::DEFAULT_LINE_BREAKS;
+
+ /**
+ * Returns the filtered stream, only including
+ * characters not in the set of line-breaking characters.
+ *
+ * @return mixed the resulting stream, or -1
+ * if the end of the resulting stream has been reached.
+ *
+ * @exception IOException if the underlying stream throws an IOException
+ * during reading
+ */
+ function read($len = null) {
+ if ( !$this->getInitialized() ) {
+ $this->_initialize();
+ $this->setInitialized(true);
+ }
+
+ $buffer = $this->in->read($len);
+ if($buffer === -1) {
+ return -1;
+ }
+
+ $buffer = preg_replace("/[".$this->_lineBreaks."]/", '', $buffer);
+
+ return $buffer;
+ }
+
+ /**
+ * Sets the line-breaking characters.
+ *
+ * @param string $lineBreaks A String containing all the characters to be
+ * considered as line-breaking.
+ */
+ function setLineBreaks($lineBreaks) {
+ $this->_lineBreaks = (string) $lineBreaks;
+ }
+
+ /**
+ * Gets the line-breaking characters.
+ *
+ * @return string A String containing all the characters that are considered as line-breaking.
+ */
+ function getLineBreaks() {
+ return $this->_lineBreaks;
+ }
+
+ /**
+ * Creates a new StripLineBreaks using the passed in
+ * Reader for instantiation.
+ *
+ * @param object A Reader object providing the underlying stream.
+ * Must not be <code>null</code>.
+ *
+ * @return object A new filter based on this configuration, but filtering
+ * the specified reader
+ */
+ function chain(Reader $reader) {
+ $newFilter = new StripLineBreaks($reader);
+ $newFilter->setLineBreaks($this->getLineBreaks());
+ $newFilter->setInitialized(true);
+ $newFilter->setProject($this->getProject());
+ return $newFilter;
+ }
+
+ /**
+ * Parses the parameters to set the line-breaking characters.
+ */
+ private function _initialize() {
+ $userDefinedLineBreaks = null;
+ $params = $this->getParameters();
+ if ( $params !== null ) {
+ for($i = 0 ; $i<count($params) ; $i++) {
+ if ( self::LINE_BREAKS_KEY === $params[$i]->getName() ) {
+ $userDefinedLineBreaks = $params[$i]->getValue();
+ break;
+ }
+ }
+ }
+
+ if ( $userDefinedLineBreaks !== null ) {
+ $this->_lineBreaks = $userDefinedLineBreaks;
+ }
+ }
+}
+
+?>
diff --git a/buildscripts/phing/classes/phing/filters/StripLineComments.php b/buildscripts/phing/classes/phing/filters/StripLineComments.php
new file mode 100644
index 00000000..5d97979a
--- /dev/null
+++ b/buildscripts/phing/classes/phing/filters/StripLineComments.php
@@ -0,0 +1,205 @@
+<?php
+
+/*
+ * $Id: StripLineComments.php,v 1.8 2005/02/27 20:52:08 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+include_once 'phing/filters/BaseParamFilterReader.php';
+include_once 'phing/filters/ChainableReader.php';
+
+/*
+ * This filter strips line comments.
+ *
+ * Example:
+ *
+ * <pre><striplinecomments>
+ * <comment value="#"/>
+ * <comment value="--"/>
+ * <comment value="REM "/>
+ * <comment value="rem "/>
+ * <comment value="//"/>
+ * </striplinecomments></pre>
+ *
+ * Or:
+ *
+ * <pre><filterreader classname="phing.filters.StripLineComments">
+ * <param type="comment" value="#"/>
+ * <param type="comment" value="--"/>
+ * <param type="comment" value="REM "/>
+ * <param type="comment" value="rem "/>
+ * <param type="comment" value="//"/>
+ * </filterreader></pre>
+ *
+ * @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
+ * @author hans lellelid, hans@velum.net
+ * @version $Revision: 1.8 $ $Date: 2005/02/27 20:52:08 $
+ * @access public
+ * @see BaseParamFilterReader
+ * @package phing.filters
+ */
+class StripLineComments extends BaseParamFilterReader implements ChainableReader {
+
+ /** Parameter name for the comment prefix. */
+ const COMMENTS_KEY = "comment";
+
+ /** Array that holds the comment prefixes. */
+ private $_comments = array();
+
+ /**
+ * Returns stream only including
+ * lines from the original stream which don't start with any of the
+ * specified comment prefixes.
+ *
+ * @return mixed the resulting stream, or -1
+ * if the end of the resulting stream has been reached.
+ *
+ * @throws IOException if the underlying stream throws an IOException
+ * during reading
+ */
+ function read($len = null) {
+
+ if ( !$this->getInitialized() ) {
+ $this->_initialize();
+ $this->setInitialized(true);
+ }
+
+ $buffer = $this->in->read($len);
+
+ if ($buffer === -1) {
+ return -1;
+ }
+
+ $lines = explode("\n", $buffer);
+ $filtered = array();
+
+ $commentsSize = count($this->_comments);
+
+ foreach($lines as $line) {
+ for($i = 0; $i < $commentsSize; $i++) {
+ $comment = $this->_comments[$i]->getValue();
+ if ( StringHelper::startsWith($comment, ltrim($line)) ) {
+ $line = null;
+ break;
+ }
+ }
+ if ($line !== null) {
+ $filtered[] = $line;
+ }
+ }
+
+ $filtered_buffer = implode("\n", $filtered);
+ return $filtered_buffer;
+ }
+
+ /*
+ * Adds a <code>comment</code> element to the list of prefixes.
+ *
+ * @return comment The <code>comment</code> element added to the
+ * list of comment prefixes to strip.
+ */
+ function createComment() {
+ $num = array_push($this->_comments, new Comment());
+ return $this->_comments[$num-1];
+ }
+
+ /*
+ * Sets the list of comment prefixes to strip.
+ *
+ * @param comments A list of strings, each of which is a prefix
+ * for a comment line. Must not be <code>null</code>.
+ */
+ function setComments($lineBreaks) {
+ if (!is_array($lineBreaks)) {
+ throw new Exception("Excpected 'array', got something else");
+ }
+ $this->_comments = $lineBreaks;
+ }
+
+ /*
+ * Returns the list of comment prefixes to strip.
+ *
+ * @return array The list of comment prefixes to strip.
+ */
+ function getComments() {
+ return $this->_comments;
+ }
+
+ /*
+ * Creates a new StripLineComments using the passed in
+ * Reader for instantiation.
+ *
+ * @param reader A Reader object providing the underlying stream.
+ * Must not be <code>null</code>.
+ *
+ * @return a new filter based on this configuration, but filtering
+ * the specified reader
+ */
+ function chain(Reader $reader) {
+ $newFilter = new StripLineComments($reader);
+ $newFilter->setComments($this->getComments());
+ $newFilter->setInitialized(true);
+ $newFilter->setProject($this->getProject());
+ return $newFilter;
+ }
+
+ /*
+ * Parses the parameters to set the comment prefixes.
+ */
+ private function _initialize() {
+ $params = $this->getParameters();
+ if ( $params !== null ) {
+ for($i = 0 ; $i<count($params) ; $i++) {
+ if ( self::COMMENTS_KEY === $params[$i]->getType() ) {
+ $comment = new Comment();
+ $comment->setValue($params[$i]->getValue());
+ array_push($this->_comments, $comment);
+ }
+ }
+ }
+ }
+}
+
+/*
+ * The class that holds a comment representation.
+*/
+class Comment {
+
+ /** The prefix for a line comment. */
+ private $_value;
+
+ /*
+ * Sets the prefix for this type of line comment.
+ *
+ * @param string $value The prefix for a line comment of this type.
+ * Must not be <code>null</code>.
+ */
+ function setValue($value) {
+ $this->_value = (string) $value;
+ }
+
+ /*
+ * Returns the prefix for this type of line comment.
+ *
+ * @return string The prefix for this type of line comment.
+ */
+ function getValue() {
+ return $this->_value;
+ }
+}
+?>
diff --git a/buildscripts/phing/classes/phing/filters/StripPhpComments.php b/buildscripts/phing/classes/phing/filters/StripPhpComments.php
new file mode 100644
index 00000000..9e21eed3
--- /dev/null
+++ b/buildscripts/phing/classes/phing/filters/StripPhpComments.php
@@ -0,0 +1,190 @@
+<?php
+
+/*
+ * $Id: StripPhpComments.php,v 1.6 2004/07/16 01:36:35 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+include_once 'phing/filters/BaseFilterReader.php';
+include_once 'phing/filters/ChainableReader.php';
+
+/**
+ * This is a Php comment and string stripper reader that filters
+ * those lexical tokens out for purposes of simple Php parsing.
+ * (if you have more complex Php parsing needs, use a real lexer).
+ * Since this class heavily relies on the single char read function,
+ * you are reccomended to make it work on top of a buffered reader.
+ *
+ * @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
+ * @author hans lellelid, hans@velum.net
+ * @version $Revision: 1.6 $ $Date: 2004/07/16 01:36:35 $
+ * @access public
+ * @see FilterReader
+ * @package phing.filters
+ * @todo -c use new PHP functions to perform this instead of regex.
+ */
+class StripPhpComments extends BaseFilterReader implements ChainableReader {
+ /**
+ * The read-ahead character, used for effectively pushing a single
+ * character back. -1 indicates that no character is in the buffer.
+ */
+ private $_readAheadCh = -1;
+
+ /**
+ * Whether or not the parser is currently in the middle of a string
+ * literal.
+ * @var boolean
+ */
+ private $_inString = false;
+
+ /**
+ * Returns the stream without Php comments.
+ *
+ * @return the resulting stream, or -1
+ * if the end of the resulting stream has been reached
+ *
+ * @throws IOException if the underlying stream throws an IOException
+ * during reading
+ */
+ function read($len = null) {
+
+ $buffer = $this->in->read($len);
+ if($buffer === -1) {
+ return -1;
+ }
+
+ // This regex replace /* */ and // style comments
+ $buffer = preg_replace('/\/\*[^*]*\*+([^\/*][^*]*\*+)*\/|\/\/[^\n]*|("(\\\\.|[^"\\\\])*"|\'(\\\\.|[^\'\\\\])*\'|.[^\/"\'\\\\]*)/s', "$2", $buffer);
+
+ // The regex above is not identical to, but is based on the expression below:
+ //
+ // created by Jeffrey Friedl
+ // and later modified by Fred Curtis.
+ // s{
+ // /\* ## Start of /* ... */ comment
+ // [^*]*\*+ ## Non-* followed by 1-or-more *'s
+ // (
+ // [^/*][^*]*\*+
+ // )* ## 0-or-more things which don't start with /
+ // ## but do end with '*'
+ // / ## End of /* ... */ comment
+ //
+ // | ## OR various things which aren't comments:
+ //
+ // (
+ // " ## Start of " ... " string
+ // (
+ // \\. ## Escaped char
+ // | ## OR
+ // [^"\\] ## Non "\
+ // )*
+ // " ## End of " ... " string
+ //
+ // | ## OR
+ //
+ // ' ## Start of ' ... ' string
+ // (
+ // \\. ## Escaped char
+ // | ## OR
+ // [^'\\] ## Non '\
+ // )*
+ // ' ## End of ' ... ' string
+ //
+ // | ## OR
+ //
+ // . ## Anything other char
+ // [^/"'\\]* ## Chars which doesn't start a comment, string or escape
+ // )
+ // }{$2}gxs;
+
+ return $buffer;
+ }
+
+
+ /*
+ * Returns the next character in the filtered stream, not including
+ * Php comments.
+ *
+ * @return the next character in the resulting stream, or -1
+ * if the end of the resulting stream has been reached
+ *
+ * @throws IOException if the underlying stream throws an IOException
+ * during reading
+ * @deprecated
+ */
+ function readChar() {
+ $ch = -1;
+
+ if ( $this->_readAheadCh !== -1 ) {
+ $ch = $this->_readAheadCh;
+ $this->_readAheadCh = -1;
+ } else {
+ $ch = $this->in->readChar();
+ if ( $ch === "\"" ) {
+ $this->_inString = !$this->_inString;
+ } else {
+ if ( !$this->_inString ) {
+ if ( $ch === "/" ) {
+ $ch = $this->in->readChar();
+ if ( $ch === "/" ) {
+ while ( $ch !== "\n" && $ch !== -1 ) {
+ $ch = $this->in->readChar();
+ }
+ } else if ( $ch === "*" ) {
+ while ( $ch !== -1 ) {
+ $ch = $this->in->readChar();
+ while ( $ch === "*" && $ch !== -1 ) {
+ $ch = $this->in->readChar();
+ }
+
+ if ( $ch === "/" ) {
+ $ch = $this->readChar();
+ echo "$ch\n";
+ break;
+ }
+ }
+ } else {
+ $this->_readAheadCh = $ch;
+ $ch = "/";
+ }
+ }
+ }
+ }
+ }
+
+ return $ch;
+ }
+
+ /**
+ * Creates a new StripJavaComments using the passed in
+ * Reader for instantiation.
+ *
+ * @param reader A Reader object providing the underlying stream.
+ * Must not be <code>null</code>.
+ *
+ * @return a new filter based on this configuration, but filtering
+ * the specified reader
+ */
+ function chain(Reader $reader) {
+ $newFilter = new StripPhpComments($reader);
+ $newFilter->setProject($this->getProject());
+ return $newFilter;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/filters/TabToSpaces.php b/buildscripts/phing/classes/phing/filters/TabToSpaces.php
new file mode 100644
index 00000000..7293d3b5
--- /dev/null
+++ b/buildscripts/phing/classes/phing/filters/TabToSpaces.php
@@ -0,0 +1,144 @@
+<?php
+
+/*
+ * $Id: TabToSpaces.php,v 1.9 2004/03/15 14:45:06 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+require_once 'phing/filters/BaseParamFilterReader.php';
+require_once 'phing/filters/ChainableReader.php';
+
+/**
+ * Converts tabs to spaces.
+ *
+ * Example:
+ *
+ * <pre><tabtospaces tablength="8"></pre>
+ *
+ * Or:
+ *
+ * <pre><filterreader classname="phing.filters.TabsToSpaces">
+ * <param name="tablength" value="8">
+ * </filterreader></pre>
+ *
+ * @author Yannick Lecaillez <yl@seasonfive.com>
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.9 $
+ * @see BaseParamFilterReader
+ * @package phing.filters
+ */
+class TabToSpaces extends BaseParamFilterReader implements ChainableReader {
+
+ /**
+ * The default tab length.
+ * @var int
+ */
+ const DEFAULT_TAB_LENGTH = 8;
+
+ /**
+ * Parameter name for the length of a tab.
+ * @var string
+ */
+ const TAB_LENGTH_KEY = "tablength";
+
+ /**
+ * Tab length in this filter.
+ * @var int
+ */
+ private $tabLength = 8; //self::DEFAULT_TAB_LENGTH;
+
+ /**
+ * Returns stream after converting tabs to the specified number of spaces.
+ *
+ * @return the resulting stream, or -1
+ * if the end of the resulting stream has been reached
+ *
+ * @exception IOException if the underlying stream throws an IOException
+ * during reading
+ */
+ function read($len = null) {
+
+ if ( !$this->getInitialized() ) {
+ $this->_initialize();
+ $this->setInitialized(true);
+ }
+
+ $buffer = $this->in->read($len);
+
+ if($buffer === -1) {
+ return -1;
+ }
+
+ $buffer = str_replace("\t", str_repeat(' ', $this->tabLength), $buffer);
+
+ return $buffer;
+ }
+
+ /**
+ * Sets the tab length.
+ *
+ * @param int $tabLength The number of spaces to be used when converting a tab.
+ */
+ function setTablength($tabLength) {
+ $this->tabLength = (int) $tabLength;
+ }
+
+ /**
+ * Returns the tab length.
+ *
+ * @return int The number of spaces used when converting a tab
+ */
+ function getTablength() {
+ return $this->tabLength;
+ }
+
+ /**
+ * Creates a new TabsToSpaces using the passed in
+ * Reader for instantiation.
+ *
+ * @param Reader $reader A Reader object providing the underlying stream.
+ * Must not be <code>null</code>.
+ *
+ * @return Reader A new filter based on this configuration, but filtering
+ * the specified reader
+ */
+ function chain(Reader $reader) {
+ $newFilter = new TabToSpaces($reader);
+ $newFilter->setTablength($this->getTablength());
+ $newFilter->setInitialized(true);
+ $newFilter->setProject($this->getProject());
+ return $newFilter;
+ }
+
+ /**
+ * Parses the parameters to set the tab length.
+ */
+ private function _initialize() {
+ $params = $this->getParameters();
+ if ( $params !== null ) {
+ for($i = 0 ; $i<count($params) ; $i++) {
+ if (self::TAB_LENGTH_KEY === $params[$i]->getName()) {
+ $this->tabLength = $params[$i]->getValue();
+ break;
+ }
+ }
+ }
+ }
+}
+
+?>
diff --git a/buildscripts/phing/classes/phing/filters/TailFilter.php b/buildscripts/phing/classes/phing/filters/TailFilter.php
new file mode 100644
index 00000000..a6af6e4b
--- /dev/null
+++ b/buildscripts/phing/classes/phing/filters/TailFilter.php
@@ -0,0 +1,157 @@
+<?php
+
+/*
+ * $Id: TailFilter.php,v 1.7 2004/03/15 14:45:06 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+require_once 'phing/filters/BaseParamFilterReader.php';
+
+/**
+ * Reads the last <code>n</code> lines of a stream. (Default is last10 lines.)
+ *
+ * Example:
+ *
+ * <pre><tailfilter lines="3" /></pre>
+ *
+ * Or:
+ *
+ * <pre><filterreader classname="phing.filters.TailFilter">
+ * <param name="lines" value="3">
+ * </filterreader></pre>
+ *
+ * @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
+ * @author hans lellelid, hans@velum.net
+ * @copyright © 2003 seasonfive. All rights reserved
+ * @version $Revision: 1.7 $
+ * @see BaseParamFilterReader
+ * @package phing.filters
+ */
+class TailFilter extends BaseParamFilterReader implements ChainableReader {
+
+ /**
+ * Parameter name for the number of lines to be returned.
+ * @var string
+ */
+ const LINES_KEY = "lines";
+
+
+ /**
+ * Number of lines to be returned in the filtered stream.
+ * @var integer
+ */
+ private $_lines = 10;
+
+ /**
+ * Array to hold lines.
+ * @var array
+ */
+ private $_lineBuffer = array();
+
+ /**
+ * Returns the last n lines of a file.
+ * @param int $len Num chars to read.
+ * @return mixed The filtered buffer or -1 if EOF.
+ */
+ function read($len = null) {
+
+ while ( ($buffer = $this->in->read($len)) !== -1 ) {
+ // Remove the last "\n" from buffer for
+ // prevent explode to add an empty cell at
+ // the end of array
+ $buffer= trim($buffer, "\n");
+
+ $lines = explode("\n", $buffer);
+
+ if ( count($lines) >= $this->_lines ) {
+ // Buffer have more (or same) number of lines than needed.
+ // Fill lineBuffer with the last "$this->_lines" lasts ones.
+ $off = count($lines)-$this->_lines;
+ $this->_lineBuffer = array_slice($lines, $off);
+ } else {
+ // Some new lines ...
+ // Prepare space for insert these new ones
+ $this->_lineBuffer = array_slice($this->_lineBuffer, count($lines)-1);
+ $this->_lineBuffer = array_merge($this->_lineBuffer, $lines);
+ }
+ }
+
+ if ( empty($this->_lineBuffer) )
+ $ret = -1;
+ else {
+ $ret = implode("\n", $this->_lineBuffer);
+ $this->_lineBuffer = array();
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Sets the number of lines to be returned in the filtered stream.
+ *
+ * @param integer $lines the number of lines to be returned in the filtered stream.
+ */
+ function setLines($lines) {
+ $this->_lines = (int) $lines;
+ }
+
+ /**
+ * Returns the number of lines to be returned in the filtered stream.
+ *
+ * @return integer The number of lines to be returned in the filtered stream.
+ */
+ function getLines() {
+ return $this->_lines;
+ }
+
+ /**
+ * Creates a new TailFilter using the passed in
+ * Reader for instantiation.
+ *
+ * @param object A Reader object providing the underlying stream.
+ * Must not be <code>null</code>.
+ *
+ * @return object A new filter based on this configuration, but filtering
+ * the specified reader.
+ */
+ function chain(Reader $reader) {
+ $newFilter = new TailFilter($reader);
+ $newFilter->setLines($this->getLines());
+ $newFilter->setInitialized(true);
+ $newFilter->setProject($this->getProject());
+ return $newFilter;
+ }
+
+ /**
+ * Scans the parameters list for the "lines" parameter and uses
+ * it to set the number of lines to be returned in the filtered stream.
+ */
+ private function _initialize() {
+ $params = $this->getParameters();
+ if ( $params !== null ) {
+ for($i=0, $_i=count($params); $i < $_i; $i++) {
+ if ( self::LINES_KEY == $params[$i]->getName() ) {
+ $this->_lines = (int) $params[$i]->getValue();
+ break;
+ }
+ }
+ }
+ }
+}
+
+?>
diff --git a/buildscripts/phing/classes/phing/filters/TidyFilter.php b/buildscripts/phing/classes/phing/filters/TidyFilter.php
new file mode 100644
index 00000000..10d75fc4
--- /dev/null
+++ b/buildscripts/phing/classes/phing/filters/TidyFilter.php
@@ -0,0 +1,162 @@
+<?php
+/*
+ * $Id: TidyFilter.php,v 1.2 2005/12/08 19:15:20 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+include_once 'phing/filters/BaseParamFilterReader.php';
+include_once 'phing/filters/ChainableReader.php';
+
+/**
+ * This filter uses the bundled-with-PHP Tidy extension to filter input.
+ *
+ * <p>
+ * Example:<br/>
+ * <pre>
+ * <tidyfilter encoding="utf8">
+ * <config name="indent" value="true"/>
+ * <config name="output-xhtml" value="true"/>
+ * </tidyfilter>
+ * </pre>
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.2 $ $Date: 2005/12/08 19:15:20 $
+ * @package phing.filters
+ */
+class TidyFilter extends BaseParamFilterReader implements ChainableReader {
+
+ /** @var string Encoding of resulting document. */
+ private $encoding = 'utf8';
+
+ /** @var array Parameter[] */
+ private $configParameters = array();
+
+ /**
+ * Set the encoding for resulting (X)HTML document.
+ * @param string $v
+ */
+ public function setEncoding($v) {
+ $this->encoding = $v;
+ }
+
+ /**
+ * Sets the config params.
+ * @param array Parameter[]
+ * @see chain()
+ */
+ public function setConfigParameters($params)
+ {
+ $this->configParameters = $params;
+ }
+
+ /**
+ * Adds a <config> element (which is a Parameter).
+ * @return Parameter
+ */
+ public function createConfig() {
+ $num = array_push($this->configParameters, new Parameter());
+ return $this->configParameters[$num-1];
+ }
+
+ /**
+ * Converts the Parameter objects being used to store configuration into a simle assoc array.
+ * @return array
+ */
+ private function getDistilledConfig() {
+ $config = array();
+ foreach($this->configParameters as $p) {
+ $config[$p->getName()] = $p->getValue();
+ }
+ return $config;
+ }
+
+ /**
+ * Reads input and returns Tidy-filtered output.
+ *
+ * @return the resulting stream, or -1 if the end of the resulting stream has been reached
+ *
+ * @throws IOException if the underlying stream throws an IOException
+ * during reading
+ */
+ function read($len = null) {
+
+ if (!class_exists('Tidy')) {
+ throw new BuildException("You must enable the 'tidy' extension in your PHP configuration in order to use the Tidy filter.");
+ }
+
+ if ( !$this->getInitialized() ) {
+ $this->_initialize();
+ $this->setInitialized(true);
+ }
+
+ $buffer = $this->in->read($len);
+ if($buffer === -1) {
+ return -1;
+ }
+
+ $config = $this->getDistilledConfig();
+
+ $tidy = new Tidy();
+ $tidy->parseString($buffer, $config, $this->encoding);
+ $tidy->cleanRepair();
+
+ return tidy_get_output($tidy);
+
+ }
+
+
+ /**
+ * Creates a new TidyFilter using the passed in Reader for instantiation.
+ *
+ * @param reader A Reader object providing the underlying stream.
+ * Must not be <code>null</code>.
+ *
+ * @return a new filter based on this configuration, but filtering
+ * the specified reader
+ */
+ public function chain(Reader $reader) {
+ $newFilter = new TidyFilter($reader);
+ $newFilter->setConfigParameters($this->configParameters);
+ $newFilter->setEncoding($this->encoding);
+ $newFilter->setProject($this->getProject());
+ return $newFilter;
+ }
+
+ /**
+ * Initializes any parameters (e.g. config options).
+ * This method is only called when this filter is used through a <filterreader> tag in build file.
+ */
+ private function _initialize() {
+ $params = $this->getParameters();
+ if ($params) {
+ foreach($params as $param) {
+ if ($param->getType() == "config") {
+ $this->configParameters[] = $param;
+ } else {
+
+ if ($param->getName() == "encoding") {
+ $this->setEncoding($param->getValue());
+ }
+
+ }
+
+ }
+ }
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/filters/TranslateGettext.php b/buildscripts/phing/classes/phing/filters/TranslateGettext.php
new file mode 100644
index 00000000..f71823e3
--- /dev/null
+++ b/buildscripts/phing/classes/phing/filters/TranslateGettext.php
@@ -0,0 +1,285 @@
+<?php
+
+/*
+ * $Id: TranslateGettext.php,v 1.11 2005/12/08 15:59:56 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+require_once 'phing/filters/BaseParamFilterReader.php';
+include_once 'phing/filters/ChainableReader.php';
+
+/**
+ * Replaces gettext("message id") and _("message id") with the translated string.
+ *
+ * Gettext is great for creating multi-lingual sites, but in some cases (e.g. for
+ * performance reasons) you may wish to replace the gettext calls with the translations
+ * of the strings; that's what this task is for. Note that this is similar to
+ * ReplaceTokens, but both the find and the replace aspect is more complicated -- hence
+ * this is a separate, stand-alone filter.
+ *
+ * <p>
+ * Example:<br>
+ * <pre>
+ * <translategettext locale="en_US" domain="messages" dir="${webroot}/local"/>
+ * </pre>
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.11 $ $Date: 2005/12/08 15:59:56 $
+ * @access public
+ * @see BaseFilterReader
+ * @package phing.filters
+ */
+class TranslateGettext extends BaseParamFilterReader implements ChainableReader {
+
+ // constants for specifying keys to expect
+ // when this is called using <filterreader ... />
+ const DOMAIN_KEY = "domain";
+ const DIR_KEY = "dir";
+ const LOCALE_KEY = "locale";
+
+ /** The domain to use */
+ private $domain = 'messages';
+
+ /** The dir containing LC_MESSAGES */
+ private $dir;
+
+ /** The locale to use */
+ private $locale;
+
+ /** The system locale before it was changed for this filter. */
+ private $storedLocale;
+
+ /**
+ * Set the text domain to use.
+ * The text domain must correspond to the name of the compiled .mo files.
+ * E.g. "messages" ==> $dir/LC_MESSAGES/messages.mo
+ * "mydomain" ==> $dir/LC_MESSAGES/mydomain.mo
+ * @param string $domain
+ */
+ function setDomain($domain) {
+ $this->domain = $domain;
+ }
+
+ /**
+ * Get the current domain.
+ * @return string
+ */
+ function getDomain() {
+ return $this->domain;
+ }
+
+ /**
+ * Sets the root locale directory.
+ * @param PhingFile $dir
+ */
+ function setDir(PhingFile $dir) {
+ $this->dir = $dir;
+ }
+
+ /**
+ * Gets the root locale directory.
+ * @return PhingFile
+ */
+ function getDir() {
+ return $this->dir;
+ }
+
+ /**
+ * Sets the locale to use for translation.
+ * Note that for gettext() to work, you have to make sure this locale
+ * is specific enough for your system (e.g. some systems may allow an 'en' locale,
+ * but others will require 'en_US', etc.).
+ * @param string $locale
+ */
+ function setLocale($locale) {
+ $this->locale = $locale;
+ }
+
+ /**
+ * Gets the locale to use for translation.
+ * @return string
+ */
+ function getLocale() {
+ return $this->locale;
+ }
+
+ /**
+ * Make sure that required attributes are set.
+ * @throws BuldException - if any required attribs aren't set.
+ */
+ protected function checkAttributes() {
+ if (!$this->domain || !$this->locale || !$this->dir) {
+ throw new BuildException("You must specify values for domain, locale, and dir attributes.");
+ }
+ }
+
+ /**
+ * Initialize the gettext/locale environment.
+ * This method will change some env vars and locale settings; the
+ * restoreEnvironment should put them all back :)
+ *
+ * @return void
+ * @throws BuildException - if locale cannot be set.
+ * @see restoreEnvironment()
+ */
+ protected function initEnvironment() {
+ $this->storedLocale = getenv("LANG");
+
+ $this->log("Setting locale to " . $this->locale, PROJECT_MSG_DEBUG);
+ putenv("LANG=".$this->locale);
+ $ret = setlocale(LC_ALL, $this->locale);
+ if ($ret === false) {
+ $msg = "Could not set locale to " . $this->locale
+ . ". You may need to use fully qualified name"
+ . " (e.g. en_US instead of en).";
+ throw new BuildException($msg);
+ }
+
+ $this->log("Binding domain '".$this->domain."' to " . $this->dir, PROJECT_MSG_DEBUG);
+ bindtextdomain($this->domain, $this->dir->getAbsolutePath());
+ textdomain($this->domain);
+ }
+
+ /**
+ * Restores environment settings and locale.
+ * This does _not_ restore any gettext-specific settings
+ * (e.g. textdomain()).
+ *
+ * @return void
+ */
+ protected function restoreEnvironment() {
+ putenv("LANG=".$this->storedLocale);
+ setlocale(LC_ALL, $this->storedLocale);
+ }
+
+ /**
+ * Performs gettext translation of msgid and returns translated text.
+ *
+ * This function simply wraps gettext() call, but provides ability to log
+ * string replacements. (alternative would be using preg_replace with /e which
+ * would probably be faster, but no ability to debug/log.)
+ *
+ * @param array $matches Array of matches; we're interested in $matches[2].
+ * @return string Translated text
+ */
+ private function xlateStringCallback($matches) {
+ $charbefore = $matches[1];
+ $msgid = $matches[2];
+ $translated = gettext($msgid);
+ $this->log("Translating \"$msgid\" => \"$translated\"", PROJECT_MSG_DEBUG);
+ return $charbefore . '"' . $translated . '"';
+ }
+
+ /**
+ * Returns the filtered stream.
+ * The original stream is first read in fully, and then translation is performed.
+ *
+ * @return mixed the filtered stream, or -1 if the end of the resulting stream has been reached.
+ *
+ * @throws IOException - if the underlying stream throws an IOException during reading
+ * @throws BuildException - if the correct params are not supplied
+ */
+ function read($len = null) {
+
+ if ( !$this->getInitialized() ) {
+ $this->_initialize();
+ $this->setInitialized(true);
+ }
+
+ // Make sure correct params/attribs have been set
+ $this->checkAttributes();
+
+ $buffer = $this->in->read($len);
+ if($buffer === -1) {
+ return -1;
+ }
+
+ // Setup the locale/gettext environment
+ $this->initEnvironment();
+
+
+ // replace any occurrences of _("") or gettext("") with
+ // the translated value.
+ //
+ // ([^\w]|^)_\("((\\"|[^"])*)"\)
+ // --$1--- -----$2----
+ // ---$3-- [match escaped quotes or any char that's not a quote]
+ //
+ // also match gettext() -- same as above
+
+ $buffer = preg_replace_callback('/([^\w]|^)_\("((\\\"|[^"])*)"\)/', array($this, 'xlateStringCallback'), $buffer);
+ $buffer = preg_replace_callback('/([^\w]|^)gettext\("((\\\"|[^"])*)"\)/', array($this, 'xlateStringCallback'), $buffer);
+
+ // Check to see if there are any _('') calls and flag an error
+
+ // Check to see if there are any unmatched gettext() calls -- and flag an error
+
+ $matches = array();
+ if (preg_match('/([^\w]|^)(gettext\([^\)]+\))/', $buffer, $matches)) {
+ $this->log("Unable to perform translation on: " . $matches[2], PROJECT_MSG_WARN);
+ }
+
+ $this->restoreEnvironment();
+
+ return $buffer;
+ }
+
+ /**
+ * Creates a new TranslateGettext filter using the passed in
+ * Reader for instantiation.
+ *
+ * @param Reader $reader A Reader object providing the underlying stream.
+ * Must not be <code>null</code>.
+ *
+ * @return TranslateGettext A new filter based on this configuration, but filtering
+ * the specified reader
+ */
+ function chain(Reader $reader) {
+ $newFilter = new TranslateGettext($reader);
+ $newFilter->setProject($this->getProject());
+ $newFilter->setDomain($this->getDomain());
+ $newFilter->setLocale($this->getLocale());
+ $newFilter->setDir($this->getDir());
+ return $newFilter;
+ }
+
+ /**
+ * Parses the parameters if this filter is being used in "generic" mode.
+ */
+ private function _initialize() {
+ $params = $this->getParameters();
+ if ( $params !== null ) {
+ foreach($params as $param) {
+ switch($param->getType()) {
+ case self::DOMAIN_KEY:
+ $this->setDomain($param->getValue());
+ break;
+ case self::DIR_KEY:
+ $this->setDir($this->project->resolveFile($param->getValue()));
+ break;
+
+ case self::LOCALE_KEY:
+ $this->setLocale($param->getValue());
+ break;
+ } // switch
+ }
+ } // if params !== null
+ }
+}
+
+?>
diff --git a/buildscripts/phing/classes/phing/filters/XsltFilter.php b/buildscripts/phing/classes/phing/filters/XsltFilter.php
new file mode 100644
index 00000000..0b8c4e6f
--- /dev/null
+++ b/buildscripts/phing/classes/phing/filters/XsltFilter.php
@@ -0,0 +1,317 @@
+<?php
+
+/*
+ * $Id: XsltFilter.php,v 1.16 2005/12/07 20:05:01 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+include_once 'phing/filters/BaseParamFilterReader.php';
+include_once 'phing/filters/ChainableReader.php';
+
+/**
+ * Applies XSL stylesheet to incoming text.
+ *
+ * Uses PHP XSLT support (libxslt).
+ *
+ * @author Hans Lellelid <hans@velum.net>
+ * @author Yannick Lecaillez <yl@seasonfive.com>
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @version $Revision: 1.16 $
+ * @see FilterReader
+ * @package phing.filters
+ */
+class XsltFilter extends BaseParamFilterReader implements ChainableReader {
+
+ /**
+ * Path to XSL stylesheet.
+ * @var string
+ */
+ private $xslFile = null;
+
+ /**
+ * Whether XML file has been transformed.
+ * @var boolean
+ */
+ private $processed = false;
+
+ /**
+ * XSLT Params.
+ * @var array
+ */
+ private $xsltParams = array();
+
+ /**
+ * Whether to use loadHTML() to parse the input XML file.
+ */
+ private $html = false;
+
+ /**
+ * Create new XSLT Param object, to handle the <param/> nested element.
+ * @return XSLTParam
+ */
+ function createParam() {
+ $num = array_push($this->xsltParams, new XSLTParam());
+ return $this->xsltParams[$num-1];
+ }
+
+ /**
+ * Sets the XSLT params for this class.
+ * This is used to "clone" this class, in the chain() method.
+ * @param array $params
+ */
+ function setParams($params) {
+ $this->xsltParams = $params;
+ }
+
+ /**
+ * Returns the XSLT params set for this class.
+ * This is used to "clone" this class, in the chain() method.
+ * @return array
+ */
+ function getParams() {
+ return $this->xsltParams;
+ }
+
+ /**
+ * Set the XSLT stylesheet.
+ * @param mixed $file PhingFile object or path.
+ */
+ function setStyle(PhingFile $file) {
+ $this->xslFile = $file;
+ }
+
+ /**
+ * Whether to use HTML parser for the XML.
+ * This is supported in libxml2 -- Yay!
+ * @return boolean
+ */
+ function getHtml() {
+ return $this->html;
+ }
+
+ /**
+ * Whether to use HTML parser for XML.
+ * @param boolean $b
+ */
+ function setHtml($b) {
+ $this->html = (boolean) $b;
+ }
+
+ /**
+ * Get the path to XSLT stylesheet.
+ * @return mixed XSLT stylesheet path.
+ */
+ function getStyle() {
+ return $this->xslFile;
+ }
+
+ /**
+ * Reads stream, applies XSLT and returns resulting stream.
+ * @return string transformed buffer.
+ * @throws BuildException - if XSLT support missing, if error in xslt processing
+ */
+ function read($len = null) {
+
+ if (!class_exists('XSLTProcessor')) {
+ throw new BuildException("Could not find the XSLTProcessor class. Make sure PHP has been compiled/configured to support XSLT.");
+ }
+
+ if ($this->processed === true) {
+ return -1; // EOF
+ }
+
+ if ( !$this->getInitialized() ) {
+ $this->_initialize();
+ $this->setInitialized(true);
+ }
+
+ // Read XML
+ $_xml = null;
+ while ( ($data = $this->in->read($len)) !== -1 )
+ $_xml .= $data;
+
+ if ($_xml === null ) { // EOF?
+ return -1;
+ }
+
+ if(empty($_xml)) {
+ $this->log("XML file is empty!", PROJECT_MSG_WARN);
+ return ''; // return empty string, don't attempt to apply XSLT
+ }
+
+ // Read XSLT
+ $_xsl = null;
+ $xslFr = new FileReader($this->xslFile);
+ $xslFr->readInto($_xsl);
+
+ $this->log("Tranforming XML " . $this->in->getResource() . " using style " . $this->xslFile->getPath(), PROJECT_MSG_VERBOSE);
+
+ $out = '';
+ try {
+ $out = $this->process($_xml, $_xsl);
+ $this->processed = true;
+ } catch (IOException $e) {
+ throw new BuildException($e);
+ }
+
+ return $out;
+ }
+
+ // {{{ method _ProcessXsltTransformation($xml, $xslt) throws BuildException
+ /**
+ * Try to process the XSLT transformation
+ *
+ * @param string XML to process.
+ * @param string XSLT sheet to use for the processing.
+ *
+ * @throws BuildException On XSLT errors
+ */
+ protected function process($xml, $xsl) {
+
+ $processor = new XSLTProcessor();
+
+ $xmlDom = new DOMDocument();
+ $xslDom = new DOMDocument();
+
+ if ($this->html) {
+ $xmlDom->loadHTML($xml);
+ } else {
+ $xmlDom->loadXML($xml);
+ }
+
+ $xslDom->loadxml($xsl);
+
+ $processor->importStylesheet($xslDom);
+
+ // ignoring param "type" attrib, because
+ // we're only supporting direct XSL params right now
+ foreach($this->xsltParams as $param) {
+ $this->log("Setting XSLT param: " . $param->getName() . "=>" . $param->getExpression(), PROJECT_MSG_DEBUG);
+ $processor->setParameter(null, $param->getName(), $param->getExpression());
+ }
+
+ $result = $processor->transformToXML($xmlDom);
+
+ if ( !$result ) {
+ //$errno = xslt_errno($processor);
+ //$err = xslt_error($processor);
+ throw new BuildException("XSLT Error");
+ } else {
+ return $result;
+ }
+ }
+
+ /**
+ * Creates a new XsltFilter using the passed in
+ * Reader for instantiation.
+ *
+ * @param Reader A Reader object providing the underlying stream.
+ * Must not be <code>null</code>.
+ *
+ * @return Reader A new filter based on this configuration, but filtering
+ * the specified reader
+ */
+ function chain(Reader $reader) {
+ $newFilter = new XsltFilter($reader);
+ $newFilter->setProject($this->getProject());
+ $newFilter->setStyle($this->getStyle());
+ $newFilter->setInitialized(true);
+ $newFilter->setParams($this->getParams());
+ $newFilter->setHtml($this->getHtml());
+ return $newFilter;
+ }
+
+ /**
+ * Parses the parameters to get stylesheet path.
+ */
+ private function _initialize() {
+ $params = $this->getParameters();
+ if ( $params !== null ) {
+ for($i = 0, $_i=count($params) ; $i < $_i; $i++) {
+ if ( $params[$i]->getType() === null ) {
+ if ($params[$i]->getName() === "style") {
+ $this->setStyle($params[$i]->getValue());
+ }
+ } elseif ($params[$i]->getType() == "param") {
+ $xp = new XSLTParam();
+ $xp->setName($params[$i]->getName());
+ $xp->setExpression($params[$i]->getValue());
+ $this->xsltParams[] = $xp;
+ }
+ }
+ }
+ }
+
+}
+
+
+/**
+ * Class that holds an XSLT parameter.
+ */
+class XSLTParam {
+
+ private $name;
+
+ private $expr;
+
+ /**
+ * Sets param name.
+ * @param string $name
+ */
+ public function setName($name) {
+ $this->name = $name;
+ }
+
+ /**
+ * Get param name.
+ * @return string
+ */
+ public function getName() {
+ return $this->name;
+ }
+
+ /**
+ * Sets expression value.
+ * @param string $expr
+ */
+ public function setExpression($expr) {
+ $this->expr = $expr;
+ }
+
+ /**
+ * Sets expression to dynamic register slot.
+ * @param RegisterSlot $expr
+ */
+ public function setListeningExpression(RegisterSlot $expr) {
+ $this->expr = $expr;
+ }
+
+ /**
+ * Returns expression value -- performs lookup if expr is registerslot.
+ * @return string
+ */
+ public function getExpression() {
+ if ($this->expr instanceof RegisterSlot) {
+ return $this->expr->getValue();
+ } else {
+ return $this->expr;
+ }
+ }
+}
+
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/filters/util/ChainReaderHelper.php b/buildscripts/phing/classes/phing/filters/util/ChainReaderHelper.php
new file mode 100644
index 00000000..80508a82
--- /dev/null
+++ b/buildscripts/phing/classes/phing/filters/util/ChainReaderHelper.php
@@ -0,0 +1,184 @@
+<?php
+/*
+ * $Id: ChainReaderHelper.php,v 1.8 2005/02/27 20:52:09 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+include_once 'phing/Project.php';
+include_once 'phing/filters/BaseFilterReader.php';
+include_once 'phing/types/PhingFilterReader.php';
+include_once 'phing/types/FilterChain.php';
+include_once 'phing/types/Parameter.php';
+include_once 'phing/util/FileUtils.php';
+include_once 'phing/util/StringHelper.php';
+include_once 'phing/filters/ChainableReader.php';
+
+/**
+ * Process a FilterReader chain.
+ *
+ * Here, the interesting method is 'getAssembledReader'.
+ * The purpose of this one is to create a simple Reader object which
+ * apply all filters on another primary Reader object.
+ *
+ * For example : In copyFile (phing.util.FileUtils) the primary Reader
+ * is a FileReader object (more accuratly, a BufferedReader) previously
+ * setted for the source file to copy. So, consider this filterchain :
+ *
+ * <filterchain>
+ * <stripphpcomments />
+ * <linecontains>
+ * <contains value="foo">
+ * </linecontains>
+ * <tabtospaces tablength="8" />
+ * </filterchain>
+ *
+ * getAssembledReader will return a Reader object wich read on each
+ * of these filters. Something like this : ('->' = 'which read data from') :
+ *
+ * [TABTOSPACES] -> [LINECONTAINS] -> [STRIPPHPCOMMENTS] -> [FILEREADER]
+ * (primary reader)
+ *
+ * So, getAssembledReader will return the TABTOSPACES Reader object. Then
+ * each read done with this Reader object will follow this path.
+ *
+ * Hope this explanation is clear :)
+ *
+ * TODO: Implement the classPath feature.
+ *
+ * @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
+ * @version $Revision: 1.8 $ $Date: 2005/02/27 20:52:09 $
+ * @access public
+ * @package phing.filters.util
+*/
+class ChainReaderHelper {
+
+ /** Primary reader to wich the reader chain is to be attached */
+ private $primaryReader = null;
+
+ /** The site of the buffer to be used. */
+ private $bufferSize = 8192;
+
+ /** Chain of filters */
+ private $filterChains = array();
+
+ /** The Phing project */
+ private $project;
+
+ /*
+ * Sets the primary reader
+ */
+ function setPrimaryReader(Reader $reader) {
+ $this->primaryReader = $reader;
+ }
+
+ /*
+ * Set the project to work with
+ */
+ function setProject(Project $project) {
+ $this->project = $project;
+ }
+
+ /*
+ * Get the project
+ */
+ function getProject() {
+ return $this->project;
+ }
+
+ /*
+ * Sets the buffer size to be used. Defaults to 8192,
+ * if this method is not invoked.
+ */
+ function setBufferSize($size) {
+ $this->bufferSize = $size;
+ }
+
+ /*
+ * Sets the collection of filter reader sets
+ */
+ function setFilterChains(&$fchain) {
+ $this->filterChains = &$fchain;
+ }
+
+ /*
+ * Assemble the reader
+ */
+ function getAssembledReader() {
+
+ $instream = $this->primaryReader;
+ $filterReadersCount = count($this->filterChains);
+ $finalFilters = array();
+
+ // Collect all filter readers of all filter chains used ...
+ for($i = 0 ; $i<$filterReadersCount ; $i++) {
+ $filterchain = &$this->filterChains[$i];
+ $filterReaders = $filterchain->getFilterReaders();
+ $readerCount = count($filterReaders);
+ for($j = 0 ; $j<$readerCount ; $j++) {
+ $finalFilters[] = $filterReaders[$j];
+ }
+ }
+
+ // ... then chain the filter readers.
+ $filtersCount = count($finalFilters);
+ if ( $filtersCount > 0 ) {
+ for($i = 0 ; $i<$filtersCount ; $i++) {
+ $filter = $finalFilters[$i];
+
+ if ( $filter instanceof PhingFilterReader ) {
+
+ // This filter reader is an external class.
+ $className = $filter->getClassName();
+ $classpath = $filter->getClasspath();
+ $project = $filter->getProject();
+
+ if ( $className !== null ) {
+ $cls = Phing::import($className, $classpath);
+ $impl = new $cls();
+ }
+
+ if ( !($impl instanceof FilterReader) ) {
+ throw new Exception($className." does not extend phing.system.io.FilterReader");
+ }
+
+ $impl->setReader($instream); // chain
+ $impl->setProject($this->getProject()); // what about $project above ?
+
+ if ( $impl instanceof Parameterizable ) {
+ $impl->setParameters($filter->getParams());
+ }
+
+ $instream = $impl; // now that it's been chained
+
+ } elseif (($filter instanceof ChainableReader) && ($filter instanceof Reader)) {
+ if ( $this->getProject() !== null && ($filter instanceof BaseFilterReader) ) {
+ $filter->setProject($this->getProject());
+ }
+ $instream = $filter->chain($instream);
+ } else {
+ throw new Exception("Cannot chain invalid filter: " . get_class($filter));
+ }
+ }
+ }
+
+ return $instream;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/filters/util/IniFileTokenReader.php b/buildscripts/phing/classes/phing/filters/util/IniFileTokenReader.php
new file mode 100644
index 00000000..34bc5943
--- /dev/null
+++ b/buildscripts/phing/classes/phing/filters/util/IniFileTokenReader.php
@@ -0,0 +1,96 @@
+<?php
+/*
+ * $Id: IniFileTokenReader.php,v 1.7 2005/05/26 13:10:51 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+include_once 'phing/types/TokenReader.php';
+include_once 'phing/system/io/IOException.php';
+include_once 'phing/filters/ReplaceTokens.php'; // For class Token
+
+/**
+ * Class that allows reading tokens from INI files.
+ *
+ * @author Manuel Holtgewe
+ * @version $Revision: 1.7 $
+ * @package phing.filters.util
+ */
+class IniFileTokenReader extends TokenReader {
+
+ /**
+ * Holds the path to the INI file that is to be read.
+ * @var object Reference to a PhingFile Object representing
+ * the path to the INI file.
+ */
+ private $file = null;
+
+ /**
+ * @var string Sets the section to load from the INI file.
+ * if omitted, all sections are loaded.
+ */
+ private $section = null;
+
+ /**
+ * Reads the next token from the INI file
+ *
+ * @throws IOException On error
+ */
+ function readToken() {
+ if ($this->file === null) {
+ throw new BuildException("No File set for IniFileTokenReader");
+ }
+
+ static $tokens = null;
+ if ($tokens === null) {
+ $tokens = array();
+ $arr = parse_ini_file($this->file->getAbsolutePath(), true);
+ if ($this->section === null) {
+ foreach ($arr as $sec_name => $values) {
+ foreach($arr[$sec_name] as $key => $value) {
+ $tok = new Token;
+ $tok->setKey($key);
+ $tok->setValue($value);
+ $tokens[] = $tok;
+ }
+ }
+ } else if (isset($arr[$this->section])) {
+ foreach ($arr[$this->section] as $key => $value) {
+ $tok = new Token;
+ $tok->setKey($key);
+ $tok->setValue($value);
+ $tokens[] = $tok;
+ }
+ }
+ }
+
+ if (count($tokens) > 0) {
+ return array_pop($tokens);
+ } else
+ return null;
+ }
+
+ function setFile(PhingFile $file) {
+ $this->file = $file;
+ }
+
+ function setSection($str) {
+ $this->section = (string) $str;
+ }
+}
+
+?>
diff --git a/buildscripts/phing/classes/phing/input/DefaultInputHandler.php b/buildscripts/phing/classes/phing/input/DefaultInputHandler.php
new file mode 100644
index 00000000..8ce76cdd
--- /dev/null
+++ b/buildscripts/phing/classes/phing/input/DefaultInputHandler.php
@@ -0,0 +1,82 @@
+<?php
+
+/*
+ * $Id: DefaultInputHandler.php,v 1.6 2004/02/27 18:49:13 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/input/InputHandler.php';
+include_once 'phing/system/io/ConsoleReader.php';
+
+/**
+ * Prompts using print(); reads input from Console.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant)
+ * @version $Revision: 1.6 $
+ * @package phing.input
+ */
+class DefaultInputHandler implements InputHandler {
+
+ /**
+ * Prompts and requests input. May loop until a valid input has
+ * been entered.
+ * @throws BuildException
+ */
+ public function handleInput(InputRequest $request) {
+ $prompt = $this->getPrompt($request);
+ $in = new ConsoleReader();
+ do {
+ print $prompt;
+ try {
+ $input = $in->readLine();
+ if ($input === "" && ($request->getDefaultValue() !== null) ) {
+ $input = $request->getDefaultValue();
+ }
+ $request->setInput($input);
+ } catch (Exception $e) {
+ throw new BuildException("Failed to read input from Console.", $e);
+ }
+ } while (!$request->isInputValid());
+ }
+
+ /**
+ * Constructs user prompt from a request.
+ *
+ * <p>This implementation adds (choice1,choice2,choice3,...) to the
+ * prompt for <code>MultipleChoiceInputRequest</code>s.</p>
+ *
+ * @param $request the request to construct the prompt for.
+ * Must not be <code>null</code>.
+ */
+ protected function getPrompt(InputRequest $request) {
+ $prompt = $request->getPrompt();
+
+ // use is_a() to avoid needing the class to be loaded
+ if (is_a($request, 'YesNoInputRequest')) { // (yes/no)
+ $prompt .= '(' . implode('/', $request->getChoices()) .')';
+ } elseif (is_a($request, 'MultipleChoiceInputRequest')) { // (a,b,c,d)
+ $prompt .= '(' . implode(',', $request->getChoices()) . ')';
+ }
+ if ($request->getDefaultValue() !== null) {
+ $prompt .= ' ['.$request->getDefaultValue().']';
+ }
+ $pchar = $request->getPromptChar();
+ return $prompt . ($pchar ? $pchar . ' ' : ' ');
+ }
+}
diff --git a/buildscripts/phing/classes/phing/input/InputHandler.php b/buildscripts/phing/classes/phing/input/InputHandler.php
new file mode 100644
index 00000000..68fad7b5
--- /dev/null
+++ b/buildscripts/phing/classes/phing/input/InputHandler.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * $Id: InputHandler.php,v 1.3 2003/12/24 12:38:39 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * Plugin to Phing to handle requests for user input.
+ *
+ * @author Stefan Bodewig <stefan.bodewig@epost.de>
+ * @version $Revision: 1.3 $
+ * @package phing.input
+ */
+interface InputHandler {
+
+ /**
+ * Handle the request encapsulated in the argument.
+ *
+ * <p>Precondition: the request.getPrompt will return a non-null
+ * value.</p>
+ *
+ * <p>Postcondition: request.getInput will return a non-null
+ * value, request.isInputValid will return true.</p>
+ * @return void
+ * @throws BuildException
+ */
+ public function handleInput(InputRequest $request);
+
+}
diff --git a/buildscripts/phing/classes/phing/input/InputRequest.php b/buildscripts/phing/classes/phing/input/InputRequest.php
new file mode 100644
index 00000000..7bfe8def
--- /dev/null
+++ b/buildscripts/phing/classes/phing/input/InputRequest.php
@@ -0,0 +1,107 @@
+<?php
+
+/*
+ * $Id: InputRequest.php,v 1.4 2003/12/24 12:38:39 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * Encapsulates an input request.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant)
+ * @version $Revision: 1.4 $
+ * @package phing.input
+ */
+class InputRequest {
+
+ protected $prompt;
+ protected $input;
+ protected $defaultValue;
+ protected $promptChar;
+
+ /**
+ * @param string $prompt The prompt to show to the user. Must not be null.
+ */
+ public function __construct($prompt) {
+ if ($prompt === null) {
+ throw new BuildException("prompt must not be null");
+ }
+ $this->prompt = $prompt;
+ }
+
+ /**
+ * Retrieves the prompt text.
+ */
+ public function getPrompt() {
+ return $this->prompt;
+ }
+
+ /**
+ * Sets the user provided input.
+ */
+ public function setInput($input) {
+ $this->input = $input;
+ }
+
+ /**
+ * Is the user input valid?
+ */
+ public function isInputValid() {
+ return true;
+ }
+
+ /**
+ * Retrieves the user input.
+ */
+ public function getInput() {
+ return $this->input;
+ }
+
+ /**
+ * Set the default value to use.
+ * @param mixed $v
+ */
+ public function setDefaultValue($v) {
+ $this->defaultValue = $v;
+ }
+
+ /**
+ * Return the default value to use.
+ * @return mixed
+ */
+ public function getDefaultValue() {
+ return $this->defaultValue;
+ }
+
+ /**
+ * Set the default value to use.
+ * @param string $c
+ */
+ public function setPromptChar($c) {
+ $this->promptChar = $c;
+ }
+
+ /**
+ * Return the default value to use.
+ * @return string
+ */
+ public function getPromptChar() {
+ return $this->promptChar;
+ }
+}
diff --git a/buildscripts/phing/classes/phing/input/MultipleChoiceInputRequest.php b/buildscripts/phing/classes/phing/input/MultipleChoiceInputRequest.php
new file mode 100644
index 00000000..d4ea1212
--- /dev/null
+++ b/buildscripts/phing/classes/phing/input/MultipleChoiceInputRequest.php
@@ -0,0 +1,58 @@
+<?php
+/*
+ * $Id: MultipleChoiceInputRequest.php,v 1.5 2004/03/15 17:11:15 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/input/InputRequest.php';
+
+/**
+ * Encapsulates an input request.
+ *
+ * @author Stefan Bodewig <stefan.bodewig@epost.de>
+ * @version $Revision: 1.5 $
+ * @package phing.input
+ */
+class MultipleChoiceInputRequest extends InputRequest {
+
+ protected $choices = array();
+
+ /**
+ * @param string $prompt The prompt to show to the user. Must not be null.
+ * @param array $choices holds all input values that are allowed.
+ * Must not be null.
+ */
+ public function __construct($prompt, $choices) {
+ parent::__construct($prompt);
+ $this->choices = $choices;
+ }
+
+ /**
+ * @return The possible values.
+ */
+ public function getChoices() {
+ return $this->choices;
+ }
+
+ /**
+ * @return true if the input is one of the allowed values.
+ */
+ public function isInputValid() {
+ return in_array($this->getInput(), $this->choices); // not strict (?)
+ }
+}
diff --git a/buildscripts/phing/classes/phing/input/PropertyFileInputHandler.php b/buildscripts/phing/classes/phing/input/PropertyFileInputHandler.php
new file mode 100644
index 00000000..e588cead
--- /dev/null
+++ b/buildscripts/phing/classes/phing/input/PropertyFileInputHandler.php
@@ -0,0 +1,129 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "Ant" and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+package org.apache.tools.ant.input;
+
+import org.apache.tools.ant.BuildException;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ * Reads input from a property file, the file name is read from the
+ * system property ant.input.properties, the prompt is the key for input.
+ *
+ * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
+ * @version $Revision: 1.1 $
+ * @since Ant 1.5
+ */
+public class PropertyFileInputHandler implements InputHandler {
+ private Properties props = null;
+
+ /**
+ * Name of the system property we expect to hold the file name.
+ */
+ public static final String FILE_NAME_KEY = "ant.input.properties";
+
+ /**
+ * Empty no-arg constructor.
+ */
+ public PropertyFileInputHandler() {
+ }
+
+ /**
+ * Picks up the input from a property, using the prompt as the
+ * name of the property.
+ *
+ * @exception BuildException if no property of that name can be found.
+ */
+ public void handleInput(InputRequest request) throws BuildException {
+ readProps();
+
+ Object o = props.get(request.getPrompt());
+ if (o == null) {
+ throw new BuildException("Unable to find input for \'"
+ + request.getPrompt()+"\'");
+ }
+ request.setInput(o.toString());
+ if (!request.isInputValid()) {
+ throw new BuildException("Found invalid input " + o
+ + " for \'" + request.getPrompt() + "\'");
+ }
+ }
+
+ /**
+ * Reads the properties file if it hasn't already been read.
+ */
+ private synchronized void readProps() throws BuildException {
+ if (props == null) {
+ String propsFile = System.getProperty(FILE_NAME_KEY);
+ if (propsFile == null) {
+ throw new BuildException("System property "
+ + FILE_NAME_KEY
+ + " for PropertyFileInputHandler not"
+ + " set");
+ }
+
+ props = new Properties();
+
+ try {
+ props.load(new FileInputStream(propsFile));
+ } catch (IOException e) {
+ throw new BuildException("Couldn't load " + propsFile, e);
+ }
+ }
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/input/YesNoInputRequest.php b/buildscripts/phing/classes/phing/input/YesNoInputRequest.php
new file mode 100644
index 00000000..e34863d5
--- /dev/null
+++ b/buildscripts/phing/classes/phing/input/YesNoInputRequest.php
@@ -0,0 +1,47 @@
+<?php
+/*
+ * $Id: YesNoInputRequest.php,v 1.4 2003/12/24 12:38:39 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/input/MultipleChoiceInputRequest.php';
+
+/**
+ * Encapsulates an input request that returns a boolean (yes/no).
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.4 $
+ * @package phing.input
+ */
+class YesNoInputRequest extends MultipleChoiceInputRequest {
+
+ /**
+ * @return true if the input is one of the allowed values.
+ */
+ public function isInputValid() {
+ return StringHelper::isBoolean($this->input);
+ }
+
+ /**
+ * Converts input to boolean.
+ * @return boolean
+ */
+ public function getInput() {
+ return StringHelper::booleanValue($this->input);
+ }
+}
diff --git a/buildscripts/phing/classes/phing/lib/Capsule.php b/buildscripts/phing/classes/phing/lib/Capsule.php
new file mode 100644
index 00000000..bab05486
--- /dev/null
+++ b/buildscripts/phing/classes/phing/lib/Capsule.php
@@ -0,0 +1,266 @@
+<?php
+
+/**
+ * Capsule is a simple "template" engine that essentially provides an isolated context
+ * for PHP scripts.
+ *
+ * There is no special templating language, and therefore no limitations to what
+ * can be accomplished within templates. The main purpose of Capsule is to separate
+ * the business logic from display / output logic.
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.9 $ $Date: 2004/08/31 20:12:02 $
+ */
+class Capsule {
+
+ /**
+ * Look for templates here (if relative path provided).
+ * @var string
+ */
+ protected $templatePath;
+
+ /**
+ * Where should output files be written?
+ * (This is named inconsistently to be compatible w/ Texen.)
+ * @var string
+ */
+ protected $outputDirectory;
+
+ /**
+ * The variables that can be used by the templates.
+ * @var array Hash of variables.
+ */
+ public $vars = array();
+
+ /**
+ * Has template been initialized.
+ */
+ protected $initialized = false;
+
+ /**
+ * Stores the pre-parse() include_path.
+ * @var string
+ */
+ private $old_include_path;
+
+ function __construct() {
+ }
+
+ /**
+ * Clears one or several or all variables.
+ * @param mixed $which String name of var, or array of names.
+ * @return void
+ */
+ function clear($which = null) {
+ if ($which === null) {
+ $this->vars = array();
+ } elseif (is_array($which)) {
+ foreach($which as $var) {
+ unset($this->vars[$var]);
+ }
+ } else {
+ unset($this->vars[$which]);
+ }
+ }
+
+ /**
+ * Set the basepath to use for template lookups.
+ * @param string $v
+ */
+ function setTemplatePath($v) {
+ $this->templatePath = rtrim($v, DIRECTORY_SEPARATOR.'/');
+ }
+
+ /**
+ * Get the basepath to use for template lookups.
+ * @return string
+ */
+ function getTemplatePath() {
+ return $this->templatePath;
+ }
+
+ /**
+ * Set a basepath to use for output file creation.
+ * @param string $v
+ */
+ function setOutputDirectory($v) {
+ $this->outputDirectory = rtrim($v, DIRECTORY_SEPARATOR.'/');
+ }
+
+ /**
+ * Get basepath to use for output file creation.
+ * @return string
+ */
+ function getOutputDirectory() {
+ return $this->outputDirectory;
+ }
+
+ /**
+ * Low overhead (no output buffering) method to simply dump template
+ * to buffer.
+ *
+ * @param string $__template
+ * @return void
+ * @throws Exception - if template cannot be found
+ */
+ function display($__template) {
+
+ // Prepend "private" variable names with $__ in this function
+ // to keep namespace conflict potential to a minimum.
+
+ // Alias this class to $generator.
+ $generator = $this;
+
+ if (isset($this->vars['this'])) {
+ throw new Exception("Assigning a variable named \$this to a context conflicts with class namespace.");
+ }
+
+ // extract variables into local namespace
+ extract($this->vars);
+
+ // prepend template path to include path,
+ // so that include "path/relative/to/templates"; can be used within templates
+ $__old_inc_path = ini_get('include_path');
+ ini_set('include_path', $this->templatePath . PATH_SEPARATOR . $__old_inc_path);
+
+ @ini_set('track_errors', true);
+ include $__template;
+ @ini_restore('track_errors');
+
+ // restore the include path
+ ini_set('include_path', $__old_inc_path);
+
+ if (!empty($php_errormsg)) {
+ throw new Exception("Unable to parse template " . $__template . ": " . $php_errormsg);
+ }
+ }
+
+ /**
+ * Fetches the results of a tempalte parse and either returns
+ * the string or writes results to a specified output file.
+ *
+ * @param string $template The template filename (relative to templatePath or absolute).
+ * @param string $outputFile If specified, contents of template will also be written to this file.
+ * @param boolean $append Should output be appended to source file?
+ * @return string The "parsed" template output.
+ * @throws Exception - if template not found.
+ */
+ function parse($template, $outputFile = null, $append = false) {
+
+ // main work done right here:
+ // hopefully this works recursively ... fingers crossed.
+ ob_start();
+
+ try {
+ $this->display($template);
+ } catch (Exception $e) {
+ ob_end_flush(); // flush the output on error (so we can see up to what point it parsed everything)
+ throw $e;
+ }
+
+ $output = ob_get_contents();
+ ob_end_clean();
+
+ if ($outputFile !== null) {
+ $outputFile = $this->resolvePath($outputFile, $this->outputDirectory);
+
+ $flags = null;
+ if ($append) $flags = FILE_APPEND;
+
+ if (!file_put_contents($outputFile, $output, $flags) && $output != "") {
+ throw new Exception("Unable to write output to " . $outputFile);
+ }
+ }
+
+ return $output;
+ }
+
+ /**
+ * This returns a "best guess" path for the given file.
+ *
+ * @param string $file File name or possibly absolute path.
+ * @param string $basepath The basepath that should be prepended if $file is not absolute.
+ * @return string "Best guess" path for this file.
+ */
+ protected function resolvePath($file, $basepath) {
+ if ( !($file{0} == DIRECTORY_SEPARATOR || $file{0} == '/')
+ // also account for C:\ style path
+ && !($file{1} == ':' && ($file{2} == DIRECTORY_SEPARATOR || $file{2} == '/'))) {
+ if ($basepath != null) {
+ $file = $basepath . DIRECTORY_SEPARATOR . $file;
+ }
+ }
+ return $file;
+ }
+
+ /**
+ * Gets value of specified var or NULL if var has not been put().
+ * @param string $name Variable name to retrieve.
+ * @return mixed
+ */
+ function get($name) {
+ if (!isset($this->vars[$name])) return null;
+ return $this->vars[$name];
+ }
+
+ /**
+ * Merges in passed hash to vars array.
+ *
+ * Given an array like:
+ *
+ * array( 'myvar' => 'Hello',
+ * 'myvar2' => 'Hello')
+ *
+ * Resulting template will have access to $myvar and $myvar2.
+ *
+ * @param array $vars
+ * @param boolean $recursiveMerge Should matching keys be recursively merged?
+ * @return void
+ */
+ function putAll($vars, $recursiveMerge = false) {
+ if ($recursiveMerge) {
+ $this->vars = array_merge_recursive($this->vars, $vars);
+ } else {
+ $this->vars = array_merge($this->vars, $vars);
+ }
+ }
+
+ /**
+ * Adds a variable to the context.
+ *
+ * Resulting template will have access to ${$name$} variable.
+ *
+ * @param string $name
+ * @param mixed $value
+ */
+ function put($name, $value) {
+ $this->vars[$name] = $value;
+ }
+
+ /**
+ * Put a variable into the context, assigning it by reference.
+ * This means that if the template modifies the variable, then it
+ * will also be modified in the context.
+ *
+ * @param $name
+ * @param &$value
+ */
+ function putRef($name, &$value) {
+ $this->vars[$name] = &$value;
+ }
+
+ /**
+ * Makes a copy of the value and puts it into the context.
+ * This is primarily to force copying (cloning) of objects, rather
+ * than the default behavior which is to assign them by reference.
+ * @param string $name
+ * @param mixed $value
+ */
+ function putCopy($name, $value) {
+ if (is_object($value)) {
+ $value = clone $value;
+ }
+ $this->vars[$name] = $value;
+ }
+
+} \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/lib/Zip.php b/buildscripts/phing/classes/phing/lib/Zip.php
new file mode 100644
index 00000000..70d31595
--- /dev/null
+++ b/buildscripts/phing/classes/phing/lib/Zip.php
@@ -0,0 +1,3588 @@
+<?php
+/* vim: set ts=4 sw=4: */
+// +----------------------------------------------------------------------+
+// | PHP Version 4 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 3.0 of the PHP license, |
+// | that is bundled with this package in the file LICENSE, and is |
+// | available through the world-wide-web at the following url: |
+// | http://www.php.net/license/3_0.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +----------------------------------------------------------------------+
+// | Author: Vincent Blavet <vincent@blavet.net> |
+// +----------------------------------------------------------------------+
+//
+// $Id: Zip.php,v 1.3 2005/12/27 16:05:57 hlellelid Exp $
+
+ // ----- Constants
+ define( 'ARCHIVE_ZIP_READ_BLOCK_SIZE', 2048 );
+
+ // ----- File list separator
+ define( 'ARCHIVE_ZIP_SEPARATOR', ',' );
+
+ // ----- Optional static temporary directory
+ // By default temporary files are generated in the script current
+ // path.
+ // If defined :
+ // - MUST BE terminated by a '/'.
+ // - MUST be a valid, already created directory
+ // Samples :
+ // define( 'ARCHIVE_ZIP_TEMPORARY_DIR', '/temp/' );
+ // define( 'ARCHIVE_ZIP_TEMPORARY_DIR', 'C:/Temp/' );
+ define( 'ARCHIVE_ZIP_TEMPORARY_DIR', '' );
+
+ // ----- Error codes
+ define( 'ARCHIVE_ZIP_ERR_NO_ERROR', 0 );
+ define( 'ARCHIVE_ZIP_ERR_WRITE_OPEN_FAIL', -1 );
+ define( 'ARCHIVE_ZIP_ERR_READ_OPEN_FAIL', -2 );
+ define( 'ARCHIVE_ZIP_ERR_INVALID_PARAMETER', -3 );
+ define( 'ARCHIVE_ZIP_ERR_MISSING_FILE', -4 );
+ define( 'ARCHIVE_ZIP_ERR_FILENAME_TOO_LONG', -5 );
+ define( 'ARCHIVE_ZIP_ERR_INVALID_ZIP', -6 );
+ define( 'ARCHIVE_ZIP_ERR_BAD_EXTRACTED_FILE', -7 );
+ define( 'ARCHIVE_ZIP_ERR_DIR_CREATE_FAIL', -8 );
+ define( 'ARCHIVE_ZIP_ERR_BAD_EXTENSION', -9 );
+ define( 'ARCHIVE_ZIP_ERR_BAD_FORMAT', -10 );
+ define( 'ARCHIVE_ZIP_ERR_DELETE_FILE_FAIL', -11 );
+ define( 'ARCHIVE_ZIP_ERR_RENAME_FILE_FAIL', -12 );
+ define( 'ARCHIVE_ZIP_ERR_BAD_CHECKSUM', -13 );
+ define( 'ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP', -14 );
+ define( 'ARCHIVE_ZIP_ERR_MISSING_OPTION_VALUE', -15 );
+ define( 'ARCHIVE_ZIP_ERR_INVALID_PARAM_VALUE', -16 );
+
+ // ----- Warning codes
+ define( 'ARCHIVE_ZIP_WARN_NO_WARNING', 0 );
+ define( 'ARCHIVE_ZIP_WARN_FILE_EXIST', 1 );
+
+ // ----- Methods parameters
+ define( 'ARCHIVE_ZIP_PARAM_PATH', 'path' );
+ define( 'ARCHIVE_ZIP_PARAM_ADD_PATH', 'add_path' );
+ define( 'ARCHIVE_ZIP_PARAM_REMOVE_PATH', 'remove_path' );
+ define( 'ARCHIVE_ZIP_PARAM_REMOVE_ALL_PATH', 'remove_all_path' );
+ define( 'ARCHIVE_ZIP_PARAM_SET_CHMOD', 'set_chmod' );
+ define( 'ARCHIVE_ZIP_PARAM_EXTRACT_AS_STRING', 'extract_as_string' );
+ define( 'ARCHIVE_ZIP_PARAM_NO_COMPRESSION', 'no_compression' );
+ define( 'ARCHIVE_ZIP_PARAM_BY_NAME', 'by_name' );
+ define( 'ARCHIVE_ZIP_PARAM_BY_INDEX', 'by_index' );
+ define( 'ARCHIVE_ZIP_PARAM_BY_EREG', 'by_ereg' );
+ define( 'ARCHIVE_ZIP_PARAM_BY_PREG', 'by_preg' );
+
+ define( 'ARCHIVE_ZIP_PARAM_PRE_EXTRACT', 'callback_pre_extract' );
+ define( 'ARCHIVE_ZIP_PARAM_POST_EXTRACT', 'callback_post_extract' );
+ define( 'ARCHIVE_ZIP_PARAM_PRE_ADD', 'callback_pre_add' );
+ define( 'ARCHIVE_ZIP_PARAM_POST_ADD', 'callback_post_add' );
+
+
+
+/**
+* Class for manipulating zip archive files
+*
+* A class which provided common methods to manipulate ZIP formatted
+* archive files.
+* It provides creation, extraction, deletion and add features.
+*
+* @author Vincent Blavet <vincent@blavet.net>
+* @version $Revision: 1.3 $
+* @package phing.lib
+*/
+class Archive_Zip
+{
+ /**
+ * The filename of the zip archive.
+ *
+ * @var string Name of the Zip file
+ */
+ var $_zipname='';
+
+ /**
+ * File descriptor of the opened Zip file.
+ *
+ * @var int Internal zip file descriptor
+ */
+ var $_zip_fd=0;
+
+ /**
+ * @var int last error code
+ */
+ var $_error_code=1;
+
+ /**
+ * @var string Last error description
+ */
+ var $_error_string='';
+
+ // {{{ constructor
+ /**
+ * Archive_Zip Class constructor. This flavour of the constructor only
+ * declare a new Archive_Zip object, identifying it by the name of the
+ * zip file.
+ *
+ * @param string $p_zipname The name of the zip archive to create
+ * @access public
+ */
+ function __construct($p_zipname)
+ {
+ if (!extension_loaded('zlib')) {
+ throw new Exception("The extension 'zlib' couldn't be found.\n".
+ "Please make sure your version of PHP was built ".
+ "with 'zlib' support.");
+ }
+
+ // ----- Set the attributes
+ $this->_zipname = $p_zipname;
+ $this->_zip_fd = 0;
+ }
+ // }}}
+
+ // {{{ create()
+ /**
+ * This method creates a Zip Archive with the filename set with
+ * the constructor.
+ * The files and directories indicated in $p_filelist
+ * are added in the archive.
+ * When a directory is in the list, the directory and its content is added
+ * in the archive.
+ * The methods takes a variable list of parameters in $p_params.
+ * The supported parameters for this method are :
+ * 'add_path' : Add a path to the archived files.
+ * 'remove_path' : Remove the specified 'root' path of the archived files.
+ * 'remove_all_path' : Remove all the path of the archived files.
+ * 'no_compression' : The archived files will not be compressed.
+ *
+ * @access public
+ * @param mixed $p_filelist The list of the files or folders to add.
+ * It can be a string with filenames separated
+ * by a comma, or an array of filenames.
+ * @param mixed $p_params An array of variable parameters and values.
+ * @return mixed An array of file description on success,
+ * an error code on error
+ */
+ function create($p_filelist, $p_params=0)
+ {
+ $this->_errorReset();
+
+ // ----- Set default values
+ if ($p_params === 0) {
+ $p_params = array();
+ }
+ if ($this->_check_parameters($p_params,
+ array('no_compression' => false,
+ 'add_path' => "",
+ 'remove_path' => "",
+ 'remove_all_path' => false)) != 1) {
+ return 0;
+ }
+
+ // ----- Look if the $p_filelist is really an array
+ $p_result_list = array();
+ if (is_array($p_filelist)) {
+ $v_result = $this->_create($p_filelist, $p_result_list, $p_params);
+ }
+
+ // ----- Look if the $p_filelist is a string
+ else if (is_string($p_filelist)) {
+ // ----- Create a list with the elements from the string
+ $v_list = explode(ARCHIVE_ZIP_SEPARATOR, $p_filelist);
+
+ $v_result = $this->_create($v_list, $p_result_list, $p_params);
+ }
+
+ // ----- Invalid variable
+ else {
+ $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER,
+ 'Invalid variable type p_filelist');
+ $v_result = ARCHIVE_ZIP_ERR_INVALID_PARAMETER;
+ }
+
+ if ($v_result != 1) {
+ return 0;
+ }
+
+ return $p_result_list;
+ }
+ // }}}
+
+ // {{{ add()
+ /**
+ * This method add files or directory in an existing Zip Archive.
+ * If the Zip Archive does not exist it is created.
+ * The files and directories to add are indicated in $p_filelist.
+ * When a directory is in the list, the directory and its content is added
+ * in the archive.
+ * The methods takes a variable list of parameters in $p_params.
+ * The supported parameters for this method are :
+ * 'add_path' : Add a path to the archived files.
+ * 'remove_path' : Remove the specified 'root' path of the archived files.
+ * 'remove_all_path' : Remove all the path of the archived files.
+ * 'no_compression' : The archived files will not be compressed.
+ * 'callback_pre_add' : A callback function that will be called before
+ * each entry archiving.
+ * 'callback_post_add' : A callback function that will be called after
+ * each entry archiving.
+ *
+ * @access public
+ * @param mixed $p_filelist The list of the files or folders to add.
+ * It can be a string with filenames separated
+ * by a comma, or an array of filenames.
+ * @param mixed $p_params An array of variable parameters and values.
+ * @return mixed An array of file description on success,
+ * 0 on an unrecoverable failure, an error code is logged.
+ */
+ function add($p_filelist, $p_params=0)
+ {
+ $this->_errorReset();
+
+ // ----- Set default values
+ if ($p_params === 0) {
+ $p_params = array();
+ }
+ if ($this->_check_parameters($p_params,
+ array ('no_compression' => false,
+ 'add_path' => '',
+ 'remove_path' => '',
+ 'remove_all_path' => false,
+ 'callback_pre_add' => '',
+ 'callback_post_add' => '')) != 1) {
+ return 0;
+ }
+
+ // ----- Look if the $p_filelist is really an array
+ $p_result_list = array();
+ if (is_array($p_filelist)) {
+ // ----- Call the create fct
+ $v_result = $this->_add($p_filelist, $p_result_list, $p_params);
+ }
+
+ // ----- Look if the $p_filelist is a string
+ else if (is_string($p_filelist)) {
+ // ----- Create a list with the elements from the string
+ $v_list = explode(ARCHIVE_ZIP_SEPARATOR, $p_filelist);
+
+ // ----- Call the create fct
+ $v_result = $this->_add($v_list, $p_result_list, $p_params);
+ }
+
+ // ----- Invalid variable
+ else {
+ $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER,
+ "add() : Invalid variable type p_filelist");
+ $v_result = ARCHIVE_ZIP_ERR_INVALID_PARAMETER;
+ }
+
+ if ($v_result != 1) {
+ return 0;
+ }
+
+ // ----- Return the result list
+ return $p_result_list;
+ }
+ // }}}
+
+ // {{{ listContent()
+ /**
+ * This method gives the names and properties of the files and directories
+ * which are present in the zip archive.
+ * The properties of each entries in the list are :
+ * filename : Name of the file.
+ * For create() or add() it's the filename given by the user.
+ * For an extract() it's the filename of the extracted file.
+ * stored_filename : Name of the file / directory stored in the archive.
+ * size : Size of the stored file.
+ * compressed_size : Size of the file's data compressed in the archive
+ * (without the zip headers overhead)
+ * mtime : Last known modification date of the file (UNIX timestamp)
+ * comment : Comment associated with the file
+ * folder : true | false (indicates if the entry is a folder)
+ * index : index of the file in the archive (-1 when not available)
+ * status : status of the action on the entry (depending of the action) :
+ * Values are :
+ * ok : OK !
+ * filtered : the file/dir was not extracted (filtered by user)
+ * already_a_directory : the file can't be extracted because a
+ * directory with the same name already
+ * exists
+ * write_protected : the file can't be extracted because a file
+ * with the same name already exists and is
+ * write protected
+ * newer_exist : the file was not extracted because a newer
+ * file already exists
+ * path_creation_fail : the file is not extracted because the
+ * folder does not exists and can't be
+ * created
+ * write_error : the file was not extracted because there was a
+ * error while writing the file
+ * read_error : the file was not extracted because there was a
+ * error while reading the file
+ * invalid_header : the file was not extracted because of an
+ * archive format error (bad file header)
+ * Note that each time a method can continue operating when there
+ * is an error on a single file, the error is only logged in the file status.
+ *
+ * @access public
+ * @return mixed An array of file description on success,
+ * 0 on an unrecoverable failure, an error code is logged.
+ */
+ function listContent()
+ {
+ $this->_errorReset();
+
+ // ----- Check archive
+ if (!$this->_checkFormat()) {
+ return(0);
+ }
+
+ $v_list = array();
+ if ($this->_list($v_list) != 1) {
+ unset($v_list);
+ return(0);
+ }
+
+ return $v_list;
+ }
+ // }}}
+
+ // {{{ extract()
+ /**
+ * This method extract the files and folders which are in the zip archive.
+ * It can extract all the archive or a part of the archive by using filter
+ * feature (extract by name, by index, by ereg, by preg). The extraction
+ * can occur in the current path or an other path.
+ * All the advanced features are activated by the use of variable
+ * parameters.
+ * The return value is an array of entry descriptions which gives
+ * information on extracted files (See listContent()).
+ * The method may return a success value (an array) even if some files
+ * are not correctly extracted (see the file status in listContent()).
+ * The supported variable parameters for this method are :
+ * 'add_path' : Path where the files and directories are to be extracted
+ * 'remove_path' : First part ('root' part) of the memorized path
+ * (if similar) to remove while extracting.
+ * 'remove_all_path' : Remove all the memorized path while extracting.
+ * 'extract_as_string' :
+ * 'set_chmod' : After the extraction of the file the indicated mode
+ * will be set.
+ * 'by_name' : It can be a string with file/dir names separated by ',',
+ * or an array of file/dir names to extract from the archive.
+ * 'by_index' : A string with range of indexes separated by ',',
+ * (sample "1,3-5,12").
+ * 'by_ereg' : A regular expression (ereg) that must match the extracted
+ * filename.
+ * 'by_preg' : A regular expression (preg) that must match the extracted
+ * filename.
+ * 'callback_pre_extract' : A callback function that will be called before
+ * each entry extraction.
+ * 'callback_post_extract' : A callback function that will be called after
+ * each entry extraction.
+ *
+ * @access public
+ * @param mixed $p_params An array of variable parameters and values.
+ * @return mixed An array of file description on success,
+ * 0 on an unrecoverable failure, an error code is logged.
+ */
+ function extract($p_params=0)
+ {
+
+ $this->_errorReset();
+
+ // ----- Check archive
+ if (!$this->_checkFormat()) {
+ return(0);
+ }
+
+ // ----- Set default values
+ if ($p_params === 0) {
+ $p_params = array();
+ }
+ if ($this->_check_parameters($p_params,
+ array ('extract_as_string' => false,
+ 'add_path' => '',
+ 'remove_path' => '',
+ 'remove_all_path' => false,
+ 'callback_pre_extract' => '',
+ 'callback_post_extract' => '',
+ 'set_chmod' => 0,
+ 'by_name' => '',
+ 'by_index' => '',
+ 'by_ereg' => '',
+ 'by_preg' => '') ) != 1) {
+ return 0;
+ }
+
+ // ----- Call the extracting fct
+ $v_list = array();
+ if ($this->_extractByRule($v_list, $p_params) != 1) {
+ unset($v_list);
+ return(0);
+ }
+
+ return $v_list;
+ }
+ // }}}
+
+
+ // {{{ delete()
+ /**
+ * This methods delete archive entries in the zip archive.
+ * Notice that at least one filtering rule (set by the variable parameter
+ * list) must be set.
+ * Also notice that if you delete a folder entry, only the folder entry
+ * is deleted, not all the files bellonging to this folder.
+ * The supported variable parameters for this method are :
+ * 'by_name' : It can be a string with file/dir names separated by ',',
+ * or an array of file/dir names to delete from the archive.
+ * 'by_index' : A string with range of indexes separated by ',',
+ * (sample "1,3-5,12").
+ * 'by_ereg' : A regular expression (ereg) that must match the extracted
+ * filename.
+ * 'by_preg' : A regular expression (preg) that must match the extracted
+ * filename.
+ *
+ * @access public
+ * @param mixed $p_params An array of variable parameters and values.
+ * @return mixed An array of file description on success,
+ * 0 on an unrecoverable failure, an error code is logged.
+ */
+ function delete($p_params)
+ {
+ $this->_errorReset();
+
+ // ----- Check archive
+ if (!$this->_checkFormat()) {
+ return(0);
+ }
+
+ // ----- Set default values
+ if ($this->_check_parameters($p_params,
+ array ('by_name' => '',
+ 'by_index' => '',
+ 'by_ereg' => '',
+ 'by_preg' => '') ) != 1) {
+ return 0;
+ }
+
+ // ----- Check that at least one rule is set
+ if ( ($p_params['by_name'] == '')
+ && ($p_params['by_index'] == '')
+ && ($p_params['by_ereg'] == '')
+ && ($p_params['by_preg'] == '')) {
+ $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER,
+ 'At least one filtering rule must'
+ .' be set as parameter');
+ return 0;
+ }
+
+ // ----- Call the delete fct
+ $v_list = array();
+ if ($this->_deleteByRule($v_list, $p_params) != 1) {
+ unset($v_list);
+ return(0);
+ }
+
+ return $v_list;
+ }
+ // }}}
+
+ // {{{ properties()
+ /**
+ * This method gives the global properties of the archive.
+ * The properties are :
+ * nb : Number of files in the archive
+ * comment : Comment associated with the archive file
+ * status : not_exist, ok
+ *
+ * @access public
+ * @param mixed $p_params {Description}
+ * @return mixed An array with the global properties or 0 on error.
+ */
+ function properties()
+ {
+ $this->_errorReset();
+
+ // ----- Check archive
+ if (!$this->_checkFormat()) {
+ return(0);
+ }
+
+ // ----- Default properties
+ $v_prop = array();
+ $v_prop['comment'] = '';
+ $v_prop['nb'] = 0;
+ $v_prop['status'] = 'not_exist';
+
+ // ----- Look if file exists
+ if (@is_file($this->_zipname)) {
+ // ----- Open the zip file
+ if (($this->_zip_fd = @fopen($this->_zipname, 'rb')) == 0) {
+ $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL,
+ 'Unable to open archive \''.$this->_zipname
+ .'\' in binary read mode');
+ return 0;
+ }
+
+ // ----- Read the central directory informations
+ $v_central_dir = array();
+ if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1) {
+ return 0;
+ }
+
+ $this->_closeFd();
+
+ // ----- Set the user attributes
+ $v_prop['comment'] = $v_central_dir['comment'];
+ $v_prop['nb'] = $v_central_dir['entries'];
+ $v_prop['status'] = 'ok';
+ }
+
+ return $v_prop;
+ }
+ // }}}
+
+
+ // {{{ duplicate()
+ /**
+ * This method creates an archive by copying the content of an other one.
+ * If the archive already exist, it is replaced by the new one without
+ * any warning.
+ *
+ * @access public
+ * @param mixed $p_archive It can be a valid Archive_Zip object or
+ * the filename of a valid zip archive.
+ * @return integer 1 on success, 0 on failure.
+ */
+ function duplicate($p_archive)
+ {
+ $this->_errorReset();
+
+ // ----- Look if the $p_archive is a Archive_Zip object
+ if ( (is_object($p_archive))
+ && (strtolower(get_class($p_archive)) == 'archive_zip')) {
+ $v_result = $this->_duplicate($p_archive->_zipname);
+ }
+
+ // ----- Look if the $p_archive is a string (so a filename)
+ else if (is_string($p_archive)) {
+ // ----- Check that $p_archive is a valid zip file
+ // TBC : Should also check the archive format
+ if (!is_file($p_archive)) {
+ $this->_errorLog(ARCHIVE_ZIP_ERR_MISSING_FILE,
+ "No file with filename '".$p_archive."'");
+ $v_result = ARCHIVE_ZIP_ERR_MISSING_FILE;
+ }
+ else {
+ $v_result = $this->_duplicate($p_archive);
+ }
+ }
+
+ // ----- Invalid variable
+ else {
+ $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER,
+ "Invalid variable type p_archive_to_add");
+ $v_result = ARCHIVE_ZIP_ERR_INVALID_PARAMETER;
+ }
+
+ return $v_result;
+ }
+ // }}}
+
+ // {{{ merge()
+ /**
+ * This method merge a valid zip archive at the end of the
+ * archive identified by the Archive_Zip object.
+ * If the archive ($this) does not exist, the merge becomes a duplicate.
+ * If the archive to add does not exist, the merge is a success.
+ *
+ * @access public
+ * @param mixed $p_archive_to_add It can be a valid Archive_Zip object or
+ * the filename of a valid zip archive.
+ * @return integer 1 on success, 0 on failure.
+ */
+ function merge($p_archive_to_add)
+ {
+ $v_result = 1;
+ $this->_errorReset();
+
+ // ----- Check archive
+ if (!$this->_checkFormat()) {
+ return(0);
+ }
+
+ // ----- Look if the $p_archive_to_add is a Archive_Zip object
+ if ( (is_object($p_archive_to_add))
+ && (strtolower(get_class($p_archive_to_add)) == 'archive_zip')) {
+ $v_result = $this->_merge($p_archive_to_add);
+ }
+
+ // ----- Look if the $p_archive_to_add is a string (so a filename)
+ else if (is_string($p_archive_to_add)) {
+ // ----- Create a temporary archive
+ $v_object_archive = new Archive_Zip($p_archive_to_add);
+
+ // ----- Merge the archive
+ $v_result = $this->_merge($v_object_archive);
+ }
+
+ // ----- Invalid variable
+ else {
+ $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER,
+ "Invalid variable type p_archive_to_add");
+ $v_result = ARCHIVE_ZIP_ERR_INVALID_PARAMETER;
+ }
+
+ return $v_result;
+ }
+ // }}}
+
+ // {{{ errorCode()
+ /**
+ * Method that gives the lastest error code.
+ *
+ * @access public
+ * @return integer The error code value.
+ */
+ function errorCode()
+ {
+ return($this->_error_code);
+ }
+ // }}}
+
+ // {{{ errorName()
+ /**
+ * This method gives the latest error code name.
+ *
+ * @access public
+ * @param boolean $p_with_code If true, gives the name and the int value.
+ * @return string The error name.
+ */
+ function errorName($p_with_code=false)
+ {
+ $v_const_list = get_defined_constants();
+
+ // ----- Extract error constants from all const.
+ for (reset($v_const_list);
+ list($v_key, $v_value) = each($v_const_list);) {
+ if (substr($v_key, 0, strlen('ARCHIVE_ZIP_ERR_'))
+ =='ARCHIVE_ZIP_ERR_') {
+ $v_error_list[$v_key] = $v_value;
+ }
+ }
+
+ // ----- Search the name form the code value
+ $v_key=array_search($this->_error_code, $v_error_list, true);
+ if ($v_key!=false) {
+ $v_value = $v_key;
+ }
+ else {
+ $v_value = 'NoName';
+ }
+
+ if ($p_with_code) {
+ return($v_value.' ('.$this->_error_code.')');
+ }
+ else {
+ return($v_value);
+ }
+ }
+ // }}}
+
+ // {{{ errorInfo()
+ /**
+ * This method returns the description associated with the latest error.
+ *
+ * @access public
+ * @param boolean $p_full If set to true gives the description with the
+ * error code, the name and the description.
+ * If set to false gives only the description
+ * and the error code.
+ * @return string The error description.
+ */
+ function errorInfo($p_full=false)
+ {
+ if ($p_full) {
+ return($this->errorName(true)." : ".$this->_error_string);
+ }
+ else {
+ return($this->_error_string." [code ".$this->_error_code."]");
+ }
+ }
+ // }}}
+
+
+// -----------------------------------------------------------------------------
+// ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS *****
+// ***** *****
+// ***** THESES FUNCTIONS MUST NOT BE USED DIRECTLY *****
+// -----------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _checkFormat()
+ // Description :
+ // This method check that the archive exists and is a valid zip archive.
+ // Several level of check exists. (futur)
+ // Parameters :
+ // $p_level : Level of check. Default 0.
+ // 0 : Check the first bytes (magic codes) (default value))
+ // 1 : 0 + Check the central directory (futur)
+ // 2 : 1 + Check each file header (futur)
+ // Return Values :
+ // true on success,
+ // false on error, the error code is set.
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_checkFormat()
+ *
+ * { Description }
+ *
+ * @param integer $p_level
+ */
+ function _checkFormat($p_level=0)
+ {
+ $v_result = true;
+
+ // ----- Reset the error handler
+ $this->_errorReset();
+
+ // ----- Look if the file exits
+ if (!is_file($this->_zipname)) {
+ // ----- Error log
+ $this->_errorLog(ARCHIVE_ZIP_ERR_MISSING_FILE,
+ "Missing archive file '".$this->_zipname."'");
+ return(false);
+ }
+
+ // ----- Check that the file is readeable
+ if (!is_readable($this->_zipname)) {
+ // ----- Error log
+ $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL,
+ "Unable to read archive '".$this->_zipname."'");
+ return(false);
+ }
+
+ // ----- Check the magic code
+ // TBC
+
+ // ----- Check the central header
+ // TBC
+
+ // ----- Check each file header
+ // TBC
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _create()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_create()
+ *
+ * { Description }
+ *
+ */
+ function _create($p_list, &$p_result_list, &$p_params)
+ {
+ $v_result=1;
+ $v_list_detail = array();
+
+ $p_add_dir = $p_params['add_path'];
+ $p_remove_dir = $p_params['remove_path'];
+ $p_remove_all_dir = $p_params['remove_all_path'];
+
+ // ----- Open the file in write mode
+ if (($v_result = $this->_openFd('wb')) != 1)
+ {
+ // ----- Return
+ return $v_result;
+ }
+
+ // ----- Add the list of files
+ $v_result = $this->_addList($p_list, $p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_params);
+
+ // ----- Close
+ $this->_closeFd();
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _add()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_add()
+ *
+ * { Description }
+ *
+ */
+ function _add($p_list, &$p_result_list, &$p_params)
+ {
+ $v_result=1;
+ $v_list_detail = array();
+
+ $p_add_dir = $p_params['add_path'];
+ $p_remove_dir = $p_params['remove_path'];
+ $p_remove_all_dir = $p_params['remove_all_path'];
+
+ // ----- Look if the archive exists or is empty and need to be created
+ if ((!is_file($this->_zipname)) || (filesize($this->_zipname) == 0)) {
+ $v_result = $this->_create($p_list, $p_result_list, $p_params);
+ return $v_result;
+ }
+
+ // ----- Open the zip file
+ if (($v_result=$this->_openFd('rb')) != 1) {
+ return $v_result;
+ }
+
+ // ----- Read the central directory informations
+ $v_central_dir = array();
+ if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1)
+ {
+ $this->_closeFd();
+ return $v_result;
+ }
+
+ // ----- Go to beginning of File
+ @rewind($this->_zip_fd);
+
+ // ----- Creates a temporay file
+ $v_zip_temp_name = ARCHIVE_ZIP_TEMPORARY_DIR.uniqid('archive_zip-').'.tmp';
+
+ // ----- Open the temporary file in write mode
+ if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
+ {
+ $this->_closeFd();
+
+ $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL,
+ 'Unable to open temporary file \''
+ .$v_zip_temp_name.'\' in binary write mode');
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- Copy the files from the archive to the temporary file
+ // TBC : Here I should better append the file and go back to erase the
+ // central dir
+ $v_size = $v_central_dir['offset'];
+ while ($v_size != 0)
+ {
+ $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
+ ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
+ $v_buffer = fread($this->_zip_fd, $v_read_size);
+ @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
+ $v_size -= $v_read_size;
+ }
+
+ // ----- Swap the file descriptor
+ // Here is a trick : I swap the temporary fd with the zip fd, in order to
+ // use the following methods on the temporary fil and not the real archive
+ $v_swap = $this->_zip_fd;
+ $this->_zip_fd = $v_zip_temp_fd;
+ $v_zip_temp_fd = $v_swap;
+
+ // ----- Add the files
+ $v_header_list = array();
+ if (($v_result = $this->_addFileList($p_list, $v_header_list,
+ $p_add_dir, $p_remove_dir,
+ $p_remove_all_dir, $p_params)) != 1)
+ {
+ fclose($v_zip_temp_fd);
+ $this->_closeFd();
+ @unlink($v_zip_temp_name);
+
+ // ----- Return
+ return $v_result;
+ }
+
+ // ----- Store the offset of the central dir
+ $v_offset = @ftell($this->_zip_fd);
+
+ // ----- Copy the block of file headers from the old archive
+ $v_size = $v_central_dir['size'];
+ while ($v_size != 0)
+ {
+ $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
+ ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
+ $v_buffer = @fread($v_zip_temp_fd, $v_read_size);
+ @fwrite($this->_zip_fd, $v_buffer, $v_read_size);
+ $v_size -= $v_read_size;
+ }
+
+ // ----- Create the Central Dir files header
+ for ($i=0, $v_count=0; $i<sizeof($v_header_list); $i++)
+ {
+ // ----- Create the file header
+ if ($v_header_list[$i]['status'] == 'ok') {
+ if (($v_result=$this->_writeCentralFileHeader($v_header_list[$i]))!=1) {
+ fclose($v_zip_temp_fd);
+ $this->_closeFd();
+ @unlink($v_zip_temp_name);
+
+ // ----- Return
+ return $v_result;
+ }
+ $v_count++;
+ }
+
+ // ----- Transform the header to a 'usable' info
+ $this->_convertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
+ }
+
+ // ----- Zip file comment
+ $v_comment = '';
+
+ // ----- Calculate the size of the central header
+ $v_size = @ftell($this->_zip_fd)-$v_offset;
+
+ // ----- Create the central dir footer
+ if (($v_result = $this->_writeCentralHeader($v_count
+ +$v_central_dir['entries'],
+ $v_size, $v_offset,
+ $v_comment)) != 1) {
+ // ----- Reset the file list
+ unset($v_header_list);
+
+ // ----- Return
+ return $v_result;
+ }
+
+ // ----- Swap back the file descriptor
+ $v_swap = $this->_zip_fd;
+ $this->_zip_fd = $v_zip_temp_fd;
+ $v_zip_temp_fd = $v_swap;
+
+ // ----- Close
+ $this->_closeFd();
+
+ // ----- Close the temporary file
+ @fclose($v_zip_temp_fd);
+
+ // ----- Delete the zip file
+ // TBC : I should test the result ...
+ @unlink($this->_zipname);
+
+ // ----- Rename the temporary file
+ // TBC : I should test the result ...
+ //@rename($v_zip_temp_name, $this->_zipname);
+ $this->_tool_Rename($v_zip_temp_name, $this->_zipname);
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _openFd()
+ // Description :
+ // Parameters :
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_openFd()
+ *
+ * { Description }
+ *
+ */
+ function _openFd($p_mode)
+ {
+ $v_result=1;
+
+ // ----- Look if already open
+ if ($this->_zip_fd != 0)
+ {
+ $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL,
+ 'Zip file \''.$this->_zipname.'\' already open');
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- Open the zip file
+ if (($this->_zip_fd = @fopen($this->_zipname, $p_mode)) == 0)
+ {
+ $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL,
+ 'Unable to open archive \''.$this->_zipname
+ .'\' in '.$p_mode.' mode');
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _closeFd()
+ // Description :
+ // Parameters :
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_closeFd()
+ *
+ * { Description }
+ *
+ */
+ function _closeFd()
+ {
+ $v_result=1;
+
+ if ($this->_zip_fd != 0)
+ @fclose($this->_zip_fd);
+ $this->_zip_fd = 0;
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _addList()
+ // Description :
+ // $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
+ // different from the real path of the file. This is usefull if you want to have PclTar
+ // running in any directory, and memorize relative path from an other directory.
+ // Parameters :
+ // $p_list : An array containing the file or directory names to add in the tar
+ // $p_result_list : list of added files with their properties (specially the status field)
+ // $p_add_dir : Path to add in the filename path archived
+ // $p_remove_dir : Path to remove in the filename path archived
+ // Return Values :
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_addList()
+ *
+ * { Description }
+ *
+ */
+ function _addList($p_list, &$p_result_list,
+ $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_params)
+ {
+ $v_result=1;
+
+ // ----- Add the files
+ $v_header_list = array();
+ if (($v_result = $this->_addFileList($p_list, $v_header_list,
+ $p_add_dir, $p_remove_dir,
+ $p_remove_all_dir, $p_params)) != 1) {
+ return $v_result;
+ }
+
+ // ----- Store the offset of the central dir
+ $v_offset = @ftell($this->_zip_fd);
+
+ // ----- Create the Central Dir files header
+ for ($i=0,$v_count=0; $i<sizeof($v_header_list); $i++)
+ {
+ // ----- Create the file header
+ if ($v_header_list[$i]['status'] == 'ok') {
+ if (($v_result = $this->_writeCentralFileHeader($v_header_list[$i])) != 1) {
+ return $v_result;
+ }
+ $v_count++;
+ }
+
+ // ----- Transform the header to a 'usable' info
+ $this->_convertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
+ }
+
+ // ----- Zip file comment
+ $v_comment = '';
+
+ // ----- Calculate the size of the central header
+ $v_size = @ftell($this->_zip_fd)-$v_offset;
+
+ // ----- Create the central dir footer
+ if (($v_result = $this->_writeCentralHeader($v_count, $v_size, $v_offset,
+ $v_comment)) != 1)
+ {
+ // ----- Reset the file list
+ unset($v_header_list);
+
+ // ----- Return
+ return $v_result;
+ }
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _addFileList()
+ // Description :
+ // $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
+ // different from the real path of the file. This is usefull if you want to
+ // run the lib in any directory, and memorize relative path from an other directory.
+ // Parameters :
+ // $p_list : An array containing the file or directory names to add in the tar
+ // $p_result_list : list of added files with their properties (specially the status field)
+ // $p_add_dir : Path to add in the filename path archived
+ // $p_remove_dir : Path to remove in the filename path archived
+ // Return Values :
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_addFileList()
+ *
+ * { Description }
+ *
+ */
+ function _addFileList($p_list, &$p_result_list,
+ $p_add_dir, $p_remove_dir, $p_remove_all_dir,
+ &$p_params)
+ {
+ $v_result=1;
+ $v_header = array();
+
+ // ----- Recuperate the current number of elt in list
+ $v_nb = sizeof($p_result_list);
+
+ // ----- Loop on the files
+ for ($j=0; ($j<count($p_list)) && ($v_result==1); $j++)
+ {
+ // ----- Recuperate the filename
+ $p_filename = $this->_tool_TranslateWinPath($p_list[$j], false);
+
+ // ----- Skip empty file names
+ if ($p_filename == "")
+ {
+ continue;
+ }
+
+ // ----- Check the filename
+ if (!file_exists($p_filename))
+ {
+ $this->_errorLog(ARCHIVE_ZIP_ERR_MISSING_FILE,
+ "File '$p_filename' does not exists");
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- Look if it is a file or a dir with no all pathnre move
+ if ((is_file($p_filename)) || ((is_dir($p_filename)) && !$p_remove_all_dir)) {
+ // ----- Add the file
+ if (($v_result = $this->_addFile($p_filename, $v_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_params)) != 1)
+ {
+ // ----- Return status
+ return $v_result;
+ }
+
+ // ----- Store the file infos
+ $p_result_list[$v_nb++] = $v_header;
+ }
+
+ // ----- Look for directory
+ if (is_dir($p_filename))
+ {
+
+ // ----- Look for path
+ if ($p_filename != ".")
+ $v_path = $p_filename."/";
+ else
+ $v_path = "";
+
+ // ----- Read the directory for files and sub-directories
+ $p_hdir = opendir($p_filename);
+ $p_hitem = readdir($p_hdir); // '.' directory
+ $p_hitem = readdir($p_hdir); // '..' directory
+ while ($p_hitem = readdir($p_hdir))
+ {
+
+ // ----- Look for a file
+ if (is_file($v_path.$p_hitem))
+ {
+
+ // ----- Add the file
+ if (($v_result = $this->_addFile($v_path.$p_hitem, $v_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_params)) != 1)
+ {
+ // ----- Return status
+ return $v_result;
+ }
+
+ // ----- Store the file infos
+ $p_result_list[$v_nb++] = $v_header;
+ }
+
+ // ----- Recursive call to _addFileList()
+ else
+ {
+
+ // ----- Need an array as parameter
+ $p_temp_list[0] = $v_path.$p_hitem;
+ $v_result = $this->_addFileList($p_temp_list, $p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_params);
+
+ // ----- Update the number of elements of the list
+ $v_nb = sizeof($p_result_list);
+ }
+ }
+
+ // ----- Free memory for the recursive loop
+ unset($p_temp_list);
+ unset($p_hdir);
+ unset($p_hitem);
+ }
+ }
+
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _addFile()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_addFile()
+ *
+ * { Description }
+ *
+ */
+ function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_params)
+ {
+ $v_result=1;
+
+ if ($p_filename == "")
+ {
+ // ----- Error log
+ $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)");
+
+ // ----- Return
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- Calculate the stored filename
+ $v_stored_filename = $p_filename;
+
+ // ----- Look for all path to remove
+ if ($p_remove_all_dir) {
+ $v_stored_filename = basename($p_filename);
+ }
+ // ----- Look for partial path remove
+ else if ($p_remove_dir != "")
+ {
+ if (substr($p_remove_dir, -1) != '/')
+ $p_remove_dir .= "/";
+
+ if ((substr($p_filename, 0, 2) == "./") || (substr($p_remove_dir, 0, 2) == "./"))
+ {
+ if ((substr($p_filename, 0, 2) == "./") && (substr($p_remove_dir, 0, 2) != "./"))
+ $p_remove_dir = "./".$p_remove_dir;
+ if ((substr($p_filename, 0, 2) != "./") && (substr($p_remove_dir, 0, 2) == "./"))
+ $p_remove_dir = substr($p_remove_dir, 2);
+ }
+
+ $v_compare = $this->_tool_PathInclusion($p_remove_dir, $p_filename);
+ if ($v_compare > 0)
+// if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir)
+ {
+
+ if ($v_compare == 2) {
+ $v_stored_filename = "";
+ }
+ else {
+ $v_stored_filename = substr($p_filename, strlen($p_remove_dir));
+ }
+ }
+ }
+ // ----- Look for path to add
+ if ($p_add_dir != "")
+ {
+ if (substr($p_add_dir, -1) == "/")
+ $v_stored_filename = $p_add_dir.$v_stored_filename;
+ else
+ $v_stored_filename = $p_add_dir."/".$v_stored_filename;
+ }
+
+ // ----- Filename (reduce the path of stored name)
+ $v_stored_filename = $this->_tool_PathReduction($v_stored_filename);
+
+
+ /* filename length moved after call-back in release 1.3
+ // ----- Check the path length
+ if (strlen($v_stored_filename) > 0xFF)
+ {
+ // ----- Error log
+ $this->_errorLog(-5, "Stored file name is too long (max. 255) : '$v_stored_filename'");
+
+ // ----- Return
+ return Archive_Zip::errorCode();
+ }
+ */
+
+ // ----- Set the file properties
+ clearstatcache();
+ $p_header['version'] = 20;
+ $p_header['version_extracted'] = 10;
+ $p_header['flag'] = 0;
+ $p_header['compression'] = 0;
+ $p_header['mtime'] = filemtime($p_filename);
+ $p_header['crc'] = 0;
+ $p_header['compressed_size'] = 0;
+ $p_header['size'] = filesize($p_filename);
+ $p_header['filename_len'] = strlen($p_filename);
+ $p_header['extra_len'] = 0;
+ $p_header['comment_len'] = 0;
+ $p_header['disk'] = 0;
+ $p_header['internal'] = 0;
+ $p_header['external'] = (is_file($p_filename)?0xFE49FFE0:0x41FF0010);
+ $p_header['offset'] = 0;
+ $p_header['filename'] = $p_filename;
+ $p_header['stored_filename'] = $v_stored_filename;
+ $p_header['extra'] = '';
+ $p_header['comment'] = '';
+ $p_header['status'] = 'ok';
+ $p_header['index'] = -1;
+
+ // ----- Look for pre-add callback
+ if ( (isset($p_params[ARCHIVE_ZIP_PARAM_PRE_ADD]))
+ && ($p_params[ARCHIVE_ZIP_PARAM_PRE_ADD] != '')) {
+
+ // ----- Generate a local information
+ $v_local_header = array();
+ $this->_convertHeader2FileInfo($p_header, $v_local_header);
+
+ // ----- Call the callback
+ // Here I do not use call_user_func() because I need to send a reference to the
+ // header.
+ eval('$v_result = '.$p_params[ARCHIVE_ZIP_PARAM_PRE_ADD].'(ARCHIVE_ZIP_PARAM_PRE_ADD, $v_local_header);');
+ if ($v_result == 0) {
+ // ----- Change the file status
+ $p_header['status'] = "skipped";
+ $v_result = 1;
+ }
+
+ // ----- Update the informations
+ // Only some fields can be modified
+ if ($p_header['stored_filename'] != $v_local_header['stored_filename']) {
+ $p_header['stored_filename'] = $this->_tool_PathReduction($v_local_header['stored_filename']);
+ }
+ }
+
+ // ----- Look for empty stored filename
+ if ($p_header['stored_filename'] == "") {
+ $p_header['status'] = "filtered";
+ }
+
+ // ----- Check the path length
+ if (strlen($p_header['stored_filename']) > 0xFF) {
+ $p_header['status'] = 'filename_too_long';
+ }
+
+ // ----- Look if no error, or file not skipped
+ if ($p_header['status'] == 'ok') {
+
+ // ----- Look for a file
+ if (is_file($p_filename))
+ {
+ // ----- Open the source file
+ if (($v_file = @fopen($p_filename, "rb")) == 0) {
+ $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
+ return Archive_Zip::errorCode();
+ }
+
+ if ($p_params['no_compression']) {
+ // ----- Read the file content
+ $v_content_compressed = @fread($v_file, $p_header['size']);
+
+ // ----- Calculate the CRC
+ $p_header['crc'] = crc32($v_content_compressed);
+ }
+ else {
+ // ----- Read the file content
+ $v_content = @fread($v_file, $p_header['size']);
+
+ // ----- Calculate the CRC
+ $p_header['crc'] = crc32($v_content);
+
+ // ----- Compress the file
+ $v_content_compressed = gzdeflate($v_content);
+ }
+
+ // ----- Set header parameters
+ $p_header['compressed_size'] = strlen($v_content_compressed);
+ $p_header['compression'] = 8;
+
+ // ----- Call the header generation
+ if (($v_result = $this->_writeFileHeader($p_header)) != 1) {
+ @fclose($v_file);
+ return $v_result;
+ }
+
+ // ----- Write the compressed content
+ $v_binary_data = pack('a'.$p_header['compressed_size'], $v_content_compressed);
+ @fwrite($this->_zip_fd, $v_binary_data, $p_header['compressed_size']);
+
+ // ----- Close the file
+ @fclose($v_file);
+ }
+
+ // ----- Look for a directory
+ else
+ {
+ // ----- Set the file properties
+ $p_header['filename'] .= '/';
+ $p_header['filename_len']++;
+ $p_header['size'] = 0;
+ $p_header['external'] = 0x41FF0010; // Value for a folder : to be checked
+
+ // ----- Call the header generation
+ if (($v_result = $this->_writeFileHeader($p_header)) != 1)
+ {
+ return $v_result;
+ }
+ }
+ }
+
+ // ----- Look for pre-add callback
+ if ( (isset($p_params[ARCHIVE_ZIP_PARAM_POST_ADD]))
+ && ($p_params[ARCHIVE_ZIP_PARAM_POST_ADD] != '')) {
+
+ // ----- Generate a local information
+ $v_local_header = array();
+ $this->_convertHeader2FileInfo($p_header, $v_local_header);
+
+ // ----- Call the callback
+ // Here I do not use call_user_func() because I need to send a reference to the
+ // header.
+ eval('$v_result = '.$p_params[ARCHIVE_ZIP_PARAM_POST_ADD].'(ARCHIVE_ZIP_PARAM_POST_ADD, $v_local_header);');
+ if ($v_result == 0) {
+ // ----- Ignored
+ $v_result = 1;
+ }
+
+ // ----- Update the informations
+ // Nothing can be modified
+ }
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _writeFileHeader()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_writeFileHeader()
+ *
+ * { Description }
+ *
+ */
+ function _writeFileHeader(&$p_header)
+ {
+ $v_result=1;
+
+ // TBC
+ //for(reset($p_header); $key = key($p_header); next($p_header)) {
+ //}
+
+ // ----- Store the offset position of the file
+ $p_header['offset'] = ftell($this->_zip_fd);
+
+ // ----- Transform UNIX mtime to DOS format mdate/mtime
+ $v_date = getdate($p_header['mtime']);
+ $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
+ $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
+
+ // ----- Packed data
+ $v_binary_data = pack("VvvvvvVVVvv", 0x04034b50, $p_header['version'], $p_header['flag'],
+ $p_header['compression'], $v_mtime, $v_mdate,
+ $p_header['crc'], $p_header['compressed_size'], $p_header['size'],
+ strlen($p_header['stored_filename']), $p_header['extra_len']);
+
+ // ----- Write the first 148 bytes of the header in the archive
+ fputs($this->_zip_fd, $v_binary_data, 30);
+
+ // ----- Write the variable fields
+ if (strlen($p_header['stored_filename']) != 0)
+ {
+ fputs($this->_zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
+ }
+ if ($p_header['extra_len'] != 0)
+ {
+ fputs($this->_zip_fd, $p_header['extra'], $p_header['extra_len']);
+ }
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _writeCentralFileHeader()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_writeCentralFileHeader()
+ *
+ * { Description }
+ *
+ */
+ function _writeCentralFileHeader(&$p_header)
+ {
+ $v_result=1;
+
+ // TBC
+ //for(reset($p_header); $key = key($p_header); next($p_header)) {
+ //}
+
+ // ----- Transform UNIX mtime to DOS format mdate/mtime
+ $v_date = getdate($p_header['mtime']);
+ $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
+ $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
+
+ // ----- Packed data
+ $v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50, $p_header['version'], $p_header['version_extracted'],
+ $p_header['flag'], $p_header['compression'], $v_mtime, $v_mdate, $p_header['crc'],
+ $p_header['compressed_size'], $p_header['size'],
+ strlen($p_header['stored_filename']), $p_header['extra_len'], $p_header['comment_len'],
+ $p_header['disk'], $p_header['internal'], $p_header['external'], $p_header['offset']);
+
+ // ----- Write the 42 bytes of the header in the zip file
+ fputs($this->_zip_fd, $v_binary_data, 46);
+
+ // ----- Write the variable fields
+ if (strlen($p_header['stored_filename']) != 0)
+ {
+ fputs($this->_zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
+ }
+ if ($p_header['extra_len'] != 0)
+ {
+ fputs($this->_zip_fd, $p_header['extra'], $p_header['extra_len']);
+ }
+ if ($p_header['comment_len'] != 0)
+ {
+ fputs($this->_zip_fd, $p_header['comment'], $p_header['comment_len']);
+ }
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _writeCentralHeader()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_writeCentralHeader()
+ *
+ * { Description }
+ *
+ */
+ function _writeCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment)
+ {
+ $v_result=1;
+
+ // ----- Packed data
+ $v_binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries, $p_nb_entries, $p_size, $p_offset, strlen($p_comment));
+
+ // ----- Write the 22 bytes of the header in the zip file
+ fputs($this->_zip_fd, $v_binary_data, 22);
+
+ // ----- Write the variable fields
+ if (strlen($p_comment) != 0)
+ {
+ fputs($this->_zip_fd, $p_comment, strlen($p_comment));
+ }
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _list()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_list()
+ *
+ * { Description }
+ *
+ */
+ function _list(&$p_list)
+ {
+ $v_result=1;
+
+ // ----- Open the zip file
+ if (($this->_zip_fd = @fopen($this->_zipname, 'rb')) == 0)
+ {
+ // ----- Error log
+ $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->_zipname.'\' in binary read mode');
+
+ // ----- Return
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- Read the central directory informations
+ $v_central_dir = array();
+ if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1)
+ {
+ return $v_result;
+ }
+
+ // ----- Go to beginning of Central Dir
+ @rewind($this->_zip_fd);
+ if (@fseek($this->_zip_fd, $v_central_dir['offset']))
+ {
+ // ----- Error log
+ $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
+
+ // ----- Return
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- Read each entry
+ for ($i=0; $i<$v_central_dir['entries']; $i++)
+ {
+ // ----- Read the file header
+ if (($v_result = $this->_readCentralFileHeader($v_header)) != 1)
+ {
+ return $v_result;
+ }
+ $v_header['index'] = $i;
+
+ // ----- Get the only interesting attributes
+ $this->_convertHeader2FileInfo($v_header, $p_list[$i]);
+ unset($v_header);
+ }
+
+ // ----- Close the zip file
+ $this->_closeFd();
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _convertHeader2FileInfo()
+ // Description :
+ // This function takes the file informations from the central directory
+ // entries and extract the interesting parameters that will be given back.
+ // The resulting file infos are set in the array $p_info
+ // $p_info['filename'] : Filename with full path. Given by user (add),
+ // extracted in the filesystem (extract).
+ // $p_info['stored_filename'] : Stored filename in the archive.
+ // $p_info['size'] = Size of the file.
+ // $p_info['compressed_size'] = Compressed size of the file.
+ // $p_info['mtime'] = Last modification date of the file.
+ // $p_info['comment'] = Comment associated with the file.
+ // $p_info['folder'] = true/false : indicates if the entry is a folder or not.
+ // $p_info['status'] = status of the action on the file.
+ // Parameters :
+ // Return Values :
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_convertHeader2FileInfo()
+ *
+ * { Description }
+ *
+ */
+ function _convertHeader2FileInfo($p_header, &$p_info)
+ {
+ $v_result=1;
+
+ // ----- Get the interesting attributes
+ $p_info['filename'] = $p_header['filename'];
+ $p_info['stored_filename'] = $p_header['stored_filename'];
+ $p_info['size'] = $p_header['size'];
+ $p_info['compressed_size'] = $p_header['compressed_size'];
+ $p_info['mtime'] = $p_header['mtime'];
+ $p_info['comment'] = $p_header['comment'];
+ $p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010);
+ $p_info['index'] = $p_header['index'];
+ $p_info['status'] = $p_header['status'];
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _extractByRule()
+ // Description :
+ // Extract a file or directory depending of rules (by index, by name, ...)
+ // Parameters :
+ // $p_file_list : An array where will be placed the properties of each
+ // extracted file
+ // $p_path : Path to add while writing the extracted files
+ // $p_remove_path : Path to remove (from the file memorized path) while writing the
+ // extracted files. If the path does not match the file path,
+ // the file is extracted with its memorized path.
+ // $p_remove_path does not apply to 'list' mode.
+ // $p_path and $p_remove_path are commulative.
+ // Return Values :
+ // 1 on success,0 or less on error (see error code list)
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_extractByRule()
+ *
+ * { Description }
+ *
+ */
+ function _extractByRule(&$p_file_list, &$p_params)
+ {
+ $v_result=1;
+
+ $p_path = $p_params['add_path'];
+ $p_remove_path = $p_params['remove_path'];
+ $p_remove_all_path = $p_params['remove_all_path'];
+
+ // ----- Check the path
+ if (($p_path == "")
+ || ((substr($p_path, 0, 1) != "/")
+ && (substr($p_path, 0, 3) != "../") && (substr($p_path,1,2)!=":/")))
+ $p_path = "./".$p_path;
+
+ // ----- Reduce the path last (and duplicated) '/'
+ if (($p_path != "./") && ($p_path != "/")) {
+ // ----- Look for the path end '/'
+ while (substr($p_path, -1) == "/") {
+ $p_path = substr($p_path, 0, strlen($p_path)-1);
+ }
+ }
+
+ // ----- Look for path to remove format (should end by /)
+ if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/')) {
+ $p_remove_path .= '/';
+ }
+ $p_remove_path_size = strlen($p_remove_path);
+
+ // ----- Open the zip file
+ if (($v_result = $this->_openFd('rb')) != 1)
+ {
+ return $v_result;
+ }
+
+ // ----- Read the central directory informations
+ $v_central_dir = array();
+ if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1)
+ {
+ // ----- Close the zip file
+ $this->_closeFd();
+
+ return $v_result;
+ }
+
+ // ----- Start at beginning of Central Dir
+ $v_pos_entry = $v_central_dir['offset'];
+
+ // ----- Read each entry
+ $j_start = 0;
+ for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++) {
+ // ----- Read next Central dir entry
+ @rewind($this->_zip_fd);
+ if (@fseek($this->_zip_fd, $v_pos_entry)) {
+ $this->_closeFd();
+
+ $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP,
+ 'Invalid archive size');
+
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- Read the file header
+ $v_header = array();
+ if (($v_result = $this->_readCentralFileHeader($v_header)) != 1) {
+ $this->_closeFd();
+
+ return $v_result;
+ }
+
+ // ----- Store the index
+ $v_header['index'] = $i;
+
+ // ----- Store the file position
+ $v_pos_entry = ftell($this->_zip_fd);
+
+ // ----- Look for the specific extract rules
+ $v_extract = false;
+
+ // ----- Look for extract by name rule
+ if ( (isset($p_params[ARCHIVE_ZIP_PARAM_BY_NAME]))
+ && ($p_params[ARCHIVE_ZIP_PARAM_BY_NAME] != 0)) {
+
+ // ----- Look if the filename is in the list
+ for ($j=0;
+ ($j<sizeof($p_params[ARCHIVE_ZIP_PARAM_BY_NAME]))
+ && (!$v_extract);
+ $j++) {
+
+ // ----- Look for a directory
+ if (substr($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j], -1) == "/") {
+
+ // ----- Look if the directory is in the filename path
+ if ( (strlen($v_header['stored_filename']) > strlen($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j]))
+ && (substr($v_header['stored_filename'], 0, strlen($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) {
+ $v_extract = true;
+ }
+ }
+ // ----- Look for a filename
+ elseif ($v_header['stored_filename'] == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j]) {
+ $v_extract = true;
+ }
+ }
+ }
+
+ // ----- Look for extract by ereg rule
+ else if ( (isset($p_params[ARCHIVE_ZIP_PARAM_BY_EREG]))
+ && ($p_params[ARCHIVE_ZIP_PARAM_BY_EREG] != "")) {
+
+ if (ereg($p_params[ARCHIVE_ZIP_PARAM_BY_EREG], $v_header['stored_filename'])) {
+ $v_extract = true;
+ }
+ }
+
+ // ----- Look for extract by preg rule
+ else if ( (isset($p_params[ARCHIVE_ZIP_PARAM_BY_PREG]))
+ && ($p_params[ARCHIVE_ZIP_PARAM_BY_PREG] != "")) {
+
+ if (preg_match($p_params[ARCHIVE_ZIP_PARAM_BY_PREG], $v_header['stored_filename'])) {
+ $v_extract = true;
+ }
+ }
+
+ // ----- Look for extract by index rule
+ else if ( (isset($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX]))
+ && ($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX] != 0)) {
+
+ // ----- Look if the index is in the list
+ for ($j=$j_start; ($j<sizeof($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX])) && (!$v_extract); $j++) {
+
+ if (($i>=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['start']) && ($i<=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['end'])) {
+ $v_extract = true;
+ }
+ if ($i>=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['end']) {
+ $j_start = $j+1;
+ }
+
+ if ($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['start']>$i) {
+ break;
+ }
+ }
+ }
+
+ // ----- Look for no rule, which means extract all the archive
+ else {
+ $v_extract = true;
+ }
+
+
+ // ----- Look for real extraction
+ if ($v_extract)
+ {
+
+ // ----- Go to the file position
+ @rewind($this->_zip_fd);
+ if (@fseek($this->_zip_fd, $v_header['offset']))
+ {
+ // ----- Close the zip file
+ $this->_closeFd();
+
+ // ----- Error log
+ $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
+
+ // ----- Return
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- Look for extraction as string
+ if ($p_params[ARCHIVE_ZIP_PARAM_EXTRACT_AS_STRING]) {
+
+ // ----- Extracting the file
+ if (($v_result = $this->_extractFileAsString($v_header, $v_string)) != 1)
+ {
+ // ----- Close the zip file
+ $this->_closeFd();
+
+ return $v_result;
+ }
+
+ // ----- Get the only interesting attributes
+ if (($v_result = $this->_convertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted])) != 1)
+ {
+ // ----- Close the zip file
+ $this->_closeFd();
+
+ return $v_result;
+ }
+
+ // ----- Set the file content
+ $p_file_list[$v_nb_extracted]['content'] = $v_string;
+
+ // ----- Next extracted file
+ $v_nb_extracted++;
+ }
+ else {
+ // ----- Extracting the file
+ if (($v_result = $this->_extractFile($v_header, $p_path, $p_remove_path, $p_remove_all_path, $p_params)) != 1)
+ {
+ // ----- Close the zip file
+ $this->_closeFd();
+
+ return $v_result;
+ }
+
+ // ----- Get the only interesting attributes
+ if (($v_result = $this->_convertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1)
+ {
+ // ----- Close the zip file
+ $this->_closeFd();
+
+ return $v_result;
+ }
+ }
+ }
+ }
+
+ // ----- Close the zip file
+ $this->_closeFd();
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _extractFile()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_extractFile()
+ *
+ * { Description }
+ *
+ */
+ function _extractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_params)
+ {
+ $v_result=1;
+
+ // ----- Read the file header
+ if (($v_result = $this->_readFileHeader($v_header)) != 1)
+ {
+ // ----- Return
+ return $v_result;
+ }
+
+
+ // ----- Check that the file header is coherent with $p_entry info
+ // TBC
+
+ // ----- Look for all path to remove
+ if ($p_remove_all_path == true) {
+ // ----- Get the basename of the path
+ $p_entry['filename'] = basename($p_entry['filename']);
+ }
+
+ // ----- Look for path to remove
+ else if ($p_remove_path != "")
+ {
+ //if (strcmp($p_remove_path, $p_entry['filename'])==0)
+ if ($this->_tool_PathInclusion($p_remove_path, $p_entry['filename']) == 2)
+ {
+
+ // ----- Change the file status
+ $p_entry['status'] = "filtered";
+
+ // ----- Return
+ return $v_result;
+ }
+
+ $p_remove_path_size = strlen($p_remove_path);
+ if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path)
+ {
+
+ // ----- Remove the path
+ $p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size);
+
+ }
+ }
+
+ // ----- Add the path
+ if ($p_path != '')
+ {
+ $p_entry['filename'] = $p_path."/".$p_entry['filename'];
+ }
+
+ // ----- Look for pre-extract callback
+ if ( (isset($p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT]))
+ && ($p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT] != '')) {
+
+ // ----- Generate a local information
+ $v_local_header = array();
+ $this->_convertHeader2FileInfo($p_entry, $v_local_header);
+
+ // ----- Call the callback
+ // Here I do not use call_user_func() because I need to send a reference to the
+ // header.
+ eval('$v_result = '.$p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT].'(ARCHIVE_ZIP_PARAM_PRE_EXTRACT, $v_local_header);');
+ if ($v_result == 0) {
+ // ----- Change the file status
+ $p_entry['status'] = "skipped";
+ $v_result = 1;
+ }
+
+ // ----- Update the informations
+ // Only some fields can be modified
+ $p_entry['filename'] = $v_local_header['filename'];
+ }
+
+ // ----- Trace
+
+ // ----- Look if extraction should be done
+ if ($p_entry['status'] == 'ok') {
+
+ // ----- Look for specific actions while the file exist
+ if (file_exists($p_entry['filename']))
+ {
+
+ // ----- Look if file is a directory
+ if (is_dir($p_entry['filename']))
+ {
+
+ // ----- Change the file status
+ $p_entry['status'] = "already_a_directory";
+
+ // ----- Return
+ //return $v_result;
+ }
+ // ----- Look if file is write protected
+ else if (!is_writeable($p_entry['filename']))
+ {
+
+ // ----- Change the file status
+ $p_entry['status'] = "write_protected";
+
+ // ----- Return
+ //return $v_result;
+ }
+
+ // ----- Look if the extracted file is older
+ else if (filemtime($p_entry['filename']) > $p_entry['mtime'])
+ {
+
+ // ----- Change the file status
+ $p_entry['status'] = "newer_exist";
+
+ // ----- Return
+ //return $v_result;
+ }
+ }
+
+ // ----- Check the directory availability and create it if necessary
+ else {
+ if ((($p_entry['external']&0x00000010)==0x00000010) || (substr($p_entry['filename'], -1) == '/'))
+ $v_dir_to_check = $p_entry['filename'];
+ else if (!strstr($p_entry['filename'], "/"))
+ $v_dir_to_check = "";
+ else
+ $v_dir_to_check = dirname($p_entry['filename']);
+
+ if (($v_result = $this->_dirCheck($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) {
+
+ // ----- Change the file status
+ $p_entry['status'] = "path_creation_fail";
+
+ // ----- Return
+ //return $v_result;
+ $v_result = 1;
+ }
+ }
+ }
+
+ // ----- Look if extraction should be done
+ if ($p_entry['status'] == 'ok') {
+
+ // ----- Do the extraction (if not a folder)
+ if (!(($p_entry['external']&0x00000010)==0x00000010))
+ {
+
+ // ----- Look for not compressed file
+ if ($p_entry['compressed_size'] == $p_entry['size'])
+ {
+
+ // ----- Opening destination file
+ if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0)
+ {
+
+ // ----- Change the file status
+ $p_entry['status'] = "write_error";
+
+ // ----- Return
+ return $v_result;
+ }
+
+
+ // ----- Read the file by ARCHIVE_ZIP_READ_BLOCK_SIZE octets blocks
+ $v_size = $p_entry['compressed_size'];
+ while ($v_size != 0)
+ {
+ $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
+ $v_buffer = fread($this->_zip_fd, $v_read_size);
+ $v_binary_data = pack('a'.$v_read_size, $v_buffer);
+ @fwrite($v_dest_file, $v_binary_data, $v_read_size);
+ $v_size -= $v_read_size;
+ }
+
+ // ----- Closing the destination file
+ fclose($v_dest_file);
+
+ // ----- Change the file mtime
+ touch($p_entry['filename'], $p_entry['mtime']);
+ }
+ else
+ {
+ // ----- Trace
+
+ // ----- Opening destination file
+ if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
+
+ // ----- Change the file status
+ $p_entry['status'] = "write_error";
+
+ return $v_result;
+ }
+
+
+ // ----- Read the compressed file in a buffer (one shot)
+ $v_buffer = @fread($this->_zip_fd, $p_entry['compressed_size']);
+
+ // ----- Decompress the file
+ $v_file_content = gzinflate($v_buffer);
+ unset($v_buffer);
+
+ // ----- Write the uncompressed data
+ @fwrite($v_dest_file, $v_file_content, $p_entry['size']);
+ unset($v_file_content);
+
+ // ----- Closing the destination file
+ @fclose($v_dest_file);
+
+ // ----- Change the file mtime
+ touch($p_entry['filename'], $p_entry['mtime']);
+ }
+
+ // ----- Look for chmod option
+ if ( (isset($p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD]))
+ && ($p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD] != 0)) {
+
+ // ----- Change the mode of the file
+ chmod($p_entry['filename'], $p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD]);
+ }
+
+ }
+ }
+
+ // ----- Look for post-extract callback
+ if ( (isset($p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT]))
+ && ($p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT] != '')) {
+
+ // ----- Generate a local information
+ $v_local_header = array();
+ $this->_convertHeader2FileInfo($p_entry, $v_local_header);
+
+ // ----- Call the callback
+ // Here I do not use call_user_func() because I need to send a reference to the
+ // header.
+ eval('$v_result = '.$p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT].'(ARCHIVE_ZIP_PARAM_POST_EXTRACT, $v_local_header);');
+ }
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _extractFileAsString()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_extractFileAsString()
+ *
+ * { Description }
+ *
+ */
+ function _extractFileAsString(&$p_entry, &$p_string)
+ {
+ $v_result=1;
+
+ // ----- Read the file header
+ $v_header = array();
+ if (($v_result = $this->_readFileHeader($v_header)) != 1)
+ {
+ // ----- Return
+ return $v_result;
+ }
+
+
+ // ----- Check that the file header is coherent with $p_entry info
+ // TBC
+
+ // ----- Trace
+
+ // ----- Do the extraction (if not a folder)
+ if (!(($p_entry['external']&0x00000010)==0x00000010))
+ {
+ // ----- Look for not compressed file
+ if ($p_entry['compressed_size'] == $p_entry['size'])
+ {
+ // ----- Trace
+
+ // ----- Reading the file
+ $p_string = fread($this->_zip_fd, $p_entry['compressed_size']);
+ }
+ else
+ {
+ // ----- Trace
+
+ // ----- Reading the file
+ $v_data = fread($this->_zip_fd, $p_entry['compressed_size']);
+
+ // ----- Decompress the file
+ $p_string = gzinflate($v_data);
+ }
+
+ // ----- Trace
+ }
+ else {
+ // TBC : error : can not extract a folder in a string
+ }
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _readFileHeader()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_readFileHeader()
+ *
+ * { Description }
+ *
+ */
+ function _readFileHeader(&$p_header)
+ {
+ $v_result=1;
+
+ // ----- Read the 4 bytes signature
+ $v_binary_data = @fread($this->_zip_fd, 4);
+ $v_data = unpack('Vid', $v_binary_data);
+
+ // ----- Check signature
+ if ($v_data['id'] != 0x04034b50)
+ {
+
+ // ----- Error log
+ $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
+
+ // ----- Return
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- Read the first 42 bytes of the header
+ $v_binary_data = fread($this->_zip_fd, 26);
+
+ // ----- Look for invalid block size
+ if (strlen($v_binary_data) != 26)
+ {
+ $p_header['filename'] = "";
+ $p_header['status'] = "invalid_header";
+
+ // ----- Error log
+ $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
+
+ // ----- Return
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- Extract the values
+ $v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data);
+
+ // ----- Get filename
+ $p_header['filename'] = fread($this->_zip_fd, $v_data['filename_len']);
+
+ // ----- Get extra_fields
+ if ($v_data['extra_len'] != 0) {
+ $p_header['extra'] = fread($this->_zip_fd, $v_data['extra_len']);
+ }
+ else {
+ $p_header['extra'] = '';
+ }
+
+ // ----- Extract properties
+ $p_header['compression'] = $v_data['compression'];
+ $p_header['size'] = $v_data['size'];
+ $p_header['compressed_size'] = $v_data['compressed_size'];
+ $p_header['crc'] = $v_data['crc'];
+ $p_header['flag'] = $v_data['flag'];
+
+ // ----- Recuperate date in UNIX format
+ $p_header['mdate'] = $v_data['mdate'];
+ $p_header['mtime'] = $v_data['mtime'];
+ if ($p_header['mdate'] && $p_header['mtime'])
+ {
+ // ----- Extract time
+ $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
+ $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
+ $v_seconde = ($p_header['mtime'] & 0x001F)*2;
+
+ // ----- Extract date
+ $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
+ $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
+ $v_day = $p_header['mdate'] & 0x001F;
+
+ // ----- Get UNIX date format
+ $p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
+
+ }
+ else
+ {
+ $p_header['mtime'] = time();
+ }
+
+ // ----- Other informations
+
+ // TBC
+ //for(reset($v_data); $key = key($v_data); next($v_data)) {
+ //}
+
+ // ----- Set the stored filename
+ $p_header['stored_filename'] = $p_header['filename'];
+
+ // ----- Set the status field
+ $p_header['status'] = "ok";
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _readCentralFileHeader()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_readCentralFileHeader()
+ *
+ * { Description }
+ *
+ */
+ function _readCentralFileHeader(&$p_header)
+ {
+ $v_result=1;
+
+ // ----- Read the 4 bytes signature
+ $v_binary_data = @fread($this->_zip_fd, 4);
+ $v_data = unpack('Vid', $v_binary_data);
+
+ // ----- Check signature
+ if ($v_data['id'] != 0x02014b50)
+ {
+
+ // ----- Error log
+ $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
+
+ // ----- Return
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- Read the first 42 bytes of the header
+ $v_binary_data = fread($this->_zip_fd, 42);
+
+ // ----- Look for invalid block size
+ if (strlen($v_binary_data) != 42)
+ {
+ $p_header['filename'] = "";
+ $p_header['status'] = "invalid_header";
+
+ // ----- Error log
+ $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
+
+ // ----- Return
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- Extract the values
+ $p_header = unpack('vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $v_binary_data);
+
+ // ----- Get filename
+ if ($p_header['filename_len'] != 0)
+ $p_header['filename'] = fread($this->_zip_fd, $p_header['filename_len']);
+ else
+ $p_header['filename'] = '';
+
+ // ----- Get extra
+ if ($p_header['extra_len'] != 0)
+ $p_header['extra'] = fread($this->_zip_fd, $p_header['extra_len']);
+ else
+ $p_header['extra'] = '';
+
+ // ----- Get comment
+ if ($p_header['comment_len'] != 0)
+ $p_header['comment'] = fread($this->_zip_fd, $p_header['comment_len']);
+ else
+ $p_header['comment'] = '';
+
+ // ----- Extract properties
+
+ // ----- Recuperate date in UNIX format
+ if ($p_header['mdate'] && $p_header['mtime'])
+ {
+ // ----- Extract time
+ $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
+ $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
+ $v_seconde = ($p_header['mtime'] & 0x001F)*2;
+
+ // ----- Extract date
+ $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
+ $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
+ $v_day = $p_header['mdate'] & 0x001F;
+
+ // ----- Get UNIX date format
+ $p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
+
+ }
+ else
+ {
+ $p_header['mtime'] = time();
+ }
+
+ // ----- Set the stored filename
+ $p_header['stored_filename'] = $p_header['filename'];
+
+ // ----- Set default status to ok
+ $p_header['status'] = 'ok';
+
+ // ----- Look if it is a directory
+ if (substr($p_header['filename'], -1) == '/')
+ {
+ $p_header['external'] = 0x41FF0010;
+ }
+
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _readEndCentralDir()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_readEndCentralDir()
+ *
+ * { Description }
+ *
+ */
+ function _readEndCentralDir(&$p_central_dir)
+ {
+ $v_result=1;
+
+ // ----- Go to the end of the zip file
+ $v_size = filesize($this->_zipname);
+ @fseek($this->_zip_fd, $v_size);
+ if (@ftell($this->_zip_fd) != $v_size) {
+ $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
+ 'Unable to go to the end of the archive \''
+ .$this->_zipname.'\'');
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- First try : look if this is an archive with no commentaries
+ // (most of the time)
+ // in this case the end of central dir is at 22 bytes of the file end
+ $v_found = 0;
+ if ($v_size > 26) {
+ @fseek($this->_zip_fd, $v_size-22);
+ if (($v_pos = @ftell($this->_zip_fd)) != ($v_size-22)) {
+ $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
+ 'Unable to seek back to the middle of the archive \''
+ .$this->_zipname.'\'');
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- Read for bytes
+ $v_binary_data = @fread($this->_zip_fd, 4);
+ $v_data = unpack('Vid', $v_binary_data);
+
+ // ----- Check signature
+ if ($v_data['id'] == 0x06054b50) {
+ $v_found = 1;
+ }
+
+ $v_pos = ftell($this->_zip_fd);
+ }
+
+ // ----- Go back to the maximum possible size of the Central Dir End Record
+ if (!$v_found) {
+ $v_maximum_size = 65557; // 0xFFFF + 22;
+ if ($v_maximum_size > $v_size)
+ $v_maximum_size = $v_size;
+ @fseek($this->_zip_fd, $v_size-$v_maximum_size);
+ if (@ftell($this->_zip_fd) != ($v_size-$v_maximum_size)) {
+ $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
+ 'Unable to seek back to the middle of the archive \''
+ .$this->_zipname.'\'');
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- Read byte per byte in order to find the signature
+ $v_pos = ftell($this->_zip_fd);
+ $v_bytes = 0x00000000;
+ while ($v_pos < $v_size) {
+ // ----- Read a byte
+ $v_byte = @fread($this->_zip_fd, 1);
+
+ // ----- Add the byte
+ $v_bytes = ($v_bytes << 8) | Ord($v_byte);
+
+ // ----- Compare the bytes
+ if ($v_bytes == 0x504b0506) {
+ $v_pos++;
+ break;
+ }
+
+ $v_pos++;
+ }
+
+ // ----- Look if not found end of central dir
+ if ($v_pos == $v_size) {
+ $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
+ "Unable to find End of Central Dir Record signature");
+ return Archive_Zip::errorCode();
+ }
+ }
+
+ // ----- Read the first 18 bytes of the header
+ $v_binary_data = fread($this->_zip_fd, 18);
+
+ // ----- Look for invalid block size
+ if (strlen($v_binary_data) != 18) {
+ $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
+ "Invalid End of Central Dir Record size : "
+ .strlen($v_binary_data));
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- Extract the values
+ $v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data);
+
+ // ----- Check the global size
+ if (($v_pos + $v_data['comment_size'] + 18) != $v_size) {
+ $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
+ "Fail to find the right signature");
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- Get comment
+ if ($v_data['comment_size'] != 0)
+ $p_central_dir['comment'] = fread($this->_zip_fd, $v_data['comment_size']);
+ else
+ $p_central_dir['comment'] = '';
+
+ $p_central_dir['entries'] = $v_data['entries'];
+ $p_central_dir['disk_entries'] = $v_data['disk_entries'];
+ $p_central_dir['offset'] = $v_data['offset'];
+ $p_central_dir['size'] = $v_data['size'];
+ $p_central_dir['disk'] = $v_data['disk'];
+ $p_central_dir['disk_start'] = $v_data['disk_start'];
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _deleteByRule()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_deleteByRule()
+ *
+ * { Description }
+ *
+ */
+ function _deleteByRule(&$p_result_list, &$p_params)
+ {
+ $v_result=1;
+ $v_list_detail = array();
+
+ // ----- Open the zip file
+ if (($v_result=$this->_openFd('rb')) != 1)
+ {
+ // ----- Return
+ return $v_result;
+ }
+
+ // ----- Read the central directory informations
+ $v_central_dir = array();
+ if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1)
+ {
+ $this->_closeFd();
+ return $v_result;
+ }
+
+ // ----- Go to beginning of File
+ @rewind($this->_zip_fd);
+
+ // ----- Scan all the files
+ // ----- Start at beginning of Central Dir
+ $v_pos_entry = $v_central_dir['offset'];
+ @rewind($this->_zip_fd);
+ if (@fseek($this->_zip_fd, $v_pos_entry)) {
+ // ----- Clean
+ $this->_closeFd();
+
+ $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP,
+ 'Invalid archive size');
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- Read each entry
+ $v_header_list = array();
+ $j_start = 0;
+ for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++) {
+
+ // ----- Read the file header
+ $v_header_list[$v_nb_extracted] = array();
+ $v_result
+ = $this->_readCentralFileHeader($v_header_list[$v_nb_extracted]);
+ if ($v_result != 1) {
+ // ----- Clean
+ $this->_closeFd();
+
+ return $v_result;
+ }
+
+ // ----- Store the index
+ $v_header_list[$v_nb_extracted]['index'] = $i;
+
+ // ----- Look for the specific extract rules
+ $v_found = false;
+
+ // ----- Look for extract by name rule
+ if ( (isset($p_params[ARCHIVE_ZIP_PARAM_BY_NAME]))
+ && ($p_params[ARCHIVE_ZIP_PARAM_BY_NAME] != 0)) {
+
+ // ----- Look if the filename is in the list
+ for ($j=0;
+ ($j<sizeof($p_params[ARCHIVE_ZIP_PARAM_BY_NAME]))
+ && (!$v_found);
+ $j++) {
+
+ // ----- Look for a directory
+ if (substr($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j], -1) == "/") {
+
+ // ----- Look if the directory is in the filename path
+ if ( (strlen($v_header_list[$v_nb_extracted]['stored_filename']) > strlen($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j]))
+ && (substr($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) {
+ $v_found = true;
+ }
+ elseif ( (($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */
+ && ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) {
+ $v_found = true;
+ }
+ }
+ // ----- Look for a filename
+ elseif ($v_header_list[$v_nb_extracted]['stored_filename']
+ == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j]) {
+ $v_found = true;
+ }
+ }
+ }
+
+ // ----- Look for extract by ereg rule
+ else if ( (isset($p_params[ARCHIVE_ZIP_PARAM_BY_EREG]))
+ && ($p_params[ARCHIVE_ZIP_PARAM_BY_EREG] != "")) {
+
+ if (ereg($p_params[ARCHIVE_ZIP_PARAM_BY_EREG],
+ $v_header_list[$v_nb_extracted]['stored_filename'])) {
+ $v_found = true;
+ }
+ }
+
+ // ----- Look for extract by preg rule
+ else if ( (isset($p_params[ARCHIVE_ZIP_PARAM_BY_PREG]))
+ && ($p_params[ARCHIVE_ZIP_PARAM_BY_PREG] != "")) {
+
+ if (preg_match($p_params[ARCHIVE_ZIP_PARAM_BY_PREG],
+ $v_header_list[$v_nb_extracted]['stored_filename'])) {
+ $v_found = true;
+ }
+ }
+
+ // ----- Look for extract by index rule
+ else if ( (isset($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX]))
+ && ($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX] != 0)) {
+
+ // ----- Look if the index is in the list
+ for ($j=$j_start;
+ ($j<sizeof($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX]))
+ && (!$v_found);
+ $j++) {
+
+ if ( ($i>=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['start'])
+ && ($i<=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['end'])) {
+ $v_found = true;
+ }
+ if ($i>=$p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['end']) {
+ $j_start = $j+1;
+ }
+
+ if ($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['start']>$i) {
+ break;
+ }
+ }
+ }
+
+ // ----- Look for deletion
+ if ($v_found) {
+ unset($v_header_list[$v_nb_extracted]);
+ }
+ else {
+ $v_nb_extracted++;
+ }
+ }
+
+ // ----- Look if something need to be deleted
+ if ($v_nb_extracted > 0) {
+
+ // ----- Creates a temporay file
+ $v_zip_temp_name = ARCHIVE_ZIP_TEMPORARY_DIR.uniqid('archive_zip-')
+ .'.tmp';
+
+ // ----- Creates a temporary zip archive
+ $v_temp_zip = new Archive_Zip($v_zip_temp_name);
+
+ // ----- Open the temporary zip file in write mode
+ if (($v_result = $v_temp_zip->_openFd('wb')) != 1) {
+ $this->_closeFd();
+
+ // ----- Return
+ return $v_result;
+ }
+
+ // ----- Look which file need to be kept
+ for ($i=0; $i<sizeof($v_header_list); $i++) {
+
+ // ----- Calculate the position of the header
+ @rewind($this->_zip_fd);
+ if (@fseek($this->_zip_fd, $v_header_list[$i]['offset'])) {
+ // ----- Clean
+ $this->_closeFd();
+ $v_temp_zip->_closeFd();
+ @unlink($v_zip_temp_name);
+
+ $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP,
+ 'Invalid archive size');
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- Read the file header
+ if (($v_result = $this->_readFileHeader($v_header_list[$i])) != 1) {
+ // ----- Clean
+ $this->_closeFd();
+ $v_temp_zip->_closeFd();
+ @unlink($v_zip_temp_name);
+
+ return $v_result;
+ }
+
+ // ----- Write the file header
+ $v_result = $v_temp_zip->_writeFileHeader($v_header_list[$i]);
+ if ($v_result != 1) {
+ // ----- Clean
+ $this->_closeFd();
+ $v_temp_zip->_closeFd();
+ @unlink($v_zip_temp_name);
+
+ return $v_result;
+ }
+
+ // ----- Read/write the data block
+ $v_result = $this->_tool_CopyBlock($this->_zip_fd,
+ $v_temp_zip->_zip_fd,
+ $v_header_list[$i]['compressed_size']);
+ if ($v_result != 1) {
+ // ----- Clean
+ $this->_closeFd();
+ $v_temp_zip->_closeFd();
+ @unlink($v_zip_temp_name);
+
+ return $v_result;
+ }
+ }
+
+ // ----- Store the offset of the central dir
+ $v_offset = @ftell($v_temp_zip->_zip_fd);
+
+ // ----- Re-Create the Central Dir files header
+ for ($i=0; $i<sizeof($v_header_list); $i++) {
+ // ----- Create the file header
+ $v_result=$v_temp_zip->_writeCentralFileHeader($v_header_list[$i]);
+ if ($v_result != 1) {
+ // ----- Clean
+ $v_temp_zip->_closeFd();
+ $this->_closeFd();
+ @unlink($v_zip_temp_name);
+
+ return $v_result;
+ }
+
+ // ----- Transform the header to a 'usable' info
+ $v_temp_zip->_convertHeader2FileInfo($v_header_list[$i],
+ $p_result_list[$i]);
+ }
+
+
+ // ----- Zip file comment
+ $v_comment = '';
+
+ // ----- Calculate the size of the central header
+ $v_size = @ftell($v_temp_zip->_zip_fd)-$v_offset;
+
+ // ----- Create the central dir footer
+ $v_result = $v_temp_zip->_writeCentralHeader(sizeof($v_header_list),
+ $v_size, $v_offset,
+ $v_comment);
+ if ($v_result != 1) {
+ // ----- Clean
+ unset($v_header_list);
+ $v_temp_zip->_closeFd();
+ $this->_closeFd();
+ @unlink($v_zip_temp_name);
+
+ return $v_result;
+ }
+
+ // ----- Close
+ $v_temp_zip->_closeFd();
+ $this->_closeFd();
+
+ // ----- Delete the zip file
+ // TBC : I should test the result ...
+ @unlink($this->_zipname);
+
+ // ----- Rename the temporary file
+ // TBC : I should test the result ...
+ //@rename($v_zip_temp_name, $this->_zipname);
+ $this->_tool_Rename($v_zip_temp_name, $this->_zipname);
+
+ // ----- Destroy the temporary archive
+ unset($v_temp_zip);
+ }
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _dirCheck()
+ // Description :
+ // Check if a directory exists, if not it creates it and all the parents directory
+ // which may be useful.
+ // Parameters :
+ // $p_dir : Directory path to check.
+ // Return Values :
+ // 1 : OK
+ // -1 : Unable to create directory
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_dirCheck()
+ *
+ * { Description }
+ *
+ * @param [type] $p_is_dir
+ */
+ function _dirCheck($p_dir, $p_is_dir=false)
+ {
+ $v_result = 1;
+
+ // ----- Remove the final '/'
+ if (($p_is_dir) && (substr($p_dir, -1)=='/')) {
+ $p_dir = substr($p_dir, 0, strlen($p_dir)-1);
+ }
+
+ // ----- Check the directory availability
+ if ((is_dir($p_dir)) || ($p_dir == "")) {
+ return 1;
+ }
+
+ // ----- Extract parent directory
+ $p_parent_dir = dirname($p_dir);
+
+ // ----- Just a check
+ if ($p_parent_dir != $p_dir) {
+ // ----- Look for parent directory
+ if ($p_parent_dir != "") {
+ if (($v_result = $this->_dirCheck($p_parent_dir)) != 1) {
+ return $v_result;
+ }
+ }
+ }
+
+ // ----- Create the directory
+ if (!@mkdir($p_dir, 0777)) {
+ $this->_errorLog(ARCHIVE_ZIP_ERR_DIR_CREATE_FAIL,
+ "Unable to create directory '$p_dir'");
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _merge()
+ // Description :
+ // If $p_archive_to_add does not exist, the function exit with a success result.
+ // Parameters :
+ // Return Values :
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_merge()
+ *
+ * { Description }
+ *
+ */
+ function _merge(&$p_archive_to_add)
+ {
+ $v_result=1;
+
+ // ----- Look if the archive_to_add exists
+ if (!is_file($p_archive_to_add->_zipname)) {
+ // ----- Nothing to merge, so merge is a success
+ return 1;
+ }
+
+ // ----- Look if the archive exists
+ if (!is_file($this->_zipname)) {
+ // ----- Do a duplicate
+ $v_result = $this->_duplicate($p_archive_to_add->_zipname);
+
+ return $v_result;
+ }
+
+ // ----- Open the zip file
+ if (($v_result=$this->_openFd('rb')) != 1) {
+ return $v_result;
+ }
+
+ // ----- Read the central directory informations
+ $v_central_dir = array();
+ if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1) {
+ $this->_closeFd();
+ return $v_result;
+ }
+
+ // ----- Go to beginning of File
+ @rewind($this->_zip_fd);
+
+ // ----- Open the archive_to_add file
+ if (($v_result=$p_archive_to_add->_openFd('rb')) != 1) {
+ $this->_closeFd();
+ return $v_result;
+ }
+
+ // ----- Read the central directory informations
+ $v_central_dir_to_add = array();
+ $v_result = $p_archive_to_add->_readEndCentralDir($v_central_dir_to_add);
+ if ($v_result != 1) {
+ $this->_closeFd();
+ $p_archive_to_add->_closeFd();
+ return $v_result;
+ }
+
+ // ----- Go to beginning of File
+ @rewind($p_archive_to_add->_zip_fd);
+
+ // ----- Creates a temporay file
+ $v_zip_temp_name = ARCHIVE_ZIP_TEMPORARY_DIR.uniqid('archive_zip-').'.tmp';
+
+ // ----- Open the temporary file in write mode
+ if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) {
+ $this->_closeFd();
+ $p_archive_to_add->_closeFd();
+ $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL,
+ 'Unable to open temporary file \''
+ .$v_zip_temp_name.'\' in binary write mode');
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- Copy the files from the archive to the temporary file
+ // TBC : Here I should better append the file and go back to erase the
+ // central dir
+ $v_size = $v_central_dir['offset'];
+ while ($v_size != 0) {
+ $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
+ ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
+ $v_buffer = fread($this->_zip_fd, $v_read_size);
+ @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
+ $v_size -= $v_read_size;
+ }
+
+ // ----- Copy the files from the archive_to_add into the temporary file
+ $v_size = $v_central_dir_to_add['offset'];
+ while ($v_size != 0) {
+ $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
+ ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
+ $v_buffer = fread($p_archive_to_add->_zip_fd, $v_read_size);
+ @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
+ $v_size -= $v_read_size;
+ }
+
+ // ----- Store the offset of the central dir
+ $v_offset = @ftell($v_zip_temp_fd);
+
+ // ----- Copy the block of file headers from the old archive
+ $v_size = $v_central_dir['size'];
+ while ($v_size != 0) {
+ $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
+ ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
+ $v_buffer = @fread($this->_zip_fd, $v_read_size);
+ @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
+ $v_size -= $v_read_size;
+ }
+
+ // ----- Copy the block of file headers from the archive_to_add
+ $v_size = $v_central_dir_to_add['size'];
+ while ($v_size != 0) {
+ $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
+ ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
+ $v_buffer = @fread($p_archive_to_add->_zip_fd, $v_read_size);
+ @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
+ $v_size -= $v_read_size;
+ }
+
+ // ----- Zip file comment
+ // TBC : I should merge the two comments
+ $v_comment = '';
+
+ // ----- Calculate the size of the (new) central header
+ $v_size = @ftell($v_zip_temp_fd)-$v_offset;
+
+ // ----- Swap the file descriptor
+ // Here is a trick : I swap the temporary fd with the zip fd, in order to use
+ // the following methods on the temporary fil and not the real archive fd
+ $v_swap = $this->_zip_fd;
+ $this->_zip_fd = $v_zip_temp_fd;
+ $v_zip_temp_fd = $v_swap;
+
+ // ----- Create the central dir footer
+ if (($v_result = $this->_writeCentralHeader($v_central_dir['entries']
+ +$v_central_dir_to_add['entries'],
+ $v_size, $v_offset,
+ $v_comment)) != 1) {
+ $this->_closeFd();
+ $p_archive_to_add->_closeFd();
+ @fclose($v_zip_temp_fd);
+ $this->_zip_fd = null;
+
+ // ----- Reset the file list
+ unset($v_header_list);
+
+ // ----- Return
+ return $v_result;
+ }
+
+ // ----- Swap back the file descriptor
+ $v_swap = $this->_zip_fd;
+ $this->_zip_fd = $v_zip_temp_fd;
+ $v_zip_temp_fd = $v_swap;
+
+ // ----- Close
+ $this->_closeFd();
+ $p_archive_to_add->_closeFd();
+
+ // ----- Close the temporary file
+ @fclose($v_zip_temp_fd);
+
+ // ----- Delete the zip file
+ // TBC : I should test the result ...
+ @unlink($this->_zipname);
+
+ // ----- Rename the temporary file
+ // TBC : I should test the result ...
+ //@rename($v_zip_temp_name, $this->_zipname);
+ $this->_tool_Rename($v_zip_temp_name, $this->_zipname);
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _duplicate()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_duplicate()
+ *
+ * { Description }
+ *
+ */
+ function _duplicate($p_archive_filename)
+ {
+ $v_result=1;
+
+ // ----- Look if the $p_archive_filename exists
+ if (!is_file($p_archive_filename)) {
+
+ // ----- Nothing to duplicate, so duplicate is a success.
+ $v_result = 1;
+
+ // ----- Return
+ return $v_result;
+ }
+
+ // ----- Open the zip file
+ if (($v_result=$this->_openFd('wb')) != 1) {
+ // ----- Return
+ return $v_result;
+ }
+
+ // ----- Open the temporary file in write mode
+ if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0) {
+ $this->_closeFd();
+ $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL,
+ 'Unable to open archive file \''
+ .$p_archive_filename.'\' in binary write mode');
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- Copy the files from the archive to the temporary file
+ // TBC : Here I should better append the file and go back to erase the
+ // central dir
+ $v_size = filesize($p_archive_filename);
+ while ($v_size != 0) {
+ $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
+ ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
+ $v_buffer = fread($v_zip_temp_fd, $v_read_size);
+ @fwrite($this->_zip_fd, $v_buffer, $v_read_size);
+ $v_size -= $v_read_size;
+ }
+
+ // ----- Close
+ $this->_closeFd();
+
+ // ----- Close the temporary file
+ @fclose($v_zip_temp_fd);
+
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ /**
+ * Archive_Zip::_check_parameters()
+ *
+ * { Description }
+ *
+ * @param integer $p_error_code
+ * @param string $p_error_string
+ */
+ function _check_parameters(&$p_params, $p_default)
+ {
+
+ // ----- Check that param is an array
+ if (!is_array($p_params)) {
+ $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER,
+ 'Unsupported parameter, waiting for an array');
+ return Archive_Zip::errorCode();
+ }
+
+ // ----- Check that all the params are valid
+ for (reset($p_params); list($v_key, $v_value) = each($p_params); ) {
+ if (!isset($p_default[$v_key])) {
+ $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER,
+ 'Unsupported parameter with key \''.$v_key.'\'');
+
+ return Archive_Zip::errorCode();
+ }
+ }
+
+ // ----- Set the default values
+ for (reset($p_default); list($v_key, $v_value) = each($p_default); ) {
+ if (!isset($p_params[$v_key])) {
+ $p_params[$v_key] = $p_default[$v_key];
+ }
+ }
+
+ // ----- Check specific parameters
+ $v_callback_list = array ('callback_pre_add','callback_post_add',
+ 'callback_pre_extract','callback_post_extract');
+ for ($i=0; $i<sizeof($v_callback_list); $i++) {
+ $v_key=$v_callback_list[$i];
+ if ( (isset($p_params[$v_key])) && ($p_params[$v_key] != '')) {
+ if (!function_exists($p_params[$v_key])) {
+ $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAM_VALUE,
+ "Callback '".$p_params[$v_key]
+ ."()' is not an existing function for "
+ ."parameter '".$v_key."'");
+ return Archive_Zip::errorCode();
+ }
+ }
+ }
+
+ return(1);
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _errorLog()
+ // Description :
+ // Parameters :
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_errorLog()
+ *
+ * { Description }
+ *
+ * @param integer $p_error_code
+ * @param string $p_error_string
+ */
+ function _errorLog($p_error_code=0, $p_error_string='')
+ {
+ $this->_error_code = $p_error_code;
+ $this->_error_string = $p_error_string;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : _errorReset()
+ // Description :
+ // Parameters :
+ // ---------------------------------------------------------------------------
+ /**
+ * Archive_Zip::_errorReset()
+ *
+ * { Description }
+ *
+ */
+ function _errorReset()
+ {
+ $this->_error_code = 1;
+ $this->_error_string = '';
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : $this->_tool_PathReduction()
+ // Description :
+ // Parameters :
+ // Return Values :
+ // ---------------------------------------------------------------------------
+ /**
+ * _tool_PathReduction()
+ *
+ * { Description }
+ *
+ */
+ function _tool_PathReduction($p_dir)
+ {
+ $v_result = "";
+
+ // ----- Look for not empty path
+ if ($p_dir != "")
+ {
+ // ----- Explode path by directory names
+ $v_list = explode("/", $p_dir);
+
+ // ----- Study directories from last to first
+ for ($i=sizeof($v_list)-1; $i>=0; $i--)
+ {
+ // ----- Look for current path
+ if ($v_list[$i] == ".")
+ {
+ // ----- Ignore this directory
+ // Should be the first $i=0, but no check is done
+ }
+ else if ($v_list[$i] == "..")
+ {
+ // ----- Ignore it and ignore the $i-1
+ $i--;
+ }
+ else if (($v_list[$i] == "") && ($i!=(sizeof($v_list)-1)) && ($i!=0))
+ {
+ // ----- Ignore only the double '//' in path,
+ // but not the first and last '/'
+ }
+ else
+ {
+ $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?"/".$v_result:"");
+ }
+ }
+ }
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : $this->_tool_PathInclusion()
+ // Description :
+ // This function indicates if the path $p_path is under the $p_dir tree. Or,
+ // said in an other way, if the file or sub-dir $p_path is inside the dir
+ // $p_dir.
+ // The function indicates also if the path is exactly the same as the dir.
+ // This function supports path with duplicated '/' like '//', but does not
+ // support '.' or '..' statements.
+ // Parameters :
+ // Return Values :
+ // 0 if $p_path is not inside directory $p_dir
+ // 1 if $p_path is inside directory $p_dir
+ // 2 if $p_path is exactly the same as $p_dir
+ // ---------------------------------------------------------------------------
+ /**
+ * _tool_PathInclusion()
+ *
+ * { Description }
+ *
+ */
+ function _tool_PathInclusion($p_dir, $p_path)
+ {
+ $v_result = 1;
+
+ // ----- Explode dir and path by directory separator
+ $v_list_dir = explode("/", $p_dir);
+ $v_list_dir_size = sizeof($v_list_dir);
+ $v_list_path = explode("/", $p_path);
+ $v_list_path_size = sizeof($v_list_path);
+
+ // ----- Study directories paths
+ $i = 0;
+ $j = 0;
+ while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) {
+
+ // ----- Look for empty dir (path reduction)
+ if ($v_list_dir[$i] == '') {
+ $i++;
+ continue;
+ }
+ if ($v_list_path[$j] == '') {
+ $j++;
+ continue;
+ }
+
+ // ----- Compare the items
+ if ( ($v_list_dir[$i] != $v_list_path[$j])
+ && ($v_list_dir[$i] != '')
+ && ( $v_list_path[$j] != '')) {
+ $v_result = 0;
+ }
+
+ // ----- Next items
+ $i++;
+ $j++;
+ }
+
+ // ----- Look if everything seems to be the same
+ if ($v_result) {
+ // ----- Skip all the empty items
+ while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) $j++;
+ while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) $i++;
+
+ if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) {
+ // ----- There are exactly the same
+ $v_result = 2;
+ }
+ else if ($i < $v_list_dir_size) {
+ // ----- The path is shorter than the dir
+ $v_result = 0;
+ }
+ }
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : $this->_tool_CopyBlock()
+ // Description :
+ // Parameters :
+ // $p_mode : read/write compression mode
+ // 0 : src & dest normal
+ // 1 : src gzip, dest normal
+ // 2 : src normal, dest gzip
+ // 3 : src & dest gzip
+ // Return Values :
+ // ---------------------------------------------------------------------------
+ /**
+ * _tool_CopyBlock()
+ *
+ * { Description }
+ *
+ * @param integer $p_mode
+ */
+ function _tool_CopyBlock($p_src, $p_dest, $p_size, $p_mode=0)
+ {
+ $v_result = 1;
+
+ if ($p_mode==0)
+ {
+ while ($p_size != 0)
+ {
+ $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
+ ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
+ $v_buffer = @fread($p_src, $v_read_size);
+ @fwrite($p_dest, $v_buffer, $v_read_size);
+ $p_size -= $v_read_size;
+ }
+ }
+ else if ($p_mode==1)
+ {
+ while ($p_size != 0)
+ {
+ $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
+ ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
+ $v_buffer = @gzread($p_src, $v_read_size);
+ @fwrite($p_dest, $v_buffer, $v_read_size);
+ $p_size -= $v_read_size;
+ }
+ }
+ else if ($p_mode==2)
+ {
+ while ($p_size != 0)
+ {
+ $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
+ ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
+ $v_buffer = @fread($p_src, $v_read_size);
+ @gzwrite($p_dest, $v_buffer, $v_read_size);
+ $p_size -= $v_read_size;
+ }
+ }
+ else if ($p_mode==3)
+ {
+ while ($p_size != 0)
+ {
+ $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
+ ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
+ $v_buffer = @gzread($p_src, $v_read_size);
+ @gzwrite($p_dest, $v_buffer, $v_read_size);
+ $p_size -= $v_read_size;
+ }
+ }
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : $this->_tool_Rename()
+ // Description :
+ // This function tries to do a simple rename() function. If it fails, it
+ // tries to copy the $p_src file in a new $p_dest file and then unlink the
+ // first one.
+ // Parameters :
+ // $p_src : Old filename
+ // $p_dest : New filename
+ // Return Values :
+ // 1 on success, 0 on failure.
+ // ---------------------------------------------------------------------------
+ /**
+ * _tool_Rename()
+ *
+ * { Description }
+ *
+ */
+ function _tool_Rename($p_src, $p_dest)
+ {
+ $v_result = 1;
+
+ // ----- Try to rename the files
+ if (!@rename($p_src, $p_dest)) {
+
+ // ----- Try to copy & unlink the src
+ if (!@copy($p_src, $p_dest)) {
+ $v_result = 0;
+ }
+ else if (!@unlink($p_src)) {
+ $v_result = 0;
+ }
+ }
+
+ // ----- Return
+ return $v_result;
+ }
+ // ---------------------------------------------------------------------------
+
+ // ---------------------------------------------------------------------------
+ // Function : $this->_tool_TranslateWinPath()
+ // Description :
+ // Translate windows path by replacing '\' by '/' and optionally removing
+ // drive letter.
+ // Parameters :
+ // $p_path : path to translate.
+ // $p_remove_disk_letter : true | false
+ // Return Values :
+ // The path translated.
+ // ---------------------------------------------------------------------------
+ /**
+ * _tool_TranslateWinPath()
+ *
+ * { Description }
+ *
+ * @param [type] $p_remove_disk_letter
+ */
+ function _tool_TranslateWinPath($p_path, $p_remove_disk_letter=true)
+ {
+ if (stristr(php_uname(), 'windows')) {
+ // ----- Look for potential disk letter
+ if ( ($p_remove_disk_letter)
+ && (($v_position = strpos($p_path, ':')) != false)) {
+ $p_path = substr($p_path, $v_position+1);
+ }
+ // ----- Change potential windows directory separator
+ if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) {
+ $p_path = strtr($p_path, '\\', '/');
+ }
+ }
+ return $p_path;
+ }
+ // ---------------------------------------------------------------------------
+
+ }
+ // End of class
+
+?>
diff --git a/buildscripts/phing/classes/phing/listener/AnsiColorLogger.php b/buildscripts/phing/classes/phing/listener/AnsiColorLogger.php
new file mode 100644
index 00000000..00b0a7a9
--- /dev/null
+++ b/buildscripts/phing/classes/phing/listener/AnsiColorLogger.php
@@ -0,0 +1,231 @@
+<?php
+/*
+ * $Id: AnsiColorLogger.php,v 1.13 2005/05/26 13:10:51 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/listener/DefaultLogger.php';
+include_once 'phing/system/util/Properties.php';
+
+/**
+ * Uses ANSI Color Code Sequences to colorize messages
+ * sent to the console.
+ *
+ * If used with the -logfile option, the output file
+ * will contain all the necessary escape codes to
+ * display the text in colorized mode when displayed
+ * in the console using applications like cat, more,
+ * etc.
+ *
+ * This is designed to work on terminals that support ANSI
+ * color codes. It works on XTerm, ETerm, Mindterm, etc.
+ * It also works on Win9x (with ANSI.SYS loaded.)
+ *
+ * NOTE:
+ * It doesn't work on WinNT's COMMAND.COM even with
+ * ANSI.SYS loaded.
+ *
+ * The default colors used for differentiating
+ * the message levels can be changed by editing the
+ * /org/apache/tools/ant/listener/defaults.properties
+ * file.
+ * This file contains 5 key/value pairs:
+ * AnsiColorLogger.ERROR_COLOR=2;31
+ * AnsiColorLogger.WARNING_COLOR=2;35
+ * AnsiColorLogger.INFO_COLOR=2;36
+ * AnsiColorLogger.VERBOSE_COLOR=2;32
+ * AnsiColorLogger.DEBUG_COLOR=2;34
+ *
+ * Another option is to pass a system variable named
+ * ant.logger.defaults, with value set to the path of
+ * the file that contains user defined Ansi Color
+ * Codes, to the <B>java</B> command using -D option.
+ *
+ * To change these colors use the following chart:
+ *
+ * <B>ANSI COLOR LOGGER CONFIGURATION</B>
+ *
+ * Format for AnsiColorLogger.*=
+ * Attribute;Foreground;Background
+ *
+ * Attribute is one of the following:
+ * 0 -> Reset All Attributes (return to normal mode)
+ * 1 -> Bright (Usually turns on BOLD)
+ * 2 -> Dim
+ * 3 -> Underline
+ * 5 -> link
+ * 7 -> Reverse
+ * 8 -> Hidden
+ *
+ * Foreground is one of the following:
+ * 30 -> Black
+ * 31 -> Red
+ * 32 -> Green
+ * 33 -> Yellow
+ * 34 -> Blue
+ * 35 -> Magenta
+ * 36 -> Cyan
+ * 37 -> White
+ *
+ * Background is one of the following:
+ * 40 -> Black
+ * 41 -> Red
+ * 42 -> Green
+ * 43 -> Yellow
+ * 44 -> Blue
+ * 45 -> Magenta
+ * 46 -> Cyan
+ * 47 -> White
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Magesh Umasankar (Ant)
+ * @package phing.listener
+ * @version $Revision: 1.13 $
+ */
+final class AnsiColorLogger extends DefaultLogger {
+
+ const ATTR_NORMAL = 0;
+ const ATTR_BRIGHT = 1;
+ const ATTR_DIM = 2;
+ const ATTR_UNDERLINE = 3;
+ const ATTR_BLINK = 5;
+ const ATTR_REVERSE = 7;
+ const ATTR_HIDDEN = 8;
+
+ const FG_BLACK = 30;
+ const FG_RED = 31;
+ const FG_GREEN = 32;
+ const FG_YELLOW = 33;
+ const FG_BLUE = 34;
+ const FG_MAGENTA = 35;
+ const FG_CYAN = 36;
+ const FG_WHITE = 37;
+
+ const BG_BLACK = 40;
+ const BG_RED = 41;
+ const BG_GREEN = 42;
+ const BG_YELLOW = 44;
+ const BG_BLUE = 44;
+ const BG_MAGENTA = 45;
+ const BG_CYAN = 46;
+ const BG_WHITE = 47;
+
+ const PREFIX = "\x1b[";
+ const SUFFIX = "m";
+ const SEPARATOR = ';';
+ const END_COLOR = "\x1b[m"; // self::PREFIX . self::SUFFIX;
+
+ private $errColor;
+ private $warnColor;
+ private $infoColor;
+ private $verboseColor;
+ private $debugColor;
+
+ private $colorsSet = false;
+
+ /**
+ * Construct new AnsiColorLogger
+ * Perform initializations that cannot be done in var declarations.
+ */
+ public function __construct() {
+ parent::__construct();
+ $this->errColor = self::PREFIX . self::ATTR_DIM . self::SEPARATOR . self::FG_RED . self::SUFFIX;
+ $this->warnColor = self::PREFIX . self::ATTR_DIM . self::SEPARATOR . self::FG_MAGENTA . self::SUFFIX;
+ $this->infoColor = self::PREFIX . self::ATTR_DIM . self::SEPARATOR . self::FG_CYAN . self::SUFFIX;
+ $this->verboseColor = self::PREFIX . self::ATTR_DIM . self::SEPARATOR . self::FG_GREEN . self::SUFFIX;
+ $this->debugColor = self::PREFIX . self::ATTR_DIM . self::SEPARATOR . self::FG_BLUE . self::SUFFIX;
+ }
+
+ /**
+ * Set the colors to use from a property file specified by the
+ * special ant property ant.logger.defaults
+ */
+ private final function setColors() {
+
+ $userColorFile = Phing::getProperty("phing.logger.defaults");
+ $systemColorFile = new PhingFile(Phing::getResourcePath("phing/listener/defaults.properties"));
+
+ $in = null;
+
+ try {
+ $prop = new Properties();
+
+ if ($userColorFile !== null) {
+ $prop->load($userColorFile);
+ } else {
+ $prop->load($systemColorFile);
+ }
+
+ $err = $prop->getProperty("AnsiColorLogger.ERROR_COLOR");
+ $warn = $prop->getProperty("AnsiColorLogger.WARNING_COLOR");
+ $info = $prop->getProperty("AnsiColorLogger.INFO_COLOR");
+ $verbose = $prop->getProperty("AnsiColorLogger.VERBOSE_COLOR");
+ $debug = $prop->getProperty("AnsiColorLogger.DEBUG_COLOR");
+ if ($err !== null) {
+ $errColor = self::PREFIX . $err . self::SUFFIX;
+ }
+ if ($warn !== null) {
+ $warnColor = self::PREFIX . $warn . self::SUFFIX;
+ }
+ if ($info !== null) {
+ $infoColor = self::PREFIX . $info . self::SUFFIX;
+ }
+ if ($verbose !== null) {
+ $verboseColor = self::PREFIX . $verbose . self::SUFFIX;
+ }
+ if ($debug !== null) {
+ $debugColor = self::PREFIX . $debug . self::SUFFIX;
+ }
+ } catch (IOException $ioe) {
+ //Ignore exception - we will use the defaults.
+ }
+ }
+
+ /**
+ * @see DefaultLogger#printMessage
+ */
+ protected final function printMessage($message, $priority) {
+
+ if ($message !== null) {
+
+ if (!$this->colorsSet) {
+ $this->setColors();
+ $this->colorsSet = true;
+ }
+
+ switch ($priority) {
+ case PROJECT_MSG_ERR:
+ $message = $this->errColor . $message . self::END_COLOR;
+ break;
+ case PROJECT_MSG_WARN:
+ $message = $this->warnColor . $message . self::END_COLOR;
+ break;
+ case PROJECT_MSG_INFO:
+ $message = $this->infoColor . $message . self::END_COLOR;
+ break;
+ case PROJECT_MSG_VERBOSE:
+ $message = $this->verboseColor . $message . self::END_COLOR;
+ break;
+ case PROJECT_MSG_DEBUG:
+ $message = $this->debugColor . $message . self::END_COLOR;
+ break;
+ }
+ print($message."\n");
+ }
+ }
+}
diff --git a/buildscripts/phing/classes/phing/listener/BuildLogger.php b/buildscripts/phing/classes/phing/listener/BuildLogger.php
new file mode 100644
index 00000000..d1c5fcb6
--- /dev/null
+++ b/buildscripts/phing/classes/phing/listener/BuildLogger.php
@@ -0,0 +1,42 @@
+<?php
+ /**
+ * $Id: BuildLogger.php,v 1.3 2005/02/11 10:51:21 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+ require_once 'phing/BuildListener.php';
+ /**
+ * Interface used by Phing Ant to log the build output.
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: BuildLogger.php,v 1.3 2005/02/11 10:51:21 mrook Exp $
+ * @package phing.listener
+ */
+ interface BuildLogger extends BuildListener
+ {
+ /**
+ * Sets the highest level of message this logger should respond to.
+ *
+ * Only messages with a message level lower than or equal to the
+ * given level should be written to the log.
+ *
+ * @param int the logging level for the logger.
+ */
+ function setMessageOutputLevel($level);
+ };
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/listener/DefaultLogger.php b/buildscripts/phing/classes/phing/listener/DefaultLogger.php
new file mode 100644
index 00000000..c7387592
--- /dev/null
+++ b/buildscripts/phing/classes/phing/listener/DefaultLogger.php
@@ -0,0 +1,233 @@
+<?php
+/*
+ * $Id: DefaultLogger.php,v 1.11 2005/08/25 19:33:43 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/BuildListener.php';
+include_once 'phing/BuildEvent.php';
+
+/**
+ * Writes a build event to the console.
+ *
+ * Currently, it only writes which targets are being executed, and
+ * any messages that get logged.
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright © 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.11 $ $Date: 2005/08/25 19:33:43 $
+ * @see BuildEvent
+ * @package phing.listener
+ */
+class DefaultLogger implements BuildListener {
+
+ /**
+ * Size of the left column in output. The default char width is 12.
+ * @var int
+ */
+ const LEFT_COLUMN_SIZE = 12;
+
+ /**
+ * The message output level that should be used. The default is
+ * <code>PROJECT_MSG_VERBOSE</code>.
+ * @var int
+ */
+ protected $msgOutputLevel = PROJECT_MSG_ERR;
+
+ /**
+ * Time that the build started
+ * @var int
+ */
+ protected $startTime;
+
+ /**
+ * Char that should be used to seperate lines. Default is the system
+ * property <em>line.seperator</em>.
+ * @var string
+ */
+ protected $lSep;
+
+ /**
+ * Construct a new default logger.
+ */
+ public function __construct() {
+ $this->lSep = Phing::getProperty("line.separator");
+ }
+
+ /**
+ * Set the msgOutputLevel this logger is to respond to.
+ *
+ * Only messages with a message level lower than or equal to the given
+ * level are output to the log.
+ *
+ * <p> Constants for the message levels are in Project.php. The order of
+ * the levels, from least to most verbose, is:
+ *
+ * <ul>
+ * <li>PROJECT_MSG_ERR</li>
+ * <li>PROJECT_MSG_WARN</li>
+ * <li>PROJECT_MSG_INFO</li>
+ * <li>PROJECT_MSG_VERBOSE</li>
+ * <li>PROJECT_MSG_DEBUG</li>
+ * </ul>
+ *
+ * The default message level for DefaultLogger is PROJECT_MSG_ERR.
+ *
+ * @param integer the logging level for the logger.
+ * @access public
+ */
+ function setMessageOutputLevel($level) {
+ $this->msgOutputLevel = (int) $level;
+ }
+
+ /**
+ * Sets the start-time when the build started. Used for calculating
+ * the build-time.
+ *
+ * @param object The BuildEvent
+ * @access public
+ */
+
+ function buildStarted(BuildEvent $event) {
+ $this->startTime = Phing::currentTimeMillis();
+ if ($this->msgOutputLevel >= PROJECT_MSG_INFO) {
+ $this->printMessage("Buildfile: ".$event->getProject()->getProperty("phing.file"), PROJECT_MSG_INFO);
+ }
+ }
+
+ /**
+ * Prints whether the build succeeded or failed, and any errors that
+ * occured during the build. Also outputs the total build-time.
+ *
+ * @param object The BuildEvent
+ * @access public
+ * @see BuildEvent::getException()
+ */
+ function buildFinished(BuildEvent $event) {
+ $error = $event->getException();
+ if ($error === null) {
+ print($this->lSep . "BUILD FINISHED" . $this->lSep);
+ } else {
+ print($this->lSep . "BUILD FAILED" . $this->lSep);
+ if (PROJECT_MSG_VERBOSE <= $this->msgOutputLevel || !($error instanceof BuildException)) {
+ print($error->__toString().$this->lSep);
+ } else {
+ print($error->getMessage());
+ }
+ }
+ print($this->lSep . "Total time: " .$this->_formatTime(Phing::currentTimeMillis() - $this->startTime) . $this->lSep);
+ }
+
+ /**
+ * Prints the current target name
+ *
+ * @param object The BuildEvent
+ * @access public
+ * @see BuildEvent::getTarget()
+ */
+ function targetStarted(BuildEvent $event) {
+ if (PROJECT_MSG_INFO <= $this->msgOutputLevel) {
+ print($this->lSep . $event->getProject()->getName() . ' > ' . $event->getTarget()->getName() . ':' . $this->lSep);
+ }
+ }
+
+ /**
+ * Fired when a target has finished. We don't need specific action on this
+ * event. So the methods are empty.
+ *
+ * @param object The BuildEvent
+ * @access public
+ * @see BuildEvent::getException()
+ */
+ function targetFinished(BuildEvent $event) {}
+
+ /**
+ * Fired when a task is started. We don't need specific action on this
+ * event. So the methods are empty.
+ *
+ * @param object The BuildEvent
+ * @access public
+ * @see BuildEvent::getTask()
+ */
+ function taskStarted(BuildEvent $event) {}
+
+ /**
+ * Fired when a task has finished. We don't need specific action on this
+ * event. So the methods are empty.
+ *
+ * @param object The BuildEvent
+ * @access public
+ * @see BuildEvent::getException()
+ */
+ function taskFinished(BuildEvent $event) {}
+
+ /**
+ * Print a message to the stdout.
+ *
+ * @param object The BuildEvent
+ * @access public
+ * @see BuildEvent::getMessage()
+ */
+ function messageLogged(BuildEvent $event) {
+ if ($event->getPriority() <= $this->msgOutputLevel) {
+ $msg = "";
+ if ($event->getTask() !== null) {
+ $name = $event->getTask();
+ $name = $name->getTaskName();
+ $msg = str_pad("[$name] ", self::LEFT_COLUMN_SIZE, " ", STR_PAD_LEFT);
+ #for ($i=0; $i < ($this->LEFT_COLUMN_SIZE - strlen($msg)); ++$i) {
+ # print(" ");
+ #}
+ #print($msg);
+ }
+ $msg .= $event->getMessage();
+ $this->printMessage($msg, $event->getPriority());
+ }
+ }
+
+ /**
+ * Formats a time micro integer to human readable format.
+ *
+ * @param integer The time stamp
+ * @access private
+ */
+ function _formatTime($micros) {
+ $seconds = $micros;
+ $minutes = $seconds / 60;
+ if ($minutes > 1) {
+ return sprintf("%1.0f minute%s %0.2f second%s",
+ $minutes, ($minutes === 1 ? " " : "s "),
+ $seconds - floor($seconds/60) * 60, ($seconds%60 === 1 ? "" : "s"));
+ } else {
+ return sprintf("%0.4f second%s", $seconds, ($seconds%60 === 1 ? "" : "s"));
+ }
+ }
+
+ /**
+ * Prints a message to console.
+ *
+ * @param string $message The message to print.
+ * Should not be <code>null</code>.
+ * @param int $priority The priority of the message.
+ * (Ignored in this implementation.)
+ * @return void
+ */
+ protected function printMessage($message, $priority) {
+ print($message . $this->lSep);
+ }
+}
diff --git a/buildscripts/phing/classes/phing/listener/NoBannerLogger.php b/buildscripts/phing/classes/phing/listener/NoBannerLogger.php
new file mode 100644
index 00000000..e222e10c
--- /dev/null
+++ b/buildscripts/phing/classes/phing/listener/NoBannerLogger.php
@@ -0,0 +1,61 @@
+<?php
+/*
+ * $Id: NoBannerLogger.php,v 1.4 2003/12/24 13:02:08 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/listener/DefaultLogger.php';
+
+/**
+ * Extends DefaultLogger to strip out empty targets. This logger is most
+ * commonly used and also enforced by the default phing invokation scripts
+ * in bin/.
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright © 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.4 $ $Date: 2003/12/24 13:02:08 $
+ * @package phing.listener
+ */
+class NoBannerLogger extends DefaultLogger {
+
+ private $targetName = null;
+
+ function targetStarted(BuildEvent $event) {
+ $target = $event->getTarget();
+ $this->targetName = $target->getName();
+ }
+
+ function targetFinished(BuildEvent $event) {
+ $this->targetName = null;
+ }
+
+ function messageLogged(BuildEvent $event) {
+ if ($event->getPriority() > $this->msgOutputLevel ||
+ null === $event->getMessage() ||
+ trim($event->getMessage() === "")) {
+ return;
+ }
+
+ if ($this->targetName !== null) {
+ print($this->lSep . "Target: ".$this->targetName . $this->lSep);
+ $this->targetName = null;
+ }
+
+ parent::messageLogged($event);
+ }
+}
diff --git a/buildscripts/phing/classes/phing/listener/PearLogger.php b/buildscripts/phing/classes/phing/listener/PearLogger.php
new file mode 100644
index 00000000..2bea6655
--- /dev/null
+++ b/buildscripts/phing/classes/phing/listener/PearLogger.php
@@ -0,0 +1,246 @@
+<?php
+/*
+ * $Id: PearLogger.php,v 1.3 2004/03/15 14:45:06 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/BuildListener.php';
+include_once 'phing/BuildEvent.php';
+require_once 'Log.php';
+
+/**
+ * Writes log messages to PEAR Log.
+ *
+ * By default it will log to file in current directory w/ name 'phing.log'. You can customize
+ * this behavior by setting properties:
+ * - pear.log.type
+ * - pear.log.name
+ * - pear.log.ident (note that this class changes ident to project name)
+ * - pear.log.conf (note that array values are currently unsupported in Phing property files)
+ *
+ * <code>
+ * phing -f build.xml -logger phing.listener.PearLogger -Dpear.log.type=file -Dpear.log.name=/path/to/log.log
+ * </code>
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.3 $ $Date: 2004/03/15 14:45:06 $
+ * @see BuildEvent
+ * @package phing.listener
+ */
+class PearLogger implements BuildListener {
+
+ /**
+ * Size of the left column in output. The default char width is 12.
+ * @var int
+ */
+ const LEFT_COLUMN_SIZE = 12;
+
+ /**
+ * The message output level that should be used. The default is
+ * <code>PROJECT_MSG_VERBOSE</code>.
+ * @var int
+ */
+ protected $msgOutputLevel = PROJECT_MSG_ERR;
+
+ /**
+ * Time that the build started
+ * @var int
+ */
+ protected $startTime;
+
+ /**
+ * Maps Phing PROJECT_MSG_* constants to PEAR_LOG_* constants.
+ * @var array
+ */
+ protected static $levelMap = array( PROJECT_MSG_DEBUG => PEAR_LOG_DEBUG,
+ PROJECT_MSG_INFO => PEAR_LOG_INFO,
+ PROJECT_MSG_VERBOSE => PEAR_LOG_NOTICE,
+ PROJECT_MSG_WARN => PEAR_LOG_WARNING,
+ PROJECT_MSG_ERR => PEAR_LOG_ERR
+ );
+ /**
+ * Whether logging has been configured.
+ * @var boolean
+ */
+ protected $logConfigured = false;
+
+ /**
+ * Configure the logger.
+ */
+ protected function configureLogging() {
+
+ $type = Phing::getDefinedProperty('pear.log.type');
+ $name = Phing::getDefinedProperty('pear.log.name');
+ $ident = Phing::getDefinedProperty('pear.log.ident');
+ $conf = Phing::getDefinedProperty('pear.log.conf');
+
+ if ($type === null) $type = 'file';
+ if ($name === null) $name = 'phing.log';
+ if ($ident === null) $ident = 'phing';
+ if ($conf === null) $conf = array();
+
+ $this->logger = Log::singleton($type, $name, $ident, $conf, self::$levelMap[$this->msgOutputLevel]);
+ }
+
+ /**
+ * Get the configured PEAR logger to use.
+ * This method just ensures that logging has been configured and returns the configured logger.
+ * @return Log
+ */
+ protected function logger() {
+ if (!$this->logConfigured) {
+ $this->configureLogging();
+ }
+ return $this->logger;
+ }
+
+ /**
+ * Set the msgOutputLevel this logger is to respond to.
+ *
+ * Only messages with a message level lower than or equal to the given
+ * level are output to the log.
+ *
+ * <p> Constants for the message levels are in Project.php. The order of
+ * the levels, from least to most verbose, is:
+ *
+ * <ul>
+ * <li>PROJECT_MSG_ERR</li>
+ * <li>PROJECT_MSG_WARN</li>
+ * <li>PROJECT_MSG_INFO</li>
+ * <li>PROJECT_MSG_VERBOSE</li>
+ * <li>PROJECT_MSG_DEBUG</li>
+ * </ul>
+ *
+ * The default message level for DefaultLogger is PROJECT_MSG_ERR.
+ *
+ * @param integer the logging level for the logger.
+ * @access public
+ */
+ function setMessageOutputLevel($level) {
+ $this->msgOutputLevel = (int) $level;
+ }
+
+ /**
+ * Sets the start-time when the build started. Used for calculating
+ * the build-time.
+ *
+ * @param object The BuildEvent
+ * @access public
+ */
+
+ function buildStarted(BuildEvent $event) {
+ $this->startTime = Phing::currentTimeMillis();
+ $this->logger()->setIdent($event->getProject()->getName());
+ $this->logger()->info("Starting build with buildfile: ". $event->getProject()->getProperty("phing.file"));
+ }
+
+ /**
+ * Prints whether the build succeeded or failed, and any errors that
+ * occured during the build. Also outputs the total build-time.
+ *
+ * @param object The BuildEvent
+ * @access public
+ * @see BuildEvent::getException()
+ */
+ function buildFinished(BuildEvent $event) {
+ $error = $event->getException();
+ if ($error === null) {
+ $msg = "Finished successful build.";
+ } else {
+ $msg = "Build failed. [reason: " . $error->getMessage() ."]";
+ }
+ $this->logger()->log($msg . " Total time: " . $this->_formatTime(Phing::currentTimeMillis() - $this->startTime));
+ }
+
+ /**
+ * Prints the current target name
+ *
+ * @param object The BuildEvent
+ * @access public
+ * @see BuildEvent::getTarget()
+ */
+ function targetStarted(BuildEvent $event) {}
+
+ /**
+ * Fired when a target has finished. We don't need specific action on this
+ * event. So the methods are empty.
+ *
+ * @param object The BuildEvent
+ * @access public
+ * @see BuildEvent::getException()
+ */
+ function targetFinished(BuildEvent $event) {}
+
+ /**
+ * Fired when a task is started. We don't need specific action on this
+ * event. So the methods are empty.
+ *
+ * @param object The BuildEvent
+ * @access public
+ * @see BuildEvent::getTask()
+ */
+ function taskStarted(BuildEvent $event) {}
+
+ /**
+ * Fired when a task has finished. We don't need specific action on this
+ * event. So the methods are empty.
+ *
+ * @param object The BuildEvent
+ * @access public
+ * @see BuildEvent::getException()
+ */
+ function taskFinished(BuildEvent $event) {}
+
+ /**
+ * Print a message to the stdout.
+ *
+ * @param object The BuildEvent
+ * @access public
+ * @see BuildEvent::getMessage()
+ */
+ function messageLogged(BuildEvent $event) {
+ if ($event->getPriority() <= $this->msgOutputLevel) {
+ $msg = "";
+ if ($event->getTask() !== null) {
+ $name = $event->getTask();
+ $name = $name->getTaskName();
+ $msg = str_pad("[$name] ", self::LEFT_COLUMN_SIZE, " ", STR_PAD_LEFT);
+ }
+ $msg .= $event->getMessage();
+ $this->logger()->log($msg, self::$levelMap[$event->getPriority()]);
+ }
+ }
+
+ /**
+ * Formats a time micro integer to human readable format.
+ *
+ * @param integer The time stamp
+ * @access private
+ */
+ function _formatTime($micros) {
+ $seconds = $micros;
+ $minutes = $seconds / 60;
+ if ($minutes > 1) {
+ return sprintf("%1.0f minute%s %0.2f second%s",
+ $minutes, ($minutes === 1 ? " " : "s "),
+ $seconds - floor($seconds/60) * 60, ($seconds%60 === 1 ? "" : "s"));
+ } else {
+ return sprintf("%0.4f second%s", $seconds, ($seconds%60 === 1 ? "" : "s"));
+ }
+ }
+}
diff --git a/buildscripts/phing/classes/phing/listener/XmlLogger.php b/buildscripts/phing/classes/phing/listener/XmlLogger.php
new file mode 100644
index 00000000..07ff031e
--- /dev/null
+++ b/buildscripts/phing/classes/phing/listener/XmlLogger.php
@@ -0,0 +1,265 @@
+<?php
+ /**
+ * $Id: XmlLogger.php,v 1.3 2005/02/11 10:51:21 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+ require_once 'phing/listener/BuildLogger.php';
+ require_once 'phing/listener/DefaultLogger.php';
+ require_once 'phing/system/util/Timer.php';
+ /**
+ * Generates a file in the current directory with
+ * an XML description of what happened during a build.
+ * The default filename is "log.xml", but this can be overridden
+ * with the property <code>XmlLogger.file</code>.
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: XmlLogger.php,v 1.3 2005/02/11 10:51:21 mrook Exp $
+ * @package phing.listener
+ */
+ class XmlLogger implements BuildLogger
+ {
+ /** XML element name for a build. */
+ const BUILD_TAG = "build";
+ /** XML element name for a target. */
+ const TARGET_TAG = "target";
+ /** XML element name for a task. */
+ const TASK_TAG = "task";
+ /** XML element name for a message. */
+ const MESSAGE_TAG = "message";
+ /** XML attribute name for a name. */
+ const NAME_ATTR = "name";
+ /** XML attribute name for a time. */
+ const TIME_ATTR = "time";
+ /** XML attribute name for a message priority. */
+ const PRIORITY_ATTR = "priority";
+ /** XML attribute name for a file location. */
+ const LOCATION_ATTR = "location";
+ /** XML attribute name for an error description. */
+ const ERROR_ATTR = "error";
+ /** XML element name for a stack trace. */
+ const STACKTRACE_TAG = "stacktrace";
+
+ private $doc = NULL;
+
+ private $buildStartTime = 0;
+ private $targetStartTime = 0;
+ private $taskStartTime = 0;
+
+ private $buildElement = NULL;
+
+ private $msgOutputLevel = PROJECT_MSG_DEBUG;
+
+ /**
+ * Constructs a new BuildListener that logs build events to an XML file.
+ */
+ function __construct()
+ {
+ $this->doc = new DOMDocument();
+ $this->doc->formatOutput = true;
+
+ $this->buildTimer = new Timer();
+ $this->targetTimer = new Timer();
+ $this->taskTimer = new Timer();
+ }
+
+ /**
+ * Fired when the build starts, this builds the top-level element for the
+ * document and remembers the time of the start of the build.
+ *
+ * @param BuildEvent Ignored.
+ */
+ function buildStarted(BuildEvent $event)
+ {
+ $this->buildTimerStart = Phing::currentTimeMillis();
+ $this->buildElement = $this->doc->createElement(XmlLogger::BUILD_TAG);
+ }
+
+ /**
+ * Fired when the build finishes, this adds the time taken and any
+ * error stacktrace to the build element and writes the document to disk.
+ *
+ * @param BuildEvent An event with any relevant extra information.
+ * Will not be <code>null</code>.
+ */
+ function buildFinished(BuildEvent $event)
+ {
+ $this->buildTimer->stop();
+
+ $elapsedTime = Phing::currentTimeMillis() - $this->buildTimerStart;
+
+ $this->buildElement->setAttribute(XmlLogger::TIME_ATTR, DefaultLogger::_formatTime($elapsedTime));
+
+ if ($event->getException() != null)
+ {
+ $this->buildElement->setAttribute(XmlLogger::ERROR_ATTR, $event->getException()->toString());
+
+ $errText = $this->doc->createCDATASection($event->getException()->getTraceAsString());
+ $stacktrace = $this->doc->createElement(XmlLogger::STACKTRACE_TAG);
+ $stacktrace->appendChild($errText);
+ $this->buildElement->appendChild($stacktrace);
+ }
+
+ $outFilename = $event->getProject()->getProperty("XmlLogger.file");
+
+ if ($outFilename == "")
+ {
+ $outFilename = "log.xml";
+ }
+ $writer = new FileWriter($outFilename);
+
+ $writer->write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ $writer->write($this->doc->saveXML($this->buildElement));
+ $writer->close();
+ }
+ /**
+ * Fired when a target starts building, remembers the current time and the name of the target.
+ *
+ * @param BuildEvent An event with any relevant extra information.
+ * Will not be <code>null</code>.
+ */
+ function targetStarted(BuildEvent $event)
+ {
+ $target = $event->getTarget();
+
+ $this->targetTimerStart = Phing::currentTimeMillis();
+
+ $this->targetElement = $this->doc->createElement(XmlLogger::TARGET_TAG);
+ $this->targetElement->setAttribute(XmlLogger::NAME_ATTR, $target->getName());
+ }
+
+ /**
+ * Fired when a target finishes building, this adds the time taken
+ * to the appropriate target element in the log.
+ *
+ * @param BuildEvent An event with any relevant extra information.
+ * Will not be <code>null</code>.
+ */
+ function targetFinished(BuildEvent $event)
+ {
+ $target = $event->getTarget();
+
+ $elapsedTime = Phing::currentTimeMillis() - $this->targetTimerStart;
+
+ $this->targetElement->setAttribute(XmlLogger::TIME_ATTR, DefaultLogger::_formatTime($elapsedTime));
+
+ $this->buildElement->appendChild($this->targetElement);
+ }
+
+ /**
+ * Fired when a task starts building, remembers the current time and the name of the task.
+ *
+ * @param BuildEvent An event with any relevant extra information.
+ * Will not be <code>null</code>.
+ */
+ function taskStarted(BuildEvent $event)
+ {
+ $task = $event->getTask();
+
+ $this->taskTimerStart = Phing::currentTimeMillis();
+
+ $this->taskElement = $this->doc->createElement(XmlLogger::TASK_TAG);
+ $this->taskElement->setAttribute(XmlLogger::NAME_ATTR, $task->getTaskName());
+ $this->taskElement->setAttribute(XmlLogger::LOCATION_ATTR, $task->getLocation()->toString());
+ }
+ /**
+ * Fired when a task finishes building, this adds the time taken
+ * to the appropriate task element in the log.
+ *
+ * @param BuildEvent An event with any relevant extra information.
+ * Will not be <code>null</code>.
+ */
+ function taskFinished(BuildEvent $event)
+ {
+ $task = $event->getTask();
+
+ $elapsedTime = Phing::currentTimeMillis() - $this->taskTimerStart;
+ $this->taskElement->setAttribute(XmlLogger::TIME_ATTR, DefaultLogger::_formatTime($elapsedTime));
+
+ $this->targetElement->appendChild($this->taskElement);
+ }
+
+ /**
+ * Fired when a message is logged, this adds a message element to the
+ * most appropriate parent element (task, target or build) and records
+ * the priority and text of the message.
+ *
+ * @param BuildEvent An event with any relevant extra information.
+ * Will not be <code>null</code>.
+ */
+ function messageLogged(BuildEvent $event)
+ {
+ $priority = $event->getPriority();
+
+ if ($priority > $this->msgOutputLevel)
+ {
+ return;
+ }
+
+ $messageElement = $this->doc->createElement(XmlLogger::MESSAGE_TAG);
+
+ switch ($priority)
+ {
+ case PROJECT_MSG_ERR:
+ $name = "error";
+ break;
+
+ case PROJECT_MSG_WARN:
+ $name = "warn";
+ break;
+
+ case PROJECT_MSG_INFO:
+ $name = "info";
+ break;
+
+ default:
+ $name = "debug";
+ break;
+ }
+
+ $messageElement->setAttribute(XmlLogger::PRIORITY_ATTR, $name);
+
+ $messageText = $this->doc->createCDATASection($event->getMessage());
+
+ $messageElement->appendChild($messageText);
+
+ if ($event->getTask() != null)
+ {
+ $this->taskElement->appendChild($messageElement);
+ }
+ else
+ if ($event->getTarget() != null)
+ {
+ $this->targetElement->appendChild($messageElement);
+ }
+ else
+ if ($this->buildElement != null)
+ {
+ $this->buildElement->appendChild($messageElement);
+ }
+ }
+
+ /**
+ * Set the logging level when using this as a Logger
+ */
+ function setMessageOutputLevel($level)
+ {
+ $this->msgOutputLevel = $level;
+ }
+ };
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/listener/defaults.properties b/buildscripts/phing/classes/phing/listener/defaults.properties
new file mode 100644
index 00000000..f60a3fd5
--- /dev/null
+++ b/buildscripts/phing/classes/phing/listener/defaults.properties
@@ -0,0 +1,43 @@
+####################################################
+#
+# ANSI COLOR LOGGER CONFIGURATION
+#
+# Format for AnsiColorLogger.*=
+# Attribute;Foreground;Background
+#
+# Attribute is one of the following:
+# 0 -> Reset All Attributes (return to normal mode)
+# 1 -> Bright (Usually turns on BOLD)
+# 2 -> Dim
+# 3 -> Underline
+# 5 -> link
+# 7 -> Reverse
+# 8 -> Hidden
+#
+# Foreground is one of the following:
+# 30 -> Black
+# 31 -> Red
+# 32 -> Green
+# 33 -> Yellow
+# 34 -> Blue
+# 35 -> Magenta
+# 36 -> Cyan
+# 37 -> White
+#
+# Background is one of the following:
+# 40 -> Black
+# 41 -> Red
+# 42 -> Green
+# 43 -> Yellow
+# 44 -> Blue
+# 45 -> Magenta
+# 46 -> Cyan
+# 47 -> White
+#
+####################################################
+
+AnsiColorLogger.ERROR_COLOR=2;31
+AnsiColorLogger.WARNING_COLOR=2;35
+AnsiColorLogger.INFO_COLOR=2;36
+AnsiColorLogger.VERBOSE_COLOR=2;32
+AnsiColorLogger.DEBUG_COLOR=2;34
diff --git a/buildscripts/phing/classes/phing/mappers/FileNameMapper.php b/buildscripts/phing/classes/phing/mappers/FileNameMapper.php
new file mode 100644
index 00000000..c8f1f8a9
--- /dev/null
+++ b/buildscripts/phing/classes/phing/mappers/FileNameMapper.php
@@ -0,0 +1,59 @@
+<?php
+/*
+ * $Id: FileNameMapper.php,v 1.7 2004/01/22 03:29:13 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * Interface for filename mapper classes.
+ *
+ * @author Andreas Aderhold, andi@binarycloud.com
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.7 $
+ * @package phing.mappers
+ */
+interface FileNameMapper {
+
+ /**
+ * The mapper implementation.
+ *
+ * @param mixed $sourceFileName The data the mapper works on.
+ * @return array The data after the mapper has been applied; must be in array format (for some reason).
+ */
+ public function main($sourceFileName);
+
+ /**
+ * Accessor. Sets the to property. The actual implementation
+ * depends on the child class.
+ *
+ * @param string $to To what this mapper should convert the from string
+ * @return void
+ */
+ public function setTo($to);
+
+ /**
+ * Accessor. Sets the from property. What this mapper should
+ * recognize. The actual implementation is dependent upon the
+ * child class
+ *
+ * @param string $from On what this mapper should work
+ * @return void
+ */
+ public function setFrom($from);
+
+}
diff --git a/buildscripts/phing/classes/phing/mappers/FlattenMapper.php b/buildscripts/phing/classes/phing/mappers/FlattenMapper.php
new file mode 100644
index 00000000..fea5c1e4
--- /dev/null
+++ b/buildscripts/phing/classes/phing/mappers/FlattenMapper.php
@@ -0,0 +1,55 @@
+<?php
+/*
+ * $Id: FlattenMapper.php,v 1.9 2005/05/26 13:10:51 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/mappers/FileNameMapper.php';
+
+/**
+ * Removes any directory information from the passed path.
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @version $Revision: 1.9 $
+ * @package phing.mappers
+ */
+class FlattenMapper implements FileNameMapper {
+
+ /**
+ * The mapper implementation. Returns string with source filename
+ * but without leading directory information
+ *
+ * @param string $sourceFileName The data the mapper works on
+ * @return array The data after the mapper has been applied
+ */
+ function main($sourceFileName) {
+ $f = new PhingFile($sourceFileName);
+ return array($f->getName());
+ }
+
+ /**
+ * Ignored here.
+ */
+ function setTo($to) {}
+
+ /**
+ * Ignored here.
+ */
+ function setFrom($from) {}
+
+}
diff --git a/buildscripts/phing/classes/phing/mappers/GlobMapper.php b/buildscripts/phing/classes/phing/mappers/GlobMapper.php
new file mode 100644
index 00000000..3c178620
--- /dev/null
+++ b/buildscripts/phing/classes/phing/mappers/GlobMapper.php
@@ -0,0 +1,113 @@
+<?php
+/*
+ * $Id: GlobMapper.php,v 1.10 2004/01/22 03:29:13 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/mappers/FileNameMapper.php';
+
+/**
+ * description here
+ *
+ * @author Andreas Aderhold, andi@binarycloud.com
+ * @version $Revision: 1.10 $
+ * @package phing.mappers
+ */
+class GlobMapper implements FileNameMapper {
+
+ /**
+ * Part of &quot;from&quot; pattern before the *.
+ */
+ private $fromPrefix = null;
+
+ /**
+ * Part of &quot;from&quot; pattern after the *.
+ */
+ private $fromPostfix = null;
+
+ /**
+ * Length of the prefix (&quot;from&quot; pattern).
+ */
+ private $prefixLength;
+
+ /**
+ * Length of the postfix (&quot;from&quot; pattern).
+ */
+ private $postfixLength;
+
+ /**
+ * Part of &quot;to&quot; pattern before the *.
+ */
+ private $toPrefix = null;
+
+ /**
+ * Part of &quot;to&quot; pattern after the *.
+ */
+ private $toPostfix = null;
+
+
+ function main($_sourceFileName) {
+ if (($this->fromPrefix === null)
+ || !StringHelper::startsWith($this->fromPrefix, $_sourceFileName)
+ || !StringHelper::endsWith($this->fromPostfix, $_sourceFileName)) {
+ return null;
+ }
+ $varpart = $this->_extractVariablePart($_sourceFileName);
+ $substitution = $this->toPrefix.$varpart.$this->toPostfix;
+ return array($substitution);
+ }
+
+
+
+ function setFrom($from) {
+ $index = strrpos($from, '*');
+
+ if ($index === false) {
+ $this->fromPrefix = $from;
+ $this->fromPostfix = "";
+ } else {
+ $this->fromPrefix = substr($from, 0, $index);
+ $this->fromPostfix = substr($from, $index+1);
+ }
+ $this->prefixLength = strlen($this->fromPrefix);
+ $this->postfixLength = strlen($this->fromPostfix);
+ }
+
+ /**
+ * Sets the &quot;to&quot; pattern. Required.
+ */
+ function setTo($to) {
+ $index = strrpos($to, '*');
+ if ($index === false) {
+ $this->toPrefix = $to;
+ $this->toPostfix = "";
+ } else {
+ $this->toPrefix = substr($to, 0, $index);
+ $this->toPostfix = substr($to, $index+1);
+ }
+ }
+
+ private function _extractVariablePart($_name) {
+ // ergh, i really hate php's string functions .... all but natural
+ $start = ($this->prefixLength === 0) ? 0 : $this->prefixLength;
+ $end = ($this->postfixLength === 0) ? strlen($_name) : strlen($_name) - $this->postfixLength;
+ $len = $end-$start;
+ return substr($_name, $start, $len);
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/mappers/IdentityMapper.php b/buildscripts/phing/classes/phing/mappers/IdentityMapper.php
new file mode 100644
index 00000000..daf80c25
--- /dev/null
+++ b/buildscripts/phing/classes/phing/mappers/IdentityMapper.php
@@ -0,0 +1,54 @@
+<?php
+/*
+ * $Id: IdentityMapper.php,v 1.7 2004/01/22 03:29:13 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/mappers/FileNameMapper.php';
+
+/**
+ * This mapper does nothing ;)
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.7 $
+ * @package phing.mappers
+ */
+class IdentityMapper implements FileNameMapper {
+
+ /**
+ * The mapper implementation. Basically does nothing in this case.
+ *
+ * @param string $sourceFileName The data the mapper works on.
+ * @return array The data after the mapper has been applied
+ */
+ function main($sourceFileName) {
+ return array($sourceFileName);
+ }
+
+ /**
+ * Ignored here.
+ */
+ function setTo($to) {}
+
+ /**
+ * Ignored here.
+ */
+ function setFrom($from) {}
+
+}
diff --git a/buildscripts/phing/classes/phing/mappers/MergeMapper.php b/buildscripts/phing/classes/phing/mappers/MergeMapper.php
new file mode 100644
index 00000000..f10f41c0
--- /dev/null
+++ b/buildscripts/phing/classes/phing/mappers/MergeMapper.php
@@ -0,0 +1,69 @@
+<?php
+/*
+ * $Id: MergeMapper.php,v 1.8 2004/01/22 03:29:13 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/mappers/FileNameMapper.php';
+
+/**
+ * For merging files into a single file. In practice just returns whatever value
+ * was set for "to".
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @version $Revision: 1.8 $
+ * @package phing.mappers
+ */
+class MergeMapper implements FileNameMapper {
+
+ /** the merge */
+ private $mergedFile;
+
+ /**
+ * The mapper implementation. Basically does nothing in this case.
+ *
+ * @param mixed The data the mapper works on
+ * @returns mixed The data after the mapper has been applied
+ * @access public
+ * @author Andreas Aderhold, andi@binarycloud.com
+ */
+ function main($sourceFileName) {
+ if ($this->mergedFile === null) {
+ throw new BuildException("MergeMapper error, to attribute not set");
+ }
+ return array($this->mergedFile);
+ }
+
+ /**
+ * Accessor. Sets the to property
+ *
+ * @param string To what this mapper should convert the from string
+ * @returns boolean True
+ * @access public
+ * @author Andreas Aderhold, andi@binarycloud.com
+ */
+ function setTo($to) {
+ $this->mergedFile = $to;
+ }
+
+ /**
+ * Ignored.
+ */
+ function setFrom($from) {}
+
+}
diff --git a/buildscripts/phing/classes/phing/mappers/RegexpMapper.php b/buildscripts/phing/classes/phing/mappers/RegexpMapper.php
new file mode 100644
index 00000000..a3d51976
--- /dev/null
+++ b/buildscripts/phing/classes/phing/mappers/RegexpMapper.php
@@ -0,0 +1,97 @@
+<?php
+/*
+ * $Id: RegexpMapper.php,v 1.9 2004/03/15 17:11:15 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/mappers/FileNameMapper.php';
+include_once 'phing/util/StringHelper.php';
+include_once 'phing/util/regexp/Regexp.php';
+
+/**
+ * Uses regular expressions to perform filename transformations.
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @author Hans Lellelid <hans@velum.net>
+ * @version $Revision: 1.9 $
+ * @package phing.mappers
+ */
+class RegexpMapper implements FileNameMapper {
+
+ /**
+ * @var string
+ */
+ private $to;
+
+ /**
+ * The Regexp engine.
+ * @var Regexp
+ */
+ private $reg;
+
+ function __construct() {
+ // instantiage regexp matcher here
+ $this->reg = new Regexp();
+ }
+
+ /**
+ * Sets the &quot;from&quot; pattern. Required.
+ */
+ function setFrom($from) {
+ $this->reg->SetPattern($from);
+ }
+
+ /**
+ * Sets the &quot;to&quot; pattern. Required.
+ */
+ function setTo($to) {
+
+ // [HL] I'm changing the way this works for now to just use string
+ //$this->to = StringHelper::toCharArray($to);
+
+ $this->to = $to;
+ }
+
+ function main($sourceFileName) {
+ if ($this->reg === null || $this->to === null || !$this->reg->matches((string) $sourceFileName)) {
+ return null;
+ }
+ return array($this->replaceReferences($sourceFileName));
+ }
+
+ /**
+ * Replace all backreferences in the to pattern with the matched groups.
+ * groups of the source.
+ * @param string $source The source filename.
+ */
+ private function replaceReferences($source) {
+
+ // FIXME
+ // Can't we just use engine->replace() to handle this? the Preg engine
+ // will automatically convert \1 references to $1
+
+ // the expression has already been processed (when ->matches() was run in Main())
+ // so no need to pass $source again to the engine.
+ $groups = (array) $this->reg->getGroups();
+
+ // replace \1 with value of $groups[1] and return the modified "to" string
+ return preg_replace('/\\\([\d]+)/e', "\$groups[$1]", $this->to);
+ }
+
+}
+
diff --git a/buildscripts/phing/classes/phing/parser/AbstractHandler.php b/buildscripts/phing/classes/phing/parser/AbstractHandler.php
new file mode 100644
index 00000000..6f8d7705
--- /dev/null
+++ b/buildscripts/phing/classes/phing/parser/AbstractHandler.php
@@ -0,0 +1,98 @@
+<?php
+
+/*
+ * $Id: AbstractHandler.php,v 1.6 2004/02/27 18:16:10 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/parser/ExpatParseException.php';
+
+/**
+ * This is an abstract class all SAX handler classes must extend
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright © 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.6 $
+ * @package phing.parser
+ */
+abstract class AbstractHandler {
+
+ public $parentHandler = null;
+ public $parser = null;
+
+ /**
+ * Constructs a SAX handler parser.
+ *
+ * The constructor must be called by all derived classes.
+ *
+ * @param object the parser object
+ * @param object the parent handler of this handler
+ */
+ protected function __construct($parser, $parentHandler) {
+ $this->parentHandler = $parentHandler;
+ $this->parser = $parser;
+ $this->parser->setHandler($this);
+ }
+
+ /**
+ * Gets invoked when a XML open tag occurs
+ *
+ * Must be overloaded by the child class. Throws an ExpatParseException
+ * if there is no handler registered for an element.
+ *
+ * @param string the name of the XML element
+ * @param array the attributes of the XML element
+ */
+ public function startElement($name, $attribs) {
+ throw new ExpatParseException("Unexpected element $name");
+ }
+
+ /**
+ * Gets invoked when element closes method.
+ *
+ */
+ protected function finished() {}
+
+ /**
+ * Gets invoked when a XML element ends.
+ *
+ * Can be overloaded by the child class. But should not. It hands
+ * over control to the parentHandler of this.
+ *
+ * @param string the name of the XML element
+ */
+ public function endElement($name) {
+ $this->finished();
+ $this->parser->setHandler($this->parentHandler);
+ }
+
+ /**
+ * Invoked by occurance of #PCDATA.
+ *
+ * @param string the name of the XML element
+ * @exception ExpatParserException if there is no CDATA but method
+ * was called
+ * @access public
+ */
+ public function characters($data) {
+ $s = trim($data);
+ if (strlen($s) > 0) {
+ throw new ExpatParseException("Unexpected text '$s'", $this->parser->getLocation());
+ }
+ }
+}
diff --git a/buildscripts/phing/classes/phing/parser/AbstractSAXParser.php b/buildscripts/phing/classes/phing/parser/AbstractSAXParser.php
new file mode 100644
index 00000000..60cf0c11
--- /dev/null
+++ b/buildscripts/phing/classes/phing/parser/AbstractSAXParser.php
@@ -0,0 +1,140 @@
+<?php
+/*
+ * $Id: AbstractSAXParser.php,v 1.13 2004/03/20 03:33:06 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * The abstract SAX parser class.
+ *
+ * This class represents a SAX parser. It is a abstract calss that must be
+ * implemented by the real parser that must extend this class
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @copyright © 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.13 $
+ * @package phing.parser
+ */
+abstract class AbstractSAXParser {
+
+ /** The AbstractHandler object. */
+ protected $handler;
+
+ /**
+ * Constructs a SAX parser
+ */
+ function __construct() {}
+
+ /**
+ * Sets options for PHP interal parser. Must be implemented by the parser
+ * class if it should be used.
+ */
+ abstract function parserSetOption($opt, $val);
+
+ /**
+ * Sets the current element handler object for this parser. Usually this
+ * is an object using extending "AbstractHandler".
+ *
+ * @param AbstractHandler $obj The handler object.
+ */
+ function setHandler( $obj) {
+ $this->handler = $obj;
+ }
+
+ /**
+ * Method that gets invoked when the parser runs over a XML start element.
+ *
+ * This method is called by PHP's internal parser funcitons and registered
+ * in the actual parser implementation.
+ * It gives control to the current active handler object by calling the
+ * <code>startElement()</code> method.
+ *
+ * BECAUSE OF PROBLEMS WITH EXCEPTIONS BUBBLING UP THROUGH xml_parse() THIS
+ * METHOD WILL CALL Phing::halt(-1) ON EXCEPTION.
+ *
+ * @param object the php's internal parser handle
+ * @param string the open tag name
+ * @param array the tag's attributes if any
+ */
+ function startElement($parser, $name, $attribs) {
+ try {
+ $this->handler->startElement($name, $attribs);
+ } catch (Exception $e) {
+ print "[Exception in XML parsing]\n";
+ print $e;
+ Phing::halt(-1);
+ }
+ }
+
+ /**
+ * Method that gets invoked when the parser runs over a XML close element.
+ *
+ * This method is called by PHP's internal parser funcitons and registered
+ * in the actual parser implementation.
+ *
+ * It gives control to the current active handler object by calling the
+ * <code>endElement()</code> method.
+ *
+ * BECAUSE OF PROBLEMS WITH EXCEPTIONS BUBBLING UP THROUGH xml_parse() THIS
+ * METHOD WILL CALL Phing::halt(-1) ON EXCEPTION.
+ *
+ * @param object the php's internal parser handle
+ * @param string the closing tag name
+ */
+ function endElement($parser, $name) {
+ try {
+ $this->handler->endElement($name);
+ } catch (Exception $e) {
+ print "[Exception in XML parsing]\n";
+ print $e;
+ Phing::halt(-1);
+ }
+ }
+
+ /**
+ * Method that gets invoked when the parser runs over CDATA.
+ *
+ * This method is called by PHP's internal parser functions and registered
+ * in the actual parser implementation.
+ *
+ * It gives control to the current active handler object by calling the
+ * <code>characters()</code> method. That processes the given CDATA.
+ *
+ * BECAUSE OF PROBLEMS WITH EXCEPTIONS BUBBLING UP THROUGH xml_parse() THIS
+ * METHOD WILL CALL Phing::halt(-1) ON EXCEPTION.
+ *
+ * @param resource $parser php's internal parser handle.
+ * @param string $data the CDATA
+ */
+ function characters($parser, $data) {
+ try {
+ $this->handler->characters($data);
+ } catch (Exception $e) {
+ print "[Exception in XML parsing]\n";
+ print $e;
+ Phing::halt(-1);
+ }
+ }
+
+ /**
+ * Entrypoint for parser. This method needs to be implemented by the
+ * child classt that utilizes the concrete parser
+ */
+ abstract function parse();
+}
diff --git a/buildscripts/phing/classes/phing/parser/DataTypeHandler.php b/buildscripts/phing/classes/phing/parser/DataTypeHandler.php
new file mode 100644
index 00000000..37d757c4
--- /dev/null
+++ b/buildscripts/phing/classes/phing/parser/DataTypeHandler.php
@@ -0,0 +1,144 @@
+<?php
+/*
+ * $Id: DataTypeHandler.php,v 1.8 2005/11/02 13:55:33 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/RuntimeConfigurable.php';
+
+/**
+ * Configures a Project (complete with Targets and Tasks) based on
+ * a XML build file.
+ * <p>
+ * Design/ZE2 migration note:
+ * If PHP would support nested classes. All the phing/parser/*Filter
+ * classes would be nested within this class
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright © 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.8 $ $Date: 2005/11/02 13:55:33 $
+ * @access public
+ * @package phing.parser
+ */
+
+class DataTypeHandler extends AbstractHandler {
+
+ private $target;
+ private $element;
+ private $wrapper;
+
+ /**
+ * Constructs a new DataTypeHandler and sets up everything.
+ *
+ * @param AbstractSAXParser $parser The XML parser (default: ExpatParser)
+ * @param AbstractHandler $parentHandler The parent handler that invoked this handler.
+ * @param ProjectConfigurator $configurator The ProjectConfigurator object
+ * @param Target $target The target object this datatype is contained in (null for top-level datatypes).
+ */
+ function __construct(AbstractSAXParser $parser, AbstractHandler $parentHandler, ProjectConfigurator $configurator, $target = null) { // FIXME b2 typehinting
+ parent::__construct($parser, $parentHandler);
+ $this->target = $target;
+ $this->configurator = $configurator;
+ }
+
+ /**
+ * Executes initialization actions required to setup the data structures
+ * related to the tag.
+ * <p>
+ * This includes:
+ * <ul>
+ * <li>creation of the datatype object</li>
+ * <li>calling the setters for attributes</li>
+ * <li>adding the type to the target object if any</li>
+ * <li>adding a reference to the task (if id attribute is given)</li>
+ * </ul>
+ *
+ * @param string the tag that comes in
+ * @param array attributes the tag carries
+ * @throws ExpatParseException if attributes are incomplete or invalid
+ * @access public
+ */
+ function init($propType, $attrs) {
+ // shorthands
+ $project = $this->configurator->project;
+ $configurator = $this->configurator;
+
+ try {//try
+ $this->element = $project->createDataType($propType);
+
+ if ($this->element === null) {
+ throw new BuildException("Unknown data type $propType");
+ }
+
+ if ($this->target !== null) {
+ $this->wrapper = new RuntimeConfigurable($this->element, $propType);
+ $this->wrapper->setAttributes($attrs);
+ $this->target->addDataType($this->wrapper);
+ } else {
+ $configurator->configure($this->element, $attrs, $project);
+ $configurator->configureId($this->element, $attrs);
+ }
+
+ } catch (BuildException $exc) {
+ throw new ExpatParseException($exc, $this->parser->getLocation());
+ }
+ }
+
+ /**
+ * Handles character data.
+ *
+ * @param string the CDATA that comes in
+ * @access public
+ */
+ function characters($data) {
+ $project = $this->configurator->project;
+ try {//try
+ $this->configurator->addText($project, $this->element, $data);
+ } catch (BuildException $exc) {
+ throw new ExpatParseException($exc->getMessage(), $this->parser->getLocation());
+ }
+ }
+
+ /**
+ * Checks for nested tags within the current one. Creates and calls
+ * handlers respectively.
+ *
+ * @param string the tag that comes in
+ * @param array attributes the tag carries
+ * @access public
+ */
+ function startElement($name, $attrs) {
+ $nef = new NestedElementHandler($this->parser, $this, $this->configurator, $this->element, $this->wrapper, $this->target);
+ $nef->init($name, $attrs);
+ }
+
+ /**
+ * Overrides endElement for data types. Tells the type
+ * handler that processing the element had been finished so
+ * handlers know they can perform actions that need to be
+ * based on the data contained within the element.
+ *
+ * @param string the name of the XML element
+ * @return void
+ */
+ function endElement($name) {
+ $this->element->parsingComplete();
+ parent::endElement($name);
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/parser/ExpatParseException.php b/buildscripts/phing/classes/phing/parser/ExpatParseException.php
new file mode 100644
index 00000000..d5086c30
--- /dev/null
+++ b/buildscripts/phing/classes/phing/parser/ExpatParseException.php
@@ -0,0 +1,31 @@
+<?php
+/*
+ * $Id: ExpatParseException.php,v 1.5 2003/11/19 05:48:28 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/BuildException.php';
+
+/**
+ * This class throws errors for Expat, the XML processor.
+ *
+ * @author Andreas Aderhold, andi@binarycloud.com
+ * @version $Revision: 1.5 $ $Date: 2003/11/19 05:48:28 $
+ * @package phing.parser
+ */
+class ExpatParseException extends BuildException {}
diff --git a/buildscripts/phing/classes/phing/parser/ExpatParser.php b/buildscripts/phing/classes/phing/parser/ExpatParser.php
new file mode 100644
index 00000000..82046f8d
--- /dev/null
+++ b/buildscripts/phing/classes/phing/parser/ExpatParser.php
@@ -0,0 +1,140 @@
+<?php
+/*
+ * $Id: ExpatParser.php,v 1.8 2005/05/26 13:10:52 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/parser/AbstractSAXParser.php';
+include_once 'phing/parser/ExpatParseException.php';
+include_once 'phing/system/io/IOException.php';
+include_once 'phing/system/io/FileReader.php';
+
+/**
+ * This class is a wrapper for the PHP's internal expat parser.
+ *
+ * It takes an XML file represented by a abstract path name, and starts
+ * parsing the file and calling the different "trap" methods inherited from
+ * the AbstractParser class.
+ *
+ * Those methods then invoke the represenatative methods in the registered
+ * handler classes.
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright © 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.8 $ $Date: 2005/05/26 13:10:52 $
+ * @access public
+ * @package phing.parser
+ */
+
+class ExpatParser extends AbstractSAXParser {
+
+ /** @var resource */
+ private $parser;
+
+ /** @var Reader */
+ private $reader;
+
+ private $file;
+
+ private $buffer = 4096;
+
+ private $error_string = "";
+
+ private $line = 0;
+
+ /** @var Location Current cursor pos in XML file. */
+ private $location;
+
+ /**
+ * Constructs a new ExpatParser object.
+ *
+ * The constructor accepts a PhingFile object that represents the filename
+ * for the file to be parsed. It sets up php's internal expat parser
+ * and options.
+ *
+ * @param Reader $reader The Reader Object that is to be read from.
+ * @param string $filename Filename to read.
+ * @throws Exception if the given argument is not a PhingFile object
+ */
+ function __construct(Reader $reader, $filename=null) {
+
+ $this->reader = $reader;
+ if ($filename !== null) {
+ $this->file = new PhingFile($filename);
+ }
+ $this->parser = xml_parser_create();
+ $this->buffer = 4096;
+ $this->location = new Location();
+ xml_set_object($this->parser, $this);
+ xml_set_element_handler($this->parser, array($this,"startElement"),array($this,"endElement"));
+ xml_set_character_data_handler($this->parser, array($this, "characters"));
+ }
+
+ /**
+ * Override PHP's parser default settings, created in the constructor.
+ *
+ * @param string the option to set
+ * @throws mixed the value to set
+ * @return boolean true if the option could be set, otherwise false
+ * @access public
+ */
+ function parserSetOption($opt, $val) {
+ return xml_parser_set_option($this->parser, $opt, $val);
+ }
+
+ /**
+ * Returns the location object of the current parsed element. It describes
+ * the location of the element within the XML file (line, char)
+ *
+ * @return object the location of the current parser
+ * @access public
+ */
+ function getLocation() {
+ if ($this->file !== null) {
+ $path = $this->file->getAbsolutePath();
+ } else {
+ $path = $this->reader->getResource();
+ }
+ $this->location = new Location($path, xml_get_current_line_number($this->parser), xml_get_current_column_number($this->parser));
+ return $this->location;
+ }
+
+ /**
+ * Starts the parsing process.
+ *
+ * @param string the option to set
+ * @return int 1 if the parsing succeeded
+ * @throws ExpatParseException if something gone wrong during parsing
+ * @throws IOException if XML file can not be accessed
+ * @access public
+ */
+ function parse() {
+
+ while ( ($data = $this->reader->read()) !== -1 ) {
+ if (!xml_parse($this->parser, $data, $this->reader->eof())) {
+ $error = xml_error_string(xml_get_error_code($this->parser));
+ $e = new ExpatParseException($error, $this->getLocation());
+ xml_parser_free($this->parser);
+ throw $e;
+ }
+ }
+ xml_parser_free($this->parser);
+
+ return 1;
+ }
+}
diff --git a/buildscripts/phing/classes/phing/parser/Location.php b/buildscripts/phing/classes/phing/parser/Location.php
new file mode 100644
index 00000000..fd79866c
--- /dev/null
+++ b/buildscripts/phing/classes/phing/parser/Location.php
@@ -0,0 +1,72 @@
+<?php
+/*
+ * $Id: Location.php,v 1.6 2003/12/24 13:02:09 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * Stores the file name and line number of a XML file
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright © 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.6 $ $Date: 2003/12/24 13:02:09 $
+ * @access public
+ * @package phing.parser
+ */
+
+class Location {
+
+ private $fileName;
+ private $lineNumber;
+ private $columnNumber;
+
+ /**
+ * Constructs the location consisting of a file name and line number
+ *
+ * @param string the filename
+ * @param integer the line number
+ * @param integer the column number
+ * @access public
+ */
+ function Location($fileName = null, $lineNumber = null, $columnNumber = null) {
+ $this->fileName = $fileName;
+ $this->lineNumber = $lineNumber;
+ $this->columnNumber = $columnNumber;
+ }
+
+ /**
+ * Returns the file name, line number and a trailing space.
+ *
+ * An error message can be appended easily. For unknown locations,
+ * returns empty string.
+ *
+ * @return string the string representation of this Location object
+ * @access public
+ */
+ function toString() {
+ $buf = "";
+ if ($this->fileName !== null) {
+ $buf.=$this->fileName;
+ if ($this->lineNumber !== null) {
+ $buf.= ":".$this->lineNumber;
+ }
+ $buf.=":".$this->columnNumber;
+ }
+ return (string) $buf;
+ }
+}
diff --git a/buildscripts/phing/classes/phing/parser/NestedElementHandler.php b/buildscripts/phing/classes/phing/parser/NestedElementHandler.php
new file mode 100644
index 00000000..8ecd0ed3
--- /dev/null
+++ b/buildscripts/phing/classes/phing/parser/NestedElementHandler.php
@@ -0,0 +1,186 @@
+<?php
+/*
+ * $Id: NestedElementHandler.php,v 1.10 2005/10/04 19:13:44 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/IntrospectionHelper.php';
+include_once 'phing/TaskContainer.php';
+
+/**
+ * The nested element handler class.
+ *
+ * This class handles the occurance of runtime registered tags like
+ * datatypes (fileset, patternset, etc) and it's possible nested tags. It
+ * introspects the implementation of the class and sets up the data structures.
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright © 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.10 $ $Date: 2005/10/04 19:13:44 $
+ * @access public
+ * @package phing.parser
+ */
+
+class NestedElementHandler extends AbstractHandler {
+
+ /**
+ * Reference to the parent object that represents the parent tag
+ * of this nested element
+ * @var object
+ */
+ private $parent;
+
+ /**
+ * Reference to the child object that represents the child tag
+ * of this nested element
+ * @var object
+ */
+ private $child;
+
+ /**
+ * Reference to the parent wrapper object
+ * @var object
+ */
+ private $parentWrapper;
+
+ /**
+ * Reference to the child wrapper object
+ * @var object
+ */
+ private $childWrapper;
+
+ /**
+ * Reference to the related target object
+ * @var object the target instance
+ */
+ private $target;
+
+ /**
+ * Constructs a new NestedElement handler and sets up everything.
+ *
+ * @param object the ExpatParser object
+ * @param object the parent handler that invoked this handler
+ * @param object the ProjectConfigurator object
+ * @param object the parent object this element is contained in
+ * @param object the parent wrapper object
+ * @param object the target object this task is contained in
+ * @access public
+ */
+ function __construct($parser, $parentHandler, $configurator, $parent, $parentWrapper, $target) {
+ parent::__construct($parser, $parentHandler);
+ $this->configurator = $configurator;
+ if ($parent instanceof TaskAdapter) {
+ $this->parent = $parent->getProxy();
+ } else {
+ $this->parent = $parent;
+ }
+ $this->parentWrapper = $parentWrapper;
+ $this->target = $target;
+ }
+
+ /**
+ * Executes initialization actions required to setup the data structures
+ * related to the tag.
+ * <p>
+ * This includes:
+ * <ul>
+ * <li>creation of the nested element</li>
+ * <li>calling the setters for attributes</li>
+ * <li>adding the element to the container object</li>
+ * <li>adding a reference to the element (if id attribute is given)</li>
+ * </ul>
+ *
+ * @param string the tag that comes in
+ * @param array attributes the tag carries
+ * @throws ExpatParseException if the setup process fails
+ * @access public
+ */
+ function init($propType, $attrs) {
+ $configurator = $this->configurator;
+ $project = $this->configurator->project;
+
+ // introspect the parent class that is custom
+ $parentClass = get_class($this->parent);
+ $ih = IntrospectionHelper::getHelper($parentClass);
+ try {
+ if ($this->parent instanceof UnknownElement) {
+ $this->child = new UnknownElement(strtolower($propType));
+ $this->parent->addChild($this->child);
+ } else {
+ $this->child = $ih->createElement($project, $this->parent, strtolower($propType));
+ }
+
+ $configurator->configureId($this->child, $attrs);
+
+ if ($this->parentWrapper !== null) {
+ $this->childWrapper = new RuntimeConfigurable($this->child, $propType);
+ $this->childWrapper->setAttributes($attrs);
+ $this->parentWrapper->addChild($this->childWrapper);
+ } else {
+ $configurator->configure($this->child, $attrs, $project);
+ $ih->storeElement($project, $this->parent, $this->child, strtolower($propType));
+ }
+ } catch (BuildException $exc) {
+ throw new ExpatParseException("Error initializing nested element <$propType>", $exc, $this->parser->getLocation());
+ }
+ }
+
+ /**
+ * Handles character data.
+ *
+ * @param string the CDATA that comes in
+ * @throws ExpatParseException if the CDATA could not be set-up properly
+ * @access public
+ */
+ function characters($data) {
+
+ $configurator = $this->configurator;
+ $project = $this->configurator->project;
+
+ if ($this->parentWrapper === null) {
+ try {
+ $configurator->addText($project, $this->child, $data);
+ } catch (BuildException $exc) {
+ throw new ExpatParseException($exc->getMessage(), $this->parser->getLocation());
+ }
+ } else {
+ $this->childWrapper->addText($data);
+ }
+ }
+
+ /**
+ * Checks for nested tags within the current one. Creates and calls
+ * handlers respectively.
+ *
+ * @param string the tag that comes in
+ * @param array attributes the tag carries
+ * @access public
+ */
+ function startElement($name, $attrs) {
+ //print(get_class($this) . " name = $name, attrs = " . implode(",",$attrs) . "\n");
+ if ($this->child instanceof TaskContainer) {
+ // taskcontainer nested element can contain other tasks - no other
+ // nested elements possible
+ $tc = new TaskHandler($this->parser, $this, $this->configurator, $this->child, $this->childWrapper, $this->target);
+ $tc->init($name, $attrs);
+ } else {
+ $neh = new NestedElementHandler($this->parser, $this, $this->configurator, $this->child, $this->childWrapper, $this->target);
+ $neh->init($name, $attrs);
+ }
+ }
+}
diff --git a/buildscripts/phing/classes/phing/parser/ProjectConfigurator.php b/buildscripts/phing/classes/phing/parser/ProjectConfigurator.php
new file mode 100644
index 00000000..6b69e955
--- /dev/null
+++ b/buildscripts/phing/classes/phing/parser/ProjectConfigurator.php
@@ -0,0 +1,246 @@
+<?php
+/*
+ * $Id: ProjectConfigurator.php,v 1.17 2006/01/06 14:57:18 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/system/io/BufferedReader.php';
+include_once 'phing/system/io/FileReader.php';
+include_once 'phing/BuildException.php';
+include_once 'phing/system/lang/FileNotFoundException.php';
+include_once 'phing/system/io/PhingFile.php';
+
+/**
+ * The datatype handler class.
+ *
+ * This class handles the occurance of registered datatype tags like
+ * FileSet
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright © 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.17 $ $Date: 2006/01/06 14:57:18 $
+ * @access public
+ * @package phing.parser
+ */
+class ProjectConfigurator {
+
+ public $project;
+ public $locator;
+
+ public $buildFile;
+ public $buildFileParent;
+
+ /**
+ * Static call to ProjectConfigurator. Use this to configure a
+ * project. Do not use the new operator.
+ *
+ * @param object the Project instance this configurator should use
+ * @param object the buildfile object the parser should use
+ * @access public
+ */
+ public static function configureProject(Project $project, PhingFile $buildFile) {
+ $pc = new ProjectConfigurator($project, $buildFile);
+ $pc->parse();
+ }
+
+ /**
+ * Constructs a new ProjectConfigurator object
+ * This constructor is private. Use a static call to
+ * <code>configureProject</code> to configure a project.
+ *
+ * @param object the Project instance this configurator should use
+ * @param object the buildfile object the parser should use
+ * @access private
+ */
+ function __construct(Project $project, PhingFile $buildFile) {
+ $this->project = $project;
+ $this->buildFile = new PhingFile($buildFile->getAbsolutePath());
+ $this->buildFileParent = new PhingFile($this->buildFile->getParent());
+ }
+
+ /**
+ * Creates the ExpatParser, sets root handler and kick off parsing
+ * process.
+ *
+ * @throws BuildException if there is any kind of execption during
+ * the parsing process
+ * @access private
+ */
+ protected function parse() {
+ try {
+ $reader = new BufferedReader(new FileReader($this->buildFile));
+ $reader->open();
+ $parser = new ExpatParser($reader);
+ $parser->parserSetOption(XML_OPTION_CASE_FOLDING,0);
+ $parser->setHandler(new RootHandler($parser, $this));
+ $this->project->log("parsing buildfile ".$this->buildFile->getName(), PROJECT_MSG_VERBOSE);
+ $parser->parse();
+ $reader->close();
+ } catch (Exception $exc) {
+ throw new BuildException("Error reading project file", $exc);
+ }
+ }
+
+ /**
+ * Configures an element and resolves eventually given properties.
+ *
+ * @param object the element to configure
+ * @param array the element's attributes
+ * @param object the project this element belongs to
+ * @throws Exception if arguments are not valid
+ * @throws BuildException if attributes can not be configured
+ * @access public
+ */
+ function configure($target, $attrs, Project $project) {
+
+ if ($target instanceof TaskAdapter) {
+ $target = $target->getProxy();
+ }
+
+ // if the target is an UnknownElement, this means that the tag had not been registered
+ // when the enclosing element (task, target, etc.) was configured. It is possible, however,
+ // that the tag was registered (e.g. using <taskdef>) after the original configuration.
+ // ... so, try to load it again:
+ if ($target instanceof UnknownElement) {
+ $tryTarget = $project->createTask($target->getTaskType());
+ if ($tryTarget) {
+ $target = $tryTarget;
+ }
+ }
+
+ $bean = get_class($target);
+ $ih = IntrospectionHelper::getHelper($bean);
+
+ foreach ($attrs as $key => $value) {
+ if ($key == 'id') {
+ continue;
+ // throw new BuildException("Id must be set Extermnally");
+ }
+ $value = self::replaceProperties($project, $value, $project->getProperties());
+ try { // try to set the attribute
+ $ih->setAttribute($project, $target, strtolower($key), $value);
+ } catch (BuildException $be) {
+ // id attribute must be set externally
+ if ($key !== "id") {
+ throw $be;
+ }
+ }
+ }
+ }
+
+ /**
+ * Configures the #CDATA of an element.
+ *
+ * @param object the project this element belongs to
+ * @param object the element to configure
+ * @param string the element's #CDATA
+ * @access public
+ */
+ function addText($project, $target, $text = null) {
+ if ($text === null || strlen(trim($text)) === 0) {
+ return;
+ }
+ $ih = IntrospectionHelper::getHelper(get_class($target));
+ $text = self::replaceProperties($project, $text, $project->getProperties());
+ $ih->addText($project, $target, $text);
+ }
+
+ /**
+ * Stores a configured child element into its parent object
+ *
+ * @param object the project this element belongs to
+ * @param object the parent element
+ * @param object the child element
+ * @param string the XML tagname
+ * @access public
+ */
+ function storeChild($project, $parent, $child, $tag) {
+ $ih = IntrospectionHelper::getHelper(get_class($parent));
+ $ih->storeElement($project, $parent, $child, $tag);
+ }
+
+ // The following two properties are a sort of hack
+ // to enable a static function to serve as the callback
+ // for preg_replace_callback(). Clearly we cannot use object
+ // variables, since the replaceProperties() is called statically.
+ // This is IMO better than using global variables in the callback.
+
+ private static $propReplaceProject;
+ private static $propReplaceProperties;
+
+ /**
+ * Replace ${} style constructions in the given value with the
+ * string value of the corresponding data types. This method is
+ * static.
+ *
+ * @param object the project that should be used for property look-ups
+ * @param string the string to be scanned for property references
+ * @param array proeprty keys
+ * @return string the replaced string or <code>null</code> if the string
+ * itself was null
+ */
+ public static function replaceProperties(Project $project, $value, $keys) {
+
+ if ($value === null) {
+ return null;
+ }
+
+ // These are a "hack" to support static callback for preg_replace_callback()
+
+ // make sure these get initialized every time
+ self::$propReplaceProperties = $keys;
+ self::$propReplaceProject = $project;
+
+ // Because we're not doing anything special (like multiple passes),
+ // regex is the simplest / fastest. PropertyTask, though, uses
+ // the old parsePropertyString() method, since it has more stringent
+ // requirements.
+
+ $sb = preg_replace_callback('/\$\{([^}]+)\}/', array('ProjectConfigurator', 'replacePropertyCallback'), $value);
+ return $sb;
+ }
+
+ /**
+ * Private [static] function for use by preg_replace_callback to replace a single param.
+ * This method makes use of a static variable to hold the
+ */
+ private static function replacePropertyCallback($matches)
+ {
+ $propertyName = $matches[1];
+ if (!isset(self::$propReplaceProperties[$propertyName])) {
+ self::$propReplaceProject->log('Property ${'.$propertyName.'} has not been set.', PROJECT_MSG_VERBOSE);
+ return $matches[0];
+ } else {
+ self::$propReplaceProject->log('Property ${'.$propertyName.'} => ' . self::$propReplaceProperties[$propertyName], PROJECT_MSG_DEBUG);
+ }
+ return self::$propReplaceProperties[$propertyName];
+ }
+
+ /**
+ * Scan Attributes for the id attribute and maybe add a reference to
+ * project.
+ *
+ * @param object the element's object
+ * @param array the element's attributes
+ */
+ function configureId(&$target, $attr) {
+ if (isset($attr['id']) && $attr['id'] !== null) {
+ $this->project->addReference($attr['id'], $target);
+ }
+ }
+}
diff --git a/buildscripts/phing/classes/phing/parser/ProjectHandler.php b/buildscripts/phing/classes/phing/parser/ProjectHandler.php
new file mode 100644
index 00000000..54486ec9
--- /dev/null
+++ b/buildscripts/phing/classes/phing/parser/ProjectHandler.php
@@ -0,0 +1,146 @@
+<?php
+/*
+ * $Id: ProjectHandler.php,v 1.14 2005/10/04 19:13:44 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/parser/AbstractHandler.php';
+require_once 'phing/system/io/PhingFile.php';
+
+/**
+ * Handler class for the <project> XML element This class handles all elements
+ * under the <project> element.
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright (c) 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.14 $ $Date: 2005/10/04 19:13:44 $
+ * @access public
+ * @package phing.parser
+ */
+class ProjectHandler extends AbstractHandler {
+
+ /**
+ * The phing project configurator object.
+ * @var ProjectConfigurator
+ */
+ private $configurator;
+
+ /**
+ * Constructs a new ProjectHandler
+ *
+ * @param object the ExpatParser object
+ * @param object the parent handler that invoked this handler
+ * @param object the ProjectConfigurator object
+ * @access public
+ */
+ function __construct($parser, $parentHandler, $configurator) {
+ $this->configurator = $configurator;
+ parent::__construct($parser, $parentHandler);
+ }
+
+ /**
+ * Executes initialization actions required to setup the project. Usually
+ * this method handles the attributes of a tag.
+ *
+ * @param string the tag that comes in
+ * @param array attributes the tag carries
+ * @param object the ProjectConfigurator object
+ * @throws ExpatParseException if attributes are incomplete or invalid
+ * @access public
+ */
+ function init($tag, $attrs) {
+ $def = null;
+ $name = null;
+ $id = null;
+ $baseDir = null;
+
+ // some shorthands
+ $project = $this->configurator->project;
+ $buildFileParent = $this->configurator->buildFileParent;
+
+ foreach ($attrs as $key => $value) {
+ if ($key === "default") {
+ $def = $value;
+ } elseif ($key === "name") {
+ $name = $value;
+ } elseif ($key === "id") {
+ $id = $value;
+ } elseif ($key === "basedir") {
+ $baseDir = $value;
+ } else {
+ throw new ExpatParseException("Unexpected attribute '$key'");
+ }
+ }
+ if ($def === null) {
+ throw new ExpatParseException("The default attribute of project is required");
+ }
+ $project->setDefaultTarget($def);
+
+ if ($name !== null) {
+ $project->setName($name);
+ $project->addReference($name, $project);
+ }
+
+ if ($id !== null) {
+ $project->addReference($id, $project);
+ }
+
+ if ($project->getProperty("project.basedir") !== null) {
+ $project->setBasedir($project->getProperty("project.basedir"));
+ } else {
+ if ($baseDir === null) {
+ $project->setBasedir($buildFileParent->getAbsolutePath());
+ } else {
+ // check whether the user has specified an absolute path
+ $f = new PhingFile($baseDir);
+ if ($f->isAbsolute()) {
+ $project->setBasedir($baseDir);
+ } else {
+ $project->setBaseDir($project->resolveFile($baseDir, $buildFileParent));
+ }
+ }
+ }
+ }
+
+ /**
+ * Handles start elements within the <project> tag by creating and
+ * calling the required handlers for the detected element.
+ *
+ * @param string the tag that comes in
+ * @param array attributes the tag carries
+ * @throws ExpatParseException if a unxepected element occurs
+ * @access public
+ */
+ function startElement($name, $attrs) {
+
+ $project = $this->configurator->project;
+ $types = $project->getDataTypeDefinitions();
+
+ if ($name == "target") {
+ $tf = new TargetHandler($this->parser, $this, $this->configurator);
+ $tf->init($name, $attrs);
+ } elseif (isset($types[$name])) {
+ $tyf = new DataTypeHandler($this->parser, $this, $this->configurator);
+ $tyf->init($name, $attrs);
+ } else {
+ $tf = new TaskHandler($this->parser, $this, $this->configurator);
+ $tf->init($name, $attrs);
+ }
+ }
+}
+
diff --git a/buildscripts/phing/classes/phing/parser/RootHandler.php b/buildscripts/phing/classes/phing/parser/RootHandler.php
new file mode 100644
index 00000000..28afb5d5
--- /dev/null
+++ b/buildscripts/phing/classes/phing/parser/RootHandler.php
@@ -0,0 +1,82 @@
+<?php
+/*
+ * $Id: RootHandler.php,v 1.7 2003/12/24 13:02:09 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/parser/AbstractHandler.php';
+include_once 'phing/parser/ExpatParseException.php';
+include_once 'phing/parser/ProjectHandler.php';
+
+/**
+ * Root filter class for a phing buildfile.
+ *
+ * The root filter is called by the parser first. This is where the phing
+ * specific parsing starts. RootHandler decides what to do next.
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright © 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.7 $
+ * @package phing.parser
+ */
+class RootHandler extends AbstractHandler {
+
+ /**
+ * The phing project configurator object
+ */
+ private $configurator;
+
+ /**
+ * Constructs a new RootHandler
+ *
+ * The root filter is required so the parser knows what to do. It's
+ * called by the ExpatParser that is instatiated in ProjectConfigurator.
+ *
+ * It recieves the expat parse object ref and a reference to the
+ * configurator
+ *
+ * @param AbstractSAXParser $parser The ExpatParser object.
+ * @param ProjectConfigurator $configurator The ProjectConfigurator object.
+ */
+ function __construct(AbstractSAXParser $parser, ProjectConfigurator $configurator) {
+ $this->configurator = $configurator;
+ parent::__construct($parser, $this);
+ }
+
+ /**
+ * Kick off a custom action for a start element tag.
+ *
+ * The root element of our buildfile is the &lt;project&gt; element. The
+ * root filter handles this element if it occurs, creates ProjectHandler
+ * to handle any nested tags & attributes of the &lt;project&gt; tag,
+ * and calls init.
+ *
+ * @param string $tag The xml tagname
+ * @param array $attrs The attributes of the tag
+ * @throws ExpatParseException if the first element within our build file
+ * is not the &gt;project&lt; element
+ */
+ function startElement($tag, $attrs) {
+ if ($tag === "project") {
+ $ph = new ProjectHandler($this->parser, $this, $this->configurator);
+ $ph->init($tag, $attrs);
+ } else {
+ throw new ExpatParseException("Unexpected tag <$tag> in top-level of build file.", $this->parser->getLocation());
+ }
+ }
+}
diff --git a/buildscripts/phing/classes/phing/parser/TargetHandler.php b/buildscripts/phing/classes/phing/parser/TargetHandler.php
new file mode 100644
index 00000000..7ca94b44
--- /dev/null
+++ b/buildscripts/phing/classes/phing/parser/TargetHandler.php
@@ -0,0 +1,149 @@
+<?php
+/*
+ * $Id: TargetHandler.php,v 1.10 2005/10/04 19:13:44 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/parser/AbstractHandler.php';
+
+/**
+ * The target handler class.
+ *
+ * This class handles the occurance of a <target> tag and it's possible
+ * nested tags (datatypes and tasks).
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.10 $
+ * @package phing.parser
+ */
+class TargetHandler extends AbstractHandler {
+
+ /**
+ * Reference to the target object that represents the currently parsed
+ * target.
+ * @var object the target instance
+ */
+ private $target;
+
+ /**
+ * The phing project configurator object
+ * @var ProjectConfigurator
+ */
+ private $configurator;
+
+ /**
+ * Constructs a new TargetHandler
+ *
+ * @param object the ExpatParser object
+ * @param object the parent handler that invoked this handler
+ * @param object the ProjectConfigurator object
+ */
+ function __construct(AbstractSAXParser $parser, AbstractHandler $parentHandler, ProjectConfigurator $configurator) {
+ parent::__construct($parser, $parentHandler);
+ $this->configurator = $configurator;
+ }
+
+ /**
+ * Executes initialization actions required to setup the data structures
+ * related to the tag.
+ * <p>
+ * This includes:
+ * <ul>
+ * <li>creation of the target object</li>
+ * <li>calling the setters for attributes</li>
+ * <li>adding the target to the project</li>
+ * <li>adding a reference to the target (if id attribute is given)</li>
+ * </ul>
+ *
+ * @param string the tag that comes in
+ * @param array attributes the tag carries
+ * @throws ExpatParseException if attributes are incomplete or invalid
+ */
+ function init($tag, $attrs) {
+ $name = null;
+ $depends = "";
+ $ifCond = null;
+ $unlessCond = null;
+ $id = null;
+ $description = null;
+
+ foreach($attrs as $key => $value) {
+ if ($key==="name") {
+ $name = (string) $value;
+ } else if ($key==="depends") {
+ $depends = (string) $value;
+ } else if ($key==="if") {
+ $ifCond = (string) $value;
+ } else if ($key==="unless") {
+ $unlessCond = (string) $value;
+ } else if ($key==="id") {
+ $id = (string) $value;
+ } else if ($key==="description") {
+ $description = (string)$value;
+ } else {
+ throw new ExpatParseException("Unexpected attribute '$key'", $this->parser->getLocation());
+ }
+ }
+
+ if ($name === null) {
+ throw new ExpatParseException("target element appears without a name attribute", $this->parser->getLocation());
+ }
+
+ // shorthand
+ $project = $this->configurator->project;
+
+ $this->target = new Target();
+ $this->target->setName($name);
+ $this->target->setIf($ifCond);
+ $this->target->setUnless($unlessCond);
+ $this->target->setDescription($description);
+
+ $project->addTarget($name, $this->target);
+
+ if ($id !== null && $id !== "") {
+ $project->addReference($id, $this->target);
+ }
+ // take care of dependencies
+ if (strlen($depends) > 0) {
+ $this->target->setDepends($depends);
+ }
+
+ }
+
+ /**
+ * Checks for nested tags within the current one. Creates and calls
+ * handlers respectively.
+ *
+ * @param string the tag that comes in
+ * @param array attributes the tag carries
+ */
+ function startElement($name, $attrs) {
+ // shorthands
+ $project = $this->configurator->project;
+ $types = $project->getDataTypeDefinitions();
+
+ if (isset($types[$name])) {
+ $th = new DataTypeHandler($this->parser, $this, $this->configurator, $this->target);
+ $th->init($name, $attrs);
+ } else {
+ $tmp = new TaskHandler($this->parser, $this, $this->configurator, $this->target, null, $this->target);
+ $tmp->init($name, $attrs);
+ }
+ }
+}
diff --git a/buildscripts/phing/classes/phing/parser/TaskHandler.php b/buildscripts/phing/classes/phing/parser/TaskHandler.php
new file mode 100644
index 00000000..976aebf2
--- /dev/null
+++ b/buildscripts/phing/classes/phing/parser/TaskHandler.php
@@ -0,0 +1,229 @@
+<?php
+/*
+ * $Id: TaskHandler.php,v 1.10 2005/10/04 19:13:44 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/UnknownElement.php';
+
+/**
+ * The task handler class.
+ *
+ * This class handles the occurance of a <task> tag and it's possible
+ * nested tags (datatypes and tasks) that may be unknown off bat and are
+ * initialized on the fly.
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright © 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.10 $
+ * @package phing.parser
+ */
+class TaskHandler extends AbstractHandler {
+
+ /**
+ * Reference to the target object that contains the currently parsed
+ * task
+ * @var object the target instance
+ */
+ private $target;
+
+ /**
+ * Reference to the target object that represents the currently parsed
+ * target. This must not necessarily be a target, hence extra variable.
+ * @var object the target instance
+ */
+ private $container;
+
+ /**
+ * Reference to the task object that represents the currently parsed
+ * target.
+ * @var Task
+ */
+ private $task;
+
+ /**
+ * Wrapper for the parent element, if any. The wrapper for this
+ * element will be added to this wrapper as a child.
+ * @var RuntimeConfigurable
+ */
+ private $parentWrapper;
+
+ /**
+ * Wrapper for this element which takes care of actually configuring
+ * the element, if this element is contained within a target.
+ * Otherwise the configuration is performed with the configure method.
+ * @see ProjectHelper::configure(Object,AttributeList,Project)
+ */
+ private $wrapper;
+
+ /**
+ * The phing project configurator object
+ * @var ProjectConfigurator
+ */
+ private $configurator;
+
+ /**
+ * Constructs a new TaskHandler and sets up everything.
+ *
+ * @param AbstractSAXParser The ExpatParser object
+ * @param object $parentHandler The parent handler that invoked this handler
+ * @param ProjectConfigurator $configurator
+ * @param TaskContainer $container The container object this task is contained in (null for top-level tasks).
+ * @param RuntimeConfigurable $parentWrapper Wrapper for the parent element, if any.
+ * @param Target $target The target object this task is contained in (null for top-level tasks).
+ */
+ function __construct(AbstractSAXParser $parser, $parentHandler, ProjectConfigurator $configurator, $container = null, $parentWrapper = null, $target = null) {
+
+ parent::__construct($parser, $parentHandler);
+
+ if (($container !== null) && !($container instanceof TaskContainer)) {
+ throw new Exception("Argument expected to be a TaskContainer, got something else");
+ }
+ if (($parentWrapper !== null) && !($parentWrapper instanceof RuntimeConfigurable)) {
+ throw new Exception("Argument expected to be a RuntimeConfigurable, got something else.");
+ }
+ if (($target !== null) && !($target instanceof Target)) {
+ throw new Exception("Argument expected to be a Target, got something else");
+ }
+
+ $this->configurator = $configurator;
+ $this->container = $container;
+ $this->parentWrapper = $parentWrapper;
+ $this->target = $target;
+ }
+
+ /**
+ * Executes initialization actions required to setup the data structures
+ * related to the tag.
+ * <p>
+ * This includes:
+ * <ul>
+ * <li>creation of the task object</li>
+ * <li>calling the setters for attributes</li>
+ * <li>adding the task to the container object</li>
+ * <li>adding a reference to the task (if id attribute is given)</li>
+ * <li>executing the task if the container is the &lt;project&gt;
+ * element</li>
+ * </ul>
+ *
+ * @param string $tag The tag that comes in
+ * @param array $attrs Attributes the tag carries
+ * @throws ExpatParseException if attributes are incomplete or invalid
+ */
+ function init($tag, $attrs) {
+ // shorthands
+ try {
+ $configurator = $this->configurator;
+ $project = $this->configurator->project;
+
+ $this->task = $project->createTask($tag);
+ } catch (BuildException $be) {
+ // swallow here, will be thrown again in
+ // UnknownElement->maybeConfigure if the problem persists.
+ print("Swallowing exception: ".$be->getMessage() . "\n");
+ }
+
+ // the task is not known of bat, try to load it on thy fly
+ if ($this->task === null) {
+ $this->task = new UnknownElement($tag);
+ $this->task->setProject($project);
+ $this->task->setTaskType($tag);
+ $this->task->setTaskName($tag);
+ }
+
+ // add file position information to the task (from parser)
+ // should be used in task exceptions to provide details
+ $this->task->setLocation($this->parser->getLocation());
+ $configurator->configureId($task, $attrs);
+
+ if ($this->container) {
+ $this->container->addTask($this->task);
+ }
+
+ // Top level tasks don't have associated targets
+ // FIXME: if we do like Ant 1.6 and create an implicitTarget in the projectconfigurator object
+ // then we don't need to check for null here ... but there's a lot of stuff that will break if we
+ // do that at this point.
+ if ($this->target !== null) {
+ $this->task->setOwningTarget($this->target);
+ $this->task->init();
+ $this->wrapper = $this->task->getRuntimeConfigurableWrapper();
+ $this->wrapper->setAttributes($attrs);
+ if ($this->parentWrapper !== null) { // this may not make sense only within this if-block, but it
+ // seems to address current use cases adequately
+ $this->parentWrapper->addChild($this->wrapper);
+ }
+ } else {
+ $this->task->init();
+ $configurator->configure($this->task, $attrs, $project);
+ }
+ }
+
+ /**
+ * Executes the task at once if it's directly beneath the <project> tag.
+ */
+ protected function finished() {
+ if ($this->task !== null && $this->target === null) {
+ try {
+ $this->task->main();
+ } catch (Exception $e) {
+ $this->task->log($e->getMessage(), PROJECT_MSG_ERR);
+ throw $e;
+ }
+ }
+ }
+
+ /**
+ * Handles character data.
+ *
+ * @param string $data The CDATA that comes in
+ */
+ function characters($data) {
+ if ($this->wrapper === null) {
+ $configurator = $this->configurator;
+ $project = $this->configurator->project;
+ try { // try
+ $configurator->addText($project, $this->task, $data);
+ } catch (BuildException $exc) {
+ throw new ExpatParseException($exc->getMessage(), $this->parser->getLocation());
+ }
+ } else {
+ $this->wrapper->addText($data);
+ }
+ }
+
+ /**
+ * Checks for nested tags within the current one. Creates and calls
+ * handlers respectively.
+ *
+ * @param string $name The tag that comes in
+ * @param array $attrs Attributes the tag carries
+ */
+ function startElement($name, $attrs) {
+ $project = $this->configurator->project;
+ if ($this->task instanceof TaskContainer) {
+ //print("TaskHandler::startElement() (TaskContainer) name = $name, attrs = " . implode(",",$attrs) . "\n");
+ $th = new TaskHandler($this->parser, $this, $this->configurator, $this->task, $this->wrapper, $this->target);
+ $th->init($name, $attrs);
+ } else {
+ //print("TaskHandler::startElement() name = $name, attrs = " . implode(",",$attrs) . "\n");
+ $tmp = new NestedElementHandler($this->parser, $this, $this->configurator, $this->task, $this->wrapper, $this->target);
+ $tmp->init($name, $attrs);
+ }
+ }
+}
diff --git a/buildscripts/phing/classes/phing/system/io/BufferedReader.php b/buildscripts/phing/classes/phing/system/io/BufferedReader.php
new file mode 100644
index 00000000..4946985c
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/io/BufferedReader.php
@@ -0,0 +1,170 @@
+<?php
+/*
+ * $Id: BufferedReader.php,v 1.6 2005/12/27 19:12:13 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+include_once 'phing/system/io/Reader.php';
+
+/*
+ * Convenience class for reading files.
+ *
+ * @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
+ * @version $Revision: 1.6 $ $Date: 2005/12/27 19:12:13 $
+ * @access public
+ * @see FilterReader
+ * @package phing.system.io
+*/
+class BufferedReader extends Reader {
+
+ private $bufferSize = 0;
+ private $buffer = null;
+ private $bufferPos = 0;
+
+ /**
+ * The Reader we are buffering for.
+ */
+ private $in;
+
+ /**
+ *
+ * @param object $reader The reader (e.g. FileReader).
+ * @param integer $buffsize The size of the buffer we should use for reading files.
+ * A large buffer ensures that most files (all scripts?) are parsed in 1 buffer.
+ */
+ function __construct(Reader $reader, $buffsize = 65536) {
+ $this->in = $reader;
+ $this->bufferSize = $buffsize;
+ }
+
+ /**
+ * Reads and returns $_bufferSize chunk of data.
+ * @return mixed buffer or -1 if EOF.
+ */
+ function read($len = null) {
+ // ignore $len param, not sure how to hanlde it, since
+ // this should only read bufferSize amount of data.
+ if ($len !== null) {
+ $this->currentPosition = ftell($this->fd);
+ }
+
+ if ( ($data = $this->in->read($this->bufferSize)) !== -1 ) {
+
+ // not all files end with a newline character, so we also need to check EOF
+ if (!$this->in->eof()) {
+
+ $notValidPart = strrchr($data, "\n");
+ $notValidPartSize = strlen($notValidPart);
+
+ if ( $notValidPartSize > 1 ) {
+ // Block doesn't finish on a EOL
+ // Find the last EOL and forgot all following stuff
+ $dataSize = strlen($data);
+ $validSize = $dataSize - $notValidPartSize + 1;
+
+ $data = substr($data, 0, $validSize);
+
+ // Rewind to the begining of the forgotten stuff.
+ $this->in->skip(-$notValidPartSize+1);
+ }
+
+ } // if !EOF
+ }
+ return $data;
+ }
+
+ function skip($n) {
+ return $this->in->skip($n);
+ }
+
+ function reset() {
+ return $this->in->reset();
+ }
+
+ function close() {
+ return $this->in->close();
+ }
+
+ function open() {
+ return $this->in->open();
+ }
+
+ /**
+ * Read a line from input stream.
+ */
+ function readLine() {
+ $line = null;
+ while ( ($ch = $this->readChar()) !== -1 ) {
+ if ( $ch === "\n" ) {
+ break;
+ }
+ $line .= $ch;
+ }
+
+ // Warning : Not considering an empty line as an EOF
+ if ( $line === null && $ch !== -1 )
+ return "";
+
+ return $line;
+ }
+
+ /**
+ * Reads a single char from the reader.
+ * @return string single char or -1 if EOF.
+ */
+ function readChar() {
+
+ if ( $this->buffer === null ) {
+ // Buffer is empty, fill it ...
+ $read = $this->in->read($this->bufferSize);
+ if ($read === -1) {
+ $ch = -1;
+ } else {
+ $this->buffer = $read;
+ return $this->readChar(); // recurse
+ }
+ } else {
+ // Get next buffered char ...
+ // handle case where buffer is read-in, but is empty. The next readChar() will return -1 EOF,
+ // so we just return empty string (char) at this point. (Probably could also return -1 ...?)
+ $ch = ($this->buffer !== "") ? $this->buffer{$this->bufferPos} : '';
+ $this->bufferPos++;
+ if ( $this->bufferPos >= strlen($this->buffer) ) {
+ $this->buffer = null;
+ $this->bufferPos = 0;
+ }
+ }
+
+ return $ch;
+ }
+
+ /**
+ * Returns whether eof has been reached in stream.
+ * This is important, because filters may want to know if the end of the file (and not just buffer)
+ * has been reached.
+ * @return boolean
+ */
+ function eof() {
+ return $this->in->eof();
+ }
+
+ function getResource() {
+ return $this->in->getResource();
+ }
+}
+?>
diff --git a/buildscripts/phing/classes/phing/system/io/BufferedWriter.php b/buildscripts/phing/classes/phing/system/io/BufferedWriter.php
new file mode 100644
index 00000000..c982db28
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/io/BufferedWriter.php
@@ -0,0 +1,72 @@
+<?php
+/*
+ * $Id: BufferedWriter.php,v 1.10 2005/05/26 13:10:52 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/system/io/Writer.php';
+
+/**
+ * Convenience class for writing files.
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.10 $
+ * @package phing.system.io
+ */
+class BufferedWriter extends Writer {
+
+ /**
+ * The size of the buffer in kb.
+ */
+ private $bufferSize = 0;
+
+ /**
+ * The Writer we are buffering output to.
+ */
+ private $out;
+
+ function __construct(Writer $writer, $buffsize = 8192) {
+ $this->out = $writer;
+ $this->bufferSize = $buffsize;
+ }
+
+ function write($buf, $off = null, $len = null) {
+ return $this->out->write($buf, $off, $len);
+ }
+
+ function newLine() {
+ $this->write(Phing::getProperty('line.separator'));
+ }
+
+ function getResource() {
+ return $this->out->getResource();
+ }
+
+ function reset() {
+ return $this->out->reset();
+ }
+
+ function close() {
+ return $this->out->close();
+ }
+
+ function open() {
+ return $this->out->open();
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/system/io/ConsoleReader.php b/buildscripts/phing/classes/phing/system/io/ConsoleReader.php
new file mode 100644
index 00000000..33b37619
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/io/ConsoleReader.php
@@ -0,0 +1,84 @@
+<?php
+/*
+ * $Id: ConsoleReader.php,v 1.4 2004/08/12 16:26:12 matthewh Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/system/io/Reader.php';
+
+/**
+ * Convenience class for reading console input.
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @author Matthew Hershberger <matthewh@lightsp.com>
+ * @version $Revision: 1.4 $
+ * @package phing.system.io
+ */
+class ConsoleReader extends Reader {
+
+ function readLine() {
+
+ $out = fgets(STDIN); // note: default maxlen is 1kb
+ $out = rtrim($out);
+
+ return $out;
+ }
+
+ /**
+ *
+ * @param int $len Num chars to read.
+ * @return string chars read or -1 if eof.
+ */
+ function read($len = null) {
+
+ $out = fread(STDIN, $len);
+
+
+ return $out;
+ // FIXME
+ // read by chars doesn't work (yet?) with PHP stdin. Maybe
+ // this is just a language feature, maybe there's a way to get
+ // ability to read chars w/o <enter> ?
+
+ }
+
+ function close() {
+ // STDIN is always open
+ }
+
+ function open() {
+ // STDIN is always open
+ }
+
+ /**
+ * Whether eof has been reached with stream.
+ * @return boolean
+ */
+ function eof() {
+ return feof(STDIN);
+ }
+
+ /**
+ * Returns path to file we are reading.
+ * @return string
+ */
+ function getResource() {
+ return "console";
+ }
+}
+?>
diff --git a/buildscripts/phing/classes/phing/system/io/FileReader.php b/buildscripts/phing/classes/phing/system/io/FileReader.php
new file mode 100644
index 00000000..cbea2c7e
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/io/FileReader.php
@@ -0,0 +1,179 @@
+<?php
+/*
+ * $Id: FileReader.php,v 1.9 2005/05/26 13:10:52 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/system/io/PhingFile.php';
+include_once 'phing/system/io/Reader.php';
+
+/**
+ * Convenience class for reading files. The constructor of this
+ * @package phing.system.io
+ */
+
+class FileReader extends Reader {
+
+ protected $file;
+ protected $fd;
+
+ protected $currentPosition = 0;
+ protected $mark = 0;
+
+ function __construct($file, $exclusive = false) {
+
+ if ($file instanceof PhingFile) {
+ $this->file = $file;
+ } elseif (is_string($file)) {
+ $this->file = new PhingFile($file);
+ } else {
+ throw new Exception("Illegal argument type to " . __METHOD__);
+ }
+ }
+
+ function skip($n) {
+ $this->open();
+
+ $start = $this->currentPosition;
+
+ $ret = @fseek($this->fd, $n, SEEK_CUR);
+ if ( $ret === -1 )
+ return -1;
+
+ $this->currentPosition = ftell($this->fd);
+
+ if ( $start > $this->currentPosition )
+ $skipped = $start - $this->currentPosition;
+ else
+ $skipped = $this->currentPosition - $start;
+
+ return $skipped;
+ }
+
+ /**
+ * Read data from file.
+ * @param int $len Num chars to read.
+ * @return string chars read or -1 if eof.
+ */
+ function read($len = null) {
+ $this->open();
+ if (feof($this->fd)) {
+ return -1;
+ }
+
+ // Compute length to read
+ // possible that filesize($this->file) will be larger than
+ // available bytes to read, but that's fine -- better to err on high end
+ $length = ($len === null) ? filesize($this->file->getAbsolutePath()) : $len;
+
+ // Read data
+ $out = fread($this->fd, $length + 1); // adding 1 seems to ensure that next call to read() will return EOF (-1)
+ $this->currentPosition = ftell($this->fd);
+
+ return $out;
+ }
+
+ function mark($n = null) {
+ $this->mark = $this->currentPosition;
+ }
+
+ function reset() {
+ // goes back to last mark, by default this would be 0 (i.e. rewind file).
+ fseek($this->fd, SEEK_SET, $this->mark);
+ $this->mark = 0;
+ }
+
+ function close() {
+ if ($this->fd === null) {
+ return true;
+ }
+
+ if (false === @fclose($this->fd)) {
+ // FAILED.
+ $msg = "Cannot fclose " . $this->file->__toString() . " $php_errormsg";
+ throw new IOException($msg);
+ } else {
+ $this->fd = null;
+ return true;
+ }
+ }
+
+ function open() {
+ global $php_errormsg;
+
+ if ($this->fd === null) {
+ $this->fd = @fopen($this->file->getAbsolutePath(), "rb");
+ }
+
+ if ($this->fd === false) {
+ // fopen FAILED.
+ // Add error from php to end of log message. $php_errormsg.
+ $msg = "Cannot fopen ".$this->file->getAbsolutePath().". $php_errormsg";
+ throw new IOException($msg);
+ }
+
+ if (false) {
+ // Locks don't seem to work on windows??? HELP!!!!!!!!!
+ // if (FALSE === @flock($fp, LOCK_EX)) { // FAILED.
+ $msg = "Cannot acquire flock on $file. $php_errormsg";
+ throw new IOException($msg);
+ }
+
+ return true;
+ }
+
+ /**
+ * Whether eof has been reached with stream.
+ * @return boolean
+ */
+ function eof() {
+ return feof($this->fd);
+ }
+
+ /**
+ * Reads a entire file and stores the data in the variable
+ * passed by reference.
+ *
+ * @param string $file String. Path and/or name of file to read.
+ * @param object &$rBuffer Reference. Variable of where to put contents.
+ *
+ * @return TRUE on success. Err object on failure.
+ * @author Charlie Killian, charlie@tizac.com
+ */
+ function readInto(&$rBuffer) {
+
+ $this->open();
+
+ $fileSize = $this->file->length();
+ if ($fileSize === false) {
+ $msg = "Cannot get filesize of " . $this->file->__toString() . " $php_errormsg";
+ throw new IOException($msg);
+ }
+ $rBuffer = fread($this->fd, $fileSize);
+ $this->close();
+ }
+
+ /**
+ * Returns path to file we are reading.
+ * @return string
+ */
+ function getResource() {
+ return $this->file->toString();
+ }
+}
+?>
diff --git a/buildscripts/phing/classes/phing/system/io/FileSystem.php b/buildscripts/phing/classes/phing/system/io/FileSystem.php
new file mode 100644
index 00000000..2802ddfb
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/io/FileSystem.php
@@ -0,0 +1,657 @@
+<?php
+
+/*
+ * $Id: FileSystem.php,v 1.11 2005/12/01 20:56:59 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * This is an abstract class for platform specific filesystem implementations
+ * you have to implement each method in the platform specific filesystem implementation
+ * classes Your local filesytem implementation must extend this class.
+ * You should also use this class as a template to write your local implementation
+ * Some native PHP filesystem specific methods are abstracted here as well. Anyway
+ * you _must_ always use this methods via a PhingFile object (that by nature uses the
+ * *FileSystem drivers to access the real filesystem via this class using natives.
+ *
+ * FIXME:
+ * - Error handling reduced to min fallthrough runtime excetions
+ * more precise errorhandling is done by the PhingFile class
+ *
+ * @author Charlie Killian <charlie@tizac.com>
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.11 $
+ * @package phing.system.io
+ */
+abstract class FileSystem {
+
+ /* properties for simple boolean attributes */
+ const BA_EXISTS = 0x01;
+ const BA_REGULAR = 0x02;
+ const BA_DIRECTORY = 0x04;
+ const BA_HIDDEN = 0x08;
+
+ /** Instance for getFileSystem() method. */
+ private static $fs;
+
+ /**
+ * Static method to return the FileSystem singelton representing
+ * this platform's local filesystem driver.
+ */
+ function getFileSystem() {
+ if (self::$fs === null) {
+ switch(Phing::getProperty('host.fstype')) {
+ case 'UNIX':
+ include_once 'phing/system/io/UnixFileSystem.php';
+ self::$fs = new UnixFileSystem();
+ break;
+ case 'WIN32':
+ include_once 'phing/system/io/Win32FileSystem.php';
+ self::$fs = new Win32FileSystem();
+ break;
+ case 'WINNT':
+ include_once 'phing/system/io/WinNTFileSystem.php';
+ self::$fs = new WinNTFileSystem();
+ break;
+ default:
+ throw new Exception("Host uses unsupported filesystem, unable to proceed");
+ }
+ }
+ return self::$fs;
+ }
+
+ /* -- Normalization and construction -- */
+
+ /**
+ * Return the local filesystem's name-separator character.
+ */
+ abstract function getSeparator();
+
+ /**
+ * Return the local filesystem's path-separator character.
+ */
+ abstract function getPathSeparator();
+
+ /**
+ * Convert the given pathname string to normal form. If the string is
+ * already in normal form then it is simply returned.
+ */
+ abstract function normalize($strPath);
+
+ /**
+ * Compute the length of this pathname string's prefix. The pathname
+ * string must be in normal form.
+ */
+ abstract function prefixLength($pathname);
+
+ /**
+ * Resolve the child pathname string against the parent.
+ * Both strings must be in normal form, and the result
+ * will be a string in normal form.
+ */
+ abstract function resolve($parent, $child);
+
+ /**
+ * Resolve the given abstract pathname into absolute form. Invoked by the
+ * getAbsolutePath and getCanonicalPath methods in the PhingFile class.
+ */
+ abstract function resolveFile(PhingFile $f);
+
+ /**
+ * Return the parent pathname string to be used when the parent-directory
+ * argument in one of the two-argument PhingFile constructors is the empty
+ * pathname.
+ */
+ abstract function getDefaultParent();
+
+ /**
+ * Post-process the given URI path string if necessary. This is used on
+ * win32, e.g., to transform "/c:/foo" into "c:/foo". The path string
+ * still has slash separators; code in the PhingFile class will translate them
+ * after this method returns.
+ */
+ abstract function fromURIPath($path);
+
+ /* -- Path operations -- */
+
+ /**
+ * Tell whether or not the given abstract pathname is absolute.
+ */
+ abstract function isAbsolute(PhingFile $f);
+
+ /**
+ * canonicalize filename by checking on disk
+ * @return mixed Canonical path or false if the file doesn't exist.
+ */
+ function canonicalize($strPath) {
+ return @realpath($strPath);
+ }
+
+ /* -- Attribute accessors -- */
+
+ /**
+ * Return the simple boolean attributes for the file or directory denoted
+ * by the given abstract pathname, or zero if it does not exist or some
+ * other I/O error occurs.
+ */
+ function getBooleanAttributes($f) {
+ throw new Exception("SYSTEM ERROR method getBooleanAttributes() not implemented by fs driver");
+ }
+
+ /**
+ * Check whether the file or directory denoted by the given abstract
+ * pathname may be accessed by this process. If the second argument is
+ * false, then a check for read access is made; if the second
+ * argument is true, then a check for write (not read-write)
+ * access is made. Return false if access is denied or an I/O error
+ * occurs.
+ */
+ function checkAccess(PhingFile $f, $write = false) {
+ // we clear stat cache, its expensive to look up from scratch,
+ // but we need to be sure
+ @clearstatcache();
+
+
+ // Shouldn't this be $f->GetAbsolutePath() ?
+ // And why doesn't GetAbsolutePath() work?
+
+ $strPath = (string) $f->getPath();
+
+ // FIXME
+ // if file object does denote a file that yet not existst
+ // path rights are checked
+ if (!@file_exists($strPath) && !is_dir($strPath)) {
+ $strPath = $f->getParent();
+ if ($strPath === null || !is_dir($strPath)) {
+ $strPath = Phing::getProperty("user.dir");
+ }
+ //$strPath = dirname($strPath);
+ }
+
+ if (!$write) {
+ return (boolean) @is_readable($strPath);
+ } else {
+ return (boolean) @is_writable($strPath);
+ }
+ }
+
+ /**
+ * Return the time at which the file or directory denoted by the given
+ * abstract pathname was last modified, or zero if it does not exist or
+ * some other I/O error occurs.
+ */
+ function getLastModifiedTime(PhingFile $f) {
+
+ if (!$f->exists()) {
+ return 0;
+ }
+
+ @clearstatcache();
+ $strPath = (string) $f->getPath();
+ $mtime = @filemtime($strPath);
+ if (false === $mtime) {
+ // FAILED. Log and return err.
+ $msg = "FileSystem::Filemtime() FAILED. Cannot can not get modified time of $strPath. $php_errormsg";
+ throw new Exception($msg);
+ } else {
+ return (int) $mtime;
+ }
+ }
+
+ /**
+ * Return the length in bytes of the file denoted by the given abstract
+ * pathname, or zero if it does not exist, is a directory, or some other
+ * I/O error occurs.
+ */
+ function getLength(PhingFile $f) {
+ $strPath = (string) $f->getAbsolutePath();
+ $fs = filesize((string) $strPath);
+ if ($fs !== false) {
+ return $fs;
+ } else {
+ $msg = "FileSystem::Read() FAILED. Cannot get filesize of $strPath. $php_errormsg";
+ throw new Exception($msg);
+ }
+ }
+
+ /* -- File operations -- */
+
+ /**
+ * Create a new empty file with the given pathname. Return
+ * true if the file was created and false if a
+ * file or directory with the given pathname already exists. Throw an
+ * IOException if an I/O error occurs.
+ *
+ * @param string Path of the file to be created.
+ *
+ * @throws IOException
+ */
+ function createNewFile($strPathname) {
+ if (@file_exists($strPathname))
+ return false;
+
+ // Create new file
+ $fp = @fopen($strPathname, "w");
+ if ($fp === false) {
+ throw new IOException("The file \"$strPathname\" could not be created");
+ }
+ @fclose($fp);
+ return true;
+ }
+
+ /**
+ * Delete the file or directory denoted by the given abstract pathname,
+ * returning true if and only if the operation succeeds.
+ */
+ function delete(PhingFile $f) {
+ if ($f->isDirectory()) {
+ return $this->rmdir($f->getPath());
+ } else {
+ return $this->unlink($f->getPath());
+ }
+ }
+
+ /**
+ * Arrange for the file or directory denoted by the given abstract
+ * pathname to be deleted when Phing::shutdown is called, returning
+ * true if and only if the operation succeeds.
+ */
+ function deleteOnExit($f) {
+ throw new Exception("deleteOnExit() not implemented by local fs driver");
+ }
+
+ /**
+ * List the elements of the directory denoted by the given abstract
+ * pathname. Return an array of strings naming the elements of the
+ * directory if successful; otherwise, return <code>null</code>.
+ */
+ function listDir(PhingFile $f) {
+ $strPath = (string) $f->getAbsolutePath();
+ $d = @dir($strPath);
+ if (!$d) {
+ return null;
+ }
+ $list = array();
+ while($entry = $d->read()) {
+ if ($entry != "." && $entry != "..") {
+ array_push($list, $entry);
+ }
+ }
+ $d->close();
+ unset($d);
+ return $list;
+ }
+
+ /**
+ * Create a new directory denoted by the given abstract pathname,
+ * returning true if and only if the operation succeeds.
+ */
+ function createDirectory(&$f) {
+ return @mkdir($f->getAbsolutePath(),0755);
+ }
+
+ /**
+ * Rename the file or directory denoted by the first abstract pathname to
+ * the second abstract pathname, returning true if and only if
+ * the operation succeeds.
+ *
+ * @param PhingFile $f1 abstract source file
+ * @param PhingFile $f2 abstract destination file
+ * @return void
+ * @throws Exception if rename cannot be performed
+ */
+ function rename(PhingFile $f1, PhingFile $f2) {
+ // get the canonical paths of the file to rename
+ $src = $f1->getAbsolutePath();
+ $dest = $f2->getAbsolutePath();
+ if (false === @rename($src, $dest)) {
+ $msg = "Rename FAILED. Cannot rename $src to $dest. $php_errormsg";
+ throw new Exception($msg);
+ }
+ }
+
+ /**
+ * Set the last-modified time of the file or directory denoted by the
+ * given abstract pathname returning true if and only if the
+ * operation succeeds.
+ * @return void
+ * @throws Exception
+ */
+ function setLastModifiedTime(PhingFile $f, $time) {
+ $path = $f->getPath();
+ $success = @touch($path, $time);
+ if (!$success) {
+ throw new Exception("Could not create directory due to: $php_errormsg");
+ }
+ }
+
+ /**
+ * Mark the file or directory denoted by the given abstract pathname as
+ * read-only, returning <code>true</code> if and only if the operation
+ * succeeds.
+ */
+ function setReadOnly($f) {
+ throw new Exception("setReadonle() not implemented by local fs driver");
+ }
+
+ /* -- Filesystem interface -- */
+
+ /**
+ * List the available filesystem roots, return array of PhingFile objects
+ */
+ function listRoots() {
+ throw new Exception("SYSTEM ERROR [listRoots() not implemented by local fs driver]");
+ }
+
+ /* -- Basic infrastructure -- */
+
+ /**
+ * Compare two abstract pathnames lexicographically.
+ */
+ function compare($f1, $f2) {
+ throw new Exception("SYSTEM ERROR [compare() not implemented by local fs driver]");
+ }
+
+ /**
+ * Copy a file.
+ *
+ * @param PhingFile $src Source path and name file to copy.
+ * @param PhingFile $dest Destination path and name of new file.
+ *
+ * @return void
+ * @throws Exception if file cannot be copied.
+ */
+ function copy(PhingFile $src, PhingFile $dest) {
+ global $php_errormsg;
+ $srcPath = $src->getAbsolutePath();
+ $destPath = $dest->getAbsolutePath();
+
+ if (false === @copy($srcPath, $destPath)) { // Copy FAILED. Log and return err.
+ // Add error from php to end of log message. $php_errormsg.
+ $msg = "FileSystem::copy() FAILED. Cannot copy $srcPath to $destPath. $php_errormsg";
+ throw new Exception($msg);
+ }
+
+ try {
+ $dest->setMode($src->getMode());
+ } catch(Exception $exc) {
+ // [MA] does chmod returns an error on systems that do not support it ?
+ // eat it up for now.
+ }
+ }
+
+ /**
+ * Change the permissions on a file or directory.
+ *
+ * @param pathname String. Path and name of file or directory.
+ * @param mode Int. The mode (permissions) of the file or
+ * directory. If using octal add leading 0. eg. 0777.
+ * Mode is affected by the umask system setting.
+ *
+ * @return void
+ * @throws Exception if operation failed.
+ */
+ function chmod($pathname, $mode) {
+ $str_mode = decoct($mode); // Show octal in messages.
+ if (false === @chmod($pathname, $mode)) {// FAILED.
+ $msg = "FileSystem::chmod() FAILED. Cannot chmod $pathname. Mode $str_mode. $php_errormsg";
+ throw new Exception($msg);
+ }
+ }
+
+ /**
+ * Locks a file and throws an Exception if this is not possible.
+ * @return void
+ * @throws Exception
+ */
+ function lock(PhingFile $f) {
+ $filename = $f->getPath();
+ $fp = @fopen($filename, "w");
+ $result = @flock($fp, LOCK_EX);
+ @fclose($fp);
+ if (!$result) {
+ throw new Exception("Could not lock file '$filename'");
+ }
+ }
+
+ /**
+ * Unlocks a file and throws an IO Error if this is not possible.
+ *
+ * @throws Exception
+ * @return void
+ */
+ function unlock(PhingFile $f) {
+ $filename = $f->getPath();
+ $fp = @fopen($filename, "w");
+ $result = @flock($fp, LOCK_UN);
+ fclose($fp);
+ if (!$result) {
+ throw new Exception("Could not unlock file '$filename'");
+ }
+ }
+
+ /**
+ * Delete a file.
+ *
+ * @param file String. Path and/or name of file to delete.
+ *
+ * @return void
+ * @throws Exception - if an error is encountered.
+ */
+ function unlink($file) {
+ global $php_errormsg;
+ if (false === @unlink($file)) {
+ $msg = "FileSystem::unlink() FAILED. Cannot unlink '$file'. $php_errormsg";
+ throw new Exception($msg);
+ }
+ }
+
+ /**
+ * Symbolically link a file to another name.
+ *
+ * Currently symlink is not implemented on Windows. Don't use if the application is to be portable.
+ *
+ * @param string $target Path and/or name of file to link.
+ * @param string $link Path and/or name of link to be created.
+ * @return void
+ */
+ function symlink($target, $link) {
+
+ // If Windows OS then symlink() will report it is not supported in
+ // the build. Use this error instead of checking for Windows as the OS.
+
+ if (false === @symlink($target, $link)) {
+ // Add error from php to end of log message. $php_errormsg.
+ $msg = "FileSystem::Symlink() FAILED. Cannot symlink '$target' to '$link'. $php_errormsg";
+ throw new Exception($msg);
+ }
+
+ }
+
+ /**
+ * Set the modification and access time on a file to the present time.
+ *
+ * @param string $file Path and/or name of file to touch.
+ * @param int $time
+ * @return void
+ */
+ function touch($file, $time = null) {
+ global $php_errormsg;
+
+ if (null === $time) {
+ $error = @touch($file);
+ } else {
+ $error = @touch($file, $time);
+ }
+
+ if (false === $error) { // FAILED.
+ // Add error from php to end of log message. $php_errormsg.
+ $msg = "FileSystem::touch() FAILED. Cannot touch '$file'. $php_errormsg";
+ throw new Exception($msg);
+ }
+ }
+
+ /**
+ * Delete an empty directory OR a directory and all of its contents.
+ *
+ * @param dir String. Path and/or name of directory to delete.
+ * @param children Boolean. False: don't delete directory contents.
+ * True: delete directory contents.
+ *
+ * @return void
+ */
+ function rmdir($dir, $children = false) {
+ global $php_errormsg;
+
+ // If children=FALSE only delete dir if empty.
+ if (false === $children) {
+
+ if (false === @rmdir($dir)) { // FAILED.
+ // Add error from php to end of log message. $php_errormsg.
+ $msg = "FileSystem::rmdir() FAILED. Cannot rmdir $dir. $php_errormsg";
+ throw new Exception($msg);
+ }
+
+ } else { // delete contents and dir.
+
+ $handle = @opendir($dir);
+
+ if (false === $handle) { // Error.
+
+ $msg = "FileSystem::rmdir() FAILED. Cannot opendir() $dir. $php_errormsg";
+ throw new Exception($msg);
+
+ } else { // Read from handle.
+
+ // Don't error on readdir().
+ while (false !== ($entry = @readdir($handle))) {
+
+ if ($entry != '.' && $entry != '..') {
+
+ // Only add / if it isn't already the last char.
+ // This ONLY serves the purpose of making the Logger
+ // output look nice:)
+
+ if (strpos(strrev($dir), DIRECTORY_SEPARATOR) === 0) {// there is a /
+ $next_entry = $dir . $entry;
+ } else { // no /
+ $next_entry = $dir . DIRECTORY_SEPARATOR . $entry;
+ }
+
+ // NOTE: As of php 4.1.1 is_dir doesn't return FALSE it
+ // returns 0. So use == not ===.
+
+ // Don't error on is_dir()
+ if (false == @is_dir($next_entry)) { // Is file.
+
+ try {
+ self::unlink($next_entry); // Delete.
+ } catch (Exception $e) {
+ $msg = "FileSystem::Rmdir() FAILED. Cannot FileSystem::Unlink() $next_entry. ". $e->getMessage();
+ throw new Exception($msg);
+ }
+
+ } else { // Is directory.
+
+ try {
+ self::rmdir($next_entry, true); // Delete
+ } catch (Exception $e) {
+ $msg = "FileSystem::rmdir() FAILED. Cannot FileSystem::rmdir() $next_entry. ". $e->getMessage();
+ throw new Exception($msg);
+ }
+
+ } // end is_dir else
+ } // end .. if
+ } // end while
+ } // end handle if
+
+ // Don't error on closedir()
+ @closedir($handle);
+
+ if (false === @rmdir($dir)) { // FAILED.
+ // Add error from php to end of log message. $php_errormsg.
+ $msg = "FileSystem::rmdir() FAILED. Cannot rmdir $dir. $php_errormsg";
+ throw new Exception($msg);
+ }
+
+ }
+
+ }
+
+ /**
+ * Set the umask for file and directory creation.
+ *
+ * @param mode Int. Permissions ususally in ocatal. Use leading 0 for
+ * octal. Number between 0 and 0777.
+ *
+ * @return void
+ * @throws Exception if there is an error performing operation.
+ */
+ function umask($mode) {
+ global $php_errormsg;
+
+ // CONSIDERME:
+ // Throw a warning if mode is 0. PHP converts illegal octal numbers to
+ // 0 so 0 might not be what the user intended.
+
+ $str_mode = decoct($mode); // Show octal in messages.
+
+ if (false === @umask($mode)) { // FAILED.
+ // Add error from php to end of log message. $php_errormsg.
+ $msg = "FileSystem::Umask() FAILED. Value $mode. $php_errormsg";
+ throw new Exception($msg);
+ }
+ }
+
+ /**
+ * Compare the modified time of two files.
+ *
+ * @param file1 String. Path and name of file1.
+ * @param file2 String. Path and name of file2.
+ *
+ * @return Int. 1 if file1 is newer.
+ * -1 if file2 is newer.
+ * 0 if files have the same time.
+ * Err object on failure.
+ *
+ * @throws Exception - if cannot get modified time of either file.
+ */
+ function compareMTimes($file1, $file2) {
+
+ $mtime1 = filemtime($file1);
+ $mtime2 = filemtime($file2);
+
+ if ($mtime1 === false) { // FAILED. Log and return err.
+ // Add error from php to end of log message. $php_errormsg.
+ $msg = "FileSystem::compareMTimes() FAILED. Cannot can not get modified time of $file1.";
+ throw new Exception($msg);
+ } elseif ($mtime2 === false) { // FAILED. Log and return err.
+ // Add error from php to end of log message. $php_errormsg.
+ $msg = "FileSystem::compareMTimes() FAILED. Cannot can not get modified time of $file2.";
+ throw new Exception($msg);
+ } else { // Worked. Log and return compare.
+ // Compare mtimes.
+ if ($mtime1 == $mtime2) {
+ return 0;
+ } else {
+ return ($mtime1 < $mtime2) ? -1 : 1;
+ } // end compare
+ }
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/system/io/FileWriter.php b/buildscripts/phing/classes/phing/system/io/FileWriter.php
new file mode 100644
index 00000000..d6265777
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/io/FileWriter.php
@@ -0,0 +1,139 @@
+<?php
+/*
+ * $Id: FileWriter.php,v 1.7 2005/05/26 13:10:52 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/system/io/PhingFile.php';
+include_once 'phing/system/io/Writer.php';
+
+/**
+ * Convenience class for reading files. The constructor of this
+ *
+ * @package phing.system.io
+ */
+class FileWriter extends Writer {
+
+ protected $file;
+ protected $fd;
+
+ /** Whether to append contents to file. */
+ protected $append;
+
+ /** Whether we should attempt to lock the file (currently disabled). */
+ protected $exclusive;
+
+ /**
+ * Construct a new FileWriter.
+ * @param mixed $file PhingFile or string pathname.
+ * @param boolean $append Append to existing file?
+ * @param boolean $exclusive Lock file? (currently disabled due to windows incompatibility)
+ */
+ function __construct($file, $append = false, $exclusive = false) {
+ if ($file instanceof PhingFile) {
+ $this->file = $file;
+ } elseif (is_string($file)) {
+ $this->file = new PhingFile($file);
+ } else {
+ throw new Exception("Invalid argument type for \$file.");
+ }
+ $this->append = $append;
+ $this->exclusive = $exclusive;
+ }
+
+ function close() {
+ if ($this->fd === null) {
+ return true;
+ }
+
+ if (false === @fclose($this->fd)) {
+ // FAILED.
+ $msg = "Cannot fclose " . $this->file->__toString() . " $php_errormsg";
+ throw new IOException($msg);
+ } else {
+ $this->fd = null;
+ return true;
+ }
+ }
+
+ function open() {
+ if ($this->fd === null) {
+ if ($this->append) { $flags = "ab"; } else { $flags = "wb"; }
+ $this->fd = @fopen($this->file->getPath(), $flags);
+ }
+
+ if ($this->fd === false) {
+ // fopen FAILED.
+ // Add error from php to end of log message. $php_errormsg.
+ $msg = "Cannot fopen ".$this->file->getPath()." $php_errormsg";
+ throw new IOException($msg);
+ }
+
+ if (false) {
+ // Locks don't seem to work on windows??? HELP!!!!!!!!!
+ // if (FALSE === @flock($fp, LOCK_EX)) { // FAILED.
+ $msg = "Cannot acquire flock on $file. $php_errormsg";
+ throw new IOException($msg);
+ }
+
+ return true;
+ }
+
+ function reset() {
+ // FIXME -- what exactly should this do, if anything?
+ // reset to beginning of file (i.e. re-open)?
+ }
+
+ function writeBuffer($buffer) {
+
+ if (!$this->file->canWrite()) {
+ throw new IOException("No permission to write to file: " . $this->file->__toString());
+ }
+
+ $this->open();
+ $result = @fwrite($this->fd, $buffer);
+ $this->close();
+
+ if ($result === false) {
+ throw new IOException("Error writing file: ". $this->file->toString());
+ } else {
+ return true;
+ }
+ }
+
+ function write($buf, $off = null, $len = null) {
+ if ( $off === null && $len === null )
+ $to_write = $buf;
+ else
+ $to_write = substr($buf, $off, $len);
+
+ $this->open();
+ $result = @fwrite($this->fd, $to_write);
+
+ if ( $result === false ) {
+ throw new IOException("Error writing file.");
+ } else {
+ return true;
+ }
+ }
+
+ function getResource() {
+ return $this->file->toString();
+ }
+}
+?>
diff --git a/buildscripts/phing/classes/phing/system/io/FilterReader.php b/buildscripts/phing/classes/phing/system/io/FilterReader.php
new file mode 100644
index 00000000..8c683408
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/io/FilterReader.php
@@ -0,0 +1,72 @@
+<?php
+/*
+ * $Id: FilterReader.php,v 1.6 2005/05/26 13:10:52 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/system/io/Reader.php';
+
+/**
+ * Convenience class for reading files. The constructor of this
+ * @package phing.system.io
+ *
+ * TODO: All filters should be ProjectComponents, too!
+ */
+class FilterReader extends Reader {
+
+ protected $in;
+
+ function __construct(Reader $in = null) {
+ $this->in = $in;
+ //parent::__construct(new FileReader($file, $exclusive));
+ }
+
+ public function setReader(Reader $in) {
+ $this->in = $in;
+ }
+
+ public function skip($n) {
+ return $this->in->skip($n);
+ }
+
+ /**
+ * Read data from source.
+ * FIXME: Clean up this function signature, as it a) params aren't being used
+ * and b) it doesn't make much sense.
+ */
+ public function read($len = null) {
+ return $this->in->read($len);
+ }
+
+ public function reset() {
+ return $this->in->reset();
+ }
+
+ public function close() {
+ return $this->in->close();
+ }
+
+ public function open() {
+ return $this->in->open();
+ }
+
+ function getResource() {
+ return $this->in->getResource();
+ }
+}
+?>
diff --git a/buildscripts/phing/classes/phing/system/io/IOException.php b/buildscripts/phing/classes/phing/system/io/IOException.php
new file mode 100644
index 00000000..e2c73b27
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/io/IOException.php
@@ -0,0 +1,28 @@
+<?php
+/*
+ * $Id: IOException.php,v 1.4 2005/02/27 20:52:09 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * Extends Exception to take advantage of methods therein.
+ *
+ * @package phing.system.io
+ */
+class IOException extends Exception {}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/system/io/PhingFile.php b/buildscripts/phing/classes/phing/system/io/PhingFile.php
new file mode 100644
index 00000000..cd881963
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/io/PhingFile.php
@@ -0,0 +1,866 @@
+<?php
+/*
+ * $Id: PhingFile.php,v 1.1 2005/05/26 13:10:52 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/system/io/FileSystem.php';
+include_once 'phing/system/lang/NullPointerException.php';
+
+/**
+ * An abstract representation of file and directory pathnames.
+ *
+ * @version $Revision: 1.1 $
+ * @package phing.system.io
+ */
+class PhingFile {
+
+ /** separator string, static, obtained from FileSystem */
+ public static $separator;
+
+ /** path separator string, static, obtained from FileSystem (; or :)*/
+ public static $pathSeparator;
+
+ /**
+ * This abstract pathname's normalized pathname string. A normalized
+ * pathname string uses the default name-separator character and does not
+ * contain any duplicate or redundant separators.
+ */
+ private $path = null;
+
+ /** The length of this abstract pathname's prefix, or zero if it has no prefix. */
+ private $prefixLength = 0;
+
+ /** constructor */
+ function __construct($arg1 = null, $arg2 = null) {
+
+ if (self::$separator === null || self::$pathSeparator === null) {
+ $fs = FileSystem::getFileSystem();
+ self::$separator = $fs->getSeparator();
+ self::$pathSeparator = $fs->getPathSeparator();
+ }
+
+ /* simulate signature identified constructors */
+ if ($arg1 instanceof PhingFile && is_string($arg2)) {
+ $this->_constructFileParentStringChild($arg1, $arg2);
+ } elseif (is_string($arg1) && ($arg2 === null)) {
+ $this->_constructPathname($arg1);
+ } elseif(is_string($arg1) && is_string($arg2)) {
+ $this->_constructStringParentStringChild($arg1, $arg2);
+ } else {
+ if ($arg1 === null) {
+ throw new NullPointerException("Argument1 to function must not be null");
+ }
+ $this->path = (string) $arg1;
+ $this->prefixLength = (int) $arg2;
+ }
+ }
+
+ /** Returns the length of this abstract pathname's prefix. */
+ function getPrefixLength() {
+ return (int) $this->prefixLength;
+ }
+
+ /* -- constructors not called by signature match, so we need some helpers --*/
+
+ function _constructPathname($pathname) {
+ // obtain ref to the filesystem layer
+ $fs = FileSystem::getFileSystem();
+
+ if ($pathname === null) {
+ throw new NullPointerException("Argument to function must not be null");
+ }
+
+ $this->path = (string) $fs->normalize($pathname);
+ $this->prefixLength = (int) $fs->prefixLength($this->path);
+ }
+
+ function _constructStringParentStringChild($parent, $child = null) {
+ // obtain ref to the filesystem layer
+ $fs = FileSystem::getFileSystem();
+
+ if ($child === null) {
+ throw new NullPointerException("Argument to function must not be null");
+ }
+ if ($parent !== null) {
+ if ($parent === "") {
+ $this->path = $fs->resolve($fs->getDefaultParent(), $fs->normalize($child));
+ } else {
+ $this->path = $fs->resolve($fs->normalize($parent), $fs->normalize($child));
+ }
+ } else {
+ $this->path = (string) $fs->normalize($child);
+ }
+ $this->prefixLength = (int) $fs->prefixLength($this->path);
+ }
+
+ function _constructFileParentStringChild($parent, $child = null) {
+ // obtain ref to the filesystem layer
+ $fs = FileSystem::getFileSystem();
+
+ if ($child === null) {
+ throw new NullPointerException("Argument to function must not be null");
+ }
+
+ if ($parent !== null) {
+ if ($parent->path === "") {
+ $this->path = $fs->resolve($fs->getDefaultParent(), $fs->normalize($child));
+ } else {
+ $this->path = $fs->resolve($parent->path, $fs->normalize($child));
+ }
+ } else {
+ $this->path = $fs->normalize($child);
+ }
+ $this->prefixLength = $fs->prefixLength($this->path);
+ }
+
+ /* -- Path-component accessors -- */
+
+ /**
+ * Returns the name of the file or directory denoted by this abstract
+ * pathname. This is just the last name in the pathname's name
+ * sequence. If the pathname's name sequence is empty, then the empty
+ * string is returned.
+ *
+ * @return The name of the file or directory denoted by this abstract
+ * pathname, or the empty string if this pathname's name sequence
+ * is empty
+ */
+ function getName() {
+ // that's a lastIndexOf
+ $index = ((($res = strrpos($this->path, self::$separator)) === false) ? -1 : $res);
+ if ($index < $this->prefixLength) {
+ return substr($this->path, $this->prefixLength);
+ }
+ return substr($this->path, $index + 1);
+ }
+
+ /**
+ * Returns the pathname string of this abstract pathname's parent, or
+ * null if this pathname does not name a parent directory.
+ *
+ * The parent of an abstract pathname consists of the pathname's prefix,
+ * if any, and each name in the pathname's name sequence except for the last.
+ * If the name sequence is empty then the pathname does not name a parent
+ * directory.
+ *
+ * @return The pathname string of the parent directory named by this
+ * abstract pathname, or null if this pathname does not name a parent
+ */
+ function getParent() {
+ // that's a lastIndexOf
+ $index = ((($res = strrpos($this->path, self::$separator)) === false) ? -1 : $res);
+ if ($index < $this->prefixLength) {
+ if (($this->prefixLength > 0) && (strlen($this->path > $this->prefixLength))) {
+ return substr($this->path, 0, $this->prefixLength);
+ }
+ return null;
+ }
+ return substr($this->path, 0, $index);
+ }
+
+ /**
+ * Returns the abstract pathname of this abstract pathname's parent,
+ * or null if this pathname does not name a parent directory.
+ *
+ * The parent of an abstract pathname consists of the pathname's prefix,
+ * if any, and each name in the pathname's name sequence except for the
+ * last. If the name sequence is empty then the pathname does not name
+ * a parent directory.
+ *
+ * @return The abstract pathname of the parent directory named by this
+ * abstract pathname, or null if this pathname
+ * does not name a parent
+ */
+ function getParentFile() {
+ $p = $this->getParent();
+ if ($p === null) {
+ return null;
+ }
+ return new PhingFile((string) $p, (int) $this->prefixLength);
+ }
+
+ /**
+ * Converts this abstract pathname into a pathname string. The resulting
+ * string uses the default name-separator character to separate the names
+ * in the name sequence.
+ *
+ * @return The string form of this abstract pathname
+ */
+ function getPath() {
+ return (string) $this->path;
+ }
+
+ /**
+ * Tests whether this abstract pathname is absolute. The definition of
+ * absolute pathname is system dependent. On UNIX systems, a pathname is
+ * absolute if its prefix is "/". On Win32 systems, a pathname is absolute
+ * if its prefix is a drive specifier followed by "\\", or if its prefix
+ * is "\\".
+ *
+ * @return true if this abstract pathname is absolute, false otherwise
+ */
+ function isAbsolute() {
+ return ($this->prefixLength !== 0);
+ }
+
+
+ /**
+ * Returns the absolute pathname string of this abstract pathname.
+ *
+ * If this abstract pathname is already absolute, then the pathname
+ * string is simply returned as if by the getPath method.
+ * If this abstract pathname is the empty abstract pathname then
+ * the pathname string of the current user directory, which is named by the
+ * system property user.dir, is returned. Otherwise this
+ * pathname is resolved in a system-dependent way. On UNIX systems, a
+ * relative pathname is made absolute by resolving it against the current
+ * user directory. On Win32 systems, a relative pathname is made absolute
+ * by resolving it against the current directory of the drive named by the
+ * pathname, if any; if not, it is resolved against the current user
+ * directory.
+ *
+ * @return The absolute pathname string denoting the same file or
+ * directory as this abstract pathname
+ * @see #isAbsolute()
+ */
+ function getAbsolutePath() {
+ $fs = FileSystem::getFileSystem();
+ return $fs->resolveFile($this);
+ }
+
+ /**
+ * Returns the absolute form of this abstract pathname. Equivalent to
+ * getAbsolutePath.
+ *
+ * @return The absolute abstract pathname denoting the same file or
+ * directory as this abstract pathname
+ */
+ function getAbsoluteFile() {
+ return new PhingFile((string) $this->getAbsolutePath());
+ }
+
+
+ /**
+ * Returns the canonical pathname string of this abstract pathname.
+ *
+ * A canonical pathname is both absolute and unique. The precise
+ * definition of canonical form is system-dependent. This method first
+ * converts this pathname to absolute form if necessary, as if by invoking the
+ * getAbsolutePath() method, and then maps it to its unique form in a
+ * system-dependent way. This typically involves removing redundant names
+ * such as "." and .. from the pathname, resolving symbolic links
+ * (on UNIX platforms), and converting drive letters to a standard case
+ * (on Win32 platforms).
+ *
+ * Every pathname that denotes an existing file or directory has a
+ * unique canonical form. Every pathname that denotes a nonexistent file
+ * or directory also has a unique canonical form. The canonical form of
+ * the pathname of a nonexistent file or directory may be different from
+ * the canonical form of the same pathname after the file or directory is
+ * created. Similarly, the canonical form of the pathname of an existing
+ * file or directory may be different from the canonical form of the same
+ * pathname after the file or directory is deleted.
+ *
+ * @return The canonical pathname string denoting the same file or
+ * directory as this abstract pathname
+ */
+ function getCanonicalPath() {
+ $fs = FileSystem::getFileSystem();
+ return $fs->canonicalize($this->path);
+ }
+
+
+ /**
+ * Returns the canonical form of this abstract pathname. Equivalent to
+ * getCanonicalPath(.
+ *
+ * @return PhingFile The canonical pathname string denoting the same file or
+ * directory as this abstract pathname
+ */
+ function getCanonicalFile() {
+ return new PhingFile($this->getCanonicalPath());
+ }
+
+ /**
+ * Converts this abstract pathname into a file: URL. The
+ * exact form of the URL is system-dependent. If it can be determined that
+ * the file denoted by this abstract pathname is a directory, then the
+ * resulting URL will end with a slash.
+ *
+ * Usage note: This method does not automatically escape
+ * characters that are illegal in URLs. It is recommended that new code
+ * convert an abstract pathname into a URL by first converting it into a
+ * URI, via the toURI() method, and then converting the URI
+ * into a URL via the URI::toURL()
+ *
+ * @return A URL object representing the equivalent file URL
+ *
+ *
+ */
+ function toURL() {
+ /*
+ // URL class not implemented yet
+ return new URL("file", "", $this->_slashify($this->getAbsolutePath(), $this->isDirectory()));
+ */
+ }
+
+ /**
+ * Constructs a file: URI that represents this abstract pathname.
+ * Not implemented yet
+ */
+ function toURI() {
+ /*
+ $f = $this->getAbsoluteFile();
+ $sp = (string) $this->slashify($f->getPath(), $f->isDirectory());
+ if (StringHelper::startsWith('//', $sp))
+ $sp = '//' + sp;
+ return new URI('file', null, $sp, null);
+ */
+ }
+
+ function _slashify($path, $isDirectory) {
+ $p = (string) $path;
+
+ if (self::$separator !== '/') {
+ $p = str_replace(self::$separator, '/', $p);
+ }
+
+ if (!StringHelper::startsWith('/', $p)) {
+ $p = '/'.$p;
+ }
+
+ if (!StringHelper::endsWith('/', $p) && $isDirectory) {
+ $p = $p.'/';
+ }
+
+ return $p;
+ }
+
+ /* -- Attribute accessors -- */
+
+ /**
+ * Tests whether the application can read the file denoted by this
+ * abstract pathname.
+ *
+ * @return true if and only if the file specified by this
+ * abstract pathname exists and can be read by the
+ * application; false otherwise
+ */
+ function canRead() {
+ $fs = FileSystem::getFileSystem();
+
+ if ($fs->checkAccess($this)) {
+ return (boolean) @is_readable($this->getAbsolutePath());
+ }
+ return false;
+ }
+
+ /**
+ * Tests whether the application can modify to the file denoted by this
+ * abstract pathname.
+ *
+ * @return true if and only if the file system actually
+ * contains a file denoted by this abstract pathname and
+ * the application is allowed to write to the file;
+ * false otherwise.
+ *
+ */
+ function canWrite() {
+ $fs = FileSystem::getFileSystem();
+ return $fs->checkAccess($this, true);
+ }
+
+ /**
+ * Tests whether the file denoted by this abstract pathname exists.
+ *
+ * @return true if and only if the file denoted by this
+ * abstract pathname exists; false otherwise
+ *
+ */
+ function exists() {
+ if ($this->isFile()) {
+ return @file_exists($this->path);
+ } else {
+ return @is_dir($this->path);
+ }
+ }
+
+ /**
+ * Tests whether the file denoted by this abstract pathname is a
+ * directory.
+ *
+ * @return true if and only if the file denoted by this
+ * abstract pathname exists and is a directory;
+ * false otherwise
+ *
+ */
+ function isDirectory() {
+ $fs = FileSystem::getFileSystem();
+ if ($fs->checkAccess($this) !== true) {
+ throw new IOException("No read access to ".$this->path);
+ }
+ return @is_dir($this->path);
+ }
+
+ /**
+ * Tests whether the file denoted by this abstract pathname is a normal
+ * file. A file is normal if it is not a directory and, in
+ * addition, satisfies other system-dependent criteria. Any non-directory
+ * file created by a Java application is guaranteed to be a normal file.
+ *
+ * @return true if and only if the file denoted by this
+ * abstract pathname exists and is a normal file;
+ * false otherwise
+ */
+ function isFile() {
+ //$fs = FileSystem::getFileSystem();
+ return @is_file($this->path);
+ }
+
+ /**
+ * Tests whether the file named by this abstract pathname is a hidden
+ * file. The exact definition of hidden is system-dependent. On
+ * UNIX systems, a file is considered to be hidden if its name begins with
+ * a period character ('.'). On Win32 systems, a file is considered to be
+ * hidden if it has been marked as such in the filesystem. Currently there
+ * seems to be no way to dermine isHidden on Win file systems via PHP
+ *
+ * @return true if and only if the file denoted by this
+ * abstract pathname is hidden according to the conventions of the
+ * underlying platform
+ */
+ function isHidden() {
+ $fs = FileSystem::getFileSystem();
+ if ($fs->checkAccess($this) !== true) {
+ throw new IOException("No read access to ".$this->path);
+ }
+ return (($fs->getBooleanAttributes($this) & $fs->BA_HIDDEN) !== 0);
+ }
+
+ /**
+ * Returns the time that the file denoted by this abstract pathname was
+ * last modified.
+ *
+ * @return A integer value representing the time the file was
+ * last modified, measured in milliseconds since the epoch
+ * (00:00:00 GMT, January 1, 1970), or 0 if the
+ * file does not exist or if an I/O error occurs
+ */
+ function lastModified() {
+ $fs = FileSystem::getFileSystem();
+ if ($fs->checkAccess($this) !== true) {
+ throw new IOException("No read access to " . $this->path);
+ }
+ return $fs->getLastModifiedTime($this);
+ }
+
+ /**
+ * Returns the length of the file denoted by this abstract pathname.
+ * The return value is unspecified if this pathname denotes a directory.
+ *
+ * @return The length, in bytes, of the file denoted by this abstract
+ * pathname, or 0 if the file does not exist
+ */
+ function length() {
+ $fs = FileSystem::getFileSystem();
+ if ($fs->checkAccess($this) !== true) {
+ throw new IOException("No read access to ".$this->path."\n");
+ }
+ return $fs->getLength($this);
+ }
+
+ /**
+ * Convenience method for returning the contents of this file as a string.
+ * This method uses file_get_contents() to read file in an optimized way.
+ * @return string
+ * @throws Exception - if file cannot be read
+ */
+ function contents() {
+ if (!$this->canRead() || !$this->isFile()) {
+ throw new IOException("Cannot read file contents!");
+ }
+ return file_get_contents($this->getAbsolutePath());
+ }
+
+ /* -- File operations -- */
+
+ /**
+ * Atomically creates a new, empty file named by this abstract pathname if
+ * and only if a file with this name does not yet exist. The check for the
+ * existence of the file and the creation of the file if it does not exist
+ * are a single operation that is atomic with respect to all other
+ * filesystem activities that might affect the file.
+ *
+ * @return true if the named file does not exist and was
+ * successfully created; <code>false</code> if the named file
+ * already exists
+ * @throws IOException if file can't be created
+ */
+ function createNewFile($parents=true, $mode=0777) {
+ $file = FileSystem::getFileSystem()->createNewFile($this->path);
+ return $file;
+ }
+
+ /**
+ * Deletes the file or directory denoted by this abstract pathname. If
+ * this pathname denotes a directory, then the directory must be empty in
+ * order to be deleted.
+ *
+ * @return true if and only if the file or directory is
+ * successfully deleted; false otherwise
+ */
+ function delete() {
+ $fs = FileSystem::getFileSystem();
+ if ($fs->checkAccess($this, true) !== true) {
+ throw new IOException("No read access to " . $this->path."\n");
+ }
+ return $fs->delete($this);
+ }
+
+ /**
+ * Requests that the file or directory denoted by this abstract pathname
+ * be deleted when php terminates. Deletion will be attempted only for
+ * normal termination of php and if and if only Phing::shutdown() is
+ * called.
+ *
+ * Once deletion has been requested, it is not possible to cancel the
+ * request. This method should therefore be used with care.
+ *
+ */
+ function deleteOnExit() {
+ $fs = FileSystem::getFileSystem();
+ $fs->deleteOnExit($this);
+ }
+
+ /**
+ * Returns an array of strings naming the files and directories in the
+ * directory denoted by this abstract pathname.
+ *
+ * If this abstract pathname does not denote a directory, then this
+ * method returns null Otherwise an array of strings is
+ * returned, one for each file or directory in the directory. Names
+ * denoting the directory itself and the directory's parent directory are
+ * not included in the result. Each string is a file name rather than a
+ * complete path.
+ *
+ * There is no guarantee that the name strings in the resulting array
+ * will appear in any specific order; they are not, in particular,
+ * guaranteed to appear in alphabetical order.
+ *
+ * @return An array of strings naming the files and directories in the
+ * directory denoted by this abstract pathname. The array will be
+ * empty if the directory is empty. Returns null if
+ * this abstract pathname does not denote a directory, or if an
+ * I/O error occurs.
+ *
+ */
+ function listDir($filter = null) {
+ $fs = FileSystem::getFileSystem();
+ return $fs->lister($this, $filter);
+ }
+
+ function listFiles($filter = null) {
+ $ss = $this->listDir($filter);
+ if ($ss === null) {
+ return null;
+ }
+ $n = count($ss);
+ $fs = array();
+ for ($i = 0; $i < $n; $i++) {
+ $fs[$i] = new PhingFile((string)$this->path, (string)$ss[$i]);
+ }
+ return $fs;
+ }
+
+ /**
+ * Creates the directory named by this abstract pathname, including any
+ * necessary but nonexistent parent directories. Note that if this
+ * operation fails it may have succeeded in creating some of the necessary
+ * parent directories.
+ *
+ * @return true if and only if the directory was created,
+ * along with all necessary parent directories; false
+ * otherwise
+ * @throws IOException
+ */
+ function mkdirs() {
+ if ($this->exists()) {
+ return false;
+ }
+ try {
+ if ($this->mkdir()) {
+ return true;
+ }
+ } catch (IOException $ioe) {
+ // IOException from mkdir() means that directory propbably didn't exist.
+ }
+ $parentFile = $this->getParentFile();
+ return (($parentFile !== null) && ($parentFile->mkdirs() && $this->mkdir()));
+ }
+
+ /**
+ * Creates the directory named by this abstract pathname.
+ *
+ * @return true if and only if the directory was created; false otherwise
+ * @throws IOException
+ */
+ function mkdir() {
+ $fs = FileSystem::getFileSystem();
+
+ if ($fs->checkAccess(new PhingFile($this->path), true) !== true) {
+ throw new IOException("No write access to " . $this->getPath());
+ }
+ return $fs->createDirectory($this);
+ }
+
+ /**
+ * Renames the file denoted by this abstract pathname.
+ *
+ * @param destFile The new abstract pathname for the named file
+ * @return true if and only if the renaming succeeded; false otherwise
+ */
+ function renameTo(PhingFile $destFile) {
+ $fs = FileSystem::getFileSystem();
+ if ($fs->checkAccess($this) !== true) {
+ throw new IOException("No write access to ".$this->getPath());
+ }
+ return $fs->rename($this, $destFile);
+ }
+
+ /**
+ * Simple-copies file denoted by this abstract pathname into another
+ * PhingFile
+ *
+ * @param PhingFile $destFile The new abstract pathname for the named file
+ * @return true if and only if the renaming succeeded; false otherwise
+ */
+ function copyTo(PhingFile $destFile) {
+ $fs = FileSystem::getFileSystem();
+
+ if ($fs->checkAccess($this) !== true) {
+ throw new IOException("No read access to ".$this->getPath()."\n");
+ }
+
+ if ($fs->checkAccess($destFile, true) !== true) {
+ throw new IOException("File::copyTo() No write access to ".$destFile->getPath());
+ }
+ return $fs->copy($this, $destFile);
+ }
+
+ /**
+ * Sets the last-modified time of the file or directory named by this
+ * abstract pathname.
+ *
+ * All platforms support file-modification times to the nearest second,
+ * but some provide more precision. The argument will be truncated to fit
+ * the supported precision. If the operation succeeds and no intervening
+ * operations on the file take place, then the next invocation of the
+ * lastModified method will return the (possibly truncated) time argument
+ * that was passed to this method.
+ *
+ * @param time The new last-modified time, measured in milliseconds since
+ * the epoch (00:00:00 GMT, January 1, 1970)
+ * @return true if and only if the operation succeeded; false otherwise
+ */
+ function setLastModified($time) {
+ $time = (int) $time;
+ if ($time < 0) {
+ throw new Exception("IllegalArgumentException, Negative $time\n");
+ }
+
+ // FIXME check if accessible
+ $fs = FileSystem::getFileSystem();
+ if ($fs->checkAccess($this, true) !== true) {
+ throw new IOException("File::setLastModified(). No write access to file\n");
+ }
+ return $fs->setLastModifiedTime($this, $time);
+ }
+
+ /**
+ * Marks the file or directory named by this abstract pathname so that
+ * only read operations are allowed. After invoking this method the file
+ * or directory is guaranteed not to change until it is either deleted or
+ * marked to allow write access. Whether or not a read-only file or
+ * directory may be deleted depends upon the underlying system.
+ *
+ * @return true if and only if the operation succeeded; false otherwise
+ */
+ function setReadOnly() {
+ $fs = FileSystem::getFileSystem();
+ if ($fs->checkAccess($this, true) !== true) {
+ // Error, no write access
+ throw new IOException("No write access to " . $this->getPath());
+ }
+ return $fs->setReadOnly($this);
+ }
+
+ /**
+ * Sets the mode of the file
+ * @param int $mode Ocatal mode.
+ */
+ function setMode($mode) {
+ $fs = FileSystem::getFileSystem();
+ return $fs->chmod($this->getPath(), $mode);
+ }
+
+ /**
+ * Retrieve the mode of this file.
+ * @return int
+ */
+ function getMode() {
+ return @fileperms($this->getPath());
+ }
+
+ /* -- Filesystem interface -- */
+
+ /**
+ * List the available filesystem roots.
+ *
+ * A particular platform may support zero or more hierarchically-organized
+ * file systems. Each file system has a root directory from which all
+ * other files in that file system can be reached.
+ * Windows platforms, for example, have a root directory for each active
+ * drive; UNIX platforms have a single root directory, namely "/".
+ * The set of available filesystem roots is affected by various system-level
+ * operations such the insertion or ejection of removable media and the
+ * disconnecting or unmounting of physical or virtual disk drives.
+ *
+ * This method returns an array of PhingFile objects that
+ * denote the root directories of the available filesystem roots. It is
+ * guaranteed that the canonical pathname of any file physically present on
+ * the local machine will begin with one of the roots returned by this
+ * method.
+ *
+ * The canonical pathname of a file that resides on some other machine
+ * and is accessed via a remote-filesystem protocol such as SMB or NFS may
+ * or may not begin with one of the roots returned by this method. If the
+ * pathname of a remote file is syntactically indistinguishable from the
+ * pathname of a local file then it will begin with one of the roots
+ * returned by this method. Thus, for example, PhingFile objects
+ * denoting the root directories of the mapped network drives of a Windows
+ * platform will be returned by this method, while PhingFile
+ * objects containing UNC pathnames will not be returned by this method.
+ *
+ * @return An array of PhingFile objects denoting the available
+ * filesystem roots, or null if the set of roots
+ * could not be determined. The array will be empty if there are
+ * no filesystem roots.
+ */
+ function listRoots() {
+ $fs = FileSystem::getFileSystem();
+ return (array) $fs->listRoots();
+ }
+
+ /* -- Tempfile management -- */
+
+ /**
+ * Returns the path to the temp directory.
+ */
+ function getTempDir() {
+ return Phing::getProperty('php.tmpdir');
+ }
+
+ /**
+ * Static method that creates a unique filename whose name begins with
+ * $prefix and ends with $suffix in the directory $directory. $directory
+ * is a reference to a PhingFile Object.
+ * Then, the file is locked for exclusive reading/writing.
+ *
+ * @author manuel holtgrewe, grin@gmx.net
+ * @throws IOException
+ * @access public
+ */
+ function createTempFile($prefix, $suffix, PhingFile $directory) {
+
+ // quick but efficient hack to create a unique filename ;-)
+ $result = null;
+ do {
+ $result = new PhingFile($directory, $prefix . substr(md5(time()), 0, 8) . $suffix);
+ } while (file_exists($result->getPath()));
+
+ $fs = FileSystem::getFileSystem();
+ $fs->createNewFile($result->getPath());
+ $fs->lock($result);
+
+ return $result;
+ }
+
+ /**
+ * If necessary, $File the lock on $File is removed and then the file is
+ * deleted
+ *
+ * @access public
+ */
+ function removeTempFile() {
+ $fs = FileSystem::getFileSystem();
+ // catch IO Exception
+ $fs->unlock($this);
+ $this->delete();
+ }
+
+
+ /* -- Basic infrastructure -- */
+
+ /**
+ * Compares two abstract pathnames lexicographically. The ordering
+ * defined by this method depends upon the underlying system. On UNIX
+ * systems, alphabetic case is significant in comparing pathnames; on Win32
+ * systems it is not.
+ *
+ * @param PhingFile $file Th file whose pathname sould be compared to the pathname of this file.
+ *
+ * @return int Zero if the argument is equal to this abstract pathname, a
+ * value less than zero if this abstract pathname is
+ * lexicographically less than the argument, or a value greater
+ * than zero if this abstract pathname is lexicographically
+ * greater than the argument
+ */
+ function compareTo(PhingFile $file) {
+ $fs = FileSystem::getFileSystem();
+ return $fs->compare($this, $file);
+ }
+
+ /**
+ * Tests this abstract pathname for equality with the given object.
+ * Returns <code>true</code> if and only if the argument is not
+ * <code>null</code> and is an abstract pathname that denotes the same file
+ * or directory as this abstract pathname. Whether or not two abstract
+ * pathnames are equal depends upon the underlying system. On UNIX
+ * systems, alphabetic case is significant in comparing pathnames; on Win32
+ * systems it is not.
+ * @return boolean
+ */
+ function equals($obj) {
+ if (($obj !== null) && ($obj instanceof PhingFile)) {
+ return ($this->compareTo($obj) === 0);
+ }
+ return false;
+ }
+
+ /** Backwards compatibility -- use PHP5's native __tostring method. */
+ function toString() {
+ return $this->getPath();
+ }
+
+ /** PHP5's native method. */
+ function __toString() {
+ return $this->getPath();
+ }
+}
+?>
diff --git a/buildscripts/phing/classes/phing/system/io/Reader.php b/buildscripts/phing/classes/phing/system/io/Reader.php
new file mode 100644
index 00000000..1e377378
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/io/Reader.php
@@ -0,0 +1,88 @@
+<?php
+/*
+ * $Id: Reader.php,v 1.5 2003/12/24 12:38:40 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+/**
+ * Abstract class for reading character streams.
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @author Yannick Lecaillez <yl@seasonfive.com>
+ * @version $Revision: 1.5 $
+ * @package phing.system.io
+ */
+abstract class Reader {
+
+ /**
+ * Read data from source.
+ * If length is specified, then only that number of chars is read,
+ * otherwise stream is read until EOF.
+ * @param int $len
+ */
+ abstract public function read($len = null);
+
+ /**
+ * Close stream.
+ */
+ abstract public function close();
+
+ /**
+ * Open stream for reading.
+ */
+ abstract public function open();
+
+ /**
+ * Returns the filename, url, etc. that is being read from.
+ * This is critical for, e.g., ExpatParser's ability to know
+ * the filename that is throwing an ExpatParserException, etc.
+ * @return string
+ */
+ abstract function getResource();
+
+ /**
+ * Move stream position relative to current pos.
+ * @param int $n
+ */
+ public function skip($n) {}
+
+ /**
+ * Reset the current position in stream to beginning or last mark (if supported).
+ */
+ public function reset() {}
+
+ /**
+ * If supported, places a "marker" (like a bookmark) at current stream position.
+ * A subsequent call to reset() will move stream position back
+ * to last marker (if supported).
+ */
+ public function mark() {}
+
+ /**
+ * Whether marking is supported.
+ * @return boolean
+ */
+ public function markSupported() {}
+
+ /**
+ * Is stream ready for reading.
+ * @return boolean
+ */
+ public function ready() {}
+
+}
+?>
diff --git a/buildscripts/phing/classes/phing/system/io/StringReader.php b/buildscripts/phing/classes/phing/system/io/StringReader.php
new file mode 100644
index 00000000..689a2115
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/io/StringReader.php
@@ -0,0 +1,73 @@
+<?php
+/*
+ * $Id: StringReader.php,v 1.8 2005/05/26 13:10:52 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * Dummy class for reading character streams.
+ * @package phing.system.io
+ */
+class StringReader extends Reader {
+
+ private $_string;
+ private $mark = 0;
+ private $currPos = 0;
+
+ function __construct($string) {
+ $this->_string = $string;
+ }
+
+ function skip($n) {}
+
+ function read($len = null) {
+ if ($len === null) {
+ return $this->_string;
+ } else {
+ if ($this->currPos >= strlen($this->_string)) {
+ return -1;
+ }
+ $out = substr($this->_string, $this->currPos, $len);
+ $this->currPos += $len;
+ return $out;
+ }
+ }
+
+ function mark() {
+ $this->mark = $this->currPos;
+ }
+
+ function reset() {
+ $this->currPos = $this->mark;
+ }
+
+ function close() {}
+
+ function open() {}
+
+ function ready() {}
+
+ function markSupported() {
+ return true;
+ }
+
+ function getResource() {
+ return '(string) "'.$this->_string . '"';
+ }
+}
+?>
diff --git a/buildscripts/phing/classes/phing/system/io/TokenReader.php b/buildscripts/phing/classes/phing/system/io/TokenReader.php
new file mode 100644
index 00000000..a57d994c
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/io/TokenReader.php
@@ -0,0 +1,51 @@
+<?php
+/*
+ * $Id: TokenReader.php,v 1.3 2003/11/19 05:48:29 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+include_once 'phing/system/io/Reader.php';
+include_once 'phing/filters/ReplaceTokens.php'; // for class Token
+
+/**
+ * Abstract class for reading Tokens from a resource
+ *
+ * @author Manuel Holtgewe
+ * @version $Revision: 1.3 $
+ * @access public
+ * @package phing.system.io
+ */
+class TokenReader extends Reader {
+
+ /**
+ * Constructor
+ */
+ function __construct() {
+ }
+
+ /**
+ * Reads a token from the resource and returns it as a
+ * Token object.
+ *
+ * @access public
+ */
+ function readToken() {
+ }
+}
+
+?>
diff --git a/buildscripts/phing/classes/phing/system/io/UnixFileSystem.php b/buildscripts/phing/classes/phing/system/io/UnixFileSystem.php
new file mode 100644
index 00000000..fb4e49b4
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/io/UnixFileSystem.php
@@ -0,0 +1,266 @@
+<?php
+/*
+ * $Id: UnixFileSystem.php,v 1.10 2005/05/26 13:10:52 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/system/io/FileSystem.php';
+
+/**
+ * UnixFileSystem class. This class encapsulates the basic file system functions
+ * for platforms using the unix (posix)-stylish filesystem. It wraps php native
+ * functions suppressing normal PHP error reporting and instead uses Exception
+ * to report and error.
+ *
+ * This class is part of a oop based filesystem abstraction and targeted to run
+ * on all supported php platforms.
+ *
+ * Note: For debugging turn track_errors on in the php.ini. The error messages
+ * and log messages from this class will then be clearer because $php_errormsg
+ * is passed as part of the message.
+ *
+ * FIXME:
+ * - Comments
+ * - Error handling reduced to min, error are handled by PhingFile mainly
+ *
+ * @author Andreas Aderhold, andi@binarycloud.com
+ * @version $Revision: 1.10 $
+ * @package phing.system.io
+ */
+class UnixFileSystem extends FileSystem {
+
+ /**
+ * returns OS dependant path separator char
+ */
+ function getSeparator() {
+ return '/';
+ }
+
+ /**
+ * returns OS dependant directory separator char
+ */
+ function getPathSeparator() {
+ return ':';
+ }
+
+ /**
+ * A normal Unix pathname contains no duplicate slashes and does not end
+ * with a slash. It may be the empty string.
+ *
+ * Check that the given pathname is normal. If not, invoke the real
+ * normalizer on the part of the pathname that requires normalization.
+ * This way we iterate through the whole pathname string only once.
+ */
+ function normalize($strPathname) {
+
+ if (empty($strPathname)) {
+ return;
+ }
+
+ // Resolve home directories. We assume /home is where all home
+ // directories reside, b/c there is no other way to do this with
+ // PHP AFAIK.
+ if ($strPathname{0} === "~") {
+ if ($strPathname{1} === "/") { // like ~/foo => /home/user/foo
+ $strPathname = "/home/" . get_current_user() . substr($strPathname, 1);
+ } else { // like ~foo => /home/foo
+ $pos = strpos($strPathname, "/");
+ $name = substr($strPathname, 1, $pos - 2);
+ $strPathname = "/home/" . $name . substr($strPathname, $pos);
+ }
+ }
+
+ $n = strlen($strPathname);
+ $prevChar = 0;
+ for ($i=0; $i < $n; $i++) {
+ $c = $strPathname{$i};
+ if (($prevChar === '/') && ($c === '/')) {
+ return self::normalizer($strPathname, $n, $i - 1);
+ }
+ $prevChar = $c;
+ }
+ if ($prevChar === '/') {
+ return self::normalizer($strPathname, $n, $n - 1);
+ }
+ return $strPathname;
+ }
+
+ /**
+ * Normalize the given pathname, whose length is $len, starting at the given
+ * $offset; everything before this offset is already normal.
+ */
+ protected function normalizer($pathname, $len, $offset) {
+ if ($len === 0) {
+ return $pathname;
+ }
+ $n = (int) $len;
+ while (($n > 0) && ($pathname{$n-1} === '/')) {
+ $n--;
+ }
+ if ($n === 0) {
+ return '/';
+ }
+ $sb = "";
+
+ if ($offset > 0) {
+ $sb .= substr($pathname, 0, $offset);
+ }
+ $prevChar = 0;
+ for ($i = $offset; $i < $n; $i++) {
+ $c = $pathname{$i};
+ if (($prevChar === '/') && ($c === '/')) {
+ continue;
+ }
+ $sb .= $c;
+ $prevChar = $c;
+ }
+ return $sb;
+ }
+
+ /**
+ * Compute the length of the pathname string's prefix. The pathname
+ * string must be in normal form.
+ */
+ function prefixLength($pathname) {
+ if (strlen($pathname === 0)) {
+ return 0;
+ }
+ return (($pathname{0} === '/') ? 1 : 0);
+ }
+
+ /**
+ * Resolve the child pathname string against the parent.
+ * Both strings must be in normal form, and the result
+ * will be in normal form.
+ */
+ function resolve($parent, $child) {
+
+ if ($child === "") {
+ return $parent;
+ }
+
+ if ($child{0} === '/') {
+ if ($parent === '/') {
+ return $child;
+ }
+ return $parent.$child;
+ }
+
+ if ($parent === '/') {
+ return $parent.$child;
+ }
+
+ return $parent.'/'.$child;
+ }
+
+ function getDefaultParent() {
+ return '/';
+ }
+
+ function isAbsolute(PhingFile $f) {
+ return ($f->getPrefixLength() !== 0);
+ }
+
+ /**
+ * the file resolver
+ */
+ function resolveFile(PhingFile $f) {
+ // resolve if parent is a file oject only
+ if ($this->isAbsolute($f)) {
+ return $f->getPath();
+ } else {
+ return $this->resolve(Phing::getProperty("user.dir"), $f->getPath());
+ }
+ }
+
+ /* -- most of the following is mapped to the php natives wrapped by FileSystem */
+
+ /* -- Attribute accessors -- */
+ function getBooleanAttributes(&$f) {
+ //$rv = getBooleanAttributes0($f);
+ $name = $f->getName();
+ $hidden = (strlen($name) > 0) && ($name{0} == '.');
+ return ($hidden ? $this->BA_HIDDEN : 0);
+ }
+
+ /**
+ * set file readonly on unix
+ */
+ function setReadOnly($f) {
+ if ($f instanceof File) {
+ $strPath = (string) $f->getPath();
+ $perms = (int) (@fileperms($strPath) & 0444);
+ return FileSystem::Chmod($strPath, $perms);
+ } else {
+ throw new Exception("IllegalArgutmentType: Argument is not File");
+ }
+ }
+
+ /**
+ * compares file paths lexicographically
+ */
+ function compare($f1, $f2) {
+ if ( ($f1 instanceof PhingFile) && ($f2 instanceof PhingFile) ) {
+ $f1Path = $f1->getPath();
+ $f2Path = $f2->getPath();
+ return (boolean) strcmp((string) $f1Path, (string) $f2Path);
+ } else {
+ throw new Exception("IllegalArgutmentType: Argument is not PhingFile");
+ }
+ }
+
+ /* -- fs interface --*/
+
+ function listRoots() {
+ if (!$this->checkAccess('/', false)) {
+ die ("Can not access root");
+ }
+ return array(new PhingFile("/"));
+ }
+
+ /**
+ * returns the contents of a directory in an array
+ */
+ function lister($f) {
+ $dir = @opendir($f->getAbsolutePath());
+ if (!$dir) {
+ throw new Exception("Can't open directory " . $f->__toString());
+ }
+ $vv = array();
+ while (($file = @readdir($dir)) !== false) {
+ if ($file == "." || $file == "..") {
+ continue;
+ }
+ $vv[] = (string) $file;
+ }
+ @closedir($dir);
+ return $vv;
+ }
+
+ function fromURIPath($p) {
+ if (StringHelper::endsWith("/", $p) && (strlen($p) > 1)) {
+
+ // "/foo/" --> "/foo", but "/" --> "/"
+ $p = substr($p, 0, strlen($p) - 1);
+
+ }
+
+ return $p;
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/system/io/Win32FileSystem.php b/buildscripts/phing/classes/phing/system/io/Win32FileSystem.php
new file mode 100644
index 00000000..c32c21ff
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/io/Win32FileSystem.php
@@ -0,0 +1,477 @@
+<?php
+/*
+ * $Id: Win32FileSystem.php,v 1.10 2005/05/26 13:10:52 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/system/io/FileSystem.php';
+
+/**
+ * @package phing.system.io
+ */
+class Win32FileSystem extends FileSystem {
+
+ protected $slash;
+ protected $altSlash;
+ protected $semicolon;
+
+ private static $driveDirCache = array();
+
+ function __construct() {
+ $this->slash = self::getSeparator();
+ $this->semicolon = self::getPathSeparator();
+ $this->altSlash = ($this->slash === '\\') ? '/' : '\\';
+ }
+
+ function isSlash($c) {
+ return ($c == '\\') || ($c == '/');
+ }
+
+ function isLetter($c) {
+ return ((ord($c) >= ord('a')) && (ord($c) <= ord('z')))
+ || ((ord($c) >= ord('A')) && (ord($c) <= ord('Z')));
+ }
+
+ function slashify($p) {
+ if ((strlen($p) > 0) && ($p{0} != $this->slash)) {
+ return $this->slash.$p;
+ }
+ else {
+ return $p;
+ }
+ }
+
+ /* -- Normalization and construction -- */
+
+ function getSeparator() {
+ // the ascii value of is the \
+ return chr(92);
+ }
+
+ function getPathSeparator() {
+ return ';';
+ }
+
+ /**
+ * A normal Win32 pathname contains no duplicate slashes, except possibly
+ * for a UNC prefix, and does not end with a slash. It may be the empty
+ * string. Normalized Win32 pathnames have the convenient property that
+ * the length of the prefix almost uniquely identifies the type of the path
+ * and whether it is absolute or relative:
+ *
+ * 0 relative to both drive and directory
+ * 1 drive-relative (begins with '\\')
+ * 2 absolute UNC (if first char is '\\'), else directory-relative (has form "z:foo")
+ * 3 absolute local pathname (begins with "z:\\")
+ */
+ function normalizePrefix($strPath, $len, $sb) {
+ $src = 0;
+ while (($src < $len) && $this->isSlash($strPath{$src})) {
+ $src++;
+ }
+ $c = "";
+ if (($len - $src >= 2)
+ && $this->isLetter($c = $strPath{$src})
+ && $strPath{$src + 1} === ':') {
+ /* Remove leading slashes if followed by drive specifier.
+ * This hack is necessary to support file URLs containing drive
+ * specifiers (e.g., "file://c:/path"). As a side effect,
+ * "/c:/path" can be used as an alternative to "c:/path". */
+ $sb .= $c;
+ $sb .= ':';
+ $src += 2;
+ }
+ else {
+ $src = 0;
+ if (($len >= 2)
+ && $this->isSlash($strPath{0})
+ && $this->isSlash($strPath{1})) {
+ /* UNC pathname: Retain first slash; leave src pointed at
+ * second slash so that further slashes will be collapsed
+ * into the second slash. The result will be a pathname
+ * beginning with "\\\\" followed (most likely) by a host
+ * name. */
+ $src = 1;
+ $sb.=$this->slash;
+ }
+ }
+ return $src;
+ }
+
+ /** Normalize the given pathname, whose length is len, starting at the given
+ offset; everything before this offset is already normal. */
+ protected function normalizer($strPath, $len, $offset) {
+ if ($len == 0) {
+ return $strPath;
+ }
+ if ($offset < 3) {
+ $offset = 0; //Avoid fencepost cases with UNC pathnames
+ }
+ $src = 0;
+ $slash = $this->slash;
+ $sb = "";
+
+ if ($offset == 0) {
+ // Complete normalization, including prefix
+ $src = $this->normalizePrefix($strPath, $len, $sb);
+ } else {
+ // Partial normalization
+ $src = $offset;
+ $sb .= substr($strPath, 0, $offset);
+ }
+
+ // Remove redundant slashes from the remainder of the path, forcing all
+ // slashes into the preferred slash
+ while ($src < $len) {
+ $c = $strPath{$src++};
+ if ($this->isSlash($c)) {
+ while (($src < $len) && $this->isSlash($strPath{$src})) {
+ $src++;
+ }
+ if ($src === $len) {
+ /* Check for trailing separator */
+ $sn = (int) strlen($sb);
+ if (($sn == 2) && ($sb{1} === ':')) {
+ // "z:\\"
+ $sb .= $slash;
+ break;
+ }
+ if ($sn === 0) {
+ // "\\"
+ $sb .= $slash;
+ break;
+ }
+ if (($sn === 1) && ($this->isSlash($sb{0}))) {
+ /* "\\\\" is not collapsed to "\\" because "\\\\" marks
+ the beginning of a UNC pathname. Even though it is
+ not, by itself, a valid UNC pathname, we leave it as
+ is in order to be consistent with the win32 APIs,
+ which treat this case as an invalid UNC pathname
+ rather than as an alias for the root directory of
+ the current drive. */
+ $sb .= $slash;
+ break;
+ }
+ // Path does not denote a root directory, so do not append
+ // trailing slash
+ break;
+ } else {
+ $sb .= $slash;
+ }
+ } else {
+ $sb.=$c;
+ }
+ }
+ $rv = (string) $sb;
+ return $rv;
+ }
+
+ /**
+ * Check that the given pathname is normal. If not, invoke the real
+ * normalizer on the part of the pathname that requires normalization.
+ * This way we iterate through the whole pathname string only once.
+ * @param string $strPath
+ * @return string
+ */
+ function normalize($strPath) {
+ $n = strlen($strPath);
+ $slash = $this->slash;
+ $altSlash = $this->altSlash;
+ $prev = 0;
+ for ($i = 0; $i < $n; $i++) {
+ $c = $strPath{$i};
+ if ($c === $altSlash) {
+ return $this->normalizer($strPath, $n, ($prev === $slash) ? $i - 1 : $i);
+ }
+ if (($c === $slash) && ($prev === $slash) && ($i > 1)) {
+ return $this->normalizer($strPath, $n, $i - 1);
+ }
+ if (($c === ':') && ($i > 1)) {
+ return $this->normalizer($strPath, $n, 0);
+ }
+ $prev = $c;
+ }
+ if ($prev === $slash) {
+ return $this->normalizer($strPath, $n, $n - 1);
+ }
+ return $strPath;
+ }
+
+ function prefixLength($strPath) {
+ $path = (string) $strPath;
+ $slash = (string) $this->slash;
+ $n = (int) strlen($path);
+ if ($n === 0) {
+ return 0;
+ }
+ $c0 = $path{0};
+ $c1 = ($n > 1) ? $path{1} :
+ 0;
+ if ($c0 === $slash) {
+ if ($c1 === $slash) {
+ return 2; // absolute UNC pathname "\\\\foo"
+ }
+ return 1; // drive-relative "\\foo"
+ }
+
+ if ($this->isLetter($c0) && ($c1 === ':')) {
+ if (($n > 2) && ($path{2}) === $slash) {
+ return 3; // Absolute local pathname "z:\\foo" */
+ }
+ return 2; // Directory-relative "z:foo"
+ }
+ return 0; // Completely relative
+ }
+
+ function resolve($parent, $child) {
+ $parent = (string) $parent;
+ $child = (string) $child;
+ $slash = (string) $this->slash;
+
+ $pn = (int) strlen($parent);
+ if ($pn === 0) {
+ return $child;
+ }
+ $cn = (int) strlen($child);
+ if ($cn === 0) {
+ return $parent;
+ }
+
+ $c = $child;
+ if (($cn > 1) && ($c{0} === $slash)) {
+ if ($c{1} === $slash) {
+ // drop prefix when child is a UNC pathname
+ $c = substr($c, 2);
+ }
+ else {
+ //Drop prefix when child is drive-relative */
+ $c = substr($c, 1);
+ }
+ }
+
+ $p = $parent;
+ if ($p{$pn - 1} === $slash) {
+ $p = substr($p, 0, $pn - 1);
+ }
+ return $p.$this->slashify($c);
+ }
+
+ function getDefaultParent() {
+ return (string) ("".$this->slash);
+ }
+
+ function fromURIPath($strPath) {
+ $p = (string) $strPath;
+ if ((strlen($p) > 2) && ($p{2} === ':')) {
+
+ // "/c:/foo" --> "c:/foo"
+ $p = substr($p,1);
+
+ // "c:/foo/" --> "c:/foo", but "c:/" --> "c:/"
+ if ((strlen($p) > 3) && StringHelper::endsWith('/', $p)) {
+ $p = substr($p, 0, strlen($p) - 1);
+ }
+ } elseif ((strlen($p) > 1) && StringHelper::endsWith('/', $p)) {
+ // "/foo/" --> "/foo"
+ $p = substr($p, 0, strlen($p) - 1);
+ }
+ return (string) $p;
+ }
+
+
+ /* -- Path operations -- */
+
+ function isAbsolute(PhingFile $f) {
+ $pl = (int) $f->getPrefixLength();
+ $p = (string) $f->getPath();
+ return ((($pl === 2) && ($p{0} === $this->slash)) || ($pl === 3) || ($pl === 1 && $p{0} === $this->slash));
+ }
+
+ /** private */
+ function _driveIndex($d) {
+ $d = (string) $d{0};
+ if ((ord($d) >= ord('a')) && (ord($d) <= ord('z'))) {
+ return ord($d) - ord('a');
+ }
+ if ((ord($d) >= ord('A')) && (ord($d) <= ord('Z'))) {
+ return ord($d) - ord('A');
+ }
+ return -1;
+ }
+
+ /** private */
+ function _getDriveDirectory($drive) {
+ $drive = (string) $drive{0};
+ $i = (int) $this->_driveIndex($drive);
+ if ($i < 0) {
+ return null;
+ }
+
+ $s = (isset(self::$driveDirCache[$i]) ? self::$driveDirCache[$i] : null);
+
+ if ($s !== null) {
+ return $s;
+ }
+
+ $s = $this->_getDriveDirectory($i + 1);
+ self::$driveDirCache[$i] = $s;
+ return $s;
+ }
+
+ function _getUserPath() {
+ //For both compatibility and security, we must look this up every time
+ return (string) $this->normalize(Phing::getProperty("user.dir"));
+ }
+
+ function _getDrive($path) {
+ $path = (string) $path;
+ $pl = $this->prefixLength($path);
+ return ($pl === 3) ? substr($path, 0, 2) : null;
+ }
+
+ function resolveFile(PhingFile $f) {
+ $path = $f->getPath();
+ $pl = (int) $f->getPrefixLength();
+
+ if (($pl === 2) && ($path{0} === $this->slash)) {
+ return path; // UNC
+ }
+
+ if ($pl === 3) {
+ return $path; // Absolute local
+ }
+
+ if ($pl === 0) {
+ return (string) ($this->_getUserPath().$this->slashify($path)); //Completely relative
+ }
+
+ if ($pl === 1) { // Drive-relative
+ $up = (string) $this->_getUserPath();
+ $ud = (string) $this->_getDrive($up);
+ if ($ud !== null) {
+ return (string) $ud.$path;
+ }
+ return (string) $up.$path; //User dir is a UNC path
+ }
+
+ if ($pl === 2) { // Directory-relative
+ $up = (string) $this->_getUserPath();
+ $ud = (string) $this->_getDrive($up);
+ if (($ud !== null) && StringHelper::startsWith($ud, $path)) {
+ return (string) ($up . $this->slashify(substr($path,2)));
+ }
+ $drive = (string) $path{0};
+ $dir = (string) $this->_getDriveDirectory($drive);
+
+ $np = (string) "";
+ if ($dir !== null) {
+ /* When resolving a directory-relative path that refers to a
+ drive other than the current drive, insist that the caller
+ have read permission on the result */
+ $p = (string) $drive . (':'.$dir.$this->slashify(substr($path,2)));
+
+ if (!$this->checkAccess($p, false)) {
+ // FIXME
+ // throw security error
+ die("Can't resolve path $p");
+ }
+ return $p;
+ }
+ return (string) $drive.':'.$this->slashify(substr($path,2)); //fake it
+ }
+
+ throw new Exception("Unresolvable path: " . $path);
+ }
+
+ /* -- most of the following is mapped to the functions mapped th php natives in FileSystem */
+
+ /* -- Attribute accessors -- */
+
+ function setReadOnly($f) {
+ // dunno how to do this on win
+ throw new Exception("WIN32FileSystem doesn't support read-only yet.");
+ }
+
+ /* -- Filesystem interface -- */
+
+ protected function _access($path) {
+ if (!$this->checkAccess($path, false)) {
+ throw new Exception("Can't resolve path $p");
+ }
+ return true;
+ }
+
+ function _nativeListRoots() {
+ // FIXME
+ }
+
+ function listRoots() {
+ $ds = _nativeListRoots();
+ $n = 0;
+ for ($i = 0; $i < 26; $i++) {
+ if ((($ds >> $i) & 1) !== 0) {
+ if (!$this->access((string)( chr(ord('A') + $i) . ':' . $this->slash))) {
+ $ds &= ~(1 << $i);
+ } else {
+ $n++;
+ }
+ }
+ }
+ $fs = array();
+ $j = (int) 0;
+ $slash = (string) $this->slash;
+ for ($i = 0; $i < 26; $i++) {
+ if ((($ds >> $i) & 1) !== 0) {
+ $fs[$j++] = new PhingFile(chr(ord('A') + $i) . ':' . $this->slash);
+ }
+ }
+ return $fs;
+ }
+
+ /* -- Basic infrastructure -- */
+
+ /** compares file paths lexicographically */
+ function compare(PhingFile $f1, PhingFile $f2) {
+ $f1Path = $f1->getPath();
+ $f2Path = $f2->getPath();
+ return (boolean) strcasecmp((string) $f1Path, (string) $f2Path);
+ }
+
+
+ /**
+ * returns the contents of a directory in an array
+ */
+ function lister($f) {
+ $dir = @opendir($f->getAbsolutePath());
+ if (!$dir) {
+ throw new Exception("Can't open directory " . $f->__toString());
+ }
+ $vv = array();
+ while (($file = @readdir($dir)) !== false) {
+ if ($file == "." || $file == "..") {
+ continue;
+ }
+ $vv[] = (string) $file;
+ }
+ @closedir($dir);
+ return $vv;
+ }
+
+}
+
+?>
diff --git a/buildscripts/phing/classes/phing/system/io/WinNTFileSystem.php b/buildscripts/phing/classes/phing/system/io/WinNTFileSystem.php
new file mode 100644
index 00000000..86f76d80
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/io/WinNTFileSystem.php
@@ -0,0 +1,35 @@
+<?php
+/*
+ * $Id: WinNTFileSystem.php,v 1.3 2003/11/19 05:48:29 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/system/io/Win32FileSystem.php';
+
+/**
+ * FileSystem for Windows NT/2000.
+ * @package phing.system.io
+ */
+
+class WinNTFileSystem extends Win32FileSystem {
+
+ /* -- class only for convenience and future use everything is inherinted --*/
+
+
+}
+?>
diff --git a/buildscripts/phing/classes/phing/system/io/Writer.php b/buildscripts/phing/classes/phing/system/io/Writer.php
new file mode 100644
index 00000000..5e1a69b9
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/io/Writer.php
@@ -0,0 +1,48 @@
+<?php
+/*
+ * $Id: Writer.php,v 1.6 2005/05/26 13:10:52 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * Abstract class for writing character streams.
+ * @package phing.system.io
+ */
+abstract class Writer {
+
+ abstract public function write($buf, $off = null, $len = null);
+
+ abstract public function reset();
+
+ abstract public function close();
+
+ abstract public function open();
+
+ public function mark() {}
+
+ public function ready() {}
+
+ public function markSupported() {}
+
+ /**
+ * Returns the filename, url, etc. that is being written to.
+ * @return string
+ */
+ abstract function getResource();
+}
+?>
diff --git a/buildscripts/phing/classes/phing/system/lang/Character.php b/buildscripts/phing/classes/phing/system/lang/Character.php
new file mode 100644
index 00000000..bb7a5589
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/lang/Character.php
@@ -0,0 +1,49 @@
+<?php
+/*
+ * $Id: Character.php,v 1.3 2003/11/19 05:48:29 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * @package phing.system.lang
+ */
+class Character {
+
+ // this class might be extended with plenty of ordinal char constants
+ // and the like to support the multibyte aware datatype (char) in php
+ // in form of an object.
+ // anyway just a thought
+
+ function isLetter($char) {
+
+ if (strlen($char) !== 1)
+ $char = 0;
+
+ $char = (int) ord($char);
+
+ if ($char >= ord('A') && $char <= ord('Z'))
+ return true;
+
+ if ($char >= ord('a') && $char <= ord('z'))
+ return true;
+
+ return false;
+ }
+
+}
+?>
diff --git a/buildscripts/phing/classes/phing/system/lang/EventObject.php b/buildscripts/phing/classes/phing/system/lang/EventObject.php
new file mode 100644
index 00000000..4a2211bc
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/lang/EventObject.php
@@ -0,0 +1,52 @@
+<?php
+/*
+ * $Id: EventObject.php,v 1.5 2005/02/27 20:52:10 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * @package phing.system.lang
+ */
+class EventObject {
+
+ /** The object on which the Event initially occurred. */
+ protected $source;
+
+ /** Constructs a prototypical Event. */
+ function __construct($source) {
+ if ($source === null) {
+ throw new Exception("Null source");
+ }
+ $this->source = $source;
+ }
+
+ /** The object on which the Event initially occurred. */
+ function getSource() {
+ return $this->source;
+ }
+
+ /** Returns a String representation of this EventObject.*/
+ function toString() {
+ if (method_exists($this->source, "toString")) {
+ return get_class($this)."[source=".$this->source->toString()."]";
+ } else {
+ return get_class($this)."[source=".get_class($this->source)."]";
+ }
+ }
+}
+?>
diff --git a/buildscripts/phing/classes/phing/system/lang/FileNotFoundException.php b/buildscripts/phing/classes/phing/system/lang/FileNotFoundException.php
new file mode 100644
index 00000000..ff48c785
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/lang/FileNotFoundException.php
@@ -0,0 +1,27 @@
+<?php
+/*
+ * $Id: FileNotFoundException.php,v 1.4 2005/02/27 20:52:10 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * @package phing.system.lang
+ */
+class FileNotFoundException extends Exception {}
+
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/system/lang/NullPointerException.php b/buildscripts/phing/classes/phing/system/lang/NullPointerException.php
new file mode 100644
index 00000000..38fa5c10
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/lang/NullPointerException.php
@@ -0,0 +1,27 @@
+<?php
+/*
+ * $Id: NullPointerException.php,v 1.4 2005/02/27 20:52:10 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * @package phing.system.lang
+ */
+class NullPointerException extends Exception {}
+
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/system/lang/SecurityException.php b/buildscripts/phing/classes/phing/system/lang/SecurityException.php
new file mode 100644
index 00000000..21e8b1c3
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/lang/SecurityException.php
@@ -0,0 +1,27 @@
+<?php
+/*
+ * $Id: SecurityException.php,v 1.4 2005/02/27 20:52:10 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * @package phing.system.lang
+ */
+class SecurityException extends Exception {}
+
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/system/util/Message.php b/buildscripts/phing/classes/phing/system/util/Message.php
new file mode 100644
index 00000000..bf7bb56b
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/util/Message.php
@@ -0,0 +1,9 @@
+<?php
+//
+// FIXME. Logger will be renamed to Message, new level is introduces MSG_NOTICE
+// Message can handle some more later on
+// - formatted output
+// - sending to dialog or phpgtk whatever
+// - etc
+//
+?>
diff --git a/buildscripts/phing/classes/phing/system/util/Properties.php b/buildscripts/phing/classes/phing/system/util/Properties.php
new file mode 100644
index 00000000..deff2cdf
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/util/Properties.php
@@ -0,0 +1,270 @@
+<?php
+
+/*
+ * $Id: Properties.php,v 1.13 2005/05/26 13:10:52 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/system/io/PhingFile.php';
+include_once 'phing/system/io/FileWriter.php';
+
+/**
+ * Convenience class for reading and writing property files.
+ *
+ * FIXME
+ * - Add support for arrays (separated by ',')
+ *
+ * @package phing.system.util
+ * @version $Revision: 1.13 $
+ */
+class Properties {
+
+ private $properties = array();
+
+ /**
+ * Load properties from a file.
+ *
+ * @param PhingFile $file
+ * @return void
+ * @throws IOException - if unable to read file.
+ */
+ function load(PhingFile $file) {
+ if ($file->canRead()) {
+ $this->parse($file->getPath(), false);
+ } else {
+ throw new IOException("Can not read file ".$file->getPath());
+ }
+
+ }
+
+ /**
+ * Replaces parse_ini_file() or better_parse_ini_file().
+ * Saves a step since we don't have to parse and then check return value
+ * before throwing an error or setting class properties.
+ *
+ * @param string $filePath
+ * @param boolean $processSections Whether to honor [SectionName] sections in INI file.
+ * @return array Properties loaded from file (no prop replacements done yet).
+ */
+ protected function parse($filePath) {
+
+ // load() already made sure that file is readable
+ // but we'll double check that when reading the file into
+ // an array
+
+ if (($lines = @file($filePath)) === false) {
+ throw new IOException("Unable to parse contents of $filePath");
+ }
+
+ $this->properties = array();
+ $sec_name = "";
+
+ foreach($lines as $line) {
+
+ $line = trim($line);
+
+ if($line == "")
+ continue;
+
+ if ($line{0} == '#' or $line{0} == ';') {
+ // it's a comment, so continue to next line
+ continue;
+ } else {
+ $pos = strpos($line, '=');
+ $property = trim(substr($line, 0, $pos));
+ $value = trim(substr($line, $pos + 1));
+ $this->properties[$property] = $this->inVal($value);
+ }
+
+ } // for each line
+ }
+
+ /**
+ * Process values when being read in from properties file.
+ * does things like convert "true" => true
+ * @param string $val Trimmed value.
+ * @return mixed The new property value (may be boolean, etc.)
+ */
+ protected function inVal($val) {
+ if ($val === "true") {
+ $val = true;
+ } elseif ($val === "false") {
+ $val = false;
+ }
+ return $val;
+ }
+
+ /**
+ * Process values when being written out to properties file.
+ * does things like convert true => "true"
+ * @param mixed $val The property value (may be boolean, etc.)
+ * @return string
+ */
+ protected function outVal($val) {
+ if ($val === true) {
+ $val = "true";
+ } elseif ($val === false) {
+ $val = "false";
+ }
+ return $val;
+ }
+
+ /**
+ * Create string representation that can be written to file and would be loadable using load() method.
+ *
+ * Essentially this function creates a string representation of properties that is ready to
+ * write back out to a properties file. This is used by store() method.
+ *
+ * @return string
+ */
+ public function toString() {
+ $buf = "";
+ foreach($this->properties as $key => $item) {
+ $buf .= $key . "=" . $this->outVal($item) . Phing::getProperty('line.separator');
+ }
+ return $buf;
+ }
+
+ /**
+ * Stores current properties to specified file.
+ *
+ * @param PhingFile $file File to create/overwrite with properties.
+ * @param string $header Header text that will be placed (within comments) at the top of properties file.
+ * @return void
+ * @throws IOException - on error writing properties file.
+ */
+ function store(PhingFile $file, $header = null) {
+ // stores the properties in this object in the file denoted
+ // if file is not given and the properties were loaded from a
+ // file prior, this method stores them in the file used by load()
+ try {
+ $fw = new FileWriter($file);
+ $fw->open();
+ if ($header !== null) {
+ $fw->write( "# " . $header . Phing::getProperty("line.separator") );
+ }
+ $fw->write($this->toString());
+ $fw->close();
+ } catch (IOException $e) {
+ throw new IOException("Error writing property file: " . $e->getMessage());
+ }
+ }
+
+ /**
+ * Returns copy of internal properties hash.
+ * Mostly for performance reasons, property hashes are often
+ * preferable to passing around objects.
+ *
+ * @return array
+ */
+ function getProperties() {
+ return $this->properties;
+ }
+
+ /**
+ * Get value for specified property.
+ * This is the same as get() method.
+ *
+ * @param string $prop The property name (key).
+ * @return mixed
+ * @see get()
+ */
+ function getProperty($prop) {
+ if (!isset($this->properties[$prop])) {
+ return null;
+ }
+ return $this->properties[$prop];
+ }
+
+ /**
+ * Get value for specified property.
+ * This function exists to provide a hashtable-like interface for
+ * properties.
+ *
+ * @param string $prop The property name (key).
+ * @return mixed
+ * @see getProperty()
+ */
+ function get($prop) {
+ if (!isset($this->properties[$prop])) {
+ return null;
+ }
+ return $this->properties[$prop];
+ }
+
+ /**
+ * Set the value for a property.
+ *
+ * @param string $key
+ * @param mixed $value
+ * @return mixed Old property value or NULL if none was set.
+ */
+ function setProperty($key, $value) {
+ $oldValue = @$this->properties[$key];
+ $this->properties[$key] = $value;
+ return $oldValue;
+ }
+
+ /**
+ * Set the value for a property.
+ * This function exists to provide hashtable-lie
+ * interface for properties.
+ *
+ * @param string $key
+ * @param mixed $value
+ */
+ function put($key, $value) {
+ return $this->setProperty($key, $value);
+ }
+
+ /**
+ * Same as keys() function, returns an array of property names.
+ * @return array
+ */
+ function propertyNames() {
+ return $this->keys();
+ }
+
+ /**
+ * Whether loaded properties array contains specified property name.
+ * @return boolean
+ */
+ function containsKey($key) {
+ return isset($this->properties[$key]);
+ }
+
+ /**
+ * Returns properties keys.
+ * Use this for foreach() {} iterations, as this is
+ * faster than looping through property values.
+ * @return array
+ */
+ function keys() {
+ return array_keys($this->properties);
+ }
+
+ /**
+ * Whether properties list is empty.
+ * @return boolean
+ */
+ function isEmpty() {
+ return empty($this->properties);
+ }
+
+}
+?>
diff --git a/buildscripts/phing/classes/phing/system/util/Register.php b/buildscripts/phing/classes/phing/system/util/Register.php
new file mode 100644
index 00000000..5ef2b2fd
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/util/Register.php
@@ -0,0 +1,115 @@
+<?php
+
+/**
+ * Static class to handle a slot-listening system.
+ *
+ * Unlike the slots/signals Qt model, this class manages something that is
+ * more like a simple hashtable, where each slot has only one value. For that
+ * reason "Registers" makes more sense, the reference being to CPU registers.
+ *
+ * This could be used for anything, but it's been built for a pretty specific phing
+ * need, and that is to allow access to dynamic values that are set by logic
+ * that is not represented in a build file. For exampe, we need a system for getting
+ * the current resource (file) that is being processed by a filterchain in a fileset.
+ *
+ * Each slot corresponds to only one read-only, dynamic-value RegisterSlot object. In
+ * a build.xml register slots are expressed using a syntax similar to variables:
+ *
+ * <replaceregexp>
+ * <regexp pattern="\n" replace="%{task.current_file}"/>
+ * </replaceregexp>
+ *
+ * The task/type must provide a supporting setter for the attribute:
+ *
+ * <code>
+ * function setListeningReplace(RegisterSlot $slot) {
+ * $this->replace = $slot;
+ * }
+ *
+ * // in main()
+ * if ($this->replace instanceof RegisterSlot) {
+ * $this->regexp->setReplace($this->replace->getValue());
+ * } else {
+ * $this->regexp->setReplace($this->replace);
+ * }
+ * </code>
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.3 $
+ * @package phing.system.util
+ */
+class Register {
+
+ /** Slots that have been registered */
+ private static $slots = array();
+
+ /**
+ * Returns RegisterSlot for specified key.
+ *
+ * If not slot exists a new one is created for key.
+ *
+ * @param string $key
+ * @return RegisterSlot
+ */
+ public static function getSlot($key) {
+ if (!isset(self::$slots[$key])) {
+ self::$slots[$key] = new RegisterSlot($key);
+ }
+ return self::$slots[$key];
+ }
+}
+
+
+/**
+ * Represents a slot in the register.
+ */
+class RegisterSlot {
+
+ /** The name of this slot. */
+ private $key;
+
+ /** The value for this slot. */
+ private $value;
+
+ /**
+ * Constructs a new RegisterSlot, setting the key to passed param.
+ * @param string $key
+ */
+ public function __construct($key) {
+ $this->key = (string) $key;
+ }
+
+ /**
+ * Sets the key / name for this slot.
+ * @param string $k
+ */
+ public function setKey($k) {
+ $this->key = (string) $k;
+ }
+
+ /**
+ * Gets the key / name for this slot.
+ * @return string
+ */
+ public function getKey() {
+ return $this->key;
+ }
+
+ /**
+ * Sets the value for this slot.
+ * @param mixed
+ */
+ public function setValue($v) {
+ $this->value = $v;
+ }
+
+ /**
+ * Returns the value at this slot.
+ * @return mixed
+ */
+ public function getValue() {
+ return $this->value;
+ }
+
+}
+?>
diff --git a/buildscripts/phing/classes/phing/system/util/Timer.php b/buildscripts/phing/classes/phing/system/util/Timer.php
new file mode 100644
index 00000000..a2a665b0
--- /dev/null
+++ b/buildscripts/phing/classes/phing/system/util/Timer.php
@@ -0,0 +1,96 @@
+<?php
+/*
+ * $Id: Timer.php,v 1.5 2003/12/24 13:02:09 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+
+/**
+ * This class can be used to obtain the execution time of all of the scripts
+ * that are executed in the process of building a page.
+ *
+ * Example:
+ * To be done before any scripts execute:
+ *
+ * $Timer = new Timer;
+ * $Timer->Start_Timer();
+ *
+ * To be done after all scripts have executed:
+ *
+ * $timer->Stop_Timer();
+ * $timer->Get_Elapsed_Time(int number_of_places);
+ *
+ * @author Charles Killian
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @package phing.system.util
+ * @version $Revision: 1.5 $ $Date: 2003/12/24 13:02:09 $
+ */
+class Timer {
+
+ /** start time */
+ protected $stime;
+
+ /** end time */
+ protected $etime;
+
+ /**
+ * This function sets the class variable $stime to the current time in
+ * microseconds.
+ * @return void
+ */
+ public function start() {
+ $this->stime = $this->getMicrotime();
+ }
+
+ /**
+ * This function sets the class variable $etime to the current time in
+ * microseconds.
+ * @return void
+ */
+ function stop() {
+ $this->etime = $this->getMicrotime();
+ }
+
+ /**
+ * This function returns the elapsed time in seconds.
+ *
+ * Call start_time() at the beginning of script execution and end_time() at
+ * the end of script execution. Then, call elapsed_time() to obtain the
+ * difference between start_time() and end_time().
+ *
+ * @param $places decimal place precision of elapsed time (default is 5)
+ * @return string Properly formatted time.
+ */
+ function getElapsedTime($places=5) {
+ $etime = $this->etime - $this->stime;
+ $format = "%0.".$places."f";
+ return (sprintf ($format, $etime));
+ }
+
+ /**
+ * This function returns the current time in microseconds.
+ *
+ * @author Everett Michaud, Zend.com
+ * @return current time in microseconds
+ * @access private
+ */
+ function getMicrotime() {
+ list($usec, $sec) = explode(" ", microtime());
+ return ((float)$usec + (float)$sec);
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/defaults.properties b/buildscripts/phing/classes/phing/tasks/defaults.properties
new file mode 100644
index 00000000..d0e62eff
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/defaults.properties
@@ -0,0 +1,69 @@
+; -------------------------------------
+; These taskdefs are loaded at startup.
+; -------------------------------------
+
+; Internal system tasks
+;
+adhoc=phing.tasks.system.AdhocTask
+adhoc-task=phing.tasks.system.AdhocTaskdefTask
+adhoc-type=phing.tasks.system.AdhocTypedefTask
+append=phing.tasks.system.AppendTask
+available=phing.tasks.system.AvailableTask
+chmod=phing.tasks.system.ChmodTask
+condition=phing.tasks.system.ConditionTask
+copy=phing.tasks.system.CopyTask
+cvs=phing.tasks.system.CvsTask
+cvspass=phing.tasks.system.CvsPassTask
+delete=phing.tasks.system.DeleteTask
+echo=phing.tasks.system.EchoTask
+exec=phing.tasks.system.ExecTask
+fail=phing.tasks.system.ExitTask
+foreach=phing.tasks.system.ForeachTask
+includepath=phing.tasks.system.IncludePathTask
+input=phing.tasks.system.InputTask
+mkdir=phing.tasks.system.MkdirTask
+move=phing.tasks.system.MoveTask
+phing=phing.tasks.system.PhingTask
+phingcall=phing.tasks.system.PhingCallTask
+php=phing.tasks.system.PhpEvalTask
+property=phing.tasks.system.PropertyTask
+propertyprompt=phing.tasks.system.PropertyPromptTask
+reflexive=phing.tasks.system.ReflexiveTask
+resolvepath=phing.tasks.system.ResolvePathTask
+taskdef=phing.tasks.system.TaskdefTask
+touch=phing.tasks.system.TouchTask
+tstamp=phing.tasks.system.TstampTask
+typedef=phing.tasks.system.TypedefTask
+uptodate=phing.tasks.system.UpToDateTask
+xslt=phing.tasks.system.XsltTask
+if=phing.tasks.system.IfTask
+warn=phing.tasks.system.WarnTask
+
+; "Core" contributed tasks
+; -- i.e. no taskdef needed.
+
+sql=phing.tasks.ext.CreoleSQLExecTask
+package-as-path=phing.tasks.ext.PackageAsPathTask
+smarty=phing.tasks.ext.SmartyTask
+capsule=phing.tasks.ext.CapsuleTask
+tar=phing.tasks.ext.TarTask
+pearpkg=phing.tasks.ext.PearPackageTask
+mail=phing.tasks.ext.MailTask
+zip=phing.tasks.ext.ZipTask
+phplint=phing.tasks.ext.PhpLintTask
+
+; "ext" tasks
+phpdoc=phing.tasks.ext.phpdoc.PHPDocumentorTask
+svnlastrevision=phing.tasks.ext.svn.SvnLastRevisionTask
+svnexport=phing.tasks.ext.svn.SvnExportTask
+phpunit2=phing.tasks.ext.phpunit2.PHPUnit2Task
+phpunit2report=phing.tasks.ext.phpunit2.PHPUnit2ReportTask
+coverage-setup=phing.tasks.ext.coverage.CoverageSetupTask
+coverage-merger=phing.tasks.ext.coverage.CoverageMergerTask
+coverage-report=phing.tasks.ext.coverage.CoverageReportTask
+ioncubeencoder=phing.tasks.ext.ioncube.IoncubeEncoderTask
+ioncubelicense=phing.tasks.ext.ioncube.IoncubeLicenseTask
+simpletest=phing.tasks.ext.simpletest.SimpleTestTask
+phplint=phing.tasks.ext.PhpLintTask
+xmllint=phing.tasks.ext.XmlLintTask
+analyze=phing.tasks.ext.ZendCodeAnalyzerTask \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/CapsuleTask.php b/buildscripts/phing/classes/phing/tasks/ext/CapsuleTask.php
new file mode 100644
index 00000000..aa43a0e4
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/CapsuleTask.php
@@ -0,0 +1,478 @@
+<?php
+
+/*
+ * $Id: CapsuleTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/Task.php';
+include_once 'phing/BuildException.php';
+include_once 'phing/lib/Capsule.php';
+include_once 'phing/util/StringHelper.php';
+
+/**
+ * A phing task for generating output by using Capsule.
+ *
+ * This is based on the interface to TexenTask from Apache's Velocity engine.
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.17 $
+ * @package phing.tasks.ext
+ */
+class CapsuleTask extends Task {
+
+ /**
+ * Capsule "template" engine.
+ * @var Capsule
+ */
+ protected $context;
+
+ /**
+ * Any vars assigned via the build file.
+ * @var array AssignedVar[]
+ */
+ protected $assignedVars = array();
+
+ /**
+ * This is the control template that governs the output.
+ * It may or may not invoke the services of worker
+ * templates.
+ * @var string
+ */
+ protected $controlTemplate;
+
+ /**
+ * This is where Velocity will look for templates
+ * using the file template loader.
+ * @var string
+ */
+ protected $templatePath;
+
+ /**
+ * This is where texen will place all the output
+ * that is a product of the generation process.
+ * @var string
+ */
+ protected $outputDirectory;
+
+ /**
+ * This is the file where the generated text
+ * will be placed.
+ * @var string
+ */
+ protected $outputFile;
+
+ /**
+ * <p>
+ * These are properties that are fed into the
+ * initial context from a properties file. This
+ * is simply a convenient way to set some values
+ * that you wish to make available in the context.
+ * </p>
+ * <p>
+ * These values are not critical, like the template path
+ * or output path, but allow a convenient way to
+ * set a value that may be specific to a particular
+ * generation task.
+ * </p>
+ * <p>
+ * For example, if you are generating scripts to allow
+ * user to automatically create a database, then
+ * you might want the <code>$databaseName</code>
+ * to be placed
+ * in the initial context so that it is available
+ * in a script that might look something like the
+ * following:
+ * <code><pre>
+ * #!bin/sh
+ *
+ * echo y | mysqladmin create $databaseName
+ * </pre></code>
+ * The value of <code>$databaseName</code> isn't critical to
+ * output, and you obviously don't want to change
+ * the ant task to simply take a database name.
+ * So initial context values can be set with
+ * properties file.
+ *
+ * @var array
+ */
+ protected $contextProperties;
+
+ // -----------------------------------------------------------------------
+ // The following getters & setters are used by phing to set properties
+ // specified in the XML for the capsule task.
+ // -----------------------------------------------------------------------
+
+ /**
+ * [REQUIRED] Set the control template for the
+ * generating process.
+ * @param string $controlTemplate
+ * @return void
+ */
+ public function setControlTemplate ($controlTemplate) {
+ $this->controlTemplate = $controlTemplate;
+ }
+
+ /**
+ * Get the control template for the
+ * generating process.
+ * @return string
+ */
+ public function getControlTemplate() {
+ return $this->controlTemplate;
+ }
+
+ /**
+ * [REQUIRED] Set the path where Velocity will look
+ * for templates using the file template
+ * loader.
+ * @return void
+ * @throws Exception
+ */
+ public function setTemplatePath($templatePath) {
+ $resolvedPath = "";
+ $tok = strtok($templatePath, ",");
+ while ( $tok ) {
+ // resolve relative path from basedir and leave
+ // absolute path untouched.
+ $fullPath = $this->project->resolveFile($tok);
+ $cpath = $fullPath->getCanonicalPath();
+ if ($cpath === false) {
+ $this->log("Template directory does not exist: " . $fullPath->getAbsolutePath());
+ } else {
+ $resolvedPath .= $cpath;
+ }
+ $tok = strtok(",");
+ if ( $tok ) {
+ $resolvedPath .= ",";
+ }
+ }
+ $this->templatePath = $resolvedPath;
+ }
+
+ /**
+ * Get the path where Velocity will look
+ * for templates using the file template
+ * loader.
+ * @return string
+ */
+ public function getTemplatePath() {
+ return $this->templatePath;
+ }
+
+ /**
+ * [REQUIRED] Set the output directory. It will be
+ * created if it doesn't exist.
+ * @param PhingFile $outputDirectory
+ * @return void
+ * @throws Exception
+ */
+ public function setOutputDirectory(PhingFile $outputDirectory) {
+ try {
+ if (!$outputDirectory->exists()) {
+ $this->log("Output directory does not exist, creating: " . $outputDirectory->getPath(),PROJECT_MSG_VERBOSE);
+ if (!$outputDirectory->mkdirs()) {
+ throw new IOException("Unable to create Ouptut directory: " . $outputDirectory->getAbsolutePath());
+ }
+ }
+ $this->outputDirectory = $outputDirectory->getCanonicalPath();
+ } catch (IOException $ioe) {
+ throw new BuildException($ioe);
+ }
+ }
+
+ /**
+ * Get the output directory.
+ * @return string
+ */
+ public function getOutputDirectory() {
+ return $this->outputDirectory;
+ }
+
+ /**
+ * [REQUIRED] Set the output file for the
+ * generation process.
+ * @param string $outputFile (TODO: change this to File)
+ * @return void
+ */
+ public function setOutputFile($outputFile) {
+ $this->outputFile = $outputFile;
+ }
+
+ /**
+ * Get the output file for the
+ * generation process.
+ * @return string
+ */
+ public function getOutputFile() {
+ return $this->outputFile;
+ }
+
+ /**
+ * Set the context properties that will be
+ * fed into the initial context be the
+ * generating process starts.
+ * @param string $file
+ * @return void
+ */
+ public function setContextProperties($file) {
+ $sources = explode(",", $file);
+ $this->contextProperties = new Properties();
+
+ // Always try to get the context properties resource
+ // from a file first. Templates may be taken from a JAR
+ // file but the context properties resource may be a
+ // resource in the filesystem. If this fails than attempt
+ // to get the context properties resource from the
+ // classpath.
+ for ($i=0, $sourcesLength=count($sources); $i < $sourcesLength; $i++) {
+ $source = new Properties();
+
+ try {
+
+ // resolve relative path from basedir and leave
+ // absolute path untouched.
+ $fullPath = $this->project->resolveFile($sources[$i]);
+ $this->log("Using contextProperties file: " . $fullPath->toString());
+ $source->load($fullPath);
+
+ } catch (Exception $e) {
+
+ throw new BuildException("Context properties file " . $sources[$i] .
+ " could not be found in the file system!");
+
+ }
+
+ $keys = $source->keys();
+
+ foreach ($keys as $key) {
+ $name = $key;
+ $value = $this->project->replaceProperties($source->getProperty($name));
+ $this->contextProperties->setProperty($name, $value);
+ }
+ }
+ }
+
+ /**
+ * Get the context properties that will be
+ * fed into the initial context be the
+ * generating process starts.
+ * @return Properties
+ */
+ public function getContextProperties() {
+ return $this->contextProperties;
+ }
+
+ /**
+ * Creates an "AssignedVar" class.
+ */
+ public function createAssign() {
+ $a = new AssignedVar();
+ $this->assignedVars[] = $a;
+ return $a;
+ }
+
+ // ---------------------------------------------------------------
+ // End of XML setters & getters
+ // ---------------------------------------------------------------
+
+ /**
+ * Creates a Smarty object.
+ *
+ * @return Smarty initialized (cleared) Smarty context.
+ * @throws Exception the execute method will catch
+ * and rethrow as a <code>BuildException</code>
+ */
+ public function initControlContext() {
+ $this->context->clear();
+ foreach($this->assignedVars as $var) {
+ $this->context->put($var->getName(), $var->getValue());
+ }
+ return $this->context;
+ }
+
+ /**
+ * Execute the input script with Velocity
+ *
+ * @throws BuildException
+ * BuildExceptions are thrown when required attributes are missing.
+ * Exceptions thrown by Velocity are rethrown as BuildExceptions.
+ */
+ public function main() {
+
+ // Make sure the template path is set.
+ if (empty($this->templatePath)) {
+ throw new BuildException("The template path needs to be defined!");
+ }
+
+ // Make sure the control template is set.
+ if ($this->controlTemplate === null) {
+ throw new BuildException("The control template needs to be defined!");
+ }
+
+ // Make sure the output directory is set.
+ if ($this->outputDirectory === null) {
+ throw new BuildException("The output directory needs to be defined!");
+ }
+
+ // Make sure there is an output file.
+ if ($this->outputFile === null) {
+ throw new BuildException("The output file needs to be defined!");
+ }
+
+ // Setup Smarty runtime.
+
+ // Smarty uses one object to store properties and to store
+ // the context for the template (unlike Velocity). We setup this object, calling it
+ // $this->context, and then initControlContext simply zeros out
+ // any assigned variables.
+ $this->context = new Capsule();
+
+ if ($this->templatePath !== null) {
+ $this->log("Using templatePath: " . $this->templatePath);
+ $this->context->setTemplatePath($this->templatePath);
+ }
+
+ // Make sure the output directory exists, if it doesn't
+ // then create it.
+ $outputDir = new PhingFile($this->outputDirectory);
+ if (!$outputDir->exists()) {
+ $this->log("Output directory does not exist, creating: " . $outputDir->getAbsolutePath());
+ $outputDir->mkdirs();
+ }
+
+ $this->context->setOutputDirectory($outputDir->getAbsolutePath());
+
+ $path = $this->outputDirectory . DIRECTORY_SEPARATOR . $this->outputFile;
+ $this->log("Generating to file " . $path);
+
+ //$writer = new FileWriter($path);
+
+ // The generator and the output path should
+ // be placed in the init context here and
+ // not in the generator class itself.
+ $c = $this->initControlContext();
+
+ // Set any variables that need to always
+ // be loaded
+ $this->populateInitialContext($c);
+
+ // Feed all the options into the initial
+ // control context so they are available
+ // in the control/worker templates.
+ if ($this->contextProperties !== null) {
+
+ foreach($this->contextProperties->keys() as $property) {
+
+ $value = $this->contextProperties->getProperty($property);
+
+ // Special exception (from Texen)
+ // for properties ending in file.contents:
+ // in that case we dump the contents of the file
+ // as the "value" for the Property.
+ if (preg_match('/file\.contents$/', $property)) {
+ // pull in contents of file specified
+
+ $property = substr($property, 0, strpos($property, "file.contents") - 1);
+
+ // reset value, and then
+ // read in teh contents of the file into that var
+ $value = "";
+ $f = new PhingFile($project->resolveFile($value)->getCanonicalPath());
+ if ($f->exists()) {
+ $fr = new FileReader($f);
+ $fr->readInto($value);
+ }
+
+ } // if ends with file.contents
+
+ if (StringHelper::isBoolean($value)) {
+ $value = StringHelper::booleanValue($value);
+ }
+
+ $c->put($property, $value);
+
+ } // foreach property
+
+ } // if contextProperties !== null
+
+ try {
+ $this->log("Parsing control template: " . $this->controlTemplate);
+ $c->parse($this->controlTemplate, $path);
+ } catch (Exception $ioe) {
+ throw new BuildException("Cannot write parsed template: ". $ioe->getMessage());
+ }
+
+ $this->cleanup();
+ }
+
+ /**
+ * Place useful objects into the initial context.
+ *
+ *
+ * @param Capsule $context The context to populate, as retrieved from
+ * {@link #initControlContext()}.
+ * @return void
+ * @throws Exception Error while populating context. The {@link
+ * #main()} method will catch and rethrow as a
+ * <code>BuildException</code>.
+ */
+ protected function populateInitialContext(Capsule $context) {
+ $this->context->put("now", strftime("%c", time()));
+ $this->context->put("task", $this);
+ }
+
+ /**
+ * A hook method called at the end of {@link #execute()} which can
+ * be overridden to perform any necessary cleanup activities (such
+ * as the release of database connections, etc.). By default,
+ * does nothing.
+ * @return void
+ * @throws Exception Problem cleaning up.
+ */
+ protected function cleanup() {
+ }
+}
+
+
+/**
+ * An "inner" class for holding assigned var values.
+ * May be need to expand beyond name/value in the future.
+ */
+class AssignedVar {
+
+ private $name;
+ private $value;
+
+ function setName($v) {
+ $this->name = $v;
+ }
+
+ function setValue($v) {
+ $this->value = $v;
+ }
+
+ function getName() {
+ return $this->name;
+ }
+
+ function getValue() {
+ return $this->value;
+ }
+
+} \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/CreoleSQLExecTask.php b/buildscripts/phing/classes/phing/tasks/ext/CreoleSQLExecTask.php
new file mode 100644
index 00000000..d35e44f4
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/CreoleSQLExecTask.php
@@ -0,0 +1,556 @@
+<?php
+/*
+ * $Id: CreoleSQLExecTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/tasks/ext/CreoleTask.php';
+include_once 'phing/system/io/StringReader.php';
+
+/**
+ * Executes a series of SQL statements on a database using Creole.
+ *
+ * <p>Statements can
+ * either be read in from a text file using the <i>src</i> attribute or from
+ * between the enclosing SQL tags.</p>
+ *
+ * <p>Multiple statements can be provided, separated by semicolons (or the
+ * defined <i>delimiter</i>). Individual lines within the statements can be
+ * commented using either --, // or REM at the start of the line.</p>
+ *
+ * <p>The <i>autocommit</i> attribute specifies whether auto-commit should be
+ * turned on or off whilst executing the statements. If auto-commit is turned
+ * on each statement will be executed and committed. If it is turned off the
+ * statements will all be executed as one transaction.</p>
+ *
+ * <p>The <i>onerror</i> attribute specifies how to proceed when an error occurs
+ * during the execution of one of the statements.
+ * The possible values are: <b>continue</b> execution, only show the error;
+ * <b>stop</b> execution and commit transaction;
+ * and <b>abort</b> execution and transaction and fail task.</p>
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Jeff Martin <jeff@custommonkey.org> (Ant)
+ * @author Michael McCallum <gholam@xtra.co.nz> (Ant)
+ * @author Tim Stephenson <tim.stephenson@sybase.com> (Ant)
+ * @package phing.tasks.ext
+ * @version $Revision: 1.21 $
+ */
+class CreoleSQLExecTask extends CreoleTask {
+
+ private $goodSql = 0;
+ private $totalSql = 0;
+
+ const DELIM_ROW = "row";
+ const DELIM_NORMAL = "normal";
+
+ /**
+ * Database connection
+ */
+ private $conn = null;
+
+ /**
+ * files to load
+ */
+ private $filesets = array();
+
+ /**
+ * SQL statement
+ */
+ private $statement = null;
+
+ /**
+ * SQL input file
+ */
+ private $srcFile = null;
+
+ /**
+ * SQL input command
+ */
+ private $sqlCommand = "";
+
+ /**
+ * SQL transactions to perform
+ */
+ private $transactions = array();
+
+ /**
+ * SQL Statement delimiter
+ */
+ private $delimiter = ";";
+
+ /**
+ * The delimiter type indicating whether the delimiter will
+ * only be recognized on a line by itself
+ */
+ private $delimiterType = "normal"; // can't use constant just defined
+
+ /**
+ * Print SQL results.
+ */
+ private $print = false;
+
+ /**
+ * Print header columns.
+ */
+ private $showheaders = true;
+
+ /**
+ * Results Output file.
+ */
+ private $output = null;
+
+
+ /**
+ * Action to perform if an error is found
+ **/
+ private $onError = "abort";
+
+ /**
+ * Encoding to use when reading SQL statements from a file
+ */
+ private $encoding = null;
+
+ /**
+ * Append to an existing file or overwrite it?
+ */
+ private $append = false;
+
+ /**
+ * Set the name of the SQL file to be run.
+ * Required unless statements are enclosed in the build file
+ */
+ public function setSrc(PhingFile $srcFile) {
+ $this->srcFile = $srcFile;
+ }
+
+ /**
+ * Set an inline SQL command to execute.
+ * NB: Properties are not expanded in this text.
+ */
+ public function addText($sql) {
+ $this->sqlCommand .= $sql;
+ }
+
+ /**
+ * Adds a set of files (nested fileset attribute).
+ */
+ public function addFileset(FileSet $set) {
+ $this->filesets[] = $set;
+ }
+
+ /**
+ * Add a SQL transaction to execute
+ */
+ public function createTransaction() {
+ $t = new SQLExecTransaction($this);
+ $this->transactions[] = $t;
+ return $t;
+ }
+
+ /**
+ * Set the file encoding to use on the SQL files read in
+ *
+ * @param encoding the encoding to use on the files
+ */
+ public function setEncoding($encoding) {
+ $this->encoding = $encoding;
+ }
+
+ /**
+ * Set the statement delimiter.
+ *
+ * <p>For example, set this to "go" and delimitertype to "ROW" for
+ * Sybase ASE or MS SQL Server.</p>
+ *
+ * @param delimiter
+ */
+ public function setDelimiter($delimiter)
+ {
+ $this->delimiter = $delimiter;
+ }
+
+ /**
+ * Set the Delimiter type for this sql task. The delimiter type takes two
+ * values - normal and row. Normal means that any occurence of the delimiter
+ * terminate the SQL command whereas with row, only a line containing just
+ * the delimiter is recognized as the end of the command.
+ *
+ * @param string $delimiterType
+ */
+ public function setDelimiterType($delimiterType)
+ {
+ $this->delimiterType = $delimiterType;
+ }
+
+ /**
+ * Set the print flag.
+ *
+ * @param boolean $print
+ */
+ public function setPrint($print)
+ {
+ $this->print = (boolean) $print;
+ }
+
+ /**
+ * Print headers for result sets from the
+ * statements; optional, default true.
+ * @param boolean $showheaders
+ */
+ public function setShowheaders($showheaders) {
+ $this->showheaders = (boolean) $showheaders;
+ }
+
+ /**
+ * Set the output file;
+ * optional, defaults to the console.
+ * @param PhingFile $output
+ */
+ public function setOutput(PhingFile $output) {
+ $this->output = $output;
+ }
+
+ /**
+ * whether output should be appended to or overwrite
+ * an existing file. Defaults to false.
+ * @param $append
+ */
+ public function setAppend($append) {
+ $this->append = (boolean) $append;
+ }
+
+
+ /**
+ * Action to perform when statement fails: continue, stop, or abort
+ * optional; default &quot;abort&quot;
+ */
+ public function setOnerror($action) {
+ $this->onError = $action;
+ }
+
+ /**
+ * Load the sql file and then execute it
+ * @throws BuildException
+ */
+ public function main() {
+
+ $savedTransaction = array();
+ for($i=0,$size=count($this->transactions); $i < $size; $i++) {
+ $savedTransaction[] = clone $this->transactions[$i];
+ }
+
+ $savedSqlCommand = $this->sqlCommand;
+
+ $this->sqlCommand = trim($this->sqlCommand);
+
+ try {
+ if ($this->srcFile === null && $this->sqlCommand === ""
+ && empty($this->filesets)) {
+ if (count($this->transactions) === 0) {
+ throw new BuildException("Source file or fileset, "
+ . "transactions or sql statement "
+ . "must be set!", $this->location);
+ }
+ }
+
+ if ($this->srcFile !== null && !$this->srcFile->exists()) {
+ throw new BuildException("Source file does not exist!", $this->location);
+ }
+
+ // deal with the filesets
+ for ($i = 0,$size=count($this->filesets); $i < $size; $i++) {
+ $fs = $this->filesets[$i];
+ $ds = $fs->getDirectoryScanner($this->project);
+ $srcDir = $fs->getDir($this->project);
+
+ $srcFiles = $ds->getIncludedFiles();
+
+ // Make a transaction for each file
+ for ($j=0, $size=count($srcFiles); $j < $size; $j++) {
+ $t = $this->createTransaction();
+ $t->setSrc(new PhingFile($srcDir, $srcFiles[$j]));
+ }
+ }
+
+ // Make a transaction group for the outer command
+ $t = $this->createTransaction();
+ if ($this->srcFile) $t->setSrc($this->srcFile);
+ $t->addText($this->sqlCommand);
+ $this->conn = $this->getConnection();
+
+ try {
+
+ $this->statement = $this->conn->createStatement();
+
+ $out = null;
+
+ try {
+
+ if ($this->output !== null) {
+ $this->log("Opening output file " . $this->output, PROJECT_MSG_VERBOSE);
+ $out = new BufferedWriter(new FileWriter($this->output->getAbsolutePath(), $this->append));
+ }
+
+ // Process all transactions
+ for ($i=0,$size=count($this->transactions); $i < $size; $i++) {
+ $this->transactions[$i]->runTransaction($out);
+ if (!$this->isAutocommit()) {
+ $this->log("Commiting transaction", PROJECT_MSG_VERBOSE);
+ $this->conn->commit();
+ }
+ }
+ if ($out) $out->close();
+ } catch (Exception $e) {
+ if ($out) $out->close();
+ throw $e;
+ }
+ } catch (IOException $e) {
+ if (!$this->isAutocommit() && $this->conn !== null && $this->onError == "abort") {
+ try {
+ $this->conn->rollback();
+ } catch (SQLException $ex) {}
+ }
+ throw new BuildException($e->getMessage(), $this->location);
+ } catch (SQLException $e){
+ if (!$this->isAutocommit() && $this->conn !== null && $this->onError == "abort") {
+ try {
+ $this->conn->rollback();
+ } catch (SQLException $ex) {}
+ }
+ throw new BuildException($e->getMessage(), $this->location);
+ }
+
+ $this->log($this->goodSql . " of " . $this->totalSql .
+ " SQL statements executed successfully");
+ } catch (Exception $e) {
+ $this->transactions = $savedTransaction;
+ $this->sqlCommand = $savedSqlCommand;
+ throw $e;
+ }
+ // finally {
+ $this->transactions = $savedTransaction;
+ $this->sqlCommand = $savedSqlCommand;
+
+ }
+
+
+ /**
+ * read in lines and execute them
+ * @throws SQLException, IOException
+ */
+ public function runStatements(Reader $reader, $out = null) {
+ $sql = "";
+ $line = "";
+ $in = new BufferedReader($reader);
+ try {
+ while (($line = $in->readLine()) !== null) {
+ $line = trim($line);
+ $line = ProjectConfigurator::replaceProperties($this->project, $line,
+ $this->project->getProperties());
+
+ if (StringHelper::startsWith("//", $line) ||
+ StringHelper::startsWith("--", $line) ||
+ StringHelper::startsWith("#", $line)) {
+ continue;
+ }
+
+ if (strlen($line) > 4
+ && strtoupper(substr($line,0, 4)) == "REM ") {
+ continue;
+ }
+
+ $sql .= " " . $line;
+ $sql = trim($sql);
+
+ // SQL defines "--" as a comment to EOL
+ // and in Oracle it may contain a hint
+ // so we cannot just remove it, instead we must end it
+ if (strpos($line, "--") !== false) {
+ $sql .= "\n";
+ }
+
+ if ($this->delimiterType == self::DELIM_NORMAL
+ && StringHelper::endsWith($this->delimiter, $sql)
+ || $this->delimiterType == self::DELIM_ROW
+ && $line == $this->delimiter) {
+ $this->log("SQL: " . $sql, PROJECT_MSG_VERBOSE);
+ $this->execSQL(StringHelper::substring($sql, 0, strlen($sql) - strlen($this->delimiter)) - 1, $out);
+ $sql = "";
+ }
+ }
+
+ // Catch any statements not followed by ;
+ if ($sql !== "") {
+ $this->execSQL($sql, $out);
+ }
+ } catch (SQLException $e) {
+ throw new BuildException("Error running statements", $e);
+ }
+ }
+
+
+ /**
+ * Exec the sql statement.
+ * @throws SQLException
+ */
+ protected function execSQL($sql, $out = null) {
+ // Check and ignore empty statements
+ if (trim($sql) == "") {
+ return;
+ }
+
+ try {
+ $this->totalSql++;
+ if (!$this->statement->execute($sql)) {
+ $this->log($this->statement->getUpdateCount() . " rows affected", PROJECT_MSG_VERBOSE);
+ } else {
+ if ($this->print) {
+ $this->printResults($out);
+ }
+ }
+
+ $this->goodSql++;
+
+ } catch (SQLException $e) {
+ $this->log("Failed to execute: " . $sql, PROJECT_MSG_ERR);
+ if ($this->onError != "continue") {
+ throw new BuildException("Failed to execute SQL", $e);
+ }
+ $this->log($e->getMessage(), PROJECT_MSG_ERR);
+ }
+ }
+
+ /**
+ * print any results in the statement.
+ * @throw SQLException
+ */
+ protected function printResults($out = null) {
+ $lSep = Phing::getProperty('line.separator');
+ $rs = null;
+ do {
+ $rs = $this->statement->getResultSet();
+
+ if ($rs !== null) {
+
+ $this->log("Processing new result set.", PROJECT_MSG_VERBOSE);
+
+ $line = "";
+
+ $colsprinted = false;
+
+ while ($rs->next()) {
+ $fields = $rs->getRow();
+
+ if (!$colsprinted && $this->showheaders) {
+ $first = true;
+ foreach($fields as $fieldName => $ignore) {
+ if ($first) $first = false; else $line .= ",";
+ $line .= $fieldName;
+ }
+ if ($out !== null) {
+ $out->write($line);
+ $out->newLine();
+ } else {
+ print($line.$lSep);
+ }
+ $line = "";
+ $colsprinted = true;
+ } // if show headers
+
+ $first = true;
+ foreach($fields as $columnValue) {
+
+ if ($columnValue != null) {
+ $columnValue = trim($columnValue);
+ }
+
+ if ($first) {
+ $first = false;
+ } else {
+ $line .= ",";
+ }
+ $line .= $columnValue;
+ }
+
+ if ($out !== null) {
+ $out->write($line);
+ $out->newLine();
+ } else {
+ print($line . $lSep);
+ }
+ $line = "";
+
+ } // while rs->next()
+ }
+ } while ($this->statement->getMoreResults());
+ print($lSep);
+ if ($out !== null) $out->newLine();
+ }
+}
+
+
+/**
+ * "Inner" class that contains the definition of a new transaction element.
+ * Transactions allow several files or blocks of statements
+ * to be executed using the same JDBC connection and commit
+ * operation in between.
+ */
+class SQLExecTransaction {
+
+ private $tSrcFile = null;
+ private $tSqlCommand = "";
+ private $parent;
+
+ function __construct($parent)
+ {
+ // Parent is required so that we can log things ...
+ $this->parent = $parent;
+ }
+
+ public function setSrc(PhingFile $src)
+ {
+ $this->tSrcFile = $src;
+ }
+
+ public function addText($sql)
+ {
+ $this->tSqlCommand .= $sql;
+ }
+
+ /**
+ * @throws IOException, SQLException
+ */
+ public function runTransaction($out = null)
+ {
+ if (!empty($this->tSqlCommand)) {
+ $this->parent->log("Executing commands", PROJECT_MSG_INFO);
+ $this->parent->runStatements(new StringReader($this->tSqlCommand), $out);
+ }
+
+ if ($this->tSrcFile !== null) {
+ $this->parent->log("Executing file: " . $this->tSrcFile->getAbsolutePath(),
+ PROJECT_MSG_INFO);
+ $reader = new FileReader($this->tSrcFile);
+ $this->parent->runStatements($reader, $out);
+ $reader->close();
+ }
+ }
+}
+
+
diff --git a/buildscripts/phing/classes/phing/tasks/ext/CreoleTask.php b/buildscripts/phing/classes/phing/tasks/ext/CreoleTask.php
new file mode 100644
index 00000000..a1b439e5
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/CreoleTask.php
@@ -0,0 +1,242 @@
+<?php
+
+/*
+ * $Id: CreoleTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+include_once 'phing/types/Reference.php';
+
+/**
+ * Handles Creole configuration needed by SQL type tasks.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Nick Chalko <nick@chalko.com> (Ant)
+ * @author Jeff Martin <jeff@custommonkey.org> (Ant)
+ * @author Michael McCallum <gholam@xtra.co.nz> (Ant)
+ * @author Tim Stephenson <tim.stephenson@sybase.com> (Ant)
+ * @version $Revision: 1.13 $
+ * @package phing.tasks.system
+ */
+abstract class CreoleTask extends Task {
+
+ /**
+ * Used for caching loaders / driver. This is to avoid
+ * getting an OutOfMemoryError when calling this task
+ * multiple times in a row.
+ *
+ * NOT IMPLEMENTED YET
+ */
+ private static $loaderMap = array();
+
+ private $caching = true;
+
+ /**
+ * Autocommit flag. Default value is false
+ */
+ private $autocommit = false;
+
+ /**
+ * [optional] Classpath to Creole driver to use.
+ * @param string
+ */
+ private $driver;
+
+ /**
+ * DB url.
+ */
+ private $url;
+
+ /**
+ * User name.
+ */
+ private $userId;
+
+ /**
+ * Password
+ */
+ private $password;
+
+ /**
+ * RDBMS Product needed for this SQL.
+ **/
+ private $rdbms;
+
+ /**
+ * Initialize CreoleTask.
+ * This method includes any necessary Creole libraries and triggers
+ * appropriate error if they cannot be found. This is not done in header
+ * because we may want this class to be loaded w/o triggering an error.
+ */
+ function init() {
+ include_once 'creole/Creole.php';
+ if (!class_exists('Creole')) {
+ throw new Exception("Creole task depends on Creole classes being on include_path. (i.e. include of 'creole/Creole.php' failed.)");
+ }
+ }
+
+ /**
+ * Caching loaders / driver. This is to avoid
+ * getting an OutOfMemoryError when calling this task
+ * multiple times in a row; default: true
+ * @param $enable
+ */
+ public function setCaching($enable) {
+ $this->caching = $enable;
+ }
+
+ /**
+ * Sets the database connection URL; required.
+ * @param url The url to set
+ */
+ public function setUrl($url) {
+ $this->url = $url;
+ }
+
+ /**
+ * Set the Creole driver to be used.
+ *
+ * @param string $driver driver class name
+ */
+ public function setDriver($driver)
+ {
+ $this->driver = $driver;
+ }
+
+ /**
+ * Sets the password; required.
+ * @param password The password to set
+ */
+ public function setPassword($password) {
+ $this->password = $password;
+ }
+
+ /**
+ * Auto commit flag for database connection;
+ * optional, default false.
+ * @param autocommit The autocommit to set
+ */
+ public function setAutocommit($autocommit) {
+ $this->autocommit = $autocommit;
+ }
+
+ /**
+ * Sets the version string, execute task only if
+ * rdbms version match; optional.
+ * @param version The version to set
+ */
+ public function setVersion($version) {
+ $this->version = $version;
+ }
+
+ protected function getLoaderMap() {
+ return self::$loaderMap;
+ }
+
+
+ /**
+ * Creates a new Connection as using the driver, url, userid and password specified.
+ * The calling method is responsible for closing the connection.
+ * @return Connection the newly created connection.
+ * @throws BuildException if the UserId/Password/Url is not set or there is no suitable driver or the driver fails to load.
+ */
+ protected function getConnection() {
+
+ if ($this->url === null) {
+ throw new BuildException("Url attribute must be set!", $this->location);
+ }
+
+ try {
+
+ $this->log("Connecting to " . $this->getUrl(), PROJECT_MSG_VERBOSE);
+ $info = new Properties();
+
+ $dsn = Creole::parseDSN($this->url);
+
+ if (!isset($dsn["username"]) && $this->userId === null) {
+ throw new BuildException("Username must be in URL or userid attribute must be set.", $this->location);
+ }
+
+ if ($this->userId) {
+ $dsn["username"] = $this->getUserId();
+ }
+
+ if ($this->password) {
+ $dsn["password"] = $this->getPassword();
+ }
+
+ if ($this->driver) {
+ Creole::registerDriver($dsn['phptype'], $this->driver);
+ }
+
+ $conn = Creole::getConnection($dsn);
+ $conn->setAutoCommit($this->autocommit);
+ return $conn;
+
+ } catch (SQLException $e) {
+ throw new BuildException($e->getMessage(), $this->location);
+ }
+
+ }
+
+ public function isCaching($value) {
+ $this->caching = $value;
+ }
+
+ /**
+ * Gets the autocommit.
+ * @return Returns a boolean
+ */
+ public function isAutocommit() {
+ return $this->autocommit;
+ }
+
+ /**
+ * Gets the url.
+ * @return Returns a String
+ */
+ public function getUrl() {
+ return $this->url;
+ }
+
+ /**
+ * Gets the userId.
+ * @return Returns a String
+ */
+ public function getUserId() {
+ return $this->userId;
+ }
+
+ /**
+ * Set the user name for the connection; required.
+ * @param userId The userId to set
+ */
+ public function setUserid($userId) {
+ $this->userId = $userId;
+ }
+
+ /**
+ * Gets the password.
+ * @return Returns a String
+ */
+ public function getPassword() {
+ return $this->password;
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/tasks/ext/MailTask.php b/buildscripts/phing/classes/phing/tasks/ext/MailTask.php
new file mode 100644
index 00000000..16d29fb8
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/MailTask.php
@@ -0,0 +1,77 @@
+<?php
+/*
+ * $Id: MailTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/Task.php';
+
+/**
+ * Send a message by mail()
+ *
+ * <mail to="user@example.org" subject="build complete">The build process is a success...</mail>
+ *
+ * @author Francois Harvey at SecuriWeb (http://www.securiweb.net)
+ * @version $Revision: 1.1 $
+ * @package phing.tasks.ext
+ */
+class MailTask extends Task {
+
+ protected $recipient;
+
+ protected $subject;
+
+ protected $msg;
+
+ function main() {
+ $this->log('Sending mail to ' . $this->recipient );
+ mail($this->recipient, $this->subject, $this->msg);
+ }
+
+ /** setter for message */
+ function setMsg($msg) {
+ $this->setMessage($msg);
+ }
+
+ /** alias setter */
+ function setMessage($msg) {
+ $this->msg = (string) $msg;
+ }
+
+ /** setter for subject **/
+ function setSubject($subject) {
+ $this->subject = (string) $subject;
+ }
+
+ /** setter for recipient **/
+ function setRecipient($recipient) {
+ $this->recipient = (string) $recipient;
+ }
+
+ /** alias for recipient **/
+ function setTo($recipient) {
+ $this->recipient = (string) $recipient;
+ }
+
+ /** Supporting the <mail>Message</mail> syntax. */
+ function addText($msg)
+ {
+ $this->msg = (string) $msg;
+ }
+}
+
diff --git a/buildscripts/phing/classes/phing/tasks/ext/PackageAsPathTask.php b/buildscripts/phing/classes/phing/tasks/ext/PackageAsPathTask.php
new file mode 100644
index 00000000..b8664aac
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/PackageAsPathTask.php
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * $Id: PackageAsPathTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+
+/**
+ * Convert dot-notation packages to relative paths.
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.5 $
+ * @package phing.tasks.ext
+ */
+class PackageAsPathTask extends Task {
+
+ /** The package to convert. */
+ protected $pckg;
+
+ /** The value to store the conversion in. */
+ protected $name;
+
+ /**
+ * Executes the package to patch converstion and stores it
+ * in the user property <code>value</code>.
+ */
+ public function main()
+ {
+ $this->project->setUserProperty($this->name, strtr($this->pckg, '.', '/'));
+ }
+
+ /**
+ * @param string $pckg the package to convert
+ */
+ public function setPackage($pckg)
+ {
+ $this->pckg = $pckg;
+ }
+
+ /**
+ * @param string $name the Ant variable to store the path in
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/tasks/ext/PearPackageTask.php b/buildscripts/phing/classes/phing/tasks/ext/PearPackageTask.php
new file mode 100644
index 00000000..4f8ee3ab
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/PearPackageTask.php
@@ -0,0 +1,421 @@
+<?php
+/*
+ * $Id: PearPackageTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/tasks/system/MatchingTask.php';
+include_once 'phing/types/FileSet.php';
+
+/**
+ * A task to create PEAR package.xml file.
+ *
+ * This class uses the PEAR_PackageFileMaintainer class to perform the work.
+ *
+ * This class is designed to be very flexible -- i.e. account for changes to the package.xml w/o
+ * requiring changes to this class. We've accomplished this by having generic <option> and <mapping>
+ * nested elements. All options are set using PEAR_PackageFileMaintainer::setOptions().
+ *
+ * The <option> tag is used to set a simple option value.
+ * <code>
+ * <option name="option_name" value="option_value"/>
+ * or <option name="option_name">option_value</option>
+ * </code>
+ *
+ * The <mapping> tag represents a complex data type. You can use nested <element> (and nested <element> with
+ * <element> tags) to represent the full complexity of the structure. Bear in mind that what you are creating
+ * will be mapped to an associative array that will be passed in via PEAR_PackageFileMaintainer::setOptions().
+ * <code>
+ * <mapping name="option_name">
+ * <element key="key_name" value="key_val"/>
+ * <element key="key_name" value="key_val"/>
+ * </mapping>
+ * </code>
+ *
+ * Here's an over-simple example of how this could be used:
+ * <code>
+ * <pearpkg name="phing" dir="${build.src.dir}" destFile="${build.base.dir}/package.xml">
+ * <fileset>
+ * <include name="**"/>
+ * </fileset>
+ * <option name="notes">Sample release notes here.</option>
+ * <option name="description">Package description</option>
+ * <option name="summary">Short description</option>
+ * <option name="version" value="2.0.0b1"/>
+ * <option name="state" value="beta"/>
+ * <mapping name="maintainers">
+ * <element>
+ * <element key="handle" value="hlellelid"/>
+ * <element key="name" value="Hans"/>
+ * <element key="email" value="hans@xmpl.org"/>
+ * <element key="role" value="lead"/>
+ * </element>
+ * </mapping>
+ * </pearpkg>
+ * </code>
+ *
+ * Look at the build.xml in the Phing base directory (assuming you have the full distro / CVS version of Phing) to
+ * see a more complete example of how to call this script.
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @package phing.tasks.ext
+ * @version $Revision: 1.9 $
+ */
+class PearPackageTask extends MatchingTask {
+
+ /** */
+ private $package;
+
+ /** Base directory for reading files. */
+ private $dir;
+
+ /** Package file */
+ private $packageFile;
+
+ /** @var array FileSet[] */
+ private $filesets = array();
+
+ /** @var PEAR_PackageFileManager */
+ private $pkg;
+
+ private $preparedOptions = array();
+
+ /** @var array PearPkgOption[] */
+ private $options = array();
+
+ /** Nested <mapping> (complex options) types. */
+ private $mappings = array();
+
+ public function init() {
+ include_once 'PEAR/PackageFileManager.php';
+ if (!class_exists('PEAR_PackageFileManager')) {
+ throw new BuildException("You must have installed PEAR_PackageFileManager in order to create a PEAR package.xml file.");
+ }
+ }
+
+ /**
+ * Sets PEAR package.xml options, based on class properties.
+ * @return void
+ */
+ private function setOptions() {
+
+ // 1) first prepare/populate options
+ $this->populateOptions();
+
+ // 2) make any final adjustments (this could move into populateOptions() also)
+
+ // default PEAR basedir would be the name of the package (e.g."phing")
+ if (!isset($this->preparedOptions['baseinstalldir'])) {
+ $this->preparedOptions['baseinstalldir'] = $this->package;
+ }
+
+ // unless filelistgenerator has been overridden, we use Phing FileSet generator
+ if (!isset($this->preparedOptions['filelistgenerator'])) {
+ if (empty($this->filesets)) {
+ throw new BuildException("You must use a <fileset> tag to specify the files to include in the package.xml");
+ }
+ $this->preparedOptions['filelistgenerator'] = 'Fileset';
+ $this->preparedOptions['usergeneratordir'] = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pearpackage';
+ // Some PHING-specific options needed by our Fileset reader
+ $this->preparedOptions['phing_project'] = $this->project;
+ $this->preparedOptions['phing_filesets'] = $this->filesets;
+ } elseif ($this->preparedOptions['filelistgeneragor'] != 'Fileset' && !empty($this->filesets)) {
+ throw new BuildException("You cannot use <fileset> element if you have specified the \"filelistgenerator\" option.");
+ }
+
+ // 3) Set the options
+
+ // No need for excessive validation here, since the PEAR class will do its own
+ // validation & return errors
+ $e = $this->pkg->setOptions($this->preparedOptions);
+
+ if (PEAR::isError($e)) {
+ throw new BuildException("Unable to set options.", new Exception($e->getMessage()));
+ }
+ }
+
+ /**
+ * Fixes the boolean in optional dependencies
+ */
+ private function fixDeps($deps)
+ {
+ foreach (array_keys($deps) as $dep)
+ {
+ if (isset($deps[$dep]['optional']) && $deps[$dep]['optional'])
+ {
+ $deps[$dep]['optional'] = "yes";
+ }
+ }
+
+ return $deps;
+ }
+
+ /**
+ * Adds the options that are set via attributes and the nested tags to the options array.
+ */
+ private function populateOptions() {
+
+ // These values could be overridden if explicitly defined using nested tags
+ $this->preparedOptions['package'] = $this->package;
+ $this->preparedOptions['packagedirectory'] = $this->dir->getAbsolutePath();
+
+ if ($this->packageFile !== null) {
+ // create one w/ full path
+ $f = new PhingFile($this->packageFile->getAbsolutePath());
+ $this->preparedOptions['packagefile'] = $f->getName();
+ // must end in trailing slash
+ $this->preparedOptions['outputdirectory'] = $f->getParent() . DIRECTORY_SEPARATOR;
+ $this->log("Creating package file: " . $f->__toString(), PROJECT_MSG_INFO);
+ } else {
+ $this->log("Creating [default] package.xml file in base directory.", PROJECT_MSG_INFO);
+ }
+
+ // converts option objects and mapping objects into
+ // key => value options that can be passed to PEAR_PackageFileManager
+
+ foreach($this->options as $opt) {
+ $this->preparedOptions[ $opt->getName() ] = $opt->getValue(); //no arrays yet. preg_split('/\s*,\s*/', $opt->getValue());
+ }
+
+ foreach($this->mappings as $map) {
+ $value = $map->getValue(); // getValue returns complex value
+
+ if ($map->getName() == 'deps')
+ {
+ $value = $this->fixDeps($value);
+ }
+
+ $this->preparedOptions[ $map->getName() ] = $value;
+ }
+ }
+
+ /**
+ * Main entry point.
+ * @return void
+ */
+ public function main() {
+
+ if ($this->dir === null) {
+ throw new BuildException("You must specify the \"dir\" attribute for PEAR package task.");
+ }
+
+ if ($this->package === null) {
+ throw new BuildException("You must specify the \"name\" attribute for PEAR package task.");
+ }
+
+ $this->pkg = new PEAR_PackageFileManager();
+
+ $this->setOptions();
+
+ $e = $this->pkg->writePackageFile();
+ if (PEAR::isError($e)) {
+ throw new BuildException("Unable to write package file.", new Exception($e->getMessage()));
+ }
+
+ }
+
+ /**
+ * Used by the PEAR_PackageFileManager_PhingFileSet lister.
+ * @return array FileSet[]
+ */
+ public function getFileSets() {
+ return $this->filesets;
+ }
+
+ // -------------------------------
+ // Set properties from XML
+ // -------------------------------
+
+ /**
+ * Nested creator, creates a FileSet for this task
+ *
+ * @return FileSet The created fileset object
+ */
+ function createFileSet() {
+ $num = array_push($this->filesets, new FileSet());
+ return $this->filesets[$num-1];
+ }
+
+ /**
+ * Set "package" property from XML.
+ * @see setName()
+ * @param string $v
+ * @return void
+ */
+ public function setPackage($v) {
+ $this->package = $v;
+ }
+
+ /**
+ * Sets "dir" property from XML.
+ * @param PhingFile $f
+ * @return void
+ */
+ public function setDir(PhingFile $f) {
+ $this->dir = $f;
+ }
+
+ /**
+ * Sets "name" property from XML.
+ * @param string $v
+ * @return void
+ */
+ public function setName($v) {
+ $this->package = $v;
+ }
+
+ /**
+ * Sets the file to use for generated package.xml
+ */
+ public function setDestFile(PhingFile $f) {
+ $this->packageFile = $f;
+ }
+
+ /**
+ * Handles nested generic <option> elements.
+ */
+ function createOption() {
+ $o = new PearPkgOption();
+ $this->options[] = $o;
+ return $o;
+ }
+
+ /**
+ * Handles nested generic <option> elements.
+ */
+ function createMapping() {
+ $o = new PearPkgMapping();
+ $this->mappings[] = $o;
+ return $o;
+ }
+}
+
+
+
+/**
+ * Generic option class is used for non-complex options.
+ */
+class PearPkgOption {
+
+ private $name;
+ private $value;
+
+ public function setName($v) { $this->name = $v; }
+ public function getName() { return $this->name; }
+
+ public function setValue($v) { $this->value = $v; }
+ public function getValue() { return $this->value; }
+ public function addText($txt) { $this->value = trim($txt); }
+
+}
+
+/**
+ * Handles complex options <mapping> elements which are hashes (assoc arrays).
+ */
+class PearPkgMapping {
+
+ private $name;
+ private $elements = array();
+
+ public function setName($v) {
+ $this->name = $v;
+ }
+
+ public function getName() {
+ return $this->name;
+ }
+
+ public function createElement() {
+ $e = new PearPkgMappingElement();
+ $this->elements[] = $e;
+ return $e;
+ }
+
+ public function getElements() {
+ return $this->elements;
+ }
+
+ /**
+ * Returns the PHP hash or array of hashes (etc.) that this mapping represents.
+ * @return array
+ */
+ public function getValue() {
+ $value = array();
+ foreach($this->getElements() as $el) {
+ if ($el->getKey() !== null) {
+ $value[ $el->getKey() ] = $el->getValue();
+ } else {
+ $value[] = $el->getValue();
+ }
+ }
+ return $value;
+ }
+}
+
+/**
+ * Sub-element of <mapping>.
+ */
+class PearPkgMappingElement {
+
+ private $key;
+ private $value;
+ private $elements = array();
+
+ public function setKey($v) {
+ $this->key = $v;
+ }
+
+ public function getKey() {
+ return $this->key;
+ }
+
+ public function setValue($v) {
+ $this->value = $v;
+ }
+
+ /**
+ * Returns either the simple value or
+ * the calculated value (array) of nested elements.
+ * @return mixed
+ */
+ public function getValue() {
+ if (!empty($this->elements)) {
+ $value = array();
+ foreach($this->elements as $el) {
+ if ($el->getKey() !== null) {
+ $value[ $el->getKey() ] = $el->getValue();
+ } else {
+ $value[] = $el->getValue();
+ }
+ }
+ return $value;
+ } else {
+ return $this->value;
+ }
+ }
+
+ /**
+ * Handles nested <element> tags.
+ */
+ public function createElement() {
+ $e = new PearPkgMappingElement();
+ $this->elements[] = $e;
+ return $e;
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/tasks/ext/PhpLintTask.php b/buildscripts/phing/classes/phing/tasks/ext/PhpLintTask.php
new file mode 100644
index 00000000..2fd89fc3
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/PhpLintTask.php
@@ -0,0 +1,82 @@
+<?php
+require_once 'phing/Task.php';
+
+/**
+ * A PHP lint task. Checking syntax of one or more PHP source file.
+ *
+ * @author Knut Urdalen <knut.urdalen@telio.no>
+ * @package phing.tasks.ext
+ */
+class PhpLintTask extends Task {
+
+ protected $file; // the source file (from xml attribute)
+ protected $filesets = array(); // all fileset objects assigned to this task
+
+ /**
+ * File to be performed syntax check on
+ * @param PhingFile $file
+ */
+ public function setFile(PhingFile $file) {
+ $this->file = $file;
+ }
+
+ /**
+ * Nested creator, creates a FileSet for this task
+ *
+ * @return FileSet The created fileset object
+ */
+ function createFileSet() {
+ $num = array_push($this->filesets, new FileSet());
+ return $this->filesets[$num-1];
+ }
+
+ /**
+ * Execute lint check against PhingFile or a FileSet
+ */
+ public function main() {
+ if(!isset($this->file) and count($this->filesets) == 0) {
+ throw new BuildException("Missing either a nested fileset or attribute 'file' set");
+ }
+
+ if($this->file instanceof PhingFile) {
+ $this->lint($this->file->getPath());
+ } else { // process filesets
+ $project = $this->getProject();
+ foreach($this->filesets as $fs) {
+ $ds = $fs->getDirectoryScanner($project);
+ $files = $ds->getIncludedFiles();
+ $dir = $fs->getDir($this->project)->getPath();
+ foreach($files as $file) {
+ $this->lint($dir.DIRECTORY_SEPARATOR.$file);
+ }
+ }
+ }
+ }
+
+ /**
+ * Performs the actual syntax check
+ *
+ * @param string $file
+ * @return void
+ */
+ protected function lint($file) {
+ $command = 'php -l ';
+ if(file_exists($file)) {
+ if(is_readable($file)) {
+ $message = array();
+ exec($command.$file, $message);
+ if(!preg_match('/^No syntax errors detected/', $message[0])) {
+ $this->log($message[1], PROJECT_MSG_ERR);
+ } else {
+ $this->log($file.': No syntax errors detected', PROJECT_MSG_INFO);
+ }
+ } else {
+ throw new BuildException('Permission denied: '.$file);
+ }
+ } else {
+ throw new BuildException('File not found: '.$file);
+ }
+ }
+}
+
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/SmartyTask.php b/buildscripts/phing/classes/phing/tasks/ext/SmartyTask.php
new file mode 100644
index 00000000..97eada3d
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/SmartyTask.php
@@ -0,0 +1,610 @@
+<?php
+
+/*
+ * $Id: SmartyTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+include_once 'phing/BuildException.php';
+include_once 'phing/util/StringHelper.php';
+
+/**
+ * A phing task for generating output by using Smarty.
+ *
+ * This is based on the TexenTask from Apache's Velocity engine. This class
+ * was originally proted in order to provide a template compiling system for
+ * Torque.
+ *
+ * TODO:
+ * - Add Path / useClasspath support?
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (SmartyTask)
+ * @author Jason van Zyl <jvanzyl@apache.org> (TexenTask)
+ * @author Robert Burrell Donkin <robertdonkin@mac.com>
+ * @version $Id: SmartyTask.php 59 2006-04-28 14:49:47Z mrook $
+ * @package phing.tasks.ext
+ */
+class SmartyTask extends Task {
+
+ /**
+ * Smarty template engine.
+ * @var Smarty
+ */
+ protected $context;
+
+ /**
+ * Variables that are assigned to the context on parse/compile.
+ * @var array
+ */
+ protected $properties = array();
+
+ /**
+ * This is the control template that governs the output.
+ * It may or may not invoke the services of worker
+ * templates.
+ * @var string
+ */
+ protected $controlTemplate;
+
+ /**
+ * This is where Velocity will look for templates
+ * using the file template loader.
+ * @var string
+ */
+ protected $templatePath;
+
+ /**
+ * This is where texen will place all the output
+ * that is a product of the generation process.
+ * @var string
+ */
+ protected $outputDirectory;
+
+ /**
+ * This is the file where the generated text
+ * will be placed.
+ * @var string
+ */
+ protected $outputFile;
+
+ /**
+ * <p>
+ * These are properties that are fed into the
+ * initial context from a properties file. This
+ * is simply a convenient way to set some values
+ * that you wish to make available in the context.
+ * </p>
+ * <p>
+ * These values are not critical, like the template path
+ * or output path, but allow a convenient way to
+ * set a value that may be specific to a particular
+ * generation task.
+ * </p>
+ * <p>
+ * For example, if you are generating scripts to allow
+ * user to automatically create a database, then
+ * you might want the <code>$databaseName</code>
+ * to be placed
+ * in the initial context so that it is available
+ * in a script that might look something like the
+ * following:
+ * <code><pre>
+ * #!bin/sh
+ *
+ * echo y | mysqladmin create $databaseName
+ * </pre></code>
+ * The value of <code>$databaseName</code> isn't critical to
+ * output, and you obviously don't want to change
+ * the ant task to simply take a database name.
+ * So initial context values can be set with
+ * properties file.
+ *
+ * @var array
+ */
+ protected $contextProperties;
+
+ /**
+ * Smarty compiles templates before parsing / replacing tokens in them.
+ * By default it will try ./templates_c, but you may wish to override this.
+ * @var string
+ */
+ protected $compilePath;
+
+ /**
+ * Whether to force Smarty to recompile templates.
+ * Smarty does check file modification time, but you can set this
+ * to be *sure* that the template will be compiled (of course it will
+ * be slower if you do).
+ * @var boolean
+ */
+ protected $forceCompile = false;
+
+ /**
+ * Smarty can use config files.
+ * This tells Smarty where to look for the config files.
+ * @var string
+ */
+ protected $configPath;
+
+ /**
+ * Customize the left delimiter for Smarty tags.
+ * @var string
+ */
+ protected $leftDelimiter;
+
+ /**
+ * Customize the right delimiter for Smarty tags.
+ * @var string
+ */
+ protected $rightDelimiter;
+
+ // -----------------------------------------------------------------------
+ // The following getters & setters are used by phing to set properties
+ // specified in the XML for the smarty task.
+ // -----------------------------------------------------------------------
+
+ public function init() {
+ include_once 'Smarty.class.php';
+ if (!class_exists('Smarty')) {
+ throw new BuildException("To use SmartyTask, you must have the path to Smarty.class.php on your include_path or your \$PHP_CLASSPATH environment variable.");
+ }
+ }
+
+ /**
+ * [REQUIRED] Set the control template for the
+ * generating process.
+ * @param string $controlTemplate
+ * @return void
+ */
+ public function setControlTemplate ($controlTemplate) {
+ $this->controlTemplate = $controlTemplate;
+ }
+
+ /**
+ * Get the control template for the
+ * generating process.
+ * @return string
+ */
+ public function getControlTemplate() {
+ return $this->controlTemplate;
+ }
+
+ /**
+ * [REQUIRED] Set the path where Velocity will look
+ * for templates using the file template
+ * loader.
+ * @return void
+ * @throws Exception
+ */
+ public function setTemplatePath($templatePath) {
+ $resolvedPath = "";
+ $tok = strtok($templatePath, ",");
+ while ( $tok ) {
+ // resolve relative path from basedir and leave
+ // absolute path untouched.
+ $fullPath = $this->project->resolveFile($tok);
+ $cpath = $fullPath->getCanonicalPath();
+ if ($cpath === false) {
+ $this->log("Template directory does not exist: " . $fullPath->getAbsolutePath());
+ } else {
+ $resolvedPath .= $cpath;
+ }
+ $tok = strtok(",");
+ if ( $tok ) {
+ $resolvedPath .= ",";
+ }
+ }
+ $this->templatePath = $resolvedPath;
+ }
+
+ /**
+ * Get the path where Velocity will look
+ * for templates using the file template
+ * loader.
+ * @return string
+ */
+ public function getTemplatePath() {
+ return $this->templatePath;
+ }
+
+ /**
+ * [REQUIRED] Set the output directory. It will be
+ * created if it doesn't exist.
+ * @param PhingFile $outputDirectory
+ * @return void
+ * @throws Exception
+ */
+ public function setOutputDirectory(PhingFile $outputDirectory) {
+ try {
+ if (!$outputDirectory->exists()) {
+ $this->log("Output directory does not exist, creating: " . $outputDirectory->getPath(),PROJECT_MSG_VERBOSE);
+ if (!$outputDirectory->mkdirs()) {
+ throw new IOException("Unable to create Ouptut directory: " . $outputDirectory->getAbsolutePath());
+ }
+ }
+ $this->outputDirectory = $outputDirectory->getCanonicalPath();
+ } catch (IOException $ioe) {
+ throw new BuildException($ioe->getMessage());
+ }
+ }
+
+ /**
+ * Get the output directory.
+ * @return string
+ */
+ public function getOutputDirectory() {
+ return $this->outputDirectory;
+ }
+
+ /**
+ * [REQUIRED] Set the output file for the
+ * generation process.
+ * @return void
+ */
+ public function setOutputFile($outputFile) {
+ $this->outputFile = $outputFile;
+ }
+
+ /**
+ * Get the output file for the
+ * generation process.
+ * @return string
+ */
+ public function getOutputFile() {
+ return $this->outputFile;
+ }
+
+ /**
+ * Set the path Smarty uses as a "cache" for compiled templates.
+ * @param string $compilePath
+ */
+ public function setCompilePath($compilePath) {
+ $this->compilePath = $compilePath;
+ }
+
+ /**
+ * Get the path Smarty uses for compiling templates.
+ * @return string
+ */
+ public function getCompilePath() {
+ return $this->compilePath;
+ }
+
+ /**
+ * Set whether Smarty should always recompile tempaltes.
+ * @param boolean $force
+ * @return void
+ */
+ public function setForceCompile($force) {
+ $this->forceCompile = (boolean) $force;
+ }
+
+ /**
+ * Get whether Smarty should always recompile template.
+ * @return boolean
+ */
+ public function getForceCompile() {
+ return $this->forceCompile;
+ }
+
+ /**
+ * Set where Smarty looks for config files.
+ * @param string $configPath
+ * @return void
+ */
+ public function setConfigPath($configPath) {
+ $this->configPath = $configPath;
+ }
+
+ /**
+ * Get the path that Smarty uses for looking for config files.
+ * @return string
+ */
+ public function getConfigPath() {
+ return $this->configPath;
+ }
+
+ /**
+ * Set Smarty template left delimiter.
+ * @param string $delim
+ * @return void
+ */
+ public function setLeftDelimiter($delim) {
+ $this->leftDelimiter = $delim;
+ }
+
+ /**
+ * Get Smarty template right delimiter
+ * @return string
+ */
+ public function getLeftDelimiter() {
+ return $this->leftDelimiter;
+ }
+
+ /**
+ * Set Smarty template right delimiter.
+ * @param string $delim
+ * @return void
+ */
+ public function setRightDelimiter($delim) {
+ $this->rightDelimiter = $delim;
+ }
+
+ /**
+ * Get Smarty template right delimiter
+ * @return string
+ */
+ public function getRightDelimiter() {
+ return $this->rightDelimiter;
+ }
+
+
+ /**
+ * Set the context properties that will be
+ * fed into the initial context be the
+ * generating process starts.
+ * @param string $file
+ * @return void
+ */
+ public function setContextProperties($file) {
+
+ $sources = explode(",", $file);
+ $this->contextProperties = new Properties();
+
+ // Always try to get the context properties resource
+ // from a file first. Templates may be taken from a JAR
+ // file but the context properties resource may be a
+ // resource in the filesystem. If this fails than attempt
+ // to get the context properties resource from the
+ // classpath.
+ for ($i=0, $sourcesLength=count($sources); $i < $sourcesLength; $i++) {
+ $source = new Properties();
+
+ try {
+
+ // resolve relative path from basedir and leave
+ // absolute path untouched.
+ $fullPath = $this->project->resolveFile($sources[$i]);
+ $this->log("Using contextProperties file: " . $fullPath->__toString());
+ $source->load($fullPath);
+
+ } catch (Exception $e) {
+
+ throw new BuildException("Context properties file " . $sources[$i] .
+ " could not be found in the file system!");
+
+ }
+
+ $keys = $source->keys();
+
+ foreach ($keys as $key) {
+ $name = $key;
+ $value = $this->project->replaceProperties($source->getProperty($name));
+ $this->contextProperties->setProperty($name, $value);
+ }
+ }
+ }
+
+ /**
+ * Get the context properties that will be
+ * fed into the initial context be the
+ * generating process starts.
+ * @return Properties
+ */
+ public function getContextProperties() {
+ return $this->contextProperties;
+ }
+
+ // ---------------------------------------------------------------
+ // End of XML setters & getters
+ // ---------------------------------------------------------------
+
+
+ /**
+ * Creates a Smarty object.
+ *
+ * @return Smarty initialized (cleared) Smarty context.
+ * @throws Exception the execute method will catch
+ * and rethrow as a <code>BuildException</code>
+ */
+ public function initControlContext() {
+ $this->context->clear_all_assign();
+ return $this->context;
+ }
+
+ /**
+ * Execute the input script with Velocity
+ *
+ * @throws BuildException
+ * BuildExceptions are thrown when required attributes are missing.
+ * Exceptions thrown by Velocity are rethrown as BuildExceptions.
+ */
+ public function main() {
+
+ // Make sure the template path is set.
+ if (empty($this->templatePath)) {
+ throw new BuildException("The template path needs to be defined!");
+ }
+
+ // Make sure the control template is set.
+ if ($this->controlTemplate === null) {
+ throw new BuildException("The control template needs to be defined!");
+ }
+
+ // Make sure the output directory is set.
+ if ($this->outputDirectory === null) {
+ throw new BuildException("The output directory needs to be defined!");
+ }
+
+ // Make sure there is an output file.
+ if ($this->outputFile === null) {
+ throw new BuildException("The output file needs to be defined!");
+ }
+
+ // Setup Smarty runtime.
+
+ // Smarty uses one object to store properties and to store
+ // the context for the template (unlike Velocity). We setup this object, calling it
+ // $this->context, and then initControlContext simply zeros out
+ // any assigned variables.
+ $this->context = new Smarty();
+
+ if ($this->compilePath !== null) {
+ $this->log("Using compilePath: " . $this->compilePath);
+ $this->context->compile_dir = $this->compilePath;
+ }
+
+ if ($this->configPath !== null) {
+ $this->log("Using configPath: " . $this->configPath);
+ $this->context->config_dir = $this->configPath;
+ }
+
+ if ($this->forceCompile !== null) {
+ $this->context->force_compile = $this->forceCompile;
+ }
+
+ if ($this->leftDelimiter !== null) {
+ $this->context->left_delimiter = $this->leftDelimiter;
+ }
+
+ if ($this->rightDelimiter !== null) {
+ $this->context->right_delimiter = $this->rightDelimiter;
+ }
+
+ if ($this->templatePath !== null) {
+ $this->log("Using templatePath: " . $this->templatePath);
+ $this->context->template_dir = $this->templatePath;
+ }
+
+ $smartyCompilePath = new PhingFile($this->context->compile_dir);
+ if (!$smartyCompilePath->exists()) {
+ $this->log("Compile directory does not exist, creating: " . $smartyCompilePath->getPath(), PROJECT_MSG_VERBOSE);
+ if (!$smartyCompilePath->mkdirs()) {
+ throw new BuildException("Smarty needs a place to compile templates; specify a 'compilePath' or create ".$this->context->compile_dir);
+ }
+ }
+
+ // Make sure the output directory exists, if it doesn't
+ // then create it.
+ $file = new PhingFile($this->outputDirectory);
+ if (!$file->exists()) {
+ $this->log("Output directory does not exist, creating: " . $file->getAbsolutePath());
+ $file->mkdirs();
+ }
+
+ $path = $this->outputDirectory . DIRECTORY_SEPARATOR . $this->outputFile;
+ $this->log("Generating to file " . $path);
+
+ $writer = new FileWriter($path);
+
+ // The generator and the output path should
+ // be placed in the init context here and
+ // not in the generator class itself.
+ $c = $this->initControlContext();
+
+ // Set any variables that need to always
+ // be loaded
+ $this->populateInitialContext($c);
+
+ // Feed all the options into the initial
+ // control context so they are available
+ // in the control/worker templates.
+ if ($this->contextProperties !== null) {
+
+ foreach($this->contextProperties->keys() as $property) {
+
+ $value = $this->contextProperties->getProperty($property);
+
+ // Special exception (from Texen)
+ // for properties ending in file.contents:
+ // in that case we dump the contents of the file
+ // as the "value" for the Property.
+ if (StringHelper::endsWith("file.contents", $property)) {
+ // pull in contents of file specified
+
+ $property = substr($property, 0, strpos($property, "file.contents") - 1);
+
+ // reset value, and then
+ // read in teh contents of the file into that var
+ $value = "";
+ $f = new PhingFile($project->resolveFile($value)->getCanonicalPath());
+ if ($f->exists()) {
+ try {
+ $fr = new FileReader($f);
+ $fr->readInto($value);
+ } catch (Exception $e) {
+ throw $e;
+ }
+ }
+
+ } // if ends with file.contents
+
+ if (StringHelper::isBoolean($value)) {
+ $value = StringHelper::booleanValue($value);
+ }
+
+ $c->assign($property, $value);
+
+ } // foreach property
+
+ } // if contextProperties !== null
+
+ try {
+ //$c->display($this->controlTemplate);
+ $writer->write($c->fetch($this->controlTemplate));
+ $writer->close();
+ } catch (IOException $ioe) {
+ $writer->close();
+ throw new BuildException("Cannot write parsed template.");
+ }
+
+ $this->cleanup();
+ }
+
+ /**
+ * <p>Place useful objects into the initial context.</p>
+ *
+ * <p>TexenTask places <code>Date().toString()</code> into the
+ * context as <code>$now</code>. Subclasses who want to vary the
+ * objects in the context should override this method.</p>
+ *
+ * <p><code>$generator</code> is not put into the context in this
+ * method.</p>
+ *
+ * @param context The context to populate, as retrieved from
+ * {@link #initControlContext()}.
+ * @return void
+ * @throws Exception Error while populating context. The {@link
+ * #execute()} method will catch and rethrow as a
+ * <code>BuildException</code>.
+ */
+ protected function populateInitialContext(Smarty $context) {
+ }
+
+ /**
+ * A hook method called at the end of {@link #execute()} which can
+ * be overridden to perform any necessary cleanup activities (such
+ * as the release of database connections, etc.). By default,
+ * does nothing.
+ * @return void
+ * @throws Exception Problem cleaning up.
+ */
+ protected function cleanup() {
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/ext/TarTask.php b/buildscripts/phing/classes/phing/tasks/ext/TarTask.php
new file mode 100644
index 00000000..8d6bb47f
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/TarTask.php
@@ -0,0 +1,380 @@
+<?php
+/*
+ * $Id: TarTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/tasks/system/MatchingTask.php';
+include_once 'phing/util/SourceFileScanner.php';
+include_once 'phing/mappers/MergeMapper.php';
+include_once 'phing/util/StringHelper.php';
+
+/**
+ * Creates a tar archive using PEAR Archive_Tar.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Stefano Mazzocchi <stefano@apache.org> (Ant)
+ * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant)
+ * @author Magesh Umasankar
+ * @version $Revision: 1.10 $
+ * @package phing.tasks.ext
+ */
+class TarTask extends MatchingTask {
+
+ const TAR_NAMELEN = 100;
+
+ const WARN = "warn";
+ const FAIL = "fail";
+ const OMIT = "omit";
+
+ private $tarFile;
+ private $baseDir;
+
+ private $longFileMode = "warn";
+
+ private $filesets = array();
+ private $fileSetFiles = array();
+
+ /**
+ * Indicates whether the user has been warned about long files already.
+ */
+ private $longWarningGiven = false;
+
+ /**
+ * Compression mode. Available options "gzip", "bzip2", "none" (null).
+ */
+ private $compression = null;
+
+ /**
+ * Ensures that PEAR lib exists.
+ */
+ public function init() {
+ include_once 'Archive/Tar.php';
+ if (!class_exists('Archive_Tar')) {
+ throw new BuildException("You must have installed the PEAR Archive_Tar class in order to use TarTask.");
+ }
+ }
+
+ /**
+ * Add a new fileset
+ * @return FileSet
+ */
+ public function createTarFileSet() {
+ $this->fileset = new TarFileSet();
+ $this->filesets[] = $this->fileset;
+ return $this->fileset;
+ }
+
+ /**
+ * Add a new fileset. Alias to createTarFileSet() for backwards compatibility.
+ * @return FileSet
+ * @see createTarFileSet()
+ */
+ public function createFileSet() {
+ $this->fileset = new TarFileSet();
+ $this->filesets[] = $this->fileset;
+ return $this->fileset;
+ }
+
+ /**
+ * Set is the name/location of where to create the tar file.
+ * @param PhingFile $destFile The output of the tar
+ */
+ public function setDestFile(PhingFile $destFile) {
+ $this->tarFile = $destFile;
+ }
+
+ /**
+ * This is the base directory to look in for things to tar.
+ * @param PhingFile $baseDir
+ */
+ public function setBasedir(PhingFile $baseDir) {
+ $this->baseDir = $baseDir;
+ }
+
+ /**
+ * Set how to handle long files, those with a path&gt;100 chars.
+ * Optional, default=warn.
+ * <p>
+ * Allowable values are
+ * <ul>
+ * <li> truncate - paths are truncated to the maximum length
+ * <li> fail - paths greater than the maximim cause a build exception
+ * <li> warn - paths greater than the maximum cause a warning and GNU is used
+ * <li> gnu - GNU extensions are used for any paths greater than the maximum.
+ * <li> omit - paths greater than the maximum are omitted from the archive
+ * </ul>
+ */
+ public function setLongfile($mode) {
+ $this->longFileMode = $mode;
+ }
+
+ /**
+ * Set compression method.
+ * Allowable values are
+ * <ul>
+ * <li> none - no compression
+ * <li> gzip - Gzip compression
+ * <li> bzip2 - Bzip2 compression
+ * </ul>
+ */
+ public function setCompression($mode) {
+ switch($mode) {
+ case "gzip":
+ $this->compression = "gz";
+ break;
+ case "bzip2":
+ $this->compression = "bz2";
+ break;
+ case "none":
+ $this->compression = null;
+ break;
+ default:
+ $this->log("Ignoring unknown compression mode: ".$mode, PROJECT_MSG_WARN);
+ $this->compression = null;
+ }
+ }
+
+ /**
+ * do the work
+ * @throws BuildException
+ */
+ public function main() {
+
+ if ($this->tarFile === null) {
+ throw new BuildException("tarfile attribute must be set!", $this->getLocation());
+ }
+
+ if ($this->tarFile->exists() && $this->tarFile->isDirectory()) {
+ throw new BuildException("tarfile is a directory!", $this->getLocation());
+ }
+
+ if ($this->tarFile->exists() && !$this->tarFile->canWrite()) {
+ throw new BuildException("Can not write to the specified tarfile!", $this->getLocation());
+ }
+
+ // shouldn't need to clone, since the entries in filesets
+ // themselves won't be modified -- only elements will be added
+ $savedFileSets = $this->filesets;
+
+ try {
+ if ($this->baseDir !== null) {
+ if (!$this->baseDir->exists()) {
+ throw new BuildException("basedir does not exist!", $this->getLocation());
+ }
+
+ // add the main fileset to the list of filesets to process.
+ $mainFileSet = new TarFileSet($this->fileset);
+ $mainFileSet->setDir($this->baseDir);
+ $this->filesets[] = $mainFileSet;
+ }
+
+ if (empty($this->filesets)) {
+ throw new BuildException("You must supply either a basedir "
+ . "attribute or some nested filesets.",
+ $this->getLocation());
+ }
+
+ // check if tar is out of date with respect to each
+ // fileset
+ $upToDate = true;
+ foreach($this->filesets as $fs) {
+ $files = $fs->getFiles($this->project);
+ if (!$this->archiveIsUpToDate($files, $fs->getDir($this->project))) {
+ $upToDate = false;
+ }
+ for ($i=0, $fcount=count($files); $i < $fcount; $i++) {
+ if ($this->tarFile->equals(new PhingFile($fs->getDir($this->project), $files[$i]))) {
+ throw new BuildException("A tar file cannot include itself", $this->getLocation());
+ }
+ }
+ }
+
+ if ($upToDate) {
+ $this->log("Nothing to do: " . $this->tarFile->__toString() . " is up to date.", PROJECT_MSG_INFO);
+ return;
+ }
+
+ $this->log("Building tar: " . $this->tarFile->__toString(), PROJECT_MSG_INFO);
+
+ $tar = new Archive_Tar($this->tarFile->getAbsolutePath(), $this->compression);
+
+ // print errors
+ $tar->setErrorHandling(PEAR_ERROR_PRINT);
+
+ foreach($this->filesets as $fs) {
+ $files = $fs->getFiles($this->project);
+ if (count($files) > 1 && strlen($fs->getFullpath()) > 0) {
+ throw new BuildException("fullpath attribute may only "
+ . "be specified for "
+ . "filesets that specify a "
+ . "single file.");
+ }
+ // FIXME
+ // Current model is only adding directories implicitly. This
+ // won't add any empty directories. Perhaps modify TarFileSet::getFiles()
+ // to also include empty directories. Not high priority, since non-inclusion
+ // of empty dirs is probably not unexpected behavior for TarTask.
+ $fsBasedir = $fs->getDir($this->project);
+ $filesToTar = array();
+ for ($i=0, $fcount=count($files); $i < $fcount; $i++) {
+ $f = new PhingFile($fsBasedir, $files[$i]);
+ $filesToTar[] = $f->getAbsolutePath();
+ }
+ $tar->addModify($filesToTar, '', $fsBasedir->getAbsolutePath());
+ }
+
+
+ } catch (IOException $ioe) {
+ $msg = "Problem creating TAR: " . $ioe->getMessage();
+ $this->filesets = $savedFileSets;
+ throw new BuildException($msg, $ioe, $this->getLocation());
+ }
+
+ $this->filesets = $savedFileSets;
+ }
+
+ /**
+ * @param array $files array of filenames
+ * @param PhingFile $dir
+ * @return boolean
+ */
+ protected function archiveIsUpToDate($files, $dir) {
+ $sfs = new SourceFileScanner($this);
+ $mm = new MergeMapper();
+ $mm->setTo($this->tarFile->getAbsolutePath());
+ return count($sfs->restrict($files, $dir, null, $mm)) == 0;
+ }
+
+}
+
+
+/**
+ * This is a FileSet with the option to specify permissions.
+ *
+ * Permissions are currently not implemented by PEAR Archive_Tar,
+ * but hopefully they will be in the future.
+ *
+ */
+class TarFileSet extends FileSet {
+
+ private $files = null;
+
+ private $mode = 0100644;
+
+ private $userName = "";
+ private $groupName = "";
+ private $prefix = "";
+ private $fullpath = "";
+ private $preserveLeadingSlashes = false;
+
+ /**
+ * Get a list of files and directories specified in the fileset.
+ * @return array a list of file and directory names, relative to
+ * the baseDir for the project.
+ */
+ public function getFiles(Project $p) {
+ if ($this->files === null) {
+ $ds = $this->getDirectoryScanner($p);
+ $this->files = $ds->getIncludedFiles();
+ }
+ return $this->files;
+ }
+
+ /**
+ * A 3 digit octal string, specify the user, group and
+ * other modes in the standard Unix fashion;
+ * optional, default=0644
+ * @param string $octalString
+ */
+ public function setMode($octalString) {
+ $octal = (int) $octalString;
+ $this->mode = 0100000 | $octal;
+ }
+
+ public function getMode() {
+ return $this->mode;
+ }
+
+ /**
+ * The username for the tar entry
+ * This is not the same as the UID, which is
+ * not currently set by the task.
+ */
+ public function setUserName($userName) {
+ $this->userName = $userName;
+ }
+
+ public function getUserName() {
+ return $this->userName;
+ }
+
+ /**
+ * The groupname for the tar entry; optional, default=""
+ * This is not the same as the GID, which is
+ * not currently set by the task.
+ */
+ public function setGroup($groupName) {
+ $this->groupName = $groupName;
+ }
+
+ public function getGroup() {
+ return $this->groupName;
+ }
+
+ /**
+ * If the prefix attribute is set, all files in the fileset
+ * are prefixed with that path in the archive.
+ * optional.
+ */
+ public function setPrefix($prefix) {
+ $this->prefix = $prefix;
+ }
+
+ public function getPrefix() {
+ return $this->prefix;
+ }
+
+ /**
+ * If the fullpath attribute is set, the file in the fileset
+ * is written with that path in the archive. The prefix attribute,
+ * if specified, is ignored. It is an error to have more than one file specified in
+ * such a fileset.
+ */
+ public function setFullpath($fullpath) {
+ $this->fullpath = $fullpath;
+ }
+
+ public function getFullpath() {
+ return $this->fullpath;
+ }
+
+ /**
+ * Flag to indicates whether leading `/'s should
+ * be preserved in the file names.
+ * Optional, default is <code>false</code>.
+ * @return void
+ */
+ public function setPreserveLeadingSlashes($b) {
+ $this->preserveLeadingSlashes = (boolean) $b;
+ }
+
+ public function getPreserveLeadingSlashes() {
+ return $this->preserveLeadingSlashes;
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/ext/XmlLintTask.php b/buildscripts/phing/classes/phing/tasks/ext/XmlLintTask.php
new file mode 100644
index 00000000..866e954d
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/XmlLintTask.php
@@ -0,0 +1,116 @@
+<?php
+require_once 'phing/Task.php';
+
+/**
+ * A XML lint task. Checking syntax of one or more XML files against an XML Schema using the DOM extension.
+ *
+ * @author Knut Urdalen <knut.urdalen@telio.no>
+ * @package phing.tasks.ext
+ */
+class XmlLintTask extends Task {
+
+ protected $file; // the source file (from xml attribute)
+ protected $schema; // the schema file (from xml attribute)
+ protected $filesets = array(); // all fileset objects assigned to this task
+
+ /**
+ * File to be performed syntax check on
+ *
+ * @param PhingFile $file
+ */
+ public function setFile(PhingFile $file) {
+ $this->file = $file;
+ }
+
+ /**
+ * XML Schema Description file to validate against
+ *
+ * @param PhingFile $schema
+ */
+ public function setSchema(PhingFile $schema) {
+ $this->schema = $schema;
+ }
+
+ /**
+ * Nested creator, creates a FileSet for this task
+ *
+ * @return FileSet The created fileset object
+ */
+ function createFileSet() {
+ $num = array_push($this->filesets, new FileSet());
+ return $this->filesets[$num-1];
+ }
+
+ /**
+ * Execute lint check against PhingFile or a FileSet
+ */
+ public function main() {
+ if(!isset($this->schema)) {
+ throw new BuildException("Missing attribute 'schema'");
+ }
+ $schema = $this->schema->getPath();
+ if(!file_exists($schema)) {
+ throw new BuildException("File not found: ".$schema);
+ }
+ if(!isset($this->file) and count($this->filesets) == 0) {
+ throw new BuildException("Missing either a nested fileset or attribute 'file' set");
+ }
+
+ set_error_handler(array($this, 'errorHandler'));
+ if($this->file instanceof PhingFile) {
+ $this->lint($this->file->getPath());
+ } else { // process filesets
+ $project = $this->getProject();
+ foreach($this->filesets as $fs) {
+ $ds = $fs->getDirectoryScanner($project);
+ $files = $ds->getIncludedFiles();
+ $dir = $fs->getDir($this->project)->getPath();
+ foreach($files as $file) {
+ $this->lint($dir.DIRECTORY_SEPARATOR.$file);
+ }
+ }
+ }
+ restore_error_handler();
+ }
+
+ /**
+ * Performs validation
+ *
+ * @param string $file
+ * @return void
+ */
+ protected function lint($file) {
+ if(file_exists($file)) {
+ if(is_readable($file)) {
+ $dom = new DOMDocument();
+ $dom->load($file);
+ if($dom->schemaValidate($this->schema->getPath())) {
+ $this->log($file.' validated', PROJECT_MSG_INFO);
+ } else {
+ $this->log($file.' fails to validate (See messages above)', PROJECT_MSG_ERR);
+ }
+ } else {
+ throw new BuildException('Permission denied: '.$file);
+ }
+ } else {
+ throw new BuildException('File not found: '.$file);
+ }
+ }
+
+ /**
+ * Local error handler to catch validation errors and log them through Phing
+ *
+ * @param int $level
+ * @param string $message
+ * @param string $file
+ * @param int $line
+ */
+ public function errorHandler($level, $message, $file, $line, $context) {
+ $matches = array();
+ preg_match('/^.*\(\): (.*)$/', $message, $matches);
+ $this->log($matches[1], PROJECT_MSG_ERR);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/ZendCodeAnalyzerTask.php b/buildscripts/phing/classes/phing/tasks/ext/ZendCodeAnalyzerTask.php
new file mode 100644
index 00000000..490ee797
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/ZendCodeAnalyzerTask.php
@@ -0,0 +1,163 @@
+<?php
+require_once 'phing/Task.php';
+
+/**
+ * ZendCodeAnalyzerTask analyze PHP source code using the ZendCodeAnalyzer included in Zend Studio 5.1
+ *
+ * Available warnings:
+ * <b>zend-error</b> - %s(line %d): %s
+ * <b>oneline-comment</b> - One-line comment ends with ?> tag.
+ * <b>bool-assign</b> - Assignment seen where boolean expression is expected. Did you mean '==' instead of '='?
+ * <b>bool-print</b> - Print statement used when boolean expression is expected.
+ * <b>bool-array</b> - Array used when boolean expression is expected.
+ * <b>bool-object</b> - Object used when boolean expression is expected.
+ * <b>call-time-ref</b> - Call-time reference is deprecated. Define function as accepting parameter by reference instead.
+ * <b>if-if-else</b> - In if-if-else construction else relates to the closest if. Use braces to make the code clearer.
+ * <b>define-params</b> - define() requires two or three parameters.
+ * <b>define-const</b> - First parameter for define() should be string. Maybe you forgot quotes?
+ * <b>break-var</b> - Break/continue with variable is dangerous - break level can be out of scope.
+ * <b>break-depth</b> - Break/continue with depth more than current nesting level.
+ * <b>var-once</b> - Variable '%s' encountered only once. May be a typo?
+ * <b>var-arg-unused</b> - Function argument '%s' is never used.
+ * <b>var-global-unused</b> - Global variable '%s' is defined but never used.
+ * <b>var-use-before-def</b> - Variable '%s' is used before it was assigned.
+ * <b>var-use-before-def-global</b> - Global variable '%s' is used without being assigned. You are probably relying on register_globals feature of PHP. Note that this feature is off by default.
+ * <b>var-no-global</b> - PHP global variable '%s' is used as local. Maybe you wanted to define '%s' as global?
+ * <b>var-value-unused</b> - Value assigned to variable '%s' is never used
+ * <b>var-ref-notmodified</b> - Function parameter '%s' is passed by reference but never modified. Consider passing by value.
+ * <b>return-empty-val</b> - Function '%s' has both empty return and return with value.
+ * <b>return-empty-used</b> - Function '%s' has empty return but return value is used.
+ * <b>return-noref</b> - Function '%s' returns reference but the value is not assigned by reference. Maybe you meant '=&' instead of '='?
+ * <b>return-end-used</b> - Control reaches the end of function '%s'(file %s, line %d) but return value is used.
+ * <b>sprintf-miss-args</b> - Missing arguments for sprintf: format reqires %d arguments but %d are supplied.
+ * <b>sprintf-extra-args</b> - Extra arguments for sprintf: format reqires %d arguments but %d are supplied.
+ * <b>unreach-code</b> - Unreachable code in function '%s'.
+ * <b>include-var</b> - include/require with user-accessible variable can be dangerous. Consider using constant instead.
+ * <b>non-object</b> - Variable '%s' used as object, but has different type.
+ * <b>bad-escape</b> - Bad escape sequence: \%c, did you mean \\%c?
+ * <b>empty-cond</b> - Condition without a body
+ * <b>expr-unused</b> - Expression result is never used
+ *
+ * @author Knut Urdalen <knut.urdalen@telio.no>
+ * @package phing.tasks.ext
+ */
+class ZendCodeAnalyzerTask extends Task {
+
+ protected $analyzerPath = ""; // Path to ZendCodeAnalyzer binary
+ protected $file = ""; // the source file (from xml attribute)
+ protected $filesets = array(); // all fileset objects assigned to this task
+ protected $warnings = array();
+ protected $counter = 0;
+ protected $disable = array();
+ protected $enable = array();
+
+ /**
+ * File to be analyzed
+ *
+ * @param PhingFile $file
+ */
+ public function setFile(PhingFile $file) {
+ $this->file = $file;
+ }
+
+ /**
+ * Path to ZendCodeAnalyzer binary
+ *
+ * @param string $analyzerPath
+ */
+ public function setAnalyzerPath($analyzerPath) {
+ $this->analyzerPath = $analyzerPath;
+ }
+
+ /**
+ * Disable warning levels. Seperate warning levels with ','
+ *
+ * @param string $disable
+ */
+ public function setDisable($disable) {
+ $this->disable = explode(",", $disable);
+ }
+
+ /**
+ * Enable warning levels. Seperate warning levels with ','
+ *
+ * @param string $enable
+ */
+ public function setEnable($enable) {
+ $this->enable = explode(",", $enable);
+ }
+
+ /**
+ * Nested creator, creates a FileSet for this task
+ *
+ * @return FileSet The created fileset object
+ */
+ function createFileSet() {
+ $num = array_push($this->filesets, new FileSet());
+ return $this->filesets[$num-1];
+ }
+
+ /**
+ * Analyze against PhingFile or a FileSet
+ */
+ public function main() {
+ if(!isset($this->analyzerPath)) {
+ throw new BuildException("Missing attribute 'analyzerPath'");
+ }
+ if(!isset($this->file) and count($this->filesets) == 0) {
+ throw new BuildException("Missing either a nested fileset or attribute 'file' set");
+ }
+
+ if($this->file instanceof PhingFile) {
+ $this->analyze($this->file->getPath());
+ } else { // process filesets
+ $project = $this->getProject();
+ foreach($this->filesets as $fs) {
+ $ds = $fs->getDirectoryScanner($project);
+ $files = $ds->getIncludedFiles();
+ $dir = $fs->getDir($this->project)->getPath();
+ foreach($files as $file) {
+ $this->analyze($dir.DIRECTORY_SEPARATOR.$file);
+ }
+ }
+ }
+ $this->log("Number of findings: ".$this->counter, PROJECT_MSG_INFO);
+ }
+
+ /**
+ * Analyze file
+ *
+ * @param string $file
+ * @return void
+ */
+ protected function analyze($file) {
+ if(file_exists($file)) {
+ if(is_readable($file)) {
+
+ // Construct shell command
+ $cmd = $this->analyzerPath." ";
+ foreach($this->enable as $enable) { // Enable warning levels
+ $cmd .= " --enable $enable ";
+ }
+ foreach($this->disable as $disable) { // Disable warning levels
+ $cmd .= " --disable $disable ";
+ }
+ $cmd .= "$file 2>&1";
+
+ // Execute command
+ $result = shell_exec($cmd);
+ $result = explode("\n", $result);
+ for($i=2, $size=count($result); $i<($size-1); $i++) {
+ $this->counter++;
+ $this->log($result[$i], PROJECT_MSG_WARN);
+ }
+ } else {
+ throw new BuildException('Permission denied: '.$file);
+ }
+ } else {
+ throw new BuildException('File not found: '.$file);
+ }
+ }
+}
+
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/ZipTask.php b/buildscripts/phing/classes/phing/tasks/ext/ZipTask.php
new file mode 100644
index 00000000..33ef16ae
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/ZipTask.php
@@ -0,0 +1,176 @@
+<?php
+/*
+ * $Id: ZipTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/tasks/system/MatchingTask.php';
+include_once 'phing/util/SourceFileScanner.php';
+include_once 'phing/mappers/MergeMapper.php';
+include_once 'phing/util/StringHelper.php';
+include_once 'phing/lib/Zip.php';
+
+/**
+ * Creates a zip archive using PEAR Archive_Zip (which is presently unreleased
+ * and included with Phing).
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Revision: 1.2 $
+ * @package phing.tasks.ext
+ * @since 2.1.0
+ */
+class ZipTask extends MatchingTask {
+
+ private $zipFile;
+ private $baseDir;
+
+ private $filesets = array();
+ private $fileSetFiles = array();
+
+ /**
+ * Add a new fileset.
+ * @return FileSet
+ */
+ public function createFileSet() {
+ $this->fileset = new FileSet();
+ $this->filesets[] = $this->fileset;
+ return $this->fileset;
+ }
+
+ /**
+ * Set is the name/location of where to create the zip file.
+ * @param PhingFile $destFile The output of the zip
+ */
+ public function setDestFile(PhingFile $destFile) {
+ $this->zipFile = $destFile;
+ }
+
+ /**
+ * This is the base directory to look in for things to zip.
+ * @param PhingFile $baseDir
+ */
+ public function setBasedir(PhingFile $baseDir) {
+ $this->baseDir = $baseDir;
+ }
+
+ /**
+ * do the work
+ * @throws BuildException
+ */
+ public function main() {
+
+ if ($this->zipFile === null) {
+ throw new BuildException("zipfile attribute must be set!", $this->getLocation());
+ }
+
+ if ($this->zipFile->exists() && $this->zipFile->isDirectory()) {
+ throw new BuildException("zipfile is a directory!", $this->getLocation());
+ }
+
+ if ($this->zipFile->exists() && !$this->zipFile->canWrite()) {
+ throw new BuildException("Can not write to the specified zipfile!", $this->getLocation());
+ }
+
+ // shouldn't need to clone, since the entries in filesets
+ // themselves won't be modified -- only elements will be added
+ $savedFileSets = $this->filesets;
+
+ try {
+ if ($this->baseDir !== null) {
+ if (!$this->baseDir->exists()) {
+ throw new BuildException("basedir does not exist!", $this->getLocation());
+ }
+
+ // add the main fileset to the list of filesets to process.
+ $mainFileSet = new FileSet($this->fileset);
+ $mainFileSet->setDir($this->baseDir);
+ $this->filesets[] = $mainFileSet;
+ }
+
+ if (empty($this->filesets)) {
+ throw new BuildException("You must supply either a basedir "
+ . "attribute or some nested filesets.",
+ $this->getLocation());
+ }
+
+ // check if zip is out of date with respect to each
+ // fileset
+ $upToDate = true;
+ foreach($this->filesets as $fs) {
+ $ds = $fs->getDirectoryScanner($this->project);
+ $files = $ds->getIncludedFiles();
+ if (!$this->archiveIsUpToDate($files, $fs->getDir($this->project))) {
+ $upToDate = false;
+ }
+ for ($i=0, $fcount=count($files); $i < $fcount; $i++) {
+ if ($this->zipFile->equals(new PhingFile($fs->getDir($this->project), $files[$i]))) {
+ throw new BuildException("A zip file cannot include itself", $this->getLocation());
+ }
+ }
+ }
+
+ if ($upToDate) {
+ $this->log("Nothing to do: " . $this->zipFile->__toString() . " is up to date.", PROJECT_MSG_INFO);
+ return;
+ }
+
+ $this->log("Building zip: " . $this->zipFile->__toString(), PROJECT_MSG_INFO);
+
+ $zip = new Archive_Zip($this->zipFile->getAbsolutePath());
+
+ foreach($this->filesets as $fs) {
+ $ds = $fs->getDirectoryScanner($this->project);
+ $files = $ds->getIncludedFiles();
+
+ // FIXME
+ // Current model is only adding directories implicitly. This
+ // won't add any empty directories. Perhaps modify FileSet::getFiles()
+ // to also include empty directories. Not high priority, since non-inclusion
+ // of empty dirs is probably not unexpected behavior for ZipTask.
+ $fsBasedir = $fs->getDir($this->project);
+ $filesToZip = array();
+ for ($i=0, $fcount=count($files); $i < $fcount; $i++) {
+ $f = new PhingFile($fsBasedir, $files[$i]);
+ $filesToZip[] = $f->getAbsolutePath();
+ }
+ $zip->add($filesToZip, array('remove_path' => $fsBasedir->getPath()));
+ }
+
+
+ } catch (IOException $ioe) {
+ $msg = "Problem creating ZIP: " . $ioe->getMessage();
+ $this->filesets = $savedFileSets;
+ throw new BuildException($msg, $ioe, $this->getLocation());
+ }
+
+ $this->filesets = $savedFileSets;
+ }
+
+ /**
+ * @param array $files array of filenames
+ * @param PhingFile $dir
+ * @return boolean
+ */
+ protected function archiveIsUpToDate($files, $dir) {
+ $sfs = new SourceFileScanner($this);
+ $mm = new MergeMapper();
+ $mm->setTo($this->zipFile->getAbsolutePath());
+ return count($sfs->restrict($files, $dir, null, $mm)) == 0;
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMerger.php b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMerger.php
new file mode 100644
index 00000000..99bcc7c4
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMerger.php
@@ -0,0 +1,127 @@
+<?php
+/**
+ * $Id: CoverageMerger.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/system/util/Properties.php';
+
+/**
+ * Saves coverage output of the test to a specified database
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: CoverageMerger.php 59 2006-04-28 14:49:47Z mrook $
+ * @package phing.tasks.ext.coverage
+ * @since 2.1.0
+ */
+class CoverageMerger
+{
+ private static function mergeCodeCoverage($left, $right)
+ {
+ $coverageMerged = array();
+
+ reset($left);
+ reset($right);
+
+ while (current($left) && current($right))
+ {
+ $linenr_left = key($left);
+ $linenr_right = key($right);
+
+ if ($linenr_left < $linenr_right)
+ {
+ $coverageMerged[$linenr_left] = current($left);
+
+ next($left);
+ }
+ else
+ if ($linenr_right < $linenr_left)
+ {
+ $coverageMerged[$linenr_right] = current($right);
+ next($right);
+ }
+ else
+ {
+ if (current($left) < 0)
+ {
+ $coverageMerged[$linenr_right] = current($right);
+ }
+ else
+ if (current($right) < 0)
+ {
+ $coverageMerged[$linenr_right] = current($left);
+ }
+ else
+ {
+ $coverageMerged[$linenr_right] = current($left) + current($right);
+ }
+
+ next($left);
+ next($right);
+ }
+ }
+
+ while (current($left))
+ {
+ $coverageMerged[key($left)] = current($left);
+ next($left);
+ }
+
+ while (current($right))
+ {
+ $coverageMerged[key($right)] = current($right);
+ next($right);
+ }
+
+ return $coverageMerged;
+ }
+
+ static function merge($project, $codeCoverageInformation)
+ {
+ $database = new PhingFile($project->getProperty('coverage.database'));
+
+ $props = new Properties();
+ $props->load($database);
+
+ $coverageTotal = $codeCoverageInformation;
+
+ foreach ($coverageTotal as $coverage)
+ {
+ foreach ($coverage as $filename => $coverageFile)
+ {
+ $filename = strtolower($filename);
+
+ if ($props->getProperty($filename) != null)
+ {
+ $file = unserialize($props->getProperty($filename));
+ $left = $file['coverage'];
+ $right = $coverageFile;
+
+ $coverageMerged = CoverageMerger::mergeCodeCoverage($left, $right);
+
+ $file['coverage'] = $coverageMerged;
+
+ $props->setProperty($filename, serialize($file));
+ }
+ }
+ }
+
+ $props->store($database);
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMergerTask.php b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMergerTask.php
new file mode 100644
index 00000000..4a78df6f
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageMergerTask.php
@@ -0,0 +1,92 @@
+<?php
+/**
+ * $Id: CoverageMergerTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+require_once 'phing/system/io/PhingFile.php';
+require_once 'phing/system/io/Writer.php';
+require_once 'phing/system/util/Properties.php';
+require_once 'phing/tasks/ext/coverage/CoverageMerger.php';
+
+/**
+ * Merges code coverage snippets into a code coverage database
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: CoverageMergerTask.php 59 2006-04-28 14:49:47Z mrook $
+ * @package phing.tasks.ext.coverage
+ * @since 2.1.0
+ */
+class CoverageMergerTask extends Task
+{
+ /** the list of filesets containing the .php filename rules */
+ private $filesets = array();
+
+ /**
+ * Add a new fileset containing the .php files to process
+ *
+ * @param FileSet the new fileset containing .php files
+ */
+ function addFileSet(FileSet $fileset)
+ {
+ $this->filesets[] = $fileset;
+ }
+
+ /**
+ * Iterate over all filesets and return all the filenames.
+ *
+ * @return array an array of filenames
+ */
+ private function getFilenames()
+ {
+ $files = array();
+
+ foreach ($this->filesets as $fileset)
+ {
+ $ds = $fileset->getDirectoryScanner($this->project);
+ $ds->scan();
+
+ $includedFiles = $ds->getIncludedFiles();
+
+ foreach ($includedFiles as $file)
+ {
+ $fs = new PhingFile(basename($ds->getBaseDir()), $file);
+
+ $files[] = $fs->getAbsolutePath();
+ }
+ }
+
+ return $files;
+ }
+
+ function main()
+ {
+ $files = $this->getFilenames();
+
+ $this->log("Merging " . count($files) . " coverage files");
+
+ foreach ($files as $file)
+ {
+ $coverageInformation = unserialize(file_get_contents($file));
+
+ CoverageMerger::merge($this->project, array($coverageInformation));
+ }
+ }
+}
+?>
diff --git a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTask.php b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTask.php
new file mode 100644
index 00000000..72fa57a7
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTask.php
@@ -0,0 +1,406 @@
+<?php
+/**
+ * $Id: CoverageReportTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+require_once 'phing/system/io/PhingFile.php';
+require_once 'phing/system/io/Writer.php';
+require_once 'phing/system/util/Properties.php';
+require_once 'phing/tasks/ext/phpunit2/PHPUnit2Util.php';
+require_once 'phing/tasks/ext/coverage/CoverageReportTransformer.php';
+
+/**
+ * Transforms information in a code coverage database to XML
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: CoverageReportTask.php 59 2006-04-28 14:49:47Z mrook $
+ * @package phing.tasks.ext.coverage
+ * @since 2.1.0
+ */
+class CoverageReportTask extends Task
+{
+ private $outfile = "coverage.xml";
+
+ private $transformers = array();
+
+ /** the classpath to use (optional) */
+ private $classpath = NULL;
+
+ /** the path to the GeSHi library (optional) */
+ private $geshipath = "";
+
+ /** the path to the GeSHi language files (optional) */
+ private $geshilanguagespath = "";
+
+ function setClasspath(Path $classpath)
+ {
+ if ($this->classpath === null)
+ {
+ $this->classpath = $classpath;
+ }
+ else
+ {
+ $this->classpath->append($classpath);
+ }
+ }
+
+ function createClasspath()
+ {
+ $this->classpath = new Path();
+ return $this->classpath;
+ }
+
+ function setGeshiPath($path)
+ {
+ $this->geshipath = $path;
+ }
+
+ function setGeshiLanguagesPath($path)
+ {
+ $this->geshilanguagespath = $path;
+ }
+
+ function __construct()
+ {
+ $this->doc = new DOMDocument();
+ $this->doc->encoding = 'UTF-8';
+ $this->doc->formatOutput = true;
+ $this->doc->appendChild($this->doc->createElement('snapshot'));
+ }
+
+ function setOutfile($outfile)
+ {
+ $this->outfile = $outfile;
+ }
+
+ /**
+ * Generate a report based on the XML created by this task
+ */
+ function createReport()
+ {
+ $transformer = new CoverageReportTransformer($this);
+ $this->transformers[] = $transformer;
+ return $transformer;
+ }
+
+ protected function getPackageElement($packageName)
+ {
+ $packages = $this->doc->documentElement->getElementsByTagName('package');
+
+ foreach ($packages as $package)
+ {
+ if ($package->getAttribute('name') == $packageName)
+ {
+ return $package;
+ }
+ }
+
+ return NULL;
+ }
+
+ protected function addClassToPackage($classname, $element)
+ {
+ $packageName = PHPUnit2Util::getPackageName($classname);
+
+ $package = $this->getPackageElement($packageName);
+
+ if ($package === NULL)
+ {
+ $package = $this->doc->createElement('package');
+ $package->setAttribute('name', $packageName);
+ $this->doc->documentElement->appendChild($package);
+ }
+
+ $package->appendChild($element);
+ }
+
+ protected function stripDiv($source)
+ {
+ $openpos = strpos($source, "<div");
+ $closepos = strpos($source, ">", $openpos);
+
+ $line = substr($source, $closepos + 1);
+
+ $tagclosepos = strpos($line, "</div>");
+
+ $line = substr($line, 0, $tagclosepos);
+
+ return $line;
+ }
+
+ protected function highlightSourceFile($filename)
+ {
+ if ($this->geshipath)
+ {
+ require_once $this->geshipath . '/geshi.php';
+
+ $source = file_get_contents($filename);
+
+ $geshi = new GeSHi($source, 'php', $this->geshilanguagespath);
+
+ $geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS);
+
+ $geshi->enable_strict_mode(true);
+
+ $geshi->enable_classes(true);
+
+ $geshi->set_url_for_keyword_group(3, '');
+
+ $html = $geshi->parse_code();
+
+ $lines = split("<li>|</li>", $html);
+
+ // skip first and last line
+ array_pop($lines);
+ array_shift($lines);
+
+ $lines = array_filter($lines);
+
+ $lines = array_map(array($this, 'stripDiv'), $lines);
+
+ return $lines;
+ }
+ else
+ {
+ $lines = file($filename);
+
+ for ($i = 0; $i < count($lines); $i++)
+ {
+ $line = $lines[$i];
+
+ $line = rtrim($line);
+
+ $lines[$i] = utf8_encode($line);
+ }
+
+ return $lines;
+ }
+ }
+
+ protected function transformSourceFile($filename, $coverageInformation, $classStartLine = 1)
+ {
+ $sourceElement = $this->doc->createElement('sourcefile');
+ $sourceElement->setAttribute('name', basename($filename));
+
+ $filelines = $this->highlightSourceFile($filename);
+
+ $linenr = 1;
+
+ foreach ($filelines as $line)
+ {
+ $lineElement = $this->doc->createElement('sourceline');
+ $lineElement->setAttribute('coveredcount', (isset($coverageInformation[$linenr]) ? $coverageInformation[$linenr] : '0'));
+
+ if ($linenr == $classStartLine)
+ {
+ $lineElement->setAttribute('startclass', 1);
+ }
+
+ $textnode = $this->doc->createTextNode($line);
+ $lineElement->appendChild($textnode);
+
+ $sourceElement->appendChild($lineElement);
+
+ $linenr++;
+ }
+
+ return $sourceElement;
+ }
+
+ protected function filterCovered($var)
+ {
+ return ($var >= 0);
+ }
+
+ protected function transformCoverageInformation($filename, $coverageInformation)
+ {
+ $classes = PHPUnit2Util::getDefinedClasses($filename, $this->classpath);
+
+ if (is_array($classes))
+ {
+ foreach ($classes as $classname)
+ {
+ $reflection = new ReflectionClass($classname);
+
+ $methods = $reflection->getMethods();
+
+ $classElement = $this->doc->createElement('class');
+ $classElement->setAttribute('name', $reflection->getName());
+
+ $this->addClassToPackage($reflection->getName(), $classElement);
+
+ $classStartLine = $reflection->getStartLine();
+
+ $methodscovered = 0;
+ $methodcount = 0;
+
+ end($coverageInformation);
+ unset($coverageInformation[key($coverageInformation)]);
+
+ // Strange PHP5 reflection bug, classes without parent class or implemented interfaces seem to start one line off
+ if ($reflection->getParentClass() == NULL && count($reflection->getInterfaces()) == 0)
+ {
+ unset($coverageInformation[$classStartLine + 1]);
+ }
+ else
+ {
+ unset($coverageInformation[$classStartLine]);
+ }
+
+ reset($coverageInformation);
+
+ foreach ($methods as $method)
+ {
+ // PHP5 reflection considers methods of a parent class to be part of a subclass, we don't
+ if ($method->getDeclaringClass()->getName() != $reflection->getName())
+ {
+ continue;
+ }
+
+ // small fix for XDEBUG_CC_UNUSED
+ if (isset($coverageInformation[$method->getStartLine()]))
+ {
+ unset($coverageInformation[$method->getStartLine()]);
+ }
+
+ if (isset($coverageInformation[$method->getEndLine()]))
+ {
+ unset($coverageInformation[$method->getEndLine()]);
+ }
+
+ if ($method->isAbstract())
+ {
+ continue;
+ }
+
+ $linenr = key($coverageInformation);
+
+ while ($linenr < $method->getStartLine())
+ {
+ next($coverageInformation);
+ $linenr = key($coverageInformation);
+ }
+
+ if (current($coverageInformation) > 0 && $method->getStartLine() <= $linenr && $linenr <= $method->getEndLine())
+ {
+ $methodscovered++;
+ }
+
+ $methodcount++;
+ }
+
+ $statementcount = count($coverageInformation);
+ $statementscovered = count(array_filter($coverageInformation, array($this, 'filterCovered')));
+
+ $classElement->appendChild($this->transformSourceFile($filename, $coverageInformation, $classStartLine));
+
+ $classElement->setAttribute('methodcount', $methodcount);
+ $classElement->setAttribute('methodscovered', $methodscovered);
+ $classElement->setAttribute('statementcount', $statementcount);
+ $classElement->setAttribute('statementscovered', $statementscovered);
+ $classElement->setAttribute('totalcount', $methodcount + $statementcount);
+ $classElement->setAttribute('totalcovered', $methodscovered + $statementscovered);
+ }
+ }
+ }
+
+ protected function calculateStatistics()
+ {
+ $packages = $this->doc->documentElement->getElementsByTagName('package');
+
+ $totalmethodcount = 0;
+ $totalmethodscovered = 0;
+
+ $totalstatementcount = 0;
+ $totalstatementscovered = 0;
+
+ foreach ($packages as $package)
+ {
+ $methodcount = 0;
+ $methodscovered = 0;
+
+ $statementcount = 0;
+ $statementscovered = 0;
+
+ $classes = $package->getElementsByTagName('class');
+
+ foreach ($classes as $class)
+ {
+ $methodcount += $class->getAttribute('methodcount');
+ $methodscovered += $class->getAttribute('methodscovered');
+
+ $statementcount += $class->getAttribute('statementcount');
+ $statementscovered += $class->getAttribute('statementscovered');
+ }
+
+ $package->setAttribute('methodcount', $methodcount);
+ $package->setAttribute('methodscovered', $methodscovered);
+
+ $package->setAttribute('statementcount', $statementcount);
+ $package->setAttribute('statementscovered', $statementscovered);
+
+ $package->setAttribute('totalcount', $methodcount + $statementcount);
+ $package->setAttribute('totalcovered', $methodscovered + $statementscovered);
+
+ $totalmethodcount += $methodcount;
+ $totalmethodscovered += $methodscovered;
+
+ $totalstatementcount += $statementcount;
+ $totalstatementscovered += $statementscovered;
+ }
+
+ $this->doc->documentElement->setAttribute('methodcount', $totalmethodcount);
+ $this->doc->documentElement->setAttribute('methodscovered', $totalmethodscovered);
+
+ $this->doc->documentElement->setAttribute('statementcount', $totalstatementcount);
+ $this->doc->documentElement->setAttribute('statementscovered', $totalstatementscovered);
+
+ $this->doc->documentElement->setAttribute('totalcount', $totalmethodcount + $totalstatementcount);
+ $this->doc->documentElement->setAttribute('totalcovered', $totalmethodscovered + $totalstatementscovered);
+ }
+
+ function main()
+ {
+ $this->log("Transforming coverage report");
+
+ $database = new PhingFile($this->project->getProperty('coverage.database'));
+
+ $props = new Properties();
+ $props->load($database);
+
+ foreach ($props->keys() as $filename)
+ {
+ $file = unserialize($props->getProperty($filename));
+
+ $this->transformCoverageInformation($file['fullname'], $file['coverage']);
+ }
+
+ $this->calculateStatistics();
+
+ $this->doc->save($this->outfile);
+
+ foreach ($this->transformers as $transformer)
+ {
+ $transformer->setXmlDocument($this->doc);
+ $transformer->transform();
+ }
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTransformer.php b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTransformer.php
new file mode 100644
index 00000000..b7fee32f
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageReportTransformer.php
@@ -0,0 +1,121 @@
+<?php
+/**
+ * $Id: CoverageReportTransformer.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+require_once 'phing/system/io/PhingFile.php';
+require_once 'phing/system/io/FileWriter.php';
+require_once 'phing/util/ExtendedFileStream.php';
+
+/**
+ * Transform a Phing/Xdebug code coverage xml report.
+ * The default transformation generates an html report in framed style.
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: CoverageReportTransformer.php 59 2006-04-28 14:49:47Z mrook $
+ * @package phing.tasks.ext.coverage
+ * @since 2.1.0
+ */
+class CoverageReportTransformer
+{
+ private $task = NULL;
+ private $styleDir = "";
+ private $toDir = "";
+ private $document = NULL;
+
+ function __construct(Task $task)
+ {
+ $this->task = $task;
+ }
+
+ function setStyleDir($styleDir)
+ {
+ $this->styleDir = $styleDir;
+ }
+
+ function setToDir($toDir)
+ {
+ $this->toDir = $toDir;
+ }
+
+ function setXmlDocument($document)
+ {
+ $this->document = $document;
+ }
+
+ function transform()
+ {
+ $dir = new PhingFile($this->toDir);
+
+ if (!$dir->exists())
+ {
+ throw new BuildException("Directory '" . $this->toDir . "' does not exist");
+ }
+
+ $xslfile = $this->getStyleSheet();
+
+ $xsl = new DOMDocument();
+ $xsl->load($xslfile->getAbsolutePath());
+
+ $proc = new XSLTProcessor();
+ $proc->importStyleSheet($xsl);
+
+ ExtendedFileStream::registerStream();
+
+ // no output for the framed report
+ // it's all done by extension...
+ $proc->setParameter('', 'output.dir', $dir->getAbsolutePath());
+ $proc->transformToXML($this->document);
+ }
+
+ private function getStyleSheet()
+ {
+ $xslname = "coverage-frames.xsl";
+
+ if ($this->styleDir)
+ {
+ $file = new PhingFile($this->styleDir, $xslname);
+ }
+ else
+ {
+ $path = Phing::getResourcePath("phing/etc/$xslname");
+
+ if ($path === NULL)
+ {
+ $path = Phing::getResourcePath("etc/$xslname");
+
+ if ($path === NULL)
+ {
+ throw new BuildException("Could not find $xslname in resource path");
+ }
+ }
+
+ $file = new PhingFile($path);
+ }
+
+ if (!$file->exists())
+ {
+ throw new BuildException("Could not find file " . $file->getPath());
+ }
+
+ return $file;
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageSetupTask.php b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageSetupTask.php
new file mode 100644
index 00000000..058b891b
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/coverage/CoverageSetupTask.php
@@ -0,0 +1,163 @@
+<?php
+/**
+ * $Id: CoverageSetupTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+require_once 'phing/system/io/PhingFile.php';
+require_once 'phing/system/io/Writer.php';
+require_once 'phing/system/util/Properties.php';
+require_once 'phing/tasks/ext/coverage/CoverageMerger.php';
+
+/**
+ * Initializes a code coverage database
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: CoverageSetupTask.php 59 2006-04-28 14:49:47Z mrook $
+ * @package phing.tasks.ext.coverage
+ * @since 2.1.0
+ */
+class CoverageSetupTask extends Task
+{
+ /** the list of filesets containing the .php filename rules */
+ private $filesets = array();
+
+ /** the filename of the coverage database */
+ private $database = "coverage.db";
+
+ /** the classpath to use (optional) */
+ private $classpath = NULL;
+
+ /**
+ * Add a new fileset containing the .php files to process
+ *
+ * @param FileSet the new fileset containing .php files
+ */
+ function addFileSet(FileSet $fileset)
+ {
+ $this->filesets[] = $fileset;
+ }
+
+ /**
+ * Sets the filename of the coverage database to use
+ *
+ * @param string the filename of the database
+ */
+ function setDatabase($database)
+ {
+ $this->database = $database;
+ }
+
+ function setClasspath(Path $classpath)
+ {
+ if ($this->classpath === null)
+ {
+ $this->classpath = $classpath;
+ }
+ else
+ {
+ $this->classpath->append($classpath);
+ }
+ }
+
+ function createClasspath()
+ {
+ $this->classpath = new Path();
+ return $this->classpath;
+ }
+
+ /**
+ * Iterate over all filesets and return the filename of all files
+ * that end with .php. This is to avoid loading an xml file
+ * for example.
+ *
+ * @return array an array of (basedir, filenames) pairs
+ */
+ private function getFilenames()
+ {
+ $files = array();
+
+ foreach ($this->filesets as $fileset)
+ {
+ $ds = $fileset->getDirectoryScanner($this->project);
+ $ds->scan();
+
+ $includedFiles = $ds->getIncludedFiles();
+
+ foreach ($includedFiles as $file)
+ {
+ if (strstr($file, ".php"))
+ {
+ $fs = new PhingFile(realpath($ds->getBaseDir()), $file);
+
+ $files[] = array('key' => strtolower($fs->getAbsolutePath()), 'fullname' => $fs->getAbsolutePath());
+ }
+ }
+ }
+
+ return $files;
+ }
+
+ function init()
+ {
+ include_once 'PHPUnit2/Framework/TestCase.php';
+ if (!class_exists('PHPUnit2_Framework_TestCase')) {
+ throw new Exception("PHPUnit2Task depends on PEAR PHPUnit2 package being installed.");
+ }
+ }
+
+ function main()
+ {
+ $files = $this->getFilenames();
+
+ $this->log("Setting up coverage database for " . count($files) . " files");
+
+ $props = new Properties();
+
+ foreach ($files as $file)
+ {
+ $fullname = $file['fullname'];
+ $filename = $file['key'];
+
+ $props->setProperty($filename, serialize(array('fullname' => $fullname, 'coverage' => array())));
+ }
+
+ $dbfile = new PhingFile($this->database);
+
+ $props->store($dbfile);
+
+ $this->project->setProperty('coverage.database', $dbfile->getAbsolutePath());
+
+ foreach ($files as $file)
+ {
+ $fullname = $file['fullname'];
+
+ xdebug_start_code_coverage(XDEBUG_CC_UNUSED);
+
+ Phing::__import($fullname, $this->classpath);
+
+ $coverage = xdebug_get_code_coverage();
+
+ xdebug_stop_code_coverage();
+
+ CoverageMerger::merge($this->project, array($coverage));
+ }
+ }
+}
+?>
diff --git a/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeComment.php b/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeComment.php
new file mode 100644
index 00000000..99434aaa
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeComment.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * $Id: IoncubeComment.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * Wrapper for comments for ionCube tasks
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: IoncubeComment.php 59 2006-04-28 14:49:47Z mrook $
+ * @package phing.tasks.ext.ioncube
+ * @since 2.2.0
+ */
+class IoncubeComment
+{
+ private $value = "";
+
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ public function addText($txt)
+ {
+ $this->value = trim($txt);
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeEncoderTask.php b/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeEncoderTask.php
new file mode 100644
index 00000000..9eecd5a0
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeEncoderTask.php
@@ -0,0 +1,336 @@
+<?php
+/**
+ * $Id: IoncubeEncoderTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+require_once 'phing/tasks/ext/ioncube/IoncubeComment.php';
+
+/**
+ * Invokes the ionCube Encoder (PHP4 or PHP5)
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: IoncubeEncoderTask.php 59 2006-04-28 14:49:47Z mrook $
+ * @package phing.tasks.ext.ioncube
+ * @since 2.2.0
+ */
+class IoncubeEncoderTask extends Task
+{
+ private $phpVersion = "5";
+ private $ioncubePath = "/usr/local/ioncube";
+ private $encoderName = "ioncube_encoder";
+
+ private $fromDir = "";
+ private $toDir = "";
+
+ private $encrypt = "";
+
+ private $targetOption = "";
+ private $binary = false;
+ private $optimize = "";
+ private $withoutRuntimeLoaderSupport = false;
+
+ private $licensePath = "";
+ private $passPhrase = "";
+
+ private $comments = array();
+
+ /**
+ * Sets the path to the ionCube encoder
+ */
+ function setIoncubePath($ioncubePath)
+ {
+ $this->ioncubePath = $ioncubePath;
+ }
+
+ /**
+ * Returns the path to the ionCube encoder
+ */
+ function getIoncubePath()
+ {
+ return $this->ioncubePath;
+ }
+
+ /**
+ * Sets the version of PHP to use (defaults to 5)
+ */
+ function setPhpVersion($phpVersion)
+ {
+ $this->phpVersion = $phpVersion;
+ }
+
+ /**
+ * Returns the version of PHP to use (defaults to 5)
+ */
+ function getPhpVersion()
+ {
+ return $this->phpVersion;
+ }
+
+ /**
+ * Sets the source directory
+ */
+ function setFromDir($fromDir)
+ {
+ $this->fromDir = $fromDir;
+ }
+
+ /**
+ * Returns the source directory
+ */
+ function getFromDir($fromDir)
+ {
+ return $this->fromDir;
+ }
+
+ /**
+ * Sets the target directory
+ */
+ function setToDir($toDir)
+ {
+ $this->toDir = $toDir;
+ }
+
+ /**
+ * Returns the target directory
+ */
+ function getToDir($toDir)
+ {
+ return $this->toDir;
+ }
+
+ /**
+ * Sets regexps of additional files to encrypt (separated by space)
+ */
+ function setEncrypt($encrypt)
+ {
+ $this->encrypt = $encrypt;
+ }
+
+ /**
+ * Returns regexps of additional files to encrypt (separated by space)
+ */
+ function getEncrypt()
+ {
+ return $this->encrypt;
+ }
+
+ /**
+ * Sets the binary option
+ */
+ function setBinary($binary)
+ {
+ $this->binary = $binary;
+ }
+
+ /**
+ * Returns the binary option
+ */
+ function getBinary()
+ {
+ return $this->binary;
+ }
+
+ /**
+ * Sets the optimize option
+ */
+ function setOptimize($optimize)
+ {
+ $this->optimize = $optimize;
+ }
+
+ /**
+ * Returns the optimize option
+ */
+ function getOptimize()
+ {
+ return $this->optimize;
+ }
+
+ /**
+ * Sets the without-runtime-loader-support option
+ */
+ function setWithoutRuntimeLoaderSupport($withoutRuntimeLoaderSupport)
+ {
+ $this->withoutRuntimeLoaderSupport = $withoutRuntimeLoaderSupport;
+ }
+
+ /**
+ * Returns the without-runtime-loader-support option
+ */
+ function getWithoutRuntimeLoaderSupport()
+ {
+ return $this->withoutRuntimeLoaderSupport;
+ }
+
+ /**
+ * Sets the option to use when encoding target directory already exists (defaults to none)
+ */
+ function setTargetOption($targetOption)
+ {
+ $this->targetOption = $targetOption;
+ }
+
+ /**
+ * Returns he option to use when encoding target directory already exists (defaults to none)
+ */
+ function getTargetOption()
+ {
+ return $this->targetOption;
+ }
+
+ /**
+ * Sets the path to the license file to use
+ */
+ function setLicensePath($licensePath)
+ {
+ $this->licensePath = $licensePath;
+ }
+
+ /**
+ * Returns the path to the license file to use
+ */
+ function getLicensePath()
+ {
+ return $this->licensePath;
+ }
+
+ /**
+ * Sets the passphrase to use when encoding files
+ */
+ function setPassPhrase($passPhrase)
+ {
+ $this->passPhrase = $passPhrase;
+ }
+
+ /**
+ * Returns the passphrase to use when encoding files
+ */
+ function getPassPhrase()
+ {
+ return $this->passPhrase;
+ }
+
+ /**
+ * Adds a comment to be used in encoded files
+ */
+ function addComment(IoncubeComment $comment)
+ {
+ $this->comments[] = $comment;
+ }
+
+ /**
+ * The main entry point
+ *
+ * @throws BuildException
+ */
+ function main()
+ {
+ $arguments = $this->constructArguments();
+
+ $encoder = new PhingFile($this->ioncubePath, $this->encoderName . ($this->phpVersion == 5 ? '5' : ''));
+
+ $this->log("Running ionCube Encoder...");
+
+ exec($encoder->__toString() . " " . $arguments . " 2>&1", $output, $return);
+
+ if ($return != 0)
+ {
+ throw new BuildException("Could not execute ionCube Encoder: " . implode(' ', $output));
+ }
+ }
+
+ /**
+ * Constructs an argument string for the ionCube encoder
+ */
+ private function constructArguments()
+ {
+ $arguments = "";
+
+ if ($this->binary)
+ {
+ $arguments.= "--binary ";
+ }
+
+ if (!empty($this->optimize))
+ {
+ $arguments.= "--optimize " . $this->optimize . " ";
+ }
+
+ if ($this->withoutRuntimeLoaderSupport)
+ {
+ $arguments.= "--without-runtime-loader-support ";
+ }
+
+ if (!empty($this->targetOption))
+ {
+ switch ($this->targetOption)
+ {
+ case "replace":
+ case "merge":
+ case "update":
+ case "rename":
+ {
+ $arguments.= "--" . $this->targetOption . "-target ";
+ } break;
+
+ default:
+ {
+ throw new BuildException("Unknown target option '" . $this->targetOption . "'");
+ } break;
+ }
+ }
+
+ if (!empty($this->encrypt))
+ {
+ foreach (explode(" ", $this->encrypt) as $encrypt)
+ {
+ $arguments.= "--encrypt '$encrypt' ";
+ }
+ }
+
+ if (!empty($this->licensePath))
+ {
+ $arguments.= "--with-license '" . $this->licensePath . "' ";
+ }
+
+ if (!empty($this->passPhrase))
+ {
+ $arguments.= "--passphrase '" . $this->passPhrase . "' ";
+ }
+
+ foreach ($this->comments as $comment)
+ {
+ $arguments.= "--add-comment '" . $comment->getValue() . "' ";
+ }
+
+ if ($this->fromDir != "")
+ {
+ $arguments .= $this->fromDir . " ";
+ }
+
+ if ($this->toDir != "")
+ {
+ $arguments .= "-o " . $this->toDir . " ";
+ }
+
+ return $arguments;
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeLicenseTask.php b/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeLicenseTask.php
new file mode 100644
index 00000000..70abd544
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/ioncube/IoncubeLicenseTask.php
@@ -0,0 +1,144 @@
+<?php
+/**
+ * $Id: IoncubeLicenseTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+require_once 'phing/tasks/ext/ioncube/IoncubeComment.php';
+
+/**
+ * Invokes the ionCube "make_license" program
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: IoncubeLicenseTask.php 59 2006-04-28 14:49:47Z mrook $
+ * @package phing.tasks.ext.ioncube
+ * @since 2.2.0
+ */
+class IoncubeLicenseTask extends Task
+{
+ private $ioncubePath = "/usr/local/ioncube";
+
+ private $licensePath = "";
+ private $passPhrase = "";
+
+ private $comments = array();
+
+ /**
+ * Sets the path to the ionCube encoder
+ */
+ function setIoncubePath($ioncubePath)
+ {
+ $this->ioncubePath = $ioncubePath;
+ }
+
+ /**
+ * Returns the path to the ionCube encoder
+ */
+ function getIoncubePath()
+ {
+ return $this->ioncubePath;
+ }
+
+ /**
+ * Sets the path to the license file to use
+ */
+ function setLicensePath($licensePath)
+ {
+ $this->licensePath = $licensePath;
+ }
+
+ /**
+ * Returns the path to the license file to use
+ */
+ function getLicensePath()
+ {
+ return $this->licensePath;
+ }
+
+ /**
+ * Sets the passphrase to use when encoding files
+ */
+ function setPassPhrase($passPhrase)
+ {
+ $this->passPhrase = $passPhrase;
+ }
+
+ /**
+ * Returns the passphrase to use when encoding files
+ */
+ function getPassPhrase()
+ {
+ return $this->passPhrase;
+ }
+
+ /**
+ * Adds a comment to be used in encoded files
+ */
+ function addComment(IoncubeComment $comment)
+ {
+ $this->comments[] = $comment;
+ }
+
+ /**
+ * The main entry point
+ *
+ * @throws BuildException
+ */
+ function main()
+ {
+ $arguments = $this->constructArguments();
+
+ $makelicense = new PhingFile($this->ioncubePath, 'make_license');
+
+ $this->log("Running ionCube make_license...");
+
+ exec($makelicense->__toString() . " " . $arguments . " 2>&1", $output, $return);
+
+ if ($return != 0)
+ {
+ throw new BuildException("Could not execute ionCube make_license: " . implode(' ', $output));
+ }
+ }
+
+ /**
+ * Constructs an argument string for the ionCube make_license
+ */
+ private function constructArguments()
+ {
+ $arguments = "";
+
+ if (!empty($this->passPhrase))
+ {
+ $arguments.= "--passphrase '" . $this->passPhrase . "' ";
+ }
+
+ foreach ($this->comments as $comment)
+ {
+ $arguments.= "--header-line '" . $comment->getValue() . "' ";
+ }
+
+ if (!empty($this->licensePath))
+ {
+ $arguments.= "--o '" . $this->licensePath . "' ";
+ }
+
+ return $arguments;
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/pearpackage/Fileset.php b/buildscripts/phing/classes/phing/tasks/ext/pearpackage/Fileset.php
new file mode 100644
index 00000000..12bd4e55
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/pearpackage/Fileset.php
@@ -0,0 +1,231 @@
+<?php
+/*
+ * $Id: Fileset.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/system/io/PhingFile.php';
+
+/**
+ * Builds list of files for PEAR_PackageFileManager using a Phing FileSet.
+ *
+ * Some code here is taken from PEAR_PackageFileManager_File -- getting results from flat
+ * array into the assoc array expected from getFileList().
+ *
+ * @author Greg Beaver
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @package phing.tasks.ext.pearpackage
+ * @version $Revision: 1.7 $
+ */
+class PEAR_PackageFileManager_Fileset {
+
+ /**
+ * @access private
+ * @var PEAR_PackageFileManager
+ */
+ private $parent;
+
+ /**
+ * Curent Phing Project.
+ * @var Project
+ */
+ private $project;
+
+ /**
+ * FileSets to use.
+ * @var array FileSet[]
+ */
+ private $filesets = array();
+
+ /**
+ * Set up the FileSet filelist generator
+ *
+ * 'project' and 'filesets' are the only options that this class uses.
+ *
+ * @param PEAR_PackageFileManager
+ * @param array
+ */
+ function __construct($parent, $options)
+ {
+ $this->parent = $parent;
+ $this->project = $options['phing_project'];
+ $this->filesets = $options['phing_filesets'];
+ }
+
+ /**
+ * Generate the <filelist></filelist> section
+ * of the package file.
+ *
+ * This function performs the backend generation of the array
+ * containing all files in this package
+ * @return array structure of all files to include
+ */
+ function getFileList() {
+
+ $allfiles = array();
+
+ foreach($this->filesets as $fs) {
+ $ds = $fs->getDirectoryScanner($this->project);
+
+ $files = $ds->getIncludedFiles();
+
+ // We need to store these files keyed by the basedir from DirectoryScanner
+ // so that we can resolve the fullpath of the file later.
+ if (isset($allfiles[$ds->getBasedir()]))
+ {
+ $allfiles[$ds->getBasedir()] = array_merge($allfiles[$ds->getBasedir()], $files);
+ }
+ else
+ {
+ $allfiles[$ds->getBasedir()] = $files;
+ }
+ }
+
+ $struc = array();
+
+ foreach($allfiles as $basedir => $files) {
+
+ foreach($files as $file) {
+
+ // paths are relative to $basedir above
+ $path = strtr(dirname($file), DIRECTORY_SEPARATOR, '/');
+
+ if (!$path || $path == '.') {
+ $path = '/'; // for array index
+ }
+
+ $parts = explode('.', basename($file));
+ $ext = array_pop($parts);
+ if (strlen($ext) == strlen($file)) {
+ $ext = '';
+ }
+
+ $f = new PhingFile($basedir, $file);
+
+ $struc[$path][] = array('file' => basename($file),
+ 'ext' => $ext,
+ 'path' => (($path == '/') ? basename($file) : $path . '/' . basename($file)),
+ 'fullpath' => $f->getAbsolutePath());
+ }
+ }
+
+ uksort($struc,'strnatcasecmp');
+ foreach($struc as $key => $ind) {
+ usort($ind, array($this, 'sortfiles'));
+ $struc[$key] = $ind;
+ }
+
+ $tempstruc = $struc;
+ $struc = array('/' => $tempstruc['/']);
+ $bv = 0;
+ foreach($tempstruc as $key => $ind) {
+ $save = $key;
+ if ($key != '/') {
+ $struc['/'] = $this->setupDirs($struc['/'], explode('/', $key), $tempstruc[$key]);
+ }
+ }
+ uksort($struc['/'], array($this, 'mystrucsort'));
+
+ return $struc;
+ }
+
+ /**
+ * Recursively move contents of $struc into associative array
+ *
+ * The contents of $struc have many indexes like 'dir/subdir/subdir2'.
+ * This function converts them to
+ * array('dir' => array('subdir' => array('subdir2')))
+ * @param array struc is array('dir' => array of files in dir,
+ * 'dir/subdir' => array of files in dir/subdir,...)
+ * @param array array form of 'dir/subdir/subdir2' array('dir','subdir','subdir2')
+ * @return array same as struc but with array('dir' =>
+ * array(file1,file2,'subdir' => array(file1,...)))
+ */
+ private function setupDirs($struc, $dir, $contents) {
+
+ if (!count($dir)) {
+ foreach($contents as $dir => $files) {
+ if (is_string($dir)) {
+ if (strpos($dir, '/')) {
+ $test = true;
+ $a = $contents[$dir];
+ unset($contents[$dir]);
+ $b = explode('/', $dir);
+ $c = array_shift($b);
+ if (isset($contents[$c])) {
+ $contents[$c] = $this->setDir($contents[$c], $this->setupDirs(array(), $b, $a));
+ } else {
+ $contents[$c] = $this->setupDirs(array(), $b, $a);
+ }
+ }
+ }
+ }
+ return $contents;
+ }
+ $me = array_shift($dir);
+ if (!isset($struc[$me])) {
+ $struc[$me] = array();
+ }
+ $struc[$me] = $this->setupDirs($struc[$me], $dir, $contents);
+ return $struc;
+ }
+
+ /**
+ * Recursively add all the subdirectories of $contents to $dir without erasing anything in
+ * $dir
+ * @param array
+ * @param array
+ * @return array processed $dir
+ */
+ function setDir($dir, $contents)
+ {
+ while(list($one,$two) = each($contents)) {
+ if (isset($dir[$one])) {
+ $dir[$one] = $this->setDir($dir[$one], $contents[$one]);
+ } else {
+ $dir[$one] = $two;
+ }
+ }
+ return $dir;
+ }
+
+ /**
+ * Sorting functions for the file list
+ * @param string
+ * @param string
+ * @access private
+ */
+ function sortfiles($a, $b)
+ {
+ return strnatcasecmp($a['file'],$b['file']);
+ }
+
+ function mystrucsort($a, $b)
+ {
+ if (is_numeric($a) && is_string($b)) return 1;
+ if (is_numeric($b) && is_string($a)) return -1;
+ if (is_numeric($a) && is_numeric($b))
+ {
+ if ($a > $b) return 1;
+ if ($a < $b) return -1;
+ if ($a == $b) return 0;
+ }
+ return strnatcasecmp($a,$b);
+ }
+}
+?>
diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PHPDocumentorTask.php b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PHPDocumentorTask.php
new file mode 100644
index 00000000..2fefc4e5
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/phpdoc/PHPDocumentorTask.php
@@ -0,0 +1,157 @@
+<?php
+
+ /**
+ * $Id: PHPDocumentorTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+ require_once 'phing/Task.php';
+
+ /**
+ * Task to run phpDocumentor.
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: PHPDocumentorTask.php 59 2006-04-28 14:49:47Z mrook $
+ * @package phing.tasks.ext.phpdoc
+ */
+ class PHPDocumentorTask extends Task
+ {
+ /**
+ * The name of the executable for phpDocumentor
+ */
+ const PHPDOC = 'phpdoc';
+
+ private $title = "Default Title";
+
+ private $destdir = ".";
+
+ private $sourcepath = NULL;
+
+ private $output = "";
+
+ private $linksource = false;
+
+ private $parseprivate = false;
+
+ /**
+ * Set the title for the generated documentation
+ */
+ function setTitle($title)
+ {
+ $this->title = $title;
+ }
+
+ /**
+ * Set the destination directory for the generated documentation
+ */
+ function setDestdir($destdir)
+ {
+ $this->destdir = $destdir;
+ }
+
+ /**
+ * Set the source path
+ */
+ function setSourcepath(Path $sourcepath)
+ {
+ if ($this->sourcepath === NULL)
+ {
+ $this->sourcepath = $sourcepath;
+ }
+ else
+ {
+ $this->sourcepath->append($sourcepath);
+ }
+ }
+
+ /**
+ * Set the output type
+ */
+ function setOutput($output)
+ {
+ $this->output = $output;
+ }
+
+ /**
+ * Should sources be linked in the generated documentation
+ */
+ function setLinksource($linksource)
+ {
+ $this->linksource = $linksource;
+ }
+
+ /**
+ * Should private members/classes be documented
+ */
+ function setParseprivate($parseprivate)
+ {
+ $this->parseprivate = $parseprivate;
+ }
+
+ /**
+ * Main entrypoint of the task
+ */
+ function main()
+ {
+ $arguments = $this->constructArguments();
+
+ exec(self::PHPDOC . " " . $arguments, $output, $retval);
+ }
+
+ /**
+ * Constructs an argument string for phpDocumentor
+ */
+ private function constructArguments()
+ {
+ $arguments = "-q ";
+
+ if ($this->title)
+ {
+ $arguments.= "-ti \"" . $this->title . "\" ";
+ }
+
+ if ($this->destdir)
+ {
+ $arguments.= "-t " . $this->destdir . " ";
+ }
+
+ if ($this->sourcepath !== NULL)
+ {
+ $arguments.= "-d " . $this->sourcepath->__toString() . " ";
+ }
+
+ if ($this->output)
+ {
+ $arguments.= "-o " . $this->output . " ";
+ }
+
+ if ($this->linksource)
+ {
+ $arguments.= "-s ";
+ }
+
+ if ($this->parseprivate)
+ {
+ $arguments.= "-pp ";
+ }
+
+ return $arguments;
+ }
+ };
+
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/BatchTest.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/BatchTest.php
new file mode 100644
index 00000000..63f8911a
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/BatchTest.php
@@ -0,0 +1,171 @@
+<?php
+/**
+ * $Id: BatchTest.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/types/FileSet.php';
+
+/**
+ * Scans a list of (.php) files given by the fileset attribute, extracts
+ * all subclasses of PHPUnit2_Framework_TestCase.
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: BatchTest.php 59 2006-04-28 14:49:47Z mrook $
+ * @package phing.tasks.ext.phpunit2
+ * @since 2.1.0
+ */
+class BatchTest
+{
+ /** the list of filesets containing the testcase filename rules */
+ private $filesets = array();
+
+ /** the reference to the project */
+ private $project = NULL;
+
+ /** the classpath to use with Phing::__import() calls */
+ private $classpath = NULL;
+
+ /** names of classes to exclude */
+ private $excludeClasses = array();
+
+ /**
+ * Create a new batchtest instance
+ *
+ * @param Project the project it depends on.
+ */
+ function __construct(Project $project)
+ {
+ $this->project = $project;
+ }
+
+ /**
+ * Sets the classes to exclude
+ */
+ function setExclude($exclude)
+ {
+ $this->excludeClasses = explode(" ", $exclude);
+ }
+
+ /**
+ * Sets the classpath
+ */
+ function setClasspath(Path $classpath)
+ {
+ if ($this->classpath === null)
+ {
+ $this->classpath = $classpath;
+ }
+ else
+ {
+ $this->classpath->append($classpath);
+ }
+ }
+
+ /**
+ * Creates a new Path object
+ */
+ function createClasspath()
+ {
+ $this->classpath = new Path();
+ return $this->classpath;
+ }
+
+ /**
+ * Returns the classpath
+ */
+ function getClasspath()
+ {
+ return $this->classpath;
+ }
+
+ /**
+ * Add a new fileset containing the XML results to aggregate
+ *
+ * @param FileSet the new fileset containing XML results.
+ */
+ function addFileSet(FileSet $fileset)
+ {
+ $this->filesets[] = $fileset;
+ }
+
+ /**
+ * Iterate over all filesets and return the filename of all files
+ * that end with .php.
+ *
+ * @return array an array of filenames
+ */
+ private function getFilenames()
+ {
+ $filenames = array();
+
+ foreach ($this->filesets as $fileset)
+ {
+ $ds = $fileset->getDirectoryScanner($this->project);
+ $ds->scan();
+
+ $files = $ds->getIncludedFiles();
+
+ foreach ($files as $file)
+ {
+ if (strstr($file, ".php"))
+ {
+ $filenames[] = $ds->getBaseDir() . "/" . $file;
+ }
+ }
+ }
+
+ return $filenames;
+ }
+
+ /**
+ * Filters an array of classes, removes all classes that are not subclasses of PHPUnit2_Framework_TestCase,
+ * or classes that are declared abstract
+ */
+ private function filterTests($input)
+ {
+ $reflect = new ReflectionClass($input);
+
+ return is_subclass_of($input, 'PHPUnit2_Framework_TestCase') && (!$reflect->isAbstract());
+ }
+
+ /**
+ * Returns an array of PHPUnit2_Framework_TestCase classes that are declared
+ * by the files included by the filesets
+ *
+ * @return array an array of PHPUnit2_Framework_TestCase classes.
+ */
+ function elements()
+ {
+ $filenames = $this->getFilenames();
+
+ $declaredClasses = array();
+
+ foreach ($filenames as $filename)
+ {
+ $definedClasses = PHPUnit2Util::getDefinedClasses($filename);
+
+ $declaredClasses = array_merge($declaredClasses, $definedClasses);
+ }
+
+ $elements = array_filter($declaredClasses, array($this, "filterTests"));
+
+ return $elements;
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/FormatterElement.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/FormatterElement.php
new file mode 100644
index 00000000..9d2a4656
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/FormatterElement.php
@@ -0,0 +1,120 @@
+<?php
+/**
+ * $Id: FormatterElement.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/tasks/ext/phpunit2/XMLPHPUnit2ResultFormatter.php';
+require_once 'phing/tasks/ext/phpunit2/PlainPHPUnit2ResultFormatter.php';
+require_once 'phing/system/io/PhingFile.php';
+
+/**
+ * A wrapper for the implementations of PHPUnit2ResultFormatter.
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: FormatterElement.php 59 2006-04-28 14:49:47Z mrook $
+ * @package phing.tasks.ext.phpunit2
+ * @since 2.1.0
+ */
+class FormatterElement
+{
+ protected $formatter = NULL;
+
+ protected $type = "";
+
+ protected $useFile = true;
+
+ protected $toDir = ".";
+
+ protected $outfile = "";
+
+ function setType($type)
+ {
+ $this->type = $type;
+
+ if ($this->type == "xml")
+ {
+ $destFile = new PhingFile($this->toDir, 'testsuites.xml');
+ $this->formatter = new XMLPHPUnit2ResultFormatter();
+ }
+ else
+ if ($this->type == "plain")
+ {
+ $this->formatter = new PlainPHPUnit2ResultFormatter();
+ }
+ else
+ {
+ throw new BuildException("Formatter '" . $this->type . "' not implemented");
+ }
+ }
+
+ function setClassName($className)
+ {
+ $classNameNoDot = Phing::import($className);
+
+ $this->formatter = new $classNameNoDot();
+ }
+
+ function setUseFile($useFile)
+ {
+ $this->useFile = $useFile;
+ }
+
+ function getUseFile()
+ {
+ return $this->useFile;
+ }
+
+ function setToDir($toDir)
+ {
+ $this->toDir = $toDir;
+ }
+
+ function getToDir()
+ {
+ return $this->toDir;
+ }
+
+ function setOutfile($outfile)
+ {
+ $this->outfile = $outfile;
+ }
+
+ function getOutfile()
+ {
+ if ($this->outfile)
+ {
+ return $this->outfile;
+ }
+ else
+ {
+ return $this->formatter->getPreferredOutfile() . $this->getExtension();
+ }
+ }
+
+ function getExtension()
+ {
+ return $this->formatter->getExtension();
+ }
+
+ function getFormatter()
+ {
+ return $this->formatter;
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2ReportTask.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2ReportTask.php
new file mode 100644
index 00000000..1e08e79c
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2ReportTask.php
@@ -0,0 +1,162 @@
+<?php
+/**
+ * $Id: PHPUnit2ReportTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+require_once 'phing/system/io/PhingFile.php';
+require_once 'phing/system/io/FileWriter.php';
+require_once 'phing/util/ExtendedFileStream.php';
+
+/**
+ * Transform a PHPUnit2 xml report using XSLT.
+ * This transformation generates an html report in either framed or non-framed
+ * style. The non-framed style is convenient to have a concise report via mail,
+ * the framed report is much more convenient if you want to browse into
+ * different packages or testcases since it is a Javadoc like report.
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: PHPUnit2ReportTask.php 59 2006-04-28 14:49:47Z mrook $
+ * @package phing.tasks.ext.phpunit2
+ * @since 2.1.0
+ */
+class PHPUnit2ReportTask extends Task
+{
+ private $format = "noframes";
+ private $styleDir = "";
+ private $toDir = "";
+
+ /** the directory where the results XML can be found */
+ private $inFile = "testsuites.xml";
+
+ /**
+ * Set the filename of the XML results file to use.
+ */
+ function setInFile($inFile)
+ {
+ $this->inFile = $inFile;
+ }
+
+ /**
+ * Set the format of the generated report. Must be noframes or frames.
+ */
+ function setFormat($format)
+ {
+ $this->format = $format;
+ }
+
+ /**
+ * Set the directory where the stylesheets are located.
+ */
+ function setStyleDir($styleDir)
+ {
+ $this->styleDir = $styleDir;
+ }
+
+ /**
+ * Set the directory where the files resulting from the
+ * transformation should be written to.
+ */
+ function setToDir($toDir)
+ {
+ $this->toDir = $toDir;
+ }
+
+ private function getStyleSheet()
+ {
+ $xslname = "phpunit2-" . $this->format . ".xsl";
+
+ if ($this->styleDir)
+ {
+ $file = new PhingFile($this->styleDir, $xslname);
+ }
+ else
+ {
+ $path = Phing::getResourcePath("phing/etc/$xslname");
+
+ if ($path === NULL)
+ {
+ $path = Phing::getResourcePath("etc/$xslname");
+
+ if ($path === NULL)
+ {
+ throw new BuildException("Could not find $xslname in resource path");
+ }
+ }
+
+ $file = new PhingFile($path);
+ }
+
+ if (!$file->exists())
+ {
+ throw new BuildException("Could not find file " . $file->getPath());
+ }
+
+ return $file;
+ }
+
+ function transform($document)
+ {
+ $dir = new PhingFile($this->toDir);
+
+ if (!$dir->exists())
+ {
+ throw new BuildException("Directory '" . $this->toDir . "' does not exist");
+ }
+
+ $xslfile = $this->getStyleSheet();
+
+ $xsl = new DOMDocument();
+ $xsl->load($xslfile->getAbsolutePath());
+
+ $proc = new XSLTProcessor();
+ $proc->importStyleSheet($xsl);
+
+ if ($this->format == "noframes")
+ {
+ $writer = new FileWriter(new PhingFile($this->toDir, "phpunit2-noframes.html"));
+ $writer->write($proc->transformToXML($document));
+ $writer->close();
+ }
+ else
+ {
+ ExtendedFileStream::registerStream();
+
+ // no output for the framed report
+ // it's all done by extension...
+ $dir = new PhingFile($this->toDir);
+ $proc->setParameter('', 'output.dir', $dir->getAbsolutePath());
+ $proc->transformToXML($document);
+ }
+ }
+
+ /**
+ * The main entry point
+ *
+ * @throws BuildException
+ */
+ function main()
+ {
+ $testSuitesDoc = new DOMDocument();
+ $testSuitesDoc->load($this->inFile);
+
+ $this->transform($testSuitesDoc);
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2ResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2ResultFormatter.php
new file mode 100644
index 00000000..5722c63e
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2ResultFormatter.php
@@ -0,0 +1,154 @@
+<?php
+/**
+ * $Id: PHPUnit2ResultFormatter.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'PHPUnit2/Framework/TestListener.php';
+
+require_once 'phing/system/io/Writer.php';
+
+/**
+ * This abstract class describes classes that format the results of a PHPUnit2 testrun.
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: PHPUnit2ResultFormatter.php 59 2006-04-28 14:49:47Z mrook $
+ * @package phing.tasks.ext.phpunit2
+ * @since 2.1.0
+ */
+abstract class PHPUnit2ResultFormatter implements PHPUnit2_Framework_TestListener
+{
+ protected $out = NULL;
+
+ protected $project = NULL;
+
+ private $timer = NULL;
+
+ private $runCount = 0;
+
+ private $failureCount = 0;
+
+ private $errorCount = 0;
+
+ /**
+ * Sets the writer the formatter is supposed to write its results to.
+ */
+ function setOutput(Writer $out)
+ {
+ $this->out = $out;
+ }
+
+ /**
+ * Returns the extension used for this formatter
+ *
+ * @return string the extension
+ */
+ function getExtension()
+ {
+ return "";
+ }
+
+ /**
+ * Sets the project
+ *
+ * @param Project the project
+ */
+ function setProject(Project $project)
+ {
+ $this->project = $project;
+ }
+
+ function getPreferredOutfile()
+ {
+ return "";
+ }
+
+ function startTestRun()
+ {
+ }
+
+ function endTestRun()
+ {
+ }
+
+ function startTestSuite(PHPUnit2_Framework_TestSuite $suite)
+ {
+ $this->runCount = 0;
+ $this->failureCount = 0;
+ $this->errorCount = 0;
+
+ $this->timer = new Timer();
+ $this->timer->start();
+ }
+
+ function endTestSuite(PHPUnit2_Framework_TestSuite $suite)
+ {
+ $this->timer->stop();
+ }
+
+ function startTest(PHPUnit2_Framework_Test $test)
+ {
+ $this->runCount++;
+ }
+
+ function endTest(PHPUnit2_Framework_Test $test)
+ {
+ }
+
+ function addError(PHPUnit2_Framework_Test $test, Exception $e)
+ {
+ $this->errorCount++;
+ }
+
+ function addFailure(PHPUnit2_Framework_Test $test, PHPUnit2_Framework_AssertionFailedError $t)
+ {
+ $this->failureCount++;
+ }
+
+ function addIncompleteTest(PHPUnit2_Framework_Test $test, Exception $e)
+ {
+ }
+
+ function getRunCount()
+ {
+ return $this->runCount;
+ }
+
+ function getFailureCount()
+ {
+ return $this->failureCount;
+ }
+
+ function getErrorCount()
+ {
+ return $this->errorCount;
+ }
+
+ function getElapsedTime()
+ {
+ if ($this->timer)
+ {
+ return $this->timer->getElapsedTime();
+ }
+ else
+ {
+ return 0;
+ }
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2Task.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2Task.php
new file mode 100644
index 00000000..ffd36405
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2Task.php
@@ -0,0 +1,239 @@
+<?php
+/**
+ * $Id: PHPUnit2Task.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+require_once 'phing/system/io/PhingFile.php';
+require_once 'phing/system/io/Writer.php';
+require_once 'phing/util/LogWriter.php';
+
+/**
+ * Runs PHPUnit2 tests.
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: PHPUnit2Task.php 59 2006-04-28 14:49:47Z mrook $
+ * @package phing.tasks.ext.phpunit2
+ * @see BatchTest
+ * @since 2.1.0
+ */
+class PHPUnit2Task extends Task
+{
+ private $batchtests = array();
+ private $formatters = array();
+ private $haltonerror = false;
+ private $haltonfailure = false;
+ private $failureproperty;
+ private $errorproperty;
+ private $printsummary = false;
+ private $testfailed = false;
+ private $codecoverage = false;
+
+ /**
+ * Initialize Task.
+ * This method includes any necessary PHPUnit2 libraries and triggers
+ * appropriate error if they cannot be found. This is not done in header
+ * because we may want this class to be loaded w/o triggering an error.
+ */
+ function init() {
+ include_once 'PHPUnit2/Util/Filter.php';
+ if (!class_exists('PHPUnit2_Util_Filter')) {
+ throw new BuildException("PHPUnit2Task depends on PEAR PHPUnit2 package being installed.", $this->getLocation());
+ }
+
+ if (version_compare(PHP_VERSION, '5.0.3') < 0) {
+ throw new BuildException("PHPUnit2Task requires PHP version >= 5.0.3.", $this->getLocation());
+ }
+
+ // other dependencies that should only be loaded when class is actually used.
+ require_once 'phing/tasks/ext/phpunit2/PHPUnit2TestRunner.php';
+ require_once 'phing/tasks/ext/phpunit2/BatchTest.php';
+ require_once 'phing/tasks/ext/phpunit2/FormatterElement.php';
+ require_once 'phing/tasks/ext/phpunit2/SummaryPHPUnit2ResultFormatter.php';
+
+ // add some defaults to the PHPUnit2 Filter
+ PHPUnit2_Util_Filter::addFileToFilter('PHPUnit2Task.php');
+ PHPUnit2_Util_Filter::addFileToFilter('PHPUnit2TestRunner.php');
+ PHPUnit2_Util_Filter::addFileToFilter('phing/Task.php');
+ PHPUnit2_Util_Filter::addFileToFilter('phing/Target.php');
+ PHPUnit2_Util_Filter::addFileToFilter('phing/Project.php');
+ PHPUnit2_Util_Filter::addFileToFilter('phing/Phing.php');
+ PHPUnit2_Util_Filter::addFileToFilter('phing.php');
+
+ }
+
+ function setFailureproperty($value)
+ {
+ $this->failureproperty = $value;
+ }
+
+ function setErrorproperty($value)
+ {
+ $this->errorproperty = $value;
+ }
+
+ function setHaltonerror($value)
+ {
+ $this->haltonerror = $value;
+ }
+
+ function setHaltonfailure($value)
+ {
+ $this->haltonfailure = $value;
+ }
+
+ function setPrintsummary($printsummary)
+ {
+ $this->printsummary = $printsummary;
+ }
+
+ function setCodecoverage($codecoverage)
+ {
+ $this->codecoverage = $codecoverage;
+ }
+
+ /**
+ * Add a new formatter to all tests of this task.
+ *
+ * @param FormatterElement formatter element
+ */
+ function addFormatter(FormatterElement $fe)
+ {
+ $this->formatters[] = $fe;
+ }
+
+ /**
+ * The main entry point
+ *
+ * @throws BuildException
+ */
+ function main()
+ {
+ $tests = array();
+
+ if ($this->printsummary)
+ {
+ $fe = new FormatterElement();
+ $fe->setClassName('SummaryPHPUnit2ResultFormatter');
+ $fe->setUseFile(false);
+ $this->formatters[] = $fe;
+ }
+
+ foreach ($this->batchtests as $batchtest)
+ {
+ $tests = array_merge($tests, $batchtest->elements());
+ }
+
+ foreach ($this->formatters as $fe)
+ {
+ $formatter = $fe->getFormatter();
+ $formatter->setProject($this->getProject());
+
+ if ($fe->getUseFile())
+ {
+ $destFile = new PhingFile($fe->getToDir(), $fe->getOutfile());
+
+ $writer = new FileWriter($destFile->getAbsolutePath());
+
+ $formatter->setOutput($writer);
+ }
+ else
+ {
+ $formatter->setOutput($this->getDefaultOutput());
+ }
+
+ $formatter->startTestRun();
+ }
+
+ foreach ($tests as $test)
+ {
+ $this->execute(new PHPUnit2_Framework_TestSuite(new ReflectionClass($test)));
+ }
+
+ foreach ($this->formatters as $fe)
+ {
+ $formatter = $fe->getFormatter();
+ $formatter->endTestRun();
+ }
+
+ if ($this->testfailed)
+ {
+ throw new BuildException("One or more tests failed");
+ }
+ }
+
+ /**
+ * @throws BuildException
+ */
+ private function execute($suite)
+ {
+ $runner = new PHPUnit2TestRunner($suite, $this->project);
+
+ $runner->setCodecoverage($this->codecoverage);
+
+ foreach ($this->formatters as $fe)
+ {
+ $formatter = $fe->getFormatter();
+
+ $runner->addFormatter($formatter);
+ }
+
+ $runner->run();
+
+ $retcode = $runner->getRetCode();
+
+ if ($retcode == PHPUnit2TestRunner::ERRORS) {
+ if ($this->errorproperty) {
+ $this->project->setNewProperty($this->errorproperty, true);
+ }
+ if ($this->haltonerror) {
+ $this->testfailed = true;
+ }
+ } elseif ($retcode == PHPUnit2TestRunner::FAILURES) {
+ if ($this->failureproperty) {
+ $this->project->setNewProperty($this->failureproperty, true);
+ }
+
+ if ($this->haltonfailure) {
+ $this->testfailed = true;
+ }
+ }
+
+ }
+
+ private function getDefaultOutput()
+ {
+ return new LogWriter($this);
+ }
+
+ /**
+ * Adds a set of tests based on pattern matching.
+ *
+ * @return BatchTest a new instance of a batch test.
+ */
+ function createBatchTest()
+ {
+ $batchtest = new BatchTest($this->getProject());
+
+ $this->batchtests[] = $batchtest;
+
+ return $batchtest;
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2TestRunner.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2TestRunner.php
new file mode 100644
index 00000000..bbd19f34
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2TestRunner.php
@@ -0,0 +1,107 @@
+<?php
+/**
+ * $Id: PHPUnit2TestRunner.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'PHPUnit2/Framework/TestListener.php';
+require_once 'PHPUnit2/Framework/TestResult.php';
+require_once 'PHPUnit2/Framework/TestSuite.php';
+
+require_once 'phing/tasks/ext/coverage/CoverageMerger.php';
+
+require_once 'phing/system/util/Timer.php';
+
+/**
+ * Simple Testrunner for PHPUnit2 that runs all tests of a testsuite.
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: PHPUnit2TestRunner.php 59 2006-04-28 14:49:47Z mrook $
+ * @package phing.tasks.ext.phpunit2
+ * @since 2.1.0
+ */
+class PHPUnit2TestRunner
+{
+ const SUCCESS = 0;
+ const FAILURES = 1;
+ const ERRORS = 2;
+
+ private $test = NULL;
+ private $suite = NULL;
+ private $retCode = 0;
+ private $formatters = array();
+
+ private $codecoverage = false;
+
+ private $project = NULL;
+
+ function __construct(PHPUnit2_Framework_TestSuite $suite, Project $project)
+ {
+ $this->suite = $suite;
+ $this->project = $project;
+ $this->retCode = self::SUCCESS;
+ }
+
+ function setCodecoverage($codecoverage)
+ {
+ $this->codecoverage = $codecoverage;
+ }
+
+ function addFormatter(PHPUnit2_Framework_TestListener $formatter)
+ {
+ $this->formatters[] = $formatter;
+ }
+
+ function run()
+ {
+ $res = new PHPUnit2_Framework_TestResult();
+
+ if ($this->codecoverage)
+ {
+ $res->collectCodeCoverageInformation(TRUE);
+ }
+
+ foreach ($this->formatters as $formatter)
+ {
+ $res->addListener($formatter);
+ }
+
+ $this->suite->run($res);
+
+ if ($this->codecoverage)
+ {
+ CoverageMerger::merge($this->project, $res->getCodeCoverageInformation());
+ }
+
+ if ($res->errorCount() != 0)
+ {
+ $this->retCode = self::ERRORS;
+ }
+
+ else if ($res->failureCount() != 0 || $res->notImplementedCount() != 0)
+ {
+ $this->retCode = self::FAILURES;
+ }
+ }
+
+ function getRetCode()
+ {
+ return $this->retCode;
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2Util.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2Util.php
new file mode 100644
index 00000000..f4d1f62a
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PHPUnit2Util.php
@@ -0,0 +1,114 @@
+<?php
+/**
+ * $Id: PHPUnit2Util.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * Various utility functions
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: PHPUnit2Util.php 59 2006-04-28 14:49:47Z mrook $
+ * @package phing.tasks.ext.phpunit2
+ * @since 2.1.0
+ */
+class PHPUnit2Util
+{
+ protected static $definedClasses = array();
+
+ /**
+ * Returns the package of a class as defined in the docblock of the class using @package
+ *
+ * @param string the name of the class
+ * @return string the name of the package
+ */
+ static function getPackageName($classname)
+ {
+ $reflect = new ReflectionClass($classname);
+
+ if (preg_match('/@package[\s]+([\.\w]+)/', $reflect->getDocComment(), $matches))
+ {
+ return $matches[1];
+ }
+ else
+ {
+ return "default";
+ }
+ }
+
+ /**
+ * Derives the classname from a filename.
+ * Assumes that there is only one class defined in that particular file, and that
+ * the naming follows the dot-path (Java) notation scheme.
+ *
+ * @param string the filename
+ * @return string the name fo the class
+ */
+ static function getClassFromFileName($filename)
+ {
+ $filename = basename($filename);
+
+ $rpos = strrpos($filename, '.');
+
+ if ($rpos != -1)
+ {
+ $filename = substr($filename, 0, $rpos);
+ }
+
+ return $filename;
+ }
+
+ /**
+ * @param string the filename
+ * @param Path optional classpath
+ * @return array list of classes defined in the file
+ */
+ static function getDefinedClasses($filename, $classpath = NULL)
+ {
+ $filename = realpath($filename);
+
+ if (!file_exists($filename))
+ {
+ throw new Exception("File '" . $filename . "' does not exist");
+ }
+
+ if (isset(self::$definedClasses[$filename]))
+ {
+ return self::$definedClasses[$filename];
+ }
+
+ Phing::__import($filename, $classpath);
+
+ $declaredClasses = get_declared_classes();
+
+ foreach ($declaredClasses as $classname)
+ {
+ $reflect = new ReflectionClass($classname);
+
+ self::$definedClasses[$reflect->getFilename()][] = $classname;
+
+ if (is_array(self::$definedClasses[$reflect->getFilename()]))
+ {
+ self::$definedClasses[$reflect->getFilename()] = array_unique(self::$definedClasses[$reflect->getFilename()]);
+ }
+ }
+
+ return self::$definedClasses[$filename];
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PlainPHPUnit2ResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PlainPHPUnit2ResultFormatter.php
new file mode 100644
index 00000000..b0a9ae58
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/PlainPHPUnit2ResultFormatter.php
@@ -0,0 +1,117 @@
+<?php
+/**
+ * $Id: PlainPHPUnit2ResultFormatter.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'PHPUnit2/Framework/Test.php';
+require_once 'PHPUnit2/Util/Filter.php';
+
+require_once 'phing/tasks/ext/phpunit2/PHPUnit2ResultFormatter.php';
+
+/**
+ * Prints plain text output of the test to a specified Writer.
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: PlainPHPUnit2ResultFormatter.php 59 2006-04-28 14:49:47Z mrook $
+ * @package phing.tasks.ext.phpunit2
+ * @since 2.1.0
+ */
+class PlainPHPUnit2ResultFormatter extends PHPUnit2ResultFormatter
+{
+ private $inner = "";
+
+ function getExtension()
+ {
+ return ".txt";
+ }
+
+ function getPreferredOutfile()
+ {
+ return "testresults";
+ }
+
+ function startTestSuite(PHPUnit2_Framework_TestSuite $suite)
+ {
+ parent::startTestSuite($suite);
+
+ $this->inner = "";
+ }
+
+ function endTestSuite(PHPUnit2_Framework_TestSuite $suite)
+ {
+ parent::endTestSuite($suite);
+
+ $sb = "Testsuite: " . $suite->getName() . "\n";
+ $sb.= "Tests run: " . $this->getRunCount();
+ $sb.= ", Failures: " . $this->getFailureCount();
+ $sb.= ", Errors: " . $this->getErrorCount();
+ $sb.= ", Time elapsed: " . $this->getElapsedTime();
+ $sb.= " sec\n";
+
+ if ($this->out != NULL)
+ {
+ $this->out->write($sb);
+ $this->out->write($this->inner);
+ }
+ }
+
+ function addError(PHPUnit2_Framework_Test $test, Exception $e)
+ {
+ parent::addError($test, $e);
+
+ $this->formatError("ERROR", $test, $e);
+ }
+
+ function addFailure(PHPUnit2_Framework_Test $test, PHPUnit2_Framework_AssertionFailedError $t)
+ {
+ parent::addFailure($test, $t);
+
+ $this->formatError("FAILED", $test, $t);
+ }
+
+ function addIncompleteTest(PHPUnit2_Framework_Test $test, Exception $e)
+ {
+ parent::addIncompleteTest($test, $e);
+
+ $this->formatError("INCOMPLETE", $test, $e);
+ }
+
+ private function formatError($type, PHPUnit2_Framework_Test $test, Exception $e)
+ {
+ if ($test != null)
+ {
+ $this->endTest($test);
+ }
+
+ $this->inner.= $test->getName() . " " . $type . "\n";
+ $this->inner.= $e->getMessage() . "\n";
+ $this->inner.= PHPUnit2_Util_Filter::getFilteredStackTrace($e) . "\n";
+ }
+
+ function endTestRun()
+ {
+ parent::endTestRun();
+
+ if ($this->out != NULL)
+ {
+ $this->out->close();
+ }
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/SummaryPHPUnit2ResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/SummaryPHPUnit2ResultFormatter.php
new file mode 100644
index 00000000..df17d2d4
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/SummaryPHPUnit2ResultFormatter.php
@@ -0,0 +1,58 @@
+<?php
+/**
+ * $Id: SummaryPHPUnit2ResultFormatter.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'PHPUnit2/Framework/Test.php';
+
+require_once 'phing/tasks/ext/phpunit2/PHPUnit2ResultFormatter.php';
+
+/**
+ * Prints short summary output of the test to Phing's logging system.
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: SummaryPHPUnit2ResultFormatter.php 59 2006-04-28 14:49:47Z mrook $
+ * @package phing.tasks.ext.phpunit2
+ * @since 2.1.0
+ */
+class SummaryPHPUnit2ResultFormatter extends PHPUnit2ResultFormatter
+{
+ function endTestSuite(PHPUnit2_Framework_TestSuite $suite)
+ {
+ parent::endTestSuite($suite);
+
+ $sb = "Tests run: " . $this->getRunCount();
+ $sb.= ", Failures: " . $this->getFailureCount();
+ $sb.= ", Errors: " . $this->getErrorCount();
+ $sb.= ", Time elapsed: " . $this->getElapsedTime();
+ $sb.= " sec\n";
+
+ if ($this->out != NULL)
+ {
+ $this->out->write($sb);
+ $this->out->close();
+ }
+ }
+
+ function getExtension()
+ {
+ return NULL;
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit2/XMLPHPUnit2ResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/XMLPHPUnit2ResultFormatter.php
new file mode 100644
index 00000000..ac2fec8f
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit2/XMLPHPUnit2ResultFormatter.php
@@ -0,0 +1,117 @@
+<?php
+/**
+ * $Id: XMLPHPUnit2ResultFormatter.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'PHPUnit2/Framework/Test.php';
+require_once 'PHPUnit2/Runner/Version.php';
+
+require_once 'PHPUnit2/Util/Log/XML.php';
+
+require_once 'phing/tasks/ext/phpunit2/PHPUnit2ResultFormatter.php';
+
+/**
+ * Prints XML output of the test to a specified Writer
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: XMLPHPUnit2ResultFormatter.php 59 2006-04-28 14:49:47Z mrook $
+ * @package phing.tasks.ext.phpunit2
+ * @since 2.1.0
+ */
+class XMLPHPUnit2ResultFormatter extends PHPUnit2ResultFormatter
+{
+ private $logger = NULL;
+
+ function __construct()
+ {
+ $this->logger = new PHPUnit2_Util_Log_XML();
+ $this->logger->setWriteDocument(false);
+ }
+
+ function getExtension()
+ {
+ return ".xml";
+ }
+
+ function getPreferredOutfile()
+ {
+ return "testsuites";
+ }
+
+ function startTestSuite(PHPUnit2_Framework_TestSuite $suite)
+ {
+ parent::startTestSuite($suite);
+
+ $this->logger->startTestSuite($suite);
+ }
+
+ function endTestSuite(PHPUnit2_Framework_TestSuite $suite)
+ {
+ parent::endTestSuite($suite);
+
+ $this->logger->endTestSuite($suite);
+ }
+
+ function startTest(PHPUnit2_Framework_Test $test)
+ {
+ parent::startTest($test);
+
+ $this->logger->startTest($test);
+ }
+
+ function endTest(PHPUnit2_Framework_Test $test)
+ {
+ parent::endTest($test);
+
+ $this->logger->endTest($test);
+ }
+
+ function addError(PHPUnit2_Framework_Test $test, Exception $e)
+ {
+ parent::addError($test, $e);
+
+ $this->logger->addError($test, $e);
+ }
+
+ function addFailure(PHPUnit2_Framework_Test $test, PHPUnit2_Framework_AssertionFailedError $t)
+ {
+ parent::addFailure($test, $t);
+
+ $this->logger->addFailure($test, $t);
+ }
+
+ function addIncompleteTest(PHPUnit2_Framework_Test $test, Exception $e)
+ {
+ parent::addIncompleteTest($test, $e);
+
+ $this->logger->addIncompleteTest($test, $e);
+ }
+
+ function endTestRun()
+ {
+ parent::endTestRun();
+
+ if ($this->out)
+ {
+ $this->out->write($this->logger->getXML());
+ $this->out->close();
+ }
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestCountResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestCountResultFormatter.php
new file mode 100644
index 00000000..11e360e0
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestCountResultFormatter.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * $Id: SimpleTestCountResultFormatter.php 58 2006-04-28 14:41:04Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/tasks/ext/simpletest/SimpleTestResultFormatter.php';
+
+/**
+ * Dummy result formatter used to count SimpleTest results
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: SimpleTestCountResultFormatter.php 58 2006-04-28 14:41:04Z mrook $
+ * @package phing.tasks.ext.simpletest
+ * @since 2.2.0
+ */
+class SimpleTestCountResultFormatter extends SimpleTestResultFormatter
+{
+ const SUCCESS = 0;
+ const FAILURES = 1;
+ const ERRORS = 2;
+
+ function getRetCode()
+ {
+ if ($this->getExceptionCount() != 0)
+ {
+ return self::ERRORS;
+ }
+ else if ($this->getFailCount() != 0)
+ {
+ return self::FAILURES;
+ }
+
+ return self::SUCCESS;
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestFormatterElement.php b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestFormatterElement.php
new file mode 100644
index 00000000..fab27315
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestFormatterElement.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * $Id: SimpleTestFormatterElement.php 58 2006-04-28 14:41:04Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/tasks/ext/simpletest/SimpleTestPlainResultFormatter.php';
+require_once 'phing/tasks/ext/simpletest/SimpleTestSummaryResultFormatter.php';
+require_once 'phing/tasks/ext/phpunit2/FormatterElement.php';
+
+/**
+ * Child class of "FormatterElement", overrides setType to provide other
+ * formatter classes for SimpleTest
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: SimpleTestFormatterElement.php 58 2006-04-28 14:41:04Z mrook $
+ * @package phing.tasks.ext.simpletest
+ * @since 2.2.0
+ */
+class SimpleTestFormatterElement extends FormatterElement
+{
+ function setType($type)
+ {
+ $this->type = $type;
+
+ if ($this->type == "xml")
+ {
+ $destFile = new PhingFile($this->toDir, 'testsuites.xml');
+ //$this->formatter = new SimpleTestXmlResultFormatter();
+ }
+ else
+ if ($this->type == "plain")
+ {
+ $this->formatter = new SimpleTestPlainResultFormatter();
+ }
+ else
+ if ($this->type == "summary")
+ {
+ $this->formatter = new SimpleTestSummaryResultFormatter();
+ }
+ else
+ {
+ throw new BuildException("Formatter '" . $this->type . "' not implemented");
+ }
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestPlainResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestPlainResultFormatter.php
new file mode 100644
index 00000000..f84ca815
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestPlainResultFormatter.php
@@ -0,0 +1,95 @@
+<?php
+/**
+ * $Id: SimpleTestPlainResultFormatter.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/tasks/ext/simpletest/SimpleTestResultFormatter.php';
+
+/**
+ * Prints plain text output of the test to a specified Writer.
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: SimpleTestPlainResultFormatter.php 59 2006-04-28 14:49:47Z mrook $
+ * @package phing.tasks.ext.simpletest
+ * @since 2.2.0
+ */
+class SimpleTestPlainResultFormatter extends SimpleTestResultFormatter
+{
+ private $inner = "";
+
+ function getExtension()
+ {
+ return ".txt";
+ }
+
+ function getPreferredOutfile()
+ {
+ return "testresults";
+ }
+
+ function paintCaseStart($test_name)
+ {
+ parent::paintCaseStart($test_name);
+
+ $this->inner = "";
+ }
+
+ function paintCaseEnd($test_name)
+ {
+ parent::paintCaseEnd($test_name);
+
+ /* Only count suites where more than one test was run */
+ if ($this->getRunCount())
+ {
+ $sb.= "Testsuite: $test_name\n";
+ $sb.= "Tests run: " . $this->getRunCount();
+ $sb.= ", Failures: " . $this->getFailureCount();
+ $sb.= ", Errors: " . $this->getErrorCount();
+ $sb.= ", Time elapsed: " . $this->getElapsedTime();
+ $sb.= " sec\n";
+
+ if ($this->out != NULL)
+ {
+ $this->out->write($sb);
+ $this->out->write($this->inner);
+ }
+ }
+ }
+
+ function paintError($message)
+ {
+ parent::paintError($message);
+
+ $this->formatError("ERROR", $message);
+ }
+
+ function paintFail($message)
+ {
+ parent::paintFail($message);
+
+ $this->formatError("FAILED", $message);
+ }
+
+ private function formatError($type, $message)
+ {
+ $this->inner.= $this->getTestName() . " " . $type . "\n";
+ $this->inner.= $message . "\n";
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestResultFormatter.php
new file mode 100644
index 00000000..7f94892f
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestResultFormatter.php
@@ -0,0 +1,162 @@
+<?php
+/**
+ * $Id: SimpleTestResultFormatter.php 58 2006-04-28 14:41:04Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'simpletest/scorer.php';
+
+require_once 'phing/system/io/Writer.php';
+
+/**
+ * This abstract class describes classes that format the results of a SimpleTest testrun.
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: SimpleTestResultFormatter.php 58 2006-04-28 14:41:04Z mrook $
+ * @package phing.tasks.ext.phpunit2
+ * @since 2.2.0
+ */
+abstract class SimpleTestResultFormatter extends SimpleReporter
+{
+ protected $out = NULL;
+
+ protected $project = NULL;
+
+ private $timer = NULL;
+
+ private $runCount = 0;
+
+ private $failureCount = 0;
+
+ private $errorCount = 0;
+
+ private $currentTest = "";
+
+ /**
+ * Sets the writer the formatter is supposed to write its results to.
+ */
+ function setOutput(Writer $out)
+ {
+ $this->out = $out;
+ }
+
+ /**
+ * Returns the extension used for this formatter
+ *
+ * @return string the extension
+ */
+ function getExtension()
+ {
+ return "";
+ }
+
+ /**
+ * Sets the project
+ *
+ * @param Project the project
+ */
+ function setProject(Project $project)
+ {
+ $this->project = $project;
+ }
+
+ function getPreferredOutfile()
+ {
+ return "";
+ }
+
+ function paintMethodStart($test_name)
+ {
+ parent::paintMethodStart($test_name);
+
+ $this->currentTest = $test_name;
+ }
+
+ function paintMethodEnd($test_name)
+ {
+ parent::paintMethodEnd($test_name);
+
+ $this->runCount++;
+ }
+
+ function paintCaseStart($test_name)
+ {
+ parent::paintCaseStart($test_name);
+
+ $this->runCount = 0;
+ $this->failureCount = 0;
+ $this->errorCount = 0;
+
+ $this->timer = new Timer();
+ $this->timer->start();
+ }
+
+ function paintCaseEnd($test_name)
+ {
+ parent::paintCaseEnd($test_name);
+
+ $this->timer->stop();
+ }
+
+ function paintError($message)
+ {
+ parent::paintError($message);
+
+ $this->errorCount++;
+ }
+
+ function paintFail($message)
+ {
+ parent::paintFail($message);
+
+ $this->failureCount++;
+ }
+
+ function getRunCount()
+ {
+ return $this->runCount;
+ }
+
+ function getFailureCount()
+ {
+ return $this->failureCount;
+ }
+
+ function getErrorCount()
+ {
+ return $this->errorCount;
+ }
+
+ function getTestName()
+ {
+ return $this->currentTest;
+ }
+
+ function getElapsedTime()
+ {
+ if ($this->timer)
+ {
+ return $this->timer->getElapsedTime();
+ }
+ else
+ {
+ return 0;
+ }
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestSummaryResultFormatter.php b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestSummaryResultFormatter.php
new file mode 100644
index 00000000..79494bc9
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestSummaryResultFormatter.php
@@ -0,0 +1,54 @@
+<?php
+/**
+ * $Id: SimpleTestSummaryResultFormatter.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/tasks/ext/simpletest/SimpleTestResultFormatter.php';
+
+/**
+ * Prints short summary output of the test to Phing's logging system.
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: SimpleTestSummaryResultFormatter.php 59 2006-04-28 14:49:47Z mrook $
+ * @package phing.tasks.ext.simpletest
+ * @since 2.2.0
+ */
+class SimpleTestSummaryResultFormatter extends SimpleTestResultFormatter
+{
+ function paintCaseEnd($test_name)
+ {
+ parent::paintCaseEnd($test_name);
+
+ /* Only count suites where more than one test was run */
+ if ($this->getRunCount())
+ {
+ $sb.= "Tests run: " . $this->getRunCount();
+ $sb.= ", Failures: " . $this->getFailureCount();
+ $sb.= ", Errors: " . $this->getErrorCount();
+ $sb.= ", Time elapsed: " . $this->getElapsedTime();
+ $sb.= " sec\n";
+
+ if ($this->out != NULL)
+ {
+ $this->out->write($sb);
+ }
+ }
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestTask.php b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestTask.php
new file mode 100644
index 00000000..6aede68f
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/simpletest/SimpleTestTask.php
@@ -0,0 +1,238 @@
+<?php
+/**
+ * $Id: SimpleTestTask.php 58 2006-04-28 14:41:04Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+require_once 'phing/system/io/PhingFile.php';
+require_once 'phing/system/io/Writer.php';
+require_once 'phing/util/LogWriter.php';
+
+/**
+ * Runs SimpleTest tests.
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: SimpleTestTask.php 58 2006-04-28 14:41:04Z mrook $
+ * @package phing.tasks.ext.simpletest
+ * @since 2.2.0
+ */
+class SimpleTestTask extends Task
+{
+ private $formatters = array();
+ private $haltonerror = false;
+ private $haltonfailure = false;
+ private $failureproperty;
+ private $errorproperty;
+ private $printsummary = false;
+ private $testfailed = false;
+
+ /**
+ * Initialize Task.
+ * This method includes any necessary SimpleTest libraries and triggers
+ * appropriate error if they cannot be found. This is not done in header
+ * because we may want this class to be loaded w/o triggering an error.
+ */
+ function init() {
+ @include_once 'simpletest/scorer.php';
+
+ if (!class_exists('SimpleReporter')) {
+ throw new BuildException("SimpleTestTask depends on SimpleTest package being installed.", $this->getLocation());
+ }
+
+ require_once 'simpletest/reporter.php';
+ require_once 'simpletest/xml.php';
+ require_once 'simpletest/test_case.php';
+ require_once 'phing/tasks/ext/simpletest/SimpleTestCountResultFormatter.php';
+ require_once 'phing/tasks/ext/simpletest/SimpleTestFormatterElement.php';
+ }
+
+ function setFailureproperty($value)
+ {
+ $this->failureproperty = $value;
+ }
+
+ function setErrorproperty($value)
+ {
+ $this->errorproperty = $value;
+ }
+
+ function setHaltonerror($value)
+ {
+ $this->haltonerror = $value;
+ }
+
+ function setHaltonfailure($value)
+ {
+ $this->haltonfailure = $value;
+ }
+
+ function setPrintsummary($printsummary)
+ {
+ $this->printsummary = $printsummary;
+ }
+
+ /**
+ * Add a new formatter to all tests of this task.
+ *
+ * @param SimpleTestFormatterElement formatter element
+ */
+ function addFormatter(SimpleTestFormatterElement $fe)
+ {
+ $this->formatters[] = $fe;
+ }
+
+ /**
+ * Add a new fileset containing the XML results to aggregate
+ *
+ * @param FileSet the new fileset containing XML results.
+ */
+ function addFileSet(FileSet $fileset)
+ {
+ $this->filesets[] = $fileset;
+ }
+
+ /**
+ * Iterate over all filesets and return the filename of all files
+ * that end with .php.
+ *
+ * @return array an array of filenames
+ */
+ private function getFilenames()
+ {
+ $filenames = array();
+
+ foreach ($this->filesets as $fileset)
+ {
+ $ds = $fileset->getDirectoryScanner($this->project);
+ $ds->scan();
+
+ $files = $ds->getIncludedFiles();
+
+ foreach ($files as $file)
+ {
+ if (strstr($file, ".php"))
+ {
+ $filenames[] = $ds->getBaseDir() . "/" . $file;
+ }
+ }
+ }
+
+ return $filenames;
+ }
+
+ /**
+ * The main entry point
+ *
+ * @throws BuildException
+ */
+ function main()
+ {
+ $group = new GroupTest();
+
+ $filenames = $this->getFilenames();
+
+ foreach ($filenames as $testfile)
+ {
+ $group->addTestFile($testfile);
+ }
+
+ if ($this->printsummary)
+ {
+ $fe = new SimpleTestFormatterElement();
+ $fe->setType('summary');
+ $fe->setUseFile(false);
+ $this->formatters[] = $fe;
+ }
+
+ foreach ($this->formatters as $fe)
+ {
+ $formatter = $fe->getFormatter();
+ $formatter->setProject($this->getProject());
+
+ if ($fe->getUseFile())
+ {
+ $destFile = new PhingFile($fe->getToDir(), $fe->getOutfile());
+
+ $writer = new FileWriter($destFile->getAbsolutePath());
+
+ $formatter->setOutput($writer);
+ }
+ else
+ {
+ $formatter->setOutput($this->getDefaultOutput());
+ }
+ }
+
+ $this->execute($group);
+
+ if ($this->testfailed)
+ {
+ throw new BuildException("One or more tests failed");
+ }
+ }
+
+ private function execute($suite)
+ {
+ $counter = new SimpleTestCountResultFormatter();
+ $reporter = new MultipleReporter();
+ $reporter->attachReporter($counter);
+
+ foreach ($this->formatters as $fe)
+ {
+ $formatter = $fe->getFormatter();
+
+ $reporter->attachReporter($formatter);
+ }
+
+ $suite->run($reporter);
+
+ $retcode = $counter->getRetCode();
+
+ if ($retcode == SimpleTestCountResultFormatter::ERRORS)
+ {
+ if ($this->errorproperty)
+ {
+ $this->project->setNewProperty($this->errorproperty, true);
+ }
+
+ if ($this->haltonerror)
+ {
+ $this->testfailed = true;
+ }
+ }
+ elseif ($retcode == SimpleTestCountResultFormatter::FAILURES)
+ {
+ if ($this->failureproperty)
+ {
+ $this->project->setNewProperty($this->failureproperty, true);
+ }
+
+ if ($this->haltonfailure)
+ {
+ $this->testfailed = true;
+ }
+ }
+ }
+
+ private function getDefaultOutput()
+ {
+ return new LogWriter($this);
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnBaseTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnBaseTask.php
new file mode 100644
index 00000000..71e3ba2e
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnBaseTask.php
@@ -0,0 +1,180 @@
+<?php
+/*
+ * $Id: SvnBaseTask.php 38 2006-03-09 14:05:11Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/Task.php';
+
+/**
+ * Send a message by mail()
+ *
+ * <mail to="user@example.org" subject="build complete">The build process is a success...</mail>
+ *
+ * @author Francois Harvey at SecuriWeb (http://www.securiweb.net)
+ * @version $Id: SvnBaseTask.php 38 2006-03-09 14:05:11Z mrook $
+ * @package phing.tasks.ext
+ */
+abstract class SvnBaseTask extends Task
+{
+ private $workingCopy = "";
+
+ private $repositoryUrl = "";
+
+ private $svnPath = "/usr/bin/svn";
+
+ private $svn = NULL;
+
+ private $mode = "";
+
+ private $svnArgs = array();
+
+ /**
+ * Initialize Task.
+ * This method includes any necessary SVN libraries and triggers
+ * appropriate error if they cannot be found. This is not done in header
+ * because we may want this class to be loaded w/o triggering an error.
+ */
+ function init() {
+ include_once 'VersionControl/SVN.php';
+ if (!class_exists('VersionControl_SVN')) {
+ throw new Exception("SvnLastRevisionTask depends on PEAR VersionControl_SVN package being installed.");
+ }
+ }
+
+ /**
+ * Sets the path to the workingcopy
+ */
+ function setWorkingCopy($workingCopy)
+ {
+ $this->workingCopy = $workingCopy;
+ }
+
+ /**
+ * Returns the path to the workingcopy
+ */
+ function getWorkingCopy()
+ {
+ return $this->workingCopy;
+ }
+
+ /**
+ * Sets the path/URI to the repository
+ */
+ function setRepositoryUrl($repositoryUrl)
+ {
+ $this->repositoryUrl = $repositoryUrl;
+ }
+
+ /**
+ * Returns the path/URI to the repository
+ */
+ function getRepositoryUrl()
+ {
+ return $this->repositoryUrl;
+ }
+
+ /**
+ * Sets the path to the SVN executable
+ */
+ function setSvnPath($svnPath)
+ {
+ $this->svnPath = $svnPath;
+ }
+
+ /**
+ * Returns the path to the SVN executable
+ */
+ function getSvnPath()
+ {
+ return $this->svnPath;
+ }
+
+ /**
+ * Creates a VersionControl_SVN class based on $mode
+ *
+ * @param string The SVN mode to use (info, export, checkout, ...)
+ * @throws BuildException
+ */
+ protected function setup($mode)
+ {
+ $this->mode = $mode;
+
+ // Set up runtime options. Will be passed to all
+ // subclasses.
+ $options = array('fetchmode' => VERSIONCONTROL_SVN_FETCHMODE_ASSOC, 'svn_path' => $this->getSvnPath());
+
+ // Pass array of subcommands we need to factory
+ $this->svn = VersionControl_SVN::factory($mode, $options);
+
+ if (!empty($this->repositoryUrl))
+ {
+ $this->svnArgs = array($this->repositoryUrl);
+ }
+ else
+ if (!empty($this->workingCopy))
+ {
+ if (is_dir($this->workingCopy))
+ {
+ if (in_array(".svn", scandir($this->workingCopy)))
+ {
+ $this->svnArgs = array($this->workingCopy);
+ }
+ else
+ {
+ throw new BuildException("'".$this->workingCopy."' doesn't seem to be a working copy");
+ }
+ }
+ else
+ {
+ throw new BuildException("'".$this->workingCopy."' is not a directory");
+ }
+ }
+ }
+
+ /**
+ * Executes the constructed VersionControl_SVN instance
+ *
+ * @param array Additional arguments to pass to SVN.
+ * @param array Switches to pass to SVN.
+ * @return string Output generated by SVN.
+ */
+ protected function run($args = array(), $switches = array())
+ {
+ $svnstack = PEAR_ErrorStack::singleton('VersionControl_SVN');
+
+ $tempArgs = $this->svnArgs;
+
+ $tempArgs = array_merge($tempArgs, $args);
+
+ if ($output = $this->svn->run($tempArgs, $switches))
+ {
+ return $output;
+ }
+ else
+ {
+ if (count($errs = $svnstack->getErrors()))
+ {
+ $err = current($errs);
+
+ throw new BuildException("Failed to run the 'svn " . $this->mode . "' command: " . $err['message']);
+ }
+ }
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnExportTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnExportTask.php
new file mode 100644
index 00000000..7cb6c897
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnExportTask.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * $Id: SvnExportTask.php 37 2006-03-09 14:04:22Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+require_once 'phing/tasks/ext/svn/SvnBaseTask.php';
+
+/**
+ * Exports/checks out a repository to a local directory
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: SvnExportTask.php 37 2006-03-09 14:04:22Z mrook $
+ * @package phing.tasks.ext.svn
+ * @see VersionControl_SVN
+ * @since 2.1.0
+ */
+class SvnExportTask extends SvnBaseTask
+{
+ private $toDir = "";
+
+ /**
+ * Sets the path to export/checkout to
+ */
+ function setToDir($toDir)
+ {
+ $this->toDir = $toDir;
+ }
+
+ /**
+ * Returns the path to export/checkout to
+ */
+ function getToDir()
+ {
+ return $this->toDir;
+ }
+
+ /**
+ * The main entry point
+ *
+ * @throws BuildException
+ */
+ function main()
+ {
+ $this->setup('export');
+
+ $this->log("Exporting SVN repository to '" . $this->toDir . "'");
+
+ $this->run(array($this->toDir));
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/ext/svn/SvnLastRevisionTask.php b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnLastRevisionTask.php
new file mode 100644
index 00000000..e45ac50c
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/svn/SvnLastRevisionTask.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * $Id: SvnLastRevisionTask.php 37 2006-03-09 14:04:22Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+require_once 'phing/tasks/ext/svn/SvnBaseTask.php';
+
+/**
+ * Stores the number of the last revision of a workingcopy in a property
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: SvnLastRevisionTask.php 37 2006-03-09 14:04:22Z mrook $
+ * @package phing.tasks.ext.svn
+ * @see VersionControl_SVN
+ * @since 2.1.0
+ */
+class SvnLastRevisionTask extends SvnBaseTask
+{
+ private $propertyName = "svn.lastrevision";
+
+ /**
+ * Sets the name of the property to use
+ */
+ function setPropertyName($propertyName)
+ {
+ $this->propertyName = $propertyName;
+ }
+
+ /**
+ * Returns the name of the property to use
+ */
+ function getPropertyName()
+ {
+ return $this->propertyName;
+ }
+
+ /**
+ * The main entry point
+ *
+ * @throws BuildException
+ */
+ function main()
+ {
+ $this->setup('info');
+
+ $output = $this->run();
+
+ if (preg_match('/Rev:[\s]+([\d]+)/', $output, $matches))
+ {
+ $this->project->setProperty($this->getPropertyName(), $matches[1]);
+ }
+ else
+ {
+ throw new BuildException("Failed to parse the output of 'svn info'.");
+ }
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/system/AdhocTask.php b/buildscripts/phing/classes/phing/tasks/system/AdhocTask.php
new file mode 100644
index 00000000..e4c291a1
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/AdhocTask.php
@@ -0,0 +1,88 @@
+<?php
+/*
+ * $Id: AdhocTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+
+/**
+ * Abstract class for creating adhoc Phing components in buildfile.
+ *
+ * By itself this class can be used to declare a single class within your buildfile.
+ * You can then reference this class in any task that takes custom classes (selectors,
+ * mappers, filters, etc.)
+ *
+ * Subclasses exist for conveniently declaring and registering tasks and types.
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.6 $
+ * @package phing.tasks.system
+ */
+class AdhocTask extends Task {
+
+ /**
+ * The PHP script
+ * @var string
+ */
+ protected $script;
+
+ protected $newClasses = array();
+
+ /**
+ * Main entry point
+ */
+ public function main() {
+ $this->execute();
+ if ($this->newClasses) {
+ foreach($this->newClasses as $classname) {
+ $this->log("Added adhoc class " . $classname, PROJECT_MSG_VERBOSE);
+ }
+ } else {
+ $this->log("Adhoc task executed but did not result in any new classes.", PROJECT_MSG_VERBOSE);
+ }
+ }
+
+ /**
+ * Get array of names of newly defined classes.
+ * @return array
+ */
+ protected function getNewClasses() {
+ return $this->newClasses;
+ }
+
+ /**
+ * Load the adhoc class, and perform any core validation.
+ * @return string The classname of the ProjectComponent class.
+ * @throws BuildException - if more than one class is defined.
+ */
+ protected function execute() {
+ $classes = get_declared_classes();
+ eval($this->script);
+ $this->newClasses = array_diff(get_declared_classes(), $classes);
+ }
+
+ /**
+ * Set the script.
+ * @param string $script
+ */
+ public function addText($script) {
+ $this->script = $script;
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/AdhocTaskdefTask.php b/buildscripts/phing/classes/phing/tasks/system/AdhocTaskdefTask.php
new file mode 100644
index 00000000..ea336f84
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/AdhocTaskdefTask.php
@@ -0,0 +1,90 @@
+<?php
+
+/*
+ * $Id: AdhocTaskdefTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/tasks/system/AdhocTask.php';
+
+/**
+ * A class for creating adhoc tasks in build file.
+ *
+ * <target name="test-adhoc">
+ * <adhoc-task name="foo"><![CDATA[
+ *
+ * class FooTest extends Task {
+ * private $bar;
+ *
+ * function setBar($bar) {
+ * $this->bar = $bar;
+ * }
+ *
+ * function main() {
+ * $this->log("In FooTest: " . $this->bar);
+ * }
+ * }
+ *
+ * ]]></adhoc-task>
+ *
+ * <foo bar="B.L.I.N.G"/>
+ * </target>
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.5 $
+ * @package phing.tasks.system
+ */
+class AdhocTaskdefTask extends AdhocTask {
+
+ /**
+ * The tag that refers to this task.
+ */
+ private $name;
+
+ /**
+ * Set the tag that will represent this adhoc task/type.
+ * @param string $name
+ */
+ public function setName($name) {
+ $this->name = $name;
+ }
+
+ /** Main entry point */
+ public function main() {
+ if ($this->name === null) {
+ throw new BuildException("The name attribute is required for adhoc task definition.",$this->location);
+ }
+
+ $this->execute();
+
+ $classes = $this->getNewClasses();
+ if (count($classes) !== 1) {
+ throw new BuildException("You must define one (and only one) class for AdhocTaskdefTask.");
+ }
+ $classname = array_shift($classes);
+
+ // instantiate it to make sure it is an instance of Task
+ $t = new $classname();
+ if (!($t instanceof Task)) {
+ throw new BuildException("The adhoc class you defined must be an instance of phing.Task", $this->location);
+ }
+
+ $this->log("Task " . $this->name . " will be handled by class " . $classname, PROJECT_MSG_VERBOSE);
+ $this->project->addTaskDefinition($this->name, $classname);
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/AdhocTypedefTask.php b/buildscripts/phing/classes/phing/tasks/system/AdhocTypedefTask.php
new file mode 100644
index 00000000..b836ad93
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/AdhocTypedefTask.php
@@ -0,0 +1,71 @@
+<?php
+
+/*
+ * $Id: AdhocTypedefTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/tasks/system/AdhocTask.php';
+
+/**
+ * A class for creating adhoc datatypes in build file.
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.4 $
+ * @package phing.tasks.system
+ */
+class AdhocTypedefTask extends AdhocTask {
+
+ /**
+ * The tag that refers to this task.
+ */
+ private $name;
+
+ /**
+ * Set the tag that will represent this adhoc task/type.
+ * @param string $name
+ */
+ public function setName($name) {
+ $this->name = $name;
+ }
+
+ /** Main entry point */
+ public function main() {
+
+ if ($this->name === null) {
+ throw new BuildException("The name attribute is required for adhoc task definition.",$this->location);
+ }
+
+ $this->execute();
+
+ $classes = $this->getNewClasses();
+ if (count($classes) !== 1) {
+ throw new BuildException("You must define one (and only one) class for AdhocTypedefTask.");
+ }
+ $classname = array_shift($classes);
+
+ // instantiate it to make sure it is an instance of ProjectComponent
+ $t = new $classname();
+ if (!($t instanceof ProjectComponent)) {
+ throw new BuildException("The adhoc class you defined must be an instance of phing.ProjectComponent", $this->location);
+ }
+
+ $this->log("Datatype " . $this->name . " will be handled by class " . $classname, PROJECT_MSG_VERBOSE);
+ $this->project->addDataTypeDefinition($this->name, $classname);
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/AppendTask.php b/buildscripts/phing/classes/phing/tasks/system/AppendTask.php
new file mode 100644
index 00000000..feb797cf
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/AppendTask.php
@@ -0,0 +1,240 @@
+<?php
+/*
+ * $Id: AppendTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+include_once 'phing/types/FileList.php';
+include_once 'phing/types/FileSet.php';
+
+/**
+ * Appends text, contents of a file or set of files defined by a filelist to a destination file.
+ *
+ * <code>
+ * <append text="And another thing\n" destfile="badthings.log"/>
+ * </code>
+ * OR
+ * <code>
+ * <append file="header.html" destfile="fullpage.html"/>
+ * <append file="body.html" destfile="fullpage.html"/>
+ * <append file="footer.html" destfile="fullpage.html"/>
+ * </code>
+ * OR
+ * <code>
+ * <append destfile="${process.outputfile}">
+ * <filterchain>
+ * <xsltfilter style="${process.stylesheet}">
+ * <param name="mode" expression="${process.xslt.mode}"/>
+ * <param name="file_name" expression="%{task.append.current_file.basename}"/> <!-- Example of using a RegisterSlot variable -->
+ * </xsltfilter>
+ * </filterchain>
+ * <filelist dir="book/" listfile="book/PhingGuide.book"/>
+ * </append>
+ * </code>
+ * @package phing.tasks.system
+ * @version $Revision: 1.14 $
+ */
+class AppendTask extends Task {
+
+ /** Append stuff to this file. */
+ private $to;
+
+ /** Explicit file to append. */
+ private $file;
+
+ /** Any filesets of files that should be appended. */
+ private $filesets = array();
+
+ /** Any filelists of files that should be appended. */
+ private $filelists = array();
+
+ /** Any filters to be applied before append happens. */
+ private $filterChains = array();
+
+ /** Text to append. (cannot be used in conjunction w/ files or filesets) */
+ private $text;
+
+ /** Sets specific file to append. */
+ function setFile(PhingFile $f) {
+ $this->file = $f;
+ }
+
+ /**
+ * Set target file to append to.
+ * @deprecated Will be removed with final release.
+ */
+ function setTo(PhingFile $f) {
+ $this->log("The 'to' attribute is deprecated in favor of 'destFile'; please update your code.", PROJECT_MSG_WARN);
+ $this->to = $f;
+ }
+
+ /**
+ * The more conventional naming for method to set destination file.
+ * @param PhingFile $f
+ */
+ function setDestFile(PhingFile $f) {
+ $this->to = $f;
+ }
+
+ /**
+ * Supports embedded <filelist> element.
+ * @return FileList
+ */
+ function createFileList() {
+ $num = array_push($this->filelists, new FileList());
+ return $this->filelists[$num-1];
+ }
+
+ /**
+ * Nested creator, adds a set of files (nested <fileset> attribute).
+ * This is for when you don't care what order files get appended.
+ * @return FileSet
+ */
+ function createFileSet() {
+ $num = array_push($this->filesets, new FileSet());
+ return $this->filesets[$num-1];
+ }
+
+ /**
+ * Creates a filterchain
+ *
+ * @return FilterChain The created filterchain object
+ */
+ function createFilterChain() {
+ $num = array_push($this->filterChains, new FilterChain($this->project));
+ return $this->filterChains[$num-1];
+ }
+
+ /**
+ * Sets text to append. (cannot be used in conjunction w/ files or filesets).
+ * @param string $txt
+ */
+ function setText($txt) {
+ $this->text = (string) $txt;
+ }
+
+ /**
+ * Sets text to append. Supports CDATA.
+ * @param string $txt
+ */
+ function addText($txt) {
+ $this->text = (string) $txt;
+ }
+
+
+ /** Append the file(s). */
+ function main() {
+
+ if ($this->to === null) {
+ throw new BuildException("You must specify the 'destFile' attribute");
+ }
+
+ if ($this->file === null && empty($this->filelists) && empty($this->filesets) && $this->text === null) {
+ throw new BuildException("You must specify a file, use a filelist, or specify a text value.");
+ }
+
+ if ($this->text !== null && ($this->file !== null || !empty($this->filelists))) {
+ throw new BuildException("Cannot use text attribute in conjunction with file or filelists.");
+ }
+
+ // create a filwriter to append to "to" file.
+ $writer = new FileWriter($this->to, $append=true);
+
+ if ($this->text !== null) {
+
+ // simply append the text
+ $this->log("Appending string to " . $this->to->getPath());
+
+ // for debugging primarily, maybe comment
+ // out for better performance(?)
+ $lines = explode("\n", $this->text);
+ foreach($lines as $line) {
+ $this->log($line, PROJECT_MSG_VERBOSE);
+ }
+
+ $writer->write($this->text);
+
+ } else {
+
+ // append explicitly-specified file
+ if ($this->file !== null) {
+ try {
+ $this->appendFile($writer, $this->file);
+ } catch (Exception $ioe) {
+ $this->log("Unable to append contents of file " . $this->file->getAbsolutePath() . ": " . $ioe->getMessage(), PROJECT_MSG_WARN);
+ }
+ }
+
+ // append the files in the filelists
+ foreach($this->filelists as $fl) {
+ try {
+ $files = $fl->getFiles($this->project);
+ $this->appendFiles($writer, $files, $fl->getDir($this->project));
+ } catch (BuildException $be) {
+ $this->log($be->getMessage(), PROJECT_MSG_WARN);
+ }
+ }
+
+ // append any files in filesets
+ foreach($this->filesets as $fs) {
+ try {
+ $files = $fs->getDirectoryScanner($this->project)->getIncludedFiles();
+ $this->appendFiles($writer, $files, $fs->getDir($this->project));
+ } catch (BuildException $be) {
+ $this->log($be->getMessage(), PROJECT_MSG_WARN);
+ }
+ }
+
+ } // if ($text ) {} else {}
+
+ $writer->close();
+ }
+
+ /**
+ * Append an array of files in a directory.
+ * @param FileWriter $writer The FileWriter that is appending to target file.
+ * @param array $files array of files to delete; can be of zero length
+ * @param PhingFile $dir directory to work from
+ */
+ private function appendFiles(FileWriter $writer, $files, PhingFile $dir) {
+ if (!empty($files)) {
+ $this->log("Attempting to append " . count($files) . " files" .($dir !== null ? ", using basedir " . $dir->getPath(): ""));
+ $basenameSlot = Register::getSlot("task.append.current_file");
+ $pathSlot = Register::getSlot("task.append.current_file.path");
+ foreach($files as $filename) {
+ try {
+ $f = new PhingFile($dir, $filename);
+ $basenameSlot->setValue($filename);
+ $pathSlot->setValue($f->getPath());
+ $this->appendFile($writer, $f);
+ } catch (Exception $ioe) {
+ $this->log("Unable to append contents of file " . $f->getAbsolutePath() . ": " . $ioe->getMessage(), PROJECT_MSG_WARN);
+ }
+ }
+ } // if !empty
+ }
+
+ private function appendFile(FileWriter $writer, PhingFile $f) {
+ $in = FileUtils::getChainedReader(new FileReader($f), $this->filterChains, $this->project);
+ while(-1 !== ($buffer = $in->read())) { // -1 indicates EOF
+ $writer->write($buffer);
+ }
+ $this->log("Appending contents of " . $f->getPath() . " to " . $this->to->getPath());
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/AvailableTask.php b/buildscripts/phing/classes/phing/tasks/system/AvailableTask.php
new file mode 100644
index 00000000..76de3e40
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/AvailableTask.php
@@ -0,0 +1,132 @@
+<?php
+/*
+ * $Id: AvailableTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+include_once 'phing/tasks/system/condition/ConditionBase.php';
+
+/**
+ * <available> task.
+ *
+ * Note: implements condition interface (see condition/Condition.php)
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright © 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.11 $
+ * @package phing.tasks.system
+ */
+class AvailableTask extends Task {
+
+ /** Property to check for. */
+ private $property;
+
+ /** Value property should be set to. */
+ private $value = "true";
+
+ /** Resource to check for */
+ private $resource;
+
+ private $type = null;
+ private $filepath = null;
+
+ function setProperty($property) {
+ $this->property = (string) $property;
+ }
+
+ function setValue($value) {
+ $this->value = (string) $value;
+ }
+
+ function setFile(PhingFile $file) {
+ $this->file = $file;
+ }
+
+ function setResource($resource) {
+ $this->resource = (string) $resource;
+ }
+
+ function setType($type) {
+ $this->type = (string) strtolower($type);
+ }
+
+ function main() {
+ if ($this->property === null) {
+ throw new BuildException("property attribute is required", $this->location);
+ }
+ if ($this->evaluate()) {
+ $this->project->setProperty($this->property, $this->value);
+ }
+ }
+
+ function evaluate() {
+ if ($this->file === null && $this->resource === null) {
+ throw new BuildException("At least one of (file|resource) is required", $this->location);
+ }
+
+ if ($this->type !== null && ($this->type !== "file" && $this->type !== "dir")) {
+ throw new BuildException("Type must be one of either dir or file", $this->location);
+ }
+
+ if (($this->file !== null) && !$this->_checkFile()) {
+ $this->log("Unable to find " . $this->file->__toString() . " to set property " . $this->property, PROJECT_MSG_VERBOSE);
+ return false;
+ }
+
+ if (($this->resource !== null) && !$this->_checkResource($this->resource)) {
+ $this->log("Unable to load resource " . $this->resource . " to set property " . $this->property, PROJECT_MSG_VERBOSE);
+ return false;
+ }
+
+ return true;
+ }
+
+ // this is prepared for the path type
+ function _checkFile() {
+ if ($this->filepath === null) {
+ return $this->_checkFile1($this->file);
+ } else {
+ $paths = $this->filepath->listDir();
+ for($i=0,$pcnt=count($paths); $i < $pcnt; $i++) {
+ $this->log("Searching " . $paths[$i], PROJECT_MSG_VERBOSE);
+ $tmp = new PhingFile($paths[$i], $this->file->getName());
+ if($tmp->isFile()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ function _checkFile1($file) {
+ if ($this->type !== null) {
+ if ($this->type === "dir") {
+ return $file->isDirectory();
+ } else if ($this->type === "file") {
+ return $file->isFile();
+ }
+ }
+ return $file->exists();
+ }
+
+ function _checkResource($resource) {
+ return $this->_checkFile1(new PhingFile(Phing::getResourcePath($resource)));
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/ChmodTask.php b/buildscripts/phing/classes/phing/tasks/system/ChmodTask.php
new file mode 100644
index 00000000..80470dea
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/ChmodTask.php
@@ -0,0 +1,177 @@
+<?php
+/*
+ * $Id: ChmodTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+include_once 'phing/types/FileSet.php';
+
+/**
+ * Task that changes the permissions on a file/directory.
+ *
+ * @author Manuel Holtgrewe <grin@gmx.net>
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.12 $
+ * @package phing.tasks.system
+ */
+class ChmodTask extends Task {
+
+ private $file;
+
+ private $mode;
+
+ private $filesets = array();
+
+ private $filesystem;
+
+ private $quiet = false;
+ private $failonerror = true;
+
+ /**
+ * This flag means 'note errors to the output, but keep going'
+ * @see setQuiet()
+ */
+ function setFailonerror($bool) {
+ $this->failonerror = $bool;
+ }
+
+ /**
+ * Set quiet mode, which suppresses warnings if chmod() fails.
+ * @see setFailonerror()
+ */
+ function setQuiet($bool) {
+ $this->quiet = $bool;
+ if ($this->quiet) {
+ $this->failonerror = false;
+ }
+ }
+
+ /**
+ * Sets a single source file to touch. If the file does not exist
+ * an empty file will be created.
+ */
+ function setFile(PhingFile $file) {
+ $this->file = $file;
+ }
+
+ function setMode($str) {
+ $this->mode = $str;
+ }
+
+ /**
+ * Nested creator, adds a set of files (nested fileset attribute).
+ */
+ function createFileSet() {
+ $num = array_push($this->filesets, new FileSet());
+ return $this->filesets[$num-1];
+ }
+
+ /**
+ * Execute the touch operation.
+ * @return void
+ */
+ function main() {
+ // Check Parameters
+ $this->checkParams();
+ $this->chmod();
+ }
+
+ /**
+ * Ensure that correct parameters were passed in.
+ * @return void
+ */
+ private function checkParams() {
+
+ if ($this->file === null && empty($this->filesets)) {
+ throw new BuildException("Specify at least one source - a file or a fileset.");
+ }
+
+ if ($this->mode === null) {
+ throw new BuildException("You have to specify an octal mode for chmod.");
+ }
+
+ // check for mode to be in the correct format
+ if (!preg_match('/^([0-7]){3,4}$/', $this->mode)) {
+ throw new BuildException("You have specified an invalid mode.");
+ }
+
+ }
+
+ /**
+ * Does the actual work.
+ * @return void
+ */
+ private function chmod() {
+
+ if (strlen($this->mode) === 4) {
+ $mode = octdec($this->mode);
+ } else {
+ // we need to prepend the 0 before converting
+ $mode = octdec("0". $this->mode);
+ }
+
+ // one file
+ if ($this->file !== null) {
+ $this->chmodFile($this->file, $mode);
+ }
+
+ // filesets
+ foreach($this->filesets as $fs) {
+
+ $ds = $fs->getDirectoryScanner($this->project);
+ $fromDir = $fs->getDir($this->project);
+
+ $srcFiles = $ds->getIncludedFiles();
+ $srcDirs = $ds->getIncludedDirectories();
+
+ for ($j = 0, $filecount = count($srcFiles); $j < $filecount; $j++) {
+ $this->chmodFile(new PhingFile($fromDir, $srcFiles[$j]), $mode);
+ }
+
+ for ($j = 0, $dircount = count($srcDirs); $j < $dircount; $j++) {
+ $this->chmodFile(new PhingFile($fromDir, $srcDirs[$j]), $mode);
+ }
+ }
+
+ }
+
+ /**
+ * Actually change the mode for the file.
+ * @param PhingFile $file
+ * @param int $mode
+ */
+ private function chmodFile(PhingFile $file, $mode) {
+ if ( !$file->exists() ) {
+ throw new BuildException("The file " . $file->__toString() . " does not exist");
+ }
+
+ try {
+ $file->setMode($mode);
+ $this->log("Changed file mode on '" . $file->__toString() ."' to " . vsprintf("%o", $mode));
+ } catch (Exception $e) {
+ if($this->failonerror) {
+ throw $e;
+ } else {
+ $this->log($e->getMessage(), $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN);
+ }
+ }
+ }
+
+}
+
diff --git a/buildscripts/phing/classes/phing/tasks/system/ConditionTask.php b/buildscripts/phing/classes/phing/tasks/system/ConditionTask.php
new file mode 100644
index 00000000..fe6ee60b
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/ConditionTask.php
@@ -0,0 +1,74 @@
+<?php
+/*
+ * $Id: ConditionTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+require_once 'phing/tasks/system/condition/ConditionBase.php';
+
+/**
+ * <condition> task as a generalization of <available>
+ *
+ * <p>This task supports boolean logic as well as pluggable conditions
+ * to decide, whether a property should be set.</p>
+ *
+ * <p>This task does not extend Task to take advantage of
+ * ConditionBase.</p>
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright © 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.7 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $
+ * @access public
+ * @package phing.tasks.system
+ */
+class ConditionTask extends ConditionBase {
+
+ private $property;
+ private $value = "true";
+
+ /**
+ * The name of the property to set. Required.
+ */
+ function setProperty($p) {
+ $this->property = $p;
+ }
+
+ /**
+ * The value for the property to set. Defaults to "true".
+ */
+ function setValue($v) {
+ $this->value = $v;
+ }
+
+ /**
+ * See whether our nested condition holds and set the property.
+ */
+ function main() {
+
+ if ($this->countConditions() > 1) {
+ throw new BuildException("You must not nest more than one condition into <condition>");
+ }
+ if ($this->countConditions() < 1) {
+ throw new BuildException("You must nest a condition into <condition>");
+ }
+ $cs = $this->getIterator();
+ if ($cs->current()->evaluate()) {
+ $this->project->setProperty($this->property, $this->value);
+ }
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/CopyTask.php b/buildscripts/phing/classes/phing/tasks/system/CopyTask.php
new file mode 100644
index 00000000..c5e4c2a5
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/CopyTask.php
@@ -0,0 +1,401 @@
+<?php
+/*
+ * $Id: CopyTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+include_once 'phing/system/io/PhingFile.php';
+include_once 'phing/util/FileUtils.php';
+include_once 'phing/util/SourceFileScanner.php';
+include_once 'phing/mappers/IdentityMapper.php';
+include_once 'phing/mappers/FlattenMapper.php';
+
+/**
+ * A phing copy task. Copies a file or directory to a new file
+ * or directory. Files are only copied if the source file is newer
+ * than the destination file, or when the destination file does not
+ * exist. It is possible to explictly overwrite existing files.
+ *
+ * @author Andreas Aderhold, andi@binarycloud.com
+ * @version $Revision: 1.16 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $
+ * @package phing.tasks.system
+ */
+class CopyTask extends Task {
+
+ protected $file = null; // the source file (from xml attribute)
+ protected $destFile = null; // the destiantion file (from xml attribute)
+ protected $destDir = null; // the destination dir (from xml attribute)
+ protected $overwrite = false; // overwrite destination (from xml attribute)
+ protected $preserveLMT = true; // sync timestamps (from xml attribute)
+ protected $includeEmpty = true; // include empty dirs? (from XML)
+ protected $flatten = false; // apply the FlattenMapper right way (from XML)
+ protected $mapperElement = null;
+
+ protected $fileCopyMap = array(); // asoc array containing mapped file names
+ protected $dirCopyMap = array(); // asoc array containing mapped file names
+ protected $fileUtils = null; // a instance of fileutils
+ protected $filesets = array(); // all fileset objects assigned to this task
+ protected $filterChains = array(); // all filterchains objects assigned to this task
+
+ protected $verbosity = PROJECT_MSG_VERBOSE;
+
+ /**
+ * Sets up this object internal stuff. i.e. the Fileutils instance
+ *
+ * @return object The CopyTask instnace
+ * @access public
+ */
+ function __construct() {
+ $this->fileUtils = new FileUtils();
+ }
+
+ /**
+ * Set the overwrite flag. IntrospectionHelper takes care of
+ * booleans in set* methods so we can assume that the right
+ * value (boolean primitive) is coming in here.
+ *
+ * @param boolean Overwrite the destination file(s) if it/they already exist
+ * @return void
+ * @access public
+ */
+ function setOverwrite($bool) {
+ $this->overwrite = (boolean) $bool;
+ }
+
+ /**
+ * Used to force listing of all names of copied files.
+ * @param boolean $verbosity
+ */
+ function setVerbose($verbosity) {
+ if ($verbosity) {
+ $this->verbosity = PROJECT_MSG_INFO;
+ } else {
+ $this->verbosity = PROJECT_MSG_VERBOSE;
+ }
+ }
+
+ /**
+ * Set the preserve timestmap flag. IntrospectionHelper takes care of
+ * booleans in set* methods so we can assume that the right
+ * value (boolean primitive) is coming in here.
+ *
+ * @param boolean Preserve the timestamp on the destination file
+ * @return void
+ * @access public
+ */
+ function setTstamp($bool) {
+ $this->preserveLMT = (boolean) $bool;
+ }
+
+
+ /**
+ * Set the include empty dirs flag. IntrospectionHelper takes care of
+ * booleans in set* methods so we can assume that the right
+ * value (boolean primitive) is coming in here.
+ *
+ * @param boolean Flag if empty dirs should be cpoied too
+ * @return void
+ * @access public
+ */
+ function setIncludeEmptyDirs($bool) {
+ $this->includeEmpty = (boolean) $bool;
+ }
+
+
+ /**
+ * Set the file. We have to manually take care of the
+ * type that is coming due to limited type support in php
+ * in and convert it manually if neccessary.
+ *
+ * @param string/object The source file. Either a string or an PhingFile object
+ * @return void
+ * @access public
+ */
+ function setFile(PhingFile $file) {
+ $this->file = $file;
+ }
+
+
+ /**
+ * Set the toFile. We have to manually take care of the
+ * type that is coming due to limited type support in php
+ * in and convert it manually if neccessary.
+ *
+ * @param string/object The dest file. Either a string or an PhingFile object
+ * @return void
+ * @access public
+ */
+ function setTofile(PhingFile $file) {
+ $this->destFile = $file;
+ }
+
+
+ /**
+ * Set the toDir. We have to manually take care of the
+ * type that is coming due to limited type support in php
+ * in and convert it manually if neccessary.
+ *
+ * @param string/object The directory, either a string or an PhingFile object
+ * @return void
+ * @access public
+ */
+ function setTodir(PhingFile $dir) {
+ $this->destDir = $dir;
+ }
+
+ /**
+ * Nested creator, creates a FileSet for this task
+ *
+ * @access public
+ * @return object The created fileset object
+ */
+ function createFileSet() {
+ $num = array_push($this->filesets, new FileSet());
+ return $this->filesets[$num-1];
+ }
+
+ /**
+ * Creates a filterchain
+ *
+ * @access public
+ * @return object The created filterchain object
+ */
+ function createFilterChain() {
+ $num = array_push($this->filterChains, new FilterChain($this->project));
+ return $this->filterChains[$num-1];
+ }
+
+ /**
+ * Nested creator, creates one Mapper for this task
+ *
+ * @access public
+ * @return object The created Mapper type object
+ * @throws BuildException
+ */
+ function createMapper() {
+ if ($this->mapperElement !== null) {
+ throw new BuildException("Cannot define more than one mapper", $this->location);
+ }
+ $this->mapperElement = new Mapper($this->project);
+ return $this->mapperElement;
+ }
+
+ /**
+ * The main entry point where everything gets in motion.
+ *
+ * @access public
+ * @return true on success
+ * @throws BuildException
+ */
+ function main() {
+
+ $this->validateAttributes();
+
+ if ($this->file !== null) {
+ if ($this->file->exists()) {
+ if ($this->destFile === null) {
+ $this->destFile = new PhingFile($this->destDir, (string) $this->file->getName());
+ }
+ if ($this->overwrite === true || ($this->file->lastModified() > $this->destFile->lastModified())) {
+ $this->fileCopyMap[$this->file->getAbsolutePath()] = $this->destFile->getAbsolutePath();
+ } else {
+ $this->log($this->file->getName()." omitted, is up to date");
+ }
+ } else {
+ // terminate build
+ throw new BuildException("Could not find file " . $this->file->__toString() . " to copy.");
+ }
+ }
+
+ $project = $this->getProject();
+
+ // process filesets
+ foreach($this->filesets as $fs) {
+ $ds = $fs->getDirectoryScanner($project);
+ $fromDir = $fs->getDir($project);
+ $srcFiles = $ds->getIncludedFiles();
+ $srcDirs = $ds->getIncludedDirectories();
+ $this->_scan($fromDir, $this->destDir, $srcFiles, $srcDirs);
+ }
+
+ // go and copy the stuff
+ $this->doWork();
+
+ if ($this->destFile !== null) {
+ $this->destDir = null;
+ }
+ }
+
+ /**
+ * Validates attributes coming in from XML
+ *
+ * @access private
+ * @return void
+ * @throws BuildException
+ */
+ private function validateAttributes() {
+
+ if ($this->file === null && count($this->filesets) === 0) {
+ throw new BuildException("CopyTask. Specify at least one source - a file or a fileset.");
+ }
+
+ if ($this->destFile !== null && $this->destDir !== null) {
+ throw new BuildException("Only one of destfile and destdir may be set.");
+ }
+
+ if ($this->destFile === null && $this->destDir === null) {
+ throw new BuildException("One of destfile or destdir must be set.");
+ }
+
+ if ($this->file !== null && $this->file->exists() && $this->file->isDirectory()) {
+ throw new BuildException("Use a fileset to copy directories.");
+ }
+
+ if ($this->destFile !== null && count($this->filesets) > 0) {
+ throw new BuildException("Cannot concatenate multple files into a single file.");
+ }
+
+ if ($this->destFile !== null) {
+ $this->destDir = new PhingFile($this->destFile->getParent());
+ }
+ }
+
+ /**
+ * Compares source files to destination files to see if they
+ * should be copied.
+ *
+ * @access private
+ * @return void
+ */
+ private function _scan(&$fromDir, &$toDir, &$files, &$dirs) {
+ /* mappers should be generic, so we get the mappers here and
+ pass them on to builMap. This method is not redundan like it seems */
+ $mapper = null;
+ if ($this->mapperElement !== null) {
+ $mapper = $this->mapperElement->getImplementation();
+ } else if ($this->flatten) {
+ $mapper = new FlattenMapper();
+ } else {
+ $mapper = new IdentityMapper();
+ }
+ $this->buildMap($fromDir, $toDir, $files, $mapper, $this->fileCopyMap);
+ $this->buildMap($fromDir, $toDir, $dirs, $mapper, $this->dirCopyMap);
+ }
+
+ /**
+ * Builds a map of filenames (from->to) that should be copied
+ *
+ * @access private
+ * @return void
+ */
+ private function buildMap(&$fromDir, &$toDir, &$names, &$mapper, &$map) {
+ $toCopy = null;
+ if ($this->overwrite) {
+ $v = array();
+ foreach($names as $name) {
+ $result = $mapper->main($name);
+ if ($result !== null) {
+ $v[] = $name;
+ }
+ }
+ $toCopy = $v;
+ } else {
+ $ds = new SourceFileScanner($this);
+ $toCopy = $ds->restrict($names, $fromDir, $toDir, $mapper);
+ }
+
+ for ($i=0,$_i=count($toCopy); $i < $_i; $i++) {
+ $src = new PhingFile($fromDir, $toCopy[$i]);
+ $mapped = $mapper->main($toCopy[$i]);
+ $dest = new PhingFile($toDir, $mapped[0]);
+ $map[$src->getAbsolutePath()] = $dest->getAbsolutePath();
+ }
+ }
+
+
+ /**
+ * Actually copies the files
+ *
+ * @access private
+ * @return void
+ * @throws BuildException
+ */
+ private function doWork() {
+
+ // These "slots" allow filters to retrieve information about the currently-being-process files
+ $fromSlot = $this->getRegisterSlot("currentFromFile");
+ $fromBasenameSlot = $this->getRegisterSlot("currentFromFile.basename");
+
+ $toSlot = $this->getRegisterSlot("currentToFile");
+ $toBasenameSlot = $this->getRegisterSlot("currentToFile.basename");
+
+ $mapSize = count($this->fileCopyMap);
+ $total = $mapSize;
+ if ($mapSize > 0) {
+ $this->log("Copying ".$mapSize." file".(($mapSize) === 1 ? '' : 's')." to ". $this->destDir->getAbsolutePath());
+ // walks the map and actually copies the files
+ $count=0;
+ foreach($this->fileCopyMap as $from => $to) {
+ if ($from === $to) {
+ $this->log("Skipping self-copy of " . $from, $this->verbosity);
+ $total--;
+ continue;
+ }
+ $this->log("From ".$from." to ".$to, $this->verbosity);
+ try { // try to copy file
+
+ $fromFile = new PhingFile($from);
+ $toFile = new PhingFile($to);
+
+ $fromSlot->setValue($fromFile->getPath());
+ $fromBasenameSlot->setValue($fromFile->getName());
+
+ $toSlot->setValue($toFile->getPath());
+ $toBasenameSlot->setValue($toFile->getName());
+
+ $this->fileUtils->copyFile($fromFile, $toFile, $this->overwrite, $this->preserveLMT, $this->filterChains, $this->getProject());
+
+ $count++;
+ } catch (IOException $ioe) {
+ $this->log("Failed to copy " . $from . " to " . $to . ": " . $ioe->getMessage(), PROJECT_MSG_ERR);
+ }
+ }
+ }
+
+ // handle empty dirs if appropriate
+ if ($this->includeEmpty) {
+ $e = array_values($this->dirCopyMap);
+ $count = 0;
+ foreach ($e as $dir) {
+ $d = new PhingFile((string) $dir);
+ if (!$d->exists()) {
+ if (!$d->mkdirs()) {
+ $this->log("Unable to create directory " . $d->__toString(), PROJECT_MSG_ERR);
+ } else {
+ $count++;
+ }
+ }
+ }
+ if ($count > 0) {
+ $this->log("Copied ".$count." empty director" . ($count == 1 ? "y" : "ies") . " to " . $this->destDir->getAbsolutePath());
+ }
+ }
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/CvsPassTask.php b/buildscripts/phing/classes/phing/tasks/system/CvsPassTask.php
new file mode 100644
index 00000000..0003c50f
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/CvsPassTask.php
@@ -0,0 +1,173 @@
+<?php
+/*
+ * $Id: CvsPassTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+include_once 'phing/system/io/BufferedReader.php';
+include_once 'phing/system/io/BufferedWriter.php';
+include_once 'phing/util/StringHelper.php';
+
+/**
+ * Adds an new entry to a CVS password file.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Jeff Martin <jeff@custommonkey.org> (Ant)
+ * @version $Revision: 1.7 $
+ * @package phing.tasks.system
+ */
+class CVSPassTask extends Task {
+
+ /** CVS Root */
+ private $cvsRoot;
+ /** Password file to add password to */
+ private $passFile;
+ /** Password to add to file */
+ private $password;
+
+ /** Array contain char conversion data */
+ private static $shifts = array(
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 114, 120, 53, 79, 96, 109, 72, 108, 70, 64, 76, 67, 116, 74, 68, 87,
+ 111, 52, 75, 119, 49, 34, 82, 81, 95, 65, 112, 86, 118, 110, 122, 105,
+ 41, 57, 83, 43, 46, 102, 40, 89, 38, 103, 45, 50, 42, 123, 91, 35,
+ 125, 55, 54, 66, 124, 126, 59, 47, 92, 71, 115, 78, 88, 107, 106, 56,
+ 36, 121, 117, 104, 101, 100, 69, 73, 99, 63, 94, 93, 39, 37, 61, 48,
+ 58, 113, 32, 90, 44, 98, 60, 51, 33, 97, 62, 77, 84, 80, 85, 223,
+ 225, 216, 187, 166, 229, 189, 222, 188, 141, 249, 148, 200, 184, 136, 248, 190,
+ 199, 170, 181, 204, 138, 232, 218, 183, 255, 234, 220, 247, 213, 203, 226, 193,
+ 174, 172, 228, 252, 217, 201, 131, 230, 197, 211, 145, 238, 161, 179, 160, 212,
+ 207, 221, 254, 173, 202, 146, 224, 151, 140, 196, 205, 130, 135, 133, 143, 246,
+ 192, 159, 244, 239, 185, 168, 215, 144, 139, 165, 180, 157, 147, 186, 214, 176,
+ 227, 231, 219, 169, 175, 156, 206, 198, 129, 164, 150, 210, 154, 177, 134, 127,
+ 182, 128, 158, 208, 162, 132, 167, 209, 149, 241, 153, 251, 237, 236, 171, 195,
+ 243, 233, 253, 240, 194, 250, 191, 155, 142, 137, 245, 235, 163, 242, 178, 152
+ );
+
+ /**
+ * Create a CVS task using the default cvspass file location.
+ */
+ public function __construct() {
+ $this->passFile = new PhingFile(
+ Phing::getProperty("cygwin.user.home",
+ Phing::getProperty("user.home"))
+ . DIRECTORY_SEPARATOR . ".cvspass");
+ }
+
+ /**
+ * Does the work.
+ *
+ * @throws BuildException if someting goes wrong with the build
+ */
+ public final function main() {
+ if ($this->cvsRoot === null) {
+ throw new BuildException("cvsroot is required");
+ }
+ if ($this->password === null) {
+ throw new BuildException("password is required");
+ }
+
+ $this->log("cvsRoot: " . $this->cvsRoot, PROJECT_MSG_DEBUG);
+ $this->log("password: " . $this->password, PROJECT_MSG_DEBUG);
+ $this->log("passFile: " . $this->passFile->__toString(), PROJECT_MSG_DEBUG);
+
+ $reader = null;
+ $writer = null;
+
+ try {
+ $buf = "";
+
+ if ($this->passFile->exists()) {
+ $reader = new BufferedReader(new FileReader($this->passFile));
+
+ $line = null;
+ while (($line = $reader->readLine()) !== null) {
+ if (!StringHelper::startsWith($this->cvsRoot, $line)) {
+ $buf .= $line . Phing::getProperty("line.separator");
+ }
+ }
+ }
+
+ $pwdfile = $buf . $this->cvsRoot . " A" . $this->mangle($this->password);
+
+ $this->log("Writing -> " . $pwdfile , PROJECT_MSG_DEBUG);
+
+ $writer = new BufferedWriter(new FileWriter($this->passFile));
+ $writer->write($pwdfile);
+ $writer->newLine();
+
+ $writer->close();
+ if ($reader) {
+ $reader->close();
+ }
+
+ } catch (IOException $e) {
+ if ($reader) {
+ try {
+ $reader->close();
+ } catch (Exception $e) {}
+ }
+
+ if ($writer) {
+ try {
+ $writer->close();
+ } catch (Exception $e) {}
+ }
+
+ throw new BuildException($e);
+ }
+ }
+
+ /**
+ * "Encode" the password.
+ */
+ private final function mangle($password){
+ $buf = "";
+ for ($i = 0, $plen = strlen($password); $i < $plen; $i++) {
+ $buf .= chr(self::$shifts[ord($password{$i})]);
+ }
+ return $buf;
+ }
+
+ /**
+ * The CVS repository to add an entry for.
+ * @param string $cvsRoot
+ */
+ public function setCvsroot($cvsRoot) {
+ $this->cvsRoot = $cvsRoot;
+ }
+
+ /**
+ * Password file to add the entry to.
+ * @param PhingFile $passFile
+ */
+ public function setPassfile(PhingFile $passFile) {
+ $this->passFile = $passFile;
+ }
+
+ /**
+ * Password to be added to the password file.
+ * @param string $password
+ */
+ public function setPassword($password) {
+ $this->password = $password;
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/CvsTask.php b/buildscripts/phing/classes/phing/tasks/system/CvsTask.php
new file mode 100644
index 00000000..de2950ec
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/CvsTask.php
@@ -0,0 +1,540 @@
+<?php
+/*
+ * $Id: CvsTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+include_once 'phing/tasks/system/ExecTask.php';
+include_once 'phing/types/Commandline.php';
+
+/**
+ * Task for performing CVS operations.
+ *
+ * NOTE: This implementation has been moved here from Cvs.java with
+ * the addition of some accessors for extensibility. Another task
+ * can extend this with some customized output processing.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author costin@dnt.ro (Ant)
+ * @author stefano@apache.org (Ant)
+ * @author Wolfgang Werner <wwerner@picturesafe.de> (Ant)
+ * @author Kevin Ross <kevin.ross@bredex.com> (Ant)
+ * @version $Revision: 1.14 $
+ * @package phing.tasks.system
+ */
+class CvsTask extends Task {
+
+ /**
+ * Default compression level to use, if compression is enabled via
+ * setCompression( true ).
+ */
+ const DEFAULT_COMPRESSION_LEVEL = 3;
+
+ private $cmd;
+
+ /**
+ * List of Commandline children
+ * @var array Commandline[]
+ */
+ private $commandlines = array();
+
+ /**
+ * the CVSROOT variable.
+ */
+ private $cvsRoot;
+
+ /**
+ * the CVS_RSH variable.
+ */
+ private $cvsRsh;
+
+ /**
+ * the package/module to check out.
+ */
+ private $cvsModule;
+
+ /**
+ * the default command.
+ */
+ private static $default_command = "checkout";
+
+ /**
+ * the CVS command to execute.
+ */
+ private $command = null;
+
+ /**
+ * suppress information messages.
+ */
+ private $quiet = false;
+
+ /**
+ * compression level to use.
+ */
+ private $compression = 0;
+
+ /**
+ * report only, don't change any files.
+ */
+ private $noexec = false;
+
+ /**
+ * CVS port
+ */
+ private $port = 0;
+
+ /**
+ * CVS password file
+ * @var File
+ */
+ private $passFile = null;
+
+ /**
+ * the directory where the checked out files should be placed.
+ * @var File
+ */
+ private $dest;
+
+ private $error;
+
+ private $output;
+
+ /**
+ * If true it will stop the build if cvs exits with error.
+ * Default is false. (Iulian)
+ * @var boolean
+ */
+ private $failOnError = false;
+
+ public function init() {
+ $this->cmd = new Commandline();
+ }
+
+ /**
+ * Sets up the environment for toExecute and then runs it.
+ * @param Commandline $toExecute
+ * @throws BuildException
+ */
+ protected function runCommand(Commandline $toExecute) {
+
+ // We are putting variables into the script's environment
+ // and not removing them (!) This should be fine, but is
+ // worth remembering and testing.
+
+ if ($this->port > 0) {
+ putenv("CVS_CLIENT_PORT=".$this->port);
+ }
+
+ // Need a better cross platform integration with <cvspass>, so
+ // use the same filename.
+
+ if ($this->passFile === null) {
+ $defaultPassFile = new PhingFile(Phing::getProperty("cygwin.user.home", Phing::getProperty("user.home"))
+ . DIRECTORY_SEPARATOR . ".cvspass");
+ if($defaultPassFile->exists()) {
+ $this->setPassfile($defaultPassFile);
+ }
+ }
+
+ if ($this->passFile !== null) {
+ if ($this->passFile->isFile() && $this->passFile->canRead()) {
+ putenv("CVS_PASSFILE=" . $this->passFile->__toString());
+ $this->log("Using cvs passfile: " . $this->passFile->__toString(), PROJECT_MSG_INFO);
+ } elseif (!$this->passFile->canRead()) {
+ $this->log("cvs passfile: " . $this->passFile->__toString()
+ . " ignored as it is not readable", PROJECT_MSG_WARN);
+ } else {
+ $this->log("cvs passfile: " . $this->passFile->__toString()
+ . " ignored as it is not a file",
+ PROJECT_MSG_WARN);
+ }
+ }
+
+ if ($this->cvsRsh !== null) {
+ putenv("CVS_RSH=".$this->cvsRsh);
+ }
+
+ // Use the ExecTask to handle execution of the command
+ $exe = new ExecTask($this->project);
+ $exe->setProject($this->project);
+
+ //exe.setAntRun(project);
+ if ($this->dest === null) {
+ $this->dest = $this->project->getBaseDir();
+ }
+
+ if (!$this->dest->exists()) {
+ $this->dest->mkdirs();
+ }
+
+ if ($this->output !== null) {
+ $exe->setOutput($this->output);
+ }
+
+ if ($this->error !== null) {
+ $exe->setError($this->error);
+ }
+
+ $exe->setDir($this->dest);
+
+ if (is_object($toExecute)) {
+ $toExecuteStr = $toExecute->__toString(); // unfortunately no more automagic for initial 5.0.0 release :(
+ }
+
+ $exe->setCommand($toExecuteStr);
+
+ try {
+ $actualCommandLine = $toExecuteStr; // we converted to string above
+ $this->log($actualCommandLine, PROJECT_MSG_INFO);
+ $retCode = $exe->execute();
+ $this->log("retCode=" . $retCode, PROJECT_MSG_DEBUG);
+ /*Throw an exception if cvs exited with error. (Iulian)*/
+ if ($this->failOnError && $retCode !== 0) {
+ throw new BuildException("cvs exited with error code "
+ . $retCode
+ . Phing::getProperty("line.separator")
+ . "Command line was ["
+ . $toExecute->describeCommand() . "]", $this->getLocation());
+ }
+ } catch (IOException $e) {
+ if ($this->failOnError) {
+ throw new BuildException($e, $this->getLocation());
+ } else {
+ $this->log("Caught exception: " . $e, PROJECT_MSG_WARN);
+ }
+ } catch (BuildException $e) {
+ if ($this->failOnError) {
+ throw $e;
+ } else {
+ $t = $e->getCause();
+ if ($t === null) {
+ $t = $e;
+ }
+ $this->log("Caught exception: " . $t, PROJECT_MSG_WARN);
+ }
+ } catch (Exception $e) {
+ if ($this->failOnError) {
+ throw new BuildException($e, $this->getLocation());
+ } else {
+ $this->log("Caught exception: " . $e, PROJECT_MSG_WARN);
+ }
+ }
+ }
+
+ /**
+ *
+ * @return void
+ * @throws BuildException
+ */
+ public function main() {
+
+ $savedCommand = $this->getCommand();
+
+ if ($this->getCommand() === null && empty($this->commandlines)) {
+ // re-implement legacy behaviour:
+ $this->setCommand(self::$default_command);
+ }
+
+ $c = $this->getCommand();
+ $cloned = null;
+ if ($c !== null) {
+ $cloned = $this->cmd->__copy();
+ $cloned->createArgument(true)->setLine($c);
+ $this->addConfiguredCommandline($cloned, true);
+ }
+
+ try {
+ for ($i = 0, $vecsize=count($this->commandlines); $i < $vecsize; $i++) {
+ $this->runCommand($this->commandlines[$i]);
+ }
+
+ // finally {
+ if ($cloned !== null) {
+ $this->removeCommandline($cloned);
+ }
+ $this->setCommand($savedCommand);
+
+ } catch (Exception $e) {
+ // finally {
+ if ($cloned !== null) {
+ $this->removeCommandline($cloned);
+ }
+ $this->setCommand($savedCommand);
+ throw $e;
+ }
+ }
+
+ /**
+ * The CVSROOT variable.
+ *
+ * @param string $root
+ */
+ public function setCvsRoot($root) {
+
+ // Check if not real cvsroot => set it to null
+ if ($root !== null) {
+ if (trim($root) == "") {
+ $root = null;
+ }
+ }
+
+ $this->cvsRoot = $root;
+ }
+
+ public function getCvsRoot() {
+ return $this->cvsRoot;
+ }
+
+ /**
+ * The CVS_RSH variable.
+ *
+ * @param rsh
+ */
+ public function setCvsRsh($rsh) {
+ // Check if not real cvsrsh => set it to null
+ if ($rsh !== null) {
+ if (trim($rsh) == "") {
+ $rsh = null;
+ }
+ }
+
+ $this->cvsRsh = $rsh;
+ }
+
+ public function getCvsRsh() {
+ return $this->cvsRsh;
+ }
+
+ /**
+ * Port used by CVS to communicate with the server.
+ *
+ * @param int $port
+ */
+ public function setPort($port){
+ $this->port = $port;
+ }
+
+ /**
+ * @return int
+ */
+ public function getPort() {
+ return $this->port;
+ }
+
+ /**
+ * Password file to read passwords from.
+ *
+ * @param passFile
+ */
+ public function setPassfile(PhingFile $passFile) {
+ $this->passFile = $passFile;
+ }
+
+ /**
+ * @return File
+ */
+ public function getPassFile() {
+ return $this->passFile;
+ }
+
+ /**
+ * The directory where the checked out files should be placed.
+ *
+ * @param PhingFile $dest
+ */
+ public function setDest(PhingFile $dest) {
+ $this->dest = $dest;
+ }
+
+ public function getDest() {
+ return $this->dest;
+ }
+
+ /**
+ * The package/module to operate upon.
+ *
+ * @param string $p
+ */
+ public function setModule($m) {
+ $this->cvsModule = $m;
+ }
+
+ public function getModule(){
+ return $this->cvsModule;
+ }
+
+ /**
+ * The tag of the package/module to operate upon.
+ * @param string $p
+ */
+ public function setTag($p) {
+ // Check if not real tag => set it to null
+ if ($p !== null && trim($p) !== "") {
+ $this->appendCommandArgument("-r");
+ $this->appendCommandArgument($p);
+ }
+ }
+
+ /**
+ * This needs to be public to allow configuration
+ * of commands externally.
+ */
+ public function appendCommandArgument($arg) {
+ $this->cmd->createArgument()->setValue($arg);
+ }
+
+ /**
+ * Use the most recent revision no later than the given date.
+ * @param p
+ */
+ public function setDate($p) {
+ if ($p !== null && trim($p) !== "") {
+ $this->appendCommandArgument("-D");
+ $this->appendCommandArgument($p);
+ }
+ }
+
+ /**
+ * The CVS command to execute.
+ * @param string $c
+ */
+ public function setCommand($c) {
+ $this->command = $c;
+ }
+
+ public function getCommand() {
+ return $this->command;
+ }
+
+ /**
+ * If true, suppress informational messages.
+ * @param boolean $q
+ */
+ public function setQuiet($q) {
+ $this->quiet = $q;
+ }
+
+ /**
+ * If true, report only and don't change any files.
+ *
+ * @param boolean $ne
+ */
+ public function setNoexec($ne) {
+ $this->noexec = (boolean) $ne;
+ }
+
+ /**
+ * Stop the build process if the command exits with
+ * a return code other than 0.
+ * Defaults to false.
+ * @param boolean $failOnError
+ */
+ public function setFailOnError($failOnError) {
+ $this->failOnError = (boolean) $failOnError;
+ }
+
+ /**
+ * Configure a commandline element for things like cvsRoot, quiet, etc.
+ * @return string
+ */
+ protected function configureCommandline($c) {
+ if ($c === null) {
+ return;
+ }
+ $c->setExecutable("cvs");
+
+ if ($this->cvsModule !== null) {
+ $c->createArgument()->setLine($this->cvsModule);
+ }
+ if ($this->compression > 0 && $this->compression < 10) {
+ $c->createArgument(true)->setValue("-z" . $this->compression);
+ }
+ if ($this->quiet) {
+ $c->createArgument(true)->setValue("-q");
+ }
+ if ($this->noexec) {
+ $c->createArgument(true)->setValue("-n");
+ }
+ if ($this->cvsRoot !== null) {
+ $c->createArgument(true)->setLine("-d" . $this->cvsRoot);
+ }
+ }
+
+ protected function removeCommandline(Commandline $c) {
+ $idx = array_search($c, $this->commandlines, true);
+ if ($idx === false) {
+ return false;
+ }
+ $this->commandlines = array_splice($this->commandlines, $idx, 1);
+ return true;
+ }
+
+ /**
+ * Configures and adds the given Commandline.
+ * @param insertAtStart If true, c is
+ */
+ public function addConfiguredCommandline(Commandline $c, $insertAtStart = false) {
+ if ($c === null) {
+ return;
+ }
+ $this->configureCommandline($c);
+ if ($insertAtStart) {
+ array_unshift($this->commandlines, $c);
+ } else {
+ array_push($this->commandlines, $c);
+ }
+ }
+
+ /**
+ * If set to a value 1-9 it adds -zN to the cvs command line, else
+ * it disables compression.
+ * @param int $level
+ */
+ public function setCompressionLevel($level) {
+ $this->compression = $level;
+ }
+
+ /**
+ * If true, this is the same as compressionlevel="3".
+ *
+ * @param boolean $usecomp If true, turns on compression using default
+ * level, AbstractCvsTask.DEFAULT_COMPRESSION_LEVEL.
+ */
+ public function setCompression($usecomp) {
+ $this->setCompressionLevel($usecomp ?
+ self::DEFAULT_COMPRESSION_LEVEL : 0);
+ }
+
+ /**
+ * File to which output should be written.
+ * @param PhingFile $output
+ */
+ function setOutput(PhingFile $f) {
+ $this->output = $f;
+ }
+
+ /**
+ * File to which error output should be written.
+ * @param PhingFile $output
+ */
+ function setError(PhingFile $f) {
+ $this->error = $f;
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/DeleteTask.php b/buildscripts/phing/classes/phing/tasks/system/DeleteTask.php
new file mode 100644
index 00000000..00e1e7a7
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/DeleteTask.php
@@ -0,0 +1,277 @@
+<?php
+/*
+ * $Id: DeleteTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+
+/**
+ * Deletes a file or directory, or set of files defined by a fileset.
+ *
+ * @version $Revision: 1.13 $
+ * @package phing.tasks.system
+ */
+class DeleteTask extends Task {
+
+ protected $file;
+ protected $dir;
+ protected $filesets = array();
+ protected $includeEmpty = false;
+
+ protected $quiet = false;
+ protected $failonerror = true;
+ protected $verbosity = PROJECT_MSG_VERBOSE;
+
+ /** Any filelists of files that should be deleted. */
+ private $filelists = array();
+
+ /**
+ * Set the name of a single file to be removed.
+ * @param PhingFile $file
+ */
+ function setFile(PhingFile $file) {
+ $this->file = $file;
+ }
+
+ /**
+ * Set the directory from which files are to be deleted.
+ * @param PhingFile $dir
+ */
+ function setDir(PhingFile $dir) {
+ $this->dir = $dir;
+ }
+
+ /**
+ * Used to force listing of all names of deleted files.
+ * @param boolean $verbosity
+ */
+ function setVerbose($verbosity) {
+ if ($verbosity) {
+ $this->verbosity = PROJECT_MSG_INFO;
+ } else {
+ $this->verbosity = PROJECT_MSG_VERBOSE;
+ }
+ }
+
+ /**
+ * If the file does not exist, do not display a diagnostic
+ * message or modify the exit status to reflect an error.
+ * This means that if a file or directory cannot be deleted,
+ * then no error is reported. This setting emulates the
+ * -f option to the Unix rm command. Default is false
+ * meaning things are verbose
+ */
+ function setQuiet($bool) {
+ $this->quiet = $bool;
+ if ($this->quiet) {
+ $this->failonerror = false;
+ }
+ }
+
+ /** this flag means 'note errors to the output, but keep going' */
+ function setFailOnError($bool) {
+ $this->failonerror = $bool;
+ }
+
+
+ /** Used to delete empty directories.*/
+ function setIncludeEmptyDirs($includeEmpty) {
+ $this->includeEmpty = (boolean) $includeEmpty;
+ }
+
+ /** Nested creator, adds a set of files (nested fileset attribute). */
+ function createFileSet() {
+ $num = array_push($this->filesets, new FileSet());
+ return $this->filesets[$num-1];
+ }
+
+ /** Nested creator, adds a set of files (nested fileset attribute). */
+ function createFileList() {
+ $num = array_push($this->filelists, new FileList());
+ return $this->filelists[$num-1];
+ }
+
+ /** Delete the file(s). */
+ function main() {
+ if ($this->file === null && $this->dir === null && count($this->filesets) === 0 && count($this->filelists) === 0) {
+ throw new BuildException("At least one of the file or dir attributes, or a fileset element, or a filelist element must be set.");
+ }
+
+ if ($this->quiet && $this->failonerror) {
+ throw new BuildException("quiet and failonerror cannot both be set to true", $this->location);
+ }
+
+ // delete a single file
+ if ($this->file !== null) {
+ if ($this->file->exists()) {
+ if ($this->file->isDirectory()) {
+ $this->log("Directory " . $this->file->__toString() . " cannot be removed using the file attribute. Use dir instead.");
+ } else {
+ $this->log("Deleting: " . $this->file->__toString());
+ try {
+ $this->file->delete();
+ } catch(Exception $e) {
+ $message = "Unable to delete file " . $this->file->__toString() .": " .$e->getMessage();
+ if($this->failonerror) {
+ throw new BuildException($message);
+ } else {
+ $this->log($message, $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN);
+ }
+ }
+ }
+ } else {
+ $this->log("Could not find file " . $this->file->getAbsolutePath() . " to delete.",PROJECT_MSG_VERBOSE);
+ }
+ }
+
+ // delete the directory
+ if ($this->dir !== null && $this->dir->exists() && $this->dir->isDirectory()) {
+ if ($this->verbosity === PROJECT_MSG_VERBOSE) {
+ $this->log("Deleting directory " . $this->dir->__toString());
+ }
+ $this->removeDir($this->dir);
+ }
+
+ // delete the files in the filelists
+ foreach($this->filelists as $fl) {
+ try {
+ $files = $fl->getFiles($this->project);
+ $this->removeFiles($fl->getDir($this->project), $files, $empty=array());
+ } catch (BuildException $be) {
+ // directory doesn't exist or is not readable
+ if ($this->failonerror) {
+ throw $be;
+ } else {
+ $this->log($be->getMessage(), $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN);
+ }
+ }
+ }
+
+ // delete the files in the filesets
+ foreach($this->filesets as $fs) {
+ try {
+ $ds = $fs->getDirectoryScanner($this->project);
+ $files = $ds->getIncludedFiles();
+ $dirs = $ds->getIncludedDirectories();
+ $this->removeFiles($fs->getDir($this->project), $files, $dirs);
+ } catch (BuildException $be) {
+ // directory doesn't exist or is not readable
+ if ($this->failonerror) {
+ throw $be;
+ } else {
+ $this->log($be->getMessage(), $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN);
+ }
+ }
+ }
+ }
+
+ /**
+ * Recursively removes a directory.
+ * @param PhingFile $d The directory to remove.
+ */
+ private function removeDir($d) {
+ $list = $d->listDir();
+ if ($list === null) {
+ $list = array();
+ }
+
+ foreach($list as $s) {
+ $f = new PhingFile($d, $s);
+ if ($f->isDirectory()) {
+ $this->removeDir($f);
+ } else {
+ $this->log("Deleting " . $f->__toString(), $this->verbosity);
+ try {
+ $f->delete();
+ } catch (Exception $e) {
+ $message = "Unable to delete file " . $f->__toString() . ": " . $e->getMessage();
+ if($this->failonerror) {
+ throw new BuildException($message);
+ } else {
+ $this->log($message, $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN);
+ }
+ }
+ }
+ }
+ $this->log("Deleting directory " . $d->getAbsolutePath(), $this->verbosity);
+ try {
+ $d->delete();
+ } catch (Exception $e) {
+ $message = "Unable to delete directory " . $d->__toString() . ": " . $e->getMessage();
+ if($this->failonerror) {
+ throw new BuildException($message);
+ } else {
+ $this->log($message, $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN);
+ }
+ }
+ }
+
+ /**
+ * remove an array of files in a directory, and a list of subdirectories
+ * which will only be deleted if 'includeEmpty' is true
+ * @param PhingFile $d directory to work from
+ * @param array &$files array of files to delete; can be of zero length
+ * @param array &$dirs array of directories to delete; can of zero length
+ */
+ private function removeFiles(PhingFile $d, &$files, &$dirs) {
+ if (count($files) > 0) {
+ $this->log("Deleting " . count($files) . " files from " . $d->__toString());
+ for ($j=0,$_j=count($files); $j < $_j; $j++) {
+ $f = new PhingFile($d, $files[$j]);
+ $this->log("Deleting " . $f->getAbsolutePath(), $this->verbosity);
+ try {
+ $f->delete();
+ } catch (Exception $e) {
+ $message = "Unable to delete file " . $f->__toString() . ": " . $e->getMessage();
+ if($this->failonerror) {
+ throw new BuildException($message);
+ } else {
+ $this->log($message, $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN);
+ }
+ }
+
+ }
+ }
+
+ if (count($dirs) > 0 && $this->includeEmpty) {
+ $dirCount = 0;
+ for ($j=count($dirs)-1; $j>=0; --$j) {
+ $dir = new PhingFile($d, $dirs[$j]);
+ $dirFiles = $dir->listDir();
+ if ($dirFiles === null || count($dirFiles) === 0) {
+ $this->log("Deleting " . $dir->__toString(), $this->verbosity);
+ try {
+ $dir->delete();
+ $dirCount++;
+ } catch (Exception $e) {
+ $message="Unable to delete directory " + $dir;
+ if($this->failonerror) {
+ throw new BuildException($message);
+ } else {
+ $this->log($message, $this->quiet ? PROJECT_MSG_VERBOSE : PROJECT_MSG_WARN);
+ }
+ }
+ }
+ }
+ if ($dirCount > 0) {
+ $this->log("Deleted $dirCount director" . ($dirCount==1 ? "y" : "ies") . " from " . $d->__toString());
+ }
+ }
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/EchoTask.php b/buildscripts/phing/classes/phing/tasks/system/EchoTask.php
new file mode 100644
index 00000000..229f5130
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/EchoTask.php
@@ -0,0 +1,107 @@
+<?php
+/*
+ * $Id: EchoTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/Task.php';
+
+/**
+ * Echos a message to the logging system or to a file
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @author Andreas Aderhold, andi@binarycloud.com
+ * @version $Revision: 1.5 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $
+ * @package phing.tasks.system
+ */
+
+class EchoTask extends Task {
+
+ protected $msg = "";
+
+ protected $file = "";
+
+ protected $append = false;
+
+ protected $level = "info";
+
+ function main() {
+ switch ($this->level)
+ {
+ case "error": $loglevel = PROJECT_MSG_ERR; break;
+ case "warning": $loglevel = PROJECT_MSG_WARN; break;
+ case "info": $loglevel = PROJECT_MSG_INFO; break;
+ case "verbose": $loglevel = PROJECT_MSG_VERBOSE; break;
+ case "debug": $loglevel = PROJECT_MSG_DEBUG; break;
+ }
+
+ if (empty($this->file))
+ {
+ $this->log($this->msg, $loglevel);
+ }
+ else
+ {
+ if ($this->append)
+ {
+ $handle = fopen($this->file, "a");
+ }
+ else
+ {
+ $handle = fopen($this->file, "w");
+ }
+
+ fwrite($handle, $this->msg);
+
+ fclose($handle);
+ }
+ }
+
+ /** setter for file */
+ function setFile($file)
+ {
+ $this->file = (string) $file;
+ }
+
+ /** setter for level */
+ function setLevel($level)
+ {
+ $this->level = (string) $level;
+ }
+
+ /** setter for append */
+ function setAppend($append)
+ {
+ $this->append = $append;
+ }
+
+ /** setter for message */
+ function setMsg($msg) {
+ $this->setMessage($msg);
+ }
+
+ /** alias setter */
+ function setMessage($msg) {
+ $this->msg = (string) $msg;
+ }
+
+ /** Supporting the <echo>Message</echo> syntax. */
+ function addText($msg)
+ {
+ $this->msg = (string) $msg;
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/ExecTask.php b/buildscripts/phing/classes/phing/tasks/system/ExecTask.php
new file mode 100644
index 00000000..104f7697
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/ExecTask.php
@@ -0,0 +1,248 @@
+<?php
+
+/*
+ * $Id: ExecTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+
+/**
+ * Executes a command on the shell.
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.17 $
+ * @package phing.tasks.system
+ */
+class ExecTask extends Task {
+
+ /**
+ * Command to execute.
+ * @var string
+ */
+ protected $command;
+
+ /**
+ * Working directory.
+ * @var File
+ */
+ protected $dir;
+
+ /**
+ * Operating system.
+ * @var string
+ */
+ protected $os;
+
+ /**
+ * Whether to escape shell command using escapeshellcmd().
+ * @var boolean
+ */
+ protected $escape = false;
+
+ /**
+ * Where to direct output.
+ * @var File
+ */
+ protected $output;
+
+ /**
+ * Whether to passthru the output
+ * @var boolean
+ */
+ protected $passthru = false;
+
+ /**
+ * Where to direct error output.
+ * @var File
+ */
+ protected $error;
+
+ /**
+ * If spawn is set then [unix] programs will redirect stdout and add '&'.
+ * @var boolean
+ */
+ protected $spawn = false;
+
+ /**
+ * Whether to check the return code.
+ * @var boolean
+ */
+ protected $checkreturn = false;
+
+ /**
+ * Main method: wraps execute() command.
+ * @return void
+ */
+ public function main() {
+ $this->execute();
+ }
+
+ /**
+ * Executes a program and returns the return code.
+ * Output from command is logged at INFO level.
+ * @return int Return code from execution.
+ */
+ public function execute() {
+
+ // test if os match
+ $myos = Phing::getProperty("os.name");
+ $this->log("Myos = " . $myos, PROJECT_MSG_VERBOSE);
+ if (($this->os !== null) && (strpos($os, $myos) === false)) {
+ // this command will be executed only on the specified OS
+ $this->log("Not found in " . $os, PROJECT_MSG_VERBOSE);
+ return 0;
+ }
+
+ if ($this->dir !== null) {
+ if ($this->dir->isDirectory()) {
+ $currdir = getcwd();
+ @chdir($this->dir->getPath());
+ } else {
+ throw new BuildException("Can't chdir to:" . $this->dir->__toString());
+ }
+ }
+
+
+ if ($this->escape == true) {
+ // FIXME - figure out whether this is correct behavior
+ $this->command = escapeshellcmd($this->command);
+ }
+
+ if ($this->error !== null) {
+ $this->command .= ' 2> ' . $this->error->getPath();
+ $this->log("Writing error output to: " . $this->error->getPath());
+ }
+
+ if ($this->output !== null) {
+ $this->command .= ' 1> ' . $this->output->getPath();
+ $this->log("Writing standard output to: " . $this->output->getPath());
+ } elseif ($this->spawn) {
+ $this->command .= ' 1>/dev/null';
+ $this->log("Sending ouptut to /dev/null");
+ }
+
+ // If neither output nor error are being written to file
+ // then we'll redirect error to stdout so that we can dump
+ // it to screen below.
+
+ if ($this->output === null && $this->error === null) {
+ $this->command .= ' 2>&1';
+ }
+
+ // we ignore the spawn boolean for windows
+ if ($this->spawn) {
+ $this->command .= ' &';
+ }
+
+ $this->log("Executing command: " . $this->command);
+
+ $output = array();
+ $return = null;
+ exec($this->command, $output, $return);
+
+ if ($this->dir !== null) {
+ @chdir($currdir);
+ }
+
+ foreach($output as $line) {
+ $this->log($line, ($this->passthru ? PROJECT_MSG_INFO : PROJECT_MSG_VERBOSE));
+ }
+
+ if($return != 0 && $this->checkreturn)
+ {
+ throw new BuildException("Task exited with code $return");
+ }
+
+ return $return;
+ }
+
+ /**
+ * The command to use.
+ * @param mixed $command String or string-compatible (e.g. w/ __toString()).
+ */
+ function setCommand($command) {
+ $this->command = "" . $command;
+ }
+
+ /**
+ * Whether to use escapeshellcmd() to escape command.
+ * @param boolean $escape
+ */
+ function setEscape($escape) {
+ $this->escape = (bool) $escape;
+ }
+
+ /**
+ * Specify the workign directory for executing this command.
+ * @param PhingFile $dir
+ */
+ function setDir(PhingFile $dir) {
+ $this->dir = $dir;
+ }
+
+ /**
+ * Specify OS (or muliple OS) that must match in order to execute this command.
+ * @param string $os
+ */
+ function setOs($os) {
+ $this->os = (string) $os;
+ }
+
+ /**
+ * File to which output should be written.
+ * @param PhingFile $output
+ */
+ function setOutput(PhingFile $f) {
+ $this->output = $f;
+ }
+
+ /**
+ * File to which error output should be written.
+ * @param PhingFile $output
+ */
+ function setError(PhingFile $f) {
+ $this->error = $f;
+ }
+
+ /**
+ * Whether to use passthru the output.
+ * @param boolean $passthru
+ */
+ function setPassthru($passthru) {
+ $this->passthru = (bool) $passthru;
+ }
+
+ /**
+ * Whether to suppress all output and run in the background.
+ * @param boolean $spawn
+ */
+ function setSpawn($spawn) {
+ $this->spawn = (bool) $spawn;
+ }
+
+ /**
+ * Whether to check the return code.
+ * @param boolean $checkreturn
+ */
+ function setCheckreturn($checkreturn) {
+ $this->checkreturn = (bool) $checkreturn;
+ }
+}
+
diff --git a/buildscripts/phing/classes/phing/tasks/system/ExitTask.php b/buildscripts/phing/classes/phing/tasks/system/ExitTask.php
new file mode 100644
index 00000000..7e08d369
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/ExitTask.php
@@ -0,0 +1,118 @@
+<?php
+/*
+ * $Id: ExitTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+
+/**
+ * Exits the active build, giving an additional message
+ * if available.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Nico Seessle <nico@seessle.de> (Ant)
+ * @version $Revision: 1.7 $
+ * @package phing.tasks.system
+ */
+class ExitTask extends Task {
+
+ private $message;
+ private $ifCondition;
+ private $unlessCondition;
+
+ /**
+ * A message giving further information on why the build exited.
+ *
+ * @param string $value message to output
+ */
+ public function setMsg($value) {
+ $this->setMessage($value);
+ }
+
+ /**
+ * A message giving further information on why the build exited.
+ *
+ * @param value message to output
+ */
+ public function setMessage($value) {
+ $this->message = $value;
+ }
+
+ /**
+ * Only fail if a property of the given name exists in the current project.
+ * @param c property name
+ */
+ public function setIf($c) {
+ $this->ifCondition = $c;
+ }
+
+ /**
+ * Only fail if a property of the given name does not
+ * exist in the current project.
+ * @param c property name
+ */
+ public function setUnless($c) {
+ $this->unlessCondition = $c;
+ }
+
+ /**
+ * @throws BuildException
+ */
+ public function main() {
+ if ($this->testIfCondition() && $this->testUnlessCondition()) {
+ if ($this->message !== null) {
+ throw new BuildException($this->message);
+ } else {
+ throw new BuildException("No message");
+ }
+ }
+ }
+
+ /**
+ * Set a multiline message.
+ */
+ public function addText($msg) {
+ if ($this->message === null) {
+ $this->message = "";
+ }
+ $this->message .= $this->project->replaceProperties($msg);
+ }
+
+ /**
+ * @return boolean
+ */
+ private function testIfCondition() {
+ if ($this->ifCondition === null || $this->ifCondition === "") {
+ return true;
+ }
+
+ return $this->project->getProperty($this->ifCondition) !== null;
+ }
+
+ /**
+ * @return boolean
+ */
+ private function testUnlessCondition() {
+ if ($this->unlessCondition === null || $this->unlessCondition === "") {
+ return true;
+ }
+ return $this->project->getProperty($this->unlessCondition) === null;
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/ForeachTask.php b/buildscripts/phing/classes/phing/tasks/system/ForeachTask.php
new file mode 100644
index 00000000..a2a42665
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/ForeachTask.php
@@ -0,0 +1,138 @@
+<?php
+/*
+ * $Id: ForeachTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+include_once 'phing/tasks/system/PhingTask.php';
+
+/**
+ * <foreach> task
+ *
+ * Task definition for the foreach task. This task takes a list with
+ * delimited values, and executes a target with set param.
+ *
+ * Usage:
+ * <foreach list="values" target="targ" param="name" delimiter="|" />
+ *
+ * Attributes:
+ * list --> The list of values to process, with the delimiter character,
+ * indicated by the "delimiter" attribute, separating each value.
+ * target --> The target to call for each token, passing the token as the
+ * parameter with the name indicated by the "param" attribute.
+ * param --> The name of the parameter to pass the tokens in as to the
+ * target.
+ * delimiter --> The delimiter string that separates the values in the "list"
+ * parameter. The default is ",".
+ *
+ * @author Jason Hines <jason@greenhell.com>
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.9 $
+ * @package phing.tasks.system
+ */
+class ForeachTask extends Task {
+
+ /** Delimter-separated list of values to process. */
+ private $list;
+
+ /** Name of parameter to pass to callee */
+ private $param;
+
+ /** Delimter that separates items in $list */
+ private $delimiter = ',';
+
+ /**
+ * PhingCallTask that will be invoked w/ calleeTarget.
+ * @var PhingCallTask
+ */
+ private $callee;
+
+ /**
+ * Target to execute.
+ * @var string
+ */
+ private $calleeTarget;
+
+ function init() {
+ $this->callee = $this->project->createTask("phingcall");
+ $this->callee->setOwningTarget($this->getOwningTarget());
+ $this->callee->setTaskName($this->getTaskName());
+ $this->callee->setLocation($this->getLocation());
+ $this->callee->init();
+ }
+
+ /**
+ * This method does the work.
+ * @return void
+ */
+ function main() {
+ if ($this->list === null) {
+ throw new BuildException("Missing list to iterate through");
+ }
+ if (trim($this->list) === '') {
+ return;
+ }
+ if ($this->param === null) {
+ throw new BuildException("You must supply a property name to set on each iteration in param");
+ }
+ if ($this->calleeTarget === null) {
+ throw new BuildException("You must supply a target to perform");
+ }
+
+ $callee = $this->callee;
+ $callee->setTarget($this->calleeTarget);
+ $callee->setInheritAll(true);
+ $callee->setInheritRefs(true);
+
+ $arr = explode($this->delimiter, $this->list);
+
+ foreach ($arr as $value) {
+ $this->log("Setting param '$this->param' to value '$value'", PROJECT_MSG_VERBOSE);
+ $prop = $callee->createProperty();
+ $prop->setOverride(true);
+ $prop->setName($this->param);
+ $prop->setValue($value);
+ $callee->main();
+ }
+ }
+
+ function setList($list) {
+ $this->list = (string) $list;
+ }
+
+ function setTarget($target) {
+ $this->calleeTarget = (string) $target;
+ }
+
+ function setParam($param) {
+ $this->param = (string) $param;
+ }
+
+ function setDelimiter($delimiter) {
+ $this->delimiter = (string) $delimiter;
+ }
+
+ /**
+ * @return Property
+ */
+ function createProperty() {
+ return $this->callee->createProperty();
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/IfTask.php b/buildscripts/phing/classes/phing/tasks/system/IfTask.php
new file mode 100644
index 00000000..ab773355
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/IfTask.php
@@ -0,0 +1,224 @@
+<?php
+
+/*
+ * $Id: IfTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/tasks/system/condition/ConditionBase.php';
+require_once 'phing/tasks/system/SequentialTask.php';
+
+/**
+ * Perform some tasks based on whether a given condition holds true or
+ * not.
+ *
+ * <p>This task is heavily based on the Condition framework that can
+ * be found in Ant 1.4 and later, therefore it cannot be used in
+ * conjunction with versions of Ant prior to 1.4.</p>
+ *
+ * <p>This task doesn't have any attributes, the condition to test is
+ * specified by a nested element - see the documentation of your
+ * <code><condition&gt;</code> task (see
+ * <a href="http://jakarta.apache.org/ant/manual/CoreTasks/condition.html">the
+ * online documentation</a> for example) for a complete list of nested
+ * elements.</p>
+ *
+ * <p>Just like the <code><condition&gt;</code> task, only a single
+ * condition can be specified - you combine them using
+ * <code><and&gt;</code> or <code><or&gt;</code> conditions.</p>
+ *
+ * <p>In addition to the condition, you can specify three different
+ * child elements, <code><elseif&gt;</code>, <code><then&gt;</code> and
+ * <code><else&gt;</code>. All three subelements are optional.
+ *
+ * Both <code><then&gt;</code> and <code><else&gt;</code> must not be
+ * used more than once inside the if task. Both are
+ * containers for Ant tasks, just like Ant's
+ * <code><parallel&gt;</code> and <code><sequential&gt;</code>
+ * tasks - in fact they are implemented using the same class as Ant's
+ * <code><sequential&gt;</code> task.</p>
+ *
+ * The <code><elseif&gt;</code> behaves exactly like an <code><if&gt;</code>
+ * except that it cannot contain the <code><else&gt;</code> element
+ * inside of it. You may specify as may of these as you like, and the
+ * order they are specified is the order they are evaluated in. If the
+ * condition on the <code><if&gt;</code> is false, then the first
+ * <code><elseif&gt;</code> who's conditional evaluates to true
+ * will be executed. The <code><else&gt;</code> will be executed
+ * only if the <code><if&gt;</code> and all <code><elseif&gt;</code>
+ * conditions are false.
+ *
+ * <p>Use the following task to define the <code><if&gt;</code>
+ * task before you use it the first time:</p>
+ *
+ * <pre><code>
+ * <taskdef name="if" classname="net.sf.antcontrib.logic.IfTask" /&gt;
+ * </code></pre>
+ *
+ * <h3>Crude Example</h3>
+ *
+ * <code>
+ * <if>
+ * <equals arg1="${foo}" arg2="bar" />
+ * <then>
+ * <echo message="The value of property foo is bar" />
+ * </then>
+ * <else>
+ * <echo message="The value of property foo is not bar" />
+ * </else>
+ * </if>
+ * </code>
+ *
+ * <code>
+ * <if>
+ * <equals arg1="${foo}" arg2="bar" /&gt;
+ * <then>
+ * <echo message="The value of property foo is 'bar'" />
+ * </then>
+ *
+ * <elseif>
+ * <equals arg1="${foo}" arg2="foo" />
+ * <then>
+ * <echo message="The value of property foo is 'foo'" />
+ * </then>
+ * </elseif>
+ *
+ * <else>
+ * <echo message="The value of property foo is not 'foo' or 'bar'" />
+ * </else>
+ * </if>
+ * </code>
+ *
+ * @author <a href="mailto:stefan.bodewig@freenet.de">Stefan Bodewig</a>
+ */
+class IfTask extends ConditionBase {
+
+
+ private $thenTasks = null;
+ private $elseIfTasks = array();
+ private $elseTasks = null;
+
+ /***
+ * A nested Else if task
+ */
+ public function addElseIf(ElseIfTask $ei)
+ {
+ $this->elseIfTasks[] = $ei;
+ }
+
+ /**
+ * A nested <then> element - a container of tasks that will
+ * be run if the condition holds true.
+ *
+ * <p>Not required.</p>
+ */
+ public function addThen(SequentialTask $t) {
+ if ($this->thenTasks != null) {
+ throw new BuildException("You must not nest more than one <then> into <if>");
+ }
+ $this->thenTasks = $t;
+ }
+
+ /**
+ * A nested <else> element - a container of tasks that will
+ * be run if the condition doesn't hold true.
+ *
+ * <p>Not required.</p>
+ */
+ public function addElse(SequentialTask $e) {
+ if ($this->elseTasks != null) {
+ throw new BuildException("You must not nest more than one <else> into <if>");
+ }
+ $this->elseTasks = $e;
+ }
+
+ public function main() {
+
+ if ($this->countConditions() > 1) {
+ throw new BuildException("You must not nest more than one condition into <if>");
+ }
+ if ($this->countConditions() < 1) {
+ throw new BuildException("You must nest a condition into <if>");
+ }
+ $conditions = $this->getConditions();
+ $c = $conditions[0];
+
+ if ($c->evaluate()) {
+ if ($this->thenTasks != null) {
+ $this->thenTasks->main();
+ }
+ } else {
+ $done = false;
+ $sz = count($this->elseIfTasks);
+ for($i=0; $i < $sz && !$done; $i++) {
+ $ei = $this->elseIfTasks[$i];
+ if ($ei->evaluate()) {
+ $done = true;
+ $ei->main();
+ }
+ }
+
+ if (!$done && $this->elseTasks != null) {
+ $this->elseTasks->main();
+ }
+ }
+ }
+}
+
+/**
+ * "Inner" class for IfTask.
+ * This class has same basic structure as the IfTask, although of course it doesn't support <else> tags.
+ */
+class ElseIfTask extends ConditionBase {
+
+ private $thenTasks = null;
+
+ public function addThen(SequentialTask $t) {
+ if ($this->thenTasks != null) {
+ throw new BuildException("You must not nest more than one <then> into <elseif>");
+ }
+ $this->thenTasks = $t;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function evaluate() {
+
+ if ($this->countConditions() > 1) {
+ throw new BuildException("You must not nest more than one condition into <elseif>");
+ }
+ if ($this->countConditions() < 1) {
+ throw new BuildException("You must nest a condition into <elseif>");
+ }
+
+ $conditions = $this->getConditions();
+ $c = $conditions[0];
+
+ return $c->evaluate();
+ }
+
+ /**
+ *
+ */
+ public function main() {
+ if ($this->thenTasks != null) {
+ $this->thenTasks->main();
+ }
+ }
+ } \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/system/IncludePathTask.php b/buildscripts/phing/classes/phing/tasks/system/IncludePathTask.php
new file mode 100644
index 00000000..ce9beee5
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/IncludePathTask.php
@@ -0,0 +1,115 @@
+<?php
+
+/*
+ * $Id: IncludePathTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+include_once 'phing/types/Path.php';
+
+/**
+ * Adds a normalized path to the PHP include_path.
+ *
+ * This provides a way to alter the include_path without editing any global php.ini settings
+ * or PHP_CLASSPATH environment variable.
+ *
+ * <code>
+ * <includepath classpath="new/path/here"/>
+ * </code>
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.1 $
+ * @package phing.tasks.system
+ */
+class IncludePathTask extends Task {
+
+ /**
+ * Classname of task to register.
+ * This can be a dot-path -- relative to a location on PHP include_path.
+ * E.g. path.to.MyClass -> path/to/MyClass.php
+ * @var string
+ */
+ private $classname;
+
+ /**
+ * Path to add to PHP include_path to aid in finding specified class.
+ * @var Path
+ */
+ private $classpath;
+
+ /**
+ * Refid to already defined classpath
+ */
+ private $classpathId;
+
+ /**
+ * Set the classpath to be used when searching for component being defined
+ *
+ * @param Path $classpath An Path object containing the classpath.
+ */
+ public function setClasspath(Path $classpath) {
+ if ($this->classpath === null) {
+ $this->classpath = $classpath;
+ } else {
+ $this->classpath->append($classpath);
+ }
+ }
+
+ /**
+ * Create the classpath to be used when searching for component being defined
+ */
+ public function createClasspath() {
+ if ($this->classpath === null) {
+ $this->classpath = new Path($this->project);
+ }
+ return $this->classpath->createPath();
+ }
+
+ /**
+ * Reference to a classpath to use when loading the files.
+ */
+ public function setClasspathRef(Reference $r) {
+ $this->classpathId = $r->getRefId();
+ $this->createClasspath()->setRefid($r);
+ }
+
+
+ /** Main entry point */
+ public function main() {
+
+ // Apparently casting to (string) no longer invokes __toString() automatically.
+ if (is_object($this->classpath)) {
+ $this->classpath = $this->classpath->__toString();
+ }
+
+ if (empty($this->classpath)) {
+ throw new BuildException("Provided classpath was empty.");
+ }
+
+ $curr_parts = explode(PATH_SEPARATOR, get_include_path());
+ $add_parts = explode(PATH_SEPARATOR, $this->classpath);
+ $new_parts = array_diff($add_parts, $curr_parts);
+
+ if ($new_parts) {
+ $this->log("Prepending new include_path components: " . implode(PATH_SEPARATOR, $new_parts), PROJECT_MSG_VERBOSE);
+ set_include_path(implode(PATH_SEPARATOR, array_merge($new_parts, $curr_parts)));
+ }
+
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/InputTask.php b/buildscripts/phing/classes/phing/tasks/system/InputTask.php
new file mode 100644
index 00000000..a5e1fdb9
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/InputTask.php
@@ -0,0 +1,146 @@
+<?php
+/*
+ * $Id: InputTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+include_once 'phing/input/InputRequest.php';
+include_once 'phing/input/YesNoInputRequest.php';
+include_once 'phing/input/MultipleChoiceInputRequest.php';
+
+/**
+ * Reads input from the InputHandler.
+ *
+ * @see Project::getInputHandler()
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Ulrich Schmidt <usch@usch.net> (Ant)
+ * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant)
+ * @version $Revision: 1.6 $
+ * @package phing.tasks.system
+ */
+class InputTask extends Task {
+
+ private $validargs;
+ private $message = ""; // required
+ private $propertyName; // required
+ private $defaultValue;
+ private $promptChar;
+
+ /**
+ * Defines valid input parameters as comma separated strings. If set, input
+ * task will reject any input not defined as accepted and requires the user
+ * to reenter it. Validargs are case sensitive. If you want 'a' and 'A' to
+ * be accepted you need to define both values as accepted arguments.
+ *
+ * @param validargs A comma separated String defining valid input args.
+ */
+ public function setValidargs ($validargs) {
+ $this->validargs = $validargs;
+ }
+
+ /**
+ * Defines the name of a property to be set from input.
+ *
+ * @param string $name Name for the property to be set from input
+ */
+ public function setPropertyName($name) {
+ $this->propertyName = $name;
+ }
+
+ /**
+ * Sets the Message which gets displayed to the user during the build run.
+ * @param message The message to be displayed.
+ */
+ public function setMessage ($message) {
+ $this->message = $message;
+ }
+
+ /**
+ * Set a multiline message.
+ */
+ public function addText($msg) {
+ $this->message .= $this->project->replaceProperties($msg);
+ }
+
+ /**
+ * Add a default value.
+ * @param string $v
+ */
+ public function setDefaultValue($v) {
+ $this->defaultValue = $v;
+ }
+
+ /**
+ * Set the character/string to use for the prompt.
+ * @param string $c
+ */
+ public function setPromptChar($c) {
+ $this->promptChar = $c;
+ }
+
+ /**
+ * Actual method executed by phing.
+ * @throws BuildException
+ */
+ public function main() {
+
+ if ($this->propertyName === null) {
+ throw new BuildException("You must specify a value for propertyName attribute.");
+ }
+
+ if ($this->validargs !== null) {
+ $accept = preg_split('/[\s,]+/', $this->validargs);
+
+ // is it a boolean (yes/no) inputrequest?
+ $yesno = false;
+ if (count($accept) == 2) {
+ $yesno = true;
+ foreach($accept as $ans) {
+ if(!StringHelper::isBoolean($ans)) {
+ $yesno = false;
+ break;
+ }
+ }
+ }
+ if ($yesno) $request = new YesNoInputRequest($this->message, $accept);
+ else $request = new MultipleChoiceInputRequest($this->message, $accept);
+ } else {
+ $request = new InputRequest($this->message);
+ }
+
+ // default default is curr prop value
+ $request->setDefaultValue($this->project->getProperty($this->propertyName));
+
+ $request->setPromptChar($this->promptChar);
+
+ // unless overridden...
+ if ($this->defaultValue !== null) {
+ $request->setDefaultValue($this->defaultValue);
+ }
+
+ $this->project->getInputHandler()->handleInput($request);
+
+ $value = $request->getInput();
+
+ if ($value !== null) {
+ $this->project->setUserProperty($this->propertyName, $value);
+ }
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/MatchingTask.php b/buildscripts/phing/classes/phing/tasks/system/MatchingTask.php
new file mode 100644
index 00000000..c5497fbd
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/MatchingTask.php
@@ -0,0 +1,361 @@
+<?php
+/*
+ * $Id: MatchingTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+require_once 'phing/types/selectors/SelectorContainer.php';
+include_once 'phing/types/FileSet.php';
+include_once 'phing/types/PatternSet.php';
+include_once 'phing/util/DirectoryScanner.php';
+
+/**
+ * This is an abstract task that should be used by all those tasks that
+ * require to include or exclude files based on pattern matching.
+ *
+ * This is very closely based on the ANT class of the same name.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Arnout J. Kuiper <ajkuiper@wxs.nl> (Ant)
+ * @author Stefano Mazzocchi <stefano@apache.org> (Ant)
+ * @author Sam Ruby <rubys@us.ibm.com> (Ant)
+ * @author Jon S. Stevens <jon@clearink.com> (Ant
+ * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant)
+ * @author Bruce Atherton <bruce@callenish.com> (Ant)
+ * @version $Revision: 1.4 $
+ * @package phing.tasks.system
+ */
+abstract class MatchingTask extends Task implements SelectorContainer {
+
+ /** @var boolean */
+ protected $useDefaultExcludes = true;
+
+ /** @var FileSet */
+ protected $fileset;
+
+ /**
+ * Create instance; set fileset to new FileSet.
+ */
+ public function __construct() {
+ $this->fileset = new FileSet();
+ }
+
+ /**
+ * @see ProjectComponent::setProject()
+ */
+ public function setProject(Project $project) {
+ parent::setProject($project);
+ $this->fileset->setProject($project);
+ }
+
+ /**
+ * add a name entry on the include list
+ * @return PatternSetNameEntry
+ */
+ public function createInclude() {
+ return $this->fileset->createInclude();
+ }
+
+ /**
+ * add a name entry on the include files list
+ * @return PatternSetNameEntry
+ */
+ public function createIncludesFile() {
+ return $this->fileset->createIncludesFile();
+ }
+
+ /**
+ * add a name entry on the exclude list
+ * @return PatternSetNameEntry
+ */
+ public function createExclude() {
+ return $this->fileset->createExclude();
+ }
+
+ /**
+ * add a name entry on the include files list
+ * @return PatternSetNameEntry
+ */
+ public function createExcludesFile() {
+ return $this->fileset->createExcludesFile();
+ }
+
+ /**
+ * add a set of patterns
+ * @return PatternSet
+ */
+ public function createPatternSet() {
+ return $this->fileset->createPatternSet();
+ }
+
+ /**
+ * Sets the set of include patterns. Patterns may be separated by a comma
+ * or a space.
+ *
+ * @param string $includes the string containing the include patterns
+ * @return void
+ */
+ public function setIncludes($includes) {
+ $this->fileset->setIncludes($includes);
+ }
+
+ /**
+ * Sets the set of exclude patterns. Patterns may be separated by a comma
+ * or a space.
+ *
+ * @param string $excludes the string containing the exclude patterns
+ */
+ public function setExcludes($excludes) {
+ $this->fileset->setExcludes($excludes);
+ }
+
+
+ /**
+ * Sets whether default exclusions should be used or not.
+ *
+ * @param boolean $useDefaultExcludes "true"|"on"|"yes" when default exclusions
+ * should be used, "false"|"off"|"no" when they
+ * shouldn't be used.
+ */
+ public function setDefaultexcludes($useDefaultExcludes) {
+ $this->useDefaultExcludes = (boolean) $useDefaultExcludes;
+ }
+
+ /**
+ * Returns the directory scanner needed to access the files to process.
+ * @return DirectoryScanner
+ */
+ protected function getDirectoryScanner(PhingFile $baseDir) {
+ $this->fileset->setDir($baseDir);
+ $this->fileset->setDefaultexcludes($this->useDefaultExcludes);
+ return $this->fileset->getDirectoryScanner($this->project);
+ }
+
+ /**
+ * Sets the name of the file containing the includes patterns.
+ *
+ * @param PhingFile $includesfile A string containing the filename to fetch
+ * the include patterns from.
+ * @return void
+ */
+ public function setIncludesfile(PhingFile $includesfile) {
+ $this->fileset->setIncludesfile(includesfile);
+ }
+
+ /**
+ * Sets the name of the file containing the includes patterns.
+ *
+ * @param PhingFile $excludesfile A string containing the filename to fetch
+ * the include patterns from.
+ * @return void
+ */
+ public function setExcludesfile(PhingFile $excludesfile) {
+ $this->fileset->setExcludesfile($excludesfile);
+ }
+
+ /**
+ * Sets case sensitivity of the file system
+ *
+ * @param boolean $isCaseSensitive "true"|"on"|"yes" if file system is case
+ * sensitive, "false"|"off"|"no" when not.
+ * @return void
+ */
+ public function setCaseSensitive($isCaseSensitive) {
+ $this->fileset->setCaseSensitive($isCaseSensitive);
+ }
+
+ /**
+ * Sets whether or not symbolic links should be followed.
+ *
+ * @param boolean $followSymlinks whether or not symbolic links should be followed
+ * @return void
+ */
+ public function setFollowSymlinks($followSymlinks) {
+ $this->fileset->setFollowSymlinks($followSymlinks);
+ }
+
+ /**
+ * Indicates whether there are any selectors here.
+ *
+ * @return boolean Whether any selectors are in this container
+ */
+ public function hasSelectors() {
+ return $this->fileset->hasSelectors();
+ }
+
+ /**
+ * Gives the count of the number of selectors in this container
+ *
+ * @return int The number of selectors in this container
+ */
+ public function selectorCount() {
+ return $this->fileset->selectorCount();
+ }
+
+ /**
+ * Returns the set of selectors as an array.
+ *
+ * @return array FileSelector[] An array of selectors in this container
+ */
+ public function getSelectors(Project $p) {
+ return $this->fileset->getSelectors($p);
+ }
+
+ /**
+ * Returns an enumerator for accessing the set of selectors.
+ *
+ * @return an enumerator that goes through each of the selectors
+ */
+ public function selectorElements() {
+ return $this->fileset->selectorElements();
+ }
+
+ /**
+ * Add a new selector into this container.
+ *
+ * @param FileSelector $selector the new selector to add
+ * @return void
+ */
+ public function appendSelector(FileSelector $selector) {
+ $this->fileset->appendSelector($selector);
+ }
+
+ /* Methods below all add specific selectors */
+
+ /**
+ * add a "Select" selector entry on the selector list
+ * @return SelectSelector
+ */
+ public function createSelector() {
+ return $this->fileset->createSelector();
+ }
+
+ /**
+ * add an "And" selector entry on the selector list
+ * @return AndSelector
+ */
+ public function createAnd() {
+ return $this->fileset->createAnd();
+ }
+
+ /**
+ * add an "Or" selector entry on the selector list
+ * @return void
+ */
+ public function createOr() {
+ return $this->fileset->createOr();
+ }
+
+ /**
+ * add a "Not" selector entry on the selector list
+ * @return NotSelector
+ */
+ public function createNot() {
+ return $this->fileset->createNot();
+ }
+
+ /**
+ * add a "None" selector entry on the selector list
+ * @return NoneSelector
+ */
+ public function createNone() {
+ return $this->fileset->createNone();
+ }
+
+ /**
+ * add a majority selector entry on the selector list
+ * @return MajoritySelector
+ */
+ public function createMajority() {
+ return $this->fileset->createMajority();
+ }
+
+ /**
+ * add a selector date entry on the selector list
+ * @return DateSelector
+ */
+ public function createDate() {
+ return $this->fileset->addDate();
+ }
+
+ /**
+ * add a selector size entry on the selector list
+ * @return SizeSelector
+ */
+ public function createSize() {
+ return $this->fileset->createSize();
+ }
+
+ /**
+ * add a selector filename entry on the selector list
+ * @return FilenameSelector
+ */
+ public function createFilename() {
+ return $this->fileset->createFilename();
+ }
+
+ /**
+ * add an extended selector entry on the selector list
+ * @return ExtendSelector
+ */
+ public function createCustom() {
+ return $this->fileset->createCustom();
+ }
+
+ /**
+ * add a contains selector entry on the selector list
+ * @return ContainsSelector
+ */
+ public function createContains() {
+ return $this->fileset->createContains();
+ }
+
+ /**
+ * add a present selector entry on the selector list
+ * @return PresentSelector
+ */
+ public function createPresent() {
+ return $this->fileset->createPresent();
+ }
+
+ /**
+ * add a depth selector entry on the selector list
+ * @return DepthSelector
+ */
+ public function createDepth() {
+ return $this->fileset->createDepth();
+ }
+
+ /**
+ * add a depends selector entry on the selector list
+ * @return DependSelector
+ */
+ public function createDepend() {
+ return $this->fileset->createDepend();
+ }
+
+ /**
+ * Accessor for the implict fileset.
+ *
+ * @return FileSet
+ */
+ protected final function getImplicitFileSet() {
+ return $this->fileset;
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/MkdirTask.php b/buildscripts/phing/classes/phing/tasks/system/MkdirTask.php
new file mode 100644
index 00000000..9d5c1f31
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/MkdirTask.php
@@ -0,0 +1,64 @@
+<?php
+/*
+ * $Id: MkdirTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+include_once 'phing/system/io/PhingFile.php';
+
+/**
+ * Task to create a directory.
+ *
+ * @author Andreas Aderhold, andi@binarycloud.com
+ * @version $Revision: 1.8 $
+ * @package phing.tasks.system
+ */
+class MkdirTask extends Task {
+
+ /** directory to create*/
+ private $dir;
+
+ /**
+ * create the directory and all parents
+ *
+ * @throws BuildException if dir is somehow invalid, or creation failed.
+ */
+ function main() {
+ if ($this->dir === null) {
+ throw new BuildException("dir attribute is required", $this->location);
+ }
+ if ($this->dir->isFile()) {
+ throw new BuildException("Unable to create directory as a file already exists with that name: " . $this->dir->getAbsolutePath());
+ }
+ if (!$this->dir->exists()) {
+ $result = $this->dir->mkdirs();
+ if (!$result) {
+ $msg = "Directory " . $this->dir->getAbsolutePath() . " creation was not successful for an unknown reason";
+ throw new BuildException($msg, $this->location);
+ }
+ $this->log("Created dir: " . $this->dir->getAbsolutePath());
+ }
+ }
+
+ /** the directory to create; required. */
+ function setDir(PhingFile $dir) {
+ $this->dir = $dir;
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/MoveTask.php b/buildscripts/phing/classes/phing/tasks/system/MoveTask.php
new file mode 100644
index 00000000..a3e94536
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/MoveTask.php
@@ -0,0 +1,197 @@
+<?php
+/*
+ * $Id: MoveTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/tasks/system/CopyTask.php';
+include_once 'phing/system/io/PhingFile.php';
+include_once 'phing/system/io/IOException.php';
+
+/**
+ * Moves a file or directory to a new file or directory.
+ *
+ * By default, the destination file is overwritten if it
+ * already exists. When overwrite is turned off, then files
+ * are only moved if the source file is newer than the
+ * destination file, or when the destination file does not
+ * exist.
+ *
+ * Source files and directories are only deleted when the file or
+ * directory has been copied to the destination successfully.
+ *
+ * @version $Revision: 1.8 $
+ * @package phing.tasks.system
+ */
+class MoveTask extends CopyTask {
+
+ function __construct() {
+ parent::__construct();
+ $this->forceOverwrite = true;
+ }
+
+ protected function doWork() {
+
+ $copyMapSize = count($this->fileCopyMap);
+ if ($copyMapSize > 0) {
+ // files to move
+ $this->log("Moving $copyMapSize files to " . $this->destDir->getAbsolutePath());
+
+ foreach($this->fileCopyMap as $from => $to) {
+ if ($from == $to) {
+ $this->log("Skipping self-move of $from", $this->verbosity);
+ continue;
+ }
+
+ $moved = false;
+ $f = new PhingFile($from);
+ $d = new PhingFile($to);
+
+ $moved = false;
+ try { // try to rename
+ $this->log("Attempting to rename $from to $to", $this->verbosity);
+ $this->renameFile($f, $d, $this->forceOverwrite);
+ $moved = true;
+ } catch (IOException $ioe) {
+ $moved = false;
+ $this->log("Failed to rename $from to $to: " . $ioe->getMessage(), $this->verbosity);
+ }
+
+ if (!$moved) {
+ try { // try to move
+ $this->log("Moving $from to $to", $this->verbosity);
+
+ $this->fileUtils->copyFile($f, $d, $this->forceOverwrite, $this->preserveLMT, $this->filterChains, $this->getProject());
+
+ $f = new PhingFile($fromFile);
+ $f->delete();
+ } catch (IOException $ioe) {
+ $msg = "Failed to move $from to $to: " . $ioe->getMessage();
+ throw new BuildException($msg, $this->location);
+ }
+ } // if !moved
+ } // foreach fileCopyMap
+ } // if copyMapSize
+
+ // handle empty dirs if appropriate
+ if ($this->includeEmpty) {
+ $e = array_keys($this->dirCopyMap);
+ $count = 0;
+ foreach ($e as $dir) {
+ $d = new PhingFile((string) $dir);
+ if (!$d->exists()) {
+ if (!$d->mkdirs()) {
+ $this->log("Unable to create directory " . $d->getAbsolutePath(), PROJECT_MSG_ERR);
+ } else {
+ $count++;
+ }
+ }
+ }
+ if ($count > 0) {
+ $this->log("moved $count empty director" . ($count == 1 ? "y" : "ies") . " to " . $this->destDir->getAbsolutePath());
+ }
+ }
+
+ if (count($this->filesets) > 0) {
+ // process filesets
+ foreach($this->filesets as $fs) {
+ $dir = $fs->getDir($this->project);
+ if ($this->okToDelete($dir)) {
+ $this->deleteDir($dir);
+ }
+ }
+ }
+ }
+
+ /** Its only ok to delete a dir tree if there are no files in it. */
+ private function okToDelete($d) {
+ $list = $d->listDir();
+ if ($list === null) {
+ return false; // maybe io error?
+ }
+
+ foreach($list as $s) {
+ $f = new PhingFile($d, $s);
+ if ($f->isDirectory()) {
+ if (!$this->okToDelete($f)) {
+ return false;
+ }
+ } else {
+ // found a file
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /** Go and delete the directory tree. */
+ private function deleteDir($d) {
+
+ $list = $d->listDir();
+ if ($list === null) {
+ return; // on an io error list() can return null
+ }
+
+ foreach($list as $fname) {
+ $f = new PhingFile($d, $fname);
+ if ($f->isDirectory()) {
+ $this->deleteDir($f);
+ } else {
+ throw new BuildException("UNEXPECTED ERROR - The file " . $f->getAbsolutePath() . " should not exist!");
+ }
+ }
+
+ $this->log("Deleting directory " . $d->getPath(), $this->verbosity);
+ try {
+ $d->delete();
+ } catch (Exception $e) {
+ throw new BuildException("Unable to delete directory " . $d->__toString() . ": " . $e->getMessage());
+ }
+ }
+
+ /**
+ * Attempts to rename a file from a source to a destination.
+ * If overwrite is set to true, this method overwrites existing file
+ * even if the destination file is newer.
+ * Otherwise, the source f
+ * ile is renamed only if the destination file #
+ * is older than it.
+ */
+ private function renameFile(PhingFile $sourceFile, PhingFile $destFile, $overwrite) {
+ $renamed = true;
+
+ // ensure that parent dir of dest file exists!
+ $parent = $destFile->getParentFile();
+ if ($parent !== null) {
+ if (!$parent->exists()) {
+ $parent->mkdirs();
+ }
+ }
+ if ($destFile->exists()) {
+ try {
+ $destFile->delete();
+ } catch (Exception $e) {
+ throw new BuildException("Unable to remove existing file " . $destFile->__toString() . ": " . $e->getMessage());
+ }
+ }
+ $renamed = $sourceFile->renameTo($destFile);
+
+ return $renamed;
+ }
+}
+?>
diff --git a/buildscripts/phing/classes/phing/tasks/system/PhingCallTask.php b/buildscripts/phing/classes/phing/tasks/system/PhingCallTask.php
new file mode 100644
index 00000000..34d4336d
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/PhingCallTask.php
@@ -0,0 +1,139 @@
+<?php
+/*
+ * $Id: PhingCallTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+
+/**
+ * Call another target in the same project.
+ *
+ * <pre>
+ * <target name="foo">
+ * <phingcall target="bar">
+ * <property name="property1" value="aaaaa" />
+ * <property name="foo" value="baz" />
+ * </phingcall>
+ * </target>
+ *
+ * <target name="bar" depends="init">
+ * <echo message="prop is ${property1} ${foo}" />
+ * </target>
+ * </pre>
+ *
+ * <p>This only works as expected if neither property1 nor foo are
+ * defined in the project itself.
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.9 $
+ * @access public
+ * @package phing.tasks.system
+ */
+class PhingCallTask extends Task {
+
+ private $callee;
+ private $subTarget;
+ // must match the default value of PhingTask#inheritAll
+ private $inheritAll = true;
+ // must match the default value of PhingTask#inheritRefs
+ private $inheritRefs = false;
+
+ /**
+ * If true, pass all properties to the new Phing project.
+ * Defaults to true. Future use.
+ * @param boolean new value
+ */
+ function setInheritAll($inherit) {
+ $this->inheritAll = (boolean) $inherit;
+ }
+
+ /**
+ * If true, pass all references to the new Phing project.
+ * Defaults to false. Future use.
+ *
+ * @param boolean new value
+ */
+ function setInheritRefs($inheritRefs) {
+ $this->inheritRefs = (boolean) $inheritRefs;
+ }
+
+ /**
+ * init this task by creating new instance of the phing task and
+ * configuring it's by calling its own init method.
+ */
+ function init() {
+ $this->callee = $this->project->createTask("phing");
+ $this->callee->setOwningTarget($this->getOwningTarget());
+ $this->callee->setTaskName($this->getTaskName());
+ $this->callee->setLocation($this->getLocation());
+ $this->callee->init();
+ }
+
+ /**
+ * hand off the work to the phing task of ours, after setting it up
+ * @throws BuildException on validation failure or if the target didn't
+ * execute
+ */
+ function main() {
+
+ $this->log("Running PhingCallTask for target '" . $this->subTarget . "'", PROJECT_MSG_DEBUG);
+ if ($this->callee === null) {
+ $this->init();
+ }
+
+ if ($this->subTarget === null) {
+ throw new BuildException("Attribute target is required.", $this->location);
+ }
+
+ $this->callee->setPhingfile($this->project->getProperty("phing.file"));
+ $this->callee->setTarget($this->subTarget);
+ $this->callee->setInheritAll($this->inheritAll);
+ $this->callee->setInheritRefs($this->inheritRefs);
+ $this->callee->main();
+ }
+
+ /**
+ * Alias for createProperty
+ * @see createProperty()
+ */
+ function createParam() {
+ if ($this->callee === null) {
+ $this->init();
+ }
+ return $this->callee->createProperty();
+ }
+
+ /**
+ * Property to pass to the invoked target.
+ */
+ function createProperty() {
+ if ($this->callee === null) {
+ $this->init();
+ }
+ return $this->callee->createProperty();
+ }
+
+ /**
+ * Target to execute, required.
+ */
+ function setTarget($target) {
+ $this->subTarget = (string) $target;
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/PhingTask.php b/buildscripts/phing/classes/phing/tasks/system/PhingTask.php
new file mode 100644
index 00000000..e9883dd7
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/PhingTask.php
@@ -0,0 +1,596 @@
+<?php
+
+/*
+ * $Id: PhingTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+include_once 'phing/Task.php';
+include_once 'phing/util/FileUtils.php';
+include_once 'phing/types/Reference.php';
+include_once 'phing/tasks/system/PropertyTask.php';
+
+/**
+ * Task that invokes phing on another build file.
+ *
+ * Use this task, for example, if you have nested buildfiles in your project. Unlike
+ * AntTask, PhingTask can even support filesets:
+ *
+ * <pre>
+ * <phing>
+ * <fileset dir="${srcdir}">
+ * <include name="** /build.xml" /> <!-- space added after ** is there because of PHP comment syntax -->
+ * <exclude name="build.xml" />
+ * </fileset>
+ * </phing>
+ * </pre>
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.20 $
+ * @package phing.tasks.system
+ */
+class PhingTask extends Task {
+
+ /** the basedir where is executed the build file */
+ private $dir;
+
+ /** build.xml (can be absolute) in this case dir will be ignored */
+ private $phingFile;
+
+ /** the target to call if any */
+ protected $newTarget;
+
+ /** should we inherit properties from the parent ? */
+ private $inheritAll = true;
+
+ /** should we inherit references from the parent ? */
+ private $inheritRefs = false;
+
+ /** the properties to pass to the new project */
+ private $properties = array();
+
+ /** the references to pass to the new project */
+ private $references = array();
+
+ /** The filesets that contain the files PhingTask is to be run on. */
+ private $filesets = array();
+
+ /** the temporary project created to run the build file */
+ private $newProject;
+
+ /** Fail the build process when the called build fails? */
+ private $haltOnFailure = false;
+
+ /**
+ * If true, abort the build process if there is a problem with or in the target build file.
+ * Defaults to false.
+ *
+ * @param boolean new value
+ */
+ public function setHaltOnFailure($hof) {
+ $this->haltOnFailure = (boolean) $hof;
+ }
+
+ /**
+ * Creates a Project instance for the project to call.
+ * @return void
+ */
+ public function init() {
+ $this->newProject = new Project();
+ $tdf = $this->project->getTaskDefinitions();
+ $this->newProject->addTaskDefinition("property", $tdf["property"]);
+ }
+
+ /**
+ * Called in execute or createProperty if newProject is null.
+ *
+ * <p>This can happen if the same instance of this task is run
+ * twice as newProject is set to null at the end of execute (to
+ * save memory and help the GC).</p>
+ *
+ * <p>Sets all properties that have been defined as nested
+ * property elements.</p>
+ */
+ private function reinit() {
+ $this->init();
+ $count = count($this->properties);
+ for ($i = 0; $i < $count; $i++) {
+ $p = $this->properties[$i];
+ $newP = $this->newProject->createTask("property");
+ $newP->setName($p->getName());
+ if ($p->getValue() !== null) {
+ $newP->setValue($p->getValue());
+ }
+ if ($p->getFile() !== null) {
+ $newP->setFile($p->getFile());
+ }
+ if ($p->getPrefix() !== null) {
+ $newP->setPrefix($p->getPrefix());
+ }
+ if ($p->getRefid() !== null) {
+ $newP->setRefid($p->getRefid());
+ }
+ if ($p->getEnvironment() !== null) {
+ $newP->setEnvironment($p->getEnvironment());
+ }
+ if ($p->getUserProperty() !== null) {
+ $newP->setUserProperty($p->getUserProperty());
+ }
+ if ($p->getOverride() !== null) {
+ $newP->setOverride($p->getOverride());
+ }
+ $this->properties[$i] = $newP;
+ }
+ }
+
+ /**
+ * Main entry point for the task.
+ *
+ * @return void
+ */
+ public function main() {
+
+ // Call Phing on the file set with the attribute "phingfile"
+ if ($this->phingFile !== null or $this->dir !== null) {
+ $this->processFile();
+ }
+
+ // if no filesets are given stop here; else process filesets
+ if (empty($this->filesets)) {
+ return;
+ }
+
+ // preserve old settings
+ $savedDir = $this->dir;
+ $savedPhingFile = $this->phingFile;
+ $savedTarget = $this->newTarget;
+ $buildFailed = false;
+
+ // set no specific target for files in filesets
+ // [HL] I'm commenting this out; I don't know why this should not be supported!
+ // $this->newTarget = null;
+
+ foreach($this->filesets as $fs) {
+
+ $ds = $fs->getDirectoryScanner($this->project);
+
+ $fromDir = $fs->getDir($this->project);
+ $srcFiles = $ds->getIncludedFiles();
+
+ foreach($srcFiles as $fname) {
+ $f = new PhingFile($ds->getbasedir(), $fname);
+ $f = $f->getAbsoluteFile();
+ $this->phingFile = $f->getAbsolutePath();
+ $this->dir = $f->getParentFile();
+ $this->processFile(); // run Phing!
+ }
+ }
+
+ // side effect free programming ;-)
+ $this->dir = $savedDir;
+ $this->phingFile = $savedPhingFile;
+ $this->newTarget = $savedTarget;
+
+ // [HL] change back to correct dir
+ if ($this->dir !== null) {
+ chdir($this->dir->getAbsolutePath());
+ }
+
+ }
+
+ /**
+ * Execute phing file.
+ *
+ * @return void
+ */
+ private function processFile() {
+
+ $savedDir = $this->dir;
+ $savedPhingFile = $this->phingFile;
+ $savedTarget = $this->newTarget;
+
+ try {
+ if ($this->newProject === null) {
+ $this->reinit();
+ }
+
+ if (($this->dir === null) && ($this->inheritAll)) {
+ $this->dir = $this->getProject()->getBaseDir();
+ }
+ $this->initializeProject();
+ if ($this->dir !== null) {
+ $this->newProject->setBaseDir($this->dir);
+ if ($savedDir !== null) { // has been set explicitly
+ $this->newProject->setInheritedProperty("project.basedir", $this->dir->getAbsolutePath());
+ }
+ } else {
+ $this->dir = $this->getProject()->getBaseDir();
+ }
+
+ $this->overrideProperties();
+ if ($this->phingFile === null) {
+ $this->phingFile = "build.xml";
+ }
+
+ $fu = new FileUtils();
+ $file = $fu->resolveFile($this->dir, $this->phingFile);
+ $this->phingFile = $file->getAbsolutePath();
+
+ $this->log("Calling Buildfile '" . $this->phingFile . "' with target '" . $this->newTarget . "'");
+
+ $this->newProject->setUserProperty("phing.file", $this->phingFile);
+
+ ProjectConfigurator::configureProject($this->newProject, new PhingFile($this->phingFile));
+
+ if ($this->newTarget === null) {
+ $this->newTarget = $this->newProject->getDefaultTarget();
+ }
+
+ // Are we trying to call the target in which we are defined?
+ if ($this->newProject->getBaseDir() == $this->project->getBaseDir() &&
+ $this->newProject->getProperty("phing.file") == $this->project->getProperty("phing.file") &&
+ $this->getOwningTarget() !== null &&
+ $this->newTarget == $this->getOwningTarget()->getName()) {
+
+ throw new BuildException("phing task calling its own parent target");
+ }
+
+ $this->addReferences();
+ $this->newProject->executeTarget($this->newTarget);
+
+ } catch (Exception $e) {
+ $buildFailed = true;
+ $this->log($e->getMessage(), PROJECT_MSG_ERR);
+
+ // important!!! continue on to perform cleanup
+ // tasks.
+ }
+
+ // } finally {
+ // restore values (prevent side-effects)
+ // !this must match code in catch () {} block!
+ $this->newProject = null;
+ $pkeys = array_keys($this->properties);
+ foreach($pkeys as $k) {
+ $this->properties[$k]->setProject(null);
+ }
+ $this->dir = $savedDir;
+ $this->phingFile = $savedPhingFile;
+ $this->newTarget = $savedTarget;
+
+ // [HL] change back to correct dir
+ if ($this->dir !== null) {
+ chdir($this->dir->getAbsolutePath());
+ }
+
+ if ($this->haltOnFailure == true && $buildFailed == true)
+ throw new BuildException("Execution of the target buildfile failed. Aborting.");
+ }
+
+ /**
+ * Configure the Project, i.e. make intance, attach build listeners
+ * (copy from father project), add Task and Datatype definitions,
+ * copy properties and references from old project if these options
+ * are set via the attributes of the XML tag.
+ *
+ * Developer note:
+ * This function replaces the old methods "init", "_reinit" and
+ * "_initializeProject".
+ *
+ * @access protected
+ */
+ private function initializeProject() {
+
+ $this->newProject->setInputHandler($this->project->getInputHandler());
+
+ foreach($this->project->getBuildListeners() as $listener) {
+ $this->newProject->addBuildListener($listener);
+ }
+
+ /* Copy things from old project. Datatypes and Tasks are always
+ * copied, properties and references only if specified so/not
+ * specified otherwise in the XML definition.
+ */
+ // Add Datatype definitions
+ foreach ($this->project->getDataTypeDefinitions() as $typeName => $typeClass) {
+ $this->newProject->addDataTypeDefinition($typeName, $typeClass);
+ }
+
+ // Add Task definitions
+ foreach ($this->project->getTaskDefinitions() as $taskName => $taskClass) {
+ if ($taskClass == "propertytask") {
+ // we have already added this taskdef in init()
+ continue;
+ }
+ $this->newProject->addTaskDefinition($taskName, $taskClass);
+ }
+
+ // set user-defined properties
+ $this->project->copyUserProperties($this->newProject);
+
+ if (!$this->inheritAll) {
+ // set System built-in properties separately,
+ // b/c we won't inherit them.
+ $this->newProject->setSystemProperties();
+
+ } else {
+ // set all properties from calling project
+ $properties = $this->project->getProperties();
+ foreach ($properties as $name => $value) {
+ if ($name == "basedir" || $name == "phing.file" || $name == "phing.version") {
+ // basedir and phing.file get special treatment in main()
+ continue;
+ }
+ // don't re-set user properties, avoid the warning message
+ if ($this->newProject->getProperty($name) === null){
+ // no user property
+ $this->newProject->setNewProperty($name, $value);
+ }
+ }
+
+ }
+
+ }
+
+ /**
+ * Override the properties in the new project with the one
+ * explicitly defined as nested elements here.
+ * @return void
+ * @throws BuildException
+ */
+ private function overrideProperties() {
+ foreach(array_keys($this->properties) as $i) {
+ $p = $this->properties[$i];
+ $p->setProject($this->newProject);
+ $p->main();
+ }
+ $this->project->copyInheritedProperties($this->newProject);
+ }
+
+ /**
+ * Add the references explicitly defined as nested elements to the
+ * new project. Also copy over all references that don't override
+ * existing references in the new project if inheritrefs has been
+ * requested.
+ *
+ * @return void
+ * @throws BuildException
+ */
+ private function addReferences() {
+
+ // parent project references
+ $projReferences = $this->project->getReferences();
+
+ $newReferences = $this->newProject->getReferences();
+
+ $subprojRefKeys = array();
+
+ if (count($this->references) > 0) {
+ for ($i=0, $count=count($this->references); $i < $count; $i++) {
+ $ref = $this->references[$i];
+ $refid = $ref->getRefId();
+
+ if ($refid === null) {
+ throw new BuildException("the refid attribute is required"
+ . " for reference elements");
+ }
+ if (!isset($projReferences[$refid])) {
+ $this->log("Parent project doesn't contain any reference '"
+ . $refid . "'",
+ PROJECT_MSG_WARN);
+ continue;
+ }
+
+ $subprojRefKeys[] = $refid;
+ //thisReferences.remove(refid);
+ $toRefid = $ref->getToRefid();
+ if ($toRefid === null) {
+ $toRefid = $refid;
+ }
+ $this->copyReference($refid, $toRefid);
+ }
+ }
+
+ // Now add all references that are not defined in the
+ // subproject, if inheritRefs is true
+ if ($this->inheritRefs) {
+
+ // get the keys that are were not used by the subproject
+ $unusedRefKeys = array_diff(array_keys($projReferences), $subprojRefKeys);
+
+ foreach($unusedRefKeys as $key) {
+ if (isset($newReferences[$key])) {
+ continue;
+ }
+ $this->copyReference($key, $key);
+ }
+ }
+ }
+
+ /**
+ * Try to clone and reconfigure the object referenced by oldkey in
+ * the parent project and add it to the new project with the key
+ * newkey.
+ *
+ * <p>If we cannot clone it, copy the referenced object itself and
+ * keep our fingers crossed.</p>
+ *
+ * @param string $oldKey
+ * @param string $newKey
+ * @return void
+ */
+ private function copyReference($oldKey, $newKey) {
+ $orig = $this->project->getReference($oldKey);
+ if ($orig === null) {
+ $this->log("No object referenced by " . $oldKey . ". Can't copy to "
+ .$newKey,
+ PROJECT_SG_WARN);
+ return;
+ }
+
+ $copy = clone $orig;
+
+ if ($copy instanceof ProjectComponent) {
+ $copy->setProject($this->newProject);
+ } elseif (in_array('setProject', get_class_methods(get_class($copy)))) {
+ $copy->setProject($this->newProject);
+ } elseif ($copy instanceof Project) {
+ // don't copy the old "Project" itself
+ } else {
+ $msg = "Error setting new project instance for "
+ . "reference with id " . $oldKey;
+ throw new BuildException($msg);
+ }
+
+ $this->newProject->addReference($newKey, $copy);
+ }
+
+ /**
+ * If true, pass all properties to the new phing project.
+ * Defaults to true.
+ *
+ * @access public
+ */
+ function setInheritAll($value) {
+ $this->inheritAll = (boolean) $value;
+ }
+
+ /**
+ * If true, pass all references to the new phing project.
+ * Defaults to false.
+ *
+ * @access public
+ */
+ function setInheritRefs($value) {
+ $this->inheritRefs = (boolean)$value;
+ }
+
+ /**
+ * The directory to use as a base directory for the new phing project.
+ * Defaults to the current project's basedir, unless inheritall
+ * has been set to false, in which case it doesn't have a default
+ * value. This will override the basedir setting of the called project.
+ *
+ * @access public
+ */
+ function setDir($d) {
+ if ( is_string($d) )
+ $this->dir = new PhingFile($d);
+ else
+ $this->dir = $d;
+ }
+
+ /**
+ * The build file to use.
+ * Defaults to "build.xml". This file is expected to be a filename relative
+ * to the dir attribute given.
+ *
+ * @access public
+ */
+ function setPhingfile($s) {
+ // it is a string and not a file to handle relative/absolute
+ // otherwise a relative file will be resolved based on the current
+ // basedir.
+ $this->phingFile = $s;
+ }
+
+ /**
+ * Alias function for setPhingfile
+ *
+ * @access public
+ */
+ function setBuildfile($s) {
+ $this->setPhingFile($s);
+ }
+
+ /**
+ * The target of the new Phing project to execute.
+ * Defaults to the new project's default target.
+ *
+ * @access public
+ */
+ function setTarget($s) {
+ $this->newTarget = $s;
+ }
+
+ /**
+ * Support for filesets; This method returns a reference to an instance
+ * of a FileSet object.
+ *
+ * @return FileSet
+ */
+ function createFileSet() {
+ $num = array_push($this->filesets, new FileSet());
+ return $this->filesets[$num-1];
+ }
+
+ /**
+ * Property to pass to the new project.
+ * The property is passed as a 'user property'
+ *
+ * @access public
+ */
+ function createProperty() {
+ $p = new PropertyTask();
+ $p->setFallback($this->newProject);
+ $p->setUserProperty(true);
+ $this->properties[] = $p;
+ return $p;
+ }
+
+ /**
+ * Reference element identifying a data type to carry
+ * over to the new project.
+ *
+ * @access public
+ */
+ function createReference() {
+ $num = array_push($this->references, new PhingReference());
+ return $this->references[$num-1];
+ }
+
+}
+
+/**
+ * Helper class that implements the nested <reference>
+ * element of <phing> and <phingcall>.
+ */
+class PhingReference extends Reference {
+
+ private $targetid = null;
+
+ /**
+ * Set the id that this reference to be stored under in the
+ * new project.
+ *
+ * @param targetid the id under which this reference will be passed to
+ * the new project */
+ public function setToRefid($targetid) {
+ $this->targetid = $targetid;
+ }
+
+ /**
+ * Get the id under which this reference will be stored in the new
+ * project
+ *
+ * @return the id of the reference in the new project.
+ */
+ public function getToRefid() {
+ return $this->targetid;
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/PhpEvalTask.php b/buildscripts/phing/classes/phing/tasks/system/PhpEvalTask.php
new file mode 100644
index 00000000..f1b72815
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/PhpEvalTask.php
@@ -0,0 +1,169 @@
+<?php
+/*
+ * $Id: PhpEvalTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+
+/**
+ * Executes PHP function or evaluates expression and sets return value to a property.
+ *
+ * WARNING:
+ * This task can, of course, be abused with devastating effects. E.g. do not
+ * modify internal Phing classes unless you know what you are doing.
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.7 $
+ * @package phing.tasks.system
+ *
+ * @todo Add support for evaluating expressions
+ */
+class PhpEvalTask extends Task {
+
+ protected $expression; // Expression to evaluate
+ protected $function; // Function to execute
+ protected $class; // Class containing function to execute
+ protected $returnProperty; // name of property to set to return value
+ protected $params = array(); // parameters for function calls
+
+ /** Main entry point. */
+ function main() {
+
+ if ($this->function === null && $this->expression === null) {
+ throw new BuildException("You must specify a function to execute or PHP expression to evalute.", $this->location);
+ }
+
+ if ($this->function !== null && $this->expression !== null) {
+ throw new BuildException("You can specify function or expression, but not both.", $this->location);
+ }
+
+ if ($this->expression !== null && !empty($this->params)) {
+ throw new BuildException("You cannot use nested <param> tags when evaluationg a PHP expression.", $this->location);
+ }
+
+ $retval = null;
+ if ($this->function !== null) {
+ $retval = $this->callFunction();
+ } elseif ($this->expression !== null) {
+ $retval = $this->evalExpression();
+ }
+
+ if ($this->returnProperty !== null) {
+ $this->project->setProperty($this->returnProperty, $retval);
+ }
+ }
+
+ /**
+ * Calls function and returns results.
+ * @return mixed
+ */
+ protected function callFunction() {
+
+ if ($this->class !== null) {
+ // import the classname & unqualify it, if necessary
+ $this->class = Phing::import($this->class);
+
+ $user_func = array($this->class, $this->function);
+ $h_func = $this->class . '::' . $this->function; // human-readable (for log)
+ } else {
+ $user_func = $this->function;
+ $h_func = $user_func; // human-readable (for log)
+ }
+
+ // put parameters into simple array
+ $params = array();
+ foreach($this->params as $p) {
+ $params[] = $p->getValue();
+ }
+
+ $this->log("Calling PHP function: " . $h_func . "()");
+ foreach($params as $p) {
+ $this->log(" param: " . $p, PROJECT_MSG_VERBOSE);
+ }
+
+ $return = call_user_func_array($user_func, $params);
+ return $return;
+ }
+
+ /**
+ * Evaluates expression and returns resulting value.
+ * @return mixed
+ */
+ protected function evalExpression() {
+ $this->log("Evaluating PHP expression: " . $this->expression);
+ if (!StringHelper::endsWith(';', trim($this->expression))) {
+ $this->expression .= ';';
+ }
+ $retval = null;
+ eval('$retval = ' . $this->expression);
+ return $retval;
+ }
+
+ /** Set function to execute */
+ public function setFunction($f) {
+ $this->function = $f;
+ }
+
+ /** Set [static] class which contains function to execute */
+ public function setClass($c) {
+ $this->class = $c;
+ }
+
+ /** Sets property name to set with return value of function or expression.*/
+ public function setReturnProperty($r) {
+ $this->returnProperty = $r;
+ }
+
+ /** Set PHP expression to evaluate. */
+ public function addText($expression) {
+ $this->expression = $expression;
+ }
+
+ /** Set PHP expression to evaluate. */
+ public function setExpression($expression) {
+ $this->expression = $expression;
+ }
+
+ /** Add a nested <param> tag. */
+ public function createParam() {
+ $p = new FunctionParam();
+ $this->params[] = $p;
+ return $p;
+ }
+}
+
+/**
+ * Supports the <param> nested tag for PhpTask.
+ */
+class FunctionParam {
+
+ private $val;
+
+ public function setValue($v) {
+ $this->val = $v;
+ }
+
+ public function addText($v) {
+ $this->val = $v;
+ }
+
+ public function getValue() {
+ return $this->val;
+ }
+} \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/system/PropertyPromptTask.php b/buildscripts/phing/classes/phing/tasks/system/PropertyPromptTask.php
new file mode 100644
index 00000000..e7e12f33
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/PropertyPromptTask.php
@@ -0,0 +1,201 @@
+<?php
+/*
+ * $Id: PropertyPromptTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+include_once 'phing/system/io/ConsoleReader.php';
+
+/**
+ * Deprecated task that uses console to prompt user for property values.
+ *
+ * This class is very slightly simpler than the InputTask, but lacks the ability
+ * to use a non-console input handler. You should, therefore, use InputTask. This
+ * class can serve as a reference, but will be removed in the future.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Anthony J. Young-Garner <ajyoung@alum.mit.edu> (Ant)
+ * @version $Revision: 1.4 $
+ * @package phing.tasks.system
+ * @deprecated - in favor of the more capable InputTask
+ */
+class PropertyPromptTask extends Task {
+
+ private $propertyName; // required
+ private $defaultValue;
+ private $proposedValue; // required
+ private $promptText; // required
+ private $promptCharacter;
+ private $useExistingValue;
+
+ /**
+ * Sets the prompt text that will be presented to the user.
+ * @param string $prompt
+ * @return void
+ */
+ public function addText($prompt) {
+ $this->setPromptText($prompt);
+ }
+
+ /**
+ * Run the PropertyPrompt task.
+ * @throws BuildException
+ */
+ public function main() {
+ $this->proposedValue = $this->project->getProperty($this->propertyName);
+ $currentValue = $this->defaultValue;
+ if ($currentValue == "" && $this->proposedValue !== null) { $currentValue = $this->proposedValue; }
+ if (! (($this->useExistingValue === true) && ($this->proposedValue !== null))) {
+
+ $this->log("Prompting user for " . $this->propertyName . ". " . $this->getDefaultMessage(), PROJECT_MSG_VERBOSE);
+
+ print "\n" . $this->promptText . " [" . $currentValue . "] " . $this->promptCharacter . " ";
+
+ /** future version should probably have hooks for validation of user input.*/
+ $reader = new ConsoleReader();
+
+ try {
+ $this->proposedValue = $reader->readLine();
+ } catch (IOException $e) {
+ $this->log("Prompt failed. Using default. (Failure reason: " . $e->getMessage().")");
+ $this->proposedValue = $this->defaultValue;
+ }
+
+ if (empty($this->proposedValue)) {
+ $this->log("No value specified, using default.", PROJECT_MSG_VERBOSE);
+ $this->proposedValue = $this->defaultValue;
+ }
+
+ if (!empty($this->proposedValue)) {
+ $this->project->setProperty($this->propertyName, $this->proposedValue);
+ }
+
+ }
+ }
+
+ /**
+ * Returns a string to be inserted in the log message
+ * indicating whether a default response was specified
+ * in the build file.
+ */
+ private function getDefaultMessage() {
+ if ($this->defaultValue == "") {
+ return "No default response specified.";
+ } else return "Default response is " . $this->defaultValue . ".";
+ }
+
+ /**
+ * Returns defaultValue specified
+ * in this task for the Property
+ * being set.
+ * @return string
+ */
+ public function getDefaultValue() {
+ return $this->defaultValue;
+ }
+
+ /**
+ * Returns the terminating character used to
+ * punctuate the prompt text.
+ * @return string
+ */
+ public function getPromptCharacter() {
+ return $this->promptCharacter;
+ }
+
+ /**
+ * Returns text of the prompt.
+ * @return java.lang.String
+ */
+ public function getPromptText() {
+ return $this->promptText;
+ }
+
+ /**
+ * Returns name of the Ant Project Property
+ * being set by this task.
+ * @return string
+ */
+ public function getPropertyName() {
+ return $this->propertyName;
+ }
+ /**
+ * Initializes this task.
+ */
+ public function init() {
+ parent::init();
+ $this->defaultValue = "";
+ $this->promptCharacter = "?";
+ $this->useExistingValue = false;
+ }
+
+ /**
+ * Insert the method's description here.
+ * Creation date: (12/10/2001 8:16:16 AM)
+ * @return boolean
+ */
+ public function isUseExistingValue() {
+ return $this->useExistingValue;
+ }
+
+ /**
+ * Sets defaultValue for the Property
+ * being set by this task.
+ * @param string $newDefaultvalue
+ */
+ public function setDefaultvalue($newDefaultvalue) {
+ $this->defaultValue = $newDefaultvalue;
+ }
+
+ /**
+ * Sets the terminating character used to
+ * punctuate the prompt text (default is "?").
+ * @param newPromptcharacter java.lang.String
+ */
+ public function setPromptCharacter($newPromptcharacter) {
+ $this->promptCharacter = $newPromptcharacter;
+ }
+
+ /**
+ * Sets text of the prompt.
+ * @param newPrompttext java.lang.String
+ */
+ public function setPromptText($newPrompttext) {
+ $this->promptText = $newPrompttext;
+ }
+
+ /**
+ * Specifies the Phing Project Property
+ * being set by this task.
+ * @param newPropertyname java.lang.String
+ */
+ public function setPropertyName($newPropertyname) {
+ $this->propertyName = $newPropertyname;
+ }
+
+ /**
+ *
+ *
+ * @param boolean newUseExistingValue
+ */
+ public function setUseExistingValue($newUseExistingValue) {
+ $this->useExistingValue = $newUseExistingValue;
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/PropertyTask.php b/buildscripts/phing/classes/phing/tasks/system/PropertyTask.php
new file mode 100644
index 00000000..d6168e44
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/PropertyTask.php
@@ -0,0 +1,438 @@
+<?php
+
+/*
+ * $Id: PropertyTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/Task.php';
+include_once 'phing/system/util/Properties.php';
+
+/**
+ * Task for setting properties in buildfiles.
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision$
+ * @package phing.tasks.system
+ */
+class PropertyTask extends Task {
+
+ /** name of the property */
+ protected $name;
+
+ /** value of the property */
+ protected $value;
+
+ protected $reference;
+ protected $env; // Environment
+ protected $file;
+ protected $ref;
+ protected $prefix;
+ protected $fallback;
+
+ /** Whether to force overwrite of existing property. */
+ protected $override = false;
+
+ /** Whether property should be treated as "user" property. */
+ protected $userProperty = false;
+
+ /**
+ * Sets a the name of current property component
+ */
+ function setName($name) {
+ $this->name = (string) $name;
+ }
+
+ /** Get property component name. */
+ function getName() {
+ return $this->name;
+ }
+
+ /**
+ * Sets a the value of current property component.
+ * @param mixed Value of name, all scalars allowed
+ */
+ function setValue($value) {
+ $this->value = (string) $value;
+ }
+
+ /**
+ * Sets value of property to CDATA tag contents.
+ * @param string $values
+ * @since 2.2.0
+ */
+ public function addText($value) {
+ $this->setValue($value);
+ }
+
+ /** Get the value of current property component. */
+ function getValue() {
+ return $this->value;
+ }
+
+ /** Set a file to use as the source for properties. */
+ function setFile($file) {
+ if (is_string($file)) {
+ $file = new PhingFile($file);
+ }
+ $this->file = $file;
+ }
+
+ /** Get the PhingFile that is being used as property source. */
+ function getFile() {
+ return $this->file;
+ }
+
+ function setRefid(Reference $ref) {
+ $this->reference = $ref;
+ }
+
+ function getRefid() {
+ return $this->reference;
+ }
+
+ /**
+ * Prefix to apply to properties loaded using <code>file</code>.
+ * A "." is appended to the prefix if not specified.
+ * @param string $prefix prefix string
+ * @return void
+ * @since 2.0
+ */
+ public function setPrefix($prefix) {
+ $this->prefix = $prefix;
+ if (!StringHelper::endsWith(".", $prefix)) {
+ $this->prefix .= ".";
+ }
+ }
+
+ /**
+ * @return string
+ * @since 2.0
+ */
+ public function getPrefix() {
+ return $this->prefix;
+ }
+
+ /**
+ * the prefix to use when retrieving environment variables.
+ * Thus if you specify environment="myenv"
+ * you will be able to access OS-specific
+ * environment variables via property names "myenv.PATH" or
+ * "myenv.TERM".
+ * <p>
+ * Note that if you supply a property name with a final
+ * "." it will not be doubled. ie environment="myenv." will still
+ * allow access of environment variables through "myenv.PATH" and
+ * "myenv.TERM". This functionality is currently only implemented
+ * on select platforms. Feel free to send patches to increase the number of platforms
+ * this functionality is supported on ;).<br>
+ * Note also that properties are case sensitive, even if the
+ * environment variables on your operating system are not, e.g. it
+ * will be ${env.Path} not ${env.PATH} on Windows 2000.
+ * @param env prefix
+ */
+ function setEnvironment($env) {
+ $this->env = (string) $env;
+ }
+
+ function getEnvironment() {
+ return $this->env;
+ }
+
+ /**
+ * Set whether this is a user property (ro).
+ * This is deprecated in Ant 1.5, but the userProperty attribute
+ * of the class is still being set via constructor, so Phing will
+ * allow this method to function.
+ * @param boolean $v
+ */
+ function setUserProperty($v) {
+ $this->userProperty = (boolean) $v;
+ }
+
+ function getUserProperty() {
+ return $this->userProperty;
+ }
+
+ function setOverride($v) {
+ $this->override = (boolean) $v;
+ }
+
+ function getOverride() {
+ return $this->override;
+ }
+
+ function toString() {
+ return (string) $this->value;
+ }
+
+ /**
+ * @param Project $p
+ */
+ function setFallback($p) {
+ $this->fallback = $p;
+ }
+
+ function getFallback() {
+ return $this->fallback;
+ }
+ /**
+ * set the property in the project to the value.
+ * if the task was give a file or env attribute
+ * here is where it is loaded
+ */
+ function main() {
+ if ($this->name !== null) {
+ if ($this->value === null && $this->ref === null) {
+ throw new BuildException("You must specify value or refid with the name attribute", $this->getLocation());
+ }
+ } else {
+ if ($this->file === null && $this->env === null ) {
+ throw new BuildException("You must specify file or environment when not using the name attribute", $this->getLocation());
+ }
+ }
+
+ if ($this->file === null && $this->prefix !== null) {
+ throw new BuildException("Prefix is only valid when loading from a file.", $this->getLocation());
+ }
+
+ if (($this->name !== null) && ($this->value !== null)) {
+ $this->addProperty($this->name, $this->value);
+ }
+
+ if ($this->file !== null) {
+ $this->loadFile($this->file);
+ }
+
+ if ( $this->env !== null ) {
+ $this->loadEnvironment($this->env);
+ }
+
+ if (($this->name !== null) && ($this->ref !== null)) {
+ // get the refereced property
+ try {
+ $this->addProperty($this->name, $this->reference->getReferencedObject($this->project)->toString());
+ } catch (BuildException $be) {
+ if ($this->fallback !== null) {
+ $this->addProperty($this->name, $this->reference->getReferencedObject($this->fallback)->toString());
+ } else {
+ throw $be;
+ }
+ }
+ }
+ }
+
+ /**
+ * load the environment values
+ * @param string $prefix prefix to place before them
+ */
+ protected function loadEnvironment($prefix) {
+
+ $props = new Properties();
+ if ( substr($prefix, strlen($prefix)-1) == '.' ) {
+ $prefix .= ".";
+ }
+ $this->log("Loading Environment $prefix", PROJECT_MSG_VERBOSE);
+ foreach($_ENV as $key => $value) {
+ $props->setProperty($prefix . '.' . $key, $value);
+ }
+ $this->addProperties($props);
+ }
+
+ /**
+ * iterate through a set of properties,
+ * resolve them then assign them
+ */
+ protected function addProperties($props) {
+ $this->resolveAllProperties($props);
+ foreach($props->keys() as $name) {
+ $value = $props->getProperty($name);
+ $v = $this->project->replaceProperties($value);
+ if ($this->prefix !== null) {
+ $name = $this->prefix . $name;
+ }
+ $this->addProperty($name, $v);
+ }
+ }
+
+ /**
+ * add a name value pair to the project property set
+ * @param string $name name of property
+ * @param string $value value to set
+ */
+ protected function addProperty($name, $value) {
+ if ($this->userProperty) {
+ if ($this->project->getUserProperty($name) === null || $this->override) {
+ $this->project->setInheritedProperty($name, $value);
+ } else {
+ $this->log("Override ignored for " . $name, PROJECT_MSG_VERBOSE);
+ }
+ } else {
+ if ($this->override) {
+ $this->project->setProperty($name, $value);
+ } else {
+ $this->project->setNewProperty($name, $value);
+ }
+ }
+ }
+
+ /**
+ * load properties from a file.
+ * @param PhingFile $file
+ */
+ protected function loadFile(PhingFile $file) {
+ $props = new Properties();
+ $this->log("Loading ". $file->getAbsolutePath(), PROJECT_MSG_INFO);
+ try { // try to load file
+ if ($file->exists()) {
+ $props->load($file);
+ $this->addProperties($props);
+ } else {
+ $this->log("Unable to find property file: ". $file->getAbsolutePath() ."... skipped", PROJECT_MSG_WARN);
+ }
+ } catch (IOException $ioe) {
+ throw new BuildException("Could not load properties from file.", $ioe);
+ }
+ }
+
+ /**
+ * Given a Properties object, this method goes through and resolves
+ * any references to properties within the object.
+ *
+ * @param Properties $props The collection of Properties that need to be resolved.
+ * @return void
+ */
+ protected function resolveAllProperties(Properties $props) {
+
+ $keys = $props->keys();
+
+ while(count($keys)) {
+
+ // There may be a nice regex/callback way to handle this
+ // replacement, but at the moment it is pretty complex, and
+ // would probably be a lot uglier to work into a preg_replace_callback()
+ // system. The biggest problem is the fact that a resolution may require
+ // multiple passes.
+
+ $name = array_shift($keys);
+ $value = $props->getProperty($name);
+ $resolved = false;
+
+ while(!$resolved) {
+
+ $fragments = array();
+ $propertyRefs = array();
+
+ // [HL] this was ::parsePropertyString($this->value ...) ... this seems wrong
+ self::parsePropertyString($value, $fragments, $propertyRefs);
+
+ $resolved = true;
+ if (count($propertyRefs) !== 0) {
+
+ $sb = "";
+
+ $i = $fragments;
+ $j = $propertyRefs;
+ while(count($i)) {
+ $fragment = array_shift($i);
+ if ($fragment === null) {
+ $propertyName = array_shift($j);
+
+ if ($propertyName === $name) {
+ // Should we maybe just log this as an error & move on?
+ // $this->log("Property ".$name." was circularly defined.", PROJECT_MSG_ERR);
+ throw new BuildException("Property ".$name." was circularly defined.");
+ }
+
+ $fragment = $this->getProject()->getProperty($propertyName);
+ if ($fragment === null) {
+ if ($props->containsKey($propertyName)) {
+ $fragment = $props->getProperty($propertyName);
+ $resolved = false; // parse again (could have been replaced w/ another var)
+ } else {
+ $fragment = "\${".$propertyName."}";
+ }
+ }
+ }
+ $sb .= $fragment;
+ }
+
+ $this->log("Resolved Property \"$value\" to \"$sb\"", PROJECT_MSG_DEBUG);
+ $value = $sb;
+ $props->setProperty($name, $value);
+
+ } // if (count($propertyRefs))
+
+ } // while (!$resolved)
+
+ } // while (count($keys)
+ }
+
+
+ /**
+ * This method will parse a string containing ${value} style
+ * property values into two lists. The first list is a collection
+ * of text fragments, while the other is a set of string property names
+ * null entries in the first list indicate a property reference from the
+ * second list.
+ *
+ * This is slower than regex, but useful for this class, which has to handle
+ * multiple parsing passes for properties.
+ *
+ * @param string $value The string to be scanned for property references
+ * @param array &$fragments The found fragments
+ * @param array &$propertyRefs The found refs
+ */
+ protected function parsePropertyString($value, &$fragments, &$propertyRefs) {
+
+ $prev = 0;
+ $pos = 0;
+
+ while (($pos = strpos($value, '$', $prev)) !== false) {
+
+ if ($pos > $prev) {
+ array_push($fragments, StringHelper::substring($value, $prev, $pos-1));
+ }
+ if ($pos === (strlen($value) - 1)) {
+ array_push($fragments, '$');
+ $prev = $pos + 1;
+ } elseif ($value{$pos+1} !== '{' ) {
+
+ // the string positions were changed to value-1 to correct
+ // a fatal error coming from function substring()
+ array_push($fragments, StringHelper::substring($value, $pos, $pos + 1));
+ $prev = $pos + 2;
+ } else {
+ $endName = strpos($value, '}', $pos);
+ if ($endName === false) {
+ throw new BuildException("Syntax error in property: $value");
+ }
+ $propertyName = StringHelper::substring($value, $pos + 2, $endName-1);
+ array_push($fragments, null);
+ array_push($propertyRefs, $propertyName);
+ $prev = $endName + 1;
+ }
+ }
+
+ if ($prev < strlen($value)) {
+ array_push($fragments, StringHelper::substring($value, $prev));
+ }
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/ReflexiveTask.php b/buildscripts/phing/classes/phing/tasks/system/ReflexiveTask.php
new file mode 100644
index 00000000..dc7cfeb7
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/ReflexiveTask.php
@@ -0,0 +1,155 @@
+<?php
+/*
+ * $Id: ReflexiveTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+
+/**
+ * This task is for using filter chains to make changes to files and overwrite the original files.
+ *
+ * This task was created to serve the need for "cleanup" tasks -- e.g. a ReplaceRegexp task or strip task
+ * being used to modify files and then overwrite the modified files. In many (most?) cases you probably
+ * should just use a copy task to preserve the original source files, but this task supports situations
+ * where there is no src vs. build directory, and modifying source files is actually desired.
+ *
+ * <code>
+ * <reflexive>
+ * <fileset dir=".">
+ * <include pattern="*.html">
+ * </fileset>
+ * <filterchain>
+ * <replaceregexp>
+ * <regexp pattern="\n\r" replace="\n"/>
+ * </replaceregexp>
+ * </filterchain>
+ * </reflexive>
+ * </code>
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.11 $
+ * @package phing.tasks.system
+ */
+class ReflexiveTask extends Task {
+
+ /** Single file to process. */
+ private $file;
+
+ /** Any filesets that should be processed. */
+ private $filesets = array();
+
+ /** Any filters to be applied before append happens. */
+ private $filterChains = array();
+
+ /** Alias for setFrom() */
+ function setFile(PhingFile $f) {
+ $this->file = $f;
+ }
+
+ /** Nested creator, adds a set of files (nested fileset attribute). */
+ function createFileSet() {
+ $num = array_push($this->filesets, new FileSet());
+ return $this->filesets[$num-1];
+ }
+
+ /**
+ * Creates a filterchain
+ *
+ * @return object The created filterchain object
+ */
+ function createFilterChain() {
+ $num = array_push($this->filterChains, new FilterChain($this->project));
+ return $this->filterChains[$num-1];
+ }
+
+ /** Append the file(s). */
+ function main() {
+
+ if ($this->file === null && empty($this->filesets)) {
+ throw new BuildException("You must specify a file or fileset(s) for the <reflexive> task.");
+ }
+
+ // compile a list of all files to modify, both file attrib and fileset elements
+ // can be used.
+
+ $files = array();
+
+ if ($this->file !== null) {
+ $files[] = $this->file;
+ }
+
+ if (!empty($this->filesets)) {
+ $filenames = array();
+ foreach($this->filesets as $fs) {
+ try {
+ $ds = $fs->getDirectoryScanner($this->project);
+ $filenames = $ds->getIncludedFiles(); // get included filenames
+ $dir = $fs->getDir($this->project);
+ foreach ($filenames as $fname) {
+ $files[] = new PhingFile($dir, $fname);
+ }
+ } catch (BuildException $be) {
+ $this->log($be->getMessage(), PROJECT_MSG_WARN);
+ }
+ }
+ }
+
+ $this->log("Applying reflexive processing to " . count($files) . " files.");
+
+ // These "slots" allow filters to retrieve information about the currently-being-process files
+ $slot = $this->getRegisterSlot("currentFile");
+ $basenameSlot = $this->getRegisterSlot("currentFile.basename");
+
+
+ foreach($files as $file) {
+ // set the register slots
+
+ $slot->setValue($file->getPath());
+ $basenameSlot->setValue($file->getName());
+
+ // 1) read contents of file, pulling through any filters
+ $in = null;
+ try {
+ $contents = "";
+ $in = FileUtils::getChainedReader(new FileReader($file), $this->filterChains, $this->project);
+ while(-1 !== ($buffer = $in->read())) {
+ $contents .= $buffer;
+ }
+ $in->close();
+ } catch (Exception $e) {
+ if ($in) $in->close();
+ $this->log("Erorr reading file: " . $e->getMessage(), PROJECT_MSG_WARN);
+ }
+
+ try {
+ // now create a FileWriter w/ the same file, and write to the file
+ $out = new FileWriter($file);
+ $out->write($contents);
+ $out->close();
+ $this->log("Applying reflexive processing to " . $file->getPath(), PROJECT_MSG_VERBOSE);
+ } catch (Exception $e) {
+ if ($out) $out->close();
+ $this->log("Error writing file back: " . $e->getMessage(), PROJECT_MSG_WARN);
+ }
+
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/system/ResolvePathTask.php b/buildscripts/phing/classes/phing/tasks/system/ResolvePathTask.php
new file mode 100644
index 00000000..b468afb5
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/ResolvePathTask.php
@@ -0,0 +1,122 @@
+<?php
+/*
+ * $Id: ResolvePathTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+
+/**
+ * Task for resolving relative paths and setting absolute path in property value.
+ *
+ * This task was created to address a need for resolving absolute paths of files / directories.
+ * In many cases a relative directory (e.g. "./build") is specified, but it needs to be treated
+ * as an absolute path since other build files (e.g. in subdirs) should all be using the same
+ * path -- and not treating it as a relative path to their own directory.
+ *
+ * <code>
+ * <property name="relative_path" value="./dirname"/>
+ * <resolvepath propertyName="absolute_path" file="${relative_path}"/>
+ * <echo>Resolved [absolute] path: ${absolute_path}</echo>
+ * </code>
+ *
+ * TODO:
+ * - Possibly integrate this with PackageAsPath, for handling/resolving dot-path paths.
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.6 $
+ * @package phing.tasks.system
+ */
+class ResolvePathTask extends Task {
+
+ /** Name of property to set. */
+ private $propertyName;
+
+ /** The [possibly] relative file/path that needs to be resolved. */
+ private $file;
+
+ /** Base directory used for resolution. */
+ private $dir;
+
+ /**
+ * Set the name of the property to set.
+ * @param string $v Property name
+ * @return void
+ */
+ public function setPropertyName($v) {
+ $this->propertyName = $v;
+ }
+
+ /**
+ * Sets a base dir to use for resolution.
+ * @param PhingFile $d
+ */
+ function setDir(PhingFile $d) {
+ $this->dir = $d;
+ }
+
+ /**
+ * Sets a path (file or directory) that we want to resolve.
+ * This is the same as setFile() -- just more generic name so that it's
+ * clear that you can also use it to set directory.
+ * @param string $f
+ * @see setFile()
+ */
+ function setPath($f) {
+ $this->file = $f;
+ }
+
+ /**
+ * Sets a file that we want to resolve.
+ * @param string $f
+ */
+ function setFile($f) {
+ $this->file = $f;
+ }
+
+ /**
+ * Perform the resolution & set property.
+ */
+ public function main() {
+
+ if (!$this->propertyName) {
+ throw new BuildException("You must specify the propertyName attribute", $this->getLocation());
+ }
+
+ // Currently only files are supported
+ if ($this->file === null) {
+ throw new BuildException("You must specify a path to resolve", $this->getLocation());
+ }
+
+ $fs = FileSystem::getFileSystem();
+
+ // if dir attribute was specified then we should
+ // use that as basedir to which file was relative.
+ // -- unless the file specified is an absolute path
+ if ($this->dir !== null && !$fs->isAbsolute(new PhingFile($this->file))) {
+ $resolved = new PhingFile($this->dir->getPath(), $this->file);
+ } else {
+ // otherwise just resolve it relative to project basedir
+ $resolved = $this->project->resolveFile($this->file);
+ }
+
+ $this->log("Resolved " . $this->file . " to " . $resolved->getAbsolutePath(), PROJECT_MSG_INFO);
+ $this->project->setProperty($this->propertyName, $resolved->getAbsolutePath());
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/SequentialTask.php b/buildscripts/phing/classes/phing/tasks/system/SequentialTask.php
new file mode 100644
index 00000000..50327e3f
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/SequentialTask.php
@@ -0,0 +1,57 @@
+<?php
+
+/*
+ * $Id: SequentialTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+require_once 'phing/TaskContainer.php';
+
+/**
+ * Sequential is a container task that contains other Phing Task objects.
+ *
+ * The sequential task has no attributes and does not support any nested
+ * elements apart from Ant tasks. Any valid Ant task may be embedded within the
+ * sequential task.
+ *
+ * @since 2.1.2
+ */
+class SequentialTask extends Task implements TaskContainer {
+
+ /** Optional Vector holding the nested tasks */
+ private $nestedTasks = array();
+
+ /**
+ * Add a nested task to Sequential.
+ * @param Task $nestedTask Nested task to execute Sequential
+ */
+ public function addTask(Task $nestedTask) {
+ $this->nestedTasks[] = $nestedTask;
+ }
+
+ /**
+ * Execute all nestedTasks.
+ * @throws BuildException if one of the nested tasks fails.
+ */
+ public function main() {
+ foreach($this->nestedTasks as $task) {
+ $task->perform();
+ }
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/TaskdefTask.php b/buildscripts/phing/classes/phing/tasks/system/TaskdefTask.php
new file mode 100644
index 00000000..4a90e106
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/TaskdefTask.php
@@ -0,0 +1,127 @@
+<?php
+
+/*
+ * $Id: TaskdefTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+
+/**
+ * Register a task for use within a buildfile.
+ *
+ * This is for registering your own tasks -- or any non-core Task -- for use within a buildfile.
+ * If you find that you are using a particular class frequently, you may want to edit the
+ * phing/tasks/defaults.properties file so that it is included by default. You may also
+ * want to submit it (if LGPL or compatible license) to be included in Phing distribution.
+ *
+ * <pre>
+ * <taskdef name="mytag" classname="path.to.MyHandlingClass"/>
+ * .
+ * .
+ * <mytag param1="val1" param2="val2"/>
+ * </pre>
+ *
+ * TODO:
+ * -- possibly refactor since this is almost the same as TypeDefTask
+ * (right now these are just too simple to really justify creating an abstract class)
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.11 $
+ * @package phing.tasks.system
+ */
+class TaskdefTask extends Task {
+
+ /** Tag name for task that will be used in XML */
+ private $name;
+
+ /**
+ * Classname of task to register.
+ * This can be a dot-path -- relative to a location on PHP include_path.
+ * E.g. path.to.MyClass -> path/to/MyClass.php
+ * @var string
+ */
+ private $classname;
+
+ /**
+ * Path to add to PHP include_path to aid in finding specified class.
+ * @var Path
+ */
+ private $classpath;
+
+ /**
+ * Refid to already defined classpath
+ */
+ private $classpathId;
+
+ /**
+ * Set the classpath to be used when searching for component being defined
+ *
+ * @param Path $classpath An Path object containing the classpath.
+ */
+ public function setClasspath(Path $classpath) {
+ if ($this->classpath === null) {
+ $this->classpath = $classpath;
+ } else {
+ $this->classpath->append($classpath);
+ }
+ }
+
+ /**
+ * Create the classpath to be used when searching for component being defined
+ */
+ public function createClasspath() {
+ if ($this->classpath === null) {
+ $this->classpath = new Path($this->project);
+ }
+ return $this->classpath->createPath();
+ }
+
+ /**
+ * Reference to a classpath to use when loading the files.
+ */
+ public function setClasspathRef(Reference $r) {
+ $this->classpathId = $r->getRefId();
+ $this->createClasspath()->setRefid($r);
+ }
+
+ /**
+ * Sets the name that will be used in XML buildfile.
+ * @param string $name
+ */
+ public function setName($name) {
+ $this->name = $name;
+ }
+
+ /**
+ * Sets the class name / dotpath to use.
+ * @param string $class
+ */
+ public function setClassname($class) {
+ $this->classname = $class;
+ }
+
+ /** Main entry point */
+ public function main() {
+ if ($this->name === null || $this->classname === null) {
+ throw new BuildException("You must specify name and class attributes for <taskdef>.");
+ }
+ $this->log("Task " . $this->name . " will be handled by class " . $this->classname, PROJECT_MSG_VERBOSE);
+ $this->project->addTaskDefinition($this->name, $this->classname, $this->classpath);
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/TouchTask.php b/buildscripts/phing/classes/phing/tasks/system/TouchTask.php
new file mode 100644
index 00000000..6c6c4080
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/TouchTask.php
@@ -0,0 +1,170 @@
+<?php
+/*
+ * $Id: TouchTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+include_once 'phing/util/DirectoryScanner.php';
+include_once 'phing/types/FileSet.php';
+include_once 'phing/util/FileUtils.php';
+include_once 'phing/system/io/PhingFile.php';
+include_once 'phing/system/io/IOException.php';
+
+/**
+ * Touch a file and/or fileset(s); corresponds to the Unix touch command.
+ *
+ * If the file to touch doesn't exist, an empty one is created.
+ *
+ * @version $Revision: 1.12 $
+ * @package phing.tasks.system
+ */
+class TouchTask extends Task {
+
+ private $file;
+ private $millis = -1;
+ private $dateTime;
+ private $filesets = array();
+ private $fileUtils;
+
+ function __construct() {
+ $this->fileUtils = new FileUtils();
+ }
+
+ /**
+ * Sets a single source file to touch. If the file does not exist
+ * an empty file will be created.
+ */
+ function setFile(PhingFile $file) {
+ $this->file = $file;
+ }
+
+ /**
+ * the new modification time of the file
+ * in milliseconds since midnight Jan 1 1970.
+ * Optional, default=now
+ */
+ function setMillis($millis) {
+ $this->millis = (int) $millis;
+ }
+
+ /**
+ * the new modification time of the file
+ * in the format MM/DD/YYYY HH:MM AM or PM;
+ * Optional, default=now
+ */
+ function setDatetime($dateTime) {
+ $this->dateTime = (string) $dateTime;
+ }
+
+ /**
+ * Nested creator, adds a set of files (nested fileset attribute).
+ * @return FileSet
+ */
+ function createFileSet() {
+ $num = array_push($this->filesets, new FileSet());
+ return $this->filesets[$num-1];
+ }
+
+ /**
+ * Execute the touch operation.
+ */
+ function main() {
+ $savedMillis = $this->millis;
+
+ if ($this->file === null && count($this->filesets) === 0) {
+ throw new BuildException("Specify at least one source - a file or a fileset.");
+ }
+
+ if ($this->file !== null && $this->file->exists() && $this->file->isDirectory()) {
+ throw new BuildException("Use a fileset to touch directories.");
+ }
+
+ try { // try to touch file
+ if ($this->dateTime !== null) {
+ $this->setMillis(strtotime($this->dateTime));
+ if ($this->millis < 0) {
+ throw new BuildException("Date of {$this->dateTime} results in negative milliseconds value relative to epoch (January 1, 1970, 00:00:00 GMT).");
+ }
+ }
+ $this->_touch();
+ } catch (Exception $ex) {
+ throw new BuildException("Error touch()ing file", $ex, $this->location);
+ }
+
+ $this->millis = $savedMillis;
+
+ }
+
+ /**
+ * Does the actual work.
+ */
+ function _touch() {
+ if ($this->file !== null) {
+ if (!$this->file->exists()) {
+ $this->log("Creating " . $this->file->__toString(), PROJECT_MSG_INFO);
+ try { // try to create file
+ $this->file->createNewFile();
+ } catch(IOException $ioe) {
+ throw new BuildException("Error creating new file " . $this->file->__toString(), $ioe, $this->location);
+ }
+ }
+ }
+
+ $resetMillis = false;
+ if ($this->millis < 0) {
+ $resetMillis = true;
+ $this->millis = Phing::currentTimeMillis();
+ }
+
+ if ($this->file !== null) {
+ $this->touchFile($this->file);
+ }
+
+ // deal with the filesets
+ foreach($this->filesets as $fs) {
+
+ $ds = $fs->getDirectoryScanner($this->getProject());
+ $fromDir = $fs->getDir($this->getProject());
+
+ $srcFiles = $ds->getIncludedFiles();
+ $srcDirs = $ds->getIncludedDirectories();
+
+ for ($j=0,$_j=count($srcFiles); $j < $_j; $j++) {
+ $this->touchFile(new PhingFile($fromDir, (string) $srcFiles[$j]));
+ }
+
+ for ($j=0,$_j=count($srcDirs); $j < $_j ; $j++) {
+ $this->touchFile(new PhingFile($fromDir, (string) $srcDirs[$j]));
+ }
+ }
+
+ if ($resetMillis) {
+ $this->millis = -1;
+ }
+ }
+
+ private function touchFile($file) {
+ if ( !$file->canWrite() ) {
+ throw new BuildException("Can not change modification date of read-only file " . $file->__toString());
+ }
+ $file->setLastModified($this->millis);
+ }
+
+}
+
diff --git a/buildscripts/phing/classes/phing/tasks/system/TstampTask.php b/buildscripts/phing/classes/phing/tasks/system/TstampTask.php
new file mode 100644
index 00000000..9341c3dd
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/TstampTask.php
@@ -0,0 +1,168 @@
+<?php
+/*
+ * $Id: TstampTask.php 58 2006-04-28 14:41:04Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+
+/**
+ * Sets properties to the current time, or offsets from the current time.
+ * The default properties are TSTAMP, DSTAMP and TODAY;
+ *
+ * Based on Ant's Tstamp task.
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Revision: 1.6 $
+ * @package phing.tasks.system
+ * @since 2.2.0
+ */
+class TstampTask extends Task
+{
+ private $customFormats = array();
+
+ private $prefix = "";
+
+ /**
+ * Set a prefix for the properties. If the prefix does not end with a "."
+ * one is automatically added.
+ * @param prefix the prefix to use.
+ */
+ public function setPrefix($prefix)
+ {
+ $this->prefix = $prefix;
+
+ if (!empty($this->prefix))
+ {
+ $this->prefix.= ".";
+ }
+ }
+
+ /**
+ * Adds a custom format
+ *
+ * @param TstampCustomFormat custom format
+ */
+ public function addFormat(TstampCustomFormat $cf)
+ {
+ $this->customFormats[] = $cf;
+ }
+
+ /**
+ * Create the timestamps. Custom ones are done before
+ * the standard ones.
+ *
+ * @throws BuildException
+ */
+ public function main()
+ {
+ foreach ($this->customFormats as $cf)
+ {
+ $cf->execute($this);
+ }
+
+ $dstamp = strftime('%Y%m%d');
+ $this->prefixProperty('DSTAMP', $dstamp);
+
+ $tstamp = strftime('%H%M');
+ $this->prefixProperty('TSTAMP', $tstamp);
+
+ $today = strftime('%B %d %Y');
+ $this->prefixProperty('TODAY', $today);
+ }
+
+ /**
+ * helper that encapsulates prefix logic and property setting
+ * policy (i.e. we use setNewProperty instead of setProperty).
+ */
+ public function prefixProperty($name, $value)
+ {
+ $this->getProject()->setNewProperty($this->prefix . $name, $value);
+ }
+}
+
+class TstampCustomFormat
+{
+ private $propertyName = "";
+ private $pattern = "";
+ private $locale = "";
+
+ /**
+ * The property to receive the date/time string in the given pattern
+ *
+ * @param propertyName the name of the property.
+ */
+ public function setProperty($propertyName)
+ {
+ $this->propertyName = $propertyName;
+ }
+
+ /**
+ * The date/time pattern to be used. The values are as
+ * defined by the PHP strftime() function.
+ *
+ * @param pattern
+ */
+ public function setPattern($pattern)
+ {
+ $this->pattern = $pattern;
+ }
+
+ /**
+ * The locale used to create date/time string.
+ *
+ * @param locale
+ */
+ public function setLocale($locale)
+ {
+ $this->locale = $locale;
+ }
+
+ /**
+ * validate parameter and execute the format.
+ *
+ * @param TstampTask reference to task
+ */
+ public function execute(TstampTask $tstamp)
+ {
+ if (empty($this->propertyName))
+ {
+ throw new BuildException("property attribute must be provided");
+ }
+
+ if (empty($this->pattern))
+ {
+ throw new BuildException("pattern attribute must be provided");
+ }
+
+ if (!empty($this->locale))
+ {
+ setlocale(LC_ALL, $this->locale);
+ }
+
+ $value = strftime($this->pattern);
+ $tstamp->prefixProperty($this->propertyName, $value);
+
+ if (!empty($this->locale))
+ {
+ // reset locale
+ setlocale(LC_ALL, NULL);
+ }
+ }
+}
+?>
diff --git a/buildscripts/phing/classes/phing/tasks/system/TypedefTask.php b/buildscripts/phing/classes/phing/tasks/system/TypedefTask.php
new file mode 100644
index 00000000..de058c90
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/TypedefTask.php
@@ -0,0 +1,125 @@
+<?php
+/*
+ * $Id: TypedefTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+
+/**
+ * Register a datatype for use within a buildfile.
+ *
+ * This is for registering your own datatypes for use within a buildfile.
+ *
+ * If you find that you are using a particular class frequently, you may want to edit the
+ * phing/types/defaults.properties file so that it is included by default. You may also
+ * want to submit it (if LGPL or compatible license) to be included in Phing distribution.
+ *
+ * <pre>
+ * <typedef name="mytype" classname="path.to.MyHandlingClass"/>
+ * .
+ * <sometask ...>
+ * <mytype param1="val1" param2="val2"/>
+ * </sometask>
+ * </pre>
+ *
+ * TODO:
+ * -- possibly refactor since this is almost the same as TaskDefTask
+ * (right now these are just too simple to really justify creating an abstract class)
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.7 $
+ * @package phing.tasks.system
+ */
+class TypedefTask extends Task {
+
+ /** Tag name for datatype that will be used in XML */
+ private $name;
+
+ /**
+ * Classname of task to register.
+ * This can be a dot-path -- relative to a location on PHP include_path.
+ * E.g. path.to.MyClass -> path/to/MyClass.php
+ * @var string
+ */
+ private $classname;
+
+ /**
+ * Path to add to PHP include_path to aid in finding specified class.
+ * @var Path
+ */
+ private $classpath;
+
+ /** Refid to already defined classpath */
+ private $classpathId;
+
+ /**
+ * Set the classpath to be used when searching for component being defined
+ *
+ * @param Path $classpath An Path object containing the classpath.
+ */
+ public function setClasspath(Path $classpath) {
+ if ($this->classpath === null) {
+ $this->classpath = $classpath;
+ } else {
+ $this->classpath->append($classpath);
+ }
+ }
+
+ /**
+ * Create the classpath to be used when searching for component being defined
+ */
+ public function createClasspath() {
+ if ($this->classpath === null) {
+ $this->classpath = new Path($this->project);
+ }
+ return $this->classpath->createPath();
+ }
+
+ /**
+ * Reference to a classpath to use when loading the files.
+ */
+ public function setClasspathRef(Reference $r) {
+ $this->classpathId = $r->getRefId();
+ $this->createClasspath()->setRefid($r);
+ }
+
+ /** Main entry point */
+ public function main() {
+ if ($this->name === null || $this->classname === null) {
+ throw new BuildException("You must specify name and class attributes for <typedef>.");
+ }
+ $this->project->addDataTypeDefinition($this->name, $this->classname, $this->classpath);
+ }
+
+ /**
+ * Sets the name that will be used in XML buildfile.
+ * @param string $name
+ */
+ public function setName($name) {
+ $this->name = $name;
+ }
+
+ /**
+ * Sets the class name / dotpath to use.
+ * @param string $class
+ */
+ public function setClassname($class) {
+ $this->classname = $class;
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/UpToDateTask.php b/buildscripts/phing/classes/phing/tasks/system/UpToDateTask.php
new file mode 100644
index 00000000..720fae12
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/UpToDateTask.php
@@ -0,0 +1,217 @@
+<?php
+/*
+ * $Id: UpToDateTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/Task.php';
+include_once 'phing/tasks/system/condition/Condition.php';
+include_once 'phing/util/DirectoryScanner.php';
+include_once 'phing/util/SourceFileScanner.php';
+include_once 'phing/mappers/MergeMapper.php';
+
+/**
+ * Sets the given property if the specified target has a timestamp
+ * greater than all of the source files.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author William Ferguson <williamf@mincom.com> (Ant)
+ * @author Hiroaki Nakamura <hnakamur@mc.neweb.ne.jp> (Ant)
+ * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant)
+ * @version $Revision: 1.6 $
+ * @package phing.tasks.system
+ */
+class UpToDateTask extends Task implements Condition {
+
+ private $_property;
+ private $_value;
+ private $_sourceFile;
+ private $_targetFile;
+ private $sourceFileSets = array();
+
+ protected $mapperElement = null;
+
+ /**
+ * The property to set if the target file is more up-to-date than
+ * (each of) the source file(s).
+ *
+ * @param property the name of the property to set if Target is up-to-date.
+ */
+ public function setProperty($property) {
+ $this->_property = $property;
+ }
+
+ /**
+ * The value to set the named property to if the target file is more
+ * up-to-date than (each of) the source file(s). Defaults to 'true'.
+ *
+ * @param value the value to set the property to if Target is up-to-date
+ */
+ public function setValue($value) {
+ $this->_value = $value;
+ }
+
+ /**
+ * Returns the value, or "true" if a specific value wasn't provided.
+ */
+ private function getValue() {
+ return ($this->_value !== null) ? $this->_value : "true";
+ }
+
+ /**
+ * The file which must be more up-to-date than (each of) the source file(s)
+ * if the property is to be set.
+ *
+ * @param file the file we are checking against.
+ */
+ public function setTargetFile($file) {
+ if (is_string($file)) {
+ $file = new PhingFile($file);
+ }
+ $this->_targetFile = $file;
+ }
+
+ /**
+ * The file that must be older than the target file
+ * if the property is to be set.
+ *
+ * @param file the file we are checking against the target file.
+ */
+ public function setSrcfile($file) {
+ if (is_string($file)) {
+ $file = new PhingFile($file);
+ }
+ $this->_sourceFile = $file;
+ }
+
+ /**
+ * Nested <srcfiles> element.
+ */
+ public function createSrcfiles() {
+ $fs = new FileSet();
+ $this->sourceFileSets[] = $fs;
+ return $fs;
+ }
+
+ /**
+ * Defines the FileNameMapper to use (nested mapper element).
+ */
+ public function createMapper() {
+ if ($this->mapperElement !== null) {
+ throw new BuildException("Cannot define more than one mapper",
+ $this->location);
+ }
+ $this->mapperElement = new Mapper($this->getProject());
+ return $this->mapperElement;
+ }
+
+ /**
+ * Evaluate (all) target and source file(s) to
+ * see if the target(s) is/are up-to-date.
+ * @return boolean
+ */
+ public function evaluate() {
+ if (count($this->sourceFileSets) === 0 && $this->_sourceFile === null) {
+ throw new BuildException("At least one srcfile or a nested "
+ . "<srcfiles> element must be set.");
+ }
+
+ if (count($this->sourceFileSets) > 0 && $this->_sourceFile !== null) {
+ throw new BuildException("Cannot specify both the srcfile "
+ . "attribute and a nested <srcfiles> "
+ . "element.");
+ }
+
+ if ($this->_targetFile === null && $this->mapperElement === null) {
+ throw new BuildException("The targetfile attribute or a nested "
+ . "mapper element must be set.");
+ }
+
+ // if the target file is not there, then it can't be up-to-date
+ if ($this->_targetFile !== null && !$this->_targetFile->exists()) {
+ return false;
+ }
+
+ // if the source file isn't there, throw an exception
+ if ($this->_sourceFile !== null && !$this->_sourceFile->exists()) {
+ throw new BuildException($this->_sourceFile->getAbsolutePath()
+ . " not found.");
+ }
+
+ $upToDate = true;
+ for($i=0,$size=count($this->sourceFileSets); $i < $size && $upToDate; $i++) {
+ $fs = $this->sourceFileSets[$i];
+ $ds = $fs->getDirectoryScanner($this->project);
+ $upToDate = $upToDate && $this->scanDir($fs->getDir($this->project),
+ $ds->getIncludedFiles());
+ }
+
+ if ($this->_sourceFile !== null) {
+ if ($this->mapperElement === null) {
+ $upToDate = $upToDate &&
+ ($this->_targetFile->lastModified() >= $this->_sourceFile->lastModified());
+ } else {
+ $sfs = new SourceFileScanner($this);
+ $upToDate = $upToDate &&
+ count($sfs->restrict($this->_sourceFile->getAbsolutePath(),
+ null, null,
+ $this->mapperElement->getImplementation())) === 0;
+ }
+ }
+ return $upToDate;
+ }
+
+
+ /**
+ * Sets property to true if target file(s) have a more recent timestamp
+ * than (each of) the corresponding source file(s).
+ * @throws BuildException
+ */
+ public function main() {
+ if ($this->_property === null) {
+ throw new BuildException("property attribute is required.",
+ $this->location);
+ }
+ $upToDate = $this->evaluate();
+ if ($upToDate) {
+ $this->project->setNewProperty($this->_property, $this->getValue());
+ if ($this->mapperElement === null) {
+ $this->log("File \"" . $this->_targetFile->getAbsolutePath()
+ . "\" is up-to-date.", PROJECT_MSG_VERBOSE);
+ } else {
+ $this->log("All target files are up-to-date.",
+ PROJECT_MSG_VERBOSE);
+ }
+ }
+ }
+
+ protected function scanDir(PhingFile $srcDir, $files) {
+ $sfs = new SourceFileScanner($this);
+ $mapper = null;
+ $dir = $srcDir;
+ if ($this->mapperElement === null) {
+ $mm = new MergeMapper();
+ $mm->setTo($this->_targetFile->getAbsolutePath());
+ $mapper = $mm;
+ $dir = null;
+ } else {
+ $mapper = $this->mapperElement->getImplementation();
+ }
+ return (count($sfs->restrict($files, $srcDir, $dir, $mapper)) === 0);
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/WarnTask.php b/buildscripts/phing/classes/phing/tasks/system/WarnTask.php
new file mode 100644
index 00000000..50318e71
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/WarnTask.php
@@ -0,0 +1,35 @@
+<?php
+/*
+ * $Id: WarnTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/tasks/system/EchoTask.php';
+
+/**
+ * Simple task to echo a warning message (PROJECT_MSG_WARN) to all output devices.
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.1 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $
+ * @package phing.tasks.system
+ */
+class WarnTask extends EchoTask {
+ function main() {
+ $this->log($this->msg, PROJECT_MSG_WARN);
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/XsltTask.php b/buildscripts/phing/classes/phing/tasks/system/XsltTask.php
new file mode 100644
index 00000000..0374aa59
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/XsltTask.php
@@ -0,0 +1,81 @@
+<?php
+/*
+ * $Id: XsltTask.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/tasks/system/CopyTask.php';
+include_once 'phing/system/io/FileReader.php';
+include_once 'phing/system/io/FileWriter.php';
+include_once 'phing/filters/XsltFilter.php';
+
+/**
+ * Implements an XSLT processing filter while copying files.
+ *
+ * This is a shortcut for calling the <copy> task with the XSLTFilter used
+ * in the <filterchains> section.
+ *
+ * @author Andreas Aderhold, andi@binarycloud.com
+ * @version $Revision: 1.8 $
+ * @package phing.tasks.system
+ */
+class XsltTask extends CopyTask {
+
+ /** XSLTFilter object that we use to handle transformation. */
+ private $xsltFilter;
+
+ /** Parameters to pass to XSLT procesor. */
+ private $parameters = array();
+
+ /**
+ * Setup the filterchains w/ XSLTFilter that we will use while copying the files.
+ */
+ function init() {
+ $xf = new XsltFilter();
+ $chain = $this->createFilterChain($this->getProject());
+ $chain->addXsltFilter($xf);
+ $this->xsltFilter = $xf;
+ }
+
+ /**
+ * Set any XSLT Param and invoke CopyTask::main()
+ * @see CopyTask::main()
+ */
+ function main() {
+ $this->log("Doing XSLT transformation using stylesheet " . $this->xsltFilter->getStyle(), PROJECT_MSG_VERBOSE);
+ $this->xsltFilter->setParams($this->parameters);
+ parent::main();
+ }
+
+ /**
+ * Set the stylesheet to use.
+ * @param PhingFile $style
+ */
+ function setStyle(PhingFile $style) {
+ $this->xsltFilter->setStyle($style);
+ }
+
+ /**
+ * Support nested <param> tags useing XSLTParam class.
+ * @return XSLTParam
+ */
+ function createParam() {
+ $num = array_push($this->parameters, new XSLTParam());
+ return $this->parameters[$num-1];
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/AndCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/AndCondition.php
new file mode 100644
index 00000000..c16ce499
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/condition/AndCondition.php
@@ -0,0 +1,46 @@
+<?php
+/*
+ * $Id: AndCondition.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/tasks/system/condition/ConditionBase.php';
+
+/**
+ * <and> condition container.
+ *
+ * Iterates over all conditions and returns false as soon as one
+ * evaluates to false.
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright © 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.7 $
+ * @package phing.tasks.system.condition
+ */
+class AndCondition extends ConditionBase implements Condition {
+
+ public function evaluate() {
+ foreach($this as $c) { // ConditionBase implements IteratorAggregator
+ if (!$c->evaluate()) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/Condition.php b/buildscripts/phing/classes/phing/tasks/system/condition/Condition.php
new file mode 100644
index 00000000..73e0c232
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/condition/Condition.php
@@ -0,0 +1,39 @@
+<?php
+
+/*
+ * $Id: Condition.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * Condition interface specification:
+ *
+ * Each condition must implement a method applying to this prototye:
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.4 $
+ * @package phing.tasks.system.condition
+ */
+interface Condition {
+ /**
+ * @return boolean
+ * @throws BuildException
+ */
+ public function evaluate();
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/ConditionBase.php b/buildscripts/phing/classes/phing/tasks/system/condition/ConditionBase.php
new file mode 100644
index 00000000..1c09fe49
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/condition/ConditionBase.php
@@ -0,0 +1,195 @@
+<?php
+/*
+ * $Id: ConditionBase.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/ProjectComponent.php';
+include_once 'phing/Project.php';
+include_once 'phing/tasks/system/AvailableTask.php';
+include_once 'phing/tasks/system/condition/Condition.php';
+
+/**
+ * Abstract baseclass for the <condition> task as well as several
+ * conditions - ensures that the types of conditions inside the task
+ * and the "container" conditions are in sync.
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright © 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.16 $
+ * @package phing.tasks.system.condition
+ */
+abstract class ConditionBase extends ProjectComponent implements IteratorAggregate {
+
+ public $conditions = array(); // needs to be public for "inner" class access
+
+ function countConditions() {
+ return count($this->conditions);
+ }
+
+ /**
+ * Required for IteratorAggregate
+ */
+ function getIterator() {
+ return new ConditionEnumeration($this);
+ }
+
+ function getConditions() {
+ return $this->conditions;
+ }
+
+ /**
+ * @return void
+ */
+ function addAvailable(AvailableTask $a) {
+ $this->conditions[] = $a;
+ }
+
+ /**
+ * @return NotCondition
+ */
+ function createNot() {
+ include_once 'phing/tasks/system/condition/NotCondition.php';
+ $num = array_push($this->conditions, new NotCondition());
+ return $this->conditions[$num-1];
+ }
+
+ /**
+ * @return AndCondition
+ */
+ function createAnd() {
+ include_once 'phing/tasks/system/condition/AndCondition.php';
+ $num = array_push($this->conditions, new AndCondition());
+ return $this->conditions[$num-1];
+ }
+
+ /**
+ * @return OrCondition
+ */
+ function createOr() {
+ include_once 'phing/tasks/system/condition/OrCondition.php';
+ $num = array_push($this->conditions, new OrCondition());
+ return $this->conditions[$num-1];
+ }
+
+ /**
+ * @return EqualsCondition
+ */
+ function createEquals() {
+ include_once 'phing/tasks/system/condition/EqualsCondition.php';
+ $num = array_push($this->conditions, new EqualsCondition());
+ return $this->conditions[$num-1];
+ }
+
+ /**
+ * @return OsCondition
+ */
+ function createOs() {
+ include_once 'phing/tasks/system/condition/OsCondition.php';
+ $num = array_push($this->conditions, new OsCondition());
+ return $this->conditions[$num-1];
+ }
+
+ /**
+ * @return IsFalseCondition
+ */
+ function createIsFalse() {
+ include_once 'phing/tasks/system/condition/IsFalseCondition.php';
+ $num = array_push($this->conditions, new IsFalseCondition());
+ return $this->conditions[$num-1];
+ }
+
+ /**
+ * @return IsTrueCondition
+ */
+ function createIsTrue() {
+ include_once 'phing/tasks/system/condition/IsTrueCondition.php';
+ $num = array_push($this->conditions, new IsTrueCondition());
+ return $this->conditions[$num-1];
+ }
+
+ /**
+ * @return ContainsCondition
+ */
+ function createContains() {
+ include_once 'phing/tasks/system/condition/ContainsCondition.php';
+ $num = array_push($this->conditions, new ContainsCondition());
+ return $this->conditions[$num-1];
+ }
+
+ /**
+ * @return IsSetCondition
+ */
+ function createIsSet() {
+ include_once 'phing/tasks/system/condition/IsSetCondition.php';
+ $num = array_push($this->conditions, new IsSetCondition());
+ return $this->conditions[$num-1];
+ }
+
+ /**
+ * @return ReferenceExistsCondition
+ */
+ function createReferenceExists() {
+ include_once 'phing/tasks/system/condition/ReferenceExistsCondition.php';
+ $num = array_push($this->conditions, new ReferenceExistsCondition());
+ return $this->conditions[$num-1];
+ }
+
+}
+
+/**
+ * "Inner" class for handling enumerations.
+ * Uses build-in PHP5 iterator support.
+ */
+class ConditionEnumeration implements Iterator {
+
+ /** Current element number */
+ private $num = 0;
+
+ /** "Outer" ConditionBase class. */
+ private $outer;
+
+ function __construct(ConditionBase $outer) {
+ $this->outer = $outer;
+ }
+
+ public function valid() {
+ return $this->outer->countConditions() > $this->num;
+ }
+
+ function current() {
+ $o = $this->outer->conditions[$this->num];
+ if ($o instanceof ProjectComponent) {
+ $o->setProject($this->outer->getProject());
+ }
+ return $o;
+ }
+
+ function next() {
+ $this->num++;
+ }
+
+ function key() {
+ return $this->num;
+ }
+
+ function rewind() {
+ $this->num = 0;
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/ContainsCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/ContainsCondition.php
new file mode 100644
index 00000000..95849cd8
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/condition/ContainsCondition.php
@@ -0,0 +1,76 @@
+<?php
+
+/*
+ * $Id: ContainsCondition.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/tasks/system/condition/Condition.php';
+
+/**
+ * Is one string part of another string?
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant)
+ * @version $Revision: 1.3 $
+ * @package phing.tasks.system.condition
+ */
+class ContainsCondition implements Condition {
+
+ private $string;
+ private $subString;
+ private $caseSensitive = true;
+
+ /**
+ * The string to search in.
+ * @param string $a1
+ */
+ public function setString($a1) {
+ $this->string = $a1;
+ }
+
+ /**
+ * The string to search for.
+ * @param string $a2
+ */
+ public function setSubstring($a2) {
+ $this->subString = $a2;
+ }
+
+ /**
+ * Whether to search ignoring case or not.
+ */
+ public function setCaseSensitive($b) {
+ $this->caseSensitive = (boolean) $b;
+ }
+
+ /**
+ * Check whether string contains substring.
+ * @throws BuildException
+ */
+ public function evaluate() {
+ if ($this->string === null || $this->subString === null) {
+ throw new BuildException("both string and substring are required "
+ . "in contains");
+ }
+
+ return $this->caseSensitive
+ ? strpos($this->string, $this->subString) !== false
+ : substr(strtolower($this->string), strtolower($this->subString)) !== false;
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/EqualsCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/EqualsCondition.php
new file mode 100644
index 00000000..32d51380
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/condition/EqualsCondition.php
@@ -0,0 +1,78 @@
+<?php
+/*
+ * $Id: EqualsCondition.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/tasks/system/condition/Condition.php';
+
+/**
+ * A simple string comparator. Compares two strings for eqiality in a
+ * binary safe manner. Implements the condition interface specification.
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright © 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.7 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $
+ * @access public
+ * @package phing.tasks.system.condition
+ */
+class EqualsCondition implements Condition {
+
+ private $arg1;
+ private $arg2;
+ private $trim = false;
+ private $caseSensitive = true;
+
+ public function setArg1($a1) {
+ $this->arg1 = $a1;
+ }
+
+ public function setArg2($a2) {
+ $this->arg2 = $a2;
+ }
+
+ /**
+ * Should we want to trim the arguments before comparing them?
+ * @param boolean $b
+ */
+ public function setTrim($b) {
+ $this->trim = (boolean) $b;
+ }
+
+ /**
+ * Should the comparison be case sensitive?
+ * @param boolean $b
+ */
+ public function setCaseSensitive($b) {
+ $this->caseSensitive = (boolean) $b;
+ }
+
+ public function evaluate() {
+ if ($this->arg1 === null || $this->arg2 === null) {
+ throw new BuildException("Both arg1 and arg2 are required in equals.");
+ }
+
+ if ($this->trim) {
+ $this->arg1 = trim($this->arg1);
+ $this->arg2 = trim($this->arg2);
+ }
+
+ //print("[comparison] Comparing '".$this->arg1."' and '".$this->arg2."'\n");
+ return $this->caseSensitive ? $this->arg1 === $this->arg2 : strtolower($this->arg1) === strtolower($this->arg2);
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/IsFalseCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/IsFalseCondition.php
new file mode 100644
index 00000000..ebbd1a3d
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/condition/IsFalseCondition.php
@@ -0,0 +1,60 @@
+<?php
+/*
+ * $Id: IsFalseCondition.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/ProjectComponent.php';
+require_once 'phing/tasks/system/condition/Condition.php';
+
+/**
+ * Condition that tests whether a given string evals to false.
+ *
+ * @author Hans Lellelid (Phing)
+ * @author Steve Loughran (Ant)
+ * @version $Revision: 1.4 $
+ * @package phing.tasks.system.condition
+ */
+class IsFalseCondition extends ProjectComponent implements Condition {
+
+ /**
+ * what we eval
+ */
+ private $value;
+
+ /**
+ * Set the value to be tested.
+ * @param boolean $value
+ */
+ public function setValue($value) {
+ $this->value = $value;
+ }
+
+ /**
+ * return the inverted value;
+ * @throws BuildException if someone forgot to spec a value
+ */
+ public function evaluate() {
+ if ($this->value === null) {
+ throw new BuildException("Nothing to test for falsehood");
+ }
+ return !$this->value;
+ }
+
+}
+
diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/IsSetCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/IsSetCondition.php
new file mode 100644
index 00000000..4f81c50f
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/condition/IsSetCondition.php
@@ -0,0 +1,53 @@
+<?php
+/*
+ * $Id: IsSetCondition.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/ProjectComponent.php';
+require_once 'phing/tasks/system/condition/Condition.php';
+
+/**
+ * Condition that tests whether a given property has been set.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant)
+ * @version $Revision: 1.4 $
+ * @package phing.tasks.system.condition
+ */
+class IsSetCondition extends ProjectComponent implements Condition {
+
+ private $property;
+
+ public function setProperty($p) {
+ $this->property = $p;
+ }
+
+ /**
+ * Check whether property is set.
+ * @throws BuildException
+ */
+ public function evaluate() {
+ if ($this->property === null) {
+ throw new BuildException("No property specified for isset "
+ . "condition");
+ }
+ return $this->project->getProperty($this->property) !== null;
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/IsTrueCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/IsTrueCondition.php
new file mode 100644
index 00000000..4affefc5
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/condition/IsTrueCondition.php
@@ -0,0 +1,59 @@
+<?php
+/*
+ * $Id: IsTrueCondition.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/ProjectComponent.php';
+require_once 'phing/tasks/system/condition/Condition.php';
+
+/**
+ * Condition that tests whether a given string evals to true.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Steve Loughran (Ant)
+ * @package phing.tasks.system.condition
+ */
+class IsTrueCondition extends ProjectComponent implements Condition {
+
+ /**
+ * what we eval
+ */
+ private $value;
+
+ /**
+ * Set the value to be tested.
+ * @param boolean $value
+ */
+ public function setValue($value) {
+ $this->value = $value;
+ }
+
+ /**
+ * return the inverted value;
+ * @throws BuildException if someone forgot to spec a value
+ */
+ public function evaluate() {
+ if ($this->value === null) {
+ throw new BuildException("Nothing to test for falsehood");
+ }
+ return $this->value;
+ }
+
+}
+
diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/NotCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/NotCondition.php
new file mode 100644
index 00000000..c76ef2b8
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/condition/NotCondition.php
@@ -0,0 +1,48 @@
+<?php
+/*
+ * $Id: NotCondition.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/tasks/system/condition/ConditionBase.php';
+
+/**
+ * <not> condition.
+ *
+ * Evaluates to true if the single condition nested into it is false
+ * and vice versa.
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright © 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.6 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $
+ * @access public
+ * @package phing.tasks.system.condition
+ */
+class NotCondition extends ConditionBase implements Condition {
+
+ function evaluate() {
+ if ($this->countConditions() > 1) {
+ throw new BuildException("You must not nest more than one condition into <not>");
+ }
+ if ($this->countConditions() < 1) {
+ throw new BuildException("You must nest a condition into <not>");
+ }
+ $conds = $this->getIterator();
+ return !$conds->current()->evaluate();
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/OrCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/OrCondition.php
new file mode 100644
index 00000000..778abfd0
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/condition/OrCondition.php
@@ -0,0 +1,46 @@
+<?php
+/*
+ * $Id: OrCondition.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/tasks/system/condition/ConditionBase.php';
+
+/**
+ * <or> condition container.
+ *
+ * Iterates over all conditions and returns true as soon as one
+ * evaluates to true.
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.8 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $
+ * @access public
+ * @package phing.tasks.system.condition
+ */
+class OrCondition extends ConditionBase implements Condition {
+
+ function evaluate() {
+ foreach($this as $c) { // ConditionBase implements IteratorAggregator
+ if ($c->evaluate()) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/OsCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/OsCondition.php
new file mode 100644
index 00000000..d80729e7
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/condition/OsCondition.php
@@ -0,0 +1,63 @@
+<?php
+/*
+ * $Id: OsCondition.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/tasks/system/condition/ConditionBase.php';
+
+/**
+ * Condition that tests the OS type.
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @copyright © 2001,2002 THYRELL. All rights reserved
+ * @version $Revision: 1.8 $ $Date: 2006-04-28 10:49:47 -0400 (Fri, 28 Apr 2006) $
+ * @access public
+ * @package phing.tasks.system.condition
+ */
+class OsCondition implements Condition {
+
+ private $family;
+
+ function setFamily($f) {
+ $this->family = strtolower($f);
+ }
+
+ function evaluate() {
+ $osName = strtolower(Phing::getProperty("os.name"));
+
+ if ($this->family !== null) {
+ if ($this->family === "windows") {
+ return StringHelper::startsWith("win", $osName);
+ } elseif ($this->family === "mac") {
+ return (strpos($osName, "mac") !== false || strpos($osName, "darwin") !== false);
+ } elseif ($this->family === ("unix")) {
+ return (
+ StringHelper::endsWith("ix", $osName) ||
+ StringHelper::endsWith("ux", $osName) ||
+ StringHelper::endsWith("bsd", $osName) ||
+ StringHelper::startsWith("sunos", $osName) ||
+ StringHelper::startsWith("darwin", $osName)
+ );
+ }
+ throw new BuildException("Don't know how to detect os family '" . $this->family . "'");
+ }
+ return false;
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/tasks/system/condition/ReferenceExistsCondition.php b/buildscripts/phing/classes/phing/tasks/system/condition/ReferenceExistsCondition.php
new file mode 100644
index 00000000..04c1cbbd
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/system/condition/ReferenceExistsCondition.php
@@ -0,0 +1,52 @@
+<?php
+/*
+ * $Id: ReferenceExistsCondition.php 59 2006-04-28 14:49:47Z mrook $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/ProjectComponent.php'; require_once 'phing/tasks/system/condition/Condition.php';
+
+/**
+ * Condition that tests whether a given reference exists.
+ *
+ * @author Matthias Pigulla <mp@webfactory.de> (Phing)
+ * @version $Revision: 1.1 $
+ * @package phing.tasks.system.condition */
+class ReferenceExistsCondition extends ProjectComponent implements Condition {
+
+ private $refid;
+
+ public function setRef($id) {
+ $this->refid = (string) $id;
+ }
+
+ /**
+ * Check whether the reference exists.
+ * @throws BuildException
+ */
+ public function evaluate() {
+ if ($this->refid === null) {
+ throw new BuildException("No ref attribute specified for reference-exists "
+ . "condition");
+ }
+ $refs = $this->project->getReferences();
+ return isset($refs[$this->refid]);
+ }
+
+}
+
diff --git a/buildscripts/phing/classes/phing/types/AbstractFileSet.php b/buildscripts/phing/classes/phing/types/AbstractFileSet.php
new file mode 100644
index 00000000..6d640705
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/AbstractFileSet.php
@@ -0,0 +1,570 @@
+<?php
+/*
+ * $Id: AbstractFileSet.php,v 1.15 2005/05/26 13:10:53 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/system/io/PhingFile.php';
+include_once 'phing/types/DataType.php';
+include_once 'phing/types/PatternSet.php';
+include_once 'phing/types/selectors/BaseSelector.php';
+include_once 'phing/types/selectors/SelectorContainer.php';
+include_once 'phing/types/selectors/BaseSelectorContainer.php';
+
+// Load all of the selectors (not really necessary but
+// helps reveal parse errors right away)
+
+include_once 'phing/types/selectors/AndSelector.php';
+include_once 'phing/types/selectors/ContainsSelector.php';
+include_once 'phing/types/selectors/ContainsRegexpSelector.php';
+include_once 'phing/types/selectors/DateSelector.php';
+include_once 'phing/types/selectors/DependSelector.php';
+include_once 'phing/types/selectors/DepthSelector.php';
+include_once 'phing/types/selectors/ExtendSelector.php';
+include_once 'phing/types/selectors/FilenameSelector.php';
+include_once 'phing/types/selectors/MajoritySelector.php';
+include_once 'phing/types/selectors/NoneSelector.php';
+include_once 'phing/types/selectors/NotSelector.php';
+include_once 'phing/types/selectors/OrSelector.php';
+include_once 'phing/types/selectors/PresentSelector.php';
+include_once 'phing/types/selectors/SizeSelector.php';
+include_once 'phing/types/selectors/TypeSelector.php';
+
+include_once 'phing/util/DirectoryScanner.php';
+
+/**
+ * The FileSet class provides methods and properties for accessing
+ * and managing filesets. It extends ProjectComponent and thus inherits
+ * all methods and properties (not explicitly declared). See ProjectComponent
+ * for further detail.
+ *
+ * TODO:
+ * - merge this with patternsets: FileSet extends PatternSet !!!
+ * requires additional mods to the parsing algo
+ * [HL] .... not sure if that really makes so much sense. I think
+ * that perhaps they should use common utility class if there really
+ * is that much shared functionality
+ *
+ * @author Andreas Aderhold <andi@binarycloud.com>
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.15 $ $Date: 2005/05/26 13:10:53 $
+ * @see ProjectComponent
+ * @package phing.types
+ */
+class AbstractFileSet extends DataType implements SelectorContainer {
+
+ // These vars are public for cloning purposes
+
+ /**
+ * @var boolean
+ */
+ public $useDefaultExcludes = true;
+
+ /**
+ * @var PatternSet
+ */
+ public $defaultPatterns;
+
+ public $additionalPatterns = array();
+ public $dir;
+ public $isCaseSensitive = true;
+ public $selectors = array();
+
+ function __construct($fileset = null) {
+ if ($fileset !== null && ($fileset instanceof FileSet)) {
+ $this->dir = $fileset->dir;
+ $this->defaultPatterns = $fileset->defaultPatterns;
+ $this->additionalPatterns = $fileset->additionalPatterns;
+ $this->useDefaultExcludes = $fileset->useDefaultExcludes;
+ $this->isCaseSensitive = $fileset->isCaseSensitive;
+ $this->selectors = $fileset->selectors;
+ }
+ $this->defaultPatterns = new PatternSet();
+ }
+
+
+ /**
+ * Makes this instance in effect a reference to another PatternSet
+ * instance.
+ * You must not set another attribute or nest elements inside
+ * this element if you make it a reference.
+ */
+ function setRefid(Reference $r) {
+ if ((isset($this->dir) && !is_null($this->dir)) || $this->defaultPatterns->hasPatterns()) {
+ throw $this->tooManyAttributes();
+ }
+ if (!empty($this->additionalPatterns)) {
+ throw $this->noChildrenAllowed();
+ }
+ if (!empty($this->selectors)) {
+ throw $this->noChildrenAllowed();
+ }
+ parent::setRefid($r);
+ }
+
+
+ function setDir($dir) {
+ if ($this->isReference()) {
+ throw $this->tooManyAttributes();
+ }
+ if ($dir instanceof PhingFile) {
+ $dir = $dir->getPath();
+ }
+ $this->dir = new PhingFile((string) $dir);
+ }
+
+
+ function getDir(Project $p) {
+ if ($this->isReference()) {
+ return $this->getRef($p)->getDir($p);
+ }
+ return $this->dir;
+ }
+
+
+ function createPatternSet() {
+ if ($this->isReference()) {
+ throw $this->noChildrenAllowed();
+ }
+ $num = array_push($this->additionalPatterns, new PatternSet());
+ return $this->additionalPatterns[$num-1];
+ }
+
+ /**
+ * add a name entry on the include list
+ */
+ function createInclude() {
+ if ($this->isReference()) {
+ throw $this->noChildrenAllowed();
+ }
+ return $this->defaultPatterns->createInclude();
+ }
+
+ /**
+ * add a name entry on the include files list
+ */
+ function createIncludesFile() {
+ if ($this->isReference()) {
+ throw $this->noChildrenAllowed();
+ }
+ return $this->defaultPatterns->createIncludesFile();
+ }
+
+ /**
+ * add a name entry on the exclude list
+ */
+ function createExclude() {
+ if ($this->isReference()) {
+ throw $this->noChildrenAllowed();
+ }
+ return $this->defaultPatterns->createExclude();
+ }
+
+ /**
+ * add a name entry on the include files list
+ */
+ function createExcludesFile() {
+ if ($this->isReference()) {
+ throw $this->noChildrenAllowed();
+ return;
+ }
+ return $this->defaultPatterns->createExcludesFile();
+ }
+
+ /**
+ * Sets the set of include patterns. Patterns may be separated by a comma
+ * or a space.
+ */
+ function setIncludes($includes) {
+ if ($this->isReference()) {
+ throw $this->tooManyAttributes();
+ }
+ $this->defaultPatterns->setIncludes($includes);
+ }
+
+ /**
+ * Sets the set of exclude patterns. Patterns may be separated by a comma
+ * or a space.
+ */
+ function setExcludes($excludes) {
+ if ($this->isReference()) {
+ throw $this->tooManyAttributes();
+ }
+ $this->defaultPatterns->setExcludes($excludes);
+ }
+
+ /**
+ * Sets the name of the file containing the includes patterns.
+ *
+ * @param $incl The file to fetch the include patterns from.
+ * @throws BE
+ */
+ function setIncludesfile($incl) {
+ if ($this->isReference()) {
+ throw $this->tooManyAttributes();
+ }
+ $this->defaultPatterns->setIncludesfile($incl);
+ }
+
+ /**
+ * Sets the name of the file containing the includes patterns.
+ *
+ * @param $excl The file to fetch the exclude patterns from.
+ * @throws BE
+ */
+ function setExcludesfile($excl) {
+ if ($this->isReference()) {
+ throw $this->tooManyAttributes();
+ }
+ $this->defaultPatterns->setExcludesfile($excl);
+ }
+
+ /**
+ * Sets whether default exclusions should be used or not.
+ *
+ * @param $useDefaultExcludes "true"|"on"|"yes" when default exclusions
+ * should be used, "false"|"off"|"no" when they
+ * shouldn't be used.
+ */
+ function setDefaultexcludes($useDefaultExcludes) {
+ if ($this->isReference()) {
+ throw $this->tooManyAttributes();
+ }
+ $this->useDefaultExcludes = $useDefaultExcludes;
+ }
+
+ /**
+ * Sets case sensitivity of the file system
+ */
+ function setCaseSensitive($isCaseSensitive) {
+ $this->isCaseSensitive = $isCaseSensitive;
+ }
+
+ /** returns a reference to the dirscanner object belonging to this fileset */
+ function getDirectoryScanner(Project $p) {
+ if ($this->isReference()) {
+ $o = $this->getRef($p);
+ return $o->getDirectoryScanner($p);
+ }
+
+ if ($this->dir === null) {
+ throw new BuildException("No directory specified for fileset.");
+ }
+ if (!$this->dir->exists()) {
+ throw new BuildException("Directory ".$this->dir->getAbsolutePath()." not found.");
+ }
+ if (!$this->dir->isDirectory()) {
+ throw new BuildException($this->dir->getAbsolutePath()." is not a directory.");
+ }
+ $ds = new DirectoryScanner();
+ $this->setupDirectoryScanner($ds, $p);
+ $ds->scan();
+ return $ds;
+ }
+
+ /** feed dirscanner with infos defined by this fileset */
+ protected function setupDirectoryScanner(DirectoryScanner $ds, Project $p) {
+ if ($ds === null) {
+ throw new Exception("DirectoryScanner cannot be null");
+ }
+ // FIXME - pass dir directly wehn dirscanner supports File
+ $ds->setBasedir($this->dir->getPath());
+
+ foreach($this->additionalPatterns as $addPattern) {
+ $this->defaultPatterns->append($addPattern, $p);
+ }
+
+ $ds->setIncludes($this->defaultPatterns->getIncludePatterns($p));
+ $ds->setExcludes($this->defaultPatterns->getExcludePatterns($p));
+
+ $p->log("FileSet: Setup file scanner in dir " . $this->dir->__toString() . " with " . $this->defaultPatterns->toString(), PROJECT_MSG_DEBUG);
+
+ if ($ds instanceof SelectorScanner) {
+ $ds->setSelectors($this->getSelectors($p));
+ }
+
+ if ($this->useDefaultExcludes) {
+ $ds->addDefaultExcludes();
+ }
+ $ds->setCaseSensitive($this->isCaseSensitive);
+ }
+
+
+ /**
+ * Performs the check for circular references and returns the
+ * referenced FileSet.
+ */
+ function getRef(Project $p) {
+ if (!$this->checked) {
+ $stk = array();
+ array_push($stk, $this);
+ $this->dieOnCircularReference($stk, $p);
+ }
+
+ $o = $this->ref->getReferencedObject($p);
+ if (!($o instanceof FileSet)) {
+ $msg = $this->ref->getRefId()." doesn't denote a fileset";
+ throw new BuildException($msg);
+ } else {
+ return $o;
+ }
+ }
+
+ // SelectorContainer methods
+
+ /**
+ * Indicates whether there are any selectors here.
+ *
+ * @return boolean Whether any selectors are in this container
+ */
+ public function hasSelectors() {
+ if ($this->isReference() && $this->getProject() !== null) {
+ return $this->getRef($this->getProject())->hasSelectors();
+ }
+ return !empty($this->selectors);
+ }
+
+ /**
+ * Indicates whether there are any patterns here.
+ *
+ * @return boolean Whether any patterns are in this container.
+ */
+ public function hasPatterns() {
+
+ if ($this->isReference() && $this->getProject() !== null) {
+ return $this->getRef($this->getProject())->hasPatterns();
+ }
+
+ if ($this->defaultPatterns->hasPatterns($this->getProject())) {
+ return true;
+ }
+
+ for($i=0,$size=count($this->additionalPatterns); $i < $size; $i++) {
+ $ps = $this->additionalPatterns[$i];
+ if ($ps->hasPatterns($this->getProject())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Gives the count of the number of selectors in this container
+ *
+ * @return int The number of selectors in this container
+ */
+ public function selectorCount() {
+ if ($this->isReference() && $this->getProject() !== null) {
+ try {
+ return $this->getRef($this->getProject())->selectorCount();
+ } catch (Exception $e) {
+ throw $e;
+ }
+ }
+ return count($this->selectors);
+ }
+
+ /**
+ * Returns the set of selectors as an array.
+ *
+ * @return an array of selectors in this container
+ */
+ public function getSelectors(Project $p) {
+ if ($this->isReference()) {
+ return $this->getRef($p)->getSelectors($p);
+ } else {
+ // *copy* selectors
+ $result = array();
+ for($i=0,$size=count($this->selectors); $i < $size; $i++) {
+ $result[] = clone $this->selectors[$i];
+ }
+ return $result;
+ }
+ }
+
+ /**
+ * Returns an array for accessing the set of selectors.
+ *
+ * @return array The array of selectors
+ */
+ public function selectorElements() {
+ if ($this->isReference() && $this->getProject() !== null) {
+ return $this->getRef($this->getProject())->selectorElements();
+ }
+ return $this->selectors;
+ }
+
+ /**
+ * Add a new selector into this container.
+ *
+ * @param selector the new selector to add
+ */
+ public function appendSelector(FileSelector $selector) {
+ if ($this->isReference()) {
+ throw $this->noChildrenAllowed();
+ }
+ $this->selectors[] = $selector;
+ }
+
+ /* Methods below all add specific selectors */
+
+ /**
+ * add a "Select" selector entry on the selector list
+ */
+ public function createSelector() {
+ $o = new SelectSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add an "And" selector entry on the selector list
+ */
+ public function createAnd() {
+ $o = new AndSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add an "Or" selector entry on the selector list
+ */
+ public function createOr() {
+ $o = new OrSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a "Not" selector entry on the selector list
+ */
+ public function createNot() {
+ $o = new NotSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a "None" selector entry on the selector list
+ */
+ public function createNone() {
+ $o = new NoneSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a majority selector entry on the selector list
+ */
+ public function createMajority() {
+ $o = new MajoritySelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a selector date entry on the selector list
+ */
+ public function createDate() {
+ $o = new DateSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a selector size entry on the selector list
+ */
+ public function createSize() {
+ $o = new SizeSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a selector filename entry on the selector list
+ */
+ public function createFilename() {
+ $o = new FilenameSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add an extended selector entry on the selector list
+ */
+ public function createCustom() {
+ $o = new ExtendSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a contains selector entry on the selector list
+ */
+ public function createContains() {
+ $o = new ContainsSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a contains selector entry on the selector list
+ */
+ public function createContainsRegexp() {
+ $o = new ContainsRegexpSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a present selector entry on the selector list
+ */
+ public function createPresent() {
+ $o = new PresentSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a depth selector entry on the selector list
+ */
+ public function createDepth() {
+ $o = new DepthSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a depends selector entry on the selector list
+ */
+ public function createDepend() {
+ $o = new DependSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a type selector entry on the selector list
+ */
+ public function createType() {
+ $o = new TypeSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+}
diff --git a/buildscripts/phing/classes/phing/types/Commandline.php b/buildscripts/phing/classes/phing/types/Commandline.php
new file mode 100644
index 00000000..877179d0
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/Commandline.php
@@ -0,0 +1,467 @@
+<?php
+/*
+ * $Id: Commandline.php,v 1.11 2005/05/26 13:10:53 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+
+/**
+ * Commandline objects help handling command lines specifying processes to
+ * execute.
+ *
+ * The class can be used to define a command line as nested elements or as a
+ * helper to define a command line by an application.
+ * <p>
+ * <code>
+ * &lt;someelement&gt;<br>
+ * &nbsp;&nbsp;&lt;acommandline executable="/executable/to/run"&gt;<br>
+ * &nbsp;&nbsp;&nbsp;&nbsp;&lt;argument value="argument 1" /&gt;<br>
+ * &nbsp;&nbsp;&nbsp;&nbsp;&lt;argument line="argument_1 argument_2 argument_3" /&gt;<br>
+ * &nbsp;&nbsp;&nbsp;&nbsp;&lt;argument value="argument 4" /&gt;<br>
+ * &nbsp;&nbsp;&lt;/acommandline&gt;<br>
+ * &lt;/someelement&gt;<br>
+ * </code>
+ * The element <code>someelement</code> must provide a method
+ * <code>createAcommandline</code> which returns an instance of this class.
+ *
+ * @author thomas.haas@softwired-inc.com
+ * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
+ */
+class Commandline {
+
+ /**
+ * @var array CommandlineArguments[]
+ */
+ public $arguments = array(); // public so "inner" class can access
+
+ /**
+ * Full path (if not on %PATH% env var) to executable program.
+ * @var string
+ */
+ public $executable; // public so "inner" class can access
+
+ const DISCLAIMER = "The ' characters around the executable and arguments are not part of the command.";
+
+ public function __construct($to_process = null) {
+ if ($to_process !== null) {
+ $tmp = $this->translateCommandline($to_process);
+ if ($tmp) {
+ $this->setExecutable(array_shift($tmp)); // removes first el
+ foreach($tmp as $arg) { // iterate through remaining elements
+ $this->createArgument()->setValue($arg);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Creates an argument object and adds it to our list of args.
+ *
+ * <p>Each commandline object has at most one instance of the
+ * argument class.</p>
+ *
+ * @param boolean $insertAtStart if true, the argument is inserted at the
+ * beginning of the list of args, otherwise it is appended.
+ * @return CommandlineArgument
+ */
+ public function createArgument($insertAtStart = false) {
+ $argument = new CommandlineArgument($this);
+ if ($insertAtStart) {
+ array_unshift($this->arguments, $argument);
+ } else {
+ array_push($this->arguments, $argument);
+ }
+ return $argument;
+ }
+
+ /**
+ * Sets the executable to run.
+ */
+ public function setExecutable($executable) {
+ if (!$executable) {
+ return;
+ }
+ $this->executable = $executable;
+ $this->executable = strtr($this->executable, '/', DIRECTORY_SEPARATOR);
+ $this->executable = strtr($this->executable, '\\', DIRECTORY_SEPARATOR);
+ }
+
+ public function getExecutable() {
+ return $this->executable;
+ }
+
+ public function addArguments($line) {
+ foreach($line as $arg) {
+ $this->createArgument()->setValue($arg);
+ }
+ }
+
+ /**
+ * Returns the executable and all defined arguments.
+ * @return array
+ */
+ public function getCommandline() {
+ $args = $this->getArguments();
+ if ($this->executable === null) {
+ return $args;
+ }
+ return array_merge(array($this->executable), $args);
+ }
+
+
+ /**
+ * Returns all arguments defined by <code>addLine</code>,
+ * <code>addValue</code> or the argument object.
+ */
+ public function getArguments() {
+ $result = array();
+ foreach($this->arguments as $arg) {
+ $parts = $arg->getParts();
+ if ($parts !== null) {
+ foreach($parts as $part) {
+ $result[] = $part;
+ }
+ }
+ }
+ return $result;
+ }
+
+ public function __toString() {
+ return self::toString($this->getCommandline());
+ }
+
+ /**
+ * Put quotes around the given String if necessary.
+ *
+ * <p>If the argument doesn't include spaces or quotes, return it
+ * as is. If it contains double quotes, use single quotes - else
+ * surround the argument by double quotes.</p>
+ *
+ * @exception BuildException if the argument contains both, single
+ * and double quotes.
+ */
+ public static function quoteArgument($argument) {
+ if (strpos($argument, "\"") !== false) {
+ if (strpos($argument, "'") !== false) {
+ throw new BuildException("Can't handle single and double quotes in same argument");
+ } else {
+ return escapeshellarg($argument);
+ }
+ } elseif (strpos($argument, "'") !== false || strpos($argument, " ") !== false) {
+ return escapeshellarg($argument);
+ //return '\"' . $argument . '\"';
+ } else {
+ return $argument;
+ }
+ }
+
+ /**
+ * Quotes the parts of the given array in way that makes them
+ * usable as command line arguments.
+ */
+ public static function toString($lines) {
+ // empty path return empty string
+ if (!$lines) {
+ return "";
+ }
+
+ // path containing one or more elements
+ $result = "";
+ for ($i = 0, $len=count($lines); $i < $len; $i++) {
+ if ($i > 0) {
+ $result .= ' ';
+ }
+ $result .= self::quoteArgument($lines[$i]);
+ }
+ return $result;
+ }
+
+ /**
+ *
+ * @param string $to_process
+ * @return array
+ */
+ public static function translateCommandline($to_process) {
+
+ if (!$to_process) {
+ return array();
+ }
+
+ // parse with a simple finite state machine
+
+ $normal = 0;
+ $inQuote = 1;
+ $inDoubleQuote = 2;
+
+ $state = $normal;
+ $args = array();
+ $current = "";
+ $lastTokenHasBeenQuoted = false;
+
+ $tok = strtok($to_process, "");
+ $tokens = preg_split('/(["\' ])/', $to_process, -1, PREG_SPLIT_DELIM_CAPTURE);
+ while(($nextTok = array_shift($tokens)) !== null) {
+ switch ($state) {
+ case $inQuote:
+ if ("'" == $nextTok) {
+ $lastTokenHasBeenQuoted = true;
+ $state = $normal;
+ } else {
+ $current .= $nextTok;
+ }
+ break;
+ case $inDoubleQuote:
+ if ("\"" == $nextTok) {
+ $lastTokenHasBeenQuoted = true;
+ $state = $normal;
+ } else {
+ $current .= $nextTok;
+ }
+ break;
+ default:
+ if ("'" == $nextTok) {
+ $state = $inQuote;
+ } elseif ("\"" == $nextTok) {
+ $state = $inDoubleQuote;
+ } elseif (" " == $nextTok) {
+ if ($lastTokenHasBeenQuoted || strlen($current) != 0) {
+ $args[] = $current;
+ $current = "";
+ }
+ } else {
+ $current .= $nextTok;
+ }
+ $lastTokenHasBeenQuoted = false;
+ break;
+ }
+ }
+
+ if ($lastTokenHasBeenQuoted || strlen($current) != 0) {
+ $args[] = $current;
+ }
+
+ if ($state == $inQuote || $state == $inDoubleQuote) {
+ throw new BuildException("unbalanced quotes in " . $to_process);
+ }
+
+ return $args;
+ }
+
+ /**
+ * @return int Number of components in current commandline.
+ */
+ public function size() {
+ return count($this->getCommandline());
+ }
+
+ public function __copy() {
+ $c = new Commandline();
+ $c->setExecutable($this->executable);
+ $c->addArguments($this->getArguments());
+ return $c;
+ }
+
+ /**
+ * Clear out the whole command line. */
+ public function clear() {
+ $this->executable = null;
+ $this->arguments->removeAllElements();
+ }
+
+ /**
+ * Clear out the arguments but leave the executable in place for
+ * another operation.
+ */
+ public function clearArgs() {
+ $this->arguments = array();
+ }
+
+ /**
+ * Return a marker.
+ *
+ * <p>This marker can be used to locate a position on the
+ * commandline - to insert something for example - when all
+ * parameters have been set.</p>
+ * @return CommandlineMarker
+ */
+ public function createMarker() {
+ return new CommandlineMarker($this, count($this->arguments));
+ }
+
+ /**
+ * Returns a String that describes the command and arguments
+ * suitable for verbose output before a call to
+ * <code>Runtime.exec(String[])<code>.
+ *
+ * <p>This method assumes that the first entry in the array is the
+ * executable to run.</p>
+ * @param array $args CommandlineArgument[] to use
+ * @return string
+ */
+ public function describeCommand($args = null) {
+
+ if ($args === null) {
+ $args = $this->getCommandline();
+ }
+
+ if (!$args) {
+ return "";
+ }
+
+ $buf = "Executing '";
+ $buf .= $args[0];
+ $buf .= "'";
+ if (count($args) > 0) {
+ $buf .= " with ";
+ $buf .= $this->describeArguments($args, 1);
+ } else {
+ $buf .= self::DISCLAIMER;
+ }
+ return $buf;
+ }
+
+ /**
+ * Returns a String that describes the arguments suitable for
+ * verbose output before a call to
+ * <code>Runtime.exec(String[])<code>
+ * @param $args arguments to use (default is to use current class args)
+ * @param $offset ignore entries before this index
+ * @return string
+ */
+ protected function describeArguments($args = null, $offset = 0) {
+ if ($args === null) {
+ $args = $this->getArguments();
+ }
+
+ if ($args === null || count($args) <= $offset) {
+ return "";
+ }
+
+ $buf = "argument";
+ if (count($args) > $offset) {
+ $buf .= "s";
+ }
+ $buf .= ":" . Phing::getProperty("line.separator");
+ for ($i = $offset, $alen=count($args); $i < $alen; $i++) {
+ $buf .= "'" . $args[$i] . "'" . Phing::getProperty("line.separator");
+ }
+ $buf .= self::DISCLAIMER;
+ return $buf;
+ }
+}
+
+
+/**
+ * "Inner" class used for nested xml command line definitions.
+ */
+class CommandlineArgument {
+
+ private $parts = array();
+ private $outer;
+
+ public function __construct(Commandline $outer) {
+ $this->outer = $outer;
+ }
+
+ /**
+ * Sets a single commandline argument.
+ *
+ * @param string $value a single commandline argument.
+ */
+ public function setValue($value) {
+ $this->parts = array($value);
+ }
+
+ /**
+ * Line to split into several commandline arguments.
+ *
+ * @param line line to split into several commandline arguments
+ */
+ public function setLine($line) {
+ if ($line === null) {
+ return;
+ }
+ $this->parts = $this->outer->translateCommandline($line);
+ }
+
+ /**
+ * Sets a single commandline argument and treats it like a
+ * PATH - ensures the right separator for the local platform
+ * is used.
+ *
+ * @param value a single commandline argument.
+ */
+ public function setPath($value) {
+ $this->parts = array( (string) $value );
+ }
+
+ /**
+ * Sets a single commandline argument to the absolute filename
+ * of the given file.
+ *
+ * @param value a single commandline argument.
+ */
+ public function setFile(PhingFile $value) {
+ $this->parts = array($value->getAbsolutePath());
+ }
+
+ /**
+ * Returns the parts this Argument consists of.
+ * @return array string[]
+ */
+ public function getParts() {
+ return $this->parts;
+ }
+}
+
+/**
+ * Class to keep track of the position of an Argument.
+ */
+// <p>This class is there to support the srcfile and targetfile
+// elements of &lt;execon&gt; and &lt;transform&gt; - don't know
+// whether there might be additional use cases.</p> --SB
+class CommandlineMarker {
+
+ private $position;
+ private $realPos = -1;
+ private $outer;
+
+ public function __construct(Comandline $outer, $position) {
+ $this->outer = $outer;
+ $this->position = $position;
+ }
+
+ /**
+ * Return the number of arguments that preceeded this marker.
+ *
+ * <p>The name of the executable - if set - is counted as the
+ * very first argument.</p>
+ */
+ public function getPosition() {
+ if ($this->realPos == -1) {
+ $realPos = ($this->outer->executable === null ? 0 : 1);
+ for ($i = 0; $i < $position; $i++) {
+ $arg = $this->arguments[$i];
+ $realPos += count($arg->getParts());
+ }
+ }
+ return $this->realPos;
+ }
+}
+
diff --git a/buildscripts/phing/classes/phing/types/DataType.php b/buildscripts/phing/classes/phing/types/DataType.php
new file mode 100644
index 00000000..2c06b80d
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/DataType.php
@@ -0,0 +1,182 @@
+<?php
+/*
+ * $Id: DataType.php,v 1.9 2005/11/02 13:55:34 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/ProjectComponent.php';
+include_once 'phing/BuildException.php';
+
+/**
+ * Base class for those classes that can appear inside the build file
+ * as stand alone data types.
+ *
+ * This class handles the common description attribute and provides
+ * a default implementation for reference handling and checking for
+ * circular references that is appropriate for types that can not be
+ * nested inside elements of the same type (i.e. patternset but not path)
+ *
+ * @package phing.types
+ */
+class DataType extends ProjectComponent {
+
+ /** The descriptin the user has set. */
+ public $description = null;
+
+ /** Value to the refid attribute. Type of Reference*/
+ public $ref = null;
+
+ /**
+ * Are we sure we don't hold circular references?
+ *
+ * Subclasses are responsible for setting this value to false
+ * if we'd need to investigate this condition (usually because a
+ * child element has been added that is a subclass of DataType).
+ * @var boolean
+ */
+ protected $checked = true;
+
+ /**
+ * Sets a description of the current data type. It will be useful
+ * in commenting what we are doing.
+ */
+ function setDescription($desc) {
+ $this->description = (string) $desc;
+ }
+
+ /** Return the description for the current data type. */
+ function getDescription() {
+ return $this->description;
+ }
+
+ /** Has the refid attribute of this element been set? */
+ function isReference() {
+ return ($this->ref !== null);
+ }
+
+ /**
+ * Set the value of the refid attribute.
+ *
+ * Subclasses may need to check whether any other attributes
+ * have been set as well or child elements have been created and
+ * thus override this method. if they do they must call parent::setRefid()
+ *
+ * @param Reference $r
+ * @return void
+ */
+ function setRefid(Reference $r) {
+ $this->ref = $r;
+ $this->checked = false;
+ }
+
+ /**
+ * Check to see whether any DataType we hold references to is
+ * included in the Stack (which holds all DataType instances that
+ * directly or indirectly reference this instance, including this
+ * instance itself).
+ *
+ * If one is included, throw a BuildException created by circularReference
+ *
+ * This implementation is appropriate only for a DataType that
+ * cannot hold other DataTypes as children.
+ *
+ * The general contract of this method is that it shouldn't do
+ * anything if checked is true and set it to true on exit.
+ */
+ function dieOnCircularReference(&$stk, Project $p) {
+ if ($this->checked || !$this->isReference()) {
+ return;
+ }
+
+ $o = $this->ref->getReferencedObject($p);
+
+ if ($o instanceof DataType) {
+
+ // TESTME - make sure that in_array() works just as well here
+ //
+ // check if reference is in stack
+ //$contains = false;
+ //for ($i=0, $size=count($stk); $i < $size; $i++) {
+ // if ($stk[$i] === $o) {
+ // $contains = true;
+ // break;
+ // }
+ //}
+
+ if (in_array($o, $stk, true)) {
+ // throw build exception
+ throw $this->circularReference();
+ } else {
+ array_push($stk, $o);
+ $o->dieOnCircularReference($stk, $p);
+ array_pop($stk);
+ }
+ }
+ $this->checked = true;
+ }
+
+ /** Performs the check for circular references and returns the referenced object. */
+ function getCheckedRef($requiredClass, $dataTypeName) {
+
+ if (!$this->checked) {
+ // should be in stack
+ $stk = array();
+ $stk[] = $this;
+ $this->dieOnCircularReference($stk, $this->getProject());
+ }
+
+ $o = $this->ref->getReferencedObject($this->getProject());
+ if (!($o instanceof $requiredClass) ) {
+ throw new BuildException($this->ref->getRefId()." doesn't denote a " . $dataTypeName);
+ } else {
+ return $o;
+ }
+ }
+
+ /**
+ * Creates an exception that indicates that refid has to be the
+ * only attribute if it is set.
+ */
+ function tooManyAttributes() {
+ return new BuildException( "You must not specify more than one attribute when using refid" );
+ }
+
+ /**
+ * Creates an exception that indicates that this XML element must
+ * not have child elements if the refid attribute is set.
+ */
+ function noChildrenAllowed() {
+ return new BuildException("You must not specify nested elements when using refid");
+ }
+
+ /**
+ * Creates an exception that indicates the user has generated a
+ * loop of data types referencing each other.
+ */
+ function circularReference() {
+ return new BuildException("This data type contains a circular reference.");
+ }
+
+ /**
+ * Template method being called when the data type has been
+ * parsed completely.
+ * @return void
+ */
+ function parsingComplete() {}
+}
+
diff --git a/buildscripts/phing/classes/phing/types/Description.php b/buildscripts/phing/classes/phing/types/Description.php
new file mode 100644
index 00000000..e69f8da4
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/Description.php
@@ -0,0 +1,53 @@
+<?php
+
+/*
+ * $Id: Description.php,v 1.4 2003/12/24 12:38:42 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * Description is used to provide a project-wide description element
+ * (that is, a description that applies to a buildfile as a whole).
+ * If present, the &lt;description&gt; element is printed out before the
+ * target descriptions.
+ *
+ * Description has no attributes, only text. There can only be one
+ * project description per project. A second description element will
+ * overwrite the first.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Craeg Strong <cstrong@arielpartners.com> (Ant)
+ * @package phing.types
+ */
+class Description extends DataType {
+
+ /**
+ * Adds descriptive text to the project.
+ *
+ * @return void
+ */
+ public function addText($text) {
+ $currentDescription = $this->project->getDescription();
+ if ($currentDescription === null) {
+ $this->project->setDescription($text);
+ } else {
+ $this->project->setDescription($currentDescription . $text);
+ }
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/types/DirSet.php b/buildscripts/phing/classes/phing/types/DirSet.php
new file mode 100644
index 00000000..45bcc636
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/DirSet.php
@@ -0,0 +1,49 @@
+<?php
+
+/*
+ * $Id: DirSet.php,v 1.3 2003/11/19 05:48:30 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/types/AbstractFileSet.php';
+
+/**
+ * Subclass as hint for supporting tasks that the included directories
+ * instead of files should be used.
+ *
+ * @package phing.types
+ */
+class DirSet extends AbstractFileSet {
+
+ public function __construct($dirset = null) {
+ parent::__construct($dirset);
+ }
+
+ /**
+ * Return a DirSet that has the same basedir and same patternsets
+ * as this one.
+ */
+ public function __clone() {
+ if ($this->isReference()) {
+ return new DirSet($this->getRef($this->getProject()));
+ } else {
+ return new DirSet($this);
+ }
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/types/FileList.php b/buildscripts/phing/classes/phing/types/FileList.php
new file mode 100644
index 00000000..1ec1273f
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/FileList.php
@@ -0,0 +1,223 @@
+<?php
+/*
+ * $Id: FileList.php,v 1.10 2005/11/01 15:26:09 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/types/DataType.php';
+include_once 'phing/system/io/PhingFile.php';
+
+/**
+ * FileList represents an explicitly named list of files. FileLists
+ * are useful when you want to capture a list of files regardless of
+ * whether they currently exist.
+ *
+ * <filelist
+ * id="docfiles"
+ * dir="${phing.docs.dir}"
+ * files="chapters/Installation.html,chapters/Setup.html"/>
+ *
+ * OR
+ *
+ * <filelist
+ * dir="${doc.src.dir}"
+ * listfile="${phing.docs.dir}/PhingGuide.book"/>
+ *
+ * (or a mixture of files="" and listfile="" can be used)
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @version $Revision: 1.10 $
+ * @package phing.types
+ */
+class FileList extends DataType {
+
+ // public for "cloning" purposes
+
+ /** Array containing all filenames. */
+ public $filenames = array();
+
+ /** Base directory for this file list. */
+ public $dir;
+
+ /** PhingFile that contains a list of files (one per line). */
+ public $listfile;
+
+ /**
+ * Construct a new FileList.
+ * @param array $filelist;
+ */
+ function __construct($filelist = null) {
+ if ($filelist !== null) {
+ $this->dir = $filelist->dir;
+ $this->filenames = $filelist->filenames;
+ $this->listfile = $filelist->listfile;
+ }
+ }
+
+ /**
+ * Makes this instance in effect a reference to another FileList
+ * instance.
+ */
+ function setRefid(Reference $r) {
+ if ($this->dir !== null || count($this->filenames) !== 0) {
+ throw $this->tooManyAttributes();
+ }
+ parent::setRefid($r);
+ }
+
+ /**
+ * Base directory for files in list.
+ * @param PhingFile $dir
+ */
+ function setDir(PhingFile $dir) {
+ if ($this->isReference()) {
+ throw $this->tooManyAttributes();
+ }
+ if (!($dir instanceof PhingFile)) {
+ $dir = new PhingFile($dir);
+ }
+ $this->dir = $dir;
+ }
+
+ /**
+ * Get the basedir for files in list.
+ * @return PhingFile
+ */
+ function getDir(Project $p) {
+ if ($this->isReference()) {
+ $ref = $this->getRef($p);
+ return $ref->getDir($p);
+ }
+ return $this->dir;
+ }
+
+ /**
+ * Set the array of files in list.
+ * @param array $filenames
+ */
+ function setFiles($filenames) {
+ if ($this->isReference()) {
+ throw $this->tooManyAttributes();
+ }
+ if (!empty($filenames)) {
+ $tok = strtok($filenames, ", \t\n\r");
+ while ($tok !== false) {
+ $fname = trim($tok);
+ if ($fname !== "") {
+ $this->filenames[] = $tok;
+ }
+ $tok = strtok(", \t\n\r");
+ }
+ }
+ }
+
+ /**
+ * Sets a source "list" file that contains filenames to add -- one per line.
+ * @param string $file
+ */
+ function setListFile($file) {
+ if ($this->isReference()) {
+ throw $this->tooManyAttributes();
+ }
+ if (!($file instanceof PhingFile)) {
+ $file = new PhingFile($file);
+ }
+ $this->listfile = $file;
+ }
+
+ /**
+ * Get the source "list" file that contains file names.
+ * @return PhingFile
+ */
+ function getListFile() {
+ if ($this->isReference()) {
+ $ref = $this->getRef($p);
+ return $ref->getListFile($p);
+ }
+ return $this->listfile;
+ }
+
+ /**
+ * Returns the list of files represented by this FileList.
+ * @param Project $p
+ * @return array
+ */
+ function getFiles(Project $p) {
+
+ if ($this->isReference()) {
+ $ret = $this->getRef($p);
+ $ret = $ret->getFiles($p);
+ return $ret;
+ }
+
+ if ($this->listfile !== null) {
+ $this->readListFile($p);
+ }
+
+ return $this->filenames;
+ }
+
+
+ /**
+ * Performs the check for circular references and returns the
+ * referenced FileSet.
+ * @param Project $p
+ */
+ function getRef(Project $p) {
+ if (!$this->checked) {
+ $stk = array();
+ array_push($stk, $this);
+ $this->dieOnCircularReference($stk, $p);
+ }
+
+ $o = $this->ref->getReferencedObject($p);
+ if (!($o instanceof FileList)) {
+ throw new BuildException($this->ref->getRefId()." doesn't denote a filelist");
+ } else {
+ return $o;
+ }
+ }
+
+ /**
+ * Reads file names from a file and adds them to the files array.
+ * @param Project $p
+ */
+ private function readListFile(Project $p) {
+ $listReader = null;
+ try {
+ // Get a FileReader
+ $listReader = new BufferedReader(new FileReader($this->listfile));
+
+ $line = $listReader->readLine();
+ while ($line !== null) {
+ if (!empty($line)) {
+ $line = $p->replaceProperties($line);
+ $this->filenames[] = trim($line);
+ }
+ $line = $listReader->readLine();
+ }
+ } catch (Exception $e) {
+ if ($listReader) $listReader->close();
+ throw new BuildException("An error occured while reading from list file " . $this->listfile->__toString() . ": " . $e->getMessage());
+ }
+
+ $listReader->close();
+ }
+
+}
+
diff --git a/buildscripts/phing/classes/phing/types/FileSet.php b/buildscripts/phing/classes/phing/types/FileSet.php
new file mode 100644
index 00000000..8cfb54dc
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/FileSet.php
@@ -0,0 +1,56 @@
+<?php
+
+/*
+ * $Id: FileSet.php,v 1.5 2003/12/24 12:38:42 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/types/AbstractFileSet.php';
+
+/**
+ * Moved out of MatchingTask to make it a standalone object that could
+ * be referenced (by scripts for example).
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Arnout J. Kuiper <ajkuiper@wxs.nl> (Ant)
+ * @author Stefano Mazzocchi <stefano@apache.org> (Ant)
+ * @author Sam Ruby <rubys@us.ibm.com> (Ant)
+ * @author Jon S. Stevens <jon@clearink.com> (Ant)
+ * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant)
+ * @author Magesh Umasankar (Ant)
+ * @package phing.types
+ */
+class FileSet extends AbstractFileSet {
+
+ function __construct($fileset = null) {
+ parent::__construct($fileset);
+ }
+
+ /**
+ * Return a FileSet that has the same basedir and same patternsets
+ * as this one.
+ */
+ public function __clone() {
+ if ($this->isReference()) {
+ return new FileSet($this->getRef($this->getProject()));
+ } else {
+ return new FileSet($this);
+ }
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/types/FilterChain.php b/buildscripts/phing/classes/phing/types/FilterChain.php
new file mode 100644
index 00000000..4f2d702b
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/FilterChain.php
@@ -0,0 +1,164 @@
+<?php
+/*
+ * $Id: FilterChain.php,v 1.11 2005/12/08 16:03:49 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/types/DataType.php';
+include_once 'phing/filters/HeadFilter.php';
+include_once 'phing/filters/TailFilter.php';
+include_once 'phing/filters/LineContains.php';
+include_once 'phing/filters/LineContainsRegexp.php';
+include_once 'phing/filters/ExpandProperties.php';
+include_once 'phing/filters/PrefixLines.php';
+include_once 'phing/filters/ReplaceRegexp.php';
+include_once 'phing/filters/ReplaceTokens.php';
+include_once 'phing/filters/StripPhpComments.php';
+include_once 'phing/filters/StripLineBreaks.php';
+include_once 'phing/filters/StripLineComments.php';
+include_once 'phing/filters/TabToSpaces.php';
+include_once 'phing/filters/TidyFilter.php';
+include_once 'phing/filters/TranslateGettext.php';
+include_once 'phing/filters/XsltFilter.php';
+
+/*
+ * FilterChain may contain a chained set of filter readers.
+ *
+ * @author Yannick Lecaillez <yl@seasonfive.com>
+ * @version $Revision: 1.11 $
+ * @package phing.types
+ */
+class FilterChain extends DataType {
+
+ private $filterReaders = array();
+
+ function __construct(Project $project) {
+ $this->project = $project;
+ }
+
+ function getFilterReaders() {
+ return $this->filterReaders;
+ }
+
+ function addExpandProperties(ExpandProperties $o) {
+ $o->setProject($this->project);
+ $this->filterReaders[] = $o;
+ }
+
+ function addGettext(TranslateGettext $o) {
+ $o->setProject($this->project);
+ $this->filterReaders[] = $o;
+ }
+
+ function addHeadFilter(HeadFilter $o) {
+ $o->setProject($this->project);
+ $this->filterReaders[] = $o;
+ }
+
+ function addTailFilter(TailFilter $o) {
+ $o->setProject($this->project);
+ $this->filterReaders[] = $o;
+ }
+
+ function addLineContains(LineContains $o) {
+ $o->setProject($this->project);
+ $this->filterReaders[] = $o;
+ }
+
+ function addLineContainsRegExp(LineContainsRegExp $o) {
+ $o->setProject($this->project);
+ $this->filterReaders[] = $o;
+ }
+
+ function addPrefixLines(PrefixLines $o) {
+ $o->setProject($this->project);
+ $this->filterReaders[] = $o;
+ }
+
+ function addReplaceTokens(ReplaceTokens $o) {
+ $o->setProject($this->project);
+ $this->filterReaders[] = $o;
+ }
+
+ function addReplaceRegexp(ReplaceRegexp $o) {
+ $o->setProject($this->project);
+ $this->filterReaders[] = $o;
+ }
+
+ function addStripPhpComments(StripPhpComments $o) {
+ $o->setProject($this->project);
+ $this->filterReaders[] = $o;
+ }
+
+ function addStripLineBreaks(StripLineBreaks $o) {
+ $o->setProject($this->project);
+ $this->filterReaders[] = $o;
+ }
+
+ function addStripLineComments(StripLineComments $o) {
+ $o->setProject($this->project);
+ $this->filterReaders[] = $o;
+ }
+
+ function addTidyFilter(TidyFilter $o) {
+ $o->setProject($this->project);
+ $this->filterReaders[] = $o;
+ }
+
+ function addTabToSpaces(TabToSpaces $o) {
+ $o->setProject($this->project);
+ $this->filterReaders[] = $o;
+ }
+
+ function addXsltFilter(XsltFilter $o) {
+ $o->setProject($this->project);
+ $this->filterReaders[] = $o;
+ }
+
+ function addFilterReader(PhingFilterReader $o) {
+ $o->setProject($this->project);
+ $this->filterReaders[] = $o;
+ }
+
+ /*
+ * Makes this instance in effect a reference to another FilterChain
+ * instance.
+ *
+ * <p>You must not set another attribute or nest elements inside
+ * this element if you make it a reference.</p>
+ *
+ * @param r the reference to which this instance is associated
+ * @throw BuildException if this instance already has been configured.
+ */
+ function setRefid(Reference $r) {
+
+ if ( count($this->filterReaders) === 0 ) {
+ throw $this->tooManyAttributes();
+ }
+
+ // change this to get the objects from the other reference
+ $o = $r->getReferencedObject($this->getProject());
+ if ( $o instanceof FilterChain ) {
+ $this->filterReaders = $o->getFilterReaders();
+ } else {
+ throw new BuildException($r->getRefId()." doesn't refer to a FilterChain");
+ }
+ parent::setRefid($r);
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/types/Mapper.php b/buildscripts/phing/classes/phing/types/Mapper.php
new file mode 100644
index 00000000..f0df6d24
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/Mapper.php
@@ -0,0 +1,207 @@
+<?php
+/*
+ * $Id: Mapper.php,v 1.11 2004/03/15 17:11:16 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/types/DataType.php';
+include_once 'phing/types/Path.php';
+
+/**
+ * Filename Mapper maps source file name(s) to target file name(s).
+ *
+ * Built-in mappers can be accessed by specifying they "type" attribute:
+ * <code>
+ * <mapper type="glob" from="*.php" to="*.php.bak"/>
+ * </code>
+ * Custom mappers can be specified by providing a dot-path to a include_path-relative
+ * class:
+ * <code>
+ * <mapper classname="myapp.mappers.DevToProdMapper" from="*.php" to="*.php"/>
+ * <!-- maps all PHP files from development server to production server, for example -->
+ * </code>
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @package phing.types
+ */
+class Mapper extends DataType {
+
+ protected $type;
+ protected $classname;
+ protected $from;
+ protected $to;
+ protected $classpath;
+ protected $classpathId;
+
+
+ function __construct(Project $project) {
+ $this->project = $project;
+ }
+
+ /**
+ * Set the classpath to be used when searching for component being defined
+ *
+ * @param Path $classpath An Path object containing the classpath.
+ */
+ public function setClasspath(Path $classpath) {
+ if ($this->isReference()) {
+ throw $this->tooManyAttributes();
+ }
+ if ($this->classpath === null) {
+ $this->classpath = $classpath;
+ } else {
+ $this->classpath->append($classpath);
+ }
+ }
+
+ /**
+ * Create the classpath to be used when searching for component being defined
+ */
+ public function createClasspath() {
+ if ($this->isReference()) {
+ throw $this->tooManyAttributes();
+ }
+ if ($this->classpath === null) {
+ $this->classpath = new Path($this->project);
+ }
+ return $this->classpath->createPath();
+ }
+
+ /**
+ * Reference to a classpath to use when loading the files.
+ */
+ public function setClasspathRef(Reference $r) {
+ if ($this->isReference()) {
+ throw $this->tooManyAttributes();
+ }
+ $this->classpathId = $r->getRefId();
+ $this->createClasspath()->setRefid($r);
+ }
+
+ /** Set the type of FileNameMapper to use. */
+ function setType($type) {
+ if ($this->isReference()) {
+ throw $this->tooManyAttributes();
+ }
+ $this->type = $type;
+ }
+
+ /** Set the class name of the FileNameMapper to use. */
+ function setClassname($classname) {
+ if ($this->isReference()) {
+ throw $this->tooManyAttributes();
+ }
+ $this->classname = $classname;
+ }
+
+ /**
+ * Set the argument to FileNameMapper.setFrom
+ */
+ function setFrom($from) {
+ if ($this->isReference()) {
+ throw $this->tooManyAttributes();
+ }
+ $this->from = $from;
+ }
+
+ /**
+ * Set the argument to FileNameMapper.setTo
+ */
+ function setTo($to) {
+ if ($this->isReference()) {
+ throw $this->tooManyAttributes();
+ }
+ $this->to = $to;
+ }
+
+ /**
+ * Make this Mapper instance a reference to another Mapper.
+ *
+ * You must not set any other attribute if you make it a reference.
+ */
+ function setRefid($r) {
+ if ($this->type !== null || $this->from !== null || $this->to !== null) {
+ throw DataType::tooManyAttributes();
+ }
+ parent::setRefid($r);
+ }
+
+ /** Factory, returns inmplementation of file name mapper as new instance */
+ function getImplementation() {
+ if ($this->isReference()) {
+ $tmp = $this->getRef();
+ return $tmp->getImplementation();
+ }
+
+ if ($this->type === null && $this->classname === null) {
+ throw new BuildException("either type or classname attribute must be set for <mapper>");
+ }
+
+ if ($this->type !== null) {
+ switch($this->type) {
+ case 'identity':
+ $this->classname = 'phing.mappers.IdentityMapper';
+ break;
+ case 'flatten':
+ $this->classname = 'phing.mappers.FlattenMapper';
+ break;
+ case 'glob':
+ $this->classname = 'phing.mappers.GlobMapper';
+ break;
+ case 'regexp':
+ case 'regex':
+ $this->classname = 'phing.mappers.RegexpMapper';
+ break;
+ case 'merge':
+ $this->classname = 'phing.mappers.MergeMapper';
+ break;
+ default:
+ throw new BuildException("Mapper type {$this->type} not known");
+ break;
+ }
+ }
+
+ // get the implementing class
+ $cls = Phing::import($this->classname, $this->classpath);
+
+ $m = new $cls;
+ $m->setFrom($this->from);
+ $m->setTo($this->to);
+
+ return $m;
+ }
+
+ /** Performs the check for circular references and returns the referenced Mapper. */
+ private function getRef() {
+ if (!$this->checked) {
+ $stk = array();
+ $stk[] = $this;
+ $this->dieOnCircularReference($stk, $this->project);
+ }
+
+ $o = $this->ref->getReferencedObject($this->project);
+ if (!($o instanceof Mapper)) {
+ $msg = $this->ref->getRefId()." doesn't denote a mapper";
+ throw new BuildException($msg);
+ } else {
+ return $o;
+ }
+ }
+}
+
+?>
diff --git a/buildscripts/phing/classes/phing/types/Parameter.php b/buildscripts/phing/classes/phing/types/Parameter.php
new file mode 100644
index 00000000..6892ed7e
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/Parameter.php
@@ -0,0 +1,99 @@
+<?php
+/*
+ * $Id: Parameter.php,v 1.6 2005/10/05 20:23:22 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+include_once 'phing/types/DataType.php';
+
+/*
+ * A parameter is composed of a name, type and value. Nested
+ * Parameters are also possible, but the using task/type has
+ * to support them
+ *
+ * @author Manuel Holtgrewe
+ * @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
+ * @package phing.types
+*/
+class Parameter extends DataType {
+
+ /** Parameter name */
+ protected $name;
+
+ /** Paramter type */
+ protected $type;
+
+ /** Parameter value */
+ protected $value;
+
+ /** Nested parameters */
+ protected $parameters = array();
+
+ function setName($name) {
+ $this->name = (string) $name;
+ }
+
+ function setType($type) {
+ $this->type = (string) $type;
+ }
+
+ /**
+ * Sets value to dynamic register slot.
+ * @param RegisterSlot $value
+ */
+ public function setListeningValue(RegisterSlot $value) {
+ $this->value = $value;
+ }
+
+ function setValue($value) {
+ $this->value = (string) $value;
+ }
+
+ function getName() {
+ return $this->name;
+ }
+
+ function getType() {
+ return $this->type;
+ }
+
+ function getValue() {
+ if ($this->value instanceof RegisterSlot) {
+ return $this->value->getValue();
+ } else {
+ return $this->value;
+ }
+ }
+
+ /**
+ * @return Parameter
+ */
+ function createParam() {
+ $num = array_push($this->parameters, new Parameter());
+ return $this->parameters[$num-1];
+ }
+
+ /**
+ * @return array Nested parameters.
+ */
+ function getParams() {
+ return $this->parameters;
+ }
+}
+
+?>
diff --git a/buildscripts/phing/classes/phing/types/Parameterizable.php b/buildscripts/phing/classes/phing/types/Parameterizable.php
new file mode 100644
index 00000000..b24aa38b
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/Parameterizable.php
@@ -0,0 +1,32 @@
+<?php
+
+/*
+ * $Id: Parameterizable.php,v 1.3 2003/11/19 05:48:30 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * Parameterizable objects take genric key value pairs.
+ *
+ * @author Hans Lellelid, hans@xmpl.org (Phing)
+ * @author Magesh Umasankar (Ant)
+ * @package phing.types
+ */
+interface Parameterizable {
+ function setParameters($parameters);
+}
diff --git a/buildscripts/phing/classes/phing/types/Path.php b/buildscripts/phing/classes/phing/types/Path.php
new file mode 100644
index 00000000..196fe9c4
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/Path.php
@@ -0,0 +1,456 @@
+<?php
+/*
+ * $Id: Path.php,v 1.13 2005/05/26 13:10:53 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/types/DataType.php';
+include_once 'phing/util/PathTokenizer.php';
+include_once 'phing/types/FileSet.php';
+
+/**
+ * This object represents a path as used by include_path or PATH
+ * environment variable.
+ *
+ * This class has been adopted from the Java Ant equivalent. The ability have
+ * path structures in Phing is important; however, because of how PHP classes interact
+ * the ability to specify CLASSPATHs makes less sense than Java.Rather than providing
+ * CLASSPATH for any tasks that take classes as parameters, perhaps a better
+ * solution in PHP is to have an IncludePath task, which prepends paths to PHP's include_path
+ * INI variable. This gets around the problem that simply using a path to load the initial
+ * PHP class is not enough (in most cases the loaded class may assume that it is on the global
+ * PHP include_path, and will try to load dependent classes accordingly). The other option is
+ * to provide a way for this class to add paths to the include path, if desired -- or to create
+ * an IncludePath subclass. Once added, though, when would a path be removed from the include path?
+ *
+ * <p>
+ * <code>
+ * &lt;sometask&gt;<br>
+ * &nbsp;&nbsp;&lt;somepath&gt;<br>
+ * &nbsp;&nbsp;&nbsp;&nbsp;&lt;pathelement location="/path/to/file" /&gt;<br>
+ * &nbsp;&nbsp;&nbsp;&nbsp;&lt;pathelement path="/path/to/class2;/path/to/class3" /&gt;<br>
+ * &nbsp;&nbsp;&nbsp;&nbsp;&lt;pathelement location="/path/to/file3" /&gt;<br>
+ * &nbsp;&nbsp;&lt;/somepath&gt;<br>
+ * &lt;/sometask&gt;<br>
+ * </code>
+ * <p>
+ * The object implemention <code>sometask</code> must provide a method called
+ * <code>createSomepath</code> which returns an instance of <code>Path</code>.
+ * Nested path definitions are handled by the Path object and must be labeled
+ * <code>pathelement</code>.<p>
+ *
+ * The path element takes a parameter <code>path</code> which will be parsed
+ * and split into single elements. It will usually be used
+ * to define a path from an environment variable.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Thomas.Haas@softwired-inc.com (Ant)
+ * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant)
+ * @package phing.types
+ */
+class Path extends DataType {
+
+ private $elements = array();
+
+ /**
+ * Constructor for internally instantiated objects sets project.
+ * @param Project $project
+ * @param string $path (for use by IntrospectionHelper)
+ */
+ public function __construct($project = null, $path = null) {
+ if ($project !== null) {
+ $this->setProject($project);
+ }
+ if ($path !== null) {
+ $this->createPathElement()->setPath($path);
+ }
+ }
+
+ /**
+ * Adds a element definition to the path.
+ * @param $location the location of the element to add (must not be
+ * <code>null</code> nor empty.
+ * @throws BuildException
+ */
+ public function setDir(PhingFile $location) {
+ if ($this->isReference()) {
+ throw $this->tooManyAttributes();
+ }
+ $this->createPathElement()->setDir($location);
+ }
+
+ /**
+ * Parses a path definition and creates single PathElements.
+ * @param path the path definition.
+ * @throws BuildException
+ */
+ public function setPath($path) {
+ if ($this->isReference()) {
+ throw $this->tooManyAttributes();
+ }
+ $this->createPathElement()->setPath($path);
+ }
+
+ /**
+ * Makes this instance in effect a reference to another Path instance.
+ *
+ * <p>You must not set another attribute or nest elements inside
+ * this element if you make it a reference.</p>
+ * @throws BuildException
+ */
+ public function setRefid(Reference $r) {
+ if (!empty($this->elements)) {
+ throw $this->tooManyAttributes();
+ }
+ $this->elements[] = $r;
+ parent::setRefid($r);
+ }
+
+ /**
+ * Creates the nested <code>&lt;pathelement&gt;</code> element.
+ * @throws BuildException
+ */
+ public function createPathElement() {
+ if ($this->isReference()) {
+ throw $this->noChildrenAllowed();
+ }
+ $pe = new PathElement($this);
+ $this->elements[] = $pe;
+ return $pe;
+ }
+
+ /**
+ * Adds a nested <code>&lt;fileset&gt;</code> element.
+ * @throws BuildException
+ */
+ public function addFileset(FileSet $fs) {
+ if ($this->isReference()) {
+ throw $this->noChildrenAllowed();
+ }
+ $this->elements[] = $fs;
+ $this->checked = false;
+ }
+
+ /**
+ * Adds a nested <code>&lt;dirset&gt;</code> element.
+ * @throws BuildException
+ */
+ public function addDirset(DirSet $dset) {
+ if ($this->isReference()) {
+ throw $this->noChildrenAllowed();
+ }
+ $this->elements[] = $dset;
+ $this->checked = false;
+ }
+
+ /**
+ * Creates a nested <code>&lt;path&gt;</code> element.
+ * @throws BuildException
+ */
+ public function createPath() {
+ if ($this->isReference()) {
+ throw $this->noChildrenAllowed();
+ }
+ $p = new Path($this->project);
+ $this->elements[] = $p;
+ $this->checked = false;
+ return $p;
+ }
+
+ /**
+ * Append the contents of the other Path instance to this.
+ */
+ public function append(Path $other) {
+ if ($other === null) {
+ return;
+ }
+ $l = $other->listPaths();
+ foreach($l as $path) {
+ if (!in_array($path, $this->elements, true)) {
+ $this->elements[] = $path;
+ }
+ }
+ }
+
+ /**
+ * Adds the components on the given path which exist to this
+ * Path. Components that don't exist, aren't added.
+ *
+ * @param Path $source - Source path whose components are examined for existence.
+ */
+ public function addExisting(Path $source) {
+ $list = $source->listPaths();
+ foreach($list as $el) {
+ $f = null;
+ if ($this->project !== null) {
+ $f = $this->project->resolveFile($el);
+ } else {
+ $f = new PhingFile($el);
+ }
+
+ if ($f->exists()) {
+ $this->setDir($f);
+ } else {
+ $this->log("dropping " . $f->__toString() . " from path as it doesn't exist",
+ PROJECT_MSG_VERBOSE);
+ }
+ }
+ }
+
+ /**
+ * Returns all path elements defined by this and nested path objects.
+ * @return array List of path elements.
+ */
+ public function listPaths() {
+ if (!$this->checked) {
+ // make sure we don't have a circular reference here
+ $stk = array();
+ array_push($stk, $this);
+ $this->dieOnCircularReference($stk, $this->project);
+ }
+
+ $result = array();
+ for ($i = 0, $elSize=count($this->elements); $i < $elSize; $i++) {
+ $o = $this->elements[$i];
+ if ($o instanceof Reference) {
+ $o = $o->getReferencedObject($this->project);
+ // we only support references to paths right now
+ if (!($o instanceof Path)) {
+ $msg = $r->getRefId() . " doesn't denote a path";
+ throw new BuildException($msg);
+ }
+ }
+
+ if (is_string($o)) {
+ $result[] = $o;
+ } elseif ($o instanceof PathElement) {
+ $parts = $o->getParts();
+ if ($parts === null) {
+ throw new BuildException("You must either set location or"
+ . " path on <pathelement>");
+ }
+ foreach($parts as $part) {
+ $result[] = $part;
+ }
+ } elseif ($o instanceof Path) {
+ $p = $o;
+ if ($p->getProject() === null) {
+ $p->setProject($this->getProject());
+ }
+ $parts = $p->listPaths();
+ foreach($parts as $part) {
+ $result[] = $part;
+ }
+ } elseif ($o instanceof DirSet) {
+ $dset = $o;
+ $ds = $dset->getDirectoryScanner($this->project);
+ $dirstrs = $ds->getIncludedDirectories();
+ $dir = $dset->getDir($this->project);
+ $this->addUnlessPresent($result, $dir, $s);
+
+ foreach($dirstrs as $dstr) {
+ $d = new PhingFile($dir, $dstr);
+ $result[] = $d->getAbsolutePath();
+ }
+
+ } elseif ($o instanceof FileList) {
+ $fl = $o;
+ $dirstrs = $fl->getFiles($this->project);
+ $dir = $fl->getDir($this->project);
+ foreach($dirstrs as $dstr) {
+ $d = new PhingFile($dir, $dstr);
+ $result[] = $d->getAbsolutePath();
+ }
+ }
+ }
+
+ return array_unique($result);
+ }
+
+
+ /**
+ * Returns a textual representation of the path, which can be used as
+ * CLASSPATH or PATH environment variable definition.
+ * @return string A textual representation of the path.
+ */
+ public function __toString() {
+
+ $list = $this->listPaths();
+
+ // empty path return empty string
+ if (empty($list)) {
+ return "";
+ }
+
+ return implode(PATH_SEPARATOR, $list);
+ }
+
+ /**
+ * Splits a PATH (with : or ; as separators) into its parts.
+ * @param Project $project
+ * @param string $source
+ */
+ public static function translatePath(Project $project, $source) {
+ $result = array();
+ if ($source == null) {
+ return "";
+ }
+
+ $tok = new PathTokenizer($source);
+ $element = "";
+ while ($tok->hasMoreTokens()) {
+ $pathElement = $tok->nextToken();
+ try {
+ $element .= self::resolveFile($project, $pathElement);
+ } catch (BuildException $e) {
+ $this->project->log("Dropping path element " . $pathElement
+ . " as it is not valid relative to the project",
+ PROJECT_MSG_VERBOSE);
+ }
+
+ for ($i = 0, $_i=strlen($element); $i < $_i; $i++) {
+ self::translateFileSep($element, $i);
+ }
+ $result[] = $element;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Returns its argument with all file separator characters
+ * replaced so that they match the local OS conventions.
+ */
+ public static function translateFile($source) {
+ if ($source == null) {
+ return "";
+ }
+
+ $result = $source;
+ for ($i = 0, $_i=strlen($source); $i < $_i; $i++) {
+ self::translateFileSep($result, $i);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Translates all occurrences of / or \ to correct separator of the
+ * current platform and returns whether it had to do any
+ * replacements.
+ */
+ protected static function translateFileSep(&$buffer, $pos) {
+ if ($buffer{$pos} == '/' || $buffer{$pos} == '\\') {
+ $buffer{$pos} = DIRECTORY_SEPARATOR;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * How many parts does this Path instance consist of.
+ * DEV NOTE: expensive call! list is generated, counted, and then
+ * discareded.
+ * @return int
+ */
+ public function size() {
+ return count($this->listPaths());
+ }
+
+ /**
+ * Return a Path that holds the same elements as this instance.
+ */
+ public function __clone() {
+ $p = new Path($this->project);
+ $p->append($this);
+ return $p;
+ }
+
+ /**
+ * Overrides the version of DataType to recurse on all DataType
+ * child elements that may have been added.
+ * @throws BuildException
+ */
+ public function dieOnCircularReference(&$stk, Project $p) {
+
+ if ($this->checked) {
+ return;
+ }
+
+ // elements can contain strings, FileSets, Reference, etc.
+ foreach($this->elements as $o) {
+
+ if ($o instanceof Reference) {
+ $o = $o->getReferencedObject($p);
+ }
+
+ if ($o instanceof DataType) {
+ if (in_array($o, $stk, true)) {
+ throw $this->circularReference();
+ } else {
+ array_push($stk, $o);
+ $o->dieOnCircularReference($stk, $p);
+ array_pop($stk);
+ }
+ }
+ }
+
+ $this->checked = true;
+ }
+
+ /**
+ * Resolve a filename with Project's help - if we know one that is.
+ *
+ * <p>Assume the filename is absolute if project is null.</p>
+ */
+ private static function resolveFile(Project $project, $relativeName) {
+ if ($project !== null) {
+ $f = $project->resolveFile($relativeName);
+ return $f->getAbsolutePath();
+ }
+ return $relativeName;
+ }
+
+}
+
+
+/**
+ * Helper class, holds the nested <code>&lt;pathelement&gt;</code> values.
+ */
+class PathElement {
+
+ private $parts = array();
+ private $outer;
+
+ public function __construct(Path $outer) {
+ $this->outer = $outer;
+ }
+
+ public function setDir(PhingFile $loc) {
+ $this->parts = array(Path::translateFile($loc->getAbsolutePath()));
+ }
+
+ public function setPath($path) {
+ $this->parts = Path::translatePath($this->outer->getProject(), $path);
+ }
+
+ public function getParts() {
+ return $this->parts;
+ }
+}
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/types/PatternSet.php b/buildscripts/phing/classes/phing/types/PatternSet.php
new file mode 100644
index 00000000..2963ab9e
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/PatternSet.php
@@ -0,0 +1,449 @@
+<?php
+/*
+ * $Id: PatternSet.php,v 1.8 2005/05/26 13:10:53 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/system/io/FileReader.php';
+include_once 'phing/types/DataType.php';
+
+/**
+ * The patternset storage component. Carries all necessary data and methods
+ * for the patternset stuff.
+ *
+ * @author Andreas Aderhold, andi@binarycloud.com
+ * @version $Revision: 1.8 $
+ * @package phing.types
+ */
+class PatternSet extends DataType {
+
+ private $includeList = array();
+ private $excludeList = array();
+ private $includesFileList = array();
+ private $excludesFileList = array();
+
+ /**
+ * Makes this instance in effect a reference to another PatternSet
+ * instance.
+ * You must not set another attribute or nest elements inside
+ * this element if you make it a reference.
+ */
+ function setRefid(Reference $r) {
+ if (!empty($this->includeList) || !empty($this->excludeList)) {
+ throw $this->tooManyAttributes();
+ }
+ parent::setRefid($r);
+ }
+
+
+ /**
+ * Add a name entry on the include list
+ *
+ * @returns PatternSetNameEntry Reference to object
+ * @throws BuildException
+ */
+ function createInclude() {
+ if ($this->isReference()) {
+ throw $this->noChildrenAllowed();
+ }
+ return $this->addPatternToList($this->includeList);
+ }
+
+
+ /**
+ * Add a name entry on the include files list
+ *
+ * @returns PatternSetNameEntry Reference to object
+ * @throws BuildException
+ */
+ function createIncludesFile() {
+ if ($this->isReference()) {
+ throw $this->noChildrenAllowed();
+ }
+ return $this->addPatternToList($this->includesFileList);
+ }
+
+ /**
+ * Add a name entry on the exclude list
+ *
+ * @returns PatternSetNameEntry Reference to object
+ * @throws BuildException
+ */
+ function createExclude() {
+ if ($this->isReference()) {
+ throw $this->noChildrenAllowed();
+ }
+ return $this->addPatternToList($this->excludeList);
+ }
+
+ /**
+ * add a name entry on the exclude files list
+ *
+ * @returns PatternSetNameEntry Reference to object
+ * @throws BuildException
+ */
+
+ function createExcludesFile() {
+ if ($this->isReference()) {
+ throw $this->noChildrenAllowed();
+ return;
+ }
+ return $this->addPatternToList($this->excludesFileList);
+ }
+
+
+ /**
+ * Sets the set of include patterns. Patterns may be separated by a comma
+ * or a space.
+ *
+ * @param string the string containing the include patterns
+ * @returns void
+ * @throws BuildException
+ */
+ function setIncludes($includes) {
+ if ($this->isReference()) {
+ throw $this->tooManyAttributes();
+ }
+ if ($includes !== null && strlen($includes) > 0) {
+ $tok = strtok($includes, ", ");
+ while ($tok !== false) {
+ $o = $this->createInclude();
+ $o->setName($tok);
+ $tok = strtok(", ");
+ }
+ }
+ }
+
+
+ /**
+ * Sets the set of exclude patterns. Patterns may be separated by a comma
+ * or a space.
+ *
+ * @param string the string containing the exclude patterns
+ * @returns void
+ * @throws BuildException
+ */
+
+ function setExcludes($excludes) {
+ if ($this->isReference()) {
+ throw $this->tooManyAttributes();
+ }
+ if ($excludes !== null && strlen($excludes) > 0) {
+ $tok = strtok($excludes, ", ");
+ while ($tok !== false) {
+ $o = $this->createExclude();
+ $o->setName($tok);
+ $tok = strtok(", ");
+ }
+ }
+ }
+
+ /**
+ * add a name entry to the given list
+ *
+ * @param array List onto which the nameentry should be added
+ * @returns PatternSetNameEntry Reference to the created PsetNameEntry instance
+ */
+ private function addPatternToList(&$list) {
+ $num = array_push($list, new PatternSetNameEntry());
+ return $list[$num-1];
+ }
+
+ /**
+ * Sets the name of the file containing the includes patterns.
+ *
+ * @param includesFile The file to fetch the include patterns from.
+ */
+ function setIncludesFile($includesFile) {
+ if ($this->isReference()) {
+ throw $this->tooManyAttributes();
+ }
+ if ($includesFile instanceof File) {
+ $includesFile = $includesFile->getPath();
+ }
+ $o = $this->createIncludesFile();
+ $o->setName($includesFile);
+ }
+
+ /**
+ * Sets the name of the file containing the excludes patterns.
+ *
+ * @param excludesFile The file to fetch the exclude patterns from.
+ */
+ function setExcludesFile($excludesFile) {
+ if ($this->isReference()) {
+ throw $this->tooManyAttributes();
+ }
+ if ($excludesFile instanceof File) {
+ $excludesFile = $excludesFile->getPath();
+ }
+ $o = $this->createExcludesFile();
+ $o->setName($excludesFile);
+ }
+
+
+ /**
+ * Reads path matching patterns from a file and adds them to the
+ * includes or excludes list
+ */
+ private function readPatterns(PhingFile $patternfile, &$patternlist, Project $p) {
+ $patternReader = null;
+ try {
+ // Get a FileReader
+ $patternReader = new BufferedReader(new FileReader($patternfile));
+
+ // Create one NameEntry in the appropriate pattern list for each
+ // line in the file.
+ $line = $patternReader->readLine();
+ while ($line !== null) {
+ if (!empty($line)) {
+ $line = $p->replaceProperties($line);
+ $this->addPatternToList($patternlist)->setName($line);
+ }
+ $line = $patternReader->readLine();
+ }
+
+ } catch (IOException $ioe) {
+ $msg = "An error occured while reading from pattern file: " . $patternfile->__toString();
+ if($patternReader) $patternReader->close();
+ throw new BuildException($msg, $ioe);
+ }
+
+ $patternReader->close();
+ }
+
+
+ /** Adds the patterns of the other instance to this set. */
+ function append($other, $p) {
+ if ($this->isReference()) {
+ throw new BuildException("Cannot append to a reference");
+ }
+
+ $incl = $other->getIncludePatterns($p);
+ if ($incl !== null) {
+ foreach($incl as $incl_name) {
+ $o = $this->createInclude();
+ $o->setName($incl_name);
+ }
+ }
+
+ $excl = $other->getExcludePatterns($p);
+ if ($excl !== null) {
+ foreach($excl as $excl_name) {
+ $o = $this->createExclude();
+ $o->setName($excl_name);
+ }
+ }
+ }
+
+ /** Returns the filtered include patterns. */
+ function getIncludePatterns(Project $p) {
+ if ($this->isReference()) {
+ $o = $this->getRef($p);
+ return $o->getIncludePatterns($p);
+ } else {
+ $this->readFiles($p);
+ return $this->makeArray($this->includeList, $p);
+ }
+ }
+
+ /** Returns the filtered exclude patterns. */
+ function getExcludePatterns(Project $p) {
+ if ($this->isReference()) {
+ $o = $this->getRef($p);
+ return $o->getExcludePatterns($p);
+ } else {
+ $this->readFiles($p);
+ return $this->makeArray($this->excludeList, $p);
+ }
+ }
+
+ /** helper for FileSet. */
+ function hasPatterns() {
+ return (boolean) count($this->includesFileList) > 0 || count($this->excludesFileList) > 0
+ || count($this->includeList) > 0 || count($this->excludeList) > 0;
+ }
+
+ /**
+ * Performs the check for circular references and returns the
+ * referenced PatternSet.
+ */
+ function getRef(Project $p) {
+ if (!$this->checked) {
+ $stk = array();
+ array_push($stk, $this);
+ $this->dieOnCircularReference($stk, $p);
+ }
+ $o = $this->ref->getReferencedObject($p);
+ if (!($o instanceof PatternSet)) {
+ $msg = $this->ref->getRefId()." doesn't denote a patternset";
+ throw new BuildException($msg);
+ } else {
+ return $o;
+ }
+ }
+
+ /** Convert a array of PatternSetNameEntry elements into an array of Strings. */
+ private function makeArray(&$list, Project $p) {
+
+ if (count($list) === 0) {
+ return null;
+ }
+
+ $tmpNames = array();
+ foreach($list as $ne) {
+ $pattern = (string) $ne->evalName($p);
+ if ($pattern !== null && strlen($pattern) > 0) {
+ array_push($tmpNames, $pattern);
+ }
+ }
+ return $tmpNames;
+ }
+
+ /** Read includesfile or excludesfile if not already done so. */
+ private function readFiles(Project $p) {
+ if (!empty($this->includesFileList)) {
+ foreach($this->includesFileList as $ne) {
+ $fileName = (string) $ne->evalName($p);
+ if ($fileName !== null) {
+ $inclFile = $p->resolveFile($fileName);
+ if (!$inclFile->exists()) {
+ throw new BuildException("Includesfile ".$inclFile->getAbsolutePath()." not found.");
+ }
+ $this->readPatterns($inclFile, $this->includeList, $p);
+ }
+ }
+ $this->includesFileList = array();
+ }
+
+ if (!empty($this->excludesFileList)) {
+ foreach($this->excludesFileList as $ne) {
+ $fileName = (string) $ne->evalName($p);
+ if ($fileName !== null) {
+ $exclFile = $p->resolveFile($fileName);
+ if (!$exclFile->exists()) {
+ throw new BuildException("Excludesfile ".$exclFile->getAbsolutePath()." not found.");
+ return;
+ }
+ $this->readPatterns($exclFile, $this->excludeList, $p);
+ }
+ }
+ $this->excludesFileList = array();
+ }
+ }
+
+
+ function toString() {
+
+ // We can't compile includeList into array because, toString() does
+ // not know about project:
+ //
+ // $includes = $this->makeArray($this->includeList, $this->project);
+ // $excludes = $this->makeArray($this->excludeList, $this->project);
+
+ if (empty($this->includeList)) {
+ $includes = "empty";
+ } else {
+ $includes = "";
+ foreach($this->includeList as $ne) {
+ $includes .= $ne->toString() . ",";
+ }
+ $includes = rtrim($includes, ",");
+ }
+
+ if (empty($this->excludeList)) {
+ $excludes = "empty";
+ } else {
+ $excludes = "";
+ foreach($this->excludeList as $ne) {
+ $excludes .= $ne->toString() . ",";
+ }
+ $excludes = rtrim($excludes, ",");
+ }
+
+ return "patternSet{ includes: $includes excludes: $excludes }";
+ }
+}
+
+
+/*
+ * Note, this class here should become a nested class to
+ * PatternSet (PatternSet:NameEntry) as it is only needed
+ * internally.
+ * This is not possible with php 4.x right now so we place
+ * this class (against good style) in this file.
+ */
+
+class PatternSetNameEntry {
+
+ private $name = null;
+ private $ifCond = null;
+ private $unlessCond = null;
+
+ function setName($name) {
+ $this->name = (string) $name;
+ }
+
+
+ function setIf($cond) {
+ $this->ifCond = (string) $cond;
+ }
+
+
+ function setUnless($cond) {
+ $this->unlessCond = (string) $cond;
+ }
+
+
+ function getName() {
+ return $this->name;
+ }
+
+
+ function evalName($project) {
+ return $this->valid($project) ? $this->name : null;
+ }
+
+
+ function valid($project) {
+ if ($this->ifCond !== null && $project->getProperty($this->ifCond) === null) {
+ return false;
+ } else if ($this->unlessCond !== null && $project->getProperty($this->unlessCond) !== null) {
+ return false;
+ }
+ return true;
+ }
+
+
+ function toString() {
+ $buf = $this->name;
+ if (($this->ifCond !== null) || ($this->unlessCond !== null)) {
+ $buf .= ":";
+ $connector = "";
+
+ if ($this->ifCond !== null) {
+ $buf .= "if->{$this->ifCond}";
+ $connector = ";";
+ }
+ if ($this->unlessCond !== null) {
+ $buf .= "$connector unless->{$this->unlessCond}";
+ }
+ }
+ return $buf;
+ }
+}
diff --git a/buildscripts/phing/classes/phing/types/PhingFilterReader.php b/buildscripts/phing/classes/phing/types/PhingFilterReader.php
new file mode 100644
index 00000000..eb45f894
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/PhingFilterReader.php
@@ -0,0 +1,136 @@
+<?php
+/*
+ * $Id: PhingFilterReader.php,v 1.9 2005/10/05 20:23:22 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+include_once 'phing/types/DataType.php';
+include_once 'phing/types/Parameter.php';
+
+/*
+ * A PhingFilterReader is a wrapper class that encloses the className
+ * and configuration of a Configurable FilterReader.
+ *
+ * @author Yannick Lecaillez <yl@seasonfive.com>
+ * @version $Revision: 1.9 $
+ * @see FilterReader
+ * @package phing.types
+*/
+class PhingFilterReader extends DataType {
+
+ private $className;
+ private $parameters = array();
+ private $classPath;
+
+ function setClassName($className) {
+ $this->className = $className;
+ }
+
+ function getClassName() {
+ return $this->className;
+ }
+
+ /**
+ * Set the classpath to load the FilterReader through (attribute).
+ * @param Path $classpath
+ */
+ function setClasspath(Path $classpath) {
+ if ( $this->isReference() ) {
+ throw $this->tooManyAttributes();
+ }
+ if ( $this->classPath === null ) {
+ $this->classPath = $classpath;
+ } else {
+ $this->classPath->append($classpath);
+ }
+ }
+
+ /*
+ * Set the classpath to load the FilterReader through (nested element).
+ */
+ function createClasspath() {
+ if ( $this->isReference() ) {
+ throw $this->noChildrenAllowed();
+ }
+ if ( $this->classPath === null ) {
+ $this->classPath = new Path($this->project);
+ }
+ return $this->classPath->createPath();
+ }
+
+ function getClasspath() {
+ return $this->classPath;
+ }
+
+ function setClasspathRef(Reference $r) {
+ if ( $this->isReference() ) {
+ throw $this->tooManyAttributes();
+ }
+ $o = $this->createClasspath();
+ $o->setRefid($r);
+ }
+
+ function addParam(Parameter $param) {
+ $this->parameters[] = $param;
+ }
+
+ function createParam() {
+ $num = array_push($this->parameters, new Parameter());
+ return $this->parameters[$num-1];
+ }
+
+ function getParams() {
+ // We return a COPY
+ $ret = array();
+ for($i=0,$size=count($this->parameters); $i < $size; $i++) {
+ $ret[] = clone $this->parameters[$i];
+ }
+ return $ret;
+ }
+
+ /*
+ * Makes this instance in effect a reference to another PhingFilterReader
+ * instance.
+ *
+ * <p>You must not set another attribute or nest elements inside
+ * this element if you make it a reference.</p>
+ *
+ * @param Reference $r the reference to which this instance is associated
+ * @exception BuildException if this instance already has been configured.
+ */
+ function setRefid(Reference $r) {
+ if ( (count($this->parameters) !== 0) || ($this->className !== null) ) {
+ throw $this->tooManyAttributes();
+ }
+ $o = $r->getReferencedObject($this->getProject());
+ if ( $o instanceof PhingFilterReader ) {
+ $this->setClassName($o->getClassName());
+ $this->setClasspath($o->getClassPath());
+ foreach($o->getParams() as $p) {
+ $this->addParam($p);
+ }
+ } else {
+ $msg = $r->getRefId()." doesn\'t refer to a PhingFilterReader";
+ throw new BuildException($msg);
+ }
+
+ parent::setRefid($r);
+ }
+}
+
+?>
diff --git a/buildscripts/phing/classes/phing/types/Reference.php b/buildscripts/phing/classes/phing/types/Reference.php
new file mode 100644
index 00000000..c226917d
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/Reference.php
@@ -0,0 +1,56 @@
+<?php
+/*
+ * $Id: Reference.php,v 1.4 2003/12/24 12:38:42 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/** Class to hold a reference to another object in the project.
+ * @package phing.types
+ */
+class Reference {
+
+ protected $refid;
+
+ function __construct($id = null) {
+ if ($id !== null) {
+ $this->setRefId($id);
+ }
+ }
+
+ function setRefId($id) {
+ $this->refid = (string) $id;
+ }
+
+ function getRefId() {
+ return $this->refid;
+ }
+
+ /** returns reference to object in references container of project */
+ function getReferencedObject($project) {
+ if ($this->refid === null) {
+ throw new BuildException("No reference specified");
+ }
+ $refs = $project->getReferences();
+ $o = @$refs[$this->refid];
+ if (!is_object($o)) {
+ throw new BuildException("Reference {$this->refid} not found.");
+ }
+ return $o;
+ }
+}
+?>
diff --git a/buildscripts/phing/classes/phing/types/RegularExpression.php b/buildscripts/phing/classes/phing/types/RegularExpression.php
new file mode 100644
index 00000000..67850c23
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/RegularExpression.php
@@ -0,0 +1,105 @@
+<?php
+/*
+ * $Id: RegularExpression.php,v 1.6 2003/12/24 12:38:42 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+include_once 'phing/types/DataType.php';
+include_once 'phing/Project.php';
+include_once 'phing/util/regexp/Regexp.php';
+
+/*
+ * A regular expression datatype. Keeps an instance of the
+ * compiled expression for speed purposes. This compiled
+ * expression is lazily evaluated (it is compiled the first
+ * time it is needed). The syntax is the dependent on which
+ * regular expression type you are using.
+ *
+ * @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
+ * @version $Revision: 1.6 $ $Date: 2003/12/24 12:38:42 $
+ * @access public
+ * @see phing.util.regex.RegexMatcher
+ * @package phing.types
+*/
+class RegularExpression extends DataType {
+
+ private $regexp = null;
+ private $ignoreCase = false;
+
+ function __construct() {
+ $this->regexp = new Regexp();
+ }
+
+ function setPattern($pattern) {
+ $this->regexp->setPattern($pattern);
+ }
+
+ function setReplace($replace) {
+ $this->regexp->setReplace($replace);
+ }
+
+ function getPattern($p) {
+ if ( $this->isReference() ) {
+ $ref = $this->getRef($p);
+ return $ref->getPattern($p);
+ }
+ return $this->regexp->getPattern();
+ }
+
+ function getReplace($p) {
+ if ( $this->isReference() ) {
+ $ref = $this->getRef($p);
+ return $ref->getReplace($p);
+ }
+
+ return $this->regexp->getReplace();
+ }
+
+ function setIgnoreCase($bit) {
+ $this->regexp->setIgnoreCase($bit);
+ }
+
+ function getIgnoreCase() {
+ return $this->regexp->getIgnoreCase();
+ }
+
+ function getRegexp(Project $p) {
+ if ( $this->isReference() ) {
+ $ref = $this->getRef($p);
+ return $ref->getRegexp($p);
+ }
+ return $this->regexp;
+ }
+
+ function getRef(Project $p) {
+ if ( !$this->checked ) {
+ $stk = array();
+ array_push($stk, $this);
+ $this->dieOnCircularReference($stk, $p);
+ }
+
+ $o = $this->ref->getReferencedObject($p);
+ if ( !($o instanceof RegularExpression) ) {
+ throw new BuildException($this->ref->getRefId()." doesn't denote a RegularExpression");
+ } else {
+ return $o;
+ }
+ }
+}
+
+?>
diff --git a/buildscripts/phing/classes/phing/types/TokenReader.php b/buildscripts/phing/classes/phing/types/TokenReader.php
new file mode 100644
index 00000000..acd7d616
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/TokenReader.php
@@ -0,0 +1,66 @@
+<?php
+/*
+ * $Id: TokenReader.php,v 1.5 2003/12/24 12:38:42 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+// include_once 'phing/system/io/Reader.php'; // really this is unrelated to Reader
+include_once 'phing/system/io/IOException.php';
+include_once 'phing/filters/ReplaceTokens.php'; // For class Token
+
+/**
+ * Abstract class for TokenReaders.
+ *
+ * @author Manuel Holtgewe
+ * @version $Revision: 1.5 $
+ * @package phing.filters.util
+ */
+abstract class TokenReader {
+
+ /**
+ * Reference to the Project the TokenReader is used in.
+ * @var Project
+ */
+ protected $project;
+
+ /**
+ * Constructor
+ * @param object Reference to the project the TokenReader is used in.
+ */
+ function __construct(Project $project) {
+ $this->project = $project;
+ }
+
+ /**
+ * Utility function for logging
+ */
+ function log($level, $msg) {
+ $this->project->log($level, $msg);
+ }
+
+ /**
+ * Reads the next token from the Reader
+ *
+ * @throws IOException - On error
+ * @return string
+ */
+ abstract public function readToken();
+
+}
+
+?>
diff --git a/buildscripts/phing/classes/phing/types/TokenSource.php b/buildscripts/phing/classes/phing/types/TokenSource.php
new file mode 100644
index 00000000..c073ece0
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/TokenSource.php
@@ -0,0 +1,157 @@
+<?php
+/*
+ * $Id: TokenSource.php,v 1.7 2004/03/18 20:44:26 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+*/
+
+require_once 'phing/types/DataType.php';
+include_once 'phing/util/StringHelper.php';
+
+/**
+ * A parameter is composed of a name, type and value.
+ *
+ * Example of usage:
+ *
+ * <replacetokens>
+ * <tokensource classname="phing.filters.util.IniFileTokenReader">
+ * <!-- all params for the TokenReader here -->
+ * <param name="file" value="tokens.ini" />
+ * </tokensource>
+ * </replacetokens>
+ *
+ * or:
+ *
+ * <filterreader classname="phing.filters.ReplaceTokens">
+ * <param type="tokensource>
+ * <param name="classname" value="phing.filters.util.IniFileTokenReader" />
+ * <param name="file" value="tokens.ini" />
+ * </param>
+ * </filterreader>
+ *
+ * @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
+ * @package phing.types
+ */
+class TokenSource extends DataType {
+
+ /**
+ * String to hold the path to the TokenReader
+ * @var string
+ */
+ protected $classname = null;
+
+ /**
+ * Array holding parameters for the wrapped TokenReader.
+ * @var array
+ */
+ protected $parameters = array();
+
+ /**
+ * Reference to the TokenReader used by this TokenSource
+ * @var TokenReader
+ */
+ protected $reader;
+
+ /**
+ * Array with key/value pairs of tokens
+ */
+ protected $tokens = array();
+
+ /**
+ * This method is called to load the sources from the reader
+ * into the buffer of the source.
+ */
+ function load() {
+ // Create new Reader
+ if ($this->classname === null) {
+ throw new BuildException("No Classname given to TokenSource.");
+ }
+
+ $classname = Phing::import($this->classname);
+ $this->reader = new $classname($this->project);
+
+ // Configure Reader
+ $this->configureTokenReader($this->reader);
+
+ // Load Tokens
+ try {
+ while ($token = $this->reader->readToken()) {
+ $this->tokens[] = $token;
+ }
+ } catch (BuildException $e) {
+ $this->log("Error reading TokenSource: " . $e->getMessage(), PROJECT_MSG_WARN);
+ } catch (IOException $e) {
+ $this->log("Error reading TokenSource: " . $e->getMessage(), PROJECT_MSG_WARN);
+ }
+ }
+
+ /**
+ * This function uses the wrapper to read the tokens and then
+ * returns them.
+ *
+ * @access public
+ */
+ function getTokens() {
+ if ($this->tokens === null)
+ $this->Load();
+
+ return $this->tokens;
+ }
+
+ /**
+ * Configures a TokenReader with the parameters passed to the
+ * TokenSource.
+ * @param TokenReader $reader
+ */
+ private function configureTokenReader(TokenReader $reader) {
+ $count = count($this->parameters);
+ for ($i = 0; $i < $count; $i++) {
+ $method_name = "Set" . $this->parameters[$i]->getName();
+ $value = $this->parameters[$i]->getValue();
+ $reader->$method_name($value);
+ }
+ }
+
+ /**
+ * Set the classname (dot-path) to use for handling token replacement.
+ * @param string $c
+ */
+ function setClassname($c) {
+ $this->classname = $c;
+ }
+
+ /**
+ * Returns the qualified classname (dot-path) to use for handling token replacement.
+ * @return string
+ */
+ function getClassname() {
+ return $this->classname;
+ }
+
+ /**
+ * Create nested <param> tag.
+ * Uses standard name/value Parameter class.
+ * @return Parameter
+ */
+ function createParam() {
+ $num = array_push($this->parameters, new Parameter());
+ return $this->parameters[$num-1];
+ }
+}
+
+
+?>
diff --git a/buildscripts/phing/classes/phing/types/defaults.properties b/buildscripts/phing/classes/phing/types/defaults.properties
new file mode 100644
index 00000000..a2d86350
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/defaults.properties
@@ -0,0 +1,13 @@
+# phing default types
+commandline=phing.types.Commandline
+fileset=phing.types.FileSet
+dirset=phing.types.DirSet
+filelist=phing.types.FileList
+patternset=phing.types.PatternSet
+mapper=phing.types.Mapper
+filterchain=phing.types.FilterChain
+filterreader=phing.types.PhingFilterReader
+regexp=phing.types.RegularExpression
+param=phing.types.Parameter
+path=phing.types.Path
+selector=phing.types.selectors.SelectSelector \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/types/selectors/AndSelector.php b/buildscripts/phing/classes/phing/types/selectors/AndSelector.php
new file mode 100644
index 00000000..3801091f
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/AndSelector.php
@@ -0,0 +1,67 @@
+<?php
+/*
+ * $Id: AndSelector.php,v 1.9 2005/05/26 13:10:53 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/types/selectors/BaseSelectorContainer.php';
+
+/**
+ * This selector has a collection of other selectors, all of which have to
+ * select a file in order for this selector to select it.
+ *
+ * @author Hans Lellelid, hans@xmpl.org (Phing)
+ * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a> (Ant)
+ * @package phing.types.selectors
+ */
+class AndSelector extends BaseSelectorContainer {
+
+ public function toString() {
+ $buf = "";
+ if ($this->hasSelectors()) {
+ $buf .= "{andselect: ";
+ $buf .= parent::toString();
+ $buf .= "}";
+ }
+ return $buf;
+ }
+
+ /**
+ * Returns true (the file is selected) only if all other selectors
+ * agree that the file should be selected.
+ *
+ * @param basedir the base directory the scan is being done from
+ * @param filename the name of the file to check
+ * @param file a PhingFile object for the filename that the selector
+ * can use
+ * @return whether the file should be selected or not
+ */
+ public function isSelected(PhingFile $basedir, $filename, PhingFile $file) {
+ $this->validate();
+ $selectors = $this->selectorElements();
+ for($i=0,$size=count($selectors); $i < $size; $i++) {
+ $result = $selectors[$i]->isSelected($basedir, $filename, $file);
+ if (!$result) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+}
+
diff --git a/buildscripts/phing/classes/phing/types/selectors/BaseExtendSelector.php b/buildscripts/phing/classes/phing/types/selectors/BaseExtendSelector.php
new file mode 100644
index 00000000..5acc54dd
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/BaseExtendSelector.php
@@ -0,0 +1,62 @@
+<?php
+
+/*
+ * $Id: BaseExtendSelector.php,v 1.5 2004/02/16 05:28:40 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/types/selectors/ExtendFileSelector.php';
+require_once 'phing/types/selectors/BaseSelector.php';
+include_once 'phing/types/Parameter.php';
+
+/**
+ * Convenience base class for all selectors accessed through ExtendSelector.
+ * It provides support for gathering the parameters together as well as for
+ * assigning an error message and throwing a build exception if an error is
+ * detected.
+ *
+ * @author Hans Lellelid, hans@xmpl.org (Phing)
+ * @author Bruce Atherton, bruce@callenish.com (Ant)
+ * @package phing.types.selectors
+ */
+abstract class BaseExtendSelector extends BaseSelector implements ExtendFileSelector {
+
+ /** The passed in parameter array. */
+ protected $parameters = null;
+
+ /**
+ * Set all the Parameters for this custom selector, collected by
+ * the ExtendSelector class.
+ *
+ * @param parameters the complete set of parameters for this selector
+ */
+ public function setParameters($parameters) {
+ $this->parameters = $parameters;
+ }
+
+ /**
+ * Allows access to the parameters gathered and set within the
+ * &lt;custom&gt; tag.
+ *
+ * @return the set of parameters defined for this selector
+ */
+ protected function getParameters() {
+ return $this->parameters;
+ }
+}
+
diff --git a/buildscripts/phing/classes/phing/types/selectors/BaseSelector.php b/buildscripts/phing/classes/phing/types/selectors/BaseSelector.php
new file mode 100644
index 00000000..e229fc24
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/BaseSelector.php
@@ -0,0 +1,84 @@
+<?php
+/*
+ * $Id: BaseSelector.php,v 1.4 2004/02/16 04:56:24 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/types/selectors/FileSelector.php';
+
+/**
+ * A convenience base class that you can subclass Selectors from. It
+ * provides some helpful common behaviour. Note that there is no need
+ * for Selectors to inherit from this class, it is only necessary that
+ * they implement FileSelector.
+ *
+ * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
+ * @package phing.types.selectors
+ */
+abstract class BaseSelector extends DataType implements FileSelector {
+
+ private $errmsg = null;
+
+ /**
+ * Allows all selectors to indicate a setup error. Note that only
+ * the first error message is recorded.
+ *
+ * @param msg The error message any BuildException should throw.
+ */
+ public function setError($msg) {
+ if ($this->errmsg === null) {
+ $this->errmsg = $msg;
+ }
+ }
+
+ /**
+ * Returns any error messages that have been set.
+ *
+ * @return the error condition
+ */
+ public function getError() {
+ return $this->errmsg;
+ }
+
+
+ /**
+ * <p>Subclasses can override this method to provide checking of their
+ * state. So long as they call validate() from isSelected(), this will
+ * be called automatically (unless they override validate()).</p>
+ * <p>Implementations should check for incorrect settings and call
+ * setError() as necessary.</p>
+ */
+ public function verifySettings() {
+ }
+
+ /**
+ * Subclasses can use this to throw the requisite exception
+ * in isSelected() in the case of an error condition.
+ */
+ public function validate() {
+ if ($this->getError() === null) {
+ $this->verifySettings();
+ }
+ if ($this->getError() !== null) {
+ throw new BuildException($this->errmsg);
+ }
+ }
+
+}
+
+
diff --git a/buildscripts/phing/classes/phing/types/selectors/BaseSelectorContainer.php b/buildscripts/phing/classes/phing/types/selectors/BaseSelectorContainer.php
new file mode 100644
index 00000000..19b84b00
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/BaseSelectorContainer.php
@@ -0,0 +1,270 @@
+<?php
+
+/*
+ * $Id: BaseSelectorContainer.php,v 1.9 2004/02/16 04:56:24 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/types/selectors/SelectorContainer.php';
+require_once 'phing/types/selectors/BaseSelector.php';
+
+/**
+ * This is the base class for selectors that can contain other selectors.
+ *
+ * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a> (Ant)
+ * @package phing.types.selectors
+ */
+abstract class BaseSelectorContainer extends BaseSelector implements SelectorContainer {
+
+ private $selectorsList = array();
+
+ /**
+ * Indicates whether there are any selectors here.
+ */
+ public function hasSelectors() {
+ return !(empty($this->selectorsList));
+ }
+
+ /**
+ * Gives the count of the number of selectors in this container
+ */
+ public function selectorCount() {
+ return count($this->selectorsList);
+ }
+
+ /**
+ * Returns a copy of the selectors as an array.
+ */
+ public function getSelectors(Project $p) {
+ $result = array();
+ for($i=0,$size=count($this->selectorsList); $i < $size; $i++) {
+ $result[] = clone $this->selectorsList[$i];
+ }
+ return $result;
+ }
+
+ /**
+ * Returns an array for accessing the set of selectors (not a copy).
+ */
+ public function selectorElements() {
+ return $this->selectorsList;
+ }
+
+ /**
+ * Convert the Selectors within this container to a string. This will
+ * just be a helper class for the subclasses that put their own name
+ * around the contents listed here.
+ *
+ * @return comma separated list of Selectors contained in this one
+ */
+ public function toString() {
+ $buf = "";
+ $arr = $this->selectorElements();
+ for($i=0,$size=count($arr); $i < $size; $i++) {
+ $buf .= $arr[$i]->toString() . (isset($arr[$i+1]) ? ', ' : '');
+ }
+ return $buf;
+ }
+
+ /**
+ * Add a new selector into this container.
+ *
+ * @param selector the new selector to add
+ * @return the selector that was added
+ */
+ public function appendSelector(FileSelector $selector) {
+ $this->selectorsList[] = $selector;
+ }
+
+ /**
+ * <p>This implementation validates the container by calling
+ * verifySettings() and then validates each contained selector
+ * provided that the selector implements the validate interface.
+ * </p>
+ * <p>Ordinarily, this will validate all the elements of a selector
+ * container even if the isSelected() method of some elements is
+ * never called. This has two effects:</p>
+ * <ul>
+ * <li>Validation will often occur twice.
+ * <li>Since it is not required that selectors derive from
+ * BaseSelector, there could be selectors in the container whose
+ * error conditions are not detected if their isSelected() call
+ * is never made.
+ * </ul>
+ */
+ public function validate() {
+ $this->verifySettings();
+ $errmsg = $this->getError();
+ if ($errmsg !== null) {
+ throw new BuildException($errmsg);
+ }
+ foreach($this->selectorsList as $o) {
+ if ($o instanceof BaseSelector) {
+ $o->validate();
+ }
+ }
+ }
+
+ /* Methods below all add specific selectors */
+
+ /**
+ * add a "Select" selector entry on the selector list
+ */
+ public function createSelector() {
+ $o = new SelectSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add an "And" selector entry on the selector list
+ */
+ public function createAnd() {
+ $o = new AndSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add an "Or" selector entry on the selector list
+ */
+ public function createOr() {
+ $o = new OrSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a "Not" selector entry on the selector list
+ */
+ public function createNot() {
+ $o = new NotSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a "None" selector entry on the selector list
+ */
+ public function createNone() {
+ $o = new NoneSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a majority selector entry on the selector list
+ */
+ public function createMajority() {
+ $o = new MajoritySelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a selector date entry on the selector list
+ */
+ public function createDate() {
+ $o = new DateSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a selector size entry on the selector list
+ */
+ public function createSize() {
+ $o = new SizeSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a selector filename entry on the selector list
+ */
+ public function createFilename() {
+ $o = new FilenameSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add an extended selector entry on the selector list
+ */
+ public function createCustom() {
+ $o = new ExtendSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a contains selector entry on the selector list
+ */
+ public function createContains() {
+ $o = new ContainsSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a contains selector entry on the selector list
+ */
+ public function createContainsRegexp() {
+ $o = new ContainsRegexpSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a present selector entry on the selector list
+ */
+ public function createPresent() {
+ $o = new PresentSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a depth selector entry on the selector list
+ */
+ public function createDepth() {
+ $o = new DepthSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a depends selector entry on the selector list
+ */
+ public function createDepend() {
+ $o = new DependSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+ /**
+ * add a type selector entry on the selector list
+ */
+ public function createType() {
+ $o = new TypeSelector();
+ $this->appendSelector($o);
+ return $o;
+ }
+
+}
+
diff --git a/buildscripts/phing/classes/phing/types/selectors/ContainsRegexpSelector.php b/buildscripts/phing/classes/phing/types/selectors/ContainsRegexpSelector.php
new file mode 100644
index 00000000..39afd2fa
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/ContainsRegexpSelector.php
@@ -0,0 +1,164 @@
+<?php
+
+/*
+ * $Id: ContainsRegexpSelector.php,v 1.3 2005/05/26 13:10:53 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/types/selectors/BaseExtendSelector.php';
+include_once 'phing/types/RegularExpression.php';
+
+/**
+ * Selector that filters files based on whether they contain a
+ * particular string using regexp.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Bruce Atherton <bruce@callenish.com> (Ant)
+ * @version $Revision: 1.3 $
+ * @package phing.types.selectors
+ */
+class ContainsRegexpSelector extends BaseExtendSelector {
+
+ /** @var string The expression set from XML. */
+ private $userProvidedExpression;
+
+ /** @var Regexp */
+ private $myExpression;
+
+ private $casesensitive = true;
+
+ /** @var RegularExpression */
+ private $myRegExp;
+
+ const EXPRESSION_KEY = "expression";
+
+ const CASE_KEY = "casesensitive";
+
+ public function toString() {
+ $buf = "{containsregexpselector expression: ";
+ $buf .= $this->userProvidedExpression;
+ $buf .= " casesensitive: ";
+ if ($this->casesensitive) {
+ $buf .= "true";
+ } else {
+ $buf .= "false";
+ }
+ $buf .= "}";
+ return $buf;
+ }
+
+ /**
+ * The expression to match on within a file.
+ *
+ * @param string $exp the string that a file must contain to be selected.
+ */
+ public function setExpression($exp) {
+ $this->userProvidedExpression = $exp;
+ }
+
+ /**
+ * Whether to ignore case in the regex match.
+ *
+ * @param boolean $casesensitive whether to pay attention to case sensitivity
+ */
+ public function setCasesensitive($casesensitive) {
+ $this->casesensitive = $casesensitive;
+ }
+
+ /**
+ * When using this as a custom selector, this method will be called.
+ * It translates each parameter into the appropriate setXXX() call.
+ *
+ * @param array $parameters the complete set of parameters for this selector
+ */
+ public function setParameters($parameters) {
+ parent::setParameters($parameters);
+ if ($parameters !== null) {
+ for ($i=0,$size=count($parameters); $i < $size; $i++) {
+ $paramname = $parameters[$i]->getName();
+ switch(strtolower($paramname)) {
+ case self::EXPRESSION_KEY:
+ $this->setExpression($parameters[$i]->getValue());
+ break;
+ case self::CASE_KEY:
+ $this->setCasesensitive($parameters[$i]->getValue());
+ break;
+ default:
+ $this->setError("Invalid parameter " . $paramname);
+ }
+ } // for each param
+ } // if params
+ }
+
+ /**
+ * Checks to make sure all settings are kosher. In this case, it
+ * means that the pattern attribute has been set.
+ *
+ */
+ public function verifySettings() {
+ if ($this->userProvidedExpression === null) {
+ $this->setError("The expression attribute is required");
+ }
+ }
+
+ /**
+ * The heart of the matter. This is where the selector gets to decide
+ * on the inclusion of a file in a particular fileset.
+ *
+ * @param basedir the base directory the scan is being done from
+ * @param filename is the name of the file to check
+ * @param file a PhingFile object the selector can use
+ * @return whether the file should be selected or not
+ */
+ public function isSelected(PhingFile $basedir, $filename, PhingFile $file) {
+
+ $this->validate();
+
+ if ($file->isDirectory()) {
+ return true;
+ }
+
+ if ($this->myRegExp === null) {
+ $this->myRegExp = new RegularExpression();
+ $this->myRegExp->setPattern($this->userProvidedExpression);
+ if (!$this->casesensitive) {
+ $this->myRegExp->setIgnoreCase(true);
+ }
+ $this->myExpression = $this->myRegExp->getRegexp($this->getProject());
+ }
+
+ $in = null;
+ try {
+ $in = new BufferedReader(new FileReader($file));
+ $teststr = $in->readLine();
+ while ($teststr !== null) {
+ if ($this->myExpression->matches($teststr)) {
+ return true;
+ }
+ $teststr = $in->readLine();
+ }
+ return false;
+ } catch (IOException $ioe) {
+ if ($in) $in->close();
+ throw new BuildException("Could not read file " . $filename);
+ }
+ $in->close();
+ }
+
+}
+
diff --git a/buildscripts/phing/classes/phing/types/selectors/ContainsSelector.php b/buildscripts/phing/classes/phing/types/selectors/ContainsSelector.php
new file mode 100644
index 00000000..d00ce995
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/ContainsSelector.php
@@ -0,0 +1,151 @@
+<?php
+
+/*
+ * $Id: ContainsSelector.php,v 1.9 2005/05/26 13:10:53 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/types/selectors/BaseExtendSelector.php';
+
+/**
+ * Selector that filters files based on whether they contain a
+ * particular string.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Bruce Atherton <bruce@callenish.com> (Ant)
+ * @package phing.types.selectors
+ */
+class ContainsSelector extends BaseExtendSelector {
+
+ private $contains = null;
+ private $casesensitive = true;
+ const CONTAINS_KEY = "text";
+ const CASE_KEY = "casesensitive";
+
+ public function toString() {
+ $buf = "{containsselector text: ";
+ $buf .= $this->contains;
+ $buf .= " casesensitive: ";
+ if ($this->casesensitive) {
+ $buf .= "true";
+ } else {
+ $buf .= "false";
+ }
+ $buf .= "}";
+ return $buf;
+ }
+
+ /**
+ * The string to search for within a file.
+ *
+ * @param string $contains the string that a file must contain to be selected.
+ */
+ public function setText($contains) {
+ $this->contains = $contains;
+ }
+
+ /**
+ * Whether to ignore case in the string being searched.
+ *
+ * @param boolean $casesensitive whether to pay attention to case sensitivity
+ */
+ public function setCasesensitive($casesensitive) {
+ $this->casesensitive = $casesensitive;
+ }
+
+ /**
+ * When using this as a custom selector, this method will be called.
+ * It translates each parameter into the appropriate setXXX() call.
+ *
+ * @param array $parameters the complete set of parameters for this selector
+ */
+ public function setParameters($parameters) {
+ parent::setParameters($parameters);
+ if ($parameters !== null) {
+ for ($i=0,$size=count($parameters); $i < $size; $i++) {
+ $paramname = $parameters[$i]->getName();
+ switch(strtolower($paramname)) {
+ case self::CONTAINS_KEY:
+ $this->setText($parameters[$i]->getValue());
+ break;
+ case self::CASE_KEY:
+ $this->setCasesensitive($parameters[$i]->getValue());
+ break;
+ default:
+ $this->setError("Invalid parameter " . $paramname);
+ }
+ } // for each param
+ } // if params
+ }
+
+ /**
+ * Checks to make sure all settings are kosher. In this case, it
+ * means that the pattern attribute has been set.
+ *
+ */
+ public function verifySettings() {
+ if ($this->contains === null) {
+ $this->setError("The text attribute is required");
+ }
+ }
+
+ /**
+ * The heart of the matter. This is where the selector gets to decide
+ * on the inclusion of a file in a particular fileset.
+ *
+ * @param basedir the base directory the scan is being done from
+ * @param filename is the name of the file to check
+ * @param file a PhingFile object the selector can use
+ * @return whether the file should be selected or not
+ */
+ public function isSelected(PhingFile $basedir, $filename, PhingFile $file) {
+
+ $this->validate();
+
+ if ($file->isDirectory()) {
+ return true;
+ }
+
+ $userstr = $this->contains;
+ if (!$this->casesensitive) {
+ $userstr = strtolower($this->contains);
+ }
+
+ $in = null;
+ try {
+ $in = new BufferedReader(new FileReader($file));
+ $teststr = $in->readLine();
+ while ($teststr !== null) {
+ if (!$this->casesensitive) {
+ $teststr = strtolower($teststr);
+ }
+ if (strpos($teststr, $userstr) !== false) {
+ return true;
+ }
+ $teststr = $in->readLine();
+ }
+ return false;
+ } catch (IOException $ioe) {
+ if ($in) $in->close();
+ throw new BuildException("Could not read file " . $filename);
+ }
+ $in->close();
+ }
+
+}
+
diff --git a/buildscripts/phing/classes/phing/types/selectors/DateSelector.php b/buildscripts/phing/classes/phing/types/selectors/DateSelector.php
new file mode 100644
index 00000000..96e5c3ba
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/DateSelector.php
@@ -0,0 +1,214 @@
+<?php
+
+/*
+ * $Id: DateSelector.php,v 1.10 2005/05/26 13:10:53 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/types/selectors/BaseExtendSelector.php';
+
+/**
+ * Selector that chooses files based on their last modified date. Ant uses
+ * millisecond precision (thanks to Java); PHP is forced to use only seconds
+ * precision.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Bruce Atherton <bruce@callenish.com> (Ant)
+ * @version $Revision: 1.10 $
+ * @package phing.types.selecctors
+ */
+class DateSelector extends BaseExtendSelector {
+
+ private $seconds = -1; // millis in Ant, but PHP doesn't support that level of precision
+ private $dateTime = null;
+ private $includeDirs = false;
+ private $granularity = 0;
+ private $cmp = 2;
+ const MILLIS_KEY = "millis";
+ const DATETIME_KEY = "datetime";
+ const CHECKDIRS_KEY = "checkdirs";
+ const GRANULARITY_KEY = "granularity";
+ const WHEN_KEY = "when";
+ private static $timeComparisons = array("before", "after", "equal");
+
+ public function __construct() {
+ //if (Os.isFamily("dos")) {
+ // granularity = 2000;
+ //}
+ }
+
+ public function toString() {
+ $buf = "{dateselector date: ";
+ $buf .= $this->dateTime;
+ $buf .= " compare: ";
+ if ($this->cmp === 0) {
+ $buf .= "before";
+ } elseif ($this->cmp === 1) {
+ $buf .= "after";
+ } else {
+ $buf .= "equal";
+ }
+ $buf .= " granularity: ";
+ $buf .= $this->granularity;
+ $buf .= "}";
+ return $buf;
+ }
+
+ /**
+ * For users that prefer to express time in seconds since 1970
+ *
+ * @param int $seconds the time to compare file's last modified date to,
+ * expressed in milliseconds
+ */
+ public function setSeconds($seconds) {
+ $this->seconds = (int) $seconds;
+ }
+
+ /**
+ * Returns the seconds value the selector is set for.
+ */
+ public function getSeconds() {
+ return $this->seconds;
+ }
+
+ /**
+ * Sets the date. The user must supply it in MM/DD/YYYY HH:MM AM_PM
+ * format
+ *
+ * @param string $dateTime a string in MM/DD/YYYY HH:MM AM_PM format
+ */
+ public function setDatetime($dateTime) {
+ $dt = strtotime($dateTime);
+ if ($dt == -1) {
+ $this->setError("Date of " . $dateTime
+ . " Cannot be parsed correctly. It should be in"
+ . " a format parsable by PHP's strtotime() function.");
+ } else {
+ $this->dateTime = $dateTime;
+ $this->setSeconds($dt);
+ }
+ }
+
+ /**
+ * Should we be checking dates on directories?
+ *
+ * @param boolean $includeDirs whether to check the timestamp on directories
+ */
+ public function setCheckdirs($includeDirs) {
+ $this->includeDirs = (boolean) $includeDirs;
+ }
+
+ /**
+ * Sets the number of milliseconds leeway we will give before we consider
+ * a file not to have matched a date.
+ * @param int $granularity
+ */
+ public function setGranularity($granularity) {
+ $this->granularity = (int) $granularity;
+ }
+
+ /**
+ * Sets the type of comparison to be done on the file's last modified
+ * date.
+ *
+ * @param string $cmp The comparison to perform
+ */
+ public function setWhen($cmp) {
+ $idx = array_search($cmp, self::$timeComparisons, true);
+ if ($idx === null) {
+ $this->setError("Invalid value for ".WHEN_KEY.": ".$cmp);
+ } else {
+ $this->cmp = $idx;
+ }
+ }
+
+ /**
+ * When using this as a custom selector, this method will be called.
+ * It translates each parameter into the appropriate setXXX() call.
+ *
+ * @param array $parameters the complete set of parameters for this selector
+ */
+ public function setParameters($parameters) {
+ parent::setParameters($parameters);
+ if ($parameters !== null) {
+ for ($i=0,$size=count($parameters); $i < $size; $i++) {
+ $paramname = $parameters[$i]->getName();
+ switch(strtolower($paramname)) {
+ case self::MILLIS_KEY:
+ $this->setMillis($parameters[$i]->getValue());
+ break;
+ case self::DATETIME_KEY:
+ $this->setDatetime($parameters[$i]->getValue());
+ break;
+ case self::CHECKDIRS_KEY:
+ $this->setCheckdirs($parameters[$i]->getValue());
+ break;
+ case self::GRANULARITY_KEY:
+ $this->setGranularity($parameters[$i]->getValue());
+ break;
+ case self::WHEN_KEY:
+ $this->setWhen($parameters[$i]->getValue());
+ break;
+ default:
+ $this->setError("Invalid parameter " . $paramname);
+ } // switch
+ }
+ }
+ }
+
+ /**
+ * This is a consistency check to ensure the selector's required
+ * values have been set.
+ */
+ public function verifySettings() {
+ if ($this->dateTime === null && $this->seconds < 0) {
+ $this->setError("You must provide a datetime or the number of "
+ . "seconds.");
+ } elseif ($this->seconds < 0) {
+ $this->setError("Date of " . $this->dateTime
+ . " results in negative seconds"
+ . " value relative to epoch (January 1, 1970, 00:00:00 GMT).");
+ }
+ }
+
+ /**
+ * The heart of the matter. This is where the selector gets to decide
+ * on the inclusion of a file in a particular fileset.
+ *
+ * @param PhingFile $basedir the base directory the scan is being done from
+ * @param string $filename is the name of the file to check
+ * @param PhingFile $file is a PhingFile object the selector can use
+ * @return boolean Whether the file should be selected or not
+ */
+ public function isSelected(PhingFile $basedir, $filename, PhingFile $file) {
+ $this->validate();
+ if ($file->isDirectory() && ($this->includeDirs === false)) {
+ return true;
+ }
+ if ($this->cmp === 0) {
+ return (($file->lastModified() - $this->granularity) < $this->seconds);
+ } elseif ($this->cmp === 1) {
+ return (($file->lastModified() . $this->granularity) > $this->seconds);
+ } else {
+ return (abs($file->lastModified() - $this->seconds) <= $this->granularity);
+ }
+ }
+
+}
+
+
diff --git a/buildscripts/phing/classes/phing/types/selectors/DependSelector.php b/buildscripts/phing/classes/phing/types/selectors/DependSelector.php
new file mode 100644
index 00000000..db73c512
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/DependSelector.php
@@ -0,0 +1,151 @@
+<?php
+
+/*
+ * $Id: DependSelector.php,v 1.8 2005/05/26 13:10:53 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/types/selectors/BaseSelector.php';
+
+/**
+ * Selector that filters files based on whether they are newer than
+ * a matching file in another directory tree. It can contain a mapper
+ * element, so isn't available as an ExtendSelector (since those
+ * parameters can't hold other elements).
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Bruce Atherton <bruce@callenish.com> (Ant)
+ * @version $Revision: 1.8 $
+ * @package phing.types.selectors
+ */
+class DependSelector extends BaseSelector {
+
+ private $targetdir = null;
+ private $mapperElement = null;
+ private $map = null;
+ private $granularity = 0;
+
+ public function __construct() {
+ // not yet supported:
+ //if (Os.isFamily("dos")) {
+ // $this->granularity = 2000;
+ //}
+ }
+
+ public function toString() {
+ $buf = "{dependselector targetdir: ";
+ if ($this->targetdir === null) {
+ $buf .= "NOT YET SET";
+ } else {
+ $buf .= $this->targetdir->getName();
+ }
+ $buf .= " granularity: ";
+ $buf .= $this->granularity;
+ if ($this->map !== null) {
+ $buf .= " mapper: ";
+ $buf .= $this->map->toString();
+ } elseif ($this->mapperElement !== null) {
+ $buf .= " mapper: ";
+ $buf .= $this->mapperElement->toString();
+ }
+ $buf .= "}";
+ return $buf;
+ }
+
+ /**
+ * The name of the file or directory which is checked for out-of-date
+ * files.
+ *
+ * @param targetdir the directory to scan looking for files.
+ */
+ public function setTargetdir(PhingFile $targetdir) {
+ $this->targetdir = $targetdir;
+ }
+
+ /**
+ * Sets the number of milliseconds leeway we will give before we consider
+ * a file out of date.
+ */
+ public function setGranularity($granularity) {
+ $this->granularity = (int) granularity;
+ }
+
+ /**
+ * Defines the FileNameMapper to use (nested mapper element).
+ * @throws BuildException
+ */
+ public function createMapper() {
+ if ($this->mapperElement !== null) {
+ throw new BuildException("Cannot define more than one mapper");
+ }
+ $this->mapperElement = new Mapper($this->project);
+ return $this->mapperElement;
+ }
+
+
+ /**
+ * Checks to make sure all settings are kosher. In this case, it
+ * means that the dest attribute has been set and we have a mapper.
+ */
+ public function verifySettings() {
+ if ($this->targetdir === null) {
+ $this->setError("The targetdir attribute is required.");
+ }
+ if ($this->mapperElement === null) {
+ $this->map = new IdentityMapper();
+ } else {
+ $this->map = $this->mapperElement->getImplementation();
+ }
+ if ($this->map === null) {
+ $this->setError("Could not set <mapper> element.");
+ }
+ }
+
+ /**
+ * The heart of the matter. This is where the selector gets to decide
+ * on the inclusion of a file in a particular fileset.
+ *
+ * @param basedir the base directory the scan is being done from
+ * @param filename is the name of the file to check
+ * @param file is a PhingFile object the selector can use
+ * @return whether the file should be selected or not
+ */
+ public function isSelected(PhingFile $basedir, $filename, PhingFile $file) {
+
+ $this->validate();
+
+ // Determine file whose out-of-dateness is to be checked
+ $destfiles = $this->map->main($filename);
+
+ // If filename does not match the To attribute of the mapper
+ // then filter it out of the files we are considering
+ if ($destfiles === null) {
+ return false;
+ }
+ // Sanity check
+ if (count($destfiles) !== 1 || $destfiles[0] === null) {
+ throw new BuildException("Invalid destination file results for " . $this->targetdir . " with filename " . $filename);
+ }
+ $destname = $destfiles[0];
+ $destfile = new PhingFile($this->targetdir, $destname);
+
+ return SelectorUtils::isOutOfDate($file, $destfile, $this->granularity);
+ }
+
+}
+
diff --git a/buildscripts/phing/classes/phing/types/selectors/DepthSelector.php b/buildscripts/phing/classes/phing/types/selectors/DepthSelector.php
new file mode 100644
index 00000000..3faafe96
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/DepthSelector.php
@@ -0,0 +1,158 @@
+<?php
+/*
+ * $Id: DepthSelector.php,v 1.7 2005/05/26 13:10:53 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/types/selectors/BaseExtendSelector.php';
+
+/**
+ * Selector that filters files based on the how deep in the directory
+ * tree they are.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Bruce Atherton <bruce@callenish.com> (Ant)
+ * @version $Revision: 1.7 $
+ * @package phing.types.selectors
+ */
+class DepthSelector extends BaseExtendSelector {
+
+ public $min = -1;
+ public $max = -1;
+ const MIN_KEY = "min";
+ const MAX_KEY = "max";
+
+ public function toString() {
+ $buf = "{depthselector min: ";
+ $buf .= $this->min;
+ $buf .= " max: ";
+ $buf .= $this->max;
+ $buf .= "}";
+ return $buf;
+ }
+
+ /**
+ * The minimum depth below the basedir before a file is selected.
+ *
+ * @param min minimum directory levels below basedir to go
+ */
+ public function setMin($min) {
+ $this->min = (int) $min;
+ }
+
+ /**
+ * The minimum depth below the basedir before a file is selected.
+ *
+ * @param min maximum directory levels below basedir to go
+ */
+ public function setMax($max) {
+ $this->max = (int) $max;
+ }
+
+ /**
+ * When using this as a custom selector, this method will be called.
+ * It translates each parameter into the appropriate setXXX() call.
+ *
+ * @param parameters the complete set of parameters for this selector
+ */
+ public function setParameters($parameters) {
+ parent::setParameters($parameters);
+ if ($parameters !== null) {
+ for ($i = 0, $size=count($parameters); $i < $size; $i++) {
+ $paramname = $parameters[$i]->getName();
+ switch(strtolower($paramname)) {
+ case self::MIN_KEY:
+ $this->setMin($parameters[$i]->getValue());
+ break;
+ case self::MAX_KEY:
+ $this->setMax($parameters[$i]->getValue());
+ break;
+
+ default:
+ $this->setError("Invalud parameter " . $paramname);
+ } // switch
+ }
+ }
+ }
+
+ /**
+ * Checks to make sure all settings are kosher. In this case, it
+ * means that the max depth is not lower than the min depth.
+ */
+ public function verifySettings() {
+ if ($this->min < 0 && $this->max < 0) {
+ $this->setError("You must set at least one of the min or the " .
+ "max levels.");
+ }
+ if ($this->max < $this->min && $this->max > -1) {
+ $this->setError("The maximum depth is lower than the minimum.");
+ }
+ }
+
+ /**
+ * The heart of the matter. This is where the selector gets to decide
+ * on the inclusion of a file in a particular fileset. Most of the work
+ * for this selector is offloaded into SelectorUtils, a static class
+ * that provides the same services for both FilenameSelector and
+ * DirectoryScanner.
+ *
+ * @param basedir the base directory the scan is being done from
+ * @param filename is the name of the file to check
+ * @param file is a PhingFile object the selector can use
+ * @return whether the file should be selected or not
+ */
+ public function isSelected(PhingFile $basedir, $filename, PhingFile $file) {
+
+ $this->validate();
+
+ $depth = -1;
+ // If you felt daring, you could cache the basedir absolute path
+ $abs_base = $basedir->getAbsolutePath();
+ $abs_file = $file->getAbsolutePath();
+
+ $tok_base = explode(DIRECTORY_SEPARATOR, $abs_base);
+ $tok_file = explode(DIRECTORY_SEPARATOR, $abs_file);
+
+ for($i=0,$size=count($tok_file); $i < $size; $i++) {
+ $filetoken = $tok_file[$i];
+ if (isset($tok_base[$i])) {
+ $basetoken = $tok_base[$i];
+ // Sanity check. Ditch it if you want faster performance
+ if ($basetoken !== $filetoken) {
+ throw new BuildException("File " . $filename .
+ " does not appear within " . $abs_base . "directory");
+ }
+ } else { // no more basepath tokens
+ $depth++;
+ if ($this->max > -1 && $depth > $this->max) {
+ return false;
+ }
+ }
+ }
+ if (isset($tok_base[$i + 1])) {
+ throw new BuildException("File " . $filename .
+ " is outside of " . $abs_base . "directory tree");
+ }
+ if ($this->min > -1 && $depth < $this->min) {
+ return false;
+ }
+ return true;
+ }
+
+}
+
diff --git a/buildscripts/phing/classes/phing/types/selectors/ExtendFileSelector.php b/buildscripts/phing/classes/phing/types/selectors/ExtendFileSelector.php
new file mode 100644
index 00000000..84a3ee5b
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/ExtendFileSelector.php
@@ -0,0 +1,43 @@
+<?php
+
+/*
+ * $Id: ExtendFileSelector.php,v 1.5 2004/02/16 05:28:40 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/types/Parameterizable.php';
+require_once 'phing/types/selectors/FileSelector.php';
+
+/**
+ * This is the interface to be used by all custom selectors, those that are
+ * called through the &lt;custom&gt; tag. It is the amalgamation of two
+ * interfaces, the FileSelector and the Paramterizable interface. Note that
+ * you will almost certainly want the default behaviour for handling
+ * Parameters, so you probably want to use the BaseExtendSelector class
+ * as the base class for your custom selector rather than implementing
+ * this interface from scratch.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Bruce Atherton <bruce@callenish.com> (Ant)
+ * @package phing.types.selectors
+ */
+interface ExtendFileSelector extends Parameterizable, FileSelector {
+ // No further methods necessary. This is just an amalgamation of two other
+ // interfaces.
+}
+
diff --git a/buildscripts/phing/classes/phing/types/selectors/ExtendSelector.php b/buildscripts/phing/classes/phing/types/selectors/ExtendSelector.php
new file mode 100644
index 00000000..cc939254
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/ExtendSelector.php
@@ -0,0 +1,127 @@
+<?php
+
+/*
+ * $Id: ExtendSelector.php,v 1.10 2005/05/26 13:10:53 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/util/StringHelper.php';
+
+/**
+ * Selector that selects files by forwarding the request on to other classes.
+ *
+ * TODO:
+ * Consider adding Path (org.apache.tools.ant.types.Path) support to this class
+ * and to the Mappers class. See Ant versions for implimentation details.
+ *
+ * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
+ * @package phing.types.selectors
+ */
+class ExtendSelector extends BaseSelector {
+
+ private $classname;
+ private $dynselector;
+ private $parameters = array();
+
+ /**
+ * Sets the classname of the custom selector.
+ *
+ * @param classname is the class which implements this selector
+ */
+ public function setClassname($classname) {
+ $this->classname = $classname;
+ }
+
+ /**
+ * Instantiates the identified custom selector class.
+ */
+ public function selectorCreate() {
+ if ($this->classname !== null && $this->classname !== "") {
+ try {
+ // assume it's fully qualified, import it
+ $cls = Phing::import($this->classname);
+
+ // make sure class exists
+ if (class_exists($cls)) {
+ $this->dynselector = new $cls();
+ } else {
+ $this->setError("Selector " . $this->classname . " not initialized, no such class");
+ }
+ } catch (Exception $e) {
+ $this->setError("Selector " . $this->classname . " not initialized, could not create class: " . $e->getMessage());
+ }
+ } else {
+ $this->setError("There is no classname specified");
+ }
+ }
+
+ /**
+ * Create new parameters to pass to custom selector.
+ *
+ * @param p The new Parameter object
+ */
+ public function addParam(Parameter $p) {
+ $this->parameters[] = $p;
+ }
+
+ /**
+ * These are errors specific to ExtendSelector only. If there are
+ * errors in the custom selector, it should throw a BuildException
+ * when isSelected() is called.
+ */
+ public function verifySettings() {
+ // Creation is done here rather than in isSelected() because some
+ // containers may do a validation pass before running isSelected(),
+ // but we need to check for the existence of the created class.
+ if ($this->dynselector === null) {
+ $this->selectorCreate();
+ }
+
+ if (empty($this->classname)) {
+ $this->setError("The classname attribute is required");
+ } elseif ($this->dynselector === null) {
+ $this->setError("Internal Error: The custom selector was not created");
+ } elseif ( !($this->dynselector instanceof ExtendFileSelector) && (count($this->parameters) > 0)) {
+ $this->setError("Cannot set parameters on custom selector that does not "
+ . "implement ExtendFileSelector.");
+ }
+ }
+
+
+ /**
+ * Allows the custom selector to choose whether to select a file. This
+ * is also where the Parameters are passed to the custom selector,
+ * since we know we must have them all by now. And since we must know
+ * both classpath and classname, creating the class is deferred to here
+ * as well.
+ *
+ * @throws BuildException
+ */
+ public function isSelected(PhingFile $basedir, $filename, PhingFile $file) {
+
+ $this->validate();
+
+ if (count($this->parameters) > 0 && $this->dynselector instanceof ExtendFileSelector) {
+ // We know that dynselector must be non-null if no error message
+ $this->dynselector->setParameters($this->parameters);
+ }
+ return $this->dynselector->isSelected($basedir, $filename, $file);
+ }
+
+}
+
diff --git a/buildscripts/phing/classes/phing/types/selectors/FileSelector.php b/buildscripts/phing/classes/phing/types/selectors/FileSelector.php
new file mode 100644
index 00000000..05926c86
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/FileSelector.php
@@ -0,0 +1,47 @@
+<?php
+
+/*
+ * $Id: FileSelector.php,v 1.4 2005/05/26 13:10:53 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * This is the interface to be used by all selectors.
+ *
+ * @author Hans Lellelid, hans@xmpl.org (Phing)
+ * @author Bruce Atherton, bruce@callenish.com (Ant)
+ * @package phing.types.selectors
+ */
+interface FileSelector {
+
+ /**
+ * Method that each selector will implement to create their
+ * selection behaviour. If there is a problem with the setup
+ * of a selector, it can throw a BuildException to indicate
+ * the problem.
+ *
+ * @param basedir A PhingFile object for the base directory
+ * @param filename The name of the file to check
+ * @param file A PhingFile object for this filename
+ * @return whether the file should be selected or not
+ * @throws BuildException if the selector was not configured correctly
+ */
+ public function isSelected(PhingFile $basedir, $filename, PhingFile $file);
+
+}
+
diff --git a/buildscripts/phing/classes/phing/types/selectors/FilenameSelector.php b/buildscripts/phing/classes/phing/types/selectors/FilenameSelector.php
new file mode 100644
index 00000000..2315c888
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/FilenameSelector.php
@@ -0,0 +1,157 @@
+<?php
+
+/*
+ * $Id: FilenameSelector.php,v 1.8 2005/05/26 13:10:53 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+
+include_once 'phing/types/selectors/BaseExtendSelector.php';
+
+/**
+ * Selector that filters files based on the filename.
+ *
+ * @author Hans Lellelid, hans@xmpl.org (Phing)
+ * @author Bruce Atherton, bruce@callenish.com (Ant)
+ * @package phing.types.selectors
+ */
+class FilenameSelector extends BaseExtendSelector {
+
+ private $pattern = null;
+ private $casesensitive = true;
+ private $negated = false;
+ const NAME_KEY = "name";
+ const CASE_KEY = "casesensitive";
+ const NEGATE_KEY = "negate";
+
+ public function toString() {
+ $buf = "{filenameselector name: ";
+ $buf .= $this->pattern;
+ $buf .= " negate: ";
+ if ($this->negated) {
+ $buf .= "true";
+ } else {
+ $buf .= "false";
+ }
+ $buf .= " casesensitive: ";
+ if ($this->casesensitive) {
+ $buf .= "true";
+ } else {
+ $buf .= "false";
+ }
+ $buf .= "}";
+ return $buf;
+ }
+
+ /**
+ * The name of the file, or the pattern for the name, that
+ * should be used for selection.
+ *
+ * @param pattern the file pattern that any filename must match
+ * against in order to be selected.
+ */
+ public function setName($pattern) {
+ $pattern = str_replace('\\', DIRECTORY_SEPARATOR, $pattern);
+ $pattern = str_replace('/', DIRECTORY_SEPARATOR, $pattern);
+
+ if (StringHelper::endsWith(DIRECTORY_SEPARATOR, $pattern)) {
+ $pattern .= "**";
+ }
+ $this->pattern = $pattern;
+ }
+
+ /**
+ * Whether to ignore case when checking filenames.
+ *
+ * @param casesensitive whether to pay attention to case sensitivity
+ */
+ public function setCasesensitive($casesensitive) {
+ $this->casesensitive = $casesensitive;
+ }
+
+ /**
+ * You can optionally reverse the selection of this selector,
+ * thereby emulating an &lt;exclude&gt; tag, by setting the attribute
+ * negate to true. This is identical to surrounding the selector
+ * with &lt;not&gt;&lt;/not&gt;.
+ *
+ * @param negated whether to negate this selection
+ */
+ public function setNegate($negated) {
+ $this->negated = $negated;
+ }
+
+ /**
+ * When using this as a custom selector, this method will be called.
+ * It translates each parameter into the appropriate setXXX() call.
+ *
+ * @param array $parameters the complete set of parameters for this selector
+ */
+ public function setParameters($parameters) {
+ parent::setParameters($parameters);
+ if ($parameters !== null) {
+ for ($i=0, $len=count($parameters); $i < $len; $i++) {
+ $paramname = $parameters[$i]->getName();
+ switch(strtolower($paramname)) {
+ case self::NAME_KEY:
+ $this->setName($parameters[$i]->getValue());
+ break;
+ case self::CASE_KEY:
+ $this->setCasesensitive($parameters[$i]->getValue());
+ break;
+ case self::NEGATE_KEY:
+ $this->setNegate($parameters[$i]->getValue());
+ break;
+ default:
+ $this->setError("Invalid parameter " . $paramname);
+ }
+ } // for each param
+ } // if params
+ }
+
+ /**
+ * Checks to make sure all settings are kosher. In this case, it
+ * means that the name attribute has been set.
+ *
+ */
+ public function verifySettings() {
+ if ($this->pattern === null) {
+ $this->setError("The name attribute is required");
+ }
+ }
+
+ /**
+ * The heart of the matter. This is where the selector gets to decide
+ * on the inclusion of a file in a particular fileset. Most of the work
+ * for this selector is offloaded into SelectorUtils, a static class
+ * that provides the same services for both FilenameSelector and
+ * DirectoryScanner.
+ *
+ * @param basedir the base directory the scan is being done from
+ * @param filename is the name of the file to check
+ * @param file is a PhingFile object the selector can use
+ * @return whether the file should be selected or not
+ */
+ public function isSelected(PhingFile $basedir, $filename, PhingFile $file) {
+ $this->validate();
+ return (SelectorUtils::matchPath($this->pattern, $filename, $this->casesensitive)
+ === !($this->negated));
+ }
+
+}
+
diff --git a/buildscripts/phing/classes/phing/types/selectors/MajoritySelector.php b/buildscripts/phing/classes/phing/types/selectors/MajoritySelector.php
new file mode 100644
index 00000000..19e0fb76
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/MajoritySelector.php
@@ -0,0 +1,92 @@
+<?php
+
+/*
+ * $Id: MajoritySelector.php,v 1.6 2005/05/26 13:10:53 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+
+/**
+ * This selector is here just to shake up your thinking a bit. Don't get
+ * too caught up in boolean, there are other ways you can evaluate a
+ * collection of selectors. This one takes a vote of the selectors it
+ * contains, and majority wins. You could also have an "all-but-one"
+ * selector, a "weighted-average" selector, and so on. These are left
+ * as exercises for the reader (as are the usecases where this would
+ * be necessary).
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Bruce Atherton <bruce@callenish.com> (Ant)
+ * @package phing.types.selectors
+ */
+class MajoritySelector extends BaseSelectorContainer {
+
+ private $allowtie = true;
+
+ public function toString() {
+ $buf = "";
+ if ($this->hasSelectors()) {
+ $buf .= "{majorityselect: ";
+ $buf .= parent::toString();
+ $buf .= "}";
+ }
+ return $buf;
+ }
+
+ public function setAllowtie($tiebreaker) {
+ $this->allowtie = $tiebreaker;
+ }
+
+ /**
+ * Returns true (the file is selected) if most of the other selectors
+ * agree. In case of a tie, go by the allowtie setting. That defaults
+ * to true, meaning in case of a tie, the file is selected.
+ *
+ * @param basedir the base directory the scan is being done from
+ * @param filename is the name of the file to check
+ * @param file is a PhingFile object for the filename that the selector
+ * can use
+ * @return whether the file should be selected or not
+ */
+ public function isSelected(PhingFile $basedir, $filename, PhingFile $file) {
+
+ $this->validate();
+
+ $yesvotes = 0;
+ $novotes = 0;
+
+ $selectors = $this->selectorElements();
+ for($i=0,$size=count($selectors); $i < $size; $i++) {
+ $result = $selectors[$i]->isSelected($basedir,$filename,$file);
+ if ($result) {
+ $yesvotes = $yesvotes + 1;
+ } else {
+ $novotes = $novotes + 1;
+ }
+ }
+ if ($yesvotes > $novotes) {
+ return true;
+ }
+ else if ($novotes > $yesvotes) {
+ return false;
+ }
+ // At this point, we know we have a tie.
+ return $this->allowtie;
+ }
+}
+
diff --git a/buildscripts/phing/classes/phing/types/selectors/NoneSelector.php b/buildscripts/phing/classes/phing/types/selectors/NoneSelector.php
new file mode 100644
index 00000000..844078a5
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/NoneSelector.php
@@ -0,0 +1,71 @@
+<?php
+/*
+ * $Id: NoneSelector.php,v 1.6 2005/05/26 13:10:53 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/types/selectors/BaseSelectorContainer.php';
+
+/**
+ * This selector has a collection of other selectors. All of those selectors
+ * must refuse to select a file before the file is considered selected by
+ * this selector.
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @author Bruce Atherton <bruce@callenish.com> (Ant)
+ * @package phing.types.selectors
+ */
+class NoneSelector extends BaseSelectorContainer {
+
+ public function toString() {
+ $buf = "";
+ if ($this->hasSelectors()) {
+ $buf .= "{noneselect: ";
+ $buf .= parent::toString();
+ $buf .= "}";
+ }
+ return $buf;
+ }
+
+ /**
+ * Returns true (the file is selected) only if all other selectors
+ * agree that the file should not be selected.
+ *
+ * @param basedir the base directory the scan is being done from
+ * @param filename is the name of the file to check
+ * @param file is a java.io.File object for the filename that the selector
+ * can use
+ * @return whether the file should be selected or not
+ */
+ public function isSelected(PhingFile $basedir, $filename, PhingFile $file) {
+
+ $this->validate();
+
+ $selectors = $this->selectorElements();
+
+ for($i=0,$size=count($selectors); $i < $size; $i++) {
+ $result = $selectors[$i]->isSelected($basedir, $filename, $file);
+ if ($result) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+}
+
diff --git a/buildscripts/phing/classes/phing/types/selectors/NotSelector.php b/buildscripts/phing/classes/phing/types/selectors/NotSelector.php
new file mode 100644
index 00000000..90237084
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/NotSelector.php
@@ -0,0 +1,59 @@
+<?php
+
+/*
+ * $Id: NotSelector.php,v 1.4 2003/12/24 17:43:26 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/types/selectors/NoneSelector.php';
+
+/**
+ * This selector has one other selectors whose meaning it inverts. It
+ * actually relies on NoneSelector for its implementation of the
+ * isSelected() method, but it adds a check to ensure there is only one
+ * other selector contained within.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Bruce Atherton <bruce@callenish.com> (Ant)
+ * @package phing.types.selectors
+ */
+class NotSelector extends NoneSelector {
+
+ public function toString() {
+ $buf = "";
+ if ($this->hasSelectors()) {
+ $buf .= "{notselect: ";
+ $buf .= parent::toString();
+ $buf .= "}";
+ }
+ return $buf;
+ }
+
+ /**
+ * Makes sure that there is only one entry, sets an error message if
+ * not.
+ */
+ public function verifySettings() {
+ if ($this->selectorCount() != 1) {
+ $this->setError("One and only one selector is allowed within the " .
+ "<not> tag");
+ }
+ }
+
+}
+
diff --git a/buildscripts/phing/classes/phing/types/selectors/OrSelector.php b/buildscripts/phing/classes/phing/types/selectors/OrSelector.php
new file mode 100644
index 00000000..6a8778fa
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/OrSelector.php
@@ -0,0 +1,72 @@
+<?php
+/*
+ * $Id: OrSelector.php,v 1.7 2005/05/26 13:10:53 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/types/selectors/BaseSelectorContainer.php';
+
+/**
+ * This selector has a collection of other selectors, any of which have to
+ * select a file in order for this selector to select it.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Bruce Atherton <bruce@callenish.com> (Ant)
+ * @package phing.types.selectors
+ */
+class OrSelector extends BaseSelectorContainer {
+
+ public function toString() {
+ $buf = "";
+ if ($this->hasSelectors()) {
+ $buf .= "{orselect: ";
+ $buf .= parent::toString();
+ $buf .= "}";
+ }
+ return $buf;
+ }
+
+ /**
+ * Returns true (the file is selected) if any of the other selectors
+ * agree that the file should be selected.
+ *
+ * @param basedir the base directory the scan is being done from
+ * @param filename the name of the file to check
+ * @param file a PhingFile object for the filename that the selector
+ * can use
+ * @return boolean Whether the file should be selected or not
+ */
+ public function isSelected(PhingFile $basedir, $filename, PhingFile $file) {
+
+ $this->validate();
+
+ $selectors = $this->selectorElements();
+
+ // First, check that all elements are correctly configured
+
+ for($i=0,$size=count($selectors); $i < $size; $i++) {
+ $result = $selectors[$i]->isSelected($basedir, $filename, $file);
+ if ($result) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
+
diff --git a/buildscripts/phing/classes/phing/types/selectors/PresentSelector.php b/buildscripts/phing/classes/phing/types/selectors/PresentSelector.php
new file mode 100644
index 00000000..f5f4c880
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/PresentSelector.php
@@ -0,0 +1,154 @@
+<?php
+
+/*
+ * $Id: PresentSelector.php,v 1.9 2005/05/26 13:10:53 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * Selector that filters files based on whether they appear in another
+ * directory tree. It can contain a mapper element, so isn't available
+ * as an ExtendSelector (since those parameters can't hold other
+ * elements).
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Bruce Atherton <bruce@callenish.com> (Ant)
+ * @package phing.types.selectors
+ */
+class PresentSelector extends BaseSelector {
+
+ private $targetdir = null;
+ private $mapperElement = null;
+ private $map = null;
+ private $destmustexist = true;
+ private static $filePresence = array("srconly", "both");
+
+ public function toString() {
+ $buf = "{presentselector targetdir: ";
+ if ($this->targetdir === null) {
+ $buf .= "NOT YET SET";
+ } else {
+ $buf .= $this->targetdir->getName();
+ }
+ $buf .= " present: ";
+ if ($this->destmustexist) {
+ $buf .= "both";
+ } else {
+ $buf .= "srconly";
+ }
+ if ($this->map !== null) {
+ $buf .= $this->map->toString();
+ } elseif ($this->mapperElement !== null) {
+ $buf .= $this->mapperElement->toString();
+ }
+ $buf .= "}";
+ return $buf;
+ }
+
+ /**
+ * The name of the file or directory which is checked for matching
+ * files.
+ *
+ * @param targetdir the directory to scan looking for matching files.
+ */
+ public function setTargetdir(PhingFile $targetdir) {
+ $this->targetdir = $targetdir;
+ }
+
+ /**
+ * Defines the FileNameMapper to use (nested mapper element).
+ * @throws BuildException
+ */
+ public function createMapper() {
+ if ($this->mapperElement !== null) {
+ throw new BuildException("Cannot define more than one mapper");
+ }
+ $this->mapperElement = new Mapper($this->getProject());
+ return $this->mapperElement;
+ }
+
+
+ /**
+ * This sets whether to select a file if its dest file is present.
+ * It could be a <code>negate</code> boolean, but by doing things
+ * this way, we get some documentation on how the system works.
+ * A user looking at the documentation should clearly understand
+ * that the ONLY files whose presence is being tested are those
+ * that already exist in the source directory, hence the lack of
+ * a <code>destonly</code> option.
+ *
+ * @param string $fp An attribute set to either <code>srconly</code or
+ * ><code>both</code>.
+ */
+ public function setPresent($fp) {
+ $idx = array_search($fp, self::$filePresence, true);
+ if ( $idx === 0 ) {
+ $this->destmustexist = false;
+ }
+ }
+
+ /**
+ * Checks to make sure all settings are kosher. In this case, it
+ * means that the targetdir attribute has been set and we have a mapper.
+ */
+ public function verifySettings() {
+ if ($this->targetdir === null) {
+ $this->setError("The targetdir attribute is required.");
+ }
+ if ($this->mapperElement === null) {
+ $this->map = new IdentityMapper();
+ } else {
+ $this->map = $this->mapperElement->getImplementation();
+ }
+ if ($this->map === null) {
+ $this->setError("Could not set <mapper> element.");
+ }
+ }
+
+ /**
+ * The heart of the matter. This is where the selector gets to decide
+ * on the inclusion of a file in a particular fileset.
+ *
+ * @param basedir the base directory the scan is being done from
+ * @param filename is the name of the file to check
+ * @param file is a PhingFile object the selector can use
+ * @return whether the file should be selected or not
+ */
+ public function isSelected(PhingFile $basedir, $filename, PhingFile $file) {
+
+ $this->validate();
+
+ // Determine file whose existence is to be checked
+ $destfiles = $this->map->main($filename);
+ // If filename does not match the To attribute of the mapper
+ // then filter it out of the files we are considering
+ if ($destfiles === null) {
+ return false;
+ }
+ // Sanity check
+ if (count($destfiles) !== 1 || $destfiles[0] === null) {
+ throw new BuildException("Invalid destination file results for "
+ . $this->targetdir . " with filename " . $filename);
+ }
+ $destname = $destfiles[0];
+ $destfile = new PhingFile($this->targetdir, $destname);
+ return $destfile->exists() === $this->destmustexist;
+ }
+
+}
+
diff --git a/buildscripts/phing/classes/phing/types/selectors/SelectSelector.php b/buildscripts/phing/classes/phing/types/selectors/SelectSelector.php
new file mode 100644
index 00000000..a7644447
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/SelectSelector.php
@@ -0,0 +1,124 @@
+<?php
+
+/*
+ * $Id: SelectSelector.php,v 1.6 2003/12/24 17:43:26 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/types/selectors/AndSelector.php';
+
+/**
+ * This selector just holds one other selector and forwards all
+ * requests to it. It exists so that there is a single selector
+ * type that can exist outside of any targets, as an element of
+ * project. It overrides all of the reference stuff so that it
+ * works as expected. Note that this is the only selector you
+ * can reference.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Bruce Atherton <bruce@callenish.com> (Ant)
+ * @version $Revision: 1.6 $
+ * @package phing.types.selectors
+ */
+class SelectSelector extends AndSelector {
+
+ public function toString() {
+ $buf = "";
+ if ($this->hasSelectors()) {
+ $buf .= "{select: ";
+ $buf .= parent::toString();
+ $buf .= "}";
+ }
+ return $buf;
+ }
+
+ /**
+ * Performs the check for circular references and returns the
+ * referenced Selector.
+ */
+ private function getRef() {
+ $o = $this->getCheckedRef(get_class($this), "SelectSelector");
+ return $o;
+ }
+
+ /**
+ * Indicates whether there are any selectors here.
+ */
+ public function hasSelectors() {
+ if ($this->isReference()) {
+ return $this->getRef()->hasSelectors();
+ }
+ return parent::hasSelectors();
+ }
+
+ /**
+ * Gives the count of the number of selectors in this container
+ */
+ public function selectorCount() {
+ if ($this->isReference()) {
+ return $this->getRef()->selectorCount();
+ }
+ return parent::selectorCount();
+ }
+
+ /**
+ * Returns the set of selectors as an array.
+ */
+ public function getSelectors(Project $p) {
+ if ($this->isReference()) {
+ return $this->getRef()->getSelectors($p);
+ }
+ return parent::getSelectors($p);
+ }
+
+ /**
+ * Returns an enumerator for accessing the set of selectors.
+ */
+ public function selectorElements() {
+ if ($this->isReference()) {
+ return $this->getRef()->selectorElements();
+ }
+ return parent::selectorElements();
+ }
+
+ /**
+ * Add a new selector into this container.
+ *
+ * @param selector the new selector to add
+ * @return the selector that was added
+ */
+ public function appendSelector(FileSelector $selector) {
+ if ($this->isReference()) {
+ throw $this->noChildrenAllowed();
+ }
+ parent::appendSelector($selector);
+ }
+
+ /**
+ * Makes sure that there is only one entry, sets an error message if
+ * not.
+ */
+ public function verifySettings() {
+ if ($this->selectorCount() != 1) {
+ $this->setError("One and only one selector is allowed within the "
+ . "<selector> tag");
+ }
+ }
+
+}
+
diff --git a/buildscripts/phing/classes/phing/types/selectors/SelectorContainer.php b/buildscripts/phing/classes/phing/types/selectors/SelectorContainer.php
new file mode 100644
index 00000000..4a73b113
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/SelectorContainer.php
@@ -0,0 +1,141 @@
+<?php
+
+/*
+ * $Id: SelectorContainer.php,v 1.3 2003/11/19 05:48:30 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+
+/**
+ * This is the interface for selectors that can contain other selectors.
+ *
+ * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
+ * @package phing.types.selectors
+ */
+interface SelectorContainer {
+
+ /**
+ * Indicates whether there are any selectors here.
+ *
+ * @return whether any selectors are in this container
+ */
+ public function hasSelectors();
+
+ /**
+ * Gives the count of the number of selectors in this container
+ *
+ * @return the number of selectors in this container
+ */
+ public function selectorCount();
+
+ /**
+ * Returns a *copy* of the set of selectors as an array.
+ *
+ * @return an array of selectors in this container
+ */
+ public function getSelectors(Project $p);
+
+ /**
+ * Returns an array for accessing the set of selectors.
+ *
+ * @return an enumerator that goes through each of the selectors
+ */
+ public function selectorElements();
+
+ /**
+ * Add a new selector into this container.
+ *
+ * @param selector the new selector to add
+ * @return the selector that was added
+ */
+ public function appendSelector(FileSelector $selector);
+
+ /* Methods below all add specific selectors */
+
+ /**
+ * add a "Select" selector entry on the selector list
+ */
+ public function createSelector();
+
+ /**
+ * add an "And" selector entry on the selector list
+ */
+ public function createAnd();
+
+ /**
+ * add an "Or" selector entry on the selector list
+ */
+ public function createOr();
+
+ /**
+ * add a "Not" selector entry on the selector list
+ */
+ public function createNot();
+
+ /**
+ * add a "None" selector entry on the selector list
+ */
+ public function createNone();
+
+ /**
+ * add a majority selector entry on the selector list
+ */
+ public function createMajority();
+
+ /**
+ * add a selector date entry on the selector list
+ */
+ public function createDate();
+
+ /**
+ * add a selector size entry on the selector list
+ */
+ public function createSize();
+
+ /**
+ * add a selector filename entry on the selector list
+ */
+ public function createFilename();
+
+ /**
+ * add an extended selector entry on the selector list
+ */
+ public function createCustom();
+
+ /**
+ * add a contains selector entry on the selector list
+ */
+ public function createContains();
+
+ /**
+ * add a present selector entry on the selector list
+ */
+ public function createPresent();
+
+ /**
+ * add a depth selector entry on the selector list
+ */
+ public function createDepth();
+
+ /**
+ * add a depends selector entry on the selector list
+ */
+ public function createDepend();
+
+}
+
diff --git a/buildscripts/phing/classes/phing/types/selectors/SelectorScanner.php b/buildscripts/phing/classes/phing/types/selectors/SelectorScanner.php
new file mode 100644
index 00000000..f5bb898a
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/SelectorScanner.php
@@ -0,0 +1,55 @@
+<?php
+
+/*
+ * $Id: SelectorScanner.php,v 1.3 2003/11/19 05:48:30 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+
+/**
+ * An interface used to describe the actions required by any type of
+ * directory scanner that supports Selecters.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Bruce Atherton <bruce@callenish.com> (Ant)
+ * @package phing.types.selectors
+ */
+interface SelectorScanner {
+
+ /**
+ * Sets the selectors the scanner should use.
+ *
+ * @param selectors the list of selectors
+ */
+ public function setSelectors($selectors);
+
+ /**
+ * Directories which were selected out of a scan.
+ *
+ * @param selectors list selector objects
+ */
+ public function getDeselectedDirectories();
+
+ /**
+ * Files which were selected out of a scan.
+ *
+ * @param selectors list selector objects
+ */
+ public function getDeselectedFiles();
+
+}
diff --git a/buildscripts/phing/classes/phing/types/selectors/SelectorUtils.php b/buildscripts/phing/classes/phing/types/selectors/SelectorUtils.php
new file mode 100644
index 00000000..87247e97
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/SelectorUtils.php
@@ -0,0 +1,440 @@
+<?php
+
+/*
+ * $Id: SelectorUtils.php,v 1.5 2005/05/26 13:10:53 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/util/StringHelper.php';
+
+/**
+ * <p>This is a utility class used by selectors and DirectoryScanner. The
+ * functionality more properly belongs just to selectors, but unfortunately
+ * DirectoryScanner exposed these as protected methods. Thus we have to
+ * support any subclasses of DirectoryScanner that may access these methods.
+ * </p>
+ * <p>This is a Singleton.</p>
+ *
+ * @author Hans Lellelid, hans@xmpl.org (Phing)
+ * @author Arnout J. Kuiper, ajkuiper@wxs.nl (Ant)
+ * @author Magesh Umasankar
+ * @author Bruce Atherton, bruce@callenish.com (Ant)
+ * @package phing.types.selectors
+ */
+class SelectorUtils {
+
+ private static $instance;
+
+ /**
+ * Retrieves the instance of the Singleton.
+ */
+ public function getInstance() {
+ if (!isset(self::$instance)) {
+ self::$instance = new SelectorUtils();
+ }
+ return self::$instance;
+ }
+
+ /**
+ * Tests whether or not a given path matches the start of a given
+ * pattern up to the first "**".
+ * <p>
+ * This is not a general purpose test and should only be used if you
+ * can live with false positives. For example, <code>pattern=**\a</code>
+ * and <code>str=b</code> will yield <code>true</code>.
+ *
+ * @param pattern The pattern to match against. Must not be
+ * <code>null</code>.
+ * @param str The path to match, as a String. Must not be
+ * <code>null</code>.
+ * @param isCaseSensitive Whether or not matching should be performed
+ * case sensitively.
+ *
+ * @return whether or not a given path matches the start of a given
+ * pattern up to the first "**".
+ */
+ public function matchPatternStart($pattern, $str, $isCaseSensitive = true) {
+
+ // When str starts with a DIRECTORY_SEPARATOR, pattern has to start with a
+ // DIRECTORY_SEPARATOR.
+ // When pattern starts with a DIRECTORY_SEPARATOR, str has to start with a
+ // DIRECTORY_SEPARATOR.
+ if (StringHelper::startsWith(DIRECTORY_SEPARATOR, $str) !==
+ StringHelper::startsWith(DIRECTORY_SEPARATOR, $pattern)) {
+ return false;
+ }
+
+ $patDirs = explode(DIRECTORY_SEPARATOR, $pattern);
+ $strDirs = explode(DIRECTORY_SEPARATOR, $str);
+
+ $patIdxStart = 0;
+ $patIdxEnd = count($patDirs)-1;
+ $strIdxStart = 0;
+ $strIdxEnd = count($strDirs)-1;
+
+ // up to first '**'
+ while ($patIdxStart <= $patIdxEnd && $strIdxStart <= $strIdxEnd) {
+ $patDir = $patDirs[$patIdxStart];
+ if ($patDir == "**") {
+ break;
+ }
+ if (!self::match($patDir, $strDirs[$strIdxStart], $isCaseSensitive)) {
+ return false;
+ }
+ $patIdxStart++;
+ $strIdxStart++;
+ }
+
+ if ($strIdxStart > $strIdxEnd) {
+ // String is exhausted
+ return true;
+ } elseif ($patIdxStart > $patIdxEnd) {
+ // String not exhausted, but pattern is. Failure.
+ return false;
+ } else {
+ // pattern now holds ** while string is not exhausted
+ // this will generate false positives but we can live with that.
+ return true;
+ }
+ }
+
+ /**
+ * Tests whether or not a given path matches a given pattern.
+ *
+ * @param pattern The pattern to match against. Must not be
+ * <code>null</code>.
+ * @param str The path to match, as a String. Must not be
+ * <code>null</code>.
+ * @param isCaseSensitive Whether or not matching should be performed
+ * case sensitively.
+ *
+ * @return <code>true</code> if the pattern matches against the string,
+ * or <code>false</code> otherwise.
+ */
+ public function matchPath($pattern, $str, $isCaseSensitive = true) {
+
+ // When str starts with a DIRECTORY_SEPARATOR, pattern has to start with a
+ // DIRECTORY_SEPARATOR.
+ // When pattern starts with a DIRECTORY_SEPARATOR, str has to start with a
+ // DIRECTORY_SEPARATOR.
+ if (StringHelper::startsWith(DIRECTORY_SEPARATOR, $str) !==
+ StringHelper::startsWith(DIRECTORY_SEPARATOR, $pattern)) {
+ return false;
+ }
+
+ $patDirs = explode(DIRECTORY_SEPARATOR, $pattern);
+ $strDirs = explode(DIRECTORY_SEPARATOR, $str);
+
+ $patIdxStart = 0;
+ $patIdxEnd = count($patDirs)-1;
+ $strIdxStart = 0;
+ $strIdxEnd = count($strDirs)-1;
+
+ // up to first '**'
+ while ($patIdxStart <= $patIdxEnd && $strIdxStart <= $strIdxEnd) {
+ $patDir = $patDirs[$patIdxStart];
+ if ($patDir == "**") {
+ break;
+ }
+ if (!self::match($patDir, $strDirs[$strIdxStart], $isCaseSensitive)) {
+ return false;
+ }
+ $patIdxStart++;
+ $strIdxStart++;
+ }
+ if ($strIdxStart > $strIdxEnd) {
+ // String is exhausted
+ for ($i=$patIdxStart; $i <= $patIdxEnd; $i++) {
+ if ($patDirs[$i] != "**") {
+ return false;
+ }
+ }
+ return true;
+ } elseif ($patIdxStart > $patIdxEnd) {
+ // String not exhausted, but pattern is. Failure.
+ return false;
+ }
+
+ // up to last '**'
+ while ($patIdxStart <= $patIdxEnd && $strIdxStart <= $strIdxEnd) {
+ $patDir = $patDirs[$patIdxEnd];
+ if ($patDir == "**") {
+ break;
+ }
+ if (!self::match($patDir, $strDirs[$strIdxEnd], $isCaseSensitive)) {
+ return false;
+ }
+ $patIdxEnd--;
+ $strIdxEnd--;
+ }
+
+ if ($strIdxStart > $strIdxEnd) {
+ // String is exhausted
+ for ($i = $patIdxStart; $i <= $patIdxEnd; $i++) {
+ if ($patDirs[$i] != "**") {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ while ($patIdxStart != $patIdxEnd && $strIdxStart <= $strIdxEnd) {
+ $patIdxTmp = -1;
+ for ($i = $patIdxStart+1; $i <= $patIdxEnd; $i++) {
+ if ($patDirs[$i] == "**") {
+ $patIdxTmp = $i;
+ break;
+ }
+ }
+ if ($patIdxTmp == $patIdxStart+1) {
+ // '**/**' situation, so skip one
+ $patIdxStart++;
+ continue;
+ }
+ // Find the pattern between padIdxStart & padIdxTmp in str between
+ // strIdxStart & strIdxEnd
+ $patLength = ($patIdxTmp-$patIdxStart-1);
+ $strLength = ($strIdxEnd-$strIdxStart+1);
+ $foundIdx = -1;
+
+ //strLoop: (start of outer loop)
+ for ($i=0; $i <= $strLength - $patLength; $i++) {
+ for ($j = 0; $j < $patLength; $j++) {
+ $subPat = $patDirs[$patIdxStart+$j+1];
+ $subStr = $strDirs[$strIdxStart+$i+$j];
+ if (!self::match($subPat, $subStr, $isCaseSensitive)) {
+ continue 2; // continue up two levels (to strLoop:)
+ }
+ }
+ $foundIdx = $strIdxStart+$i; // only reached if all sub patterns matched
+ break;
+ }
+
+ if ($foundIdx == -1) {
+ return false;
+ }
+
+ $patIdxStart = $patIdxTmp;
+ $strIdxStart = $foundIdx + $patLength;
+ }
+
+ for ($i = $patIdxStart; $i <= $patIdxEnd; $i++) {
+ if ($patDirs[$i] != "**") {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Tests whether or not a string matches against a pattern.
+ * The pattern may contain two special characters:<br>
+ * '*' means zero or more characters<br>
+ * '?' means one and only one character
+ *
+ * @param pattern The pattern to match against.
+ * Must not be <code>null</code>.
+ * @param str The string which must be matched against the pattern.
+ * Must not be <code>null</code>.
+ * @param isCaseSensitive Whether or not matching should be performed
+ * case sensitively.
+ *
+ *
+ * @return <code>true</code> if the string matches against the pattern,
+ * or <code>false</code> otherwise.
+ */
+ public function match($pattern, $str, $isCaseSensitive = true) {
+
+ $patArr = StringHelper::toCharArray($pattern);
+ $strArr = StringHelper::toCharArray($str);
+ $patIdxStart = 0;
+ $patIdxEnd = count($patArr)-1;
+ $strIdxStart = 0;
+ $strIdxEnd = count($strArr)-1;
+
+ $containsStar = false;
+ for ($i = 0, $size=count($patArr); $i < $size; $i++) {
+ if ($patArr[$i] == '*') {
+ $containsStar = true;
+ break;
+ }
+ }
+
+ if (!$containsStar) {
+ // No '*'s, so we make a shortcut
+ if ($patIdxEnd != $strIdxEnd) {
+ return false; // Pattern and string do not have the same size
+ }
+ for ($i = 0; $i <= $patIdxEnd; $i++) {
+ $ch = $patArr[$i];
+ if ($ch != '?') {
+ if ($isCaseSensitive && $ch !== $strArr[$i]) {
+ return false;// Character mismatch
+ }
+ if (!$isCaseSensitive && strtoupper($ch) !==
+ strtoupper($strArr[$i])) {
+ return false; // Character mismatch
+ }
+ }
+ }
+ return true; // String matches against pattern
+ }
+
+ if ($patIdxEnd == 0) {
+ return true; // Pattern contains only '*', which matches anything
+ }
+
+ // Process characters before first star
+ while(($ch = $patArr[$patIdxStart]) != '*' && $strIdxStart <= $strIdxEnd) {
+ if ($ch != '?') {
+ if ($isCaseSensitive && $ch !== $strArr[$strIdxStart]) {
+ return false;// Character mismatch
+ }
+ if (!$isCaseSensitive && strtoupper($ch) !==
+ strtoupper($strArr[$strIdxStart])) {
+ return false;// Character mismatch
+ }
+ }
+ $patIdxStart++;
+ $strIdxStart++;
+ }
+
+ if ($strIdxStart > $strIdxEnd) {
+ // All characters in the string are used. Check if only '*'s are
+ // left in the pattern. If so, we succeeded. Otherwise failure.
+ for ($i = $patIdxStart; $i <= $patIdxEnd; $i++) {
+ if ($patArr[$i] != '*') {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // Process characters after last star
+ while(($ch = $patArr[$patIdxEnd]) != '*' && $strIdxStart <= $strIdxEnd) {
+ if ($ch != '?') {
+ if ($isCaseSensitive && $ch !== $strArr[$strIdxEnd]) {
+ return false;// Character mismatch
+ }
+ if (!$isCaseSensitive && strtoupper($ch) !==
+ strtoupper($strArr[$strIdxEnd])) {
+ return false;// Character mismatch
+ }
+ }
+ $patIdxEnd--;
+ $strIdxEnd--;
+ }
+ if ($strIdxStart > $strIdxEnd) {
+ // All characters in the string are used. Check if only '*'s are
+ // left in the pattern. If so, we succeeded. Otherwise failure.
+ for ($i = $patIdxStart; $i <= $patIdxEnd; $i++) {
+ if ($patArr[$i] != '*') {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // process pattern between stars. padIdxStart and patIdxEnd point
+ // always to a '*'.
+ while ($patIdxStart !== $patIdxEnd && $strIdxStart <= $strIdxEnd) {
+ $patIdxTmp = -1;
+ for ($i = $patIdxStart+1; $i <= $patIdxEnd; $i++) {
+ if ($patArr[$i] == '*') {
+ $patIdxTmp = $i;
+ break;
+ }
+ }
+ if ($patIdxTmp === $patIdxStart + 1) {
+ // Two stars next to each other, skip the first one.
+ $patIdxStart++;
+ continue;
+ }
+ // Find the pattern between padIdxStart & padIdxTmp in str between
+ // strIdxStart & strIdxEnd
+ $patLength = ($patIdxTmp - $patIdxStart - 1);
+ $strLength = ($strIdxEnd - $strIdxStart + 1);
+ $foundIdx = -1;
+
+ //strLoop:
+ for ($i = 0; $i <= $strLength - $patLength; $i++) {
+ for ($j = 0; $j < $patLength; $j++) {
+ $ch = $patArr[$patIdxStart+$j+1];
+ if ($ch != '?') {
+ if ($isCaseSensitive && $ch !== $strArr[$strIdxStart+$i+$j]) {
+ continue 2; //continue to strLoop:
+ }
+ if (!$isCaseSensitive && strtoupper($ch) !==
+ strtoupper($strArr[$strIdxStart+$i+$j])) {
+ continue 2; //continue to strLoop:
+ }
+ }
+ }
+ // only reached if sub loop completed w/o invoking continue 2
+ $foundIdx = $strIdxStart + $i;
+ break;
+ }
+
+ if ($foundIdx == -1) {
+ return false;
+ }
+
+ $patIdxStart = $patIdxTmp;
+ $strIdxStart = $foundIdx + $patLength;
+ }
+
+ // All characters in the string are used. Check if only '*'s are left
+ // in the pattern. If so, we succeeded. Otherwise failure.
+ for ($i = $patIdxStart; $i <= $patIdxEnd; $i++) {
+ if ($patArr[$i] != '*') {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns dependency information on these two files. If src has been
+ * modified later than target, it returns true. If target doesn't exist,
+ * it likewise returns true. Otherwise, target is newer than src and
+ * is not out of date, thus the method returns false. It also returns
+ * false if the src file doesn't even exist, since how could the
+ * target then be out of date.
+ *
+ * @param PhingFile $src the original file
+ * @param PhingFile $target the file being compared against
+ * @param int $granularity the amount in seconds of slack we will give in
+ * determining out of dateness
+ * @return whether the target is out of date
+ */
+ public function isOutOfDate(PhingFile $src, PhingFile $target, $granularity) {
+ if (!$src->exists()) {
+ return false;
+ }
+ if (!$target->exists()) {
+ return true;
+ }
+ if (($src->lastModified() - $granularity) > $target->lastModified()) {
+ return true;
+ }
+ return false;
+ }
+
+}
+
diff --git a/buildscripts/phing/classes/phing/types/selectors/SizeSelector.php b/buildscripts/phing/classes/phing/types/selectors/SizeSelector.php
new file mode 100644
index 00000000..bbc26423
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/SizeSelector.php
@@ -0,0 +1,228 @@
+<?php
+
+/*
+ * $Id: SizeSelector.php,v 1.8 2005/05/26 13:10:53 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+
+/**
+ * Selector that filters files based on their size.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Bruce Atherton <bruce@callenish.com> (Ant)
+ * @package phing.types.selectors
+ */
+class SizeSelector extends BaseExtendSelector {
+
+ private $size = -1;
+ private $multiplier = 1;
+ private $sizelimit = -1;
+ private $cmp = 2;
+ const SIZE_KEY = "value";
+ const UNITS_KEY = "units";
+ const WHEN_KEY = "when";
+
+ private static $sizeComparisons = array("less", "more", "equal");
+ private static $byteUnits = array("K", "k", "kilo", "KILO",
+ "Ki", "KI", "ki", "kibi", "KIBI",
+ "M", "m", "mega", "MEGA",
+ "Mi", "MI", "mi", "mebi", "MEBI",
+ "G", "g", "giga", "GIGA",
+ "Gi", "GI", "gi", "gibi", "GIBI",
+ "T", "t", "tera", "TERA",
+ /* You wish! */ "Ti", "TI", "ti", "tebi", "TEBI"
+ );
+
+ public function toString() {
+ $buf = "{sizeselector value: ";
+ $buf .= $this->sizelimit;
+ $buf .= "compare: ";
+ if ($this->cmp === 0) {
+ $buf .= "less";
+ } elseif ($this->cmp === 1) {
+ $buf .= "more";
+ } else {
+ $buf .= "equal";
+ }
+ $buf .= "}";
+ return $buf;
+ }
+
+ /**
+ * A size selector needs to know what size to base its selecting on.
+ * This will be further modified by the multiplier to get an
+ * actual size limit.
+ *
+ * @param size the size to select against expressed in units
+ */
+ public function setValue($size) {
+ $this->size = $size;
+ if (($this->multiplier !== 0) && ($this->size > -1)) {
+ $this->sizelimit = $size * $this->multiplier;
+ }
+ }
+
+ /**
+ * Sets the units to use for the comparison. This is a little
+ * complicated because common usage has created standards that
+ * play havoc with capitalization rules. Thus, some people will
+ * use "K" for indicating 1000's, when the SI standard calls for
+ * "k". Others have tried to introduce "K" as a multiple of 1024,
+ * but that falls down when you reach "M", since "m" is already
+ * defined as 0.001.
+ * <p>
+ * To get around this complexity, a number of standards bodies
+ * have proposed the 2^10 standard, and at least one has adopted
+ * it. But we are still left with a populace that isn't clear on
+ * how capitalization should work.
+ * <p>
+ * We therefore ignore capitalization as much as possible.
+ * Completely mixed case is not possible, but all upper and lower
+ * forms are accepted for all long and short forms. Since we have
+ * no need to work with the 0.001 case, this practice works here.
+ * <p>
+ * This function translates all the long and short forms that a
+ * unit prefix can occur in and translates them into a single
+ * multiplier.
+ *
+ * @param $units The units to compare the size to.
+ * @return void
+ */
+ public function setUnits($units) {
+ $i = array_search($units, self::$byteUnits, true);
+ if ($i === false) $i = -1; // make it java-like
+
+ $this->multiplier = 0;
+ if (($i > -1) && ($i < 4)) {
+ $this->multiplier = 1000;
+ } elseif (($i > 3) && ($i < 9)) {
+ $this->multiplier = 1024;
+ } elseif (($i > 8) && ($i < 13)) {
+ $this->multiplier = 1000000;
+ } elseif (($i > 12) && ($i < 18)) {
+ $this->multiplier = 1048576;
+ } elseif (($i > 17) && ($i < 22)) {
+ $this->multiplier = 1000000000;
+ } elseif (($i > 21) && ($i < 27)) {
+ $this->multiplier = 1073741824;
+ } elseif (($i > 26) && ($i < 31)) {
+ $this->multiplier = 1000000000000;
+ } elseif (($i > 30) && ($i < 36)) {
+ $this->multiplier = 1099511627776;
+ }
+ if (($this->multiplier > 0) && ($this->size > -1)) {
+ $this->sizelimit = $this->size * $this->multiplier;
+ }
+ }
+
+ /**
+ * This specifies when the file should be selected, whether it be
+ * when the file matches a particular size, when it is smaller,
+ * or whether it is larger.
+ *
+ * @param cmp The comparison to perform, an EnumeratedAttribute
+ */
+ public function setWhen($cmp) {
+ $c = array_search($cmp, self::$sizeComparisons, true);
+ if ($c !== false) {
+ $this->cmp = $c;
+ }
+ }
+
+ /**
+ * When using this as a custom selector, this method will be called.
+ * It translates each parameter into the appropriate setXXX() call.
+ *
+ * @param parameters the complete set of parameters for this selector
+ */
+ public function setParameters($parameters) {
+ parent::setParameters($parameters);
+ if ($parameters !== null) {
+ for ($i = 0, $size=count($parameters); $i < $size; $i++) {
+ $paramname = $parameters[$i]->getName();
+ switch(strtolower($paramname)) {
+ case self::SIZE_KEY:
+ try {
+ $this->setValue($parameters[$i]->getValue());
+ } catch (Exception $nfe) {
+ $this->setError("Invalid size setting "
+ . $parameters[$i]->getValue());
+ }
+ break;
+ case self::UNITS_KEY:
+ $this->setUnits($parameters[$i]->getValue());
+ break;
+ case self::WHEN_KEY:
+ $this->setWhen($parameters[$i]->getValue());
+ break;
+ default:
+ $this->setError("Invalid parameter " . $paramname);
+ }
+ }
+ }
+ }
+
+ /**
+ * <p>Checks to make sure all settings are kosher. In this case, it
+ * means that the size attribute has been set (to a positive value),
+ * that the multiplier has a valid setting, and that the size limit
+ * is valid. Since the latter is a calculated value, this can only
+ * fail due to a programming error.
+ * </p>
+ * <p>If a problem is detected, the setError() method is called.
+ * </p>
+ */
+ public function verifySettings() {
+ if ($this->size < 0) {
+ $this->setError("The value attribute is required, and must be positive");
+ } elseif ($this->multiplier < 1) {
+ $this->setError("Invalid Units supplied, must be K,Ki,M,Mi,G,Gi,T,or Ti");
+ } elseif ($this->sizelimit < 0) {
+ $this->setError("Internal error: Code is not setting sizelimit correctly");
+ }
+ }
+
+ /**
+ * The heart of the matter. This is where the selector gets to decide
+ * on the inclusion of a file in a particular fileset.
+ *
+ * @param basedir A PhingFile object for the base directory
+ * @param filename The name of the file to check
+ * @param file A PhingFile object for this filename
+ * @return whether the file should be selected or not
+ */
+ public function isSelected(PhingFile $basedir, $filename, PhingFile $file) {
+
+ $this->validate();
+
+ // Directory size never selected for
+ if ($file->isDirectory()) {
+ return true;
+ }
+ if ($this->cmp === 0) {
+ return ($file->length() < $this->sizelimit);
+ } elseif ($this->cmp === 1) {
+ return ($file->length() > $this->sizelimit);
+ } else {
+ return ($file->length() === $this->sizelimit);
+ }
+ }
+
+}
+
diff --git a/buildscripts/phing/classes/phing/types/selectors/TypeSelector.php b/buildscripts/phing/classes/phing/types/selectors/TypeSelector.php
new file mode 100644
index 00000000..f1532308
--- /dev/null
+++ b/buildscripts/phing/classes/phing/types/selectors/TypeSelector.php
@@ -0,0 +1,113 @@
+<?php
+
+/*
+ * $Id: TypeSelector.php,v 1.3 2005/05/26 13:10:53 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/types/selectors/BaseExtendSelector.php';
+
+/**
+ * Selector that selects a certain kind of file: directory or regular file.
+ *
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+ * @author Jeff Turner <jefft@apache.org> (Ant)
+ * @version $Revision: 1.3 $
+ * @package phing.types.selectors
+ */
+class TypeSelector extends BaseExtendSelector {
+
+ private $type;
+
+ /** Key to used for parameterized custom selector */
+ const TYPE_KEY = "type";
+
+ /** Valid types */
+ private static $types = array('file', 'dir');
+
+ /**
+ * @return string A string describing this object
+ */
+ public function toString() {
+ $buf = "{typeselector type: " . $this->type . "}";
+ return $buf;
+ }
+
+ /**
+ * Set the type of file to require.
+ * @param string $type The type of file - 'file' or 'dir'
+ */
+ public function setType($type) {
+ $this->type = $type;
+ }
+
+ /**
+ * When using this as a custom selector, this method will be called.
+ * It translates each parameter into the appropriate setXXX() call.
+ *
+ * @param array $parameters the complete set of parameters for this selector
+ */
+ public function setParameters($parameters) {
+ parent::setParameters($parameters);
+ if ($parameters !== null) {
+ for ($i = 0, $size=count($parameters); $i < $size; $i++) {
+ $paramname = $parameters[$i]->getName();
+ if (self::TYPE_KEY == strtolower($paramname)) {
+ $this->setType($parameters[$i]->getValue());
+ } else {
+ $this->setError("Invalid parameter " . $paramname);
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks to make sure all settings are kosher. In this case, it
+ * means that the pattern attribute has been set.
+ *
+ */
+ public function verifySettings() {
+ if ($this->type === null) {
+ $this->setError("The type attribute is required");
+ } elseif (!in_array($this->type, self::$types, true)) {
+ $this->setError("Invalid type specified; must be one of (" . implode(self::$types) . ")");
+ }
+ }
+
+ /**
+ * The heart of the matter. This is where the selector gets to decide
+ * on the inclusion of a file in a particular fileset.
+ *
+ * @param PhingFile $basedir the base directory the scan is being done from
+ * @param string $filename is the name of the file to check
+ * @param PhingFile $file is a PhingFile object the selector can use
+ * @return boolean Whether the file should be selected or not
+ */
+ public function isSelected(PhingFile $basedir, $filename, PhingFile $file) {
+
+ // throw BuildException on error
+ $this->validate();
+
+ if ($file->isDirectory()) {
+ return $this->type === 'dir';
+ } else {
+ return $this->type === 'file';
+ }
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/util/DirectoryScanner.php b/buildscripts/phing/classes/phing/util/DirectoryScanner.php
new file mode 100644
index 00000000..e04c4880
--- /dev/null
+++ b/buildscripts/phing/classes/phing/util/DirectoryScanner.php
@@ -0,0 +1,710 @@
+<?php
+/*
+ * $Id: DirectoryScanner.php,v 1.15 2005/12/13 21:56:26 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/types/selectors/SelectorScanner.php';
+include_once 'phing/util/StringHelper.php';
+include_once 'phing/types/selectors/SelectorUtils.php';
+
+/**
+ * Class for scanning a directory for files/directories that match a certain
+ * criteria.
+ *
+ * These criteria consist of a set of include and exclude patterns. With these
+ * patterns, you can select which files you want to have included, and which
+ * files you want to have excluded.
+ *
+ * The idea is simple. A given directory is recursively scanned for all files
+ * and directories. Each file/directory is matched against a set of include
+ * and exclude patterns. Only files/directories that match at least one
+ * pattern of the include pattern list, and don't match a pattern of the
+ * exclude pattern list will be placed in the list of files/directories found.
+ *
+ * When no list of include patterns is supplied, "**" will be used, which
+ * means that everything will be matched. When no list of exclude patterns is
+ * supplied, an empty list is used, such that nothing will be excluded.
+ *
+ * The pattern matching is done as follows:
+ * The name to be matched is split up in path segments. A path segment is the
+ * name of a directory or file, which is bounded by DIRECTORY_SEPARATOR
+ * ('/' under UNIX, '\' under Windows).
+ * E.g. "abc/def/ghi/xyz.php" is split up in the segments "abc", "def", "ghi"
+ * and "xyz.php".
+ * The same is done for the pattern against which should be matched.
+ *
+ * Then the segments of the name and the pattern will be matched against each
+ * other. When '**' is used for a path segment in the pattern, then it matches
+ * zero or more path segments of the name.
+ *
+ * There are special case regarding the use of DIRECTORY_SEPARATOR at
+ * the beginning of the pattern and the string to match:
+ * When a pattern starts with a DIRECTORY_SEPARATOR, the string
+ * to match must also start with a DIRECTORY_SEPARATOR.
+ * When a pattern does not start with a DIRECTORY_SEPARATOR, the
+ * string to match may not start with a DIRECTORY_SEPARATOR.
+ * When one of these rules is not obeyed, the string will not
+ * match.
+ *
+ * When a name path segment is matched against a pattern path segment, the
+ * following special characters can be used:
+ * '*' matches zero or more characters,
+ * '?' matches one character.
+ *
+ * Examples:
+ *
+ * "**\*.php" matches all .php files/dirs in a directory tree.
+ *
+ * "test\a??.php" matches all files/dirs which start with an 'a', then two
+ * more characters and then ".php", in a directory called test.
+ *
+ * "**" matches everything in a directory tree.
+ *
+ * "**\test\**\XYZ*" matches all files/dirs that start with "XYZ" and where
+ * there is a parent directory called test (e.g. "abc\test\def\ghi\XYZ123").
+ *
+ * Case sensitivity may be turned off if necessary. By default, it is
+ * turned on.
+ *
+ * Example of usage:
+ * $ds = new DirectroyScanner();
+ * $includes = array("**\*.php");
+ * $excludes = array("modules\*\**");
+ * $ds->SetIncludes($includes);
+ * $ds->SetExcludes($excludes);
+ * $ds->SetBasedir("test");
+ * $ds->SetCaseSensitive(true);
+ * $ds->Scan();
+ *
+ * print("FILES:");
+ * $files = ds->GetIncludedFiles();
+ * for ($i = 0; $i < count($files);$i++) {
+ * println("$files[$i]\n");
+ * }
+ *
+ * This will scan a directory called test for .php files, but excludes all
+ * .php files in all directories under a directory called "modules"
+ *
+ * This class is complete preg/ereg free port of the Java class
+ * org.apache.tools.ant.DirectoryScanner. Even functions that use preg/ereg
+ * internally (like split()) are not used. Only the _fast_ string functions
+ * and comparison operators (=== !=== etc) are used for matching and tokenizing.
+ *
+ * @author Arnout J. Kuiper, ajkuiper@wxs.nl
+ * @author Magesh Umasankar, umagesh@rediffmail.com
+ * @author Andreas Aderhold, andi@binarycloud.com
+ *
+ * @version $Revision: 1.15 $
+ * @package phing.util
+ */
+class DirectoryScanner implements SelectorScanner {
+
+ /** default set of excludes */
+ protected $DEFAULTEXCLUDES = array(
+ "**/*~",
+ "**/#*#",
+ "**/.#*",
+ "**/%*%",
+ "**/CVS",
+ "**/CVS/**",
+ "**/.cvsignore",
+ "**/SCCS",
+ "**/SCCS/**",
+ "**/vssver.scc",
+ "**/.svn",
+ "**/.svn/**",
+ "**/._*",
+ "**/.DS_Store",
+ );
+
+ /** The base directory which should be scanned. */
+ protected $basedir;
+
+ /** The patterns for the files that should be included. */
+ protected $includes = null;
+
+ /** The patterns for the files that should be excluded. */
+ protected $excludes = null;
+
+ /**
+ * The files that where found and matched at least one includes, and matched
+ * no excludes.
+ */
+ protected $filesIncluded;
+
+ /** The files that where found and did not match any includes. Trie */
+ protected $filesNotIncluded;
+
+ /**
+ * The files that where found and matched at least one includes, and also
+ * matched at least one excludes. Trie object.
+ */
+ protected $filesExcluded;
+
+ /**
+ * The directories that where found and matched at least one includes, and
+ * matched no excludes.
+ */
+ protected $dirsIncluded;
+
+ /** The directories that where found and did not match any includes. */
+ protected $dirsNotIncluded;
+
+ /**
+ * The files that where found and matched at least one includes, and also
+ * matched at least one excludes.
+ */
+ protected $dirsExcluded;
+
+ /** Have the vars holding our results been built by a slow scan? */
+ protected $haveSlowResults = false;
+
+ /** Should the file system be treated as a case sensitive one? */
+ protected $isCaseSensitive = true;
+
+ /** Selectors */
+ protected $selectors = null;
+
+ protected $filesDeselected;
+ protected $dirsDeselected;
+
+ /** if there are no deselected files */
+ protected $everythingIncluded = true;
+
+ /**
+ * Does the path match the start of this pattern up to the first "**".
+ * This is a static mehtod and should always be called static
+ *
+ * This is not a general purpose test and should only be used if you
+ * can live with false positives.
+ *
+ * pattern=**\a and str=b will yield true.
+ *
+ * @param pattern the (non-null) pattern to match against
+ * @param str the (non-null) string (path) to match
+ * @param isCaseSensitive must matches be case sensitive?
+ * @return boolean true if matches, otherwise false
+ */
+ function matchPatternStart($pattern, $str, $isCaseSensitive = true) {
+ return SelectorUtils::matchPatternStart($pattern, $str, $isCaseSensitive);
+ }
+
+ /**
+ * Matches a path against a pattern. Static
+ *
+ * @param pattern the (non-null) pattern to match against
+ * @param str the (non-null) string (path) to match
+ * @param isCaseSensitive must a case sensitive match be done?
+ *
+ * @return true when the pattern matches against the string.
+ * false otherwise.
+ */
+ function matchPath($pattern, $str, $isCaseSensitive = true) {
+ return SelectorUtils::matchPath($pattern, $str, $isCaseSensitive);
+ }
+
+ /**
+ * Matches a string against a pattern. The pattern contains two special
+ * characters:
+ * '*' which means zero or more characters,
+ * '?' which means one and only one character.
+ *
+ * @param pattern the (non-null) pattern to match against
+ * @param str the (non-null) string that must be matched against the
+ * pattern
+ *
+ * @return boolean true when the string matches against the pattern,
+ * false otherwise.
+ * @access public
+ */
+ function match($pattern, $str, $isCaseSensitive = true) {
+ return SelectorUtils::match($pattern, $str, $isCaseSensitive);
+ }
+
+ /**
+ * Sets the basedir for scanning. This is the directory that is scanned
+ * recursively. All '/' and '\' characters are replaced by
+ * DIRECTORY_SEPARATOR
+ *
+ * @param basedir the (non-null) basedir for scanning
+ */
+ function setBasedir($_basedir) {
+ $_basedir = str_replace('\\', DIRECTORY_SEPARATOR, $_basedir);
+ $_basedir = str_replace('/', DIRECTORY_SEPARATOR, $_basedir);
+ $this->basedir = $_basedir;
+ }
+
+ /**
+ * Gets the basedir that is used for scanning. This is the directory that
+ * is scanned recursively.
+ *
+ * @return the basedir that is used for scanning
+ */
+ function getBasedir() {
+ return $this->basedir;
+ }
+
+ /**
+ * Sets the case sensitivity of the file system
+ *
+ * @param specifies if the filesystem is case sensitive
+ */
+ function setCaseSensitive($_isCaseSensitive) {
+ $this->isCaseSensitive = ($_isCaseSensitive) ? true : false;
+ }
+
+ /**
+ * Sets the set of include patterns to use. All '/' and '\' characters are
+ * replaced by DIRECTORY_SEPARATOR. So the separator used need
+ * not match DIRECTORY_SEPARATOR.
+ *
+ * When a pattern ends with a '/' or '\', "**" is appended.
+ *
+ * @param includes list of include patterns
+ */
+ function setIncludes($_includes = array()) {
+ if (empty($_includes) || is_null($_includes)) {
+ $this->includes = null;
+ } else {
+ for ($i = 0; $i < count($_includes); $i++) {
+ $pattern = null;
+ $pattern = str_replace('\\', DIRECTORY_SEPARATOR, $_includes[$i]);
+ $pattern = str_replace('/', DIRECTORY_SEPARATOR, $pattern);
+ if (StringHelper::endsWith(DIRECTORY_SEPARATOR, $pattern)) {
+ $pattern .= "**";
+ }
+ $this->includes[] = $pattern;
+ }
+ }
+ }
+
+ /**
+ * Sets the set of exclude patterns to use. All '/' and '\' characters are
+ * replaced by <code>File.separatorChar</code>. So the separator used need
+ * not match <code>File.separatorChar</code>.
+ *
+ * When a pattern ends with a '/' or '\', "**" is appended.
+ *
+ * @param excludes list of exclude patterns
+ */
+
+ function setExcludes($_excludes = array()) {
+ if (empty($_excludes) || is_null($_excludes)) {
+ $this->excludes = null;
+ } else {
+ for ($i = 0; $i < count($_excludes); $i++) {
+ $pattern = null;
+ $pattern = str_replace('\\', DIRECTORY_SEPARATOR, $_excludes[$i]);
+ $pattern = str_replace('/', DIRECTORY_SEPARATOR, $pattern);
+ if (StringHelper::endsWith(DIRECTORY_SEPARATOR, $pattern)) {
+ $pattern .= "**";
+ }
+ $this->excludes[] = $pattern;
+ }
+ }
+ }
+
+ /**
+ * Scans the base directory for files that match at least one include
+ * pattern, and don't match any exclude patterns.
+ *
+ */
+ function scan() {
+
+ if ((empty($this->basedir)) || (!@is_dir($this->basedir))) {
+ return false;
+ }
+
+ if ($this->includes === null) {
+ // No includes supplied, so set it to 'matches all'
+ $this->includes = array("**");
+ }
+ if (is_null($this->excludes)) {
+ $this->excludes = array();
+ }
+
+ $this->filesIncluded = array();
+ $this->filesNotIncluded = array();
+ $this->filesExcluded = array();
+ $this->dirsIncluded = array();
+ $this->dirsNotIncluded = array();
+ $this->dirsExcluded = array();
+ $this->dirsDeselected = array();
+ $this->filesDeselected = array();
+
+ if ($this->isIncluded("")) {
+ if (!$this->isExcluded("")) {
+ if ($this->isSelected("", $this->basedir)) {
+ $this->dirsIncluded[] = "";
+ } else {
+ $this->dirsDeselected[] = "";
+ }
+ } else {
+ $this->dirsExcluded[] = "";
+ }
+ } else {
+ $this->dirsNotIncluded[] = "";
+ }
+
+ $this->scandir($this->basedir, "", true);
+ return true;
+ }
+
+ /**
+ * Toplevel invocation for the scan.
+ *
+ * Returns immediately if a slow scan has already been requested.
+ */
+ protected function slowScan() {
+
+ if ($this->haveSlowResults) {
+ return;
+ }
+
+ // copy trie object add CopyInto() method
+ $excl = $this->dirsExcluded;
+ $notIncl = $this->dirsNotIncluded;
+
+ for ($i=0, $_i=count($excl); $i < $_i; $i++) {
+ if (!$this->couldHoldIncluded($excl[$i])) {
+ $this->scandir($this->basedir.$excl[$i], $excl[$i].DIRECTORY_SEPARATOR, false);
+ }
+ }
+
+ for ($i=0, $_i=count($notIncl); $i < $_i; $i++) {
+ if (!$this->couldHoldIncluded($notIncl[$i])) {
+ $this->scandir($this->basedir.$notIncl[$i], $notIncl[$i].DIRECTORY_SEPARATOR, false);
+ }
+ }
+
+ $this->haveSlowResults = true;
+ }
+
+ /**
+ * Lists contens of a given directory and returns array with entries
+ *
+ * @param src String. Source path and name file to copy.
+ *
+ * @access public
+ * @return array directory entries
+ * @author Albert Lash, alash@plateauinnovation.com
+ */
+
+ function listDir($_dir) {
+ $d = dir($_dir);
+ $list = array();
+ while($entry = $d->read()) {
+ if ($entry != "." && $entry != "..") {
+ $list[] = $entry;
+ }
+ }
+ $d->close();
+ return $list;
+ }
+
+ /**
+ * Scans the passed dir for files and directories. Found files and
+ * directories are placed in their respective collections, based on the
+ * matching of includes and excludes. When a directory is found, it is
+ * scanned recursively.
+ *
+ * @param dir the directory to scan
+ * @param vpath the path relative to the basedir (needed to prevent
+ * problems with an absolute path when using dir)
+ *
+ * @access private
+ * @see #filesIncluded
+ * @see #filesNotIncluded
+ * @see #filesExcluded
+ * @see #dirsIncluded
+ * @see #dirsNotIncluded
+ * @see #dirsExcluded
+ */
+ private function scandir($_rootdir, $_vpath, $_fast) {
+
+ if (!is_readable($_rootdir)) {
+ return;
+ }
+
+ $newfiles = self::listDir($_rootdir);
+
+ for ($i=0,$_i=count($newfiles); $i < $_i; $i++) {
+
+ $file = $_rootdir . DIRECTORY_SEPARATOR . $newfiles[$i];
+ $name = $_vpath . $newfiles[$i];
+
+ if (@is_dir($file)) {
+ if ($this->isIncluded($name)) {
+ if (!$this->isExcluded($name)) {
+ if ($this->isSelected($name, $file)) {
+ $this->dirsIncluded[] = $name;
+ if ($_fast) {
+ $this->scandir($file, $name.DIRECTORY_SEPARATOR, $_fast);
+ }
+ } else {
+ $this->everythingIncluded = false;
+ $this->dirsDeselected[] = $name;
+ if ($_fast && $this->couldHoldIncluded($name)) {
+ $this->scandir($file, $name.DIRECTORY_SEPARATOR, $_fast);
+ }
+ }
+ } else {
+ $this->everythingIncluded = false;
+ $this->dirsExcluded[] = $name;
+ if ($_fast && $this->couldHoldIncluded($name)) {
+ $this->scandir($file, $name.DIRECTORY_SEPARATOR, $_fast);
+ }
+ }
+ } else {
+ $this->everythingIncluded = false;
+ $this->dirsNotIncluded[] = $name;
+ if ($_fast && $this->couldHoldIncluded($name)) {
+ $this->scandir($file, $name.DIRECTORY_SEPARATOR, $_fast);
+ }
+ }
+
+ if (!$_fast) {
+ $this->scandir($file, $name.DIRECTORY_SEPARATOR, $_fast);
+ }
+
+ } elseif (@is_file($file)) {
+ if ($this->isIncluded($name)) {
+ if (!$this->isExcluded($name)) {
+ if ($this->isSelected($name, $file)) {
+ $this->filesIncluded[] = $name;
+ } else {
+ $this->everythingIncluded = false;
+ $this->filesDeselected[] = $name;
+ }
+ } else {
+ $this->everythingIncluded = false;
+ $this->filesExcluded[] = $name;
+ }
+ } else {
+ $this->everythingIncluded = false;
+ $this->filesNotIncluded[] = $name;
+ }
+ }
+ }
+ }
+
+ /**
+ * Tests whether a name matches against at least one include pattern.
+ *
+ * @param name the name to match
+ * @return <code>true</code> when the name matches against at least one
+ * include pattern, <code>false</code> otherwise.
+ */
+ protected function isIncluded($_name) {
+ for ($i=0, $_i=count($this->includes); $i < $_i; $i++) {
+ if (DirectoryScanner::matchPath($this->includes[$i], $_name, $this->isCaseSensitive)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Tests whether a name matches the start of at least one include pattern.
+ *
+ * @param name the name to match
+ * @return <code>true</code> when the name matches against at least one
+ * include pattern, <code>false</code> otherwise.
+ */
+ protected function couldHoldIncluded($_name) {
+ for ($i = 0; $i < count($this->includes); $i++) {
+ if (DirectoryScanner::matchPatternStart($this->includes[$i], $_name, $this->isCaseSensitive)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Tests whether a name matches against at least one exclude pattern.
+ *
+ * @param name the name to match
+ * @return <code>true</code> when the name matches against at least one
+ * exclude pattern, <code>false</code> otherwise.
+ */
+ protected function isExcluded($_name) {
+ for ($i = 0; $i < count($this->excludes); $i++) {
+ if (DirectoryScanner::matchPath($this->excludes[$i], $_name, $this->isCaseSensitive)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get the names of the files that matched at least one of the include
+ * patterns, and matched none of the exclude patterns.
+ * The names are relative to the basedir.
+ *
+ * @return the names of the files
+ */
+ function getIncludedFiles() {
+ return $this->filesIncluded;
+ }
+
+ /**
+ * Get the names of the files that matched at none of the include patterns.
+ * The names are relative to the basedir.
+ *
+ * @return the names of the files
+ */
+ function getNotIncludedFiles() {
+ $this->slowScan();
+ return $this->filesNotIncluded;
+ }
+
+ /**
+ * Get the names of the files that matched at least one of the include
+ * patterns, an matched also at least one of the exclude patterns.
+ * The names are relative to the basedir.
+ *
+ * @return the names of the files
+ */
+
+ function getExcludedFiles() {
+ $this->slowScan();
+ return $this->filesExcluded;
+ }
+
+ /**
+ * <p>Returns the names of the files which were selected out and
+ * therefore not ultimately included.</p>
+ *
+ * <p>The names are relative to the base directory. This involves
+ * performing a slow scan if one has not already been completed.</p>
+ *
+ * @return the names of the files which were deselected.
+ *
+ * @see #slowScan
+ */
+ public function getDeselectedFiles() {
+ $this->slowScan();
+ return $this->filesDeselected;
+ }
+
+ /**
+ * Get the names of the directories that matched at least one of the include
+ * patterns, an matched none of the exclude patterns.
+ * The names are relative to the basedir.
+ *
+ * @return the names of the directories
+ */
+
+ function getIncludedDirectories() {
+ return $this->dirsIncluded;
+ }
+
+ /**
+ * Get the names of the directories that matched at none of the include
+ * patterns.
+ * The names are relative to the basedir.
+ *
+ * @return the names of the directories
+ */
+ function getNotIncludedDirectories() {
+ $this->slowScan();
+ return $this->dirsNotIncluded;
+ }
+
+ /**
+ * <p>Returns the names of the directories which were selected out and
+ * therefore not ultimately included.</p>
+ *
+ * <p>The names are relative to the base directory. This involves
+ * performing a slow scan if one has not already been completed.</p>
+ *
+ * @return the names of the directories which were deselected.
+ *
+ * @see #slowScan
+ */
+ public function getDeselectedDirectories() {
+ $this->slowScan();
+ return $this->dirsDeselected;
+ }
+
+ /**
+ * Get the names of the directories that matched at least one of the include
+ * patterns, an matched also at least one of the exclude patterns.
+ * The names are relative to the basedir.
+ *
+ * @return the names of the directories
+ */
+ function getExcludedDirectories() {
+ $this->slowScan();
+ return $this->dirsExcluded;
+ }
+
+ /**
+ * Adds the array with default exclusions to the current exclusions set.
+ *
+ */
+ function addDefaultExcludes() {
+ //$excludesLength = ($this->excludes == null) ? 0 : count($this->excludes);
+ foreach($this->DEFAULTEXCLUDES as $pattern) {
+ $pattern = str_replace('\\', DIRECTORY_SEPARATOR, $pattern);
+ $pattern = str_replace('/', DIRECTORY_SEPARATOR, $pattern);
+ $this->excludes[] = $pattern;
+ }
+ }
+
+ /**
+ * Sets the selectors that will select the filelist.
+ *
+ * @param selectors specifies the selectors to be invoked on a scan
+ */
+ public function setSelectors($selectors) {
+ $this->selectors = $selectors;
+ }
+
+ /**
+ * Returns whether or not the scanner has included all the files or
+ * directories it has come across so far.
+ *
+ * @return <code>true</code> if all files and directories which have
+ * been found so far have been included.
+ */
+ public function isEverythingIncluded() {
+ return $this->everythingIncluded;
+ }
+
+ /**
+ * Tests whether a name should be selected.
+ *
+ * @param string $name The filename to check for selecting.
+ * @param string $file The full file path.
+ * @return boolean False when the selectors says that the file
+ * should not be selected, True otherwise.
+ */
+ protected function isSelected($name, $file) {
+ if ($this->selectors !== null) {
+ for ($i=0,$size=count($this->selectors); $i < $size; $i++) {
+ if (($this->selectors[$i]->isSelected(new PhingFile($this->basedir), $name, new PhingFile($file))) === false) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/buildscripts/phing/classes/phing/util/ExtendedFileStream.php b/buildscripts/phing/classes/phing/util/ExtendedFileStream.php
new file mode 100644
index 00000000..5fdcae47
--- /dev/null
+++ b/buildscripts/phing/classes/phing/util/ExtendedFileStream.php
@@ -0,0 +1,133 @@
+<?php
+
+ include_once 'phing/system/io/PhingFile.php';
+
+ /**
+ * $Id: ExtendedFileStream.php,v 1.5 2005/12/27 15:51:26 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+ /**
+ * Extended file stream wrapper class which auto-creates directories
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: ExtendedFileStream.php,v 1.5 2005/12/27 15:51:26 hlellelid Exp $
+ * @package phing.util
+ */
+ class ExtendedFileStream
+ {
+ private $fp = NULL;
+
+ static function registerStream()
+ {
+ if (!in_array("efile", stream_get_wrappers()))
+ {
+ stream_wrapper_register("efile", "ExtendedFileStream");
+ }
+ }
+
+ private function createDirectories($path)
+ {
+ $f = new PhingFile($path);
+ if (!$f->exists()) {
+ $f->mkdirs();
+ }
+ }
+
+ function stream_open($path, $mode, $options, &$opened_path)
+ {
+ /** Small fix for Windows */
+ if ($path[8] == DIRECTORY_SEPARATOR)
+ {
+ $filepath = substr($path, 7);
+ }
+ else
+ {
+ $filepath = substr($path, 8);
+ }
+
+ $this->createDirectories(dirname($filepath));
+
+ $this->fp = fopen($filepath, $mode);
+
+ return true;
+ }
+
+ function stream_close()
+ {
+ fclose($this->fp);
+ $this->fp = NULL;
+ }
+
+ function stream_read($count)
+ {
+ return fread($this->fp, $count);
+ }
+
+ function stream_write($data)
+ {
+ return fwrite($this->fp, $data);
+ }
+
+ function stream_eof()
+ {
+ return feof($this->fp);
+ }
+
+ function stream_tell()
+ {
+ return ftell($this->fp);
+ }
+
+ function stream_seek($offset, $whence)
+ {
+ return fseek($this->fp, $offset, $whence);
+ }
+
+ function stream_flush()
+ {
+ return fflush($this->fp);
+ }
+
+ function stream_stat()
+ {
+ return fstat($this->fp);
+ }
+
+ function unlink($path)
+ {
+ return FALSE;
+ }
+
+ function rename($path_from, $path_to)
+ {
+ return FALSE;
+ }
+
+ function mkdir($path, $mode, $options)
+ {
+ return FALSE;
+ }
+
+ function rmdir($path, $options)
+ {
+ return FALSE;
+ }
+ };
+
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/util/FileUtils.php b/buildscripts/phing/classes/phing/util/FileUtils.php
new file mode 100644
index 00000000..0f5ff19a
--- /dev/null
+++ b/buildscripts/phing/classes/phing/util/FileUtils.php
@@ -0,0 +1,294 @@
+<?php
+/*
+ * $Id: FileUtils.php,v 1.10 2005/05/26 13:10:53 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+include_once 'phing/system/lang/Character.php';
+include_once 'phing/util/StringHelper.php';
+include_once 'phing/system/io/BufferedReader.php';
+include_once 'phing/system/io/BufferedWriter.php';
+include_once 'phing/filters/util/ChainReaderHelper.php';
+include_once 'phing/system/io/PhingFile.php';
+
+/**
+ * File utility class.
+ * - handles os independent stuff etc
+ * - mapper stuff
+ * - filter stuff
+ *
+ * @package phing.util
+ * @version $Revision: 1.10 $
+ */
+class FileUtils {
+
+ /**
+ * Returns a new Reader with filterchains applied. If filterchains are empty,
+ * simply returns passed reader.
+ *
+ * @param Reader $in Reader to modify (if appropriate).
+ * @param array &$filterChains filter chains to apply.
+ * @param Project $project
+ * @return Reader Assembled Reader (w/ filter chains).
+ */
+ function getChainedReader(Reader $in, &$filterChains, Project $project) {
+ if (!empty($filterChains)) {
+ $crh = new ChainReaderHelper();
+ $crh->setBufferSize(65536); // 64k buffer, but isn't being used (yet?)
+ $crh->setPrimaryReader($in);
+ $crh->setFilterChains($filterChains);
+ $crh->setProject($project);
+ $rdr = $crh->getAssembledReader();
+ return $rdr;
+ } else {
+ return $in;
+ }
+ }
+
+ /**
+ * Copies a file using filter chains.
+ *
+ * @param PhingFile $sourceFile
+ * @param PhingFile $destFile
+ * @param boolean $overwrite
+ * @param boolean $preserveLastModified
+ * @param array $filterChains
+ * @param Project $project
+ * @return void
+ */
+ function copyFile(PhingFile $sourceFile, PhingFile $destFile, $overwrite = false, $preserveLastModified = true, &$filterChains = null, Project $project) {
+
+ if ($overwrite || !$destFile->exists() || $destFile->lastModified() < $sourceFile->lastModified()) {
+ if ($destFile->exists() && $destFile->isFile()) {
+ $destFile->delete();
+ }
+
+ // ensure that parent dir of dest file exists!
+ $parent = $destFile->getParentFile();
+ if ($parent !== null && !$parent->exists()) {
+ $parent->mkdirs();
+ }
+
+ if ((is_array($filterChains)) && (!empty($filterChains))) {
+
+ $in = self::getChainedReader(new BufferedReader(new FileReader($sourceFile)), $filterChains, $project);
+ $out = new BufferedWriter(new FileWriter($destFile));
+
+ // New read() methods returns a big buffer.
+ while(-1 !== ($buffer = $in->read())) { // -1 indicates EOF
+ $out->write($buffer);
+ }
+
+ if ( $in !== null )
+ $in->close();
+ if ( $out !== null )
+ $out->close();
+ } else {
+ // simple copy (no filtering)
+ $sourceFile->copyTo($destFile);
+ }
+
+ if ($preserveLastModified) {
+ $destFile->setLastModified($sourceFile->lastModified());
+ }
+
+ }
+ }
+
+ /**
+ * Interpret the filename as a file relative to the given file -
+ * unless the filename already represents an absolute filename.
+ *
+ * @param $file the "reference" file for relative paths. This
+ * instance must be an absolute file and must not contain
+ * ./ or ../ sequences (same for \ instead of /).
+ * @param $filename a file name
+ *
+ * @return PhingFile A PhingFile object pointing to an absolute file that doesn't contain ./ or ../ sequences
+ * and uses the correct separator for the current platform.
+ */
+ function resolveFile($file, $filename) {
+ // remove this and use the static class constant File::seperator
+ // as soon as ZE2 is ready
+ $fs = FileSystem::getFileSystem();
+
+ $filename = str_replace('/', $fs->getSeparator(), str_replace('\\', $fs->getSeparator(), $filename));
+
+ // deal with absolute files
+ if (StringHelper::startsWith($fs->getSeparator(), $filename) ||
+ (strlen($filename) >= 2 && Character::isLetter($filename{0}) && $filename{1} === ':')) {
+ return new PhingFile($this->normalize($filename));
+ }
+
+ if (strlen($filename) >= 2 && Character::isLetter($filename{0}) && $filename{1} === ':') {
+ return new PhingFile($this->normalize($filename));
+ }
+
+ $helpFile = new PhingFile($file->getAbsolutePath());
+
+ $tok = strtok($filename, $fs->getSeparator());
+ while ($tok !== false) {
+ $part = $tok;
+ if ($part === '..') {
+ $parentFile = $helpFile->getParent();
+ if ($parentFile === null) {
+ $msg = "The file or path you specified ($filename) is invalid relative to ".$file->getPath();
+ throw new IOException($msg);
+ }
+ $helpFile = new PhingFile($parentFile);
+ } else if ($part === '.') {
+ // Do nothing here
+ } else {
+ $helpFile = new PhingFile($helpFile, $part);
+ }
+ $tok = strtok($fs->getSeparator());
+ }
+ return new PhingFile($helpFile->getAbsolutePath());
+ }
+
+ /**
+ * Normalize the given absolute path.
+ *
+ * This includes:
+ * - Uppercase the drive letter if there is one.
+ * - Remove redundant slashes after the drive spec.
+ * - resolve all ./, .\, ../ and ..\ sequences.
+ * - DOS style paths that start with a drive letter will have
+ * \ as the separator.
+ * @param string $path Path to normalize.
+ * @return string
+ */
+ function normalize($path) {
+
+ $path = (string) $path;
+ $orig = $path;
+
+ $path = str_replace('/', DIRECTORY_SEPARATOR, str_replace('\\', DIRECTORY_SEPARATOR, $path));
+
+ // make sure we are dealing with an absolute path
+ if (!StringHelper::startsWith(DIRECTORY_SEPARATOR, $path)
+ && !(strlen($path) >= 2 && Character::isLetter($path{0}) && $path{1} === ':')) {
+ throw new IOException("$path is not an absolute path");
+ }
+
+ $dosWithDrive = false;
+ $root = null;
+
+ // Eliminate consecutive slashes after the drive spec
+
+ if (strlen($path) >= 2 && Character::isLetter($path{0}) && $path{1} === ':') {
+ $dosWithDrive = true;
+
+ $ca = str_replace('/', '\\', $path);
+ $ca = StringHelper::toCharArray($ca);
+
+ $path = strtoupper($ca[0]).':';
+
+ for ($i=2, $_i=count($ca); $i < $_i; $i++) {
+ if (($ca[$i] !== '\\') ||
+ ($ca[$i] === '\\' && $ca[$i - 1] !== '\\')
+ ) {
+ $path .= $ca[$i];
+ }
+ }
+
+ $path = str_replace('\\', DIRECTORY_SEPARATOR, $path);
+
+ if (strlen($path) == 2) {
+ $root = $path;
+ $path = "";
+ } else {
+ $root = substr($path, 0, 3);
+ $path = substr($path, 3);
+ }
+
+ } else {
+ if (strlen($path) == 1) {
+ $root = DIRECTORY_SEPARATOR;
+ $path = "";
+ } else if ($path{1} == DIRECTORY_SEPARATOR) {
+ // UNC drive
+ $root = DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR;
+ $path = substr($path, 2);
+ }
+ else {
+ $root = DIRECTORY_SEPARATOR;
+ $path = substr($path, 1);
+ }
+ }
+
+ $s = array();
+ array_push($s, $root);
+ $tok = strtok($path, DIRECTORY_SEPARATOR);
+ while ($tok !== false) {
+ $thisToken = $tok;
+ if ("." === $thisToken) {
+ $tok = strtok(DIRECTORY_SEPARATOR);
+ continue;
+ } elseif (".." === $thisToken) {
+ if (count($s) < 2) {
+ // using '..' in path that is too short
+ throw new IOException("Cannot resolve path: $orig");
+ } else {
+ array_pop($s);
+ }
+ } else { // plain component
+ array_push($s, $thisToken);
+ }
+ $tok = strtok(DIRECTORY_SEPARATOR);
+ }
+
+ $sb = "";
+ for ($i=0,$_i=count($s); $i < $_i; $i++) {
+ if ($i > 1) {
+ // not before the filesystem root and not after it, since root
+ // already contains one
+ $sb .= DIRECTORY_SEPARATOR;
+ }
+ $sb .= (string) $s[$i];
+ }
+
+
+ $path = (string) $sb;
+ if ($dosWithDrive === true) {
+ $path = str_replace('/', '\\', $path);
+ }
+ return $path;
+ }
+
+ /**
+ * @return boolean Whether contents of two files is the same.
+ */
+ public function contentEquals(PhingFile $file1, PhingFile $file2) {
+
+ if (!($file1->exists() || $file2->exists())) {
+ return false;
+ }
+
+ if (!($file1->canRead() || $file2->canRead())) {
+ return false;
+ }
+
+ $c1 = file_get_contents($file1->getAbsolutePath());
+ $c2 = file_get_contents($file2->getAbsolutePath());
+
+ return trim($c1) == trim($c2);
+ }
+
+}
+?>
diff --git a/buildscripts/phing/classes/phing/util/LogWriter.php b/buildscripts/phing/classes/phing/util/LogWriter.php
new file mode 100644
index 00000000..9e704fc3
--- /dev/null
+++ b/buildscripts/phing/classes/phing/util/LogWriter.php
@@ -0,0 +1,96 @@
+<?php
+
+ /**
+ * $Id: LogWriter.php,v 1.2 2004/11/09 13:16:11 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+ require_once 'phing/system/io/Writer.php';
+ require_once 'phing/Task.php';
+
+ /**
+ * Extends the Writer class to output messages to Phing's log
+ *
+ * @author Michiel Rook <michiel@trendserver.nl>
+ * @version $Id: LogWriter.php,v 1.2 2004/11/09 13:16:11 hlellelid Exp $
+ * @package phing.util
+ */
+ class LogWriter extends Writer
+ {
+ private $task = NULL;
+
+ private $level = NULL;
+
+ /**
+ * Constructs a new LogWriter object
+ */
+ function __construct(Task $task, $level = PROJECT_MSG_INFO)
+ {
+ $this->task = $task;
+ $this->level = $level;
+ }
+
+ /**
+ * @see Writer::write()
+ */
+ function write($buf, $off = null, $len = null)
+ {
+ $lines = explode("\n", $buf);
+
+ foreach ($lines as $line)
+ {
+ if ($line == "")
+ {
+ continue;
+ }
+
+ $this->task->log($line, $this->level);
+ }
+ }
+
+ /**
+ * @see Writer::reset()
+ */
+ function reset()
+ {
+ }
+
+ /**
+ * @see Writer::close()
+ */
+ function close()
+ {
+ }
+
+ /**
+ * @see Writer::open()
+ */
+ function open()
+ {
+ }
+
+ /**
+ * @see Writer::getResource()
+ */
+ function getResource()
+ {
+ return $this->task;
+ }
+ }
+
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/util/PathTokenizer.php b/buildscripts/phing/classes/phing/util/PathTokenizer.php
new file mode 100644
index 00000000..29c0f059
--- /dev/null
+++ b/buildscripts/phing/classes/phing/util/PathTokenizer.php
@@ -0,0 +1,245 @@
+<?php
+/*
+ * $Id: PathTokenizer.php,v 1.3 2003/12/24 12:38:42 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+
+
+include_once 'phing/util/StringHelper.php';
+
+
+
+/**
+
+ * A Path tokenizer takes a path and returns the components that make up
+
+ * that path.
+
+ *
+
+ * The path can use path separators of either ':' or ';' and file separators
+
+ * of either '/' or '\'.
+
+ *
+
+ * @author Hans Lellelid <hans@xmpl.org> (Phing)
+
+ * @author Conor MacNeill (Ant)
+
+ * @author Jeff Tulley <jtulley@novell.com> (Ant)
+
+ * @pacakge phing.util
+
+ */
+
+class PathTokenizer {
+
+
+
+ /**
+
+ * A array of tokens, created by preg_split().
+
+ */
+
+ private $tokens = array();
+
+
+
+ /**
+
+ * A string which stores any path components which have been read ahead
+
+ * due to DOS filesystem compensation.
+
+ * @var string
+
+ */
+
+ private $lookahead;
+
+
+
+ /**
+
+ * Flag to indicate whether or not we are running on a platform with a
+
+ * DOS style filesystem
+
+ * @var boolean
+
+ */
+
+ private $dosStyleFilesystem;
+
+
+
+ /**
+
+ * Constructs a path tokenizer for the specified path.
+
+ *
+
+ * @param path The path to tokenize. Must not be <code>null</code>.
+
+ */
+
+ public function __construct($path) {
+
+ // on Windows and Unix, we can ignore delimiters and still have
+
+ // enough information to tokenize correctly.
+
+ $this->tokens = preg_split("/[;:]/", $path, -1, PREG_SPLIT_NO_EMPTY);
+
+ $this->dosStyleFilesystem = ( PATH_SEPARATOR == ';');
+
+ }
+
+
+
+ /**
+
+ * Tests if there are more path elements available from this tokenizer's
+
+ * path. If this method returns <code>true</code>, then a subsequent call
+
+ * to nextToken will successfully return a token.
+
+ *
+
+ * @return <code>true</code> if and only if there is at least one token
+
+ * in the string after the current position; <code>false</code> otherwise.
+
+ */
+
+ public function hasMoreTokens() {
+
+ if ($this->lookahead !== null) {
+
+ return true;
+
+ }
+
+ return !empty($this->tokens);
+
+ }
+
+
+
+ /**
+
+ * Returns the next path element from this tokenizer.
+
+ *
+
+ * @return the next path element from this tokenizer.
+
+ *
+
+ * @throws Exception if there are no more elements in this tokenizer's path.
+
+ */
+
+ public function nextToken() {
+
+
+
+ if ($this->lookahead !== null) {
+
+ $token = $this->lookahead;
+
+ $this->lookahead = null;
+
+ } else {
+
+ $token = trim(array_shift($this->tokens));
+
+ }
+
+
+
+
+
+ if (strlen($token) === 1 && Character::isLetter($token{0})
+
+ && $this->dosStyleFilesystem
+
+ && !empty($this->tokens)) {
+
+ // we are on a dos style system so this path could be a drive
+
+ // spec. We look at the next token
+
+ $nextToken = trim(array_shift($this->tokens));
+
+ if (StringHelper::startsWith('\\', $nextToken) || StringHelper::startsWith('/', $nextToken)) {
+
+ // we know we are on a DOS style platform and the next path
+
+ // starts with a slash or backslash, so we know this is a
+
+ // drive spec
+
+ $token .= ':' . $nextToken;
+
+ } else {
+
+ // store the token just read for next time
+
+ $this->lookahead = $nextToken;
+
+ }
+
+ }
+
+
+
+ return $token;
+
+ }
+
+
+
+ /**
+
+ * Non StringTokenizer function, that indicates whether the specified path is contained in loaded tokens.
+
+ * We can do this easily because in PHP implimentation we're using arrays.
+
+ * @param string $path path to search for.
+
+ * @return boolean
+
+ */
+
+ public function contains($path) {
+
+ return in_array($path, $this->tokens, true);
+
+ }
+
+
+
+}
+
+
+
diff --git a/buildscripts/phing/classes/phing/util/SourceFileScanner.php b/buildscripts/phing/classes/phing/util/SourceFileScanner.php
new file mode 100644
index 00000000..b157dcb9
--- /dev/null
+++ b/buildscripts/phing/classes/phing/util/SourceFileScanner.php
@@ -0,0 +1,159 @@
+<?php
+/*
+ * $Id: SourceFileScanner.php,v 1.11 2005/05/26 13:10:53 mrook Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * Utility class that collects the functionality of the various
+ * scanDir methods that have been scattered in several tasks before.
+ *
+ * The only method returns an array of source files. The array is a
+ * subset of the files given as a parameter and holds only those that
+ * are newer than their corresponding target files.
+ * @package phing.util
+ */
+class SourceFileScanner {
+
+ /** Instance of FileUtils */
+ private $fileUtils;
+
+ /** Task this class is working for -- for logging purposes. */
+ private $task;
+
+ /**
+ * @param task The task we should log messages through
+ */
+ function __construct($task) {
+ $this->task = $task;
+ $this->fileUtils = new FileUtils();
+ }
+
+ /**
+ * Restrict the given set of files to those that are newer than
+ * their corresponding target files.
+ *
+ * @param files the original set of files
+ * @param srcDir all files are relative to this directory
+ * @param destDir target files live here. if null file names
+ * returned by the mapper are assumed to be absolute.
+ * @param FilenameMapper knows how to construct a target file names from
+ * source file names.
+ * @param force Boolean that determines if the files should be
+ * forced to be copied.
+ */
+ function restrict(&$files, $srcDir, $destDir, $mapper, $force = false) {
+ $now = time();
+ $targetList = "";
+
+ /*
+ If we're on Windows, we have to munge the time up to 2 secs to
+ be able to check file modification times.
+ (Windows has a max resolution of two secs for modification times)
+ */
+ $osname = strtolower(Phing::getProperty('os.name'));
+
+ // indexOf()
+ $index = ((($res = strpos($osname, 'win')) === false) ? -1 : $res);
+ if ($index >= 0 ) {
+ $now += 2000;
+ }
+
+ $v = array();
+
+ for ($i=0, $size=count($files); $i < $size; $i++) {
+
+ $targets = $mapper->main($files[$i]);
+ if (empty($targets)) {
+ $this->task->log($files[$i]." skipped - don't know how to handle it", PROJECT_MSG_VERBOSE);
+ continue;
+ }
+
+ $src = null;
+ try {
+ if ($srcDir === null) {
+ $src = new PhingFile($files[$i]);
+ } else {
+ $src = $this->fileUtils->resolveFile($srcDir, $files[$i]);
+ }
+
+ if ($src->lastModified() > $now) {
+ $this->task->log("Warning: ".$files[$i]." modified in the future (".$src->lastModified()." > ".$now.")", PROJECT_MSG_WARN);
+ }
+ } catch (IOException $ioe) {
+ $this->task->log("Unable to read file ".$files[$i]." (skipping): " . $ioe->getMessage());
+ continue;
+ }
+
+ $added = false;
+ $targetList = "";
+
+ for ($j=0,$_j=count($targets); (!$added && $j < $_j); $j++) {
+
+ $dest = null;
+ if ($destDir === null) {
+ $dest = new PhingFile($targets[$j]);
+ } else {
+ $dest = $this->fileUtils->resolveFile($destDir, $targets[$j]);
+ }
+
+ if (!$dest->exists()) {
+ $this->task->log($files[$i]." added as " . $dest->__toString() . " doesn't exist.", PROJECT_MSG_VERBOSE);
+ $v[] =$files[$i];
+ $added = true;
+ } elseif ($src->lastModified() > $dest->lastModified()) {
+ $this->task->log($files[$i]." added as " . $dest->__toString() . " is outdated.", PROJECT_MSG_VERBOSE );
+ $v[]=$files[$i];
+ $added = true;
+ } elseif ($force === true) {
+ $this->task->log($files[$i]." added as " . $dest->__toString() . " is forced to be overwritten.", PROJECT_MSG_VERBOSE );
+ $v[]=$files[$i];
+ $added = true;
+ } else {
+ if (strlen($targetList) > 0) {
+ $targetList .= ", ";
+ }
+ $targetList .= $dest->getAbsolutePath();
+ }
+ }
+
+ if (!$added) {
+ $this->task->log($files[$i]." omitted as ".$targetList." ".(count($targets) === 1 ? " is " : " are ")."up to date.", PROJECT_MSG_VERBOSE);
+ }
+
+ }
+ $result = array();
+ $result = $v;
+ return $result;
+ }
+
+ /**
+ * Convenience layer on top of restrict that returns the source
+ * files as PhingFile objects (containing absolute paths if srcDir is
+ * absolute).
+ */
+ function restrictAsFiles(&$files, &$srcDir, &$destDir, &$mapper) {
+ $res = $this->restrict($files, $srcDir, $destDir, $mapper);
+ $result = array();
+ for ($i=0; $i<count($res); $i++) {
+ $result[$i] = new PhingFile($srcDir, $res[$i]);
+ }
+ return $result;
+ }
+}
+?>
diff --git a/buildscripts/phing/classes/phing/util/StringHelper.php b/buildscripts/phing/classes/phing/util/StringHelper.php
new file mode 100644
index 00000000..5d4bfd7a
--- /dev/null
+++ b/buildscripts/phing/classes/phing/util/StringHelper.php
@@ -0,0 +1,209 @@
+<?php
+
+/**
+ * String helper utility class.
+ *
+ * This class includes some Java-like functions for parsing strings,
+ * as well as some functions for getting qualifiers / unqualifying phing-style
+ * classpaths. (e.g. "phing.util.StringHelper").
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @package phing.system.util
+ */
+class StringHelper {
+
+ private static $TRUE_VALUES = array("on", "true", "t", "yes");
+ private static $FALSE_VALUES = array("off", "false", "f", "no");
+
+ /**
+ * Replaces identifier tokens with corresponding text values in passed string.
+ *
+ * @params array $strings Array of strings to multiply. (If string is passed, will convert to array)
+ * @params array $tokens The tokens to search for.
+ * @params array $replacements The values with which to replace found tokens.
+ * @return string
+ */
+ public static function multiply($strings, $tokens, $replacements) {
+ $strings = (array) $strings;
+ $results = array();
+ foreach ($strings as $string) {
+ $results[] = str_replace($tokens, $replacements, $string);
+ }
+ return $results;
+ }
+
+ /**
+ * Remove qualification to name.
+ * E.g. eg.Cat -> Cat
+ * @param string $qualifiedName
+ * @param string $separator Character used to separate.
+ */
+ public static function unqualify($qualifiedName, $separator = '.') {
+ // if false, then will be 0
+ $pos = strrpos($qualifiedName, $separator);
+ if ($pos === false) {
+ return $qualifiedName; // there is no '.' in the qualifed name
+ } else {
+ return substr($qualifiedName, $pos + 1); // start just after '.'
+ }
+ }
+
+ /**
+ * Converts a string to an indexed array of chars
+ * There's really no reason for this to be used in PHP, since strings
+ * are all accessible using the $string{0} notation.
+ * @param string $string
+ * @return array
+ * @deprecated
+ */
+ public static function toCharArray($str) {
+ $ret=array();
+ $len=strlen($str);
+ for ($i=0; $i < $len; $i++) {
+ $ret[] = $str{$i};
+ }
+ return $ret;
+ }
+
+ /**
+ * Get the qualifier part of a qualified name.
+ * E.g. eg.Cat -> eg
+ * @return string
+ */
+ public static function qualifier($qualifiedName, $seperator = '.') {
+ $pos = strrchr($qualifiedName, $seperator);
+ if ($pos === false) {
+ return '';
+ } else {
+ return substr($qualifiedName, 0, $pos);
+ }
+ }
+
+ /**
+ * @param array $columns String[]
+ * @param string $prefix
+ * @return array String[]
+ */
+ public static function prefix( $columns, $prefix) {
+ if ($prefix == null) return $columns;
+ $qualified = array();
+ foreach($columns as $key => $column) {
+ $qualified[$key] = $prefix . $column;
+ }
+ return $qualified;
+ }
+
+ /**
+ *
+ * @return string
+ */
+ public static function root($qualifiedName, $separator = '.') {
+ $loc = strpos($qualifiedName, $separator);
+ return ($loc === false) ? $qualifiedName : substr($qualifiedName, 0, $loc);
+ }
+
+ /**
+ * @return int
+ */
+ public static function hashCode($string) {
+ return crc32($string);
+ }
+
+ /**
+ * @return boolean
+ */
+ public static function booleanValue($s) {
+ if (is_bool($s)) {
+ return $s; // it's already boolean (not a string)
+ }
+ // otherwise assume it's something like "true" or "t"
+ $trimmed = strtolower(trim($s));
+ return (boolean) in_array($trimmed, self::$TRUE_VALUES);
+ }
+
+ /** tests if a string is a representative of a boolean */
+ public static function isBoolean($s) {
+
+ if (is_bool($s)) {
+ return true; // it already is boolean
+ }
+
+ if ($s === "" || $s === null || !is_string($s)) {
+ return false; // not a valid string for testing
+ }
+
+ $test = trim(strtolower($s));
+ return (boolean) in_array($test, array_merge(self::$FALSE_VALUES, self::$TRUE_VALUES));
+ }
+
+ /**
+ * Creates a key based on any number of passed params.
+ * @return string
+ */
+ public static function key() {
+ $args = func_get_args();
+ return serialize($args);
+ }
+
+ /** tests if a string starts with a given string */
+ public static function startsWith($check, $string) {
+ if ($check === "" || $check === $string) {
+ return true;
+ } else {
+ return (strpos($string, $check) === 0) ? true : false;
+ }
+ }
+
+ /** tests if a string ends with a given string */
+ public static function endsWith($check, $string) {
+ if ($check === "" || $check === $string) {
+ return true;
+ } else {
+ return (strpos(strrev($string), strrev($check)) === 0) ? true : false;
+ }
+ }
+
+ /**
+ * a natural way of getting a subtring, php's circular string buffer and strange
+ * return values suck if you want to program strict as of C or friends
+ */
+ public static function substring($string, $startpos, $endpos = -1) {
+ $len = strlen($string);
+ $endpos = (int) (($endpos === -1) ? $len-1 : $endpos);
+ if ($startpos > $len-1 || $startpos < 0) {
+ trigger_error("substring(), Startindex out of bounds must be 0<n<$len", E_USER_ERROR);
+ }
+ if ($endpos > $len-1 || $endpos < $startpos) {
+ trigger_error("substring(), Endindex out of bounds must be $startpos<n<".($len-1), E_USER_ERROR);
+ }
+ if ($startpos === $endpos) {
+ return (string) $string{$startpos};
+ } else {
+ $len = $endpos-$startpos;
+ }
+ return substr($string, $startpos, $len+1);
+ }
+
+ /**
+ * Does the value correspond to a slot variable?
+ * @param string $value
+ */
+ public static function isSlotVar($value) {
+ $value = trim($value);
+ if ($value === "") return false;
+ return preg_match('/^%\{([\w\.\-]+)\}$/', $value);
+ }
+
+ /**
+ * Extracts the variable name for a slot var in the format %{task.current_file}
+ * @param string $var The var from build file.
+ * @return string Extracted name part.
+ */
+ public static function slotVar($var) {
+ return trim($var, '%{} ');
+ }
+
+}
+
+
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/util/regexp/PregEngine.php b/buildscripts/phing/classes/phing/util/regexp/PregEngine.php
new file mode 100644
index 00000000..758b40f3
--- /dev/null
+++ b/buildscripts/phing/classes/phing/util/regexp/PregEngine.php
@@ -0,0 +1,105 @@
+<?php
+/*
+ * $Id: PregEngine.php,v 1.6 2003/12/24 12:38:42 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/util/regexp/RegexpEngine.php';
+
+/**
+ * PREG Regexp Engine.
+ * Implements a regexp engine using PHP's preg_match(), preg_match_all(), and preg_replace() functions.
+ *
+ * @author hans lellelid, hans@velum.net
+ * @package phing.util.regex
+ */
+class PregEngine implements RegexpEngine {
+
+ /**
+ * @var boolean
+ */
+ private $ignoreCase = false;
+
+ /**
+ * Sets whether or not regex operation is case sensitive.
+ * @param boolean $bit
+ * @return void
+ */
+ function setIgnoreCase($bit) {
+ $this->ignoreCase = (boolean) $bit;
+ }
+
+ /**
+ * Gets whether or not regex operation is case sensitive.
+ * @return boolean
+ */
+ function getIgnoreCase() {
+ return $this->ignoreCase;
+ }
+
+ /**
+ * The pattern needs to be converted into PREG style -- which includes adding expression delims & any flags, etc.
+ * @param string $pattern
+ * @return string prepared pattern.
+ */
+ private function preparePattern($pattern)
+ {
+ return '/'.$pattern.'/'.($this->ignoreCase ? 'i' : '');
+ }
+
+ /**
+ * Matches pattern against source string and sets the matches array.
+ * @param string $pattern The regex pattern to match.
+ * @param string $source The source string.
+ * @param array $matches The array in which to store matches.
+ * @return boolean Success of matching operation.
+ */
+ function match($pattern, $source, &$matches) {
+ return preg_match($this->preparePattern($pattern), $source, $matches);
+ }
+
+ /**
+ * Matches all patterns in source string and sets the matches array.
+ * @param string $pattern The regex pattern to match.
+ * @param string $source The source string.
+ * @param array $matches The array in which to store matches.
+ * @return boolean Success of matching operation.
+ */
+ function matchAll($pattern, $source, &$matches) {
+ return preg_match_all($this->preparePattern($pattern), $source, $matches);
+ }
+
+ /**
+ * Replaces $pattern with $replace in $source string.
+ * References to \1 group matches will be replaced with more preg-friendly
+ * $1.
+ * @param string $pattern The regex pattern to match.
+ * @param string $replace The string with which to replace matches.
+ * @param string $source The source string.
+ * @return string The replaced source string.
+ */
+ function replace($pattern, $replace, $source) {
+ // convert \1 -> $1, because we want to use the more generic \1 in the XML
+ // but PREG prefers $1 syntax.
+ $replace = preg_replace('/[^\\\]\\\(\d+)/', '$1', $replace);
+ return preg_replace($this->preparePattern($pattern), $replace, $source);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/util/regexp/Regexp.php b/buildscripts/phing/classes/phing/util/regexp/Regexp.php
new file mode 100644
index 00000000..68c06668
--- /dev/null
+++ b/buildscripts/phing/classes/phing/util/regexp/Regexp.php
@@ -0,0 +1,168 @@
+<?php
+/*
+ * $Id: Regexp.php,v 1.5 2003/12/24 18:40:33 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * A factory class for regex functions.
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @package phing.util.regexp
+ * @version $Revision: 1.5 $
+ */
+class Regexp {
+
+ /**
+ * Matching groups found.
+ * @var array
+ */
+ private $groups = array();
+
+ /**
+ * Pattern to match.
+ * @var string
+ */
+ private $pattern;
+
+ /**
+ * Replacement pattern.
+ * @var string
+ */
+ private $replace;
+
+ /**
+ * The regex engine -- e.g. 'preg' or 'ereg';
+ * @var RegexpEngine
+ */
+ private $engine;
+
+ /**
+ * Constructor sets the regex engine to use (preg by default).
+ * @param string $_engineType The regex engine to use.
+ */
+ function __construct($engineType='preg') {
+ if ($engineType == 'preg') {
+ include_once 'phing/util/regexp/PregEngine.php';
+ $this->engine = new PregEngine();
+ } elseif ($engineType == 'ereg') {
+ include_once 'phing/util/regexp/EregEngine.php';
+ $this->engine = new EregEngine();
+ } else {
+ throw new BuildException("Invalid engine type for Regexp: " . $engineType);
+ }
+ }
+
+ /**
+ * Sets pattern to use for matching.
+ * @param string $pat The pattern to match on.
+ * @return void
+ */
+ public function setPattern($pat) {
+ $this->pattern = (string) $pat;
+ }
+
+
+ /**
+ * Gets pattern to use for matching.
+ * @return string The pattern to match on.
+ */
+ public function getPattern() {
+ return $this->pattern;
+ }
+
+ /**
+ * Sets replacement string.
+ * @param string $rep The pattern to replace matches with.
+ * @return void
+ */
+ public function setReplace($rep) {
+ $this->replace = (string) $rep;
+ }
+
+ /**
+ * Gets replacement string.
+ * @return string The pattern to replace matches with.
+ * @return void
+ */
+ public function getReplace() {
+ return $this->replace;
+ }
+
+ /**
+ * Performs match of specified pattern against $subject.
+ * @param string $subject The subject, on which to perform matches.
+ * @return boolean Whether or not pattern matches subject string passed.
+ */
+ public function matches($subject) {
+ if($this->pattern === null) {
+ throw new Exception("No pattern specified for regexp match().");
+ }
+ return $this->engine->match($this->pattern, $subject, $this->groups);
+ }
+
+ /**
+ * Performs replacement of specified pattern and replacement strings.
+ * @param string $subject Text on which to perform replacement.
+ * @return string subject after replacement has been performed.
+ */
+ public function replace($subject) {
+ if ($this->pattern === null || $this->replace === null) {
+ throw new Exception("Missing pattern or replacement string regexp replace().");
+ }
+ return $this->engine->replace($this->pattern, $this->replace, $subject);
+ }
+
+ /**
+ * Get array of matched groups.
+ * @return array Matched groups
+ */
+ function getGroups() {
+ return $this->groups;
+ }
+
+ /**
+ * Get specific matched group.
+ * @param integer $idx
+ * @return string specified group or NULL if group is not set.
+ */
+ function getGroup($idx) {
+ if (!isset($this->groups[$idx])) {
+ return null;
+ }
+ return $this->groups[$idx];
+ }
+
+ /**
+ * Sets whether the regexp matching is case insensitive.
+ * (default is false -- i.e. case sensisitive)
+ * @param boolean $bit
+ */
+ function setIgnoreCase($bit) {
+ $this->engine->setIgnoreCase($bit);
+ }
+
+ /**
+ * Gets whether the regexp matching is case insensitive.
+ * @return boolean
+ */
+ function getIgnoreCase() {
+ return $this->engine->getIgnoreCase();
+ }
+}
+
+?> \ No newline at end of file
diff --git a/buildscripts/phing/classes/phing/util/regexp/RegexpEngine.php b/buildscripts/phing/classes/phing/util/regexp/RegexpEngine.php
new file mode 100644
index 00000000..7d323466
--- /dev/null
+++ b/buildscripts/phing/classes/phing/util/regexp/RegexpEngine.php
@@ -0,0 +1,74 @@
+<?php
+/*
+ * $Id: RegexpEngine.php,v 1.4 2003/12/24 12:38:42 hlellelid Exp $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+/**
+ * Contains some shared attributes and methods -- and some abstract methods with
+ * engine-specific implementations that sub-classes must override.
+ *
+ * @author Hans Lellelid <hans@velum.net>
+ * @package phing.util.regex
+ * @version $Revision: 1.4 $
+ */
+interface RegexpEngine {
+
+ /**
+ * Sets whether or not regex operation should ingore case.
+ * @param boolean $bit
+ * @return void
+ */
+ public function setIgnoreCase($bit);
+
+ /**
+ * Returns status of ignore case flag.
+ * @return boolean
+ */
+ public function getIgnoreCase();
+
+ /**
+ * Matches pattern against source string and sets the matches array.
+ * @param string $pattern The regex pattern to match.
+ * @param string $source The source string.
+ * @param array $matches The array in which to store matches.
+ * @return boolean Success of matching operation.
+ */
+ function match($pattern, $source, &$matches);
+
+ /**
+ * Matches all patterns in source string and sets the matches array.
+ * @param string $pattern The regex pattern to match.
+ * @param string $source The source string.
+ * @param array $matches The array in which to store matches.
+ * @return boolean Success of matching operation.
+ */
+ function matchAll($pattern, $source, &$matches);
+
+ /**
+ * Replaces $pattern with $replace in $source string.
+ * @param string $pattern The regex pattern to match.
+ * @param string $replace The string with which to replace matches.
+ * @param string $source The source string.
+ * @return string The replaced source string.
+ */
+ function replace($pattern, $replace, $source);
+
+}
+
+?> \ No newline at end of file
diff --git a/buildscripts/phing/etc/VERSION.TXT b/buildscripts/phing/etc/VERSION.TXT
new file mode 100644
index 00000000..00fa3b83
--- /dev/null
+++ b/buildscripts/phing/etc/VERSION.TXT
@@ -0,0 +1 @@
+Phing 2.2 BRANCH (SVN) \ No newline at end of file
diff --git a/buildscripts/phing/etc/coverage-frames.xsl b/buildscripts/phing/etc/coverage-frames.xsl
new file mode 100644
index 00000000..5e8d8e3e
--- /dev/null
+++ b/buildscripts/phing/etc/coverage-frames.xsl
@@ -0,0 +1,669 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
+ xmlns:exsl="http://exslt.org/common"
+ xmlns:date="http://exslt.org/dates-and-times"
+ extension-element-prefixes="exsl date">
+<xsl:output method="html" indent="yes"/>
+<xsl:decimal-format decimal-separator="." grouping-separator="," />
+<!--
+ Copyright 2001-2004 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<!--
+
+ Sample stylesheet to be used with Xdebug/Phing code coverage output.
+ Based on JProbe stylesheets from Apache Ant.
+
+ It creates a set of HTML files a la javadoc where you can browse easily
+ through all packages and classes.
+
+ @author Michiel Rook <a href="mailto:michiel@trendserver.nl"/>
+ @author Stephane Bailliez <a href="mailto:sbailliez@apache.org"/>
+
+-->
+
+<!-- default output directory is current directory -->
+<xsl:param name="output.dir" select="'.'"/>
+
+<!-- ======================================================================
+ Root element
+ ======================================================================= -->
+<xsl:template match="/snapshot">
+ <!-- create the index.html -->
+ <exsl:document href="efile://{$output.dir}/index.html">
+ <xsl:call-template name="index.html"/>
+ </exsl:document>
+
+ <!-- create the stylesheet.css -->
+ <exsl:document href="efile://{$output.dir}/stylesheet.css">
+ <xsl:call-template name="stylesheet.css"/>
+ </exsl:document>
+
+ <!-- create the overview-packages.html at the root -->
+ <exsl:document href="efile://{$output.dir}/overview-summary.html">
+ <xsl:apply-templates select="." mode="overview.packages"/>
+ </exsl:document>
+
+ <!-- create the all-packages.html at the root -->
+ <exsl:document href="efile://{$output.dir}/overview-frame.html">
+ <xsl:apply-templates select="." mode="all.packages"/>
+ </exsl:document>
+
+ <!-- create the all-classes.html at the root -->
+ <exsl:document href="efile://{$output.dir}/allclasses-frame.html">
+ <xsl:apply-templates select="." mode="all.classes"/>
+ </exsl:document>
+
+ <!-- process all packages -->
+ <xsl:apply-templates select="./package" mode="write"/>
+</xsl:template>
+
+<!-- =======================================================================
+ Frameset definition. Entry point for the report.
+ 3 frames: packageListFrame, classListFrame, classFrame
+ ======================================================================= -->
+<xsl:template name="index.html">
+<html>
+ <head><title>Coverage Results.</title></head>
+ <frameset cols="20%,80%">
+ <frameset rows="30%,70%">
+ <frame src="overview-frame.html" name="packageListFrame"/>
+ <frame src="allclasses-frame.html" name="classListFrame"/>
+ </frameset>
+ <frame src="overview-summary.html" name="classFrame"/>
+ </frameset>
+ <noframes>
+ <h2>Frame Alert</h2>
+ <p>
+ This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client.
+ </p>
+ </noframes>
+</html>
+</xsl:template>
+
+<!-- =======================================================================
+ Stylesheet CSS used
+ ======================================================================= -->
+<!-- this is the stylesheet css to use for nearly everything -->
+<xsl:template name="stylesheet.css">
+ .bannercell {
+ border: 0px;
+ padding: 0px;
+ }
+ body {
+ margin-left: 10;
+ margin-right: 10;
+ background-color:#FFFFFF;
+ font-family: verdana,arial,sanserif;
+ color:#000000;
+ }
+ a {
+ color: #003399;
+ }
+ a:hover {
+ color: #888888;
+ }
+ .a td {
+ background: #efefef;
+ }
+ .b td {
+ background: #fff;
+ }
+ th, td {
+ text-align: left;
+ vertical-align: top;
+ }
+ th {
+ font-weight:bold;
+ background: #ccc;
+ color: black;
+ }
+ table, th, td {
+ font-size: 12px;
+ border: none
+ }
+ table.log tr td, tr th {
+ }
+ h2 {
+ font-weight:bold;
+ font-size: 12px;
+ margin-bottom: 5;
+ }
+ h3 {
+ font-size:100%;
+ font-weight: 12px;
+ background: #DFDFDF
+ color: white;
+ text-decoration: none;
+ padding: 5px;
+ margin-right: 2px;
+ margin-left: 2px;
+ margin-bottom: 0;
+ }
+ .small {
+ font-size: 9px;
+ }
+TD.empty {
+ FONT-SIZE: 2px; BACKGROUND: #c0c0c0; BORDER:#9c9c9c 1px solid;
+ color: #c0c0c0;
+}
+TD.fullcover {
+ FONT-SIZE: 2px; BACKGROUND: #00df00; BORDER:#9c9c9c 1px solid;
+ color: #00df00;
+}
+TD.covered {
+ FONT-SIZE: 2px; BACKGROUND: #00df00; BORDER-LEFT:#9c9c9c 1px solid;BORDER-TOP:#9c9c9c 1px solid;BORDER-BOTTOM:#9c9c9c 1px solid;
+ color: #00df00;
+}
+TD.uncovered {
+ FONT-SIZE: 2px; BACKGROUND: #df0000; BORDER:#9c9c9c 1px solid;
+ color: #df0000;
+}
+PRE.srcLine {
+ BACKGROUND: #ffffff; MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px;
+}
+td.lineCount, td.coverageCount {
+ BACKGROUND: #F0F0F0; PADDING-RIGHT: 3px;
+ text-align: right;
+}
+td.lineCountHighlight {
+ background: #C8C8F0; PADDING-RIGHT: 3px;
+ text-align: right;
+}
+td.coverageCountHighlight {
+ background: #F0C8C8; PADDING-RIGHT: 3px;
+ text-align: right;
+}
+span.srcLineHighlight {
+ background: #F0C8C8;
+}
+span.srcLine {
+ background: #C8C8F0;
+}
+TD.srcLineClassStart {
+ WIDTH: 100%; BORDER-TOP:#dcdcdc 1px solid; FONT-WEIGHT: bold;
+}
+.srcLine , .srcLine ol, .srcLine ol li {margin: 0;}
+.srcLine .de1, .srcLine .de2 {font-family: 'Courier New', Courier, monospace; font-weight: normal;}
+.srcLine .imp {font-weight: bold; color: red;}
+.srcLine .kw1 {color: #b1b100;}
+.srcLine .kw2 {color: #000000; font-weight: bold;}
+.srcLine .kw3 {color: #000066;}
+.srcLine .co1 {color: #808080; font-style: italic;}
+.srcLine .co2 {color: #808080; font-style: italic;}
+.srcLine .coMULTI {color: #808080; font-style: italic;}
+.srcLine .es0 {color: #000099; font-weight: bold;}
+.srcLine .br0 {color: #66cc66;}
+.srcLine .st0 {color: #ff0000;}
+.srcLine .nu0 {color: #cc66cc;}
+.srcLine .me1 {color: #006600;}
+.srcLine .me2 {color: #006600;}
+.srcLine .re0 {color: #0000ff;}
+</xsl:template>
+
+<!-- =======================================================================
+ List of all classes in all packages
+ This will be the first page in the classListFrame
+ ======================================================================= -->
+<xsl:template match="snapshot" mode="all.classes">
+ <html>
+ <head>
+ <xsl:call-template name="create.stylesheet.link"/>
+ </head>
+ <body>
+ <h2>All Classes</h2>
+ <table width="100%">
+ <xsl:for-each select="package/class">
+ <xsl:sort select="@name"/>
+ <xsl:variable name="package.name" select="(ancestor::package)[last()]/@name"/>
+ <xsl:variable name="link">
+ <xsl:if test="not($package.name='')">
+ <xsl:value-of select="translate($package.name,'.','/')"/><xsl:text>/</xsl:text>
+ </xsl:if><xsl:value-of select="@name"/><xsl:text>.html</xsl:text>
+ </xsl:variable>
+ <tr>
+ <td nowrap="nowrap">
+ <a target="classFrame" href="{$link}"><xsl:value-of select="@name"/></a>
+ <xsl:choose>
+ <xsl:when test="@totalcount=0">
+ <i> (-)</i>
+ </xsl:when>
+ <xsl:otherwise>
+ <i> (<xsl:value-of select="format-number(@totalcovered div @totalcount, '0.0%')"/>)</i>
+ </xsl:otherwise>
+ </xsl:choose>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </body>
+ </html>
+</xsl:template>
+
+<!-- list of all packages -->
+<xsl:template match="snapshot" mode="all.packages">
+ <html>
+ <head>
+ <xsl:call-template name="create.stylesheet.link"/>
+ </head>
+ <body>
+ <h2><a href="overview-summary.html" target="classFrame">Overview</a></h2>
+ <h2>All Packages</h2>
+ <table width="100%">
+ <xsl:for-each select="package">
+ <xsl:sort select="@name" order="ascending"/>
+ <tr>
+ <td nowrap="nowrap">
+ <a href="{translate(@name,'.','/')}/package-summary.html" target="classFrame">
+ <xsl:value-of select="@name"/>
+ </a>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </body>
+ </html>
+</xsl:template>
+
+<!-- overview of statistics in packages -->
+<xsl:template match="snapshot" mode="overview.packages">
+ <html>
+ <head>
+ <xsl:call-template name="create.stylesheet.link"/>
+ </head>
+ <body onload="open('allclasses-frame.html','classListFrame')">
+ <xsl:call-template name="pageHeader"/>
+ <table class="log" cellpadding="5" cellspacing="0" width="100%">
+ <tr class="a">
+ <td class="small">Packages: <xsl:value-of select="count(package)"/></td>
+ <td class="small">Classes: <xsl:value-of select="count(package/class)"/></td>
+ <td class="small">Methods: <xsl:value-of select="@methodcount"/></td>
+ <td class="small">LOC: <xsl:value-of select="count(package/class/sourcefile/sourceline)"/></td>
+ <td class="small">Statements: <xsl:value-of select="@statementcount"/></td>
+ </tr>
+ </table>
+ <br/>
+
+ <table class="log" cellpadding="5" cellspacing="0" width="100%">
+ <tr>
+ <th width="100%" nowrap="nowrap"></th>
+ <th>Statements</th>
+ <th>Methods</th>
+ <th width="350" colspan="2" nowrap="nowrap">Total coverage</th>
+ </tr>
+ <tr class="a">
+ <td><b>Project</b></td>
+ <xsl:call-template name="stats.formatted"/>
+ </tr>
+ <tr>
+ <td colspan="3"><br/></td>
+ </tr>
+ <tr>
+ <th width="100%">Packages</th>
+ <th>Statements</th>
+ <th>Methods</th>
+ <th width="350" colspan="2" nowrap="nowrap">Total coverage</th>
+ </tr>
+ <!-- display packages and sort them via their coverage rate -->
+ <xsl:for-each select="package">
+ <xsl:sort data-type="number" select="@totalcovered div @totalcount"/>
+ <tr>
+ <xsl:call-template name="alternate-row"/>
+ <td><a href="{translate(@name,'.','/')}/package-summary.html"><xsl:value-of select="@name"/></a></td>
+ <xsl:call-template name="stats.formatted"/>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <xsl:call-template name="pageFooter"/>
+ </body>
+ </html>
+</xsl:template>
+
+<!--
+ detailed info for a package. It will output the list of classes
+, the summary page, and the info for each class
+-->
+<xsl:template match="package" mode="write">
+ <xsl:variable name="package.dir">
+ <xsl:if test="not(@name = '')"><xsl:value-of select="translate(@name,'.','/')"/></xsl:if>
+ <xsl:if test="@name = ''">.</xsl:if>
+ </xsl:variable>
+
+ <!-- create a classes-list.html in the package directory -->
+ <exsl:document href="efile://{$output.dir}/{$package.dir}/package-frame.html">
+ <xsl:apply-templates select="." mode="classes.list"/>
+ </exsl:document>
+
+ <!-- create a package-summary.html in the package directory -->
+ <exsl:document href="efile://{$output.dir}/{$package.dir}/package-summary.html">
+ <xsl:apply-templates select="." mode="package.summary"/>
+ </exsl:document>
+
+ <!-- for each class, creates a @name.html -->
+ <xsl:for-each select="class">
+ <exsl:document href="efile://{$output.dir}/{$package.dir}/{@name}.html">
+ <xsl:apply-templates select="." mode="class.details"/>
+ </exsl:document>
+ </xsl:for-each>
+</xsl:template>
+
+<!-- list of classes in a package -->
+<xsl:template match="package" mode="classes.list">
+ <html>
+ <HEAD>
+ <xsl:call-template name="create.stylesheet.link">
+ <xsl:with-param name="package.name" select="@name"/>
+ </xsl:call-template>
+ </HEAD>
+ <BODY>
+ <table width="100%">
+ <tr>
+ <td nowrap="nowrap">
+ <H2><a href="package-summary.html" target="classFrame"><xsl:value-of select="@name"/></a></H2>
+ </td>
+ </tr>
+ </table>
+
+ <H2>Classes</H2>
+ <TABLE WIDTH="100%">
+ <xsl:for-each select="class">
+ <xsl:sort select="@name"/>
+ <tr>
+ <td nowrap="nowrap">
+ <a href="{@name}.html" target="classFrame"><xsl:value-of select="@name"/></a>
+ <xsl:choose>
+ <xsl:when test="@totalcount=0">
+ <i> (-)</i>
+ </xsl:when>
+ <xsl:otherwise>
+ <i>(<xsl:value-of select="format-number(@totalcovered div @totalcount, '0.0%')"/>)</i>
+ </xsl:otherwise>
+ </xsl:choose>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </TABLE>
+ </BODY>
+ </html>
+</xsl:template>
+
+<!-- summary of a package -->
+<xsl:template match="package" mode="package.summary">
+ <HTML>
+ <HEAD>
+ <xsl:call-template name="create.stylesheet.link">
+ <xsl:with-param name="package.name" select="@name"/>
+ </xsl:call-template>
+ </HEAD>
+ <!-- when loading this package, it will open the classes into the frame -->
+ <BODY onload="open('package-frame.html','classListFrame')">
+ <xsl:call-template name="pageHeader"/>
+ <table class="log" cellpadding="5" cellspacing="0" width="100%">
+ <tr class="a">
+ <td class="small">Classes: <xsl:value-of select="count(class)"/></td>
+ <td class="small">Methods: <xsl:value-of select="@methodcount"/></td>
+ <td class="small">LOC: <xsl:value-of select="count(class/sourcefile/sourceline)"/></td>
+ <td class="small">Statements: <xsl:value-of select="@statementcount"/></td>
+ </tr>
+ </table>
+ <br/>
+
+ <table class="log" cellpadding="5" cellspacing="0" width="100%">
+ <tr>
+ <th width="100%">Package</th>
+ <th>Statements</th>
+ <th>Methods</th>
+ <th width="350" colspan="2" nowrap="nowrap">Total coverage</th>
+ </tr>
+ <xsl:apply-templates select="." mode="stats"/>
+
+ <xsl:if test="count(class) &gt; 0">
+ <tr>
+ <td colspan="3"><br/></td>
+ </tr>
+ <tr>
+ <th width="100%">Classes</th>
+ <th>Statements</th>
+ <th>Methods</th>
+ <th width="350" colspan="2" nowrap="nowrap">Total coverage</th>
+ </tr>
+ <xsl:apply-templates select="class" mode="stats">
+ <xsl:sort data-type="number" select="@totalcovered div @totalcount"/>
+ </xsl:apply-templates>
+ </xsl:if>
+ </table>
+ <xsl:call-template name="pageFooter"/>
+ </BODY>
+ </HTML>
+</xsl:template>
+
+<!-- details of a class -->
+<xsl:template match="class" mode="class.details">
+ <xsl:variable name="package.name" select="(ancestor::package)[last()]/@name"/>
+ <HTML>
+ <HEAD>
+ <xsl:call-template name="create.stylesheet.link">
+ <xsl:with-param name="package.name" select="$package.name"/>
+ </xsl:call-template>
+ </HEAD>
+ <BODY>
+ <xsl:call-template name="pageHeader"/>
+ <table class="log" cellpadding="5" cellspacing="0" width="100%">
+ <tr class="a">
+ <td class="small">Methods: <xsl:value-of select="@methodcount"/></td>
+ <td class="small">LOC: <xsl:value-of select="count(sourcefile/sourceline)"/></td>
+ <td class="small">Statements: <xsl:value-of select="@statementcount"/></td>
+ </tr>
+ </table>
+ <br/>
+
+ <!-- class summary -->
+ <table class="log" cellpadding="5" cellspacing="0" width="100%">
+ <tr>
+ <th width="100%">Source file</th>
+ <th>Statements</th>
+ <th>Methods</th>
+ <th width="250" colspan="2" nowrap="nowrap">Total coverage</th>
+ </tr>
+ <tr>
+ <xsl:call-template name="alternate-row"/>
+ <td><xsl:value-of select="sourcefile/@name"/></td>
+ <xsl:call-template name="stats.formatted"/>
+ </tr>
+ </table>
+ <table cellspacing="0" cellpadding="0" width="100%">
+ <xsl:apply-templates select="sourcefile/sourceline"/>
+ </table>
+ <br/>
+ <xsl:call-template name="pageFooter"/>
+ </BODY>
+ </HTML>
+
+</xsl:template>
+
+<!-- Page Header -->
+<xsl:template name="pageHeader">
+ <!-- jakarta logo -->
+ <table border="0" cellpadding="0" cellspacing="0" width="100%">
+ <tr>
+ <td class="bannercell" rowspan="2">
+ <a href="http://phing.info/">
+ <img src="http://phing.info/images/phing.gif" alt="http://phing.info/" align="left" border="0"/>
+ </a>
+ </td>
+ <td style="text-align:right"><h2>Source Code Coverage</h2></td>
+ </tr>
+ <tr>
+ <td style="text-align:right">Designed for use with <a href='http://pear.php.net/package/PHPUnit2'>PHPUnit2</a>, <a href='http://www.xdebug.org/'>Xdebug</a> and <a href='http://phing.info/'>Phing</a>.</td>
+ </tr>
+ </table>
+ <hr size="1"/>
+</xsl:template>
+
+<!-- Page Footer -->
+<xsl:template name="pageFooter">
+ <table width="100%">
+ <tr><td><hr noshade="yes" size="1"/></td></tr>
+ <tr><td class="small">Report generated at <xsl:value-of select="date:date-time()"/></td></tr>
+ </table>
+</xsl:template>
+
+<xsl:template match="package" mode="stats">
+ <tr>
+ <xsl:call-template name="alternate-row"/>
+ <td><xsl:value-of select="@name"/></td>
+ <xsl:call-template name="stats.formatted"/>
+ </tr>
+</xsl:template>
+
+<xsl:template match="class" mode="stats">
+ <tr>
+ <xsl:call-template name="alternate-row"/>
+ <td><a href="{@name}.html" target="classFrame"><xsl:value-of select="@name"/></a></td>
+ <xsl:call-template name="stats.formatted"/>
+ </tr>
+</xsl:template>
+
+<xsl:template name="stats.formatted">
+ <xsl:choose>
+ <xsl:when test="@statementcount=0">
+ <td>-</td>
+ </xsl:when>
+ <xsl:otherwise>
+ <td>
+ <xsl:value-of select="format-number(@statementscovered div @statementcount,'0.0%')"/>
+ </td>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="@methodcount=0">
+ <td>-</td>
+ </xsl:when>
+ <xsl:otherwise>
+ <td>
+ <xsl:value-of select="format-number(@methodscovered div @methodcount,'0.0%')"/>
+ </td>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="@totalcount=0">
+ <td>-</td>
+ <td>
+ <table cellspacing="0" cellpadding="0" border="0" width="100%" style="display: inline">
+ <tr>
+ <td class="empty" width="200" height="12">&#160;</td>
+ </tr>
+ </table>
+ </td>
+ </xsl:when>
+ <xsl:otherwise>
+ <td>
+ <xsl:value-of select="format-number(@totalcovered div @totalcount,'0.0%')"/>
+ </td>
+ <td>
+ <xsl:variable name="leftwidth"><xsl:value-of select="format-number((@totalcovered * 200) div @totalcount,'0')"/></xsl:variable>
+ <xsl:variable name="rightwidth"><xsl:value-of select="format-number(200 - (@totalcovered * 200) div @totalcount,'0')"/></xsl:variable>
+ <table cellspacing="0" cellpadding="0" border="0" width="100%" style="display: inline">
+ <tr>
+ <xsl:choose>
+ <xsl:when test="$leftwidth=200">
+ <td class="fullcover" width="200" height="12">&#160;</td>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="not($leftwidth=0)">
+ <td class="covered" width="{$leftwidth}" height="12">&#160;</td>
+ </xsl:if>
+ <xsl:if test="not($rightwidth=0)">
+ <td class="uncovered" width="{$rightwidth}" height="12">&#160;</td>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </tr>
+ </table>
+ </td>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template match="sourceline">
+ <tr>
+ <xsl:if test="@coveredcount>0">
+ <td class="lineCountHighlight"><xsl:value-of select="position()"/></td>
+ <td class="lineCountHighlight"><xsl:value-of select="@coveredcount"/></td>
+ </xsl:if>
+ <xsl:if test="@coveredcount&lt;0">
+ <td class="lineCountHighlight"><xsl:value-of select="position()"/></td>
+ <td class="coverageCountHighlight">0</td>
+ </xsl:if>
+ <xsl:if test="@coveredcount=0">
+ <td class="lineCount"><xsl:value-of select="position()"/></td>
+ <td class="coverageCount"></td>
+ </xsl:if>
+ <td>
+ <xsl:if test="@startclass=1">
+ <xsl:attribute name="class">srcLineClassStart</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@coveredcount>0">
+ <span class="srcLine">
+ <pre class="srcLine"><xsl:value-of select="."/></pre>
+ </span>
+ </xsl:if>
+ <xsl:if test="@coveredcount&lt;0">
+ <span class="srcLineHighlight">
+ <pre class="srcLine"><xsl:value-of select="."/></pre>
+ </span>
+ </xsl:if>
+ <xsl:if test="@coveredcount=0">
+ <pre class="srcLine"><xsl:value-of select="."/></pre>
+ </xsl:if>
+ </td>
+ </tr>
+</xsl:template>
+
+<!--
+ transform string like a.b.c to ../../../
+ @param path the path to transform into a descending directory path
+-->
+<xsl:template name="path">
+ <xsl:param name="path"/>
+ <xsl:if test="contains($path,'.')">
+ <xsl:text>../</xsl:text>
+ <xsl:call-template name="path">
+ <xsl:with-param name="path"><xsl:value-of select="substring-after($path,'.')"/></xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="not(contains($path,'.')) and not($path = '')">
+ <xsl:text>../</xsl:text>
+ </xsl:if>
+</xsl:template>
+
+
+<!-- create the link to the stylesheet based on the package name -->
+<xsl:template name="create.stylesheet.link">
+ <xsl:param name="package.name"/>
+ <LINK REL ="stylesheet" TYPE="text/css" TITLE="Style"><xsl:attribute name="href"><xsl:if test="not($package.name = 'unnamed package')"><xsl:call-template name="path"><xsl:with-param name="path" select="$package.name"/></xsl:call-template></xsl:if>stylesheet.css</xsl:attribute></LINK>
+</xsl:template>
+
+<!-- alternated row style -->
+<xsl:template name="alternate-row">
+<xsl:attribute name="class">
+ <xsl:if test="position() mod 2 = 1">a</xsl:if>
+ <xsl:if test="position() mod 2 = 0">b</xsl:if>
+</xsl:attribute>
+</xsl:template>
+
+</xsl:stylesheet>
+
+
diff --git a/buildscripts/phing/etc/log.xsl b/buildscripts/phing/etc/log.xsl
new file mode 100644
index 00000000..a460b667
--- /dev/null
+++ b/buildscripts/phing/etc/log.xsl
@@ -0,0 +1,216 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<xsl:output method="html" indent="yes" encoding="US-ASCII"/>
+<!--
+ Copyright 2000-2004 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<!--
+
+ The purpose have this XSL is to provide a nice way to look at the output
+ from the Ant XmlLogger (ie: ant -listener org.apache.tools.ant.XmlLogger )
+
+ @author <a href="mailto:michiel@trendserver.nl>Michiel Rook</a>
+ @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a>
+
+-->
+<xsl:decimal-format decimal-separator="." grouping-separator="," />
+
+<xsl:template match="/">
+<html>
+ <head>
+ <title>Phing Build Log</title>
+ <style type="text/css">
+ .bannercell {
+ border: 0px;
+ padding: 0px;
+ }
+ body {
+ margin: 0;
+ font:normal 100% arial,helvetica,sanserif;
+ background-color:#FFFFFF;
+ color:#000000;
+ }
+ table.status {
+ font:bold 80% arial,helvetica,sanserif;
+ background-color:#525D76;
+ color:#ffffff;
+ }
+ table.log tr td, tr th {
+ font-size: 80%;
+ }
+ .error {
+ color:red;
+ }
+ .warn {
+ color:brown;
+ }
+ .info {
+ color:gray;
+ }
+ .debug{
+ color:gray;
+ }
+ .failed {
+ font-size:80%;
+ background-color: red;
+ color:#FFFFFF;
+ font-weight: bold
+ }
+ .complete {
+ font-size:80%;
+ background-color: #525D76;
+ color:#FFFFFF;
+ font-weight: bold
+ }
+ .a td {
+ background: #efefef;
+ }
+ .b td {
+ background: #fff;
+ }
+ th, td {
+ text-align: left;
+ vertical-align: top;
+ }
+ th {
+ background: #ccc;
+ color: black;
+ }
+ table, th, td {
+ border: none
+ }
+ h3 {
+ font:bold 80% arial,helvetica,sanserif;
+ background: #525D76;
+ color: white;
+ text-decoration: none;
+ padding: 5px;
+ margin-right: 2px;
+ margin-left: 2px;
+ margin-bottom: 0;
+ }
+ a {
+ color: #003399;
+ }
+ a:hover {
+ color: #888888;
+ }
+ </style>
+ </head>
+ <body>
+ <!-- jakarta logo -->
+ <table border="0" cellpadding="0" cellspacing="0" width="100%">
+ <tr>
+ <td valign="top" class="bannercell">
+ <a href="http://phing.info/">
+ <img src="http://phing.info/images/phing.gif" alt="http://phing.info/" align="left" border="0"/>
+ </a>
+ </td>
+ <td style="text-align:right;vertical-align:bottom">
+ <a href="http://phing.info/">Phing</a>
+ </td>
+ </tr>
+ </table>
+
+ <table border="0" width="100%">
+ <tr><td><hr noshade="yes" size="1"/></td></tr>
+ </table>
+
+ <xsl:apply-templates select="build"/>
+
+ <!-- FOOTER -->
+ <table width="100%">
+ <tr><td><hr noshade="yes" size="1"/></td></tr>
+ <tr><td>
+ <div align="center"><font color="#525D76" size="-1"><em>
+ <a href="http://phing.info/">Phing</a>
+ </em></font></div>
+ </td></tr>
+ </table>
+ </body>
+</html>
+</xsl:template>
+
+<xsl:template match="build">
+ <!-- build status -->
+ <table width="100%">
+ <xsl:attribute name="class">
+ <xsl:if test="@error">failed</xsl:if>
+ <xsl:if test="not(@error)">complete</xsl:if>
+ </xsl:attribute>
+ <tr>
+ <xsl:if test="@error">
+ <td nowrap="yes">Build Failed</td>
+ </xsl:if>
+ <xsl:if test="not(@error)">
+ <td nowrap="yes">Build Complete</td>
+ </xsl:if>
+ <td style="text-align:right" nowrap="yes">Total Time: <xsl:value-of select="@time"/></td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <xsl:if test="@error">
+ <tt><xsl:value-of select="@error"/></tt><br/>
+ <i style="font-size:80%">See the <a href="#stacktrace" alt="Click for details">stacktrace</a>.</i>
+ </xsl:if>
+ </td>
+ </tr>
+ </table>
+ <table border="1" cellspacing="2" cellpadding="3" width="100%" style="font-size:80%">
+ <tr class="a"><td width="1">phing.file</td><td><xsl:value-of select="substring-after(//message[contains(text(),'phing.file')], '->')"/></td></tr>
+ <tr class="b"><td width="1">phing.version</td><td><xsl:value-of select="substring-after(//message[contains(text(),'phing.version')], '->')"/></td></tr>
+ </table>
+ <!-- build information -->
+ <h3>Build events</h3>
+ <table class="log" border="1" cellspacing="2" cellpadding="3" width="100%">
+ <tr>
+ <th nowrap="yes" align="left" width="1%">target</th>
+ <th nowrap="yes" align="left" width="1%">task</th>
+ <th nowrap="yes" align="left">message</th>
+ </tr>
+ <xsl:apply-templates select=".//message[@priority != 'debug']"/>
+ </table>
+ <p>
+ <!-- stacktrace -->
+ <xsl:if test="stacktrace">
+ <a name="stacktrace"/>
+ <h3>Error details</h3>
+ <table width="100%">
+ <tr><td>
+ <pre><xsl:value-of select="stacktrace"/></pre>
+ </td></tr>
+ </table>
+ </xsl:if>
+ </p>
+</xsl:template>
+
+<!-- report every message but those with debug priority -->
+<xsl:template match="message[@priority!='debug']">
+ <tr valign="top">
+ <!-- alternated row style -->
+ <xsl:attribute name="class">
+ <xsl:if test="position() mod 2 = 1">a</xsl:if>
+ <xsl:if test="position() mod 2 = 0">b</xsl:if>
+ </xsl:attribute>
+ <td nowrap="yes" width="1%"><xsl:value-of select="../../@name"/></td>
+ <td nowrap="yes" style="text-align:right" width="1%">[ <xsl:value-of select="../@name"/> ]</td>
+ <td class="{@priority}" nowrap="yes">
+ <xsl:value-of select="text()"/>
+ </td>
+ </tr>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/buildscripts/phing/etc/phpunit2-frames.xsl b/buildscripts/phing/etc/phpunit2-frames.xsl
new file mode 100644
index 00000000..7ccc4f33
--- /dev/null
+++ b/buildscripts/phing/etc/phpunit2-frames.xsl
@@ -0,0 +1,677 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
+ xmlns:exsl="http://exslt.org/common"
+ xmlns:str="http://exslt.org/strings"
+ xmlns:date="http://exslt.org/dates-and-times"
+ extension-element-prefixes="exsl str date">
+<xsl:include href="str.replace.function.xsl"/>
+<xsl:output method="html" indent="yes" encoding="US-ASCII"/>
+<xsl:decimal-format decimal-separator="." grouping-separator=","/>
+<!--
+ Copyright 2001-2004 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<!--
+
+ Sample stylesheet to be used with Phing/PHPUnit2 output.
+ Based on JUnit stylesheets from Apache Ant.
+
+ It creates a set of HTML files a la javadoc where you can browse easily
+ through all packages and classes.
+
+ @author Michiel Rook <a href="mailto:michiel@trendserver.nl"/>
+ @author Stephane Bailliez <a href="mailto:sbailliez@apache.org"/>
+ @author Erik Hatcher <a href="mailto:ehatcher@apache.org"/>
+ @author Martijn Kruithof <a href="mailto:martijn@kruithof.xs4all.nl"/>
+
+-->
+<xsl:param name="output.dir" select="'.'"/>
+
+
+<xsl:template match="testsuites">
+ <!-- create the index.html -->
+ <exsl:document href="efile://{$output.dir}/index.html">
+ <xsl:call-template name="index.html"/>
+ </exsl:document>
+
+ <!-- create the stylesheet.css -->
+ <exsl:document href="efile://{$output.dir}/stylesheet.css">
+ <xsl:call-template name="stylesheet.css"/>
+ </exsl:document>
+
+ <!-- create the overview-packages.html at the root -->
+ <exsl:document href="efile://{$output.dir}/overview-summary.html">
+ <xsl:apply-templates select="." mode="overview.packages"/>
+ </exsl:document>
+
+ <!-- create the all-packages.html at the root -->
+ <exsl:document href="efile://{$output.dir}/overview-frame.html">
+ <xsl:apply-templates select="." mode="all.packages"/>
+ </exsl:document>
+
+ <!-- create the all-classes.html at the root -->
+ <exsl:document href="efile://{$output.dir}/allclasses-frame.html">
+ <xsl:apply-templates select="." mode="all.classes"/>
+ </exsl:document>
+
+ <!-- process all packages -->
+ <xsl:for-each select="./testsuite[not(./@package = preceding-sibling::testsuite/@package)]">
+ <xsl:call-template name="package">
+ <xsl:with-param name="name" select="@package"/>
+ </xsl:call-template>
+ </xsl:for-each>
+</xsl:template>
+
+
+<xsl:template name="package">
+ <xsl:param name="name"/>
+ <xsl:variable name="package.dir">
+ <xsl:if test="not($name = '')"><xsl:value-of select="translate($name,'.','/')"/></xsl:if>
+ <xsl:if test="$name = ''">.</xsl:if>
+ </xsl:variable>
+ <!--Processing package <xsl:value-of select="@name"/> in <xsl:value-of select="$output.dir"/> -->
+ <!-- create a classes-list.html in the package directory -->
+ <exsl:document href="efile://{$output.dir}/{$package.dir}/package-frame.html">
+ <xsl:call-template name="classes.list">
+ <xsl:with-param name="name" select="$name"/>
+ </xsl:call-template>
+ </exsl:document>
+
+ <!-- create a package-summary.html in the package directory -->
+ <exsl:document href="efile://{$output.dir}/{$package.dir}/package-summary.html">
+ <xsl:call-template name="package.summary">
+ <xsl:with-param name="name" select="$name"/>
+ </xsl:call-template>
+ </exsl:document>
+
+ <!-- for each class, creates a @name.html -->
+ <!-- @bug there will be a problem with inner classes having the same name, it will be overwritten -->
+ <xsl:for-each select="/testsuites/testsuite[@package = $name]">
+ <exsl:document href="efile://{$output.dir}/{$package.dir}/{@name}.html">
+ <xsl:apply-templates select="." mode="class.details"/>
+ </exsl:document>
+ <xsl:if test="string-length(./system-out)!=0">
+ <exsl:document href="efile://{$output.dir}/{$package.dir}/{@name}-out.txt">
+ <xsl:value-of select="./system-out" />
+ </exsl:document>
+ </xsl:if>
+ <xsl:if test="string-length(./system-err)!=0">
+ <exsl:document href="efile://{$output.dir}/{$package.dir}/{@name}-err.txt">
+ <xsl:value-of select="./system-err" />
+ </exsl:document>
+ </xsl:if>
+ </xsl:for-each>
+</xsl:template>
+
+<xsl:template name="index.html">
+<html>
+ <head>
+ <title>Unit Test Results.</title>
+ </head>
+ <frameset cols="20%,80%">
+ <frameset rows="30%,70%">
+ <frame src="overview-frame.html" name="packageListFrame"/>
+ <frame src="allclasses-frame.html" name="classListFrame"/>
+ </frameset>
+ <frame src="overview-summary.html" name="classFrame"/>
+ <noframes>
+ <h2>Frame Alert</h2>
+ <p>
+ This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client.
+ </p>
+ </noframes>
+ </frameset>
+</html>
+</xsl:template>
+
+<!-- this is the stylesheet css to use for nearly everything -->
+<xsl:template name="stylesheet.css">
+body {
+ font-family: verdana,arial,helvetica;
+ color:#000000;
+ font-size: 12px;
+}
+table tr td, table tr th {
+ font-family: verdana,arial,helvetica;
+ font-size: 12px;
+}
+table.details tr th{
+ font-family: verdana,arial,helvetica;
+ font-weight: bold;
+ text-align:left;
+ background:#a6caf0;
+}
+table.details tr td{
+ background:#eeeee0;
+}
+
+p {
+ line-height:1.5em;
+ margin-top:0.5em; margin-bottom:1.0em;
+ font-size: 12px;
+}
+h1 {
+ margin: 0px 0px 5px;
+ font-family: verdana,arial,helvetica;
+}
+h2 {
+ margin-top: 1em; margin-bottom: 0.5em;
+ font-family: verdana,arial,helvetica;
+}
+h3 {
+ margin-bottom: 0.5em;
+ font-family: verdana,arial,helvetica;
+}
+h4 {
+ margin-bottom: 0.5em;
+ font-family: verdana,arial,helvetica;
+}
+h5 {
+ margin-bottom: 0.5em;
+ font-family: verdana,arial,helvetica;
+}
+h6 {
+ margin-bottom: 0.5em;
+ font-family: verdana,arial,helvetica;
+}
+.Error {
+ font-weight:bold; color:red;
+}
+.Failure {
+ font-weight:bold; color:purple;
+}
+.small {
+ font-size: 9px;
+}
+a {
+ color: #003399;
+}
+a:hover {
+ color: #888888;
+}
+</xsl:template>
+
+
+<!-- ======================================================================
+ This page is created for every testsuite class.
+ It prints a summary of the testsuite and detailed information about
+ testcase methods.
+ ====================================================================== -->
+<xsl:template match="testsuite" mode="class.details">
+ <xsl:variable name="package.name" select="@package"/>
+ <xsl:variable name="class.name"><xsl:if test="not($package.name = '')"><xsl:value-of select="$package.name"/>.</xsl:if><xsl:value-of select="@name"/></xsl:variable>
+ <html>
+ <head>
+ <title>Unit Test Results: <xsl:value-of select="$class.name"/></title>
+ <xsl:call-template name="create.stylesheet.link">
+ <xsl:with-param name="package.name" select="$package.name"/>
+ </xsl:call-template>
+ </head>
+ <body>
+ <xsl:call-template name="pageHeader"/>
+ <h3>Class <xsl:value-of select="$class.name"/></h3>
+
+
+ <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
+ <xsl:call-template name="testsuite.test.header"/>
+ <xsl:apply-templates select="." mode="print.test"/>
+ </table>
+
+ <h2>Tests</h2>
+ <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
+ <xsl:call-template name="testcase.test.header"/>
+ <!--
+ test can even not be started at all (failure to load the class)
+ so report the error directly
+ -->
+ <xsl:if test="./error">
+ <tr class="Error">
+ <td colspan="4"><xsl:apply-templates select="./error"/></td>
+ </tr>
+ </xsl:if>
+ <xsl:apply-templates select="./testcase" mode="print.test"/>
+ </table>
+ <xsl:call-template name="pageFooter"/>
+ </body>
+ </html>
+</xsl:template>
+
+<!-- ======================================================================
+ This page is created for every package.
+ It prints the name of all classes that belongs to this package.
+ @param name the package name to print classes.
+ ====================================================================== -->
+<!-- list of classes in a package -->
+<xsl:template name="classes.list">
+ <xsl:param name="name"/>
+ <html>
+ <head>
+ <title>Unit Test Classes: <xsl:value-of select="$name"/></title>
+ <xsl:call-template name="create.stylesheet.link">
+ <xsl:with-param name="package.name" select="$name"/>
+ </xsl:call-template>
+ </head>
+ <body>
+ <table width="100%">
+ <tr>
+ <td nowrap="nowrap">
+ <h2><a href="package-summary.html" target="classFrame">
+ <xsl:value-of select="$name"/>
+ <xsl:if test="$name = ''">&lt;none&gt;</xsl:if>
+ </a></h2>
+ </td>
+ </tr>
+ </table>
+
+ <h2>Classes</h2>
+ <table width="100%">
+ <xsl:for-each select="/testsuites/testsuite[./@package = $name]">
+ <xsl:sort select="@name"/>
+ <tr>
+ <td nowrap="nowrap">
+ <a href="{@name}.html" target="classFrame"><xsl:value-of select="@name"/></a>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </body>
+ </html>
+</xsl:template>
+
+
+<!--
+ Creates an all-classes.html file that contains a link to all package-summary.html
+ on each class.
+-->
+<xsl:template match="testsuites" mode="all.classes">
+ <html>
+ <head>
+ <title>All Unit Test Classes</title>
+ <xsl:call-template name="create.stylesheet.link">
+ <xsl:with-param name="package.name"/>
+ </xsl:call-template>
+ </head>
+ <body>
+ <h2>Classes</h2>
+ <table width="100%">
+ <xsl:apply-templates select="testsuite" mode="all.classes">
+ <xsl:sort select="@name"/>
+ </xsl:apply-templates>
+ </table>
+ </body>
+ </html>
+</xsl:template>
+
+<xsl:template match="testsuite" mode="all.classes">
+ <xsl:variable name="package.name" select="@package"/>
+ <tr>
+ <td nowrap="nowrap">
+ <a target="classFrame">
+ <xsl:attribute name="href">
+ <xsl:if test="not($package.name='')">
+ <xsl:value-of select="translate($package.name,'.','/')"/><xsl:text>/</xsl:text>
+ </xsl:if><xsl:value-of select="@name"/><xsl:text>.html</xsl:text>
+ </xsl:attribute>
+ <xsl:value-of select="@name"/>
+ </a>
+ </td>
+ </tr>
+</xsl:template>
+
+
+<!--
+ Creates an html file that contains a link to all package-summary.html files on
+ each package existing on testsuites.
+ @bug there will be a problem here, I don't know yet how to handle unnamed package :(
+-->
+<xsl:template match="testsuites" mode="all.packages">
+ <html>
+ <head>
+ <title>All Unit Test Packages</title>
+ <xsl:call-template name="create.stylesheet.link">
+ <xsl:with-param name="package.name"/>
+ </xsl:call-template>
+ </head>
+ <body>
+ <h2><a href="overview-summary.html" target="classFrame">Home</a></h2>
+ <h2>Packages</h2>
+ <table width="100%">
+ <xsl:apply-templates select="testsuite[not(./@package = preceding-sibling::testsuite/@package)]" mode="all.packages">
+ <xsl:sort select="@package"/>
+ </xsl:apply-templates>
+ </table>
+ </body>
+ </html>
+</xsl:template>
+
+<xsl:template match="testsuite" mode="all.packages">
+ <tr>
+ <td nowrap="nowrap">
+ <a href="./{translate(@package,'.','/')}/package-summary.html" target="classFrame">
+ <xsl:value-of select="@package"/>
+ <xsl:if test="@package = ''">&lt;none&gt;</xsl:if>
+ </a>
+ </td>
+ </tr>
+</xsl:template>
+
+
+<xsl:template match="testsuites" mode="overview.packages">
+ <html>
+ <head>
+ <title>Unit Test Results: Summary</title>
+ <xsl:call-template name="create.stylesheet.link">
+ <xsl:with-param name="package.name"/>
+ </xsl:call-template>
+ </head>
+ <body>
+ <xsl:attribute name="onload">open('allclasses-frame.html','classListFrame')</xsl:attribute>
+ <xsl:call-template name="pageHeader"/>
+ <h2>Summary</h2>
+ <xsl:variable name="testCount" select="sum(testsuite/@tests)"/>
+ <xsl:variable name="errorCount" select="sum(testsuite/@errors)"/>
+ <xsl:variable name="failureCount" select="sum(testsuite/@failures)"/>
+ <xsl:variable name="timeCount" select="sum(testsuite/@time)"/>
+ <xsl:variable name="successRate" select="($testCount - $failureCount - $errorCount) div $testCount"/>
+ <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
+ <tr valign="top">
+ <th>Tests</th>
+ <th>Failures</th>
+ <th>Errors</th>
+ <th>Success rate</th>
+ <th>Time</th>
+ </tr>
+ <tr valign="top">
+ <xsl:attribute name="class">
+ <xsl:choose>
+ <xsl:when test="$errorCount &gt; 0">Error</xsl:when>
+ <xsl:when test="$failureCount &gt; 0">Failure</xsl:when>
+ <xsl:otherwise>Pass</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <td><xsl:value-of select="$testCount"/></td>
+ <td><xsl:value-of select="$failureCount"/></td>
+ <td><xsl:value-of select="$errorCount"/></td>
+ <td>
+ <xsl:call-template name="display-percent">
+ <xsl:with-param name="value" select="$successRate"/>
+ </xsl:call-template>
+ </td>
+ <td>
+ <xsl:call-template name="display-time">
+ <xsl:with-param name="value" select="$timeCount"/>
+ </xsl:call-template>
+ </td>
+
+ </tr>
+ </table>
+ <table border="0" width="95%">
+ <tr>
+ <td style="text-align: justify;">
+ Note: <em>failures</em> are anticipated and checked for with assertions while <em>errors</em> are unanticipated.
+ </td>
+ </tr>
+ </table>
+
+ <h2>Packages</h2>
+ <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
+ <xsl:call-template name="testsuite.test.header"/>
+ <xsl:for-each select="testsuite[not(./@package = preceding-sibling::testsuite/@package)]">
+ <xsl:sort select="@package" order="ascending"/>
+ <!-- get the node set containing all testsuites that have the same package -->
+ <xsl:variable name="insamepackage" select="/testsuites/testsuite[./@package = current()/@package]"/>
+ <tr valign="top">
+ <!-- display a failure if there is any failure/error in the package -->
+ <xsl:attribute name="class">
+ <xsl:choose>
+ <xsl:when test="sum($insamepackage/@errors) &gt; 0">Error</xsl:when>
+ <xsl:when test="sum($insamepackage/@failures) &gt; 0">Failure</xsl:when>
+ <xsl:otherwise>Pass</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <td><a href="./{translate(@package,'.','/')}/package-summary.html">
+ <xsl:value-of select="@package"/>
+ <xsl:if test="@package = ''">&lt;none&gt;</xsl:if>
+ </a></td>
+ <td><xsl:value-of select="sum($insamepackage/@tests)"/></td>
+ <td><xsl:value-of select="sum($insamepackage/@errors)"/></td>
+ <td><xsl:value-of select="sum($insamepackage/@failures)"/></td>
+ <td>
+ <xsl:call-template name="display-time">
+ <xsl:with-param name="value" select="sum($insamepackage/@time)"/>
+ </xsl:call-template>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <xsl:call-template name="pageFooter"/>
+ </body>
+ </html>
+</xsl:template>
+
+
+<xsl:template name="package.summary">
+ <xsl:param name="name"/>
+ <html>
+ <head>
+ <xsl:call-template name="create.stylesheet.link">
+ <xsl:with-param name="package.name" select="$name"/>
+ </xsl:call-template>
+ </head>
+ <body>
+ <xsl:attribute name="onload">open('package-frame.html','classListFrame')</xsl:attribute>
+ <xsl:call-template name="pageHeader"/>
+ <h3>Package <xsl:value-of select="$name"/></h3>
+
+ <!--table border="0" cellpadding="5" cellspacing="2" width="95%">
+ <xsl:call-template name="class.metrics.header"/>
+ <xsl:apply-templates select="." mode="print.metrics"/>
+ </table-->
+
+ <xsl:variable name="insamepackage" select="/testsuites/testsuite[./@package = $name]"/>
+ <xsl:if test="count($insamepackage) &gt; 0">
+ <h2>Classes</h2>
+ <p>
+ <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
+ <xsl:call-template name="testsuite.test.header"/>
+ <xsl:apply-templates select="$insamepackage" mode="print.test">
+ <xsl:sort select="@name"/>
+ </xsl:apply-templates>
+ </table>
+ </p>
+ </xsl:if>
+ <xsl:call-template name="pageFooter"/>
+ </body>
+ </html>
+</xsl:template>
+
+
+<!--
+ transform string like a.b.c to ../../../
+ @param path the path to transform into a descending directory path
+-->
+<xsl:template name="path">
+ <xsl:param name="path"/>
+ <xsl:if test="contains($path,'.')">
+ <xsl:text>../</xsl:text>
+ <xsl:call-template name="path">
+ <xsl:with-param name="path"><xsl:value-of select="substring-after($path,'.')"/></xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="not(contains($path,'.')) and not($path = '')">
+ <xsl:text>../</xsl:text>
+ </xsl:if>
+</xsl:template>
+
+
+<!-- create the link to the stylesheet based on the package name -->
+<xsl:template name="create.stylesheet.link">
+ <xsl:param name="package.name"/>
+ <link rel="stylesheet" type="text/css" title="Style"><xsl:attribute name="href"><xsl:if test="not($package.name = 'unnamed package')"><xsl:call-template name="path"><xsl:with-param name="path" select="$package.name"/></xsl:call-template></xsl:if>stylesheet.css</xsl:attribute></link>
+</xsl:template>
+
+
+<!-- Page HEADER -->
+<xsl:template name="pageHeader">
+ <h1>Unit Test Results</h1>
+ <table width="100%">
+ <tr>
+ <td align="left"></td>
+ <td align="right">Designed for use with <a href='http://pear.php.net/package/PHPUnit2'>PHPUnit2</a> and <a href='http://phing.info/'>Phing</a>.</td>
+ </tr>
+ </table>
+ <hr size="1"/>
+</xsl:template>
+
+<!-- Page Footer -->
+<xsl:template name="pageFooter">
+ <table width="100%">
+ <tr><td><hr noshade="yes" size="1"/></td></tr>
+ <tr><td class="small">Report generated at <xsl:value-of select="date:date-time()"/></td></tr>
+ </table>
+</xsl:template>
+
+<!-- class header -->
+<xsl:template name="testsuite.test.header">
+ <tr valign="top">
+ <th width="80%">Name</th>
+ <th>Tests</th>
+ <th>Errors</th>
+ <th>Failures</th>
+ <th nowrap="nowrap">Time(s)</th>
+ </tr>
+</xsl:template>
+
+<!-- method header -->
+<xsl:template name="testcase.test.header">
+ <tr valign="top">
+ <th>Name</th>
+ <th>Status</th>
+ <th width="80%">Type</th>
+ <th nowrap="nowrap">Time(s)</th>
+ </tr>
+</xsl:template>
+
+
+<!-- class information -->
+<xsl:template match="testsuite" mode="print.test">
+ <tr valign="top">
+ <xsl:attribute name="class">
+ <xsl:choose>
+ <xsl:when test="@errors[.&gt; 0]">Error</xsl:when>
+ <xsl:when test="@failures[.&gt; 0]">Failure</xsl:when>
+ <xsl:otherwise>Pass</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <td><a href="{@name}.html"><xsl:value-of select="@name"/></a></td>
+ <td><xsl:apply-templates select="@tests"/></td>
+ <td><xsl:apply-templates select="@errors"/></td>
+ <td><xsl:apply-templates select="@failures"/></td>
+ <td><xsl:call-template name="display-time">
+ <xsl:with-param name="value" select="@time"/>
+ </xsl:call-template>
+ </td>
+ </tr>
+</xsl:template>
+
+<xsl:template match="testcase" mode="print.test">
+ <tr valign="top">
+ <xsl:attribute name="class">
+ <xsl:choose>
+ <xsl:when test="error">Error</xsl:when>
+ <xsl:when test="failure">Failure</xsl:when>
+ <xsl:otherwise>TableRowColor</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <td><xsl:value-of select="@name"/></td>
+ <xsl:choose>
+ <xsl:when test="failure">
+ <td>Failure</td>
+ <td><xsl:apply-templates select="failure"/></td>
+ </xsl:when>
+ <xsl:when test="error">
+ <td>Error</td>
+ <td><xsl:apply-templates select="error"/></td>
+ </xsl:when>
+ <xsl:otherwise>
+ <td>Success</td>
+ <td></td>
+ </xsl:otherwise>
+ </xsl:choose>
+ <td>
+ <xsl:call-template name="display-time">
+ <xsl:with-param name="value" select="@time"/>
+ </xsl:call-template>
+ </td>
+ </tr>
+</xsl:template>
+
+
+<!-- Note : the below template error and failure are the same style
+ so just call the same style store in the toolkit template -->
+<xsl:template match="failure">
+ <xsl:call-template name="display-failures"/>
+</xsl:template>
+
+<xsl:template match="error">
+ <xsl:call-template name="display-failures"/>
+</xsl:template>
+
+<!-- Style for the error and failure in the testcase template -->
+<xsl:template name="display-failures">
+ <xsl:choose>
+ <xsl:when test="not(@message)">N/A</xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@message"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!-- display the stacktrace -->
+ <br/><br/>
+ <code>
+ <xsl:call-template name="br-replace">
+ <xsl:with-param name="word" select="."/>
+ </xsl:call-template>
+ </code>
+</xsl:template>
+
+<!--
+ template that will convert a carriage return into a br tag
+ @param word the text from which to convert CR to BR tag
+-->
+<xsl:template name="br-replace">
+ <xsl:choose>
+ <xsl:when test="contains($word,'&#x0A;')">
+ <xsl:value-of select="substring-before($word,'&#x0A;')"/>
+ <br />
+ <xsl:call-template name="br-replace">
+ <xsl:with-param name="word" select="substring-after($word,'&#x0A;')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$word"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template name="display-time">
+ <xsl:param name="value"/>
+ <xsl:value-of select="format-number($value,'0.000')"/>
+</xsl:template>
+
+<xsl:template name="display-percent">
+ <xsl:param name="value"/>
+ <xsl:value-of select="format-number($value,'0.00%')"/>
+</xsl:template>
+</xsl:stylesheet>
+
diff --git a/buildscripts/phing/etc/phpunit2-noframes.xsl b/buildscripts/phing/etc/phpunit2-noframes.xsl
new file mode 100644
index 00000000..d2c772da
--- /dev/null
+++ b/buildscripts/phing/etc/phpunit2-noframes.xsl
@@ -0,0 +1,436 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
+ xmlns:exsl="http://exslt.org/common"
+ xmlns:str="http://exslt.org/strings"
+ xmlns:date="http://exslt.org/dates-and-times"
+ extension-element-prefixes="exsl str date">
+<xsl:include href="str.replace.function.xsl"/>
+<xsl:output method="html" indent="yes" encoding="US-ASCII"
+ doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN" />
+<xsl:decimal-format decimal-separator="." grouping-separator="," />
+<!--
+ Copyright 2001-2004 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<!--
+
+ Sample stylesheet to be used with Phing/PHPUnit2 output.
+ Based on JUnit stylesheets from Apache Ant.
+
+ It creates a non-framed report that can be useful to send via
+ e-mail or such.
+
+ @author Michiel Rook <a href="mailto:michiel@trendserver.nl"/>
+ @author Stephane Bailliez <a href="mailto:sbailliez@apache.org"/>
+ @author Erik Hatcher <a href="mailto:ehatcher@apache.org"/>
+
+-->
+<xsl:template match="testsuites">
+ <html>
+ <head>
+ <title>Unit Test Results</title>
+ <style type="text/css">
+ body {
+ font-family: verdana,arial,helvetica;
+ color:#000000;
+ font-size: 12px;
+ }
+ table tr td, table tr th {
+ font-family: verdana,arial,helvetica;
+ font-size: 12px;
+ }
+ table.details tr th{
+ font-family: verdana,arial,helvetica;
+ font-weight: bold;
+ text-align:left;
+ background:#a6caf0;
+ }
+ table.details tr td{
+ background:#eeeee0;
+ }
+
+ p {
+ line-height:1.5em;
+ margin-top:0.5em; margin-bottom:1.0em;
+ font-size: 12px;
+ }
+ h1 {
+ margin: 0px 0px 5px;
+ font-family: verdana,arial,helvetica;
+ }
+ h2 {
+ margin-top: 1em; margin-bottom: 0.5em;
+ font-family: verdana,arial,helvetica;
+ }
+ h3 {
+ margin-bottom: 0.5em;
+ font-family: verdana,arial,helvetica;
+ }
+ h4 {
+ margin-bottom: 0.5em;
+ font-family: verdana,arial,helvetica;
+ }
+ h5 {
+ margin-bottom: 0.5em;
+ font-family: verdana,arial,helvetica;
+ }
+ h6 {
+ margin-bottom: 0.5em;
+ font-family: verdana,arial,helvetica;
+ }
+ .Error {
+ font-weight:bold; color:red;
+ }
+ .Failure {
+ font-weight:bold; color:purple;
+ }
+ .small {
+ font-size: 9px;
+ }
+ a {
+ color: #003399;
+ }
+ a:hover {
+ color: #888888;
+ }
+ </style>
+ </head>
+ <body>
+ <a name="top"></a>
+ <xsl:call-template name="pageHeader"/>
+
+ <!-- Summary part -->
+ <xsl:call-template name="summary"/>
+ <hr size="1" width="95%" align="left"/>
+
+ <!-- Package List part -->
+ <xsl:call-template name="packagelist"/>
+ <hr size="1" width="95%" align="left"/>
+
+ <!-- For each package create its part -->
+ <xsl:call-template name="packages"/>
+ <hr size="1" width="95%" align="left"/>
+
+ <!-- For each class create the part -->
+ <xsl:call-template name="classes"/>
+
+ <xsl:call-template name="pageFooter"/>
+ </body>
+ </html>
+</xsl:template>
+
+
+
+ <!-- ================================================================== -->
+ <!-- Write a list of all packages with an hyperlink to the anchor of -->
+ <!-- of the package name. -->
+ <!-- ================================================================== -->
+ <xsl:template name="packagelist">
+ <h2>Packages</h2>
+ Note: package statistics are not computed recursively, they only sum up all of its testsuites numbers.
+ <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
+ <xsl:call-template name="testsuite.test.header"/>
+ <!-- list all packages recursively -->
+ <xsl:for-each select="./testsuite[not(./@package = preceding-sibling::testsuite/@package)]">
+ <xsl:sort select="@package"/>
+ <xsl:variable name="testsuites-in-package" select="/testsuites/testsuite[./@package = current()/@package]"/>
+ <xsl:variable name="testCount" select="sum($testsuites-in-package/@tests)"/>
+ <xsl:variable name="errorCount" select="sum($testsuites-in-package/@errors)"/>
+ <xsl:variable name="failureCount" select="sum($testsuites-in-package/@failures)"/>
+ <xsl:variable name="timeCount" select="sum($testsuites-in-package/@time)"/>
+
+ <!-- write a summary for the package -->
+ <tr valign="top">
+ <!-- set a nice color depending if there is an error/failure -->
+ <xsl:attribute name="class">
+ <xsl:choose>
+ <xsl:when test="$failureCount &gt; 0">Failure</xsl:when>
+ <xsl:when test="$errorCount &gt; 0">Error</xsl:when>
+ </xsl:choose>
+ </xsl:attribute>
+ <td><a href="#{@package}"><xsl:value-of select="@package"/></a></td>
+ <td><xsl:value-of select="$testCount"/></td>
+ <td><xsl:value-of select="$errorCount"/></td>
+ <td><xsl:value-of select="$failureCount"/></td>
+ <td>
+ <xsl:call-template name="display-time">
+ <xsl:with-param name="value" select="$timeCount"/>
+ </xsl:call-template>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </xsl:template>
+
+
+ <!-- ================================================================== -->
+ <!-- Write a package level report -->
+ <!-- It creates a table with values from the document: -->
+ <!-- Name | Tests | Errors | Failures | Time -->
+ <!-- ================================================================== -->
+ <xsl:template name="packages">
+ <!-- create an anchor to this package name -->
+ <xsl:for-each select="/testsuites/testsuite[not(./@package = preceding-sibling::testsuite/@package)]">
+ <xsl:sort select="@package"/>
+ <a name="{@package}"></a>
+ <h3>Package <xsl:value-of select="@package"/></h3>
+
+ <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
+ <xsl:call-template name="testsuite.test.header"/>
+
+ <!-- match the testsuites of this package -->
+ <xsl:apply-templates select="/testsuites/testsuite[./@package = current()/@package]" mode="print.test"/>
+ </table>
+ <a href="#top">Back to top</a>
+ <p/>
+ <p/>
+ </xsl:for-each>
+ </xsl:template>
+
+ <xsl:template name="classes">
+ <xsl:for-each select="testsuite">
+ <xsl:sort select="@name"/>
+ <!-- create an anchor to this class name -->
+ <a name="{@name}"></a>
+ <h3>TestCase <xsl:value-of select="@name"/></h3>
+
+ <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
+ <xsl:call-template name="testcase.test.header"/>
+ <!--
+ test can even not be started at all (failure to load the class)
+ so report the error directly
+ -->
+ <xsl:if test="./error">
+ <tr class="Error">
+ <td colspan="4"><xsl:apply-templates select="./error"/></td>
+ </tr>
+ </xsl:if>
+ <xsl:apply-templates select="./testcase" mode="print.test"/>
+ </table>
+ <p/>
+
+ <a href="#top">Back to top</a>
+ </xsl:for-each>
+ </xsl:template>
+
+ <xsl:template name="summary">
+ <h2>Summary</h2>
+ <xsl:variable name="testCount" select="sum(testsuite/@tests)"/>
+ <xsl:variable name="errorCount" select="sum(testsuite/@errors)"/>
+ <xsl:variable name="failureCount" select="sum(testsuite/@failures)"/>
+ <xsl:variable name="timeCount" select="sum(testsuite/@time)"/>
+ <xsl:variable name="successRate" select="($testCount - $failureCount - $errorCount) div $testCount"/>
+ <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
+ <tr valign="top">
+ <th>Tests</th>
+ <th>Failures</th>
+ <th>Errors</th>
+ <th>Success rate</th>
+ <th>Time</th>
+ </tr>
+ <tr valign="top">
+ <xsl:attribute name="class">
+ <xsl:choose>
+ <xsl:when test="$failureCount &gt; 0">Failure</xsl:when>
+ <xsl:when test="$errorCount &gt; 0">Error</xsl:when>
+ </xsl:choose>
+ </xsl:attribute>
+ <td><xsl:value-of select="$testCount"/></td>
+ <td><xsl:value-of select="$failureCount"/></td>
+ <td><xsl:value-of select="$errorCount"/></td>
+ <td>
+ <xsl:call-template name="display-percent">
+ <xsl:with-param name="value" select="$successRate"/>
+ </xsl:call-template>
+ </td>
+ <td>
+ <xsl:call-template name="display-time">
+ <xsl:with-param name="value" select="$timeCount"/>
+ </xsl:call-template>
+ </td>
+
+ </tr>
+ </table>
+ <table border="0" width="95%">
+ <tr>
+ <td style="text-align: justify;">
+ Note: <i>failures</i> are anticipated and checked for with assertions while <i>errors</i> are unanticipated.
+ </td>
+ </tr>
+ </table>
+ </xsl:template>
+
+<!-- Page HEADER -->
+<xsl:template name="pageHeader">
+ <h1>Unit Test Results</h1>
+ <table width="100%">
+ <tr>
+ <td align="left"></td>
+ <td align="right">Designed for use with <a href='http://pear.php.net/package/PHPUnit2'>PHPUnit2</a> and <a href='http://phing.info/'>Phing</a>.</td>
+ </tr>
+ </table>
+ <hr size="1"/>
+</xsl:template>
+
+<!-- Page Footer -->
+<xsl:template name="pageFooter">
+ <table width="100%">
+ <tr><td><hr noshade="yes" size="1"/></td></tr>
+ <tr><td class="small">Report generated at <xsl:value-of select="date:date-time()"/></td></tr>
+ </table>
+</xsl:template>
+
+<xsl:template match="testsuite" mode="header">
+ <tr valign="top">
+ <th width="80%">Name</th>
+ <th>Tests</th>
+ <th>Errors</th>
+ <th>Failures</th>
+ <th nowrap="nowrap">Time(s)</th>
+ </tr>
+</xsl:template>
+
+<!-- class header -->
+<xsl:template name="testsuite.test.header">
+ <tr valign="top">
+ <th width="80%">Name</th>
+ <th>Tests</th>
+ <th>Errors</th>
+ <th>Failures</th>
+ <th nowrap="nowrap">Time(s)</th>
+ </tr>
+</xsl:template>
+
+<!-- method header -->
+<xsl:template name="testcase.test.header">
+ <tr valign="top">
+ <th>Name</th>
+ <th>Status</th>
+ <th width="80%">Type</th>
+ <th nowrap="nowrap">Time(s)</th>
+ </tr>
+</xsl:template>
+
+
+<!-- class information -->
+<xsl:template match="testsuite" mode="print.test">
+ <tr valign="top">
+ <!-- set a nice color depending if there is an error/failure -->
+ <xsl:attribute name="class">
+ <xsl:choose>
+ <xsl:when test="@failures[.&gt; 0]">Failure</xsl:when>
+ <xsl:when test="@errors[.&gt; 0]">Error</xsl:when>
+ </xsl:choose>
+ </xsl:attribute>
+
+ <!-- print testsuite information -->
+ <td><a href="#{@name}"><xsl:value-of select="@name"/></a></td>
+ <td><xsl:value-of select="@tests"/></td>
+ <td><xsl:value-of select="@errors"/></td>
+ <td><xsl:value-of select="@failures"/></td>
+ <td>
+ <xsl:call-template name="display-time">
+ <xsl:with-param name="value" select="@time"/>
+ </xsl:call-template>
+ </td>
+ </tr>
+</xsl:template>
+
+<xsl:template match="testcase" mode="print.test">
+ <tr valign="top">
+ <xsl:attribute name="class">
+ <xsl:choose>
+ <xsl:when test="failure | error">Error</xsl:when>
+ </xsl:choose>
+ </xsl:attribute>
+ <td><xsl:value-of select="@name"/></td>
+ <xsl:choose>
+ <xsl:when test="failure">
+ <td>Failure</td>
+ <td><xsl:apply-templates select="failure"/></td>
+ </xsl:when>
+ <xsl:when test="error">
+ <td>Error</td>
+ <td><xsl:apply-templates select="error"/></td>
+ </xsl:when>
+ <xsl:otherwise>
+ <td>Success</td>
+ <td></td>
+ </xsl:otherwise>
+ </xsl:choose>
+ <td>
+ <xsl:call-template name="display-time">
+ <xsl:with-param name="value" select="@time"/>
+ </xsl:call-template>
+ </td>
+ </tr>
+</xsl:template>
+
+
+<xsl:template match="failure">
+ <xsl:call-template name="display-failures"/>
+</xsl:template>
+
+<xsl:template match="error">
+ <xsl:call-template name="display-failures"/>
+</xsl:template>
+
+<!-- Style for the error and failure in the tescase template -->
+<xsl:template name="display-failures">
+ <xsl:choose>
+ <xsl:when test="not(@message)">N/A</xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@message"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!-- display the stacktrace -->
+ <code>
+ <br/><br/>
+ <xsl:call-template name="br-replace">
+ <xsl:with-param name="word" select="."/>
+ </xsl:call-template>
+ </code>
+</xsl:template>
+
+<!--
+ template that will convert a carriage return into a br tag
+ @param word the text from which to convert CR to BR tag
+-->
+<xsl:template name="br-replace">
+ <xsl:choose>
+ <xsl:when test="contains($word,'&#x0A;')">
+ <xsl:value-of select="substring-before($word,'&#x0A;')"/>
+ <br />
+ <xsl:call-template name="br-replace">
+ <xsl:with-param name="word" select="substring-after($word,'&#x0A;')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$word"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template name="display-time">
+ <xsl:param name="value"/>
+ <xsl:value-of select="format-number($value,'0.000')"/>
+</xsl:template>
+
+<xsl:template name="display-percent">
+ <xsl:param name="value"/>
+ <xsl:value-of select="format-number($value,'0.00%')"/>
+</xsl:template>
+
+</xsl:stylesheet>
+
diff --git a/buildscripts/phing/etc/str.replace.function.xsl b/buildscripts/phing/etc/str.replace.function.xsl
new file mode 100644
index 00000000..5d74e86c
--- /dev/null
+++ b/buildscripts/phing/etc/str.replace.function.xsl
@@ -0,0 +1,105 @@
+<?xml version="1.0"?>
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:str="http://exslt.org/strings"
+ xmlns:func="http://exslt.org/functions"
+ xmlns:exsl="http://exslt.org/common"
+ extension-element-prefixes="str exsl func">
+
+<func:function name="str:replace">
+ <xsl:param name="string" select="''" />
+ <xsl:param name="search" select="/.." />
+ <xsl:param name="replace" select="/.." />
+ <xsl:choose>
+ <xsl:when test="not($string)">
+ <func:result select="/.." />
+ </xsl:when>
+ <xsl:when test="function-available('exsl:node-set')">
+ <!-- this converts the search and replace arguments to node sets
+ if they are one of the other XPath types -->
+ <xsl:variable name="search-nodes-rtf">
+ <xsl:copy-of select="$search" />
+ </xsl:variable>
+ <xsl:variable name="replace-nodes-rtf">
+ <xsl:copy-of select="$replace" />
+ </xsl:variable>
+ <xsl:variable name="replacements-rtf">
+ <xsl:for-each select="exsl:node-set($search-nodes-rtf)/node()">
+ <xsl:variable name="pos" select="position()" />
+ <replace search="{.}">
+ <xsl:copy-of select="exsl:node-set($replace-nodes-rtf)/node()[$pos]" />
+ </replace>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:variable name="sorted-replacements-rtf">
+ <xsl:for-each select="exsl:node-set($replacements-rtf)/replace">
+ <xsl:sort select="string-length(@search)" data-type="number" order="descending" />
+ <xsl:copy-of select="." />
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:variable name="result">
+ <xsl:choose>
+ <xsl:when test="not($search)">
+ <xsl:value-of select="$string" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="str:_replace">
+ <xsl:with-param name="string" select="$string" />
+ <xsl:with-param name="replacements" select="exsl:node-set($sorted-replacements-rtf)/replace" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <func:result select="exsl:node-set($result)/node()" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">
+ ERROR: function implementation of str:replace() relies on exsl:node-set().
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+</func:function>
+
+<xsl:template name="str:_replace">
+ <xsl:param name="string" select="''" />
+ <xsl:param name="replacements" select="/.." />
+ <xsl:choose>
+ <xsl:when test="not($string)" />
+ <xsl:when test="not($replacements)">
+ <xsl:value-of select="$string" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="replacement" select="$replacements[1]" />
+ <xsl:variable name="search" select="$replacement/@search" />
+ <xsl:choose>
+ <xsl:when test="not(string($search))">
+ <xsl:value-of select="substring($string, 1, 1)" />
+ <xsl:copy-of select="$replacement/node()" />
+ <xsl:call-template name="str:_replace">
+ <xsl:with-param name="string" select="substring($string, 2)" />
+ <xsl:with-param name="replacements" select="$replacements" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains($string, $search)">
+ <xsl:call-template name="str:_replace">
+ <xsl:with-param name="string" select="substring-before($string, $search)" />
+ <xsl:with-param name="replacements" select="$replacements[position() > 1]" />
+ </xsl:call-template>
+ <xsl:copy-of select="$replacement/node()" />
+ <xsl:call-template name="str:_replace">
+ <xsl:with-param name="string" select="substring-after($string, $search)" />
+ <xsl:with-param name="replacements" select="$replacements" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="str:_replace">
+ <xsl:with-param name="string" select="$string" />
+ <xsl:with-param name="replacements" select="$replacements[position() > 1]" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+</xsl:stylesheet> \ No newline at end of file
diff --git a/buildscripts/phing/pear/BuildPhingPEARPackageTask.php b/buildscripts/phing/pear/BuildPhingPEARPackageTask.php
new file mode 100644
index 00000000..6ac6ad51
--- /dev/null
+++ b/buildscripts/phing/pear/BuildPhingPEARPackageTask.php
@@ -0,0 +1,270 @@
+<?php
+/*
+ * $Id$
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once 'phing/tasks/system/MatchingTask.php';
+include_once 'phing/types/FileSet.php';
+include_once 'phing/tasks/ext/pearpackage/Fileset.php';
+
+/**
+ *
+ * @author Hans Lellelid <hans@xmpl.org>
+ * @package phing.tasks.ext
+ * @version $Revision$
+ */
+class BuildPhingPEARPackageTask extends MatchingTask {
+
+ /** Base directory for reading files. */
+ private $dir;
+
+ private $version;
+ private $state = 'stable';
+ private $notes;
+
+ private $filesets = array();
+
+ /** Package file */
+ private $packageFile;
+
+ public function init() {
+ include_once 'PEAR/PackageFileManager2.php';
+ if (!class_exists('PEAR_PackageFileManager2')) {
+ throw new BuildException("You must have installed PEAR_PackageFileManager2 (PEAR_PackageFileManager >= 1.6.0) in order to create a PEAR package.xml file.");
+ }
+ }
+
+ private function setOptions($pkg){
+
+ $options['baseinstalldir'] = 'phing';
+ $options['packagedirectory'] = $this->dir->getAbsolutePath();
+
+ if (empty($this->filesets)) {
+ throw new BuildException("You must use a <fileset> tag to specify the files to include in the package.xml");
+ }
+
+ $options['filelistgenerator'] = 'Fileset';
+
+ // Some PHING-specific options needed by our Fileset reader
+ $options['phing_project'] = $this->getProject();
+ $options['phing_filesets'] = $this->filesets;
+
+ if ($this->packageFile !== null) {
+ // create one w/ full path
+ $f = new PhingFile($this->packageFile->getAbsolutePath());
+ $options['packagefile'] = $f->getName();
+ // must end in trailing slash
+ $options['outputdirectory'] = $f->getParent() . DIRECTORY_SEPARATOR;
+ $this->log("Creating package file: " . $f->getPath(), PROJECT_MSG_INFO);
+ } else {
+ $this->log("Creating [default] package.xml file in base directory.", PROJECT_MSG_INFO);
+ }
+
+ // add install exceptions
+ $options['installexceptions'] = array( 'bin/phing.php' => '/',
+ 'bin/pear-phing' => '/',
+ 'bin/pear-phing.bat' => '/',
+ );
+
+ $options['dir_roles'] = array( 'phing_guide' => 'doc',
+ 'etc' => 'data',
+ 'example' => 'doc');
+
+ $options['exceptions'] = array( 'bin/pear-phing.bat' => 'script',
+ 'bin/pear-phing' => 'script',
+ 'CREDITS' => 'doc',
+ 'CHANGELOG' => 'doc',
+ 'README' => 'doc',
+ 'TODO' => 'doc');
+
+ $pkg->setOptions($options);
+
+ }
+
+ /**
+ * Main entry point.
+ * @return void
+ */
+ public function main() {
+
+ if ($this->dir === null) {
+ throw new BuildException("You must specify the \"dir\" attribute for PEAR package task.");
+ }
+
+ if ($this->version === null) {
+ throw new BuildException("You must specify the \"version\" attribute for PEAR package task.");
+ }
+
+ $package = new PEAR_PackageFileManager2();
+
+ $this->setOptions($package);
+
+ // the hard-coded stuff
+ $package->setPackage('phing');
+ $package->setSummary('PHP5 project build system based on Apache Ant');
+ $package->setDescription('PHing Is Not GNU make; it\'s a project build system based on Apache Ant.
+You can do anything with it that you could do with a traditional build system like GNU make, and its use of
+simple XML build files and extensible PHP "task" classes make it an easy-to-use and highly flexible build framework.
+Features include file transformations (e.g. token replacement, XSLT transformation, Smarty template transformations,
+etc.), file system operations, interactive build support, SQL execution, and much more.');
+ $package->setChannel('pear.phing.info');
+ $package->setPackageType('php');
+
+ $package->setReleaseVersion($this->version);
+ $package->setAPIVersion($this->version);
+
+ $package->setReleaseStability($this->state);
+ $package->setAPIStability($this->state);
+
+ $package->setNotes($this->notes);
+
+ $package->setLicense('LGPL', 'http://www.gnu.org/licenses/lgpl.html');
+
+ // Add package maintainers
+ $package->addMaintainer('lead', 'hans', 'Hans Lellelid', 'hans@xmpl.org');
+ $package->addMaintainer('lead', 'mrook', 'Michiel Rook', 'michiel@trendserver.nl');
+
+
+
+ // (wow ... this is a poor design ...)
+ //
+ // note that the order of the method calls below is creating
+ // sub-"release" sections which have specific rules. This replaces
+ // the platformexceptions system in the older version of PEAR's package.xml
+ //
+ // Programmatically, I feel the need to re-iterate that this API for PEAR_PackageFileManager
+ // seems really wrong. Sub-sections should be encapsulated in objects instead of having
+ // a "flat" API that does not represent the structure being created....
+
+
+ // creating a sub-section for 'windows'
+ $package->addRelease();
+ $package->setOSInstallCondition('windows');
+ $package->addInstallAs('bin/phing.php', 'phing.php');
+ $package->addInstallAs('bin/pear-phing.bat', 'phing.bat');
+ $package->addIgnoreToRelease('bin/pear-phing');
+
+ // creating a sub-section for non-windows
+ $package->addRelease();
+ //$package->setOSInstallCondition('(*ix|*ux|darwin*|*BSD|SunOS*)');
+ $package->addInstallAs('bin/phing.php', 'phing.php');
+ $package->addInstallAs('bin/pear-phing', 'phing');
+ $package->addIgnoreToRelease('bin/pear-phing.bat');
+
+
+ // "core" dependencies
+ $package->setPhpDep('5.0.0');
+ $package->setPearinstallerDep('1.4.0');
+
+ // "package" dependencies
+ $package->addPackageDepWithChannel( 'optional', 'VersionControl_SVN', 'pear.php.net', '0.3.0alpha1');
+ $package->addPackageDepWithChannel( 'optional', 'PHPUnit2', 'pear.php.net', '2.3.0');
+ $package->addPackageDepWithChannel( 'optional', 'PhpDocumentor', 'pear.php.net', '1.3.0RC3');
+ $package->addPackageDepWithChannel( 'optional', 'Xdebug', 'pear.php.net', '2.0.0beta2');
+ $package->addPackageDepWithChannel( 'optional', 'Archive_Tar', 'pear.php.net', '1.3.0');
+ $package->addPackageDepWithChannel( 'optional', 'PEAR_PackageFileManager', 'pear.php.net', '1.5.2');
+
+ // now add the replacements ....
+ $package->addReplacement('Phing.php', 'pear-config', '@DATA-DIR@', 'data_dir');
+ $package->addReplacement('bin/pear-phing.bat', 'pear-config', '@PHP-BIN@', 'php_bin');
+ $package->addReplacement('bin/pear-phing.bat', 'pear-config', '@BIN-DIR@', 'bin_dir');
+ $package->addReplacement('bin/pear-phing.bat', 'pear-config', '@PEAR-DIR@', 'php_dir');
+ $package->addReplacement('bin/pear-phing', 'pear-config', '@PHP-BIN@', 'php_bin');
+ $package->addReplacement('bin/pear-phing', 'pear-config', '@BIN-DIR@', 'bin_dir');
+ $package->addReplacement('bin/pear-phing', 'pear-config', '@PEAR-DIR@', 'php_dir');
+
+ // now we run this weird generateContents() method that apparently
+ // is necessary before we can add replacements ... ?
+ $package->generateContents();
+
+ $e = $package->writePackageFile();
+
+ if (PEAR::isError($e)) {
+ throw new BuildException("Unable to write package file.", new Exception($e->getMessage()));
+ }
+
+ }
+
+ /**
+ * Used by the PEAR_PackageFileManager_PhingFileSet lister.
+ * @return array FileSet[]
+ */
+ public function getFileSets() {
+ return $this->filesets;
+ }
+
+ // -------------------------------
+ // Set properties from XML
+ // -------------------------------
+
+ /**
+ * Nested creator, creates a FileSet for this task
+ *
+ * @return FileSet The created fileset object
+ */
+ function createFileSet() {
+ $num = array_push($this->filesets, new FileSet());
+ return $this->filesets[$num-1];
+ }
+
+ /**
+ * Set the version we are building.
+ * @param string $v
+ * @return void
+ */
+ public function setVersion($v){
+ $this->version = $v;
+ }
+
+ /**
+ * Set the state we are building.
+ * @param string $v
+ * @return void
+ */
+ public function setState($v) {
+ $this->state = $v;
+ }
+
+ /**
+ * Sets release notes field.
+ * @param string $v
+ * @return void
+ */
+ public function setNotes($v) {
+ $this->notes = $v;
+ }
+ /**
+ * Sets "dir" property from XML.
+ * @param PhingFile $f
+ * @return void
+ */
+ public function setDir(PhingFile $f) {
+ $this->dir = $f;
+ }
+
+ /**
+ * Sets the file to use for generated package.xml
+ */
+ public function setDestFile(PhingFile $f) {
+ $this->packageFile = $f;
+ }
+
+}
+
+
diff --git a/buildscripts/phing/pear/build.xml b/buildscripts/phing/pear/build.xml
new file mode 100644
index 00000000..128dcd03
--- /dev/null
+++ b/buildscripts/phing/pear/build.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0"?>
+<!--
+ This build file packages the phing files, builds a package.xml (version 2) for installation
+ using PEAR and creates the TAR and TGZ files.
+-->
+<project name="phing" basedir="." default="main">
+
+ <property name="phing.home" value=".."/>
+ <property name="build.base.dir" value="build"/>
+ <property name="pkgname" value="phing-${version}"/>
+ <property name="build.src.dir" value="${build.base.dir}/${pkgname}"/>
+
+ <!-- some default properties -->
+ <property name="notes">This is the latest release of Phing.</property>
+ <property name="state" value="stable"/>
+
+ <taskdef
+ name="pear-package"
+ classname="BuildPhingPEARPackageTask" classpath="."/>
+
+ <fileset dir="${phing.home}/classes/phing" id="classes">
+ <include name="**"/>
+ </fileset>
+
+ <fileset dir="${phing.home}/docs" id="docs">
+ <include name="example/**"/>
+ <include name="phing_guide/book/**"/>
+ </fileset>
+
+ <fileset dir="${phing.home}" id="etc">
+ <include name="etc/**"/>
+ <exclude name="etc/VERSION.TXT"/>
+ </fileset>
+
+ <fileset dir="${phing.home}" id="scripts">
+ <include name="bin/pear-*"/>
+ <include name="bin/phing.php"/>
+ </fileset>
+
+ <fileset dir="${phing.home}" id="misc">
+ <include name="CHANGELOG"/>
+ <include name="CREDITS"/>
+ <include name="README"/>
+ <include name="TODO"/>
+ <exclude name="INSTALL*"/>
+ </fileset>
+
+ <!--
+ ==============================================
+ Main entry point
+ ==============================================
+ -->
+ <target name="main" if="version" depends="versioncheck,copy-files,create-package-xml,tar"/>
+
+ <!--
+ ===================================================================
+ Target: checks if language was given, otherwise fail
+ ===================================================================
+ -->
+ <target name="versioncheck" unless="version">
+ <echo message="====================================================="/>
+ <echo message="Version not specified. You must enter a version. In"/>
+ <echo message="the future you can add this to build.properties or"/>
+ <echo message="enter it on the command line: "/>
+ <echo message=" "/>
+ <echo message="-Dversion=2.0.0b1"/>
+ <echo message="====================================================="/>
+ <input propertyname="version" promptChar=":">Phing version for package</input>
+
+ <property name="pkgname" value="phing-${version}" override="true"/>
+ <property name="build.src.dir" value="${build.base.dir}/${pkgname}" override="true"/>
+
+ </target>
+
+ <!--
+ ==============================================
+ Copy the desired files into the build/ dir
+ making sure to put them in the directory
+ structure that will be needed for PEAR install
+ ==============================================
+ -->
+ <target name="copy-files">
+
+ <echo>-----------------------------</echo>
+ <echo>| Creating directory layout |</echo>
+ <echo>-----------------------------</echo>
+
+ <delete dir="${build.base.dir}"/>
+
+ <copy todir="${build.src.dir}">
+ <fileset refid="classes"/>
+ <fileset refid="docs"/>
+ <fileset refid="etc"/>
+ <fileset refid="scripts"/>
+ <fileset refid="misc"/>
+ </copy>
+
+ <append destFile="${build.src.dir}/etc/VERSION.TXT">Phing version ${version}</append>
+
+ <chmod file="${build.src.dir}/bin/pear-phing" mode="755"/>
+
+ </target>
+
+ <!--
+ ==============================================
+ Create a PEAR package.xml which will guide the
+ installation.
+ ==============================================
+ -->
+ <target name="create-package-xml" depends="versioncheck" if="version">
+
+ <echo>-----------------------------</echo>
+ <echo>| Creating PEAR package.xml |</echo>
+ <echo>-----------------------------</echo>
+ <echo></echo>
+ <echo>... (This step may take some time) ...</echo>
+
+ <delete file="${tarfile}"/>
+ <pear-package dir="${build.src.dir}" destFile="${build.base.dir}/package.xml" version="${version}" state="${state}" notes="${notes}">
+
+ <fileset refid="classes"/>
+ <fileset refid="docs"/>
+ <fileset refid="etc"/>
+ <fileset refid="misc"/>
+ <fileset refid="scripts"/>
+
+ <fileset dir="${build.src.dir}">
+ <include name="etc/VERSION.TXT"/>
+ </fileset>
+
+ </pear-package>
+
+ </target>
+
+ <!--
+ ==============================================
+ Create a tar.gz of the files, which will be
+ installed by pear package manager.
+ ==============================================
+ -->
+ <target name="tar">
+ <echo>-----------------------------</echo>
+ <echo>| Creating TAR packages |</echo>
+ <echo>-----------------------------</echo>
+
+ <property name="tgzfile" value="${build.base.dir}/${pkgname}.tgz"/>
+ <delete file="${tgzfile}"/>
+ <tar compression="gzip" destFile="${tgzfile}" basedir="${build.base.dir}" />
+
+ <property name="tarfile" value="${build.base.dir}/${pkgname}.tar"/>
+ <delete file="${tarfile}"/>
+ <tar compression="none" destFile="${tarfile}" basedir="${build.base.dir}" />
+
+ </target>
+
+</project> \ No newline at end of file
diff --git a/buildscripts/phing/tasks/ManualIndexTask.php b/buildscripts/phing/tasks/ManualIndexTask.php
new file mode 100644
index 00000000..1725880f
--- /dev/null
+++ b/buildscripts/phing/tasks/ManualIndexTask.php
@@ -0,0 +1,38 @@
+<?php
+
+require_once 'phing/Task.php';
+
+/**
+ * Task to index PRADO API docs.
+ */
+class ManualIndexTask extends Task
+{
+ private $docdir;
+ private $todir;
+
+ /**
+ * @param string the API documentation directory
+ */
+ public function setDocdir($value)
+ {
+ $this->docdir=$value;
+ }
+
+ public function setTodir($value)
+ {
+ $this->todir=$value;
+ }
+
+ public function main()
+ {
+ $srcdir=realpath(dirname(__FILE__).'/../../../');
+ $zend_path = $srcdir.'/demos/quickstart/protected/index';
+ set_include_path(get_include_path().PATH_SEPARATOR.realpath($zend_path));
+ require_once ('Zend/Search/Lucene.php');
+ require_once($srcdir.'/buildscripts/index/api_index.php');
+ $api = new api_index($this->todir, realpath($this->docdir));
+ $api->create_index();
+ }
+}
+
+?> \ No newline at end of file
diff --git a/buildscripts/phing/tasks/PradoDocTask.php b/buildscripts/phing/tasks/PradoDocTask.php
new file mode 100644
index 00000000..3ab891bd
--- /dev/null
+++ b/buildscripts/phing/tasks/PradoDocTask.php
@@ -0,0 +1,137 @@
+<?php
+require_once 'phing/Task.php';
+
+/**
+ * Task to run phpDocumentor for PRADO API docs.
+ */
+class PradoDocTask extends Task
+{
+ private $phpdoc = 'phpdoc';
+
+ private $title = "Default Title";
+
+ private $destdir = ".";
+
+ private $sourcepath = NULL;
+
+ private $ignorelist = '';
+
+ private $output = "";
+
+ private $linksource = false;
+
+ private $parseprivate = false;
+
+ function setPhpdoc($phpdoc)
+ {
+ $this->phpdoc=$phpdoc;
+ }
+
+ /**
+ * Set the title for the generated documentation
+ */
+ function setTitle($title)
+ {
+ $this->title = $title;
+ }
+
+ /**
+ * Set the destination directory for the generated documentation
+ */
+ function setDestdir($destdir)
+ {
+ $this->destdir = $destdir;
+ }
+
+ /**
+ * Set the source path
+ */
+ function setSourcepath(Path $sourcepath)
+ {
+ if ($this->sourcepath === NULL)
+ {
+ $this->sourcepath = $sourcepath;
+ }
+ else
+ {
+ $this->sourcepath->append($sourcepath);
+ }
+ }
+
+ /**
+ * Set the output type
+ */
+ function setOutput($output)
+ {
+ $this->output = $output;
+ }
+
+ /**
+ * Should sources be linked in the generated documentation
+ */
+ function setLinksource($linksource)
+ {
+ $this->linksource = $linksource;
+ }
+
+ function setIgnorelist($ignorelist)
+ {
+ $this->ignorelist=$ignorelist;
+ }
+
+ /**
+ * Main entrypoint of the task
+ */
+ function main()
+ {
+ $arguments = $this->constructArguments();
+ exec($this->phpdoc . " " . $arguments, $output, $retval);
+ }
+
+ /**
+ * Constructs an argument string for phpDocumentor
+ */
+ private function constructArguments()
+ {
+ $arguments = "-q \"on\" ";
+
+ if ($this->title)
+ {
+ $arguments.= "-ti \"" . $this->title . "\" ";
+ }
+
+ if ($this->destdir)
+ {
+ $arguments.= "-t \"" . $this->destdir . "\" ";
+ }
+
+ if ($this->sourcepath !== NULL)
+ {
+ $arguments.= "-d \"" . $this->sourcepath->__toString() . "\" ";
+ }
+
+ if ($this->output)
+ {
+ $arguments.= "-o \"" . $this->output . "\" ";
+ }
+
+ if ($this->linksource)
+ {
+ $arguments.= "-s ";
+ }
+
+ if ($this->parseprivate)
+ {
+ $arguments.= "-pp ";
+ }
+
+ if ($this->ignorelist)
+ {
+ $arguments.='-i "'.$this->ignorelist.'" ';
+ }
+
+ return $arguments;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/buildscripts/phing/tasks/PradoPearTask.php b/buildscripts/phing/tasks/PradoPearTask.php
new file mode 100644
index 00000000..5d615084
--- /dev/null
+++ b/buildscripts/phing/tasks/PradoPearTask.php
@@ -0,0 +1,133 @@
+<?php
+
+require_once 'phing/Task.php';
+require_once('PEAR/PackageFileManager2.php');
+
+/**
+ * Task to run phpDocumentor for PRADO API docs.
+ */
+class PradoPearTask extends Task
+{
+ private $pkgdir;
+ private $channel;
+ private $version;
+ private $state;
+ private $category;
+ private $package;
+ private $summary;
+ private $pkgdescription;
+ private $notes;
+ private $license;
+
+ function setPkgdir($value)
+ {
+ $this->pkgdir=$value;
+ }
+
+ function setChannel($value)
+ {
+ $this->channel=$value;
+ }
+
+ function setVersion($value)
+ {
+ $this->version=$value;
+ }
+
+ function setState($value)
+ {
+ $this->state=$value;
+ }
+
+ function setCategory($value)
+ {
+ $this->category=$value;
+ }
+
+ function setPackage($value)
+ {
+ $this->package=$value;
+ }
+
+ function setSummary($value)
+ {
+ $this->summary=$value;
+ }
+
+ function setPkgdescription($value)
+ {
+ $this->pkgdescription=$value;
+ }
+
+ function setNotes($value)
+ {
+ $this->notes=$value;
+ }
+
+ function setLicense($value)
+ {
+ $this->license=$value;
+ }
+
+ /**
+ * Main entrypoint of the task
+ */
+ function main()
+ {
+ $pkg = new PEAR_PackageFileManager2();
+
+ $e = $pkg->setOptions(
+ array(
+ 'baseinstalldir' => 'prado',
+ 'packagedirectory' => $this->pkgdir,
+ 'pathtopackagefile' => $this->pkgdir,
+ 'filelistgenerator' => 'file',
+ 'simpleoutput' => true,
+ 'ignore' => array(),
+ 'dir_roles' =>
+ array(
+ 'docs' => 'doc',
+ 'examples' => 'doc',
+ 'framework' => 'php',
+ 'framework/js' => 'doc',
+ 'framework/3rdParty' => 'doc',
+ ),
+ 'exceptions' =>
+ array(
+ 'requirements.php' => 'doc',
+ ),
+ )
+ );
+
+ // PEAR error checking
+ if (PEAR::isError($e))
+ die($e->getMessage());
+ $pkg->setPackage($this->package);
+ $pkg->setSummary($this->summary);
+ $pkg->setDescription($this->pkgdescription);
+ $pkg->setChannel($this->channel);
+
+ $pkg->setReleaseStability($this->state);
+ $pkg->setAPIStability($this->state);
+ $pkg->setReleaseVersion($this->version);
+ $pkg->setAPIVersion($this->version);
+
+ $pkg->setLicense($this->license);
+ $pkg->setNotes($this->notes);
+ $pkg->setPackageType('php');
+ $pkg->setPhpDep('5.0.0');
+ $pkg->setPearinstallerDep('1.4.2');
+
+ $pkg->addRelease();
+ $pkg->addMaintainer('lead','qxue','Qiang (Charlie) Xue','qiang.xue@gmail.com');
+
+ $test = $pkg->generateContents();
+
+ $e = $pkg->writePackageFile();
+
+ if (PEAR::isError($e))
+ echo $e->getMessage();
+ }
+}
+
+?> \ No newline at end of file
diff --git a/buildscripts/phing/tasks/PradoTestTask.php b/buildscripts/phing/tasks/PradoTestTask.php
new file mode 100644
index 00000000..ba1e06be
--- /dev/null
+++ b/buildscripts/phing/tasks/PradoTestTask.php
@@ -0,0 +1,18 @@
+<?php
+require_once 'phing/Task.php';
+require_once 'phing/tasks/ext/phpunit2/PHPUnit2Task.php';
+
+/**
+ * Task to run PRADO unit tests
+ */
+class PradoTestTask extends PHPUnit2Task
+{
+ function init()
+ {
+ $phpunit2_path = realpath(dirname(__FILE__).'/../..');
+ set_include_path(get_include_path().PATH_SEPARATOR.$phpunit2_path);
+ parent::init();
+ }
+}
+
+?> \ No newline at end of file
diff --git a/buildscripts/phing/tasks/PradoVersionTask.php b/buildscripts/phing/tasks/PradoVersionTask.php
new file mode 100644
index 00000000..911b68d4
--- /dev/null
+++ b/buildscripts/phing/tasks/PradoVersionTask.php
@@ -0,0 +1,56 @@
+<?php
+require_once 'phing/Task.php';
+include_once 'phing/tasks/system/PropertyTask.php';
+
+class PradoVersionTask extends PropertyTask
+{
+ /**
+ * Execute lint check against PhingFile or a FileSet
+ */
+ public function main()
+ {
+ $this->addProperty('prado.version',$this->getPradoVersion());
+ $this->addProperty('prado.revision',$this->getPradoRevision());
+ if(substr(PHP_OS, 0, 3) == 'WIN')
+ $this->addProperty('prado.winbuild','true');
+ else
+ $this->addProperty('prado.winbuild','false');
+ }
+
+ /**
+ * @return string Prado version
+ */
+ private function getPradoVersion()
+ {
+ $coreFile=dirname(__FILE__).'/../../../framework/PradoBase.php';
+ if(is_file($coreFile))
+ {
+ $contents=file_get_contents($coreFile);
+ $matches=array();
+ if(preg_match('/public static function getVersion.*?return \'(.*?)\'/ms',$contents,$matches)>0)
+ return $matches[1];
+ }
+ return 'unknown';
+ }
+
+ /**
+ * @return string Prado SVN revision
+ */
+ private function getPradoRevision()
+ {
+ $svnPath=dirname(__FILE__).'/../../../.svn';
+ if(is_file($svnPath.'/all-wcprops'))
+ $propFile=$svnPath.'/all-wcprops';
+ else if(is_file($svnPath.'/dir-wcprops'))
+ $propFile=$svnPath.'/dir-wcprops';
+ else
+ return 'unknown';
+ $contents=file_get_contents($propFile);
+ if(preg_match('/\\/repos\\/prado\\/\\!svn\\/ver\\/(\d+)\\//ms',$contents,$matches)>0)
+ return $matches[1];
+ else
+ return 'unknown';
+ }
+}
+
+?> \ No newline at end of file
diff --git a/buildscripts/phing/tasks/QuickstartIndexTask.php b/buildscripts/phing/tasks/QuickstartIndexTask.php
new file mode 100644
index 00000000..f3107fd3
--- /dev/null
+++ b/buildscripts/phing/tasks/QuickstartIndexTask.php
@@ -0,0 +1,32 @@
+<?php
+
+require_once 'phing/Task.php';
+
+/**
+ * Task to index quickstart
+ */
+class QuickstartIndexTask extends Task
+{
+ private $todir;
+
+ public function setTodir($value)
+ {
+ $this->todir=$value;
+ }
+
+ public function main()
+ {
+ $srcdir=realpath(dirname(__FILE__).'/../../../');
+ $zend_path = $srcdir.'/demos/quickstart/protected/index';
+ set_include_path(get_include_path().PATH_SEPARATOR.realpath($zend_path));
+ require_once ('Zend/Search/Lucene.php');
+
+ require_once($srcdir.'/buildscripts/index/quickstart_index.php');
+ $quickstart_source = $srcdir.'/buildscripts/texbuilder/pages.php';
+ $quickstart_base = $srcdir.'/demos/quickstart/protected/pages/';
+ $quickstart = new quickstart_index($this->todir, realpath($quickstart_base), realpath($quickstart_source));
+ $quickstart->create_index();
+ }
+}
+
+?> \ No newline at end of file
diff --git a/buildscripts/texbuilder/quickstart.tex b/buildscripts/texbuilder/quickstart.tex
index ee3010fe..35ba86a5 100644
--- a/buildscripts/texbuilder/quickstart.tex
+++ b/buildscripts/texbuilder/quickstart.tex
@@ -42,10 +42,10 @@
%----------------- TITLE --------------
-\title{\Huge \bfseries Prado v3.0.1 Quick Start Tutorial
+\title{\Huge \bfseries PRADO v3.0.2 Quickstart Tutorial
\thanks{Copyright 2005-2006. All Rights Reserved.}
}
-\author{Qiang Xue, Wei Zhuo}
+\author{Qiang Xue and Wei Zhuo}
\date{\today}