From fae6352bf28fcb8b2ce16a8a6e72dafc8373019c Mon Sep 17 00:00:00 2001 From: anubis Date: Sun, 4 Jan 2009 19:22:54 -0500 Subject: [PATCH] Update to PEAR 1.7.2, Image_Canvas 0.3.1, Image_Color 1.0.3, Image_Graph 0.7.2, XML_Parser 1.3.1. Removed PHP_Compat, and references to it. Removed ionCube/Zend/mmCache compatibility checks in test.php script. Changed minimum PHP requirement to 5.0 in test.php script. --- includes/pear/Compat.php | 133 - includes/pear/Compat/Components.php | 71 - includes/pear/Compat/Constant/E_STRICT.php | 35 - includes/pear/Compat/Constant/FILE.php | 51 - includes/pear/Compat/Constant/PHP_EOL.php | 49 - includes/pear/Compat/Constant/STD.php | 43 - includes/pear/Compat/Constant/T.php | 72 - includes/pear/Compat/Constant/UPLOAD_ERR.php | 51 - .../pear/Compat/Function/array_combine.php | 71 - .../pear/Compat/Function/array_diff_assoc.php | 75 - .../pear/Compat/Function/array_diff_key.php | 66 - .../Compat/Function/array_diff_uassoc.php | 83 - .../pear/Compat/Function/array_diff_ukey.php | 79 - .../Compat/Function/array_intersect_assoc.php | 69 - .../Compat/Function/array_intersect_key.php | 67 - .../Function/array_intersect_uassoc.php | 90 - .../Compat/Function/array_intersect_ukey.php | 79 - includes/pear/Compat/Function/array_udiff.php | 83 - .../Compat/Function/array_udiff_assoc.php | 85 - .../Compat/Function/array_udiff_uassoc.php | 82 - .../pear/Compat/Function/array_uintersect.php | 82 - .../Function/array_uintersect_assoc.php | 81 - .../Function/array_uintersect_uassoc.php | 97 - .../Compat/Function/array_walk_recursive.php | 68 - includes/pear/Compat/Function/clone.php | 56 - .../pear/Compat/Function/convert_uudecode.php | 79 - .../pear/Compat/Function/convert_uuencode.php | 79 - .../Compat/Function/debug_print_backtrace.php | 67 - .../Compat/Function/file_get_contents.php | 57 - .../Compat/Function/file_put_contents.php | 104 - includes/pear/Compat/Function/fprintf.php | 54 - includes/pear/Compat/Function/get_headers.php | 77 - .../pear/Compat/Function/get_include_path.php | 39 - .../Compat/Function/html_entity_decode.php | 72 - .../pear/Compat/Function/http_build_query.php | 99 - .../Function/image_type_to_mime_type.php | 147 - .../pear/Compat/Function/ob_get_clean.php | 46 - .../pear/Compat/Function/ob_get_flush.php | 46 - .../Compat/Function/php_strip_whitespace.php | 86 - .../Compat/Function/restore_include_path.php | 37 - includes/pear/Compat/Function/scandir.php | 69 - .../pear/Compat/Function/set_include_path.php | 37 - .../pear/Compat/Function/str_ireplace.php | 113 - includes/pear/Compat/Function/str_shuffle.php | 53 - includes/pear/Compat/Function/str_split.php | 52 - .../pear/Compat/Function/str_word_count.php | 68 - includes/pear/Compat/Function/stripos.php | 73 - includes/pear/Compat/Function/strpbrk.php | 63 - includes/pear/Compat/Function/strripos.php | 82 - .../pear/Compat/Function/substr_compare.php | 74 - includes/pear/Image/Canvas.php | 1440 +++---- includes/pear/Image/Canvas/Color.php | 362 +- includes/pear/Image/Canvas/Fonts/README | 22 +- includes/pear/Image/Canvas/Fonts/fontmap.txt | 48 +- includes/pear/Image/Canvas/GD.php | 3423 +++++++++-------- includes/pear/Image/Canvas/GD/JPG.php | 236 +- includes/pear/Image/Canvas/GD/PNG.php | 248 +- includes/pear/Image/Canvas/ImageMap.php | 706 ++-- includes/pear/Image/Canvas/PDF.php | 2017 +++++----- includes/pear/Image/Canvas/SVG.php | 1862 ++++----- includes/pear/Image/Canvas/Tool.php | 432 +-- includes/pear/Image/Canvas/WithMap.php | 554 +-- includes/pear/Image/Color.php | 1434 +++---- includes/pear/Image/Graph.php | 1702 ++++---- includes/pear/Image/Graph/Axis.php | 3331 ++++++++-------- includes/pear/Image/Graph/Axis/Category.php | 861 +++-- .../pear/Image/Graph/Axis/Logarithmic.php | 325 +- .../pear/Image/Graph/Axis/Marker/Area.php | 310 +- .../pear/Image/Graph/Axis/Marker/Line.php | 246 +- includes/pear/Image/Graph/Axis/Radar.php | 406 +- includes/pear/Image/Graph/Common.php | 619 +-- includes/pear/Image/Graph/Config.php | 58 +- includes/pear/Image/Graph/Constants.php | 448 +-- .../pear/Image/Graph/DataPreprocessor.php | 146 +- .../Image/Graph/DataPreprocessor/Array.php | 204 +- .../Image/Graph/DataPreprocessor/Currency.php | 130 +- .../Image/Graph/DataPreprocessor/Date.php | 178 +- .../Graph/DataPreprocessor/Formatted.php | 178 +- .../Image/Graph/DataPreprocessor/Function.php | 182 +- .../Graph/DataPreprocessor/NumberText.php | 176 +- .../Graph/DataPreprocessor/RomanNumerals.php | 156 +- .../Graph/DataPreprocessor/Sequential.php | 132 +- includes/pear/Image/Graph/DataSelector.php | 132 +- .../Graph/DataSelector/EveryNthPoint.php | 192 +- .../pear/Image/Graph/DataSelector/NoZeros.php | 134 +- .../pear/Image/Graph/DataSelector/Values.php | 178 +- includes/pear/Image/Graph/Dataset.php | 964 ++--- .../pear/Image/Graph/Dataset/Function.php | 292 +- includes/pear/Image/Graph/Dataset/Random.php | 152 +- .../pear/Image/Graph/Dataset/Sequential.php | 226 +- includes/pear/Image/Graph/Dataset/Trivial.php | 518 +-- .../Image/Graph/Dataset/VectorFunction.php | 368 +- includes/pear/Image/Graph/Element.php | 1488 +++---- includes/pear/Image/Graph/Figure/Circle.php | 126 +- includes/pear/Image/Graph/Figure/Ellipse.php | 192 +- includes/pear/Image/Graph/Figure/Polygon.php | 186 +- .../pear/Image/Graph/Figure/Rectangle.php | 190 +- includes/pear/Image/Graph/Fill.php | 124 +- includes/pear/Image/Graph/Fill/Array.php | 272 +- includes/pear/Image/Graph/Fill/Gradient.php | 296 +- includes/pear/Image/Graph/Fill/Image.php | 192 +- includes/pear/Image/Graph/Font.php | 314 +- includes/pear/Image/Graph/Grid.php | 348 +- includes/pear/Image/Graph/Grid/Bars.php | 232 +- includes/pear/Image/Graph/Grid/Lines.php | 226 +- includes/pear/Image/Graph/Grid/Polar.php | 220 +- includes/pear/Image/Graph/Images/Maps/README | 32 +- includes/pear/Image/Graph/Layout.php | 436 +-- .../pear/Image/Graph/Layout/Horizontal.php | 370 +- includes/pear/Image/Graph/Layout/Matrix.php | 400 +- includes/pear/Image/Graph/Layout/Vertical.php | 214 +- includes/pear/Image/Graph/Legend.php | 768 ++-- includes/pear/Image/Graph/Line/Array.php | 256 +- includes/pear/Image/Graph/Line/Dashed.php | 150 +- includes/pear/Image/Graph/Line/Dotted.php | 132 +- includes/pear/Image/Graph/Line/Formatted.php | 178 +- includes/pear/Image/Graph/Line/Solid.php | 208 +- includes/pear/Image/Graph/Logo.php | 304 +- includes/pear/Image/Graph/Marker.php | 244 +- includes/pear/Image/Graph/Marker/Array.php | 208 +- includes/pear/Image/Graph/Marker/Asterisk.php | 216 +- includes/pear/Image/Graph/Marker/Average.php | 180 +- includes/pear/Image/Graph/Marker/Box.php | 150 +- includes/pear/Image/Graph/Marker/Bubble.php | 180 +- includes/pear/Image/Graph/Marker/Circle.php | 190 +- includes/pear/Image/Graph/Marker/Cross.php | 226 +- includes/pear/Image/Graph/Marker/Diamond.php | 144 +- includes/pear/Image/Graph/Marker/Icon.php | 264 +- includes/pear/Image/Graph/Marker/Pinpoint.php | 128 +- includes/pear/Image/Graph/Marker/Plus.php | 194 +- includes/pear/Image/Graph/Marker/Pointing.php | 278 +- .../Image/Graph/Marker/Pointing/Angular.php | 208 +- .../Image/Graph/Marker/Pointing/Radial.php | 180 +- .../Image/Graph/Marker/ReversePinpoint.php | 128 +- includes/pear/Image/Graph/Marker/Star.php | 174 +- includes/pear/Image/Graph/Marker/Triangle.php | 148 +- includes/pear/Image/Graph/Marker/Value.php | 426 +- includes/pear/Image/Graph/Plot.php | 1640 ++++---- includes/pear/Image/Graph/Plot/Area.php | 380 +- includes/pear/Image/Graph/Plot/Band.php | 401 +- includes/pear/Image/Graph/Plot/Bar.php | 607 +-- includes/pear/Image/Graph/Plot/BoxWhisker.php | 590 +-- .../pear/Image/Graph/Plot/CandleStick.php | 496 +-- includes/pear/Image/Graph/Plot/Dot.php | 192 +- includes/pear/Image/Graph/Plot/Fit/Line.php | 234 +- includes/pear/Image/Graph/Plot/Impulse.php | 405 +- includes/pear/Image/Graph/Plot/Line.php | 333 +- includes/pear/Image/Graph/Plot/Odo.php | 1434 +++---- includes/pear/Image/Graph/Plot/Pie.php | 1102 +++--- includes/pear/Image/Graph/Plot/Radar.php | 232 +- .../pear/Image/Graph/Plot/Smoothed/Area.php | 285 +- .../pear/Image/Graph/Plot/Smoothed/Bezier.php | 344 +- .../pear/Image/Graph/Plot/Smoothed/Line.php | 334 +- .../pear/Image/Graph/Plot/Smoothed/Radar.php | 280 +- includes/pear/Image/Graph/Plot/Step.php | 396 +- includes/pear/Image/Graph/Plotarea.php | 2286 +++++------ .../pear/Image/Graph/Plotarea/Element.php | 172 +- includes/pear/Image/Graph/Plotarea/Map.php | 606 +-- includes/pear/Image/Graph/Plotarea/Radar.php | 484 +-- includes/pear/Image/Graph/Simple.php | 240 +- includes/pear/Image/Graph/Title.php | 386 +- includes/pear/Image/Graph/Tool.php | 580 +-- includes/pear/Image/docs/ChangeLog | 48 - includes/pear/Image/docs/LICENSE | 344 -- includes/pear/Image/docs/README | 41 - includes/pear/Image/docs/colors.txt | 142 - .../pear/Image/docs/examples/antialias.php | 104 - .../Image/docs/examples/axis_direction.php | 54 - includes/pear/Image/docs/examples/canvas.php | 61 - .../examples/category_axis_explanation.php | 84 - .../pear/Image/docs/examples/color_chart.php | 51 - .../pear/Image/docs/examples/customize.php | 116 - .../pear/Image/docs/examples/data/colors.txt | 140 - .../Image/docs/examples/datapreprocessor.php | 99 - .../docs/examples/double_category_axis.php | 100 - .../Image/docs/examples/driver_filepdf.php | 53 - .../pear/Image/docs/examples/driver_pdf.php | 198 - .../Image/docs/examples/driver_png_svg.php | 72 - .../pear/Image/docs/examples/driver_swf01.php | 57 - .../pear/Image/docs/examples/driver_swf02.php | 197 - .../pear/Image/docs/examples/driver_swf03.php | 53 - .../Image/docs/examples/frontpage_sample.php | 313 -- .../docs/examples/gradient_fill_area.php | 80 - .../pear/Image/docs/examples/gradient_pie.php | 106 - .../Image/docs/examples/gradient_step.php | 77 - .../pear/Image/docs/examples/horizontal.php | 127 - .../Image/docs/examples/html_image_map.php | 108 - .../pear/Image/docs/examples/image_fill.php | 85 - .../pear/Image/docs/examples/imagemap.png | Bin 8737 -> 0 bytes .../docs/examples/images/audi-tt-coupe.jpg | Bin 93601 -> 0 bytes .../pear/Image/docs/examples/images/audi.png | Bin 1738 -> 0 bytes .../pear/Image/docs/examples/images/bmw.png | Bin 1684 -> 0 bytes .../pear/Image/docs/examples/images/coins.png | Bin 2327 -> 0 bytes .../Image/docs/examples/images/mercedes.png | Bin 2431 -> 0 bytes .../Image/docs/examples/images/modify.jpg | Bin 87978 -> 0 bytes .../Image/docs/examples/images/mountain.jpg | Bin 22009 -> 0 bytes .../Image/docs/examples/images/porsche.png | Bin 1949 -> 0 bytes includes/pear/Image/docs/examples/index.html | 1 - .../Image/docs/examples/layout_matrix.php | 49 - .../pear/Image/docs/examples/line_break.php | 78 - .../pear/Image/docs/examples/log_axis.php | 104 - .../docs/examples/log_axis_intersect.php | 106 - .../pear/Image/docs/examples/logo_graph.php | 194 - .../Image/docs/examples/manual_labels.php | 42 - includes/pear/Image/docs/examples/misc01.php | 197 - includes/pear/Image/docs/examples/misc02.php | 117 - includes/pear/Image/docs/examples/misc03.php | 78 - includes/pear/Image/docs/examples/misc04.php | 35 - includes/pear/Image/docs/examples/misc05.php | 146 - includes/pear/Image/docs/examples/misc06.php | 132 - .../Image/docs/examples/multiple_plots.php | 82 - .../Image/docs/examples/negative_values.php | 72 - .../pear/Image/docs/examples/pear-icon.png | Bin 927 -> 0 bytes .../pear/Image/docs/examples/plot_all.php | 231 -- .../docs/examples/plot_all_horizontal.php | 247 -- .../examples/plot_all_horizontal_invert.php | 250 -- .../pear/Image/docs/examples/plot_area.php | 57 - .../Image/docs/examples/plot_area_smooth.php | 55 - .../Image/docs/examples/plot_area_stack.php | 64 - .../pear/Image/docs/examples/plot_band.php | 62 - .../pear/Image/docs/examples/plot_bar.php | 55 - .../docs/examples/plot_bar_horizontal.php | 80 - .../Image/docs/examples/plot_bar_multiple.php | 72 - .../Image/docs/examples/plot_bar_stacked.php | 73 - .../docs/examples/plot_bar_stacked100pct.php | 83 - .../examples/plot_bar_stacked_horizontal.php | 79 - .../examples/plot_bar_stacked_negative.php | 74 - .../Image/docs/examples/plot_boxwhisker.php | 64 - .../Image/docs/examples/plot_candlestick.php | 84 - .../pear/Image/docs/examples/plot_impulse.php | 51 - .../docs/examples/plot_impulse_stacked.php | 66 - .../pear/Image/docs/examples/plot_line.php | 55 - .../Image/docs/examples/plot_line_smooth.php | 51 - .../pear/Image/docs/examples/plot_map.php | 75 - .../pear/Image/docs/examples/plot_odo.php | 121 - .../pear/Image/docs/examples/plot_pie.php | 58 - .../Image/docs/examples/plot_pie_rotate.php | 80 - .../pear/Image/docs/examples/plot_radar.php | 82 - .../Image/docs/examples/plot_radar_smooth.php | 78 - .../pear/Image/docs/examples/plot_scatter.php | 65 - .../docs/examples/plot_scatter_linefit.php | 60 - .../pear/Image/docs/examples/plot_step.php | 60 - .../Image/docs/examples/secondary_axis.php | 85 - includes/pear/Image/docs/examples/simple.php | 28 - .../pear/Image/docs/examples/simple_graph.php | 40 - .../Image/docs/examples/small_pie_plot.php | 53 - .../Image/docs/examples/vector_function.php | 62 - includes/pear/Image/tests/README | 12 - includes/pear/Image/tests/axis/category.php | 87 - .../pear/Image/tests/axis/intersection.php | 82 - .../axis/intersection_secondary_axis.php | 89 - includes/pear/Image/tests/axis/inversion.php | 89 - .../pear/Image/tests/axis/labelinterval.php | 99 - .../pear/Image/tests/axis/logarithmic.php | 84 - includes/pear/Image/tests/canvas_body.php | 326 -- includes/pear/Image/tests/freetype.php | 70 - includes/pear/Image/tests/gd.php | 75 - includes/pear/Image/tests/gradients.php | 87 - includes/pear/Image/tests/imagemap.php | 180 - includes/pear/Image/tests/jpg.php | 39 - includes/pear/Image/tests/lineends.php | 85 - includes/pear/Image/tests/pdf.php | 39 - includes/pear/Image/tests/pear-icon.png | Bin 927 -> 0 bytes includes/pear/Image/tests/plot/area.php | 79 - includes/pear/Image/tests/plot/bar.php | 79 - .../pear/Image/tests/plot/horizontal/area.php | 92 - .../pear/Image/tests/plot/horizontal/bar.php | 92 - .../Image/tests/plot/horizontal/impulse.php | 91 - .../pear/Image/tests/plot/horizontal/line.php | 91 - .../pear/Image/tests/plot/horizontal/step.php | 92 - includes/pear/Image/tests/plot/impulse.php | 78 - includes/pear/Image/tests/plot/line.php | 78 - includes/pear/Image/tests/plot/step.php | 79 - includes/pear/Image/tests/png.php | 39 - includes/pear/Image/tests/svg.php | 39 - includes/pear/Image/tests/text.php | 109 - includes/pear/OS/Guess.php | 59 +- includes/pear/PEAR.php | 53 +- includes/pear/PEAR/Autoloader.php | 8 +- includes/pear/PEAR/Builder.php | 69 +- includes/pear/PEAR/ChannelFile.php | 60 +- includes/pear/PEAR/ChannelFile/Parser.php | 8 +- includes/pear/PEAR/Command.php | 17 +- includes/pear/PEAR/Command/Auth.php | 51 +- includes/pear/PEAR/Command/Auth.xml | 5 +- includes/pear/PEAR/Command/Build.php | 8 +- includes/pear/PEAR/Command/Channels.php | 291 +- includes/pear/PEAR/Command/Channels.xml | 11 +- includes/pear/PEAR/Command/Common.php | 50 +- includes/pear/PEAR/Command/Config.php | 71 +- includes/pear/PEAR/Command/Install.php | 598 ++- includes/pear/PEAR/Command/Install.xml | 7 +- includes/pear/PEAR/Command/Mirror.php | 20 +- includes/pear/PEAR/Command/Package.php | 432 +-- includes/pear/PEAR/Command/Package.xml | 4 +- includes/pear/PEAR/Command/Pickle.php | 18 +- includes/pear/PEAR/Command/Pickle.xml | 4 +- includes/pear/PEAR/Command/Registry.php | 121 +- includes/pear/PEAR/Command/Registry.xml | 4 + includes/pear/PEAR/Command/Remote.php | 277 +- includes/pear/PEAR/Command/Remote.xml | 16 + includes/pear/PEAR/Command/Test.php | 190 +- includes/pear/PEAR/Command/Test.xml | 18 + includes/pear/PEAR/Common.php | 39 +- includes/pear/PEAR/Config.php | 191 +- includes/pear/PEAR/Dependency.php | 45 +- includes/pear/PEAR/Dependency2.php | 290 +- includes/pear/PEAR/DependencyDB.php | 98 +- includes/pear/PEAR/Downloader.php | 663 +++- includes/pear/PEAR/Downloader/Package.php | 321 +- includes/pear/PEAR/ErrorStack.php | 69 +- includes/pear/PEAR/Exception.php | 53 +- includes/pear/PEAR/FixPHP5PEARWarnings.php | 7 + includes/pear/PEAR/Frontend.php | 111 +- includes/pear/PEAR/Frontend/CLI.php | 151 +- includes/pear/PEAR/Installer.php | 911 +++-- includes/pear/PEAR/Installer/Role.php | 27 +- includes/pear/PEAR/Installer/Role/Cfg.php | 108 + includes/pear/PEAR/Installer/Role/Cfg.xml | 15 + includes/pear/PEAR/Installer/Role/Common.php | 12 +- includes/pear/PEAR/Installer/Role/Data.php | 8 +- includes/pear/PEAR/Installer/Role/Data.xml | 2 + includes/pear/PEAR/Installer/Role/Doc.php | 8 +- includes/pear/PEAR/Installer/Role/Doc.xml | 2 + includes/pear/PEAR/Installer/Role/Ext.php | 8 +- includes/pear/PEAR/Installer/Role/Ext.xml | 1 + includes/pear/PEAR/Installer/Role/Php.php | 8 +- includes/pear/PEAR/Installer/Role/Php.xml | 2 + includes/pear/PEAR/Installer/Role/Script.php | 8 +- includes/pear/PEAR/Installer/Role/Script.xml | 2 + includes/pear/PEAR/Installer/Role/Src.php | 8 +- includes/pear/PEAR/Installer/Role/Src.xml | 5 +- includes/pear/PEAR/Installer/Role/Test.php | 8 +- includes/pear/PEAR/Installer/Role/Test.xml | 2 + includes/pear/PEAR/Installer/Role/Www.php | 34 + includes/pear/PEAR/Installer/Role/Www.xml | 15 + includes/pear/PEAR/PackageFile.php | 82 +- .../pear/PEAR/PackageFile/Generator/v1.php | 25 +- .../pear/PEAR/PackageFile/Generator/v2.php | 194 +- includes/pear/PEAR/PackageFile/Parser/v1.php | 20 +- includes/pear/PEAR/PackageFile/Parser/v2.php | 10 +- includes/pear/PEAR/PackageFile/v1.php | 46 +- includes/pear/PEAR/PackageFile/v2.php | 143 +- .../pear/PEAR/PackageFile/v2/Validator.php | 406 +- includes/pear/PEAR/PackageFile/v2/rw.php | 176 +- includes/pear/PEAR/Packager.php | 23 +- includes/pear/PEAR/REST.php | 777 ++-- includes/pear/PEAR/REST/10.php | 1419 ++++--- includes/pear/PEAR/REST/11.php | 521 ++- includes/pear/PEAR/REST/13.php | 280 ++ includes/pear/PEAR/Registry.php | 247 +- includes/pear/PEAR/Remote.php | 73 +- includes/pear/PEAR/RunTest.php | 1116 ++++-- includes/pear/PEAR/Task/Common.php | 10 +- includes/pear/PEAR/Task/Postinstallscript.php | 18 +- .../pear/PEAR/Task/Postinstallscript/rw.php | 8 +- includes/pear/PEAR/Task/Replace.php | 14 +- includes/pear/PEAR/Task/Replace/rw.php | 8 +- includes/pear/PEAR/Task/Unixeol.php | 10 +- includes/pear/PEAR/Task/Unixeol/rw.php | 8 +- includes/pear/PEAR/Task/Windowseol.php | 10 +- includes/pear/PEAR/Task/Windowseol/rw.php | 8 +- includes/pear/PEAR/Validate.php | 44 +- includes/pear/PEAR/Validator/PECL.php | 21 +- includes/pear/PEAR/XMLParser.php | 16 +- includes/pear/System.php | 134 +- includes/pear/XML/Parser.php | 393 +- includes/pear/XML/Parser/Simple.php | 287 +- includes/pear/scripts/pear.bat | 115 - includes/pear/scripts/pear.sh | 28 - includes/pear/scripts/pearcmd.php | 423 -- includes/pear/scripts/peardev.bat | 229 -- includes/pear/scripts/peardev.sh | 28 - includes/pear/scripts/pecl.bat | 115 - includes/pear/scripts/pecl.sh | 28 - includes/pear/scripts/peclcmd.php | 45 - modules/core/email_piping.inc.php | 3 +- modules/core/import.inc.php | 5 +- modules/core/version.inc.php | 3 +- modules/invoice/invoice.inc.php | 3 +- modules/module/module.inc.php | 6 +- modules/report/class.Level.php | 5 +- modules/ticket/ticket.inc.php | 3 +- test.php | 284 +- 384 files changed, 34150 insertions(+), 44524 deletions(-) delete mode 100644 includes/pear/Compat.php delete mode 100644 includes/pear/Compat/Components.php delete mode 100644 includes/pear/Compat/Constant/E_STRICT.php delete mode 100644 includes/pear/Compat/Constant/FILE.php delete mode 100644 includes/pear/Compat/Constant/PHP_EOL.php delete mode 100644 includes/pear/Compat/Constant/STD.php delete mode 100644 includes/pear/Compat/Constant/T.php delete mode 100644 includes/pear/Compat/Constant/UPLOAD_ERR.php delete mode 100644 includes/pear/Compat/Function/array_combine.php delete mode 100644 includes/pear/Compat/Function/array_diff_assoc.php delete mode 100644 includes/pear/Compat/Function/array_diff_key.php delete mode 100644 includes/pear/Compat/Function/array_diff_uassoc.php delete mode 100644 includes/pear/Compat/Function/array_diff_ukey.php delete mode 100644 includes/pear/Compat/Function/array_intersect_assoc.php delete mode 100644 includes/pear/Compat/Function/array_intersect_key.php delete mode 100644 includes/pear/Compat/Function/array_intersect_uassoc.php delete mode 100644 includes/pear/Compat/Function/array_intersect_ukey.php delete mode 100644 includes/pear/Compat/Function/array_udiff.php delete mode 100644 includes/pear/Compat/Function/array_udiff_assoc.php delete mode 100644 includes/pear/Compat/Function/array_udiff_uassoc.php delete mode 100644 includes/pear/Compat/Function/array_uintersect.php delete mode 100644 includes/pear/Compat/Function/array_uintersect_assoc.php delete mode 100644 includes/pear/Compat/Function/array_uintersect_uassoc.php delete mode 100644 includes/pear/Compat/Function/array_walk_recursive.php delete mode 100644 includes/pear/Compat/Function/clone.php delete mode 100644 includes/pear/Compat/Function/convert_uudecode.php delete mode 100644 includes/pear/Compat/Function/convert_uuencode.php delete mode 100644 includes/pear/Compat/Function/debug_print_backtrace.php delete mode 100644 includes/pear/Compat/Function/file_get_contents.php delete mode 100644 includes/pear/Compat/Function/file_put_contents.php delete mode 100644 includes/pear/Compat/Function/fprintf.php delete mode 100644 includes/pear/Compat/Function/get_headers.php delete mode 100644 includes/pear/Compat/Function/get_include_path.php delete mode 100644 includes/pear/Compat/Function/html_entity_decode.php delete mode 100644 includes/pear/Compat/Function/http_build_query.php delete mode 100644 includes/pear/Compat/Function/image_type_to_mime_type.php delete mode 100644 includes/pear/Compat/Function/ob_get_clean.php delete mode 100644 includes/pear/Compat/Function/ob_get_flush.php delete mode 100644 includes/pear/Compat/Function/php_strip_whitespace.php delete mode 100644 includes/pear/Compat/Function/restore_include_path.php delete mode 100644 includes/pear/Compat/Function/scandir.php delete mode 100644 includes/pear/Compat/Function/set_include_path.php delete mode 100644 includes/pear/Compat/Function/str_ireplace.php delete mode 100644 includes/pear/Compat/Function/str_shuffle.php delete mode 100644 includes/pear/Compat/Function/str_split.php delete mode 100644 includes/pear/Compat/Function/str_word_count.php delete mode 100644 includes/pear/Compat/Function/stripos.php delete mode 100644 includes/pear/Compat/Function/strpbrk.php delete mode 100644 includes/pear/Compat/Function/strripos.php delete mode 100644 includes/pear/Compat/Function/substr_compare.php delete mode 100644 includes/pear/Image/docs/ChangeLog delete mode 100644 includes/pear/Image/docs/LICENSE delete mode 100644 includes/pear/Image/docs/README delete mode 100644 includes/pear/Image/docs/colors.txt delete mode 100644 includes/pear/Image/docs/examples/antialias.php delete mode 100644 includes/pear/Image/docs/examples/axis_direction.php delete mode 100644 includes/pear/Image/docs/examples/canvas.php delete mode 100644 includes/pear/Image/docs/examples/category_axis_explanation.php delete mode 100644 includes/pear/Image/docs/examples/color_chart.php delete mode 100644 includes/pear/Image/docs/examples/customize.php delete mode 100644 includes/pear/Image/docs/examples/data/colors.txt delete mode 100644 includes/pear/Image/docs/examples/datapreprocessor.php delete mode 100644 includes/pear/Image/docs/examples/double_category_axis.php delete mode 100644 includes/pear/Image/docs/examples/driver_filepdf.php delete mode 100644 includes/pear/Image/docs/examples/driver_pdf.php delete mode 100644 includes/pear/Image/docs/examples/driver_png_svg.php delete mode 100644 includes/pear/Image/docs/examples/driver_swf01.php delete mode 100644 includes/pear/Image/docs/examples/driver_swf02.php delete mode 100644 includes/pear/Image/docs/examples/driver_swf03.php delete mode 100644 includes/pear/Image/docs/examples/frontpage_sample.php delete mode 100644 includes/pear/Image/docs/examples/gradient_fill_area.php delete mode 100644 includes/pear/Image/docs/examples/gradient_pie.php delete mode 100644 includes/pear/Image/docs/examples/gradient_step.php delete mode 100644 includes/pear/Image/docs/examples/horizontal.php delete mode 100644 includes/pear/Image/docs/examples/html_image_map.php delete mode 100644 includes/pear/Image/docs/examples/image_fill.php delete mode 100644 includes/pear/Image/docs/examples/imagemap.png delete mode 100644 includes/pear/Image/docs/examples/images/audi-tt-coupe.jpg delete mode 100644 includes/pear/Image/docs/examples/images/audi.png delete mode 100644 includes/pear/Image/docs/examples/images/bmw.png delete mode 100644 includes/pear/Image/docs/examples/images/coins.png delete mode 100644 includes/pear/Image/docs/examples/images/mercedes.png delete mode 100644 includes/pear/Image/docs/examples/images/modify.jpg delete mode 100644 includes/pear/Image/docs/examples/images/mountain.jpg delete mode 100644 includes/pear/Image/docs/examples/images/porsche.png delete mode 100644 includes/pear/Image/docs/examples/index.html delete mode 100644 includes/pear/Image/docs/examples/layout_matrix.php delete mode 100644 includes/pear/Image/docs/examples/line_break.php delete mode 100644 includes/pear/Image/docs/examples/log_axis.php delete mode 100644 includes/pear/Image/docs/examples/log_axis_intersect.php delete mode 100644 includes/pear/Image/docs/examples/logo_graph.php delete mode 100644 includes/pear/Image/docs/examples/manual_labels.php delete mode 100644 includes/pear/Image/docs/examples/misc01.php delete mode 100644 includes/pear/Image/docs/examples/misc02.php delete mode 100644 includes/pear/Image/docs/examples/misc03.php delete mode 100644 includes/pear/Image/docs/examples/misc04.php delete mode 100644 includes/pear/Image/docs/examples/misc05.php delete mode 100644 includes/pear/Image/docs/examples/misc06.php delete mode 100644 includes/pear/Image/docs/examples/multiple_plots.php delete mode 100644 includes/pear/Image/docs/examples/negative_values.php delete mode 100644 includes/pear/Image/docs/examples/pear-icon.png delete mode 100644 includes/pear/Image/docs/examples/plot_all.php delete mode 100644 includes/pear/Image/docs/examples/plot_all_horizontal.php delete mode 100644 includes/pear/Image/docs/examples/plot_all_horizontal_invert.php delete mode 100644 includes/pear/Image/docs/examples/plot_area.php delete mode 100644 includes/pear/Image/docs/examples/plot_area_smooth.php delete mode 100644 includes/pear/Image/docs/examples/plot_area_stack.php delete mode 100644 includes/pear/Image/docs/examples/plot_band.php delete mode 100644 includes/pear/Image/docs/examples/plot_bar.php delete mode 100644 includes/pear/Image/docs/examples/plot_bar_horizontal.php delete mode 100644 includes/pear/Image/docs/examples/plot_bar_multiple.php delete mode 100644 includes/pear/Image/docs/examples/plot_bar_stacked.php delete mode 100644 includes/pear/Image/docs/examples/plot_bar_stacked100pct.php delete mode 100644 includes/pear/Image/docs/examples/plot_bar_stacked_horizontal.php delete mode 100644 includes/pear/Image/docs/examples/plot_bar_stacked_negative.php delete mode 100644 includes/pear/Image/docs/examples/plot_boxwhisker.php delete mode 100644 includes/pear/Image/docs/examples/plot_candlestick.php delete mode 100644 includes/pear/Image/docs/examples/plot_impulse.php delete mode 100644 includes/pear/Image/docs/examples/plot_impulse_stacked.php delete mode 100644 includes/pear/Image/docs/examples/plot_line.php delete mode 100644 includes/pear/Image/docs/examples/plot_line_smooth.php delete mode 100644 includes/pear/Image/docs/examples/plot_map.php delete mode 100644 includes/pear/Image/docs/examples/plot_odo.php delete mode 100644 includes/pear/Image/docs/examples/plot_pie.php delete mode 100644 includes/pear/Image/docs/examples/plot_pie_rotate.php delete mode 100644 includes/pear/Image/docs/examples/plot_radar.php delete mode 100644 includes/pear/Image/docs/examples/plot_radar_smooth.php delete mode 100644 includes/pear/Image/docs/examples/plot_scatter.php delete mode 100644 includes/pear/Image/docs/examples/plot_scatter_linefit.php delete mode 100644 includes/pear/Image/docs/examples/plot_step.php delete mode 100644 includes/pear/Image/docs/examples/secondary_axis.php delete mode 100644 includes/pear/Image/docs/examples/simple.php delete mode 100644 includes/pear/Image/docs/examples/simple_graph.php delete mode 100644 includes/pear/Image/docs/examples/small_pie_plot.php delete mode 100644 includes/pear/Image/docs/examples/vector_function.php delete mode 100644 includes/pear/Image/tests/README delete mode 100644 includes/pear/Image/tests/axis/category.php delete mode 100644 includes/pear/Image/tests/axis/intersection.php delete mode 100644 includes/pear/Image/tests/axis/intersection_secondary_axis.php delete mode 100644 includes/pear/Image/tests/axis/inversion.php delete mode 100644 includes/pear/Image/tests/axis/labelinterval.php delete mode 100644 includes/pear/Image/tests/axis/logarithmic.php delete mode 100644 includes/pear/Image/tests/canvas_body.php delete mode 100644 includes/pear/Image/tests/freetype.php delete mode 100644 includes/pear/Image/tests/gd.php delete mode 100644 includes/pear/Image/tests/gradients.php delete mode 100644 includes/pear/Image/tests/imagemap.php delete mode 100644 includes/pear/Image/tests/jpg.php delete mode 100644 includes/pear/Image/tests/lineends.php delete mode 100644 includes/pear/Image/tests/pdf.php delete mode 100644 includes/pear/Image/tests/pear-icon.png delete mode 100644 includes/pear/Image/tests/plot/area.php delete mode 100644 includes/pear/Image/tests/plot/bar.php delete mode 100644 includes/pear/Image/tests/plot/horizontal/area.php delete mode 100644 includes/pear/Image/tests/plot/horizontal/bar.php delete mode 100644 includes/pear/Image/tests/plot/horizontal/impulse.php delete mode 100644 includes/pear/Image/tests/plot/horizontal/line.php delete mode 100644 includes/pear/Image/tests/plot/horizontal/step.php delete mode 100644 includes/pear/Image/tests/plot/impulse.php delete mode 100644 includes/pear/Image/tests/plot/line.php delete mode 100644 includes/pear/Image/tests/plot/step.php delete mode 100644 includes/pear/Image/tests/png.php delete mode 100644 includes/pear/Image/tests/svg.php delete mode 100644 includes/pear/Image/tests/text.php create mode 100644 includes/pear/PEAR/FixPHP5PEARWarnings.php create mode 100644 includes/pear/PEAR/Installer/Role/Cfg.php create mode 100644 includes/pear/PEAR/Installer/Role/Cfg.xml create mode 100644 includes/pear/PEAR/Installer/Role/Www.php create mode 100644 includes/pear/PEAR/Installer/Role/Www.xml create mode 100644 includes/pear/PEAR/REST/13.php delete mode 100644 includes/pear/scripts/pear.bat delete mode 100644 includes/pear/scripts/pear.sh delete mode 100644 includes/pear/scripts/pearcmd.php delete mode 100644 includes/pear/scripts/peardev.bat delete mode 100644 includes/pear/scripts/peardev.sh delete mode 100644 includes/pear/scripts/pecl.bat delete mode 100644 includes/pear/scripts/pecl.sh delete mode 100644 includes/pear/scripts/peclcmd.php diff --git a/includes/pear/Compat.php b/includes/pear/Compat.php deleted file mode 100644 index 23e26b5a..00000000 --- a/includes/pear/Compat.php +++ /dev/null @@ -1,133 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: Compat.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Provides missing functionality in the form of constants and functions - * for older versions of PHP - * - * Optionally, you may simply include the file. - * e.g. require_once 'PHP/Compat/Function/scandir.php'; - * - * @category PHP - * @package PHP_Compat - * @version $Revision: 1.1 $ - * @author Aidan Lister - * @static - */ -class PHP_Compat -{ - /** - * Load a function, or array of functions - * - * @param string|array $function The function or functions to load - * @return bool|array TRUE if loaded, FALSE if not - */ - function loadFunction($function) - { - // Recursiveness - if (is_array($function)) { - $res = array(); - foreach ($function as $singlefunc) { - $res[$singlefunc] = PHP_Compat::loadFunction($singlefunc); - } - - return $res; - } - - // Load function - if (!function_exists($function)) { - $file = sprintf('PHP/Compat/Function/%s.php', $function); - if ((@include_once $file) !== false) { - return true; - } - } - - return false; - } - - - /** - * Load a constant, or array of constants - * - * @param string|array $constant The constant or constants to load - * @return bool|array TRUE if loaded, FALSE if not - */ - function loadConstant($constant) - { - // Recursiveness - if (is_array($constant)) { - $res = array(); - foreach ($constant as $singleconst) { - $res[$singleconst] = PHP_Compat::loadConstant($singleconst); - } - - return $res; - } - - // Load constant - $file = sprintf('PHP/Compat/Constant/%s.php', $constant); - if ((@include_once $file) !== false) { - return true; - } - - return false; - } - - - /** - * Load components for a PHP version - * - * @param string $version PHP Version to load - * @return array An associative array of component names loaded - */ - function loadVersion($version = null) - { - // Include list of components - require 'PHP/Compat/Components.php'; - - // Include version_compare to work with older versions - PHP_Compat::loadFunction('version_compare'); - - // Init - $phpversion = phpversion(); - $methods = array( - 'function' => 'loadFunction', - 'constant' => 'loadConstant'); - $res = array(); - - // Iterate each component - foreach ($components as $type => $slice) { - foreach ($slice as $component => $compversion) { - if (($version === null && - 1 === version_compare($compversion, $phpversion)) || // C > PHP - (0 === version_compare($compversion, $version) || // C = S - 1 === version_compare($compversion, $phpversion))) { // C > PHP - - $res[$type][$component] = - call_user_func(array('PHP_Compat', $methods[$type]), $component); - } - } - } - - return $res; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Components.php b/includes/pear/Compat/Components.php deleted file mode 100644 index bb0814dc..00000000 --- a/includes/pear/Compat/Components.php +++ /dev/null @@ -1,71 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: Components.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -// Functions -$components['function']['array_combine'] = '5.0.0'; -$components['function']['array_diff_assoc'] = '4.3.0'; -$components['function']['array_diff_key'] = '5.0.2'; -$components['function']['array_diff_ukey'] = '5.0.2'; -$components['function']['array_intersect_assoc'] = '5.0.0'; -$components['function']['array_intersect_key'] = '5.0.2'; -$components['function']['array_intersect_uassoc'] = '5.0.0'; -$components['function']['array_intersect_ukey'] = '5.0.2'; -$components['function']['array_udiff'] = '5.0.0'; -$components['function']['array_udiff_assoc'] = '5.0.0'; -$components['function']['array_udiff_uassoc'] = '5.0.0'; -$components['function']['array_uintersect'] = '5.0.0'; -$components['function']['array_uintersect_assoc'] = '5.0.0'; -$components['function']['array_uintersect_uassoc'] = '5.0.0'; -$components['function']['array_walk_recursive'] = '5.0.0'; -$components['function']['clone'] = '5.0.0'; -$components['function']['convert_uudecode'] = '5.0.0'; -$components['function']['convert_uuencode'] = '5.0.0'; -$components['function']['debug_print_backtrace'] = '5.0.0'; -$components['function']['file_get_contents'] = '4.3.0'; -$components['function']['file_put_contents'] = '5.0.0'; -$components['function']['fprintf'] = '5.0.0'; -$components['function']['get_headers'] = '5.0.0'; -$components['function']['get_include_path'] = '4.3.0'; -$components['function']['html_entity_decode'] = '4.3.0'; -$components['function']['http_build_query'] = '5.0.0'; -$components['function']['image_type_to_mime_type'] = '4.3.0'; -$components['function']['ob_get_clean'] = '4.3.0'; -$components['function']['ob_get_flush'] = '4.3.0'; -$components['function']['php_strip_whitespace'] = '5.0.0'; -$components['function']['restore_include_path'] = '4.3.0'; -$components['function']['scandir'] = '5.0.0'; -$components['function']['set_include_path'] = '4.3.0'; -$components['function']['str_ireplace'] = '5.0.0'; -$components['function']['str_shuffle'] = '4.3.0'; -$components['function']['str_split'] = '5.0.0'; -$components['function']['str_word_count'] = '4.3.0'; -$components['function']['stripos'] = '5.0.0'; -$components['function']['strpbrk'] = '5.0.0'; -$components['function']['strripos'] = '5.0.0'; -$components['function']['substr_compare'] = '5.0.0'; - -// Constants -$components['constant']['E_STRICT'] = '5.0.0'; -$components['constant']['FILE'] = '4.3.0'; -$components['constant']['PHP_EOL'] = '5.0.1'; -$components['constant']['STD'] = '4.3.0'; -$components['constant']['T'] = '5.0.0'; -$components['constant']['UPLOAD_ERR'] = '4.3.0'; -?> \ No newline at end of file diff --git a/includes/pear/Compat/Constant/E_STRICT.php b/includes/pear/Compat/Constant/E_STRICT.php deleted file mode 100644 index 9f1d2693..00000000 --- a/includes/pear/Compat/Constant/E_STRICT.php +++ /dev/null @@ -1,35 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: E_STRICT.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace constant E_STRICT - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/ref.errorfunc - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5 - */ -if (!defined('E_STRICT')) { - define('E_STRICT', 2048); -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Constant/FILE.php b/includes/pear/Compat/Constant/FILE.php deleted file mode 100644 index e70a6210..00000000 --- a/includes/pear/Compat/Constant/FILE.php +++ /dev/null @@ -1,51 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: FILE.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace filesystem constants - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/ref.filesystem - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5 - */ -if (!defined('FILE_USE_INCLUDE_PATH')) { - define('FILE_USE_INCLUDE_PATH', 1); -} - -if (!defined('FILE_IGNORE_NEW_LINES')) { - define('FILE_IGNORE_NEW_LINES', 2); -} - -if (!defined('FILE_SKIP_EMPTY_LINES')) { - define('FILE_SKIP_EMPTY_LINES', 4); -} - -if (!defined('FILE_APPEND')) { - define('FILE_APPEND', 8); -} - -if (!defined('FILE_NO_DEFAULT_CONTEXT')) { - define('FILE_NO_DEFAULT_CONTEXT', 16); -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Constant/PHP_EOL.php b/includes/pear/Compat/Constant/PHP_EOL.php deleted file mode 100644 index 2d4d87f0..00000000 --- a/includes/pear/Compat/Constant/PHP_EOL.php +++ /dev/null @@ -1,49 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: PHP_EOL.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace PHP_EOL constant - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/reserved.constants.core - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5.0.2 - */ -if (!defined('PHP_EOL')) { - switch (strtoupper(substr(PHP_OS, 0, 3))) { - // Windows - case 'WIN': - define('PHP_EOL', "\r\n"); - break; - - // Mac - case 'DAR': - define('PHP_EOL', "\r"); - break; - - // Unix - default: - define('PHP_EOL', "\n"); - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Constant/STD.php b/includes/pear/Compat/Constant/STD.php deleted file mode 100644 index 3488b987..00000000 --- a/includes/pear/Compat/Constant/STD.php +++ /dev/null @@ -1,43 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: STD.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace commandline constants - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/features.commandline - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 4.3.0 - */ -if (!defined('STDIN')) { - define('STDIN', fopen('php://stdin', 'r')); -} - -if (!defined('STDOUT')) { - define('STDOUT', fopen('php://stdout', 'w')); -} - -if (!defined('STDERR')) { - define('STDERR', fopen('php://stderr', 'w')); -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Constant/T.php b/includes/pear/Compat/Constant/T.php deleted file mode 100644 index 1c3143c6..00000000 --- a/includes/pear/Compat/Constant/T.php +++ /dev/null @@ -1,72 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: T.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace tokenizer constants - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/ref.tokenizer - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5 - */ -if (!defined('T_ML_COMMENT')) { - define('T_ML_COMMENT', T_COMMENT); -} -if (!defined('T_DOC_COMMENT')) { - define('T_DOC_COMMENT', T_ML_COMMENT); -} - -if (!defined('T_OLD_FUNCTION')) { - define('T_OLD_FUNCTION', -1); -} -if (!defined('T_ABSTRACT')) { - define('T_ABSTRACT', -1); -} -if (!defined('T_CATCH')) { - define('T_CATCH', -1); -} -if (!defined('T_FINAL')) { - define('T_FINAL', -1); -} -if (!defined('T_INSTANCEOF')) { - define('T_INSTANCEOF', -1); -} -if (!defined('T_PRIVATE')) { - define('T_PRIVATE', -1); -} -if (!defined('T_PROTECTED')) { - define('T_PROTECTED', -1); -} -if (!defined('T_PUBLIC')) { - define('T_PUBLIC', -1); -} -if (!defined('T_THROW')) { - define('T_THROW', -1); -} -if (!defined('T_TRY')) { - define('T_TRY', -1); -} -if (!defined('T_CLONE')) { - define('T_CLONE', -1); -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Constant/UPLOAD_ERR.php b/includes/pear/Compat/Constant/UPLOAD_ERR.php deleted file mode 100644 index 2bcb9469..00000000 --- a/includes/pear/Compat/Constant/UPLOAD_ERR.php +++ /dev/null @@ -1,51 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: UPLOAD_ERR.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace upload error constants - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/features.file-upload.errors - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 4.3.0 - */ -if (!defined('UPLOAD_ERR_OK')) { - define('UPLOAD_ERR_OK', 0); -} - -if (!defined('UPLOAD_ERR_INI_SIZE')) { - define('UPLOAD_ERR_INI_SIZE', 1); -} - -if (!defined('UPLOAD_ERR_FORM_SIZE')) { - define('UPLOAD_ERR_FORM_SIZE', 2); -} - -if (!defined('UPLOAD_ERR_PARTIAL')) { - define('UPLOAD_ERR_PARTIAL', 3); -} - -if (!defined('UPLOAD_ERR_NO_FILE')) { - define('UPLOAD_ERR_NO_FILE', 4); -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/array_combine.php b/includes/pear/Compat/Function/array_combine.php deleted file mode 100644 index dc1d7227..00000000 --- a/includes/pear/Compat/Function/array_combine.php +++ /dev/null @@ -1,71 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: array_combine.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace array_combine() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.array_combine - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5 - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('array_combine')) { - function array_combine($keys, $values) - { - if (!is_array($keys)) { - user_error('array_combine() expects parameter 1 to be array, ' . - gettype($keys) . ' given', E_USER_WARNING); - return; - } - - if (!is_array($values)) { - user_error('array_combine() expects parameter 2 to be array, ' . - gettype($values) . ' given', E_USER_WARNING); - return; - } - - $key_count = count($keys); - $value_count = count($values); - if ($key_count !== $value_count) { - user_error('array_combine() Both parameters should have equal number of elements', E_USER_WARNING); - return false; - } - - if ($key_count === 0 || $value_count === 0) { - user_error('array_combine() Both parameters should have number of elements at least 0', E_USER_WARNING); - return false; - } - - $keys = array_values($keys); - $values = array_values($values); - - $combined = array(); - for ($i = 0; $i < $key_count; $i++) { - $combined[$keys[$i]] = $values[$i]; - } - - return $combined; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/array_diff_assoc.php b/includes/pear/Compat/Function/array_diff_assoc.php deleted file mode 100644 index f215b262..00000000 --- a/includes/pear/Compat/Function/array_diff_assoc.php +++ /dev/null @@ -1,75 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: array_diff_assoc.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace array_diff_assoc() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.array_diff_assoc - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 4.3.0 - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('array_diff_assoc')) { - function array_diff_assoc() - { - // Check we have enough arguments - $args = func_get_args(); - $count = count($args); - if (count($args) < 2) { - user_error('Wrong parameter count for array_diff_assoc()', E_USER_WARNING); - return; - } - - // Check arrays - for ($i = 0; $i < $count; $i++) { - if (!is_array($args[$i])) { - user_error('array_diff_assoc() Argument #' . - ($i + 1) . ' is not an array', E_USER_WARNING); - return; - } - } - - // Get the comparison array - $array_comp = array_shift($args); - --$count; - - // Traverse values of the first array - foreach ($array_comp as $key => $value) { - // Loop through the other arrays - for ($i = 0; $i < $count; $i++) { - // Loop through this arrays key/value pairs and compare - foreach ($args[$i] as $comp_key => $comp_value) { - if ((string)$key === (string)$comp_key && - (string)$value === (string)$comp_value) - { - - unset($array_comp[$key]); - } - } - } - } - - return $array_comp; - } -} -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/array_diff_key.php b/includes/pear/Compat/Function/array_diff_key.php deleted file mode 100644 index 1ed9a3fa..00000000 --- a/includes/pear/Compat/Function/array_diff_key.php +++ /dev/null @@ -1,66 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: array_diff_key.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace array_diff_key() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.array_diff_key - * @author Tom Buskens - * @version $Revision: 1.1 $ - * @since PHP 5.0.2 - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('array_diff_key')) { - function array_diff_key() - { - $args = func_get_args(); - if (count($args) < 2) { - user_error('Wrong parameter count for array_diff_key()', E_USER_WARNING); - return; - } - - // Check arrays - $array_count = count($args); - for ($i = 0; $i !== $array_count; $i++) { - if (!is_array($args[$i])) { - user_error('array_diff_key() Argument #' . - ($i + 1) . ' is not an array', E_USER_WARNING); - return; - } - } - - $result = $args[0]; - foreach ($args[0] as $key1 => $value1) { - for ($i = 1; $i !== $array_count; $i++) { - foreach ($args[$i] as $key2 => $value2) { - if ((string) $key1 === (string) $key2) { - unset($result[$key2]); - break 2; - } - } - } - } - return $result; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/array_diff_uassoc.php b/includes/pear/Compat/Function/array_diff_uassoc.php deleted file mode 100644 index 5904e3af..00000000 --- a/includes/pear/Compat/Function/array_diff_uassoc.php +++ /dev/null @@ -1,83 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: array_diff_uassoc.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace array_diff_uassoc() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.array_diff_uassoc - * @version $Revision: 1.1 $ - * @since PHP 5.0.0 - * @require PHP 4.0.6 (is_callable) - */ -if (!function_exists('array_diff_uassoc')) { - function array_diff_uassoc() - { - // Sanity check - $args = func_get_args(); - if (count($args) < 3) { - user_error('Wrong parameter count for array_diff_uassoc()', E_USER_WARNING); - return; - } - - // Get compare function - $compare_func = array_pop($args); - if (!is_callable($compare_func)) { - if (is_array($compare_func)) { - $compare_func = $compare_func[0] . '::' . $compare_func[1]; - } - user_error('array_diff_uassoc() Not a valid callback ' . - $compare_func, E_USER_WARNING); - return; - } - - // Check arrays - $array_count = count($args); - for ($i = 0; $i !== $array_count; $i++) { - if (!is_array($args[$i])) { - user_error('array_diff_uassoc() Argument #' . - ($i + 1) . ' is not an array', E_USER_WARNING); - return; - } - } - - // Compare entries - $result = array(); - foreach ($args[0] as $k => $v) { - for ($i = 1; $i < $array_count; $i++) { - foreach ($args[$i] as $kk => $vv) { - if ($v == $vv) { - $compare = call_user_func_array($compare_func, array($k, $kk)); - if ($compare == 0) { - continue 3; - } - } - } - } - - $result[$k] = $v; - } - - return $result; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/array_diff_ukey.php b/includes/pear/Compat/Function/array_diff_ukey.php deleted file mode 100644 index 3272a26c..00000000 --- a/includes/pear/Compat/Function/array_diff_ukey.php +++ /dev/null @@ -1,79 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: array_diff_ukey.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace array_diff_ukey() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.array_diff_ukey - * @author Tom Buskens - * @version $Revision: 1.1 $ - * @since PHP 5.0.2 - * @require PHP 4.0.6 (is_callable) - */ -if (!function_exists('array_diff_ukey')) { - function array_diff_ukey() - { - $args = func_get_args(); - if (count($args) < 3) { - user_error('Wrong parameter count for array_diff_ukey()', E_USER_WARNING); - return; - } - - // Get compare function - $compare_func = array_pop($args); - if (!is_callable($compare_func)) { - if (is_array($compare_func)) { - $compare_func = $compare_func[0].'::'.$compare_func[1]; - } - user_error('array_diff_ukey() Not a valid callback ' . - $compare_func, E_USER_WARNING); - return; - } - - // Check arrays - $array_count = count($args); - for ($i = 0; $i !== $array_count; $i++) { - if (!is_array($args[$i])) { - user_error('array_diff_ukey() Argument #' . - ($i + 1) . ' is not an array', E_USER_WARNING); - return; - } - } - - // Compare entries - $result = $args[0]; - foreach ($args[0] as $key1 => $value1) { - for ($i = 1; $i !== $array_count; $i++) { - foreach ($args[$i] as $key2 => $value2) { - if (!(call_user_func($compare_func, (string) $key1, (string) $key2))) { - unset($result[$key1]); - break 2; - } - } - } - } - - return $result; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/array_intersect_assoc.php b/includes/pear/Compat/Function/array_intersect_assoc.php deleted file mode 100644 index 20522485..00000000 --- a/includes/pear/Compat/Function/array_intersect_assoc.php +++ /dev/null @@ -1,69 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: array_intersect_assoc.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace array_intersect_assoc() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.array_intersect_assoc - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 4.3.0 - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('array_intersect_assoc')) { - function array_intersect_assoc() - { - // Sanity check - $args = func_get_args(); - if (count($args) < 2) { - user_error('wrong parameter count for array_intersect_assoc()', E_USER_WARNING); - return; - } - - // Check arrays - $array_count = count($args); - for ($i = 0; $i !== $array_count; $i++) { - if (!is_array($args[$i])) { - user_error('array_intersect_assoc() Argument #' . - ($i + 1) . ' is not an array', E_USER_WARNING); - return; - } - } - - // Compare entries - $intersect = array(); - foreach ($args[0] as $key => $value) { - $intersect[$key] = $value; - - for ($i = 1; $i < $array_count; $i++) { - if (!isset($args[$i][$key]) || $args[$i][$key] != $value) { - unset($intersect[$key]); - break; - } - } - } - - return $intersect; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/array_intersect_key.php b/includes/pear/Compat/Function/array_intersect_key.php deleted file mode 100644 index 84224c61..00000000 --- a/includes/pear/Compat/Function/array_intersect_key.php +++ /dev/null @@ -1,67 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: array_intersect_key.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace array_intersect_key() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.array_intersect_key - * @author Tom Buskens - * @version $Revision: 1.1 $ - * @since PHP 5.0.2 - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('array_intersect_key')) { - function array_intersect_key() - { - $args = func_get_args(); - if (count($args) < 2) { - user_error('Wrong parameter count for array_intersect_key()', E_USER_WARNING); - return; - } - - // Check arrays - $array_count = count($args); - for ($i = 0; $i !== $array_count; $i++) { - if (!is_array($args[$i])) { - user_error('array_intersect_key() Argument #' . - ($i + 1) . ' is not an array', E_USER_WARNING); - return; - } - } - - // Compare entries - $result = array(); - foreach ($args[0] as $key1 => $value1) { - for ($i = 1; $i !== $array_count; $i++) { - foreach ($args[$i] as $key2 => $value2) { - if ((string) $key1 === (string) $key2) { - $result[$key1] = $value1; - } - } - } - } - - return $result; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/array_intersect_uassoc.php b/includes/pear/Compat/Function/array_intersect_uassoc.php deleted file mode 100644 index 9540563f..00000000 --- a/includes/pear/Compat/Function/array_intersect_uassoc.php +++ /dev/null @@ -1,90 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: array_intersect_uassoc.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace array_intersect_assoc() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.array_intersect_uassoc - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5 - * @require PHP 4.0.6 (is_callable) - */ -if (!function_exists('array_intersect_uassoc')) { - function array_intersect_uassoc() - { - // Sanity check - $args = func_get_args(); - if (count($args) < 3) { - user_error('Wrong parameter count for array_intersect_ukey()', E_USER_WARNING); - return; - } - - // Get compare function - $compare_func = array_pop($args); - if (!is_callable($compare_func)) { - if (is_array($compare_func)) { - $compare_func = $compare_func[0] . '::' . $compare_func[1]; - } - user_error('array_intersect_uassoc() Not a valid callback ' . - $compare_func, E_USER_WARNING); - return; - } - - // Check arrays - $array_count = count($args); - for ($i = 0; $i !== $array_count; $i++) { - if (!is_array($args[$i])) { - user_error('array_intersect_uassoc() Argument #' . - ($i + 1) . ' is not an array', E_USER_WARNING); - return; - } - } - - // Compare entries - $result = array(); - foreach ($args[0] as $k => $v) { - for ($i = 0; $i < $array_count; $i++) { - $match = false; - foreach ($args[$i] as $kk => $vv) { - $compare = call_user_func_array($compare_func, array($k, $kk)); - if ($compare === 0 && $v == $vv) { - $match = true; - continue 2; - } - } - - if ($match === false) { - continue 2; - } - } - - if ($match === true) { - $result[$k] = $v; - } - } - - return $result; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/array_intersect_ukey.php b/includes/pear/Compat/Function/array_intersect_ukey.php deleted file mode 100644 index 17d1f01d..00000000 --- a/includes/pear/Compat/Function/array_intersect_ukey.php +++ /dev/null @@ -1,79 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: array_intersect_ukey.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace array_intersect_ukey() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.array_intersect_ukey - * @author Tom Buskens - * @version $Revision: 1.1 $ - * @since PHP 5.0.2 - * @require PHP 4.0.6 (is_callable) - */ -if (!function_exists('array_intersect_ukey')) { - function array_intersect_ukey() - { - $args = func_get_args(); - if (count($args) < 3) { - user_error('Wrong parameter count for array_intersect_ukey()', E_USER_WARNING); - return; - } - - // Get compare function - $compare_func = array_pop($args); - if (!is_callable($compare_func)) { - if (is_array($compare_func)) { - $compare_func = $compare_func[0].'::'.$compare_func[1]; - } - user_error('array_diff_ukey() Not a valid callback ' . - $compare_func, E_USER_WARNING); - return; - } - - // Check arrays - $array_count = count($args); - for ($i = 0; $i !== $array_count; $i++) { - if (!is_array($args[$i])) { - user_error('array_intersect_ukey() Argument #' . - ($i + 1) . ' is not an array', E_USER_WARNING); - return; - } - } - - // Compare entries - $result = array(); - foreach ($args[0] as $key1 => $value1) { - for ($i = 1; $i !== $array_count; $i++) { - foreach ($args[$i] as $key2 => $value2) { - if (!(call_user_func($compare_func, (string) $key1, (string) $key2))) { - $result[$key1] = $value1; - break 2; - } - } - } - } - - return $result; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/array_udiff.php b/includes/pear/Compat/Function/array_udiff.php deleted file mode 100644 index db716bf4..00000000 --- a/includes/pear/Compat/Function/array_udiff.php +++ /dev/null @@ -1,83 +0,0 @@ - | -// | Aidan Lister | -// +----------------------------------------------------------------------+ -// -// $Id: array_udiff.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace array_udiff() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.array_udiff - * @author Stephan Schmidt - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5 - * @require PHP 4.0.6 (is_callable) - */ -if (!function_exists('array_udiff')) { - function array_udiff() - { - $args = func_get_args(); - - if (count($args) < 3) { - user_error('Wrong parameter count for array_udiff()', E_USER_WARNING); - return; - } - - // Get compare function - $compare_func = array_pop($args); - if (!is_callable($compare_func)) { - if (is_array($compare_func)) { - $compare_func = $compare_func[0] . '::' . $compare_func[1]; - } - user_error('array_udiff() Not a valid callback ' . - $compare_func, E_USER_WARNING); - return; - } - - // Check arrays - $cnt = count($args); - for ($i = 0; $i < $cnt; $i++) { - if (!is_array($args[$i])) { - user_error('array_udiff() Argument #' . - ($i + 1). ' is not an array', E_USER_WARNING); - return; - } - } - - $diff = array (); - // Traverse values of the first array - foreach ($args[0] as $key => $value) { - // Check all arrays - for ($i = 1; $i < $cnt; $i++) { - foreach ($args[$i] as $cmp_value) { - $result = call_user_func($compare_func, $value, $cmp_value); - if ($result === 0) { - continue 3; - } - } - } - $diff[$key] = $value; - } - return $diff; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/array_udiff_assoc.php b/includes/pear/Compat/Function/array_udiff_assoc.php deleted file mode 100644 index ad62507c..00000000 --- a/includes/pear/Compat/Function/array_udiff_assoc.php +++ /dev/null @@ -1,85 +0,0 @@ - | -// | Aidan Lister | -// +----------------------------------------------------------------------+ -// -// $Id: array_udiff_assoc.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace array_udiff_assoc() - * - * @category PHP - * @package PHP_Compat - * @author Stephan Schmidt - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @link http://php.net/function.array-udiff-assoc - * @since PHP 5 - * @require PHP 4.0.6 (is_callable) - */ -if (!function_exists('array_udiff_assoc')) { - function array_udiff_assoc() - { - $args = func_get_args(); - if (count($args) < 3) { - user_error('Wrong parameter count for array_udiff_assoc()', E_USER_WARNING); - return; - } - - // Get compare function - $compare_func = array_pop($args); - if (!is_callable($compare_func)) { - if (is_array($compare_func)) { - $compare_func = $compare_func[0] . '::' . $compare_func[1]; - } - user_error('array_udiff_assoc() Not a valid callback ' . - $compare_func, E_USER_WARNING); - return; - } - - // Check arrays - $count = count($args); - for ($i = 0; $i < $count; $i++) { - if (!is_array($args[$i])) { - user_error('array_udiff_assoc() Argument #' . - ($i + 1) . ' is not an array', E_USER_WARNING); - return; - } - } - - $diff = array (); - // Traverse values of the first array - foreach ($args[0] as $key => $value) { - // Check all arrays - for ($i = 1; $i < $count; $i++) { - if (!array_key_exists($key, $args[$i])) { - continue; - } - $result = call_user_func($compare_func, $value, $args[$i][$key]); - if ($result === 0) { - continue 2; - } - } - - $diff[$key] = $value; - } - - return $diff; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/array_udiff_uassoc.php b/includes/pear/Compat/Function/array_udiff_uassoc.php deleted file mode 100644 index 6cc8338d..00000000 --- a/includes/pear/Compat/Function/array_udiff_uassoc.php +++ /dev/null @@ -1,82 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: array_udiff_uassoc.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace array_udiff_uassoc() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.array_udiff_uassoc - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5 - * @require PHP 4.0.6 (is_callable) - */ -if (!function_exists('array_udiff_uassoc')) { - function array_udiff_uassoc() - { - $args = func_get_args(); - if (count($args) < 3) { - user_error('Wrong parameter count for array_udiff_uassoc()', E_USER_WARNING); - return; - } - - // Get compare function - $compare_func = array_pop($args); - if (!is_callable($compare_func)) { - if (is_array($compare_func)) { - $compare_func = $compare_func[0] . '::' . $compare_func[1]; - } - user_error('array_udiff_uassoc() Not a valid callback ' . $compare_func, E_USER_WARNING); - return; - } - - // Check arrays - $count = count($args); - for ($i = 0; $i < $count; $i++) { - if (!is_array($args[$i])) { - user_error('array_udiff_uassoc() Argument #' . - ($i + 1) . ' is not an array', E_USER_WARNING); - return; - } - } - - // Traverse values of the first array - $diff = array (); - foreach ($args[0] as $key => $value) { - // Check all arrays - for ($i = 1; $i < $count; $i++) { - if (!array_key_exists($key, $args[$i])) { - continue; - } - $result = call_user_func($compare_func, $value, $args[$i][$key]); - if ($result === 0) { - continue 2; - } - } - - $diff[$key] = $value; - } - - return $diff; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/array_uintersect.php b/includes/pear/Compat/Function/array_uintersect.php deleted file mode 100644 index baa079fd..00000000 --- a/includes/pear/Compat/Function/array_uintersect.php +++ /dev/null @@ -1,82 +0,0 @@ - | -// | Aidan Lister | -// +----------------------------------------------------------------------+ -// -// $Id: array_uintersect.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace array_uintersect() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.array_uintersect - * @author Tom Buskens - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5 - * @require PHP 4.0.6 (is_callable) - */ -if (!function_exists('array_uintersect')) { - function array_uintersect() - { - $args = func_get_args(); - if (count($args) < 3) { - user_error('wrong parameter count for array_uintersect()', - E_USER_WARNING); - return; - } - - // Get compare function - $user_func = array_pop($args); - if (!is_callable($user_func)) { - if (is_array($user_func)) { - $user_func = $user_func[0] . '::' . $user_func[1]; - } - user_error('array_uintersect() Not a valid callback ' . - $user_func, E_USER_WARNING); - return; - } - - // Check arrays - $array_count = count($args); - for ($i = 0; $i < $array_count; $i++) { - if (!is_array($args[$i])) { - user_error('array_uintersect() Argument #' . - ($i + 1) . ' is not an array', E_USER_WARNING); - return; - } - } - - // Compare entries - $output = array(); - foreach ($args[0] as $key => $item) { - for ($i = 1; $i !== $array_count; $i++) { - $array = $args[$i]; - foreach($array as $key0 => $item0) { - if (!call_user_func($user_func, $item, $item0)) { - $output[$key] = $item; - } - } - } - } - - return $output; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/array_uintersect_assoc.php b/includes/pear/Compat/Function/array_uintersect_assoc.php deleted file mode 100644 index 8f5f1a7b..00000000 --- a/includes/pear/Compat/Function/array_uintersect_assoc.php +++ /dev/null @@ -1,81 +0,0 @@ - | -// | Aidan Lister | -// +----------------------------------------------------------------------+ -// -// $Id: array_uintersect_assoc.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace array_uintersect_assoc() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.array_uintersect_assoc - * @author Tom Buskens - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5 - * @require PHP 4.0.6 (is_callable) - */ -if (!function_exists('array_uintersect_assoc')) { - function array_uintersect_assoc() - { - $args = func_get_args(); - if (count($args) < 3) { - user_error('wrong parameter count for array_uintersect_assoc()', E_USER_WARNING); - return; - } - - // Get compare function - $user_func = array_pop($args); - if (!is_callable($user_func)) { - if (is_array($user_func)) { - $user_func = $user_func[0] . '::' . $user_func[1]; - } - user_error('array_uintersect_assoc() Not a valid callback ' . - $user_func, E_USER_WARNING); - return; - } - - // Check arrays - $array_count = count($args); - for ($i = 0; $i < $array_count; $i++) { - if (!is_array($args[$i])) { - user_error('array_uintersect_assoc() Argument #' . - ($i + 1) . ' is not an array', E_USER_WARNING); - return; - } - } - - // Compare entries - $output = array(); - foreach ($args[0] as $key => $item) { - for ($i = 1; $i !== $array_count; $i++) { - if (array_key_exists($key, $args[$i])) { - $compare = call_user_func($user_func, $item, $args[$i][$key]); - if ($compare === 0) { - $output[$key] = $item; - } - } - } - } - - return $output; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/array_uintersect_uassoc.php b/includes/pear/Compat/Function/array_uintersect_uassoc.php deleted file mode 100644 index c3ec7faa..00000000 --- a/includes/pear/Compat/Function/array_uintersect_uassoc.php +++ /dev/null @@ -1,97 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: array_uintersect_uassoc.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace array_uintersect_uassoc() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.array_uintersect_uassoc - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5 - * @require PHP 4.0.6 (is_callable) - */ -if (!function_exists('array_uintersect_uassoc')) { - function array_uintersect_uassoc() - { - $args = func_get_args(); - if (count($args) < 4) { - user_error('Wrong parameter count for array_uintersect_uassoc()', - E_USER_WARNING); - return; - } - - // Get key_compare_func - $key_compare_func = array_pop($args); - if (!is_callable($key_compare_func)) { - if (is_array($key_compare_func)) { - $key_compare_func = $key_compare_func[0] . '::' . $key_compare_func[1]; - } - user_error('array_uintersect_uassoc() Not a valid callback ' . - $key_compare_func, E_USER_WARNING); - return; - } - - // Get data_compare_func - $data_compare_func = array_pop($args); - if (!is_callable($data_compare_func)) { - if (is_array($data_compare_func)) { - $data_compare_func = $data_compare_func[0] . '::' . $data_compare_func[1]; - } - user_error('array_uintersect_uassoc() Not a valid callback ' - . $data_compare_func, E_USER_WARNING); - return; - } - - // Check arrays - $count = count($args); - for ($i = 0; $i !== $count; $i++) { - if (!is_array($args[$i])) { - user_error('array_uintersect_uassoc() Argument #' . - ($i + 1) . ' is not an array', E_USER_WARNING); - return; - } - } - - // Traverse values of the first array - $intersect = array (); - foreach ($args[0] as $key => $value) { - // Check against each array - for ($i = 1; $i < $count; $i++) { - // Traverse each element in current array - foreach ($args[$i] as $ckey => $cvalue) { - // Compare key and value - if (call_user_func($key_compare_func, $key, $ckey) === 0 && - call_user_func($data_compare_func, $value, $cvalue) === 0) - { - - $intersect[$key] = $value; - continue; - } - } - } - } - - return $intersect; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/array_walk_recursive.php b/includes/pear/Compat/Function/array_walk_recursive.php deleted file mode 100644 index b37c7d77..00000000 --- a/includes/pear/Compat/Function/array_walk_recursive.php +++ /dev/null @@ -1,68 +0,0 @@ - | -// | Aidan Lister | -// +----------------------------------------------------------------------+ -// -// $Id: array_walk_recursive.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace array_walk_recursive() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.array_walk_recursive - * @author Tom Buskens - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5 - * @require PHP 4.0.6 (is_callable) - */ -if (!function_exists('array_walk_recursive')) { - function array_walk_recursive(&$input, $funcname) - { - if (!is_callable($funcname)) { - if (is_array($funcname)) { - $funcname = $funcname[0] . '::' . $funcname[1]; - } - user_error('array_walk_recursive() Not a valid callback ' . $user_func, - E_USER_WARNING); - return; - } - - if (!is_array($input)) { - user_error('array_walk_recursive() The argument should be an array', - E_USER_WARNING); - return; - } - - $args = func_get_args(); - - foreach ($input as $key => $item) { - if (is_array($item)) { - array_walk_recursive($item, $funcname, $args); - $input[$key] = $item; - } else { - $args[0] = &$item; - $args[1] = &$key; - call_user_func_array($funcname, $args); - $input[$key] = $item; - } - } - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/clone.php b/includes/pear/Compat/Function/clone.php deleted file mode 100644 index 84a4c11a..00000000 --- a/includes/pear/Compat/Function/clone.php +++ /dev/null @@ -1,56 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: clone.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace clone() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/language.oop5.cloning - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5.0.0 - * @require PHP 4.0.0 (user_error) - */ -if (version_compare(phpversion(), '5.0') === -1) { - // Needs to be wrapped in eval as clone is a keyword in PHP5 - eval(' - function clone($object) - { - // Sanity check - if (!is_object($object)) { - user_error(\'clone() __clone method called on non-object\', E_USER_WARNING); - return; - } - - // Use serialize/unserialize trick to deep copy the object - $object = unserialize(serialize($object)); - - // If there is a __clone method call it on the "new" class - if (method_exists($object, \'__clone\')) { - $object->__clone(); - } - - return $object; - } - '); -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/convert_uudecode.php b/includes/pear/Compat/Function/convert_uudecode.php deleted file mode 100644 index 0180f534..00000000 --- a/includes/pear/Compat/Function/convert_uudecode.php +++ /dev/null @@ -1,79 +0,0 @@ - | -// | Aidan Lister | -// +----------------------------------------------------------------------+ -// -// $Id: convert_uudecode.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace convert_uudecode() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.convert_uudecode - * @author Michael Wallner - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5 - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('convert_uudecode')) { - function convert_uudecode($string) - { - // Sanity check - if (!is_scalar($string)) { - user_error('convert_uuencode() expects parameter 1 to be string, ' . - gettype($string) . ' given', E_USER_WARNING); - return false; - } - - if (strlen($string) < 8) { - user_error('convert_uuencode() The given parameter is not a valid uuencoded string', E_USER_WARNING); - return false; - } - - $decoded = ''; - foreach (explode("\n", $string) as $line) { - - $c = count($bytes = unpack('c*', substr(trim($line), 1))); - - while ($c % 4) { - $bytes[++$c] = 0; - } - - foreach (array_chunk($bytes, 4) as $b) { - $b0 = $b[0] == 0x60 ? 0 : $b[0] - 0x20; - $b1 = $b[1] == 0x60 ? 0 : $b[1] - 0x20; - $b2 = $b[2] == 0x60 ? 0 : $b[2] - 0x20; - $b3 = $b[3] == 0x60 ? 0 : $b[3] - 0x20; - - $b0 <<= 2; - $b0 |= ($b1 >> 4) & 0x03; - $b1 <<= 4; - $b1 |= ($b2 >> 2) & 0x0F; - $b2 <<= 6; - $b2 |= $b3 & 0x3F; - - $decoded .= pack('c*', $b0, $b1, $b2); - } - } - - return rtrim($decoded, "\0"); - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/convert_uuencode.php b/includes/pear/Compat/Function/convert_uuencode.php deleted file mode 100644 index d1ec04b1..00000000 --- a/includes/pear/Compat/Function/convert_uuencode.php +++ /dev/null @@ -1,79 +0,0 @@ - | -// | Aidan Lister | -// +----------------------------------------------------------------------+ -// -// $Id: convert_uuencode.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace convert_uuencode() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.convert_uuencode - * @author Michael Wallner - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5 - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('convert_uuencode')) { - function convert_uuencode($string) - { - // Sanity check - if (!is_scalar($string)) { - user_error('convert_uuencode() expects parameter 1 to be string, ' . - gettype($string) . ' given', E_USER_WARNING); - return false; - } - - $u = 0; - $encoded = ''; - - while ($c = count($bytes = unpack('c*', substr($string, $u, 45)))) { - $u += 45; - $encoded .= pack('c', $c + 0x20); - - while ($c % 3) { - $bytes[++$c] = 0; - } - - foreach (array_chunk($bytes, 3) as $b) { - $b0 = ($b[0] & 0xFC) >> 2; - $b1 = (($b[0] & 0x03) << 4) + (($b[1] & 0xF0) >> 4); - $b2 = (($b[1] & 0x0F) << 2) + (($b[2] & 0xC0) >> 6); - $b3 = $b[2] & 0x3F; - - $b0 = $b0 ? $b0 + 0x20 : 0x60; - $b1 = $b1 ? $b1 + 0x20 : 0x60; - $b2 = $b2 ? $b2 + 0x20 : 0x60; - $b3 = $b3 ? $b3 + 0x20 : 0x60; - - $encoded .= pack('c*', $b0, $b1, $b2, $b3); - } - - $encoded .= "\n"; - } - - // Add termination characters - $encoded .= "\x60\n"; - - return $encoded; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/debug_print_backtrace.php b/includes/pear/Compat/Function/debug_print_backtrace.php deleted file mode 100644 index e6a157b5..00000000 --- a/includes/pear/Compat/Function/debug_print_backtrace.php +++ /dev/null @@ -1,67 +0,0 @@ - | -// | Aidan Lister | -// +----------------------------------------------------------------------+ -// -// $Id: debug_print_backtrace.php,v 1.1 2005/07/23 05:56:02 Tony Exp $ - - -/** - * Replace debug_print_backtrace() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.debug_print_backtrace - * @author Laurent Laville - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5 - * @require PHP 4.0.0 - */ -if (!function_exists('debug_print_backtrace2')) { - function debug_print_backtrace2() - { - // Get backtrace - $backtrace = debug_backtrace(); - - // Unset call to debug_print_backtrace - array_shift($backtrace); - - // Iterate backtrace - $calls = array(); - foreach ($backtrace as $i => $call) { - $location = $call['file'] . ':' . $call['line']; - $function = (isset($call['class'])) ? - $call['class'] . '.' . $call['function'] : - $call['function']; - - $params = ''; - if (isset($call['args'])) { - $params = implode(', ', $call['args']); - } - - $calls[] = sprintf('#%d %s(%s) called at [%s]', - $i, - $function, - $params, - $location); - } - - echo implode("\n", $calls); - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/file_get_contents.php b/includes/pear/Compat/Function/file_get_contents.php deleted file mode 100644 index 770e44b2..00000000 --- a/includes/pear/Compat/Function/file_get_contents.php +++ /dev/null @@ -1,57 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: file_get_contents.php,v 1.1 2005/07/23 05:56:03 Tony Exp $ - - -/** - * Replace file_get_contents() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.file_get_contents - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @internal resource_context is not supported - * @since PHP 5 - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('file_get_contents')) { - function file_get_contents($filename, $incpath = false, $resource_context = null) - { - if (false === $fh = fopen($filename, 'rb', $incpath)) { - user_error('file_get_contents() failed to open stream: No such file or directory', - E_USER_WARNING); - return false; - } - - clearstatcache(); - if ($fsize = @filesize($filename)) { - $data = fread($fh, $fsize); - } else { - $data = ''; - while (!feof($fh)) { - $data .= fread($fh, 8192); - } - } - - fclose($fh); - return $data; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/file_put_contents.php b/includes/pear/Compat/Function/file_put_contents.php deleted file mode 100644 index b3a369d0..00000000 --- a/includes/pear/Compat/Function/file_put_contents.php +++ /dev/null @@ -1,104 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: file_put_contents.php,v 1.1 2005/07/23 05:56:03 Tony Exp $ - - -if (!defined('FILE_USE_INCLUDE_PATH')) { - define('FILE_USE_INCLUDE_PATH', 1); -} - -if (!defined('FILE_APPEND')) { - define('FILE_APPEND', 8); -} - - -/** - * Replace file_put_contents() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.file_put_contents - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @internal resource_context is not supported - * @since PHP 5 - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('file_put_contents')) { - function file_put_contents($filename, $content, $flags = null, $resource_context = null) - { - // If $content is an array, convert it to a string - if (is_array($content)) { - $content = implode('', $content); - } - - // If we don't have a string, throw an error - if (!is_scalar($content)) { - user_error('file_put_contents() The 2nd parameter should be either a string or an array', - E_USER_WARNING); - return false; - } - - // Get the length of date to write - $length = strlen($content); - - // Check what mode we are using - $mode = ($flags & FILE_APPEND) ? - $mode = 'a' : - $mode = 'w'; - - // Check if we're using the include path - $use_inc_path = ($flags & FILE_USE_INCLUDE_PATH) ? - true : - false; - - // Open the file for writing - if (($fh = @fopen($filename, $mode, $use_inc_path)) === false) { - user_error('file_put_contents() failed to open stream: Permission denied', - E_USER_WARNING); - return false; - } - - // Write to the file - $bytes = 0; - if (($bytes = @fwrite($fh, $content)) === false) { - $errormsg = sprintf('file_put_contents() Failed to write %d bytes to %s', - $length, - $filename); - user_error($errormsg, E_USER_WARNING); - return false; - } - - // Close the handle - @fclose($fh); - - // Check all the data was written - if ($bytes != $length) { - $errormsg = sprintf('file_put_contents() Only %d of %d bytes written, possibly out of free disk space.', - $bytes, - $length); - user_error($errormsg, E_USER_WARNING); - return false; - } - - // Return length - return $bytes; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/fprintf.php b/includes/pear/Compat/Function/fprintf.php deleted file mode 100644 index 8af49713..00000000 --- a/includes/pear/Compat/Function/fprintf.php +++ /dev/null @@ -1,54 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: fprintf.php,v 1.1 2005/07/23 05:56:03 Tony Exp $ - - -/** - * Replace fprintf() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.fprintf - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5 - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('fprintf')) { - function fprintf() { - $args = func_get_args(); - - if (count($args) < 2) { - user_error('Wrong parameter count for fprintf()', E_USER_WARNING); - return; - } - - $resource_handle = array_shift($args); - $format = array_shift($args); - - if (!is_resource($resource_handle)) { - user_error('fprintf() supplied argument is not a valid stream resource', - E_USER_WARNING); - return false; - } - - return fwrite($resource_handle, vsprintf($format, $args)); - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/get_headers.php b/includes/pear/Compat/Function/get_headers.php deleted file mode 100644 index 129a4f61..00000000 --- a/includes/pear/Compat/Function/get_headers.php +++ /dev/null @@ -1,77 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: get_headers.php,v 1.1 2005/07/23 05:56:03 Tony Exp $ - - -/** - * Replace get_headers() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.get_headers - * @author Aeontech - * @author Cpurruc - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5.0.0 - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('get_headers')) { - function get_headers($url, $format = 0) - { - // Init - $urlinfo = parse_url($url); - $port = isset($urlinfo['port']) ? $urlinfo['port'] : 80; - - // Connect - $fp = fsockopen($urlinfo['host'], $port, $errno, $errstr, 30); - if ($fp === false) { - return false; - } - - // Send request - $head = 'HEAD ' . $urlinfo['path'] . - (isset($urlinfo['query']) ? '?' . $urlinfo['query'] : '') . - ' HTTP/1.0' . "\r\n" . - 'Host: ' . $urlinfo['host'] . "\r\n\r\n"; - fputs($fp, $head); - - // Read - while (!feof($fp)) { - if ($header = trim(fgets($fp, 1024))) { - list($key) = explode(':', $header); - - if ($format === 1) { - // First element is the HTTP header type, such as HTTP 200 OK - // It doesn't have a separate name, so check for it - if ($key == $header) { - $headers[] = $header; - } else { - $headers[$key] = substr($header, strlen($key)+2); - } - } else { - $headers[] = $header; - } - } - } - - return $headers; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/get_include_path.php b/includes/pear/Compat/Function/get_include_path.php deleted file mode 100644 index ffa86c8b..00000000 --- a/includes/pear/Compat/Function/get_include_path.php +++ /dev/null @@ -1,39 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: get_include_path.php,v 1.1 2005/07/23 05:56:03 Tony Exp $ - - -/** - * Replace get_include_path() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.get_include_path - * @author Stephan Schmidt - * @version $Revision: 1.1 $ - * @since PHP 4.3.0 - * @require PHP 4.0.0 - */ -if (!function_exists('get_include_path')) { - function get_include_path() - { - return ini_get('include_path'); - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/html_entity_decode.php b/includes/pear/Compat/Function/html_entity_decode.php deleted file mode 100644 index 2bdb0189..00000000 --- a/includes/pear/Compat/Function/html_entity_decode.php +++ /dev/null @@ -1,72 +0,0 @@ - | -// | Aidan Lister | -// +----------------------------------------------------------------------+ -// -// $Id: html_entity_decode.php,v 1.1 2005/07/23 05:56:03 Tony Exp $ - - -if (!defined('ENT_NOQUOTES')) { - define('ENT_NOQUOTES', 0); -} - -if (!defined('ENT_COMPAT')) { - define('ENT_COMPAT', 2); -} - -if (!defined('ENT_QUOTES')) { - define('ENT_QUOTES', 3); -} - - -/** - * Replace html_entity_decode() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.html_entity_decode - * @author David Irvine - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 4.3.0 - * @internal Setting the charset will not do anything - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('html_entity_decode')) { - function html_entity_decode($string, $quote_style = ENT_COMPAT, $charset = null) - { - if (!is_int($quote_style)) { - user_error('html_entity_decode() expects parameter 2 to be long, ' . - gettype($quote_style) . ' given', E_USER_WARNING); - return; - } - - $trans_tbl = get_html_translation_table(HTML_ENTITIES); - $trans_tbl = array_flip($trans_tbl); - - // Add single quote to translation table; - $trans_tbl['''] = '\''; - - // Not translating double quotes - if ($quote_style & ENT_NOQUOTES) { - // Remove double quote from translation table - unset($trans_tbl['"']); - } - - return strtr($string, $trans_tbl); - } -} -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/http_build_query.php b/includes/pear/Compat/Function/http_build_query.php deleted file mode 100644 index 81a318f4..00000000 --- a/includes/pear/Compat/Function/http_build_query.php +++ /dev/null @@ -1,99 +0,0 @@ - | -// | Aidan Lister | -// +----------------------------------------------------------------------+ -// -// $Id: http_build_query.php,v 1.1 2005/07/23 05:56:03 Tony Exp $ - - -/** - * Replace function http_build_query() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.http-build-query - * @author Stephan Schmidt - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5 - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('http_build_query')) { - function http_build_query($formdata, $numeric_prefix = null) - { - // If $formdata is an object, convert it to an array - if (is_object($formdata)) { - $formdata = get_object_vars($formdata); - } - - // Check we have an array to work with - if (!is_array($formdata)) { - user_error('http_build_query() Parameter 1 expected to be Array or Object. Incorrect value given.', - E_USER_WARNING); - return false; - } - - // If the array is empty, return null - if (empty($formdata)) { - return; - } - - // Argument seperator - $separator = ini_get('arg_separator.output'); - - // Start building the query - $tmp = array (); - foreach ($formdata as $key => $val) { - if (is_integer($key) && $numeric_prefix != null) { - $key = $numeric_prefix . $key; - } - - if (is_scalar($val)) { - array_push($tmp, urlencode($key).'='.urlencode($val)); - continue; - } - - // If the value is an array, recursively parse it - if (is_array($val)) { - array_push($tmp, __http_build_query($val, urlencode($key))); - continue; - } - } - - return implode($separator, $tmp); - } - - // Helper function - function __http_build_query ($array, $name) - { - $tmp = array (); - foreach ($array as $key => $value) { - if (is_array($value)) { - array_push($tmp, __http_build_query($value, sprintf('%s[%s]', $name, $key))); - } elseif (is_scalar($value)) { - array_push($tmp, sprintf('%s[%s]=%s', $name, urlencode($key), urlencode($value))); - } elseif (is_object($value)) { - array_push($tmp, __http_build_query(get_object_vars($value), sprintf('%s[%s]', $name, $key))); - } - } - - // Argument seperator - $separator = ini_get('arg_separator.output'); - - return implode($separator, $tmp); - } -} -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/image_type_to_mime_type.php b/includes/pear/Compat/Function/image_type_to_mime_type.php deleted file mode 100644 index 1f05c7d7..00000000 --- a/includes/pear/Compat/Function/image_type_to_mime_type.php +++ /dev/null @@ -1,147 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: image_type_to_mime_type.php,v 1.1 2005/07/23 05:56:03 Tony Exp $ - - -if (!defined('IMAGETYPE_GIF')) { - define('IMAGETYPE_GIF', 1); -} - -if (!defined('IMAGETYPE_JPEG')) { - define('IMAGETYPE_JPEG', 2); -} - -if (!defined('IMAGETYPE_PNG')) { - define('IMAGETYPE_PNG', 3); -} - -if (!defined('IMAGETYPE_SWF')) { - define('IMAGETYPE_SWF', 4); -} - -if (!defined('IMAGETYPE_PSD')) { - define('IMAGETYPE_PSD', 5); -} - -if (!defined('IMAGETYPE_BMP')) { - define('IMAGETYPE_BMP', 6); -} - -if (!defined('IMAGETYPE_TIFF_II')) { - define('IMAGETYPE_TIFF_II', 7); -} - -if (!defined('IMAGETYPE_TIFF_MM')) { - define('IMAGETYPE_TIFF_MM', 8); -} - -if (!defined('IMAGETYPE_JPC')) { - define('IMAGETYPE_JPC', 9); -} - -if (!defined('IMAGETYPE_JP2')) { - define('IMAGETYPE_JP2', 10); -} - -if (!defined('IMAGETYPE_JPX')) { - define('IMAGETYPE_JPX', 11); -} - -if (!defined('IMAGETYPE_JB2')) { - define('IMAGETYPE_JB2', 12); -} - -if (!defined('IMAGETYPE_SWC')) { - define('IMAGETYPE_SWC', 13); -} - -if (!defined('IMAGETYPE_IFF')) { - define('IMAGETYPE_IFF', 14); -} - -if (!defined('IMAGETYPE_WBMP')) { - define('IMAGETYPE_WBMP', 15); -} - -if (!defined('IMAGETYPE_XBM')) { - define('IMAGETYPE_XBM', 16); -} - - -/** - * Replace image_type_to_mime_type() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.image_type_to_mime_type - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 4.3.0 - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('image_type_to_mime_type')) { - function image_type_to_mime_type($imagetype) - { - switch ($imagetype): - case IMAGETYPE_GIF: - return 'image/gif'; - break; - case IMAGETYPE_JPEG: - return 'image/jpeg'; - break; - case IMAGETYPE_PNG: - return 'image/png'; - break; - case IMAGETYPE_SWF: - case IMAGETYPE_SWC: - return 'application/x-shockwave-flash'; - break; - case IMAGETYPE_PSD: - return 'image/psd'; - break; - case IMAGETYPE_BMP: - return 'image/bmp'; - break; - case IMAGETYPE_TIFF_MM: - case IMAGETYPE_TIFF_II: - return 'image/tiff'; - break; - case IMAGETYPE_JP2: - return 'image/jp2'; - break; - case IMAGETYPE_IFF: - return 'image/iff'; - break; - case IMAGETYPE_WBMP: - return 'image/vnd.wap.wbmp'; - break; - case IMAGETYPE_XBM: - return 'image/xbm'; - break; - case IMAGETYPE_JPX: - case IMAGETYPE_JB2: - case IMAGETYPE_JPC: - default: - return 'application/octet-stream'; - break; - - endswitch; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/ob_get_clean.php b/includes/pear/Compat/Function/ob_get_clean.php deleted file mode 100644 index 130b0424..00000000 --- a/includes/pear/Compat/Function/ob_get_clean.php +++ /dev/null @@ -1,46 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: ob_get_clean.php,v 1.1 2005/07/23 05:56:03 Tony Exp $ - - -/** - * Replace ob_get_clean() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.ob_get_clean - * @author Aidan Lister - * @author Thiemo Mättig (http://maettig.com/) - * @version $Revision: 1.1 $ - * @since PHP 4.3.0 - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('ob_get_clean')) { - function ob_get_clean() - { - $contents = ob_get_contents(); - - if ($contents !== false) { - ob_end_clean(); - } - - return $contents; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/ob_get_flush.php b/includes/pear/Compat/Function/ob_get_flush.php deleted file mode 100644 index 3d2ef77e..00000000 --- a/includes/pear/Compat/Function/ob_get_flush.php +++ /dev/null @@ -1,46 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: ob_get_flush.php,v 1.1 2005/07/23 05:56:03 Tony Exp $ - - -/** - * Replace ob_get_flush() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.ob_get_flush - * @author Aidan Lister - * @author Thiemo Mättig (http://maettig.com/) - * @version $Revision: 1.1 $ - * @since PHP 4.3.0 - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('ob_get_flush')) { - function ob_get_flush() - { - $contents = ob_get_contents(); - - if ($contents !== false) { - ob_end_flush(); - } - - return $contents; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/php_strip_whitespace.php b/includes/pear/Compat/Function/php_strip_whitespace.php deleted file mode 100644 index 39824358..00000000 --- a/includes/pear/Compat/Function/php_strip_whitespace.php +++ /dev/null @@ -1,86 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: php_strip_whitespace.php,v 1.1 2005/07/23 05:56:03 Tony Exp $ - - -/** - * Replace php_strip_whitespace() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.php_strip_whitespace - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5 - * @require PHP 4.0.0 (user_error) + Tokenizer extension - */ -if (!function_exists('php_strip_whitespace')) { - function php_strip_whitespace($file) - { - // Sanity check - if (!is_scalar($file)) { - user_error('php_strip_whitespace() expects parameter 1 to be string, ' . - gettype($file) . ' given', E_USER_WARNING); - return; - } - - // Load file / tokens - $source = implode('', file($file)); - $tokens = token_get_all($source); - - // Init - $source = ''; - $was_ws = false; - - // Process - foreach ($tokens as $token) { - if (is_string($token)) { - // Single character tokens - $source .= $token; - } else { - list($id, $text) = $token; - - switch ($id) { - // Skip all comments - case T_COMMENT: - case T_ML_COMMENT: - case T_DOC_COMMENT: - break; - - // Remove whitespace - case T_WHITESPACE: - // We don't want more than one whitespace in a row replaced - if ($was_ws !== true) { - $source .= ' '; - } - $was_ws = true; - break; - - default: - $was_ws = false; - $source .= $text; - break; - } - } - } - - return $source; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/restore_include_path.php b/includes/pear/Compat/Function/restore_include_path.php deleted file mode 100644 index 7da7fae7..00000000 --- a/includes/pear/Compat/Function/restore_include_path.php +++ /dev/null @@ -1,37 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: restore_include_path.php,v 1.1 2005/07/23 05:56:03 Tony Exp $ - - -/** - * Replace restore_include_path() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.restore_include_path - * @author Stephan Schmidt - * @version $Revision: 1.1 $ - * @since PHP 4.3.0 - */ -if (!function_exists('restore_include_path')) { - function restore_include_path() - { - return ini_restore('include_path'); - } -} -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/scandir.php b/includes/pear/Compat/Function/scandir.php deleted file mode 100644 index e3fc5bcc..00000000 --- a/includes/pear/Compat/Function/scandir.php +++ /dev/null @@ -1,69 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: scandir.php,v 1.1 2005/07/23 05:56:03 Tony Exp $ - - -/** - * Replace scandir() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.scandir - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5 - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('scandir')) { - function scandir($directory, $sorting_order = 0) - { - if (!is_string($directory)) { - user_error('scandir() expects parameter 1 to be string, ' . - gettype($directory) . ' given', E_USER_WARNING); - return; - } - - if (!is_int($sorting_order) && !is_bool($sorting_order)) { - user_error('scandir() expects parameter 2 to be long, ' . - gettype($sorting_order) . ' given', E_USER_WARNING); - return; - } - - if (!is_dir($directory) || (false === $fh = @opendir($directory))) { - user_error('scandir() failed to open dir: Invalid argument', E_USER_WARNING); - return false; - } - - $files = array (); - while (false !== ($filename = readdir($fh))) { - $files[] = $filename; - } - - closedir($fh); - - if ($sorting_order == 1) { - rsort($files); - } else { - sort($files); - } - - return $files; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/set_include_path.php b/includes/pear/Compat/Function/set_include_path.php deleted file mode 100644 index 11f24e1f..00000000 --- a/includes/pear/Compat/Function/set_include_path.php +++ /dev/null @@ -1,37 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: set_include_path.php,v 1.1 2005/07/23 05:56:03 Tony Exp $ - - -/** - * Replace set_include_path() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.set_include_path - * @author Stephan Schmidt - * @version $Revision: 1.1 $ - * @since PHP 4.3.0 - */ -if (!function_exists('set_include_path')) { - function set_include_path($new_include_path) - { - return ini_set('include_path', $new_include_path); - } -} -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/str_ireplace.php b/includes/pear/Compat/Function/str_ireplace.php deleted file mode 100644 index fb7e40eb..00000000 --- a/includes/pear/Compat/Function/str_ireplace.php +++ /dev/null @@ -1,113 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: str_ireplace.php,v 1.1 2005/07/23 05:56:03 Tony Exp $ - - -/** - * Replace str_ireplace() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.str_ireplace - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5 - * @require PHP 4.0.0 (user_error) - * @note count not by returned by reference, to enable - * change '$count = null' to '&$count' - */ -if (!function_exists('str_ireplace')) { - function str_ireplace($search, $replace, $subject, $count = null) - { - // Sanity check - if (is_string($search) && is_array($replace)) { - user_error('Array to string conversion', E_USER_NOTICE); - $replace = (string) $replace; - } - - // If search isn't an array, make it one - if (!is_array($search)) { - $search = array ($search); - } - $search = array_values($search); - - // If replace isn't an array, make it one, and pad it to the length of search - if (!is_array($replace)) { - $replace_string = $replace; - - $replace = array (); - for ($i = 0, $c = count($search); $i < $c; $i++) { - $replace[$i] = $replace_string; - } - } - $replace = array_values($replace); - - // Check the replace array is padded to the correct length - $length_replace = count($replace); - $length_search = count($search); - if ($length_replace < $length_search) { - for ($i = $length_replace; $i < $length_search; $i++) { - $replace[$i] = ''; - } - } - - // If subject is not an array, make it one - $was_array = false; - if (!is_array($subject)) { - $was_array = true; - $subject = array ($subject); - } - - // Loop through each subject - $count = 0; - foreach ($subject as $subject_key => $subject_value) { - // Loop through each search - foreach ($search as $search_key => $search_value) { - // Split the array into segments, in between each part is our search - $segments = explode(strtolower($search_value), strtolower($subject_value)); - - // The number of replacements done is the number of segments minus the first - $count += count($segments) - 1; - $pos = 0; - - // Loop through each segment - foreach ($segments as $segment_key => $segment_value) { - // Replace the lowercase segments with the upper case versions - $segments[$segment_key] = substr($subject_value, $pos, strlen($segment_value)); - // Increase the position relative to the initial string - $pos += strlen($segment_value) + strlen($search_value); - } - - // Put our original string back together - $subject_value = implode($replace[$search_key], $segments); - } - - $result[$subject_key] = $subject_value; - } - - // Check if subject was initially a string and return it as a string - if ($was_array === true) { - return $result[0]; - } - - // Otherwise, just return the array - return $result; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/str_shuffle.php b/includes/pear/Compat/Function/str_shuffle.php deleted file mode 100644 index a4dc8bf7..00000000 --- a/includes/pear/Compat/Function/str_shuffle.php +++ /dev/null @@ -1,53 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: str_shuffle.php,v 1.1 2005/07/23 05:56:03 Tony Exp $ - - -/** - * Replace str_shuffle() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.str_shuffle - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 4.3.0 - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('str_shuffle')) { - function str_shuffle($str) - { - $newstr = ''; - $strlen = strlen($str); - $str = (string) $str; - - // Seed - list($usec, $sec) = explode(' ', microtime()); - $seed = (float) $sec + ((float) $usec * 100000); - mt_srand($seed); - - // Shuffle - for ($i = 0; $strlen > $i; $i++) { - $newstr .= $str[mt_rand(0, $strlen - 1)]; - } - - return $newstr; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/str_split.php b/includes/pear/Compat/Function/str_split.php deleted file mode 100644 index dd784a0a..00000000 --- a/includes/pear/Compat/Function/str_split.php +++ /dev/null @@ -1,52 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: str_split.php,v 1.1 2005/07/23 05:56:03 Tony Exp $ - - -/** - * Replace str_split() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.str_split - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5 - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('str_split')) { - function str_split($string, $split_length = 1) - { - if (!is_scalar($split_length)) { - user_error('str_split() expects parameter 2 to be long, ' . - gettype($split_length) . ' given', E_USER_WARNING); - return false; - } - - $split_length = (int) $split_length; - if ($split_length < 1) { - user_error('str_split() The length of each segment must be greater than zero', E_USER_WARNING); - return false; - } - - preg_match_all('/.{1,' . $split_length . '}/s', $string, $matches); - return $matches[0]; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/str_word_count.php b/includes/pear/Compat/Function/str_word_count.php deleted file mode 100644 index d818b150..00000000 --- a/includes/pear/Compat/Function/str_word_count.php +++ /dev/null @@ -1,68 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: str_word_count.php,v 1.1 2005/07/23 05:56:03 Tony Exp $ - - -/** - * Replace str_word_count() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.str_word_count - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 4.3.0 - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('str_word_count')) { - function str_word_count($string, $format = null) - { - if ($format !== 1 && $format !== 2 && $format !== null) { - user_error('str_word_count() The specified format parameter, "' . $format . '" is invalid', - E_USER_WARNING); - return false; - } - - $word_string = preg_replace('/[0-9]+/', '', $string); - $word_array = preg_split('/[^A-Za-z0-9_\']+/', $word_string, -1, PREG_SPLIT_NO_EMPTY); - - switch ($format) { - case null: - $result = count($word_array); - break; - - case 1: - $result = $word_array; - break; - - case 2: - $lastmatch = 0; - $word_assoc = array(); - foreach ($word_array as $word) { - $word_assoc[$lastmatch = strpos($string, $word, $lastmatch)] = $word; - $lastmatch += strlen($word); - } - $result = $word_assoc; - break; - } - - return $result; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/stripos.php b/includes/pear/Compat/Function/stripos.php deleted file mode 100644 index e5543ef1..00000000 --- a/includes/pear/Compat/Function/stripos.php +++ /dev/null @@ -1,73 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: stripos.php,v 1.1 2005/07/23 05:56:03 Tony Exp $ - - -/** - * Replace stripos() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.stripos - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5 - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('stripos')) { - function stripos($haystack, $needle, $offset = null) - { - if (!is_scalar($haystack)) { - user_error('stripos() expects parameter 1 to be string, ' . - gettype($haystack) . ' given', E_USER_WARNING); - return false; - } - - if (!is_scalar($needle)) { - user_error('stripos() needle is not a string or an integer.', E_USER_WARNING); - return false; - } - - if (!is_int($offset) && !is_bool($offset) && !is_null($offset)) { - user_error('stripos() expects parameter 3 to be long, ' . - gettype($offset) . ' given', E_USER_WARNING); - return false; - } - - // Manipulate the string if there is an offset - $fix = 0; - if (!is_null($offset)) { - if ($offset > 0) { - $haystack = substr($haystack, $offset, strlen($haystack) - $offset); - $fix = $offset; - } - } - - $segments = explode(strtolower($needle), strtolower($haystack), 2); - - // Check there was a match - if (count($segments) == 1) { - return false; - } - - $position = strlen($segments[0]) + $fix; - return $position; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/strpbrk.php b/includes/pear/Compat/Function/strpbrk.php deleted file mode 100644 index 46d292c2..00000000 --- a/includes/pear/Compat/Function/strpbrk.php +++ /dev/null @@ -1,63 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: strpbrk.php,v 1.1 2005/07/23 05:56:03 Tony Exp $ - - -/** - * Replace strpbrk() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.strpbrk - * @author Stephan Schmidt - * @version $Revision: 1.1 $ - * @since PHP 5 - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('strpbrk')) { - function strpbrk($haystack, $char_list) - { - if (!is_scalar($haystack)) { - user_error('strpbrk() expects parameter 1 to be string, ' . - gettype($haystack) . ' given', E_USER_WARNING); - return false; - } - - if (!is_scalar($char_list)) { - user_error('strpbrk() expects parameter 2 to be scalar, ' . - gettype($needle) . ' given', E_USER_WARNING); - return false; - } - - $haystack = (string) $haystack; - $char_list = (string) $char_list; - - $len = strlen($haystack); - for ($i = 0; $i < $len; $i++) { - $char = substr($haystack, $i, 1); - if (strpos($char_list, $char) === false) { - continue; - } - return substr($haystack, $i); - } - - return false; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/strripos.php b/includes/pear/Compat/Function/strripos.php deleted file mode 100644 index 48d359b3..00000000 --- a/includes/pear/Compat/Function/strripos.php +++ /dev/null @@ -1,82 +0,0 @@ - | -// | Stephan Schmidt | -// +----------------------------------------------------------------------+ -// -// $Id: strripos.php,v 1.1 2005/07/23 05:56:03 Tony Exp $ - - -/** - * Replace strripos() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.strripos - * @author Aidan Lister - * @author Stephan Schmidt - * @version $Revision: 1.1 $ - * @since PHP 5 - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('strripos')) { - function strripos($haystack, $needle, $offset = null) - { - if (!is_scalar($haystack)) { - user_error('strripos() expects parameter 1 to be scalar, ' . - gettype($haystack) . ' given', E_USER_WARNING); - return false; - } - - if (!is_scalar($needle)) { - user_error('strripos() expects parameter 2 to be scalar, ' . - gettype($needle) . ' given', E_USER_WARNING); - return false; - } - - if (!is_int($offset) && !is_bool($offset) && !is_null($offset)) { - user_error('strripos() expects parameter 3 to be long, ' . - gettype($offset) . ' given', E_USER_WARNING); - return false; - } - - // Manipulate the string if there is an offset - $fix = 0; - if (!is_null($offset)) { - // If the offset is larger than the haystack, return - if (abs($offset) >= strlen($haystack)) { - return false; - } - - // Check whether offset is negative or positive - if ($offset > 0) { - $haystack = substr($haystack, $offset, strlen($haystack) - $offset); - // We need to add this to the position of the needle - $fix = $offset; - } else { - $haystack = substr($haystack, 0, strlen($haystack) + $offset); - } - } - - $segments = explode(strtolower($needle), strtolower($haystack)); - - $last_seg = count($segments) - 1; - $position = strlen($haystack) + $fix - strlen($segments[$last_seg]) - strlen($needle); - - return $position; - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Compat/Function/substr_compare.php b/includes/pear/Compat/Function/substr_compare.php deleted file mode 100644 index 45757256..00000000 --- a/includes/pear/Compat/Function/substr_compare.php +++ /dev/null @@ -1,74 +0,0 @@ - | -// | Aidan Lister | -// +----------------------------------------------------------------------+ -// -// $Id: substr_compare.php,v 1.1 2005/07/23 05:56:03 Tony Exp $ - - -/** - * Replace substr_compare() - * - * @category PHP - * @package PHP_Compat - * @link http://php.net/function.substr_compare - * @author Tom Buskens - * @author Aidan Lister - * @version $Revision: 1.1 $ - * @since PHP 5 - * @require PHP 4.0.0 (user_error) - */ -if (!function_exists('substr_compare')) { - function substr_compare($main_str, $str, $offset, $length = null, $case_insensitive = false) - { - if (!is_string($main_str)) { - user_error('substr_compare() expects parameter 1 to be string, ' . - gettype($main_str) . ' given', E_USER_WARNING); - return; - } - - if (!is_string($str)) { - user_error('substr_compare() expects parameter 2 to be string, ' . - gettype($str) . ' given', E_USER_WARNING); - return; - } - - if (!is_int($offset)) { - user_error('substr_compare() expects parameter 3 to be long, ' . - gettype($offset) . ' given', E_USER_WARNING); - return; - } - - if (is_null($length)) { - $length = strlen($main_str) - $offset; - } elseif ($offset >= strlen($main_str)) { - user_error('substr_compare() The start position cannot exceed initial string length', - E_USER_WARNING); - return false; - } - - $main_str = substr($main_str, $offset, $length); - $str = substr($str, 0, strlen($main_str)); - - if ($case_insensitive === false) { - return strcmp($main_str, $str); - } else { - return strcasecmp($main_str, $str); - } - } -} - -?> \ No newline at end of file diff --git a/includes/pear/Image/Canvas.php b/includes/pear/Image/Canvas.php index 7be71264..25cb45e9 100644 --- a/includes/pear/Image/Canvas.php +++ b/includes/pear/Image/Canvas.php @@ -1,709 +1,733 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Canvas.php,v 1.5 2005/09/30 18:59:35 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -/** - * Specfies the path to the system location of font files. - * - * Remember trailing slash! - * - * This is set by default on Windows systems to %SystemRoot%\Fonts\ - */ -if (!defined('IMAGE_CANVAS_SYSTEM_FONT_PATH')) { - if (isset($_SERVER['SystemRoot'])) { - define('IMAGE_CANVAS_SYSTEM_FONT_PATH', $_SERVER['SystemRoot'] . '/Fonts/'); - } else { - /** - * @ignore - */ - define('IMAGE_CANVAS_SYSTEM_FONT_PATH', ''); - } -} - -/** - * Class for handling different output formats - * - * @category Images - * @package Image_Canvas - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - * @abstract - */ -class Image_Canvas -{ - - /** - * The leftmost pixel of the element on the canvas - * @var int - * @access private - */ - var $_left = 0; - - /** - * The topmost pixel of the element on the canvas - * @var int - * @access private - */ - var $_top = 0; - - /** - * The width of the graph - * @var int - * @access private - */ - var $_width = 0; - - /** - * The height of the graph - * @var int - * @access private - */ - var $_height = 0; - - /** - * Polygon vertex placeholder - * @var array - * @access private - */ - var $_polygon = array(); - - /** - * The thickness of the line(s) - * @var int - * @access private - */ - var $_thickness = 1; - - /** - * The line style - * @var mixed - * @access private - */ - var $_lineStyle = 'transparent'; - - /** - * The fill style - * @var mixed - * @access private - */ - var $_fillStyle = 'transparent'; - - /** - * The font options - * @var array - * @access private - */ - var $_font = array(); - - /** - * The default font - * @var array - * @access private - */ - var $_defaultFont = array('name' => 'Courier New', 'color' => 'black', 'size' => 9); - - /** - * Create the canvas. - * - * Parameters available: - * - * 'width' The width of the graph on the canvas - * - * 'height' The height of the graph on the canvas - * - * 'left' The left offset of the graph on the canvas - * - * 'top' The top offset of the graph on the canvas - * - * @param array $params Parameter array - * @abstract - */ - function Image_Canvas($params) - { - if (isset($params['left'])) { - $this->_left = $params['left']; - } - - if (isset($params['top'])) { - $this->_top = $params['top']; - } - - if (isset($params['width'])) { - $this->_width = $params['width']; - } - - if (isset($params['height'])) { - $this->_height = $params['height']; - } - - $this->setDefaultFont($this->_defaultFont); - } - - /** - * Get the x-point from the relative to absolute coordinates - * - * @param float $x The relative x-coordinate (in percentage of total width) - * @return float The x-coordinate as applied to the canvas - * @access private - */ - function _getX($x) - { - return floor($this->_left + $x); - } - - /** - * Get the y-point from the relative to absolute coordinates - * - * @param float $y The relative y-coordinate (in percentage of total width) - * @return float The y-coordinate as applied to the canvas - * @access private - */ - function _getY($y) - { - return floor($this->_top + $y); - } - - /** - * Get the width of the canvas - * - * @return int The width - */ - function getWidth() - { - return $this->_width; - } - - /** - * Get the height of the canvas - * - * @return int The height - */ - function getHeight() - { - return $this->_height; - } - - /** - * Sets the thickness of the line(s) to be drawn - * - * @param int $thickness The actual thickness (in pixels) - */ - function setLineThickness($thickness) - { - $this->_thickness = $thickness; - } - - /** - * Sets the color of the line(s) to be drawn - * - * @param mixed $color The color of the line - */ - function setLineColor($color) - { - $this->_lineStyle = $color; - } - - /** - * Sets the style of the filling of drawn objects. - * - * This method gives simple access to setFillColor(), setFillImage() and - * setGradientFill() - * - * @param mixed $fill The fill style - */ - function setFill($fill) - { - if (is_array($fill)) { - $this->setGradientFill($fill); - } elseif (file_exists($fill)) { - $this->setFillImage($fill); - } else { - $this->setFillColor($fill); - } - } - - /** - * Sets the color of the filling of drawn objects - * - * @param mixed $color The fill color - */ - function setFillColor($color) - { - $this->_fillStyle = $color; - } - - /** - * Sets an image that should be used for filling - * - * @param string $filename The filename of the image to fill with - */ - function setFillImage($filename) - { - } - - /** - * Sets a gradient fill - * - * @param array $gradient Gradient fill options - */ - function setGradientFill($gradient) - { - $this->_fillStyle = $gradient; - } - - /** - * Sets the font options. - * - * The $font array may have the following entries: - * - * 'name' The name of the font. This name must either be supported - * natively by the canvas or mapped to a font using the font-mapping scheme - * - * 'size' Size in pixels - * - * 'angle' The angle with which to write the text - * - * @param array $fontOptions The font options. - */ - function setFont($fontOptions) - { - $this->_font = $fontOptions; - - if (!isset($this->_font['color'])) { - $this->_font['color'] = 'black'; - } - - if (!(isset($this->_font['angle'])) || ($this->_font['angle'] === false)) { - $this->_font['angle'] = 0; - } - - if (isset($this->_font['angle'])) { - if ((($this->_font['angle'] > 45) && ($this->_font['angle'] < 135)) || - (($this->_font['angle'] > 225) && ($this->_font['angle'] < 315)) - ) { - $this->_font['vertical'] = true; - } - } - - if ((!isset($this->_font['file'])) && (isset($this->_font['name']))) { - include_once 'Image/Canvas/Tool.php'; - $this->_font['file'] = Image_Canvas_Tool::fontMap($this->_font['name']); - } - } - - /** - * Sets the default font options. - * - * The $font array may have the following entries: - * - * 'name' The name of the font. This name must either be supported - * natively by the canvas or mapped to a font using the font-mapping scheme - * - * 'size' Size in pixels - * - * 'angle' The angle with which to write the text - * - * @param array $fontOptions The font options. - */ - function setDefaultFont($fontOptions) - { - $this->setFont($fontOptions); - $this->_defaultFont = $this->_font; - } - - /** - * Resets the canvas. - * - * Includes fillstyle, linestyle, thickness and polygon - * - * @access private - */ - function _reset() - { - $this->_lineStyle = false; - $this->_fillStyle = false; - $this->_thickness = 1; - $this->_polygon = array(); - $this->_font = $this->_defaultFont; - } - - /** - * Draw a line end - * - * Parameter array: - * 'x': int X point - * 'y': int Y point - * 'end': string The end type of the end - * 'angle': int [optional] The angle with which to draw the end - * @param array $params Parameter array - */ - function drawEnd($params) - { - } - - /** - * Draw a line - * - * Parameter array: - * 'x0': int X start point - * 'y0': int Y start point - * 'x1': int X end point - * 'y1': int Y end point - * 'end0': string [optional] The end type of end0 (the start) - * 'end1': string [optional] The end type of end1 (the end) - * 'size0': int [optional] The size of end0 - * 'size1': int [optional] The size of end1 - * 'color': mixed [optional] The line color - * @param array $params Parameter array - */ - function line($params) - { - $x0 = $this->_getX($params['x0']); - $y0 = $this->_getY($params['y0']); - $x1 = $this->_getX($params['x1']); - $y1 = $this->_getY($params['y1']); - if (isset($params['end0'])) { - $angle = Image_Canvas_Tool::getAngle($x1, $y1, $x0, $y0); - $this->drawEnd( - array( - 'end' => $params['end0'], - 'x' => $params['x0'], - 'y' => $params['y0'], - 'angle' => $angle, - 'color' => (isset($params['color0']) ? $params['color0'] : false), - 'size' => $params['size0'] - ) - ); - } - if (isset($params['end1'])) { - $angle = Image_Canvas_Tool::getAngle($x0, $y0, $x1, $y1); - //print "
"; var_dump($params, $angle); print "
"; - $this->drawEnd( - array( - 'end' => $params['end1'], - 'x' => $params['x1'], - 'y' => $params['y1'], - 'angle' => $angle, - 'color' => (isset($params['color1']) ? $params['color1'] : false), - 'size' => $params['size1'] - ) - ); - } - $this->_reset(); - } - - /** - * Adds vertex to a polygon - * - * Parameter array: - * 'x': int X point - * 'y': int Y point - * 'url': string [optional] URL to link the vertex to (must be used with 'map_vertices' in polygon() on a canvas that support image maps) - * 'alt': string [optional] Alternative text to show in the image map (must be used with 'map_vertices' in polygon() on a canvas that support image maps) - * 'target': string [optional] The link target on the image map (must be used with 'map_vertices' in polygon() on a canvas that support image maps) - * 'mapsize': int [optional] The size of the "map", i.e. the size of the hot spot (must be used with 'map_vertices' in polygon() on a canvas that support image maps) - * @param array $params Parameter array - */ - function addVertex($params) - { - $params['X'] = $this->_getX($params['x']); - $params['Y'] = $this->_getY($params['y']); - $this->_polygon[] = $params; - } - - /** - * Adds "splined" vertex to a polygon - * - * Parameter array: - * 'x': int X point - * 'y': int Y point - * 'p1x': int X Control point 1 - * 'p1y': int Y Control point 1 - * 'p2x': int X Control point 2 - * 'p2y': int Y Control point 2 - * 'url': string [optional] URL to link the vertex to (must be used with 'map_vertices' in polygon() on a canvas that support image maps) - * 'alt': string [optional] Alternative text to show in the image map (must be used with 'map_vertices' in polygon() on a canvas that support image maps) - * 'target': string [optional] The link target on the image map (must be used with 'map_vertices' in polygon() on a canvas that support image maps) - * 'mapsize': int [optional] The size of the "map", i.e. the size of the hot spot (must be used with 'map_vertices' in polygon() on a canvas that support image maps) - * @param array $params Parameter array - */ - function addSpline($params) - { - $params['X'] = $this->_getX($params['x']); - $params['Y'] = $this->_getY($params['y']); - $params['P1X'] = $this->_getX($params['p1x']); - $params['P1Y'] = $this->_getY($params['p1y']); - $params['P2X'] = $this->_getX($params['p2x']); - $params['P2Y'] = $this->_getY($params['p2y']); - $this->_polygon[] = $params; - } - - /** - * Draws a polygon - * - * Parameter array: - * 'connect': bool [optional] Specifies whether the start point should be - * connected to the endpoint (closed polygon) or not (connected line) - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function polygon($params) - { - $this->_reset(); - } - - /** - * Draw a rectangle - * - * Parameter array: - * 'x0': int X start point - * 'y0': int Y start point - * 'x1': int X end point - * 'y1': int Y end point - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function rectangle($params) - { - $this->_reset(); - } - - /** - * Draw an ellipse - * - * Parameter array: - * 'x': int X center point - * 'y': int Y center point - * 'rx': int X radius - * 'ry': int Y radius - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function ellipse($params) - { - $this->_reset(); - } - - /** - * Draw a pie slice - * - * Parameter array: - * 'x': int X center point - * 'y': int Y center point - * 'rx': int X radius - * 'ry': int Y radius - * 'v1': int The starting angle (in degrees) - * 'v2': int The end angle (in degrees) - * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) - * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function pieslice($params) - { - $this->_reset(); - } - - /** - * Get the width of a text, - * - * @param string $text The text to get the width of - * @return int The width of the text - */ - function textWidth($text) - { - } - - /** - * Get the height of a text, - * - * @param string $text The text to get the height of - * @return int The height of the text - */ - function textHeight($text) - { - } - - /** - * Writes text - * - * Parameter array: - * 'x': int X-point of text - * 'y': int Y-point of text - * 'text': string The text to add - * 'alignment': array [optional] Alignment - * 'color': mixed [optional] The color of the text - */ - function addText($params) - { - $this->_reset(); - } - - /** - * Overlay image - * - * Parameter array: - * 'x': int X-point of overlayed image - * 'y': int Y-point of overlayed image - * 'filename': string The filename of the image to overlay - * 'width': int [optional] The width of the overlayed image (resizing if possible) - * 'height': int [optional] The height of the overlayed image (resizing if possible) - * 'alignment': array [optional] Alignment - */ - function image($params) - { - } - - /** - * Start a group. - * - * What this does, depends on the canvas/format. - * - * @param string $name The name of the group - */ - function startGroup($name = false) - { - } - - /** - * End the "current" group. - * - * What this does, depends on the canvas/format. - */ - function endGroup() - { - } - - /** - * Output the result of the canvas to the browser - * - * @param array $params Parameter array, the contents and meaning depends on the actual Canvas - * @abstract - */ - function show($params = false) - { - if ($params === false) { - header('Expires: Tue, 2 Jul 1974 17:41:00 GMT'); // Date in the past - header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); // always modified - header('Cache-Control: no-cache, must-revalidate'); // HTTP/1.1 - header('Pragma: no-cache'); - } - } - - /** - * Save the result of the canvas to a file - * - * Parameter array: - * 'filename': string The file to output to - * @param array $params Parameter array, the contents and meaning depends on the actual Canvas - * @abstract - */ - function save($params = false) - { - } - - /** - * Get a canvas specific HTML tag. - * - * This method implicitly saves the canvas to the filename in the - * filesystem path specified and parses it as URL specified by URL path - * - * Parameter array: - * 'filename': string - * 'filepath': string Path to the file on the file system. Remember the final slash - * 'urlpath': string Path to the file available through an URL. Remember the final slash - */ - function toHtml($params) - { - $this->save(array('filename' => $params['filepath'] . $params['filename'])); - } - - /** - * Canvas factory method. - * - * Supported canvass are: - * - * 'png': output in PNG format (using GD) - * - * 'jpg': output in JPEG format (using GD) - * - * 'pdf': output in PDF format (using PDFlib) - * - * 'svg': output in SVG format - * - * 'imagemap': output as a html image map - * - * An example of usage: - * - * - * 800, 'height' => 600, 'antialias' => 'native') - * ); - * ?> - * - * - * @param string $canvas The canvas type - * @param array $params The parameters for the canvas constructor - * @return Image_Canvas The newly created canvas - * @static - */ - function &factory($canvas, $params) - { - $canvas = strtoupper($canvas); - - if (($canvas == 'PNG') || ($canvas == 'GD')) { - $canvas = 'GD_PNG'; - } - if (($canvas == 'JPG') || ($canvas == 'JPEG')) { - $canvas = 'GD_JPG'; - } - - if ($canvas == 'IMAGEMAP') { - $canvas = 'ImageMap'; - } - - $class = 'Image_Canvas_'. $canvas; - include_once 'Image/Canvas/'. str_replace('_', '/', $canvas) . '.php'; - - $obj =& new $class($params); - return $obj; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Canvas.php,v 1.7 2006/02/28 22:46:25 nosey Exp $ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ + +/** + * Specfies the path to the system location of font files. + * + * Remember trailing slash! + * + * This is set by default on Windows systems to %SystemRoot%\Fonts\ + */ +if (!defined('IMAGE_CANVAS_SYSTEM_FONT_PATH')) { + if (isset($_SERVER['SystemRoot'])) { + define('IMAGE_CANVAS_SYSTEM_FONT_PATH', $_SERVER['SystemRoot'] . '/Fonts/'); + } else { + /** + * @ignore + */ + define('IMAGE_CANVAS_SYSTEM_FONT_PATH', ''); + } +} + +/** + * Class for handling different output formats + * + * @category Images + * @package Image_Canvas + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + * @abstract + */ +class Image_Canvas +{ + + /** + * The leftmost pixel of the element on the canvas + * @var int + * @access private + */ + var $_left = 0; + + /** + * The topmost pixel of the element on the canvas + * @var int + * @access private + */ + var $_top = 0; + + /** + * The width of the graph + * @var int + * @access private + */ + var $_width = 0; + + /** + * The height of the graph + * @var int + * @access private + */ + var $_height = 0; + + /** + * Polygon vertex placeholder + * @var array + * @access private + */ + var $_polygon = array(); + + /** + * The thickness of the line(s) + * @var int + * @access private + */ + var $_thickness = 1; + + /** + * The line style + * @var mixed + * @access private + */ + var $_lineStyle = 'transparent'; + + /** + * The fill style + * @var mixed + * @access private + */ + var $_fillStyle = 'transparent'; + + /** + * The font options + * @var array + * @access private + */ + var $_font = array(); + + /** + * The default font + * @var array + * @access private + */ + var $_defaultFont = array('name' => 'Courier New', 'color' => 'black', 'size' => 9); + + /** + * Create the canvas. + * + * Parameters available: + * + * 'width' The width of the graph on the canvas + * + * 'height' The height of the graph on the canvas + * + * 'left' The left offset of the graph on the canvas + * + * 'top' The top offset of the graph on the canvas + * + * @param array $params Parameter array + * @abstract + */ + function Image_Canvas($params) + { + if (isset($params['left'])) { + $this->_left = $params['left']; + } + + if (isset($params['top'])) { + $this->_top = $params['top']; + } + + if (isset($params['width'])) { + $this->_width = $params['width']; + } + + if (isset($params['height'])) { + $this->_height = $params['height']; + } + + $this->setDefaultFont($this->_defaultFont); + } + + /** + * Get the x-point from the relative to absolute coordinates + * + * @param float $x The relative x-coordinate (in percentage of total width) + * @return float The x-coordinate as applied to the canvas + * @access private + */ + function _getX($x) + { + return floor($this->_left + $x); + } + + /** + * Get the y-point from the relative to absolute coordinates + * + * @param float $y The relative y-coordinate (in percentage of total width) + * @return float The y-coordinate as applied to the canvas + * @access private + */ + function _getY($y) + { + return floor($this->_top + $y); + } + + /** + * Get the width of the canvas + * + * @return int The width + */ + function getWidth() + { + return $this->_width; + } + + /** + * Get the height of the canvas + * + * @return int The height + */ + function getHeight() + { + return $this->_height; + } + + /** + * Sets the thickness of the line(s) to be drawn + * + * @param int $thickness The actual thickness (in pixels) + */ + function setLineThickness($thickness) + { + $this->_thickness = $thickness; + } + + /** + * Sets the color of the line(s) to be drawn + * + * @param mixed $color The color of the line + */ + function setLineColor($color) + { + $this->_lineStyle = $color; + } + + /** + * Sets the style of the filling of drawn objects. + * + * This method gives simple access to setFillColor(), setFillImage() and + * setGradientFill() + * + * @param mixed $fill The fill style + */ + function setFill($fill) + { + if (is_array($fill)) { + $this->setGradientFill($fill); + } elseif (file_exists($fill)) { + $this->setFillImage($fill); + } else { + $this->setFillColor($fill); + } + } + + /** + * Sets the color of the filling of drawn objects + * + * @param mixed $color The fill color + */ + function setFillColor($color) + { + $this->_fillStyle = $color; + } + + /** + * Sets an image that should be used for filling + * + * @param string $filename The filename of the image to fill with + */ + function setFillImage($filename) + { + } + + /** + * Sets a gradient fill + * + * @param array $gradient Gradient fill options + */ + function setGradientFill($gradient) + { + $this->_fillStyle = $gradient; + } + + /** + * Sets the font options. + * + * The $font array may have the following entries: + * + * 'name' The name of the font. This name must either be supported + * natively by the canvas or mapped to a font using the font-mapping scheme + * + * 'size' Size in pixels + * + * 'angle' The angle with which to write the text + * + * @param array $fontOptions The font options. + */ + function setFont($fontOptions) + { + $this->_font = $fontOptions; + + if (!isset($this->_font['color'])) { + $this->_font['color'] = 'black'; + } + + if (!(isset($this->_font['angle'])) || ($this->_font['angle'] === false)) { + $this->_font['angle'] = 0; + } + + if (isset($this->_font['angle'])) { + if ((($this->_font['angle'] > 45) && ($this->_font['angle'] < 135)) || + (($this->_font['angle'] > 225) && ($this->_font['angle'] < 315)) + ) { + $this->_font['vertical'] = true; + } + } + + if ((!isset($this->_font['file'])) && (isset($this->_font['name']))) { + include_once 'Image/Canvas/Tool.php'; + $this->_font['file'] = Image_Canvas_Tool::fontMap($this->_font['name']); + } + } + + /** + * Sets the default font options. + * + * The $font array may have the following entries: + * + * 'name' The name of the font. This name must either be supported + * natively by the canvas or mapped to a font using the font-mapping scheme + * + * 'size' Size in pixels + * + * 'angle' The angle with which to write the text + * + * @param array $fontOptions The font options. + */ + function setDefaultFont($fontOptions) + { + $this->setFont($fontOptions); + $this->_defaultFont = $this->_font; + } + + /** + * Resets the canvas. + * + * Includes fillstyle, linestyle, thickness and polygon + * + * @access private + */ + function _reset() + { + $this->_lineStyle = false; + $this->_fillStyle = false; + $this->_thickness = 1; + $this->_polygon = array(); + $this->_font = $this->_defaultFont; + } + + /** + * Reset the canvas. + * + * Includes fillstyle, linestyle, thickness and polygon + */ + function reset() + { + $this->_reset(); + } + + /** + * Draw a line end + * + * Parameter array: + * 'x': int X point + * 'y': int Y point + * 'end': string The end type of the end + * 'angle': int [optional] The angle with which to draw the end + * @param array $params Parameter array + */ + function drawEnd($params) + { + } + + /** + * Draw a line + * + * Parameter array: + * 'x0': int X start point + * 'y0': int Y start point + * 'x1': int X end point + * 'y1': int Y end point + * 'end0': string [optional] The end type of end0 (the start) + * 'end1': string [optional] The end type of end1 (the end) + * 'size0': int [optional] The size of end0 + * 'size1': int [optional] The size of end1 + * 'color': mixed [optional] The line color + * @param array $params Parameter array + */ + function line($params) + { + $x0 = $this->_getX($params['x0']); + $y0 = $this->_getY($params['y0']); + $x1 = $this->_getX($params['x1']); + $y1 = $this->_getY($params['y1']); + if (isset($params['end0'])) { + $angle = Image_Canvas_Tool::getAngle($x1, $y1, $x0, $y0); + $this->drawEnd( + array( + 'end' => $params['end0'], + 'x' => $params['x0'], + 'y' => $params['y0'], + 'angle' => $angle, + 'color' => (isset($params['color0']) ? $params['color0'] : false), + 'size' => $params['size0'] + ) + ); + } + if (isset($params['end1'])) { + $angle = Image_Canvas_Tool::getAngle($x0, $y0, $x1, $y1); + //print "
"; var_dump($params, $angle); print "
"; + $this->drawEnd( + array( + 'end' => $params['end1'], + 'x' => $params['x1'], + 'y' => $params['y1'], + 'angle' => $angle, + 'color' => (isset($params['color1']) ? $params['color1'] : false), + 'size' => $params['size1'] + ) + ); + } + $this->_reset(); + } + + /** + * Adds vertex to a polygon + * + * Parameter array: + * 'x': int X point + * 'y': int Y point + * 'url': string [optional] URL to link the vertex to (must be used with 'map_vertices' in polygon() on a canvas that support image maps) + * 'alt': string [optional] Alternative text to show in the image map (must be used with 'map_vertices' in polygon() on a canvas that support image maps) + * 'target': string [optional] The link target on the image map (must be used with 'map_vertices' in polygon() on a canvas that support image maps) + * 'mapsize': int [optional] The size of the "map", i.e. the size of the hot spot (must be used with 'map_vertices' in polygon() on a canvas that support image maps) + * @param array $params Parameter array + */ + function addVertex($params) + { + $params['X'] = $this->_getX($params['x']); + $params['Y'] = $this->_getY($params['y']); + $this->_polygon[] = $params; + } + + /** + * Adds "splined" vertex to a polygon + * + * Parameter array: + * 'x': int X point + * 'y': int Y point + * 'p1x': int X Control point 1 + * 'p1y': int Y Control point 1 + * 'p2x': int X Control point 2 + * 'p2y': int Y Control point 2 + * 'url': string [optional] URL to link the vertex to (must be used with 'map_vertices' in polygon() on a canvas that support image maps) + * 'alt': string [optional] Alternative text to show in the image map (must be used with 'map_vertices' in polygon() on a canvas that support image maps) + * 'target': string [optional] The link target on the image map (must be used with 'map_vertices' in polygon() on a canvas that support image maps) + * 'mapsize': int [optional] The size of the "map", i.e. the size of the hot spot (must be used with 'map_vertices' in polygon() on a canvas that support image maps) + * @param array $params Parameter array + */ + function addSpline($params) + { + $params['X'] = $this->_getX($params['x']); + $params['Y'] = $this->_getY($params['y']); + $params['P1X'] = $this->_getX($params['p1x']); + $params['P1Y'] = $this->_getY($params['p1y']); + $params['P2X'] = $this->_getX($params['p2x']); + $params['P2Y'] = $this->_getY($params['p2y']); + $this->_polygon[] = $params; + } + + /** + * Draws a polygon + * + * Parameter array: + * 'connect': bool [optional] Specifies whether the start point should be + * connected to the endpoint (closed polygon) or not (connected line) + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function polygon($params) + { + $this->_reset(); + } + + /** + * Draw a rectangle + * + * Parameter array: + * 'x0': int X start point + * 'y0': int Y start point + * 'x1': int X end point + * 'y1': int Y end point + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function rectangle($params) + { + $this->_reset(); + } + + /** + * Draw an ellipse + * + * Parameter array: + * 'x': int X center point + * 'y': int Y center point + * 'rx': int X radius + * 'ry': int Y radius + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function ellipse($params) + { + $this->_reset(); + } + + /** + * Draw a pie slice + * + * Parameter array: + * 'x': int X center point + * 'y': int Y center point + * 'rx': int X radius + * 'ry': int Y radius + * 'v1': int The starting angle (in degrees) + * 'v2': int The end angle (in degrees) + * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) + * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function pieslice($params) + { + $this->_reset(); + } + + /** + * Get the width of a text, + * + * @param string $text The text to get the width of + * @return int The width of the text + */ + function textWidth($text) + { + } + + /** + * Get the height of a text, + * + * @param string $text The text to get the height of + * @return int The height of the text + */ + function textHeight($text) + { + } + + /** + * Writes text + * + * Parameter array: + * 'x': int X-point of text + * 'y': int Y-point of text + * 'text': string The text to add + * 'alignment': array [optional] Alignment + * 'color': mixed [optional] The color of the text + */ + function addText($params) + { + $this->_reset(); + } + + /** + * Overlay image + * + * Parameter array: + * 'x': int X-point of overlayed image + * 'y': int Y-point of overlayed image + * 'filename': string The filename of the image to overlay + * 'width': int [optional] The width of the overlayed image (resizing if possible) + * 'height': int [optional] The height of the overlayed image (resizing if possible) + * 'alignment': array [optional] Alignment + */ + function image($params) + { + } + + /** + * Set clipping to occur + * + * Parameter array: + * + * 'x0': int X point of Upper-left corner + * 'y0': int X point of Upper-left corner + * 'x1': int X point of lower-right corner + * 'y1': int Y point of lower-right corner + */ + function setClipping($params = false) + { + } + + /** + * Start a group. + * + * What this does, depends on the canvas/format. + * + * @param string $name The name of the group + */ + function startGroup($name = false) + { + } + + /** + * End the "current" group. + * + * What this does, depends on the canvas/format. + */ + function endGroup() + { + } + + /** + * Output the result of the canvas to the browser + * + * @param array $params Parameter array, the contents and meaning depends on the actual Canvas + * @abstract + */ + function show($params = false) + { + if ($params === false) { + header('Expires: Tue, 2 Jul 1974 17:41:00 GMT'); // Date in the past + header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); // always modified + header('Cache-Control: no-cache, must-revalidate'); // HTTP/1.1 + header('Pragma: no-cache'); + } + } + + /** + * Save the result of the canvas to a file + * + * Parameter array: + * 'filename': string The file to output to + * @param array $params Parameter array, the contents and meaning depends on the actual Canvas + * @abstract + */ + function save($params = false) + { + } + + /** + * Get a canvas specific HTML tag. + * + * This method implicitly saves the canvas to the filename in the + * filesystem path specified and parses it as URL specified by URL path + * + * Parameter array: + * 'filename': string + * 'filepath': string Path to the file on the file system. Remember the final slash + * 'urlpath': string Path to the file available through an URL. Remember the final slash + */ + function toHtml($params) + { + $this->save(array('filename' => $params['filepath'] . $params['filename'])); + } + + /** + * Canvas factory method. + * + * Supported canvass are: + * + * 'png': output in PNG format (using GD) + * + * 'jpg': output in JPEG format (using GD) + * + * 'pdf': output in PDF format (using PDFlib) + * + * 'svg': output in SVG format + * + * 'imagemap': output as a html image map + * + * An example of usage: + * + * + * 800, 'height' => 600, 'antialias' => 'native') + * ); + * ?> + * + * + * @param string $canvas The canvas type + * @param array $params The parameters for the canvas constructor + * @return Image_Canvas The newly created canvas + * @static + */ + function &factory($canvas, $params) + { + $canvas = strtoupper($canvas); + + if (($canvas == 'PNG') || ($canvas == 'GD')) { + $canvas = 'GD_PNG'; + } + if (($canvas == 'JPG') || ($canvas == 'JPEG')) { + $canvas = 'GD_JPG'; + } + + if ($canvas == 'IMAGEMAP') { + $canvas = 'ImageMap'; + } + + $class = 'Image_Canvas_'. $canvas; + include_once 'Image/Canvas/'. str_replace('_', '/', $canvas) . '.php'; + + $obj =& new $class($params); + return $obj; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Canvas/Color.php b/includes/pear/Image/Canvas/Color.php index 0e5bc2ec..c062451e 100644 --- a/includes/pear/Image/Canvas/Color.php +++ b/includes/pear/Image/Canvas/Color.php @@ -1,182 +1,182 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: Color.php,v 1.3 2005/09/14 17:25:46 nosey Exp $ - -/** -* Class for color-handling -* -* @author Stefan Neufeind -* @package Image_Canvas -* @category images -* @license The PHP License, version 2.02 -*/ - -/** -* Color class to be extended; from package PEAR::Image_Color -*/ -require_once 'Image/Color.php'; - -/** -* Class for color-handling -* -* This is used to extend the functionality of the current PEAR::Image_Color v0.4. -* I hope to be allowed to incorporate some of the improvements in a new Image_Color release. -* -* @author Stefan Neufeind -* @package Image_Canvas -* @access public -*/ -class Image_Canvas_Color extends Image_Color -{ - /** - * Allocates a color in the given image. - * - * Userdefined color specifications get translated into - * an array of rgb values. - * - * @param resource GD-resource - * @param mixed any color representation supported by color2RGB() - * @return resource Image color handle - * @see color2RGB() - * @access public - * @static - */ - function allocateColor(&$img, $color) - { - $color = Image_Canvas_Color::color2RGB($color); - - if (($color[3] == 255) || (!function_exists("imagecolorallocatealpha"))) { - return imagecolorallocate($img, $color[0], $color[1], $color[2]); - } else { - return imagecolorallocatealpha($img, $color[0], $color[1], $color[2], 127-round(($color[3]*127)/255)); - } - } - - /** - * Convert any color-representation into an array of 4 ints (RGBA). - * - * Userdefined color specifications get translated into - * an array of rgb values. - * - * @param mixed any color representation supported by Image_Canvas_Color::color2RGB() - * @return array Array of 4 ints (RGBA-representation) - * @access public - * @static - */ - function color2RGB($color) - { - if (is_array($color)) { - if (!is_numeric($color[0])) { - return null; // error - } - if (count($color) == 3) { // assume RGB-color - - // 255 = alpha-value; full opaque - return array((int) $color[0], - (int) $color[1], - (int) $color[2], - 255); - } - if (count($color) == 4) { // assume RGBA-color - - // 255 = alpha-value; full opaque - return array((int) $color[0], - (int) $color[1], - (int) $color[2], - (int) $color[3]); - } - return null; // error - } elseif (is_string($color)) { - $alphaPos = strpos($color, '@'); - if ($alphaPos === false) { - $alpha = 255; - } else { - $alphaFloat = (float) substr($color, $alphaPos+1); - // restrict to range 0..1 - $alphaFloat = max(min($alphaFloat, 1), 0); - $alpha = (int) round((float) 255 * $alphaFloat); - $color = substr($color, 0, $alphaPos); - } - if ($color[0] == '#') { // hex-color given, e.g. #FFB4B4 - $tempColor = parent::hex2rgb($color); - return array((int) $tempColor[0], - (int) $tempColor[1], - (int) $tempColor[2], - $alpha); - } - if (strpos($color,'%') !== false) { - $tempColor = parent::percentageColor2RGB($color); - return array((int) $tempColor[0], - (int) $tempColor[1], - (int) $tempColor[2], - $alpha); - } else { - $tempColor = parent::namedColor2RGB($color); - return array((int) $tempColor[0], - (int) $tempColor[1], - (int) $tempColor[2], - $alpha); - } - } else { - return null; // error - } - } - - /** - * getRange - * Given a degree, you can get the range of colors between one color and - * another color. - * - * @access public - * @param string How much each 'step' between the colors we should take. - * @return array Returns an array of all the colors, one element for each color. - */ - function getRange ($degrees) - { - $tempColors = parent::getRange($degrees); - - // now add alpha-channel information - $steps = count($tempColors); - for($counter=0;$counter<$steps;$counter++) { - $tempColors[$counter] = parent::hex2rgb($tempColors[$counter]); - unset($tempColors[$counter]['hex']); - $tempColors[$counter][3] = (int) round( - (((float) $this->color1[3]*($steps-$counter))+ - ((float) $this->color2[3]*($counter)) - ) / $steps - ); - } - - return $tempColors; - } - - /** - * Internal method to correctly set the colors. - * - * @param mixed color 1 - * @param mixed color 2 - * @access private - */ - function _setColors ( $col1, $col2 ) - { - $this->color1 = Image_Canvas_Color::color2RGB($col1); - $this->color2 = Image_Canvas_Color::color2RGB($col2); - } -} + | +// +----------------------------------------------------------------------+ +// +// $Id: Color.php,v 1.3 2005/09/14 17:25:46 nosey Exp $ + +/** +* Class for color-handling +* +* @author Stefan Neufeind +* @package Image_Canvas +* @category images +* @license The PHP License, version 2.02 +*/ + +/** +* Color class to be extended; from package PEAR::Image_Color +*/ +require_once 'Image/Color.php'; + +/** +* Class for color-handling +* +* This is used to extend the functionality of the current PEAR::Image_Color v0.4. +* I hope to be allowed to incorporate some of the improvements in a new Image_Color release. +* +* @author Stefan Neufeind +* @package Image_Canvas +* @access public +*/ +class Image_Canvas_Color extends Image_Color +{ + /** + * Allocates a color in the given image. + * + * Userdefined color specifications get translated into + * an array of rgb values. + * + * @param resource GD-resource + * @param mixed any color representation supported by color2RGB() + * @return resource Image color handle + * @see color2RGB() + * @access public + * @static + */ + function allocateColor(&$img, $color) + { + $color = Image_Canvas_Color::color2RGB($color); + + if (($color[3] == 255) || (!function_exists("imagecolorallocatealpha"))) { + return imagecolorallocate($img, $color[0], $color[1], $color[2]); + } else { + return imagecolorallocatealpha($img, $color[0], $color[1], $color[2], 127-round(($color[3]*127)/255)); + } + } + + /** + * Convert any color-representation into an array of 4 ints (RGBA). + * + * Userdefined color specifications get translated into + * an array of rgb values. + * + * @param mixed any color representation supported by Image_Canvas_Color::color2RGB() + * @return array Array of 4 ints (RGBA-representation) + * @access public + * @static + */ + function color2RGB($color) + { + if (is_array($color)) { + if (!is_numeric($color[0])) { + return null; // error + } + if (count($color) == 3) { // assume RGB-color + + // 255 = alpha-value; full opaque + return array((int) $color[0], + (int) $color[1], + (int) $color[2], + 255); + } + if (count($color) == 4) { // assume RGBA-color + + // 255 = alpha-value; full opaque + return array((int) $color[0], + (int) $color[1], + (int) $color[2], + (int) $color[3]); + } + return null; // error + } elseif (is_string($color)) { + $alphaPos = strpos($color, '@'); + if ($alphaPos === false) { + $alpha = 255; + } else { + $alphaFloat = (float) substr($color, $alphaPos+1); + // restrict to range 0..1 + $alphaFloat = max(min($alphaFloat, 1), 0); + $alpha = (int) round((float) 255 * $alphaFloat); + $color = substr($color, 0, $alphaPos); + } + if ($color[0] == '#') { // hex-color given, e.g. #FFB4B4 + $tempColor = parent::hex2rgb($color); + return array((int) $tempColor[0], + (int) $tempColor[1], + (int) $tempColor[2], + $alpha); + } + if (strpos($color,'%') !== false) { + $tempColor = parent::percentageColor2RGB($color); + return array((int) $tempColor[0], + (int) $tempColor[1], + (int) $tempColor[2], + $alpha); + } else { + $tempColor = parent::namedColor2RGB($color); + return array((int) $tempColor[0], + (int) $tempColor[1], + (int) $tempColor[2], + $alpha); + } + } else { + return null; // error + } + } + + /** + * getRange + * Given a degree, you can get the range of colors between one color and + * another color. + * + * @access public + * @param string How much each 'step' between the colors we should take. + * @return array Returns an array of all the colors, one element for each color. + */ + function getRange ($degrees) + { + $tempColors = parent::getRange($degrees); + + // now add alpha-channel information + $steps = count($tempColors); + for($counter=0;$counter<$steps;$counter++) { + $tempColors[$counter] = parent::hex2rgb($tempColors[$counter]); + unset($tempColors[$counter]['hex']); + $tempColors[$counter][3] = (int) round( + (((float) $this->color1[3]*($steps-$counter))+ + ((float) $this->color2[3]*($counter)) + ) / $steps + ); + } + + return $tempColors; + } + + /** + * Internal method to correctly set the colors. + * + * @param mixed color 1 + * @param mixed color 2 + * @access private + */ + function _setColors ( $col1, $col2 ) + { + $this->color1 = Image_Canvas_Color::color2RGB($col1); + $this->color2 = Image_Canvas_Color::color2RGB($col2); + } +} ?> \ No newline at end of file diff --git a/includes/pear/Image/Canvas/Fonts/README b/includes/pear/Image/Canvas/Fonts/README index 0a836147..c84e5846 100644 --- a/includes/pear/Image/Canvas/Fonts/README +++ b/includes/pear/Image/Canvas/Fonts/README @@ -1,12 +1,12 @@ -This is where the font files are located. - -Font files can be found at: - -MS CoreFonts - http://corefonts.sourceforge.net/ - -Divide By Zero (most are cartoonish) - http://fonts.tom7.com/ - -MING FDB Fonts +This is where the font files are located. + +Font files can be found at: + +MS CoreFonts + http://corefonts.sourceforge.net/ + +Divide By Zero (most are cartoonish) + http://fonts.tom7.com/ + +MING FDB Fonts http://ming.sf.net/ \ No newline at end of file diff --git a/includes/pear/Image/Canvas/Fonts/fontmap.txt b/includes/pear/Image/Canvas/Fonts/fontmap.txt index ccec67dd..22b71fe7 100644 --- a/includes/pear/Image/Canvas/Fonts/fontmap.txt +++ b/includes/pear/Image/Canvas/Fonts/fontmap.txt @@ -1,25 +1,25 @@ -Arial,arial.ttf -Arial Bold,arialbd.ttf -Arial Bold Italic,arialbi.ttf -Arial Italic,ariali.ttf -Courier New,cour.ttf -Courier New Bold,courbd.ttf -Courier New Bold Italic,courbi.ttf -Courier New Italic,couri.ttf -Garamond,gara.ttf -Garamond Bold,garabd.ttf -Garamond Italic,garait.ttf -Gothic,gothic.ttf -Gothic Bold,gothicb.ttf -Gothic Bold Italic,gothicbi.ttf -Gothic Italic,gothici.ttf -Sans Serif,micross.ttf -Reference Sans Serif,refsan.ttf -Times New Roman,times.ttf -Times New Roman Bold,timesbd.ttf -Times New Roman Bold Italic,timesbi.ttf -Times New Roman Italic,timesi.ttf -Verdana,verdana.ttf -Verdana Bold,verdanab.ttf -Verdana Bold Italic,verdanaz.ttf +Arial,arial.ttf +Arial Bold,arialbd.ttf +Arial Bold Italic,arialbi.ttf +Arial Italic,ariali.ttf +Courier New,cour.ttf +Courier New Bold,courbd.ttf +Courier New Bold Italic,courbi.ttf +Courier New Italic,couri.ttf +Garamond,gara.ttf +Garamond Bold,garabd.ttf +Garamond Italic,garait.ttf +Gothic,gothic.ttf +Gothic Bold,gothicb.ttf +Gothic Bold Italic,gothicbi.ttf +Gothic Italic,gothici.ttf +Sans Serif,micross.ttf +Reference Sans Serif,refsan.ttf +Times New Roman,times.ttf +Times New Roman Bold,timesbd.ttf +Times New Roman Bold Italic,timesbi.ttf +Times New Roman Italic,timesi.ttf +Verdana,verdana.ttf +Verdana Bold,verdanab.ttf +Verdana Bold Italic,verdanaz.ttf Verdana Italic,verdanai.ttf \ No newline at end of file diff --git a/includes/pear/Image/Canvas/GD.php b/includes/pear/Image/Canvas/GD.php index 227c3305..cff04643 100644 --- a/includes/pear/Image/Canvas/GD.php +++ b/includes/pear/Image/Canvas/GD.php @@ -1,1632 +1,1793 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: GD.php,v 1.8 2005/09/25 07:41:43 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -/** - * Include file Image/Canvas.php - */ -require_once 'Image/Canvas/WithMap.php'; - -/** - * Include file Image/Canvas/Color.php - */ -require_once 'Image/Canvas/Color.php'; - -/** - * Canvas class to output using PHP GD support. - * - * @category Images - * @package Image_Canvas - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - * @abstract - */ -class Image_Canvas_GD extends Image_Canvas_WithMap -{ - - /** - * The canvas of the graph - * @var resource - * @access private - */ - var $_canvas; - - /** - * The canvas to use for tiled filling - * @var resource - * @access private - */ - var $_tileImage = null; - - /** - * Is version GD2 installed? - * @var bool - * @access private - */ - var $_gd2 = true; - - /** - * Antialiasing? - * - * Possible values 'off', 'driver' and 'native' - * - * @var string - * @access private - */ - var $_antialias = 'off'; - - /** - * Create the GD canvas. - * - * Parameters available: - * - * 'width' The width of the graph on the canvas - * - * 'height' The height of the graph on the canvas - * - * 'left' The left offset of the graph on the canvas - * - * 'top' The top offset of the graph on the canvas - * - * 'antialias' = 'native' enables native GD antialiasing - this - * method has no severe impact on performance (approx +5%). Requires PHP - * 4.3.2 (with bundled GD2) - * - * 'antialias' = {true|'driver'} Image_Graph implemented method. This method - * has a severe impact on performance, drawing an antialiased line this - * way is about XX times slower, with an overall performance impact of - * about +40%. The justification for this method is that if native support - * is not available this can be used, it is also a future feature that this - * method for antialiasing will support line styles. - * - * Use antialiased for best results with a line/area chart having just a few - * datapoints. Native antialiasing does not provide a good appearance with - * short lines, as for example with smoothed charts. Antialiasing does not - * (currently) work with linestyles, neither native nor driver method! - * - * 'noalpha' = true If alpha blending is to be disabled - * - * 'filename' An image to open, on which the graph is created on - * - * 'gd' A GD resource to add the image to, use this option to continue - * working on an already existing GD resource. Make sure this is passed 'by- - * reference' (using &) - * - * 'usemap' Initialize an image map - * - * 'gd' and 'filename' are mutually exclusive with 'gd' as preference - * - * 'width' and 'height' are required unless 'filename' or 'gd' are - * specified, in which case the width and height are taken as the actual - * image width/height. If the latter is the case and 'left' and/or 'top' was - * also specified, the actual 'width'/'height' are altered so that the graph - * fits inside the canvas (i.e 'height' = actual height - top, etc.) - * - * @param array $param Parameter array - */ - function Image_Canvas_GD($param) - { - include_once 'Image/Canvas/Color.php'; - - parent::Image_Canvas_WithMap($param); - - $this->_gd2 = ($this->_version() == 2); - $this->_font = array('font' => 1, 'color' => 'black'); - - if ((isset($param['gd'])) && (is_resource($param['gd']))) { - $this->_canvas =& $param['gd']; - } elseif (isset($param['filename'])) { - $this->_canvas =& $this->_getGD($param['filename']); - } else { - if ($this->_gd2) { - $this->_canvas = ImageCreateTrueColor( - $this->_width, - $this->_height - ); - if ((!isset($param['noalpha'])) || ($param['noalpha'] !== true)) { - ImageAlphaBlending($this->_canvas, true); - } - } else { - $this->_canvas = ImageCreate($this->_width, $this->_height); - } - } - - if (isset($param['antialias'])) { - $this->_antialias = $param['antialias']; - } - - if ($this->_antialias === true) { - $this->_antialias = 'driver'; - } - - if (($this->_gd2) && ($this->_antialias === 'native')) { - ImageAntialias($this->_canvas, true); - } - } - - /** - * Get an GD image resource from a file - * - * @param string $filename - * @return mixed The GD image resource - * @access private - */ - function &_getGD($filename) - { - $info = getimagesize($filename); - - $result = null; - switch($info[2]) { - case IMG_PNG: - $result =& ImageCreateFromPNG($filename); - break; - - case IMG_JPG: - $result =& ImageCreateFromJPEG($filename); - break; - - case IMG_GIF: - $result =& ImageCreateFromGIF($filename); - break; - } - return $result; - } - - /** - * Get the color index for the RGB color - * - * @param int $color The color - * @return int The GD image index of the color - * @access private - */ - function _color($color = false) - { - if (($color === false) || ($color === 'opague') || ($color === 'transparent')) { - return ImageColorTransparent($this->_canvas); - } else { - return Image_Canvas_Color::allocateColor($this->_canvas, $color); - } - } - - /** - * Get the GD applicable linestyle - * - * @param mixed $lineStyle The line style to return, false if the one - * explicitly set - * @return mixed A GD compatible linestyle - * @access private - */ - function _getLineStyle($lineStyle = false) - { - if ($this->_gd2) { - ImageSetThickness($this->_canvas, $this->_thickness); - } - - if ($lineStyle == 'transparent') { - return false; - } elseif ($lineStyle === false) { - if (is_array($this->_lineStyle)) { - $colors = array(); - foreach ($this->_lineStyle as $color) { - if ($color === 'transparent') { - $color = false; - } - $colors[] = $this->_color($color); - } - ImageSetStyle($this->_canvas, $colors); - return IMG_COLOR_STYLED; - } else { - return $this->_color($this->_lineStyle); - } - } else { - return $this->_color($lineStyle); - } - } - - /** - * Get the GD applicable fillstyle - * - * @param mixed $fillStyle The fillstyle to return, false if the one - * explicitly set - * @return mixed A GD compatible fillstyle - * @access private - */ - function _getFillStyle($fillStyle = false, $x0 = 0, $y0 = 0, $x1 = 0, $y1 = 0) - { - if ($this->_tileImage != null) { - ImageDestroy($this->_tileImage); - $this->_tileImage = null; - } - if ($fillStyle == 'transparent') { - return false; - } elseif ($fillStyle === false) { - if (is_resource($this->_fillStyle)) { - $x = min($x0, $x1); - $y = min($y0, $y1); - $w = abs($x1 - $x0) + 1; - $h = abs($y1 - $y0) + 1; - if ($this->_gd2) { - $this->_tileImage = ImageCreateTrueColor( - $this->getWidth(), - $this->getHeight() - ); - - ImageCopyResampled( - $this->_tileImage, - $this->_fillStyle, - $x, - $y, - 0, - 0, - $w, - $h, - ImageSX($this->_fillStyle), - ImageSY($this->_fillStyle) - ); - } else { - $this->_tileImage = ImageCreate( - $this->getWidth(), - $this->getHeight() - ); - - ImageCopyResized( - $this->_tileImage, - $this->_fillStyle, - $x, - $y, - 0, - 0, - $w, - $h, - ImageSX($this->_fillStyle), - ImageSY($this->_fillStyle) - ); - } - ImageSetTile($this->_canvas, $this->_tileImage); - return IMG_COLOR_TILED; - } elseif ((is_array($this->_fillStyle)) && (isset($this->_fillStyle['direction']))) { - $width = abs($x1 - $x0) + 1; - $height = abs($y1 - $y0) + 1; - - switch ($this->_fillStyle['direction']) { - case 'horizontal': - $count = $width; - break; - - case 'vertical': - $count = $height; - break; - - case 'horizontal_mirror': - $count = $width / 2; - break; - - case 'vertical_mirror': - $count = $height / 2; - break; - - case 'diagonal_tl_br': - case 'diagonal_bl_tr': - $count = sqrt($width * $width + $height * $height); - break; - - case 'radial': - $count = max($width, $height, sqrt($width * $width + $height * $height)) + 1; - break; - - } - - $count = round($count); - - if ($this->_gd2) { - $this->_tileImage = ImageCreateTrueColor( - $this->getWidth(), - $this->getHeight() - ); - } else { - $this->_tileImage = ImageCreate( - $this->getWidth(), - $this->getHeight() - ); - } - - - $startColor = Image_Canvas_Color::color2RGB( - ($this->_fillStyle['direction'] == 'radial' ? - $this->_fillStyle['end'] : - $this->_fillStyle['start'] - ) - ); - $endColor = Image_Canvas_Color::color2RGB( - ($this->_fillStyle['direction'] == 'radial' ? - $this->_fillStyle['start'] : - $this->_fillStyle['end'] - ) - ); - - $redIncrement = ($endColor[0] - $startColor[0]) / $count; - $greenIncrement = ($endColor[1] - $startColor[1]) / $count; - $blueIncrement = ($endColor[2] - $startColor[2]) / $count; - - $color = false; - for ($i = 0; $i < $count; $i ++) { - unset($color); - if ($i == 0) { - $color = $startColor; - unset($color[3]); - } else { - $color[0] = round(($redIncrement * $i) + - $redIncrement + $startColor[0]); - $color[1] = round(($greenIncrement * $i) + - $greenIncrement + $startColor[1]); - $color[2] = round(($blueIncrement * $i) + - $blueIncrement + $startColor[2]); - } - $color = Image_Canvas_Color::allocateColor( - $this->_tileImage, - $color - ); - - switch ($this->_fillStyle['direction']) { - case 'horizontal': - ImageLine($this->_tileImage, - $x0 + $i, - $y0, - $x0 + $i, - $y1, $color); - break; - - case 'vertical': - ImageLine($this->_tileImage, - $x0, - $y1 - $i, - $x1, - $y1 - $i, $color); - break; - - case 'horizontal_mirror': - if (($x0 + $i) <= ($x1 - $i)) { - ImageLine($this->_tileImage, - $x0 + $i, - $y0, - $x0 + $i, - $y1, $color); - - ImageLine($this->_tileImage, - $x1 - $i, - $y0, - $x1 - $i, - $y1, $color); - } - break; - - case 'vertical_mirror': - if (($y0 + $i) <= ($y1 - $i)) { - ImageLine($this->_tileImage, - $x0, - $y0 + $i, - $x1, - $y0 + $i, $color); - ImageLine($this->_tileImage, - $x0, - $y1 - $i, - $x1, - $y1 - $i, $color); - } - break; - - case 'diagonal_tl_br': - if (($i > $width) && ($i > $height)) { - $polygon = array ( - $x1, $y0 + $i - $width - 1, - $x1, $y1, - $x0 + $i - $height - 1, $y1); - } elseif ($i > $width) { - $polygon = array ( - $x0, $y0 + $i, - $x0, $y1, - $x1, $y1, - $x1, $y0 + $i - $width - 1); - } elseif ($i > $height) { - $polygon = array ( - $x0 + $i - $height - 1, $y1, - $x1, $y1, - $x1, $y0, - $x0 + $i, $y0); - } else { - $polygon = array ( - $x0, $y0 + $i, - $x0, $y1, - $x1, $y1, - $x1, $y0, - $x0 + $i, $y0); - } - ImageFilledPolygon( - $this->_tileImage, - $polygon, - count($polygon) / 2, - $color - ); - break; - - case 'diagonal_bl_tr': - if (($i > $width) && ($i > $height)) { - $polygon = array ( - $x1, $y1 - $i + $width - 1, - $x1, $y0, - $x0 + $i - $height - 1, $y0); - } elseif ($i > $width) { - $polygon = array ( - $x0, $y1 - $i, - $x0, $y0, - $x1, $y0, - $x1, $y1 - $i + $width - 1); - } elseif ($i > $height) { - $polygon = array ( - $x0 + $i - $height - 1, $y0, - $x1, $y0, - $x1, $y1, - $x0 + $i, $y1); - } else { - $polygon = array ( - $x0, $y1 - $i, - $x0, $y0, - $x1, $y0, - $x1, $y1, - $x0 + $i, $y1); - } - ImageFilledPolygon( - $this->_tileImage, - $polygon, - count($polygon) / 2, - $color - ); - break; - - case 'radial': - if (($this->_gd2) && ($i < $count)) { - ImageFilledEllipse( - $this->_tileImage, - $x0 + $width / 2, - $y0 + $height / 2, - $count - $i, - $count - $i, - $color - ); - } - break; - } - } - ImageSetTile($this->_canvas, $this->_tileImage); - return IMG_COLOR_TILED; - } else { - return $this->_color($this->_fillStyle); - } - } else { - return $this->_color($fillStyle); - } - } - - /** - * Sets an image that should be used for filling - * - * @param string $filename The filename of the image to fill with - */ - function setFillImage($filename) - { - $this->_fillStyle =& $this->_getGD($filename); - } - - /** - * Sets the font options. - * - * The $font array may have the following entries: - * - * 'ttf' = the .ttf file (either the basename, filename or full path) - * If 'ttf' is specified, then the following can be specified - * - * 'size' = size in pixels - * - * 'angle' = the angle with which to write the text - * - * @param array $font The font options. - */ - function setFont($fontOptions) - { - parent::setFont($fontOptions); - - if (isset($this->_font['ttf'])) { - $this->_font['file'] = str_replace('\\', '/', $this->_mapFont($this->_font['ttf'])); - } elseif (!isset($this->_font['font'])) { - $this->_font['font'] = 1; - } - - if (!isset($this->_font['color'])) { - $this->_font['color'] = 'black'; - } - - if ((isset($this->_font['angle'])) && ($this->_font['angle'] === false)) { - $this->_font['angle'] = 0; - } - } - - /** - * Calculate pixels on a line - * - * @param int $x0 X start point - * @param int $y0 X start point - * @param int $x1 X end point - * @param int $y1 Y end point - * @return array An associated array of x,y points with all pixels on the - * line - * @access private - */ - function &_linePixels($x0, $y0, $x1, $y1) - { - $pixels = array(); - if (abs($x0 - $x1) > abs($y0 - $y1)) { - if ($x1 != $x0) { - $m = ($y1 - $y0) / ($x1 - $x0); - } else { - $m = 0; - } - $b = $y0 - $m * $x0; - $strx = min($x0, $x1); - $endx = max($x0, $x1); - for ($x = $strx; $x <= $endx; $x++) { - $pixels[] = array('X' => $x, 'Y' => ($m * $x + $b)); - } - } else { - if ($y1 != $y0) { - $m = ($x1 - $x0) / ($y1 - $y0); - } else { - $m = 0; - } - $b = $x0 - $m * $y0; - $stry = min($y0, $y1); - $endy = max($y0, $y1); - for ($y = $stry; $y <= $endy; $y++) { - $pixels[] = array('X' => ($m * $y + $b), 'Y' => $y); - } - } - return $pixels; - } - - /** - * Draws an antialiased line - * - * @param int $x0 X start point - * @param int $y0 X start point - * @param int $x1 X end point - * @param int $y1 Y end point - * @param mixed $color The line color, can be omitted - * @access private - */ - function _antialiasedLine($x0, $y0, $x1, $y1, $color = false) - { - if (($line = $this->_getLineStyle($color)) !== false) { - if ($line >= 0) { - $line = ImageColorsForIndex($this->_canvas, $line); - $pixels = &$this->_linePixels($x0, $y0, $x1, $y1); - foreach ($pixels as $point) { - $this->_antialiasedPixel($point['X'], $point['Y'], $line); - } - unset($pixels); - } - } - } - - - /** - * Draws an antialiased pixel - * - * @param int $x X point - * @param int $y Y point - * @param mixed $color The pixel color - * @access private - */ - function _antialiasedPixel($x, $y, $color) - { - $fx = floor($x); - $fy = floor($y); - $cx = ceil($x); - $cy = ceil($y); - $xa = $x - $fx; - $xb = $cx - $x; - $ya = $y - $fy; - $yb = $cy - $y; - if (($cx == $fx) && ($cy == $fy)) { - $this->_antialisedSubPixel($fx, $fy, 0.0, 1.0, $color); - } else { - $this->_antialisedSubPixel($fx, $fy, $xa + $ya, $xb + $yb, $color); - if ($cy != $fy) { - $this->_antialisedSubPixel($fx, $cy, $xa + $yb, $xb + $ya, $color); - } - if ($cx != $fx) { - $this->_antialisedSubPixel($cx, $fy, $xb + $ya, $xa + $yb, $color); - if ($cy != $fy) { - $this->_antialisedSubPixel($cx, $cy, $xb + $yb, $xa + $ya, $color); - } - } - } - } - - /** - * Antialias'es the pixel around x,y with weights a,b - * - * @param int $x X point - * @param int $y Y point - * @param int $a The weight of the current color - * @param int $b The weight of the applied/wanted color - * @param mixed $color The pixel color - * @access private - */ - function _antialisedSubPixel($x, $y, $a, $b, $color) - { - $x = $this->_getX($x); - $y = $this->_getX($y); - if (($x >=0 ) && ($y >= 0) && ($x < $this->getWidth()) && ($y < $this->getHeight())) { - $tempColor = ImageColorsForIndex($this->_canvas, ImageColorAt($this->_canvas, $x, $y)); - - $newColor[0] = min(255, round($tempColor['red'] * $a + $color['red'] * $b)); - $newColor[1] = min(255, round($tempColor['green'] * $a + $color['green'] * $b)); - $newColor[2] = min(255, round($tempColor['blue'] * $a + $color['blue'] * $b)); - //$newColor[3] = 0; - $color = '#'; - foreach ($newColor as $acolor) { - $color .= sprintf('%02s', dechex($acolor)); - } - $newColor = $this->_color($color);//,'rgb(' . $newColor[0] . ',' . $newColor[1] . ',' . $newColor[2] .')'; - - ImageSetPixel($this->_canvas, $x, $y, $newColor); - } - } - - - /** - * Draw a line end - * - * Parameter array: - * - * 'x': int X point - * - * 'y': int Y point - * - * 'end': string The end type of the end - * - * 'size': int The size of the end - * - * 'color': string The color of the end - * - * 'angle': int [optional] The angle with which to draw the end - * - * @param array $params Parameter array - */ - function drawEnd($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $size = $params['size']; - //var_dump($params); - $angle = deg2rad((isset($params['angle']) ? $params['angle'] : 0)); - $pi2 = pi() / 2; - switch ($params['end']) { - case 'lollipop': - case 'circle': - $this->ellipse( - array( - 'x' => $x, - 'y' => $y, - 'rx' => $size / 2, - 'ry' => $size / 2, - 'fill' => $params['color'], - 'line' => $params['color'] - ) - ); - break; - case 'diamond': - $x0 = round($params['x'] + cos($angle) * $size * 0.65); - $y0 = round($params['y'] - sin($angle) * $size * 0.65); - $shape = array( - $x0 + round(cos($angle) * $size * 0.65), - $y0 - round(sin($angle) * $size * 0.65), - $x0 + round(cos($angle + $pi2) * $size * 0.65), - $y0 - round(sin($angle + $pi2) * $size * 0.65), - $x0 + round(cos($angle + pi()) * $size * 0.65), - $y0 - round(sin($angle + pi()) * $size * 0.65), - $x0 + round(cos($angle + 3 * $pi2) * $size * 0.65), - $y0 - round(sin($angle + 3 * $pi2) * $size * 0.65) - ); - break; - case 'line': - $this->line( - array( - 'x0' => $x + round(cos($angle + $pi2) * $size / 2), - 'y0' => $y - round(sin($angle + $pi2) * $size / 2), - 'x1' => $x + round(cos($angle + 3 * $pi2) * $size / 2), - 'y1' => $y - round(sin($angle + 3 * $pi2) * $size / 2), - 'color' => $params['color'] - ) - ); - break; - case 'box': - case 'rectangle': - $x0 = round($params['x'] + cos($angle) * $size / 2); - $y0 = round($params['y'] - sin($angle) * $size / 2); - $pi4 = pi() / 4; - $shape = array( - $x0 + round(cos($angle + $pi4) * $size / 2), - $y0 - round(sin($angle + $pi4) * $size / 2), - $x0 + round(cos($angle + $pi2 + $pi4) * $size / 2), - $y0 - round(sin($angle + $pi2 + $pi4) * $size / 2), - $x0 + round(cos($angle + pi() + $pi4) * $size / 2), - $y0 - round(sin($angle + pi() + $pi4) * $size / 2), - $x0 + round(cos($angle + 3 * $pi2 + $pi4) * $size / 2), - $y0 - round(sin($angle + 3 * $pi2 + $pi4) * $size / 2) - ); - break; - case 'arrow': - $shape = array( - $x + cos($angle) * $size, - $y - sin($angle) * $size, - $x + cos($angle + $pi2) * $size * 0.4, - $y - sin($angle + $pi2) * $size * 0.4, - $x + cos($angle + 3 * $pi2) * $size * 0.4, - $y - sin($angle + 3 * $pi2) * $size * 0.4, - ); - break; - case 'arrow2': - $shape = array( - $x + round(cos($angle) * $size), - $y - round(sin($angle) * $size), - $x + round(cos($angle + $pi2 + deg2rad(45)) * $size), - $y - round(sin($angle + $pi2 + deg2rad(45)) * $size), - $x, - $y, - $x + round(cos($angle + 3 * $pi2 - deg2rad(45)) * $size), - $y - round(sin($angle + 3 * $pi2 - deg2rad(45)) * $size), - ); - break; - } - - if (isset($shape)) { - // output the shape - if (($fill = $this->_getFillStyle($params['color'])) !== false) { - ImageFilledPolygon($this->_canvas, $shape, count($shape)/2, $fill); - } - } - parent::drawEnd($params); - } - - /** - * Draw a line - * - * Parameter array: - * - * 'x0': int X start point - * - * 'y0': int Y start point - * - * 'x1': int X end point - * - * 'y1': int Y end point - * - * 'color': mixed [optional] The line color - * - * @param array $params Parameter array - */ - function line($params) - { - $x0 = $this->_getX($params['x0']); - $y0 = $this->_getY($params['y0']); - $x1 = $this->_getX($params['x1']); - $y1 = $this->_getY($params['y1']); - $color = (isset($params['color']) ? $params['color'] : false); - - $x0 = $this->_getX($x0); - $y0 = $this->_getY($y0); - $x1 = $this->_getX($x1); - $y1 = $this->_getY($y1); - if (($this->_antialias === 'driver') && ($x0 != $x1) && ($y0 != $y1)) { - $this->_antialiasedLine($x0, $y0, $x1, $y1, $color); - } elseif (($line = $this->_getLineStyle($color)) !== false) { - ImageLine($this->_canvas, $x0, $y0, $x1, $y1, $line); - } - parent::line($params); - } - - /** - * Parameter array: - * - * 'connect': bool [optional] Specifies whether the start point should be - * connected to the endpoint (closed polygon) or not (connected line) - * - * 'fill': mixed [optional] The fill color - * - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function polygon($params) - { - include_once 'Image/Canvas/Tool.php'; - - $connectEnds = (isset($params['connect']) ? $params['connect'] : false); - $fillColor = (isset($params['fill']) ? $params['fill'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - if (!$connectEnds) { - $fillColor = 'transparent'; - } - $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor); - - $lastPoint = false; - foreach ($this->_polygon as $point) { - if (($lastPoint) && (isset($lastPoint['P1X'])) && - (isset($lastPoint['P1Y'])) && (isset($lastPoint['P2X'])) && - (isset($lastPoint['P2Y']))) - { - $dx = abs($point['X'] - $lastPoint['X']); - $dy = abs($point['Y'] - $lastPoint['Y']); - $d = sqrt($dx * $dx + $dy * $dy); - if ($d > 0) { - $interval = 1 / $d; - for ($t = 0; $t <= 1; $t = $t + $interval) { - $x = Image_Canvas_Tool::bezier( - $t, - $lastPoint['X'], - $lastPoint['P1X'], - $lastPoint['P2X'], - $point['X'] - ); - - $y = Image_Canvas_Tool::bezier( - $t, - $lastPoint['Y'], - $lastPoint['P1Y'], - $lastPoint['P2Y'], - $point['Y'] - ); - - if (!isset($low['X'])) { - $low['X'] = $x; - } else { - $low['X'] = min($x, $low['X']); - } - if (!isset($high['X'])) { - $high['X'] = $x; - } else { - $high['X'] = max($x, $high['X']); - } - if (!isset($low['Y'])) { - $low['Y'] = $y; - } else { - $low['Y'] = min($y, $low['Y']); - } - if (!isset($high['Y'])) { - $high['Y'] = $y; - } else { - $high['Y'] = max($y, $high['Y']); - } - $polygon[] = $x; - $polygon[] = $y; - } - if (($t - $interval) < 1) { - $x = Image_Canvas_Tool::bezier( - 1, - $lastPoint['X'], - $lastPoint['P1X'], - $lastPoint['P2X'], - $point['X'] - ); - - $y = Image_Canvas_Tool::bezier( - 1, - $lastPoint['Y'], - $lastPoint['P1Y'], - $lastPoint['P2Y'], - $point['Y'] - ); - - $polygon[] = $x; - $polygon[] = $y; - } - } - } else { - if (!isset($low['X'])) { - $low['X'] = $point['X']; - } else { - $low['X'] = min($point['X'], $low['X']); - } - if (!isset($high['X'])) { - $high['X'] = $point['X']; - } else { - $high['X'] = max($point['X'], $high['X']); - } - if (!isset($low['Y'])) { - $low['Y'] = $point['Y']; - } else { - $low['Y'] = min($point['Y'], $low['Y']); - } - if (!isset($high['Y'])) { - $high['Y'] = $point['Y']; - } else { - $high['Y'] = max($point['Y'], $high['Y']); - } - - $polygon[] = $point['X']; - $polygon[] = $point['Y']; - } - $lastPoint = $point; - } - - if ((isset($polygon)) && (is_array($polygon))) { - if ($connectEnds) { - if (($fill = $this->_getFillStyle($fillColor, $low['X'], $low['Y'], $high['X'], $high['Y'])) !== false) { - ImageFilledPolygon($this->_canvas, $polygon, count($polygon)/2, $fill); - } - if ($this->_antialias === 'driver') { - $pfirst = $p0 = false; - reset($polygon); - - while (list(, $x) = each($polygon)) { - list(, $y) = each($polygon); - if ($p0 !== false) { - $this->_antialiasedLine($p0['X'], $p0['Y'], $x, $y, $lineColor); - } - if ($pfirst === false) { - $pfirst = array('X' => $x, 'Y' => $y); - } - $p0 = array('X' => $x, 'Y' => $y);; - } - - $this->_antialiasedLine($p0['X'], $p0['Y'], $pfirst['X'], $pfirst['Y'], $lineColor); - } elseif (($line = $this->_getLineStyle($lineColor)) !== false) { - ImagePolygon($this->_canvas, $polygon, count($polygon)/2, $line); - } - } else { - $prev_point = false; - if ($this->_antialias === 'driver') { - reset($polygon); - while (list(, $x) = each($polygon)) { - list(, $y) = each($polygon); - if ($prev_point) { - $this->_antialiasedLine( - $prev_point['X'], - $prev_point['Y'], - $x, - $y, - $lineColor - ); - } - $prev_point = array('X' => $x, 'Y' => $y);; - } - } elseif (($line = $this->_getLineStyle($lineColor)) !== false) { - reset($polygon); - while (list(, $x) = each($polygon)) { - list(, $y) = each($polygon); - if ($prev_point) { - ImageLine( - $this->_canvas, - $prev_point['X'], - $prev_point['Y'], - $x, - $y, - $line - ); - } - $prev_point = array('X' => $x, 'Y' => $y);; - } - } - } - } - - parent::polygon($params); - } - - /** - * Draw a rectangle - * - * Parameter array: - * - * 'x0': int X start point - * - * 'y0': int Y start point - * - * 'x1': int X end point - * - * 'y1': int Y end point - * - * 'fill': mixed [optional] The fill color - * - * 'line': mixed [optional] The line color - * - * @param array $params Parameter array - */ - function rectangle($params) - { - $x0 = $this->_getX($params['x0']); - $y0 = $this->_getY($params['y0']); - $x1 = $this->_getX($params['x1']); - $y1 = $this->_getY($params['y1']); - $fillColor = (isset($params['fill']) ? $params['fill'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - if (($fill = $this->_getFillStyle($fillColor, $x0, $y0, $x1, $y1)) !== false) { - ImageFilledRectangle($this->_canvas, $x0, $y0, $x1, $y1, $fill); - } - - if (($line = $this->_getLineStyle($lineColor)) !== false) { - ImageRectangle($this->_canvas, $x0, $y0, $x1, $y1, $line); - } - - parent::rectangle($params); - } - - /** - * Draw an ellipse - * - * Parameter array: - * - * 'x': int X center point - * - * 'y': int Y center point - * - * 'rx': int X radius - * - * 'ry': int Y radius - * - * 'fill': mixed [optional] The fill color - * - * 'line': mixed [optional] The line color - * - * @param array $params Parameter array - */ - function ellipse($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $rx = $this->_getX($params['rx']); - $ry = $this->_getY($params['ry']); - $fillColor = (isset($params['fill']) ? $params['fill'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - if (($fill = $this->_getFillStyle($fillColor, $x - $rx, $y - $ry, $x + $rx, $y + $ry)) !== false) { - ImageFilledEllipse($this->_canvas, $x, $y, $rx * 2, $ry * 2, $fill); - } - - if (($line = $this->_getLineStyle($lineColor)) !== false) { - ImageEllipse($this->_canvas, $x, $y, $rx * 2, $ry * 2, $line); - } - parent::ellipse($params); - } - - /** - * Draw a pie slice - * - * Parameter array: - * - * 'x': int X center point - * - * 'y': int Y center point - * - * 'rx': int X radius - * - * 'ry': int Y radius - * - * 'v1': int The starting angle (in degrees) - * - * 'v2': int The end angle (in degrees) - * - * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) - * - * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) - * - * 'fill': mixed [optional] The fill color - * - * 'line': mixed [optional] The line color - * - * @param array $params Parameter array - */ - function pieslice($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $rx = $params['rx']; - $ry = $params['ry']; - $v1 = $params['v1']; - $v2 = $params['v2']; - $srx = (isset($params['srx']) ? $params['srx'] : 0); - $sry = (isset($params['sry']) ? $params['sry'] : 0); - $fillColor = (isset($params['fill']) ? $params['fill'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - $dA = 0.1; - - if (($srx !== false) && ($sry !== false)) { - $angle = max($v1, $v2); - while ($angle >= min($v1, $v2)) { - $polygon[] = ($x + $srx * cos(deg2rad($angle % 360))); - $polygon[] = ($y + $sry * sin(deg2rad($angle % 360))); - $angle -= $dA; - } - if (($angle + $dA) > min($v1, $v2)) { - $polygon[] = ($x + $srx * cos(deg2rad(min($v1, $v2) % 360))); - $polygon[] = ($y + $sry * sin(deg2rad(min($v1, $v2) % 360))); - } - } else { - $polygon[] = $x; - $polygon[] = $y; - } - - $angle = min($v1, $v2); - while ($angle <= max($v1, $v2)) { - $polygon[] = ($x + $rx * cos(deg2rad($angle % 360))); - $polygon[] = ($y + $ry * sin(deg2rad($angle % 360))); - $angle += $dA; - } - - if (($angle - $dA) < max($v1, $v2)) { - $polygon[] = ($x + $rx * cos(deg2rad(max($v1, $v2) % 360))); - $polygon[] = ($y + $ry * sin(deg2rad(max($v1, $v2) % 360))); - } - - if (($fill = $this->_getFillStyle($fillColor, $x - $rx - 1, $y - $ry - 1, $x + $rx + 1, $y + $ry + 1)) !== false) { - ImageFilledPolygon($this->_canvas, $polygon, count($polygon) / 2, $fill); - } - - if (($line = $this->_getLineStyle($lineColor)) !== false) { - ImagePolygon($this->_canvas, $polygon, count($polygon) / 2, $line); - } - - parent::pieSlice($params); - } - - /** - * Get the width of a text, - * - * @param string $text The text to get the width of - * @return int The width of the text - */ - function textWidth($text) - { - if (isset($this->_font['file'])) { - $angle = 0; - if (isset($this->_font['angle'])) { - $angle = $this->_font['angle']; - } - - $width = 0; - $lines = explode("\n", $text); - foreach ($lines as $line) { - $bounds = ImageTTFBBox( - $this->_font['size'], - $angle, - $this->_font['file'], - $text - ); - - $x0 = min($bounds[0], $bounds[2], $bounds[4], $bounds[6]); - $x1 = max($bounds[0], $bounds[2], $bounds[4], $bounds[6]); - $width = max(abs($x0 - $x1), $width); - } - return $width; - } else { - if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { - return ImageFontHeight($this->_font['font']) * (substr_count($text, "\n") + 1); - } else { - $width = 0; - $lines = explode("\n", $text); - foreach ($lines as $line) { - $width = max($width, ImageFontWidth($this->_font['font']) * strlen($line)); - } - return $width; - } - } - } - - /** - * Get the height of a text. - * - * Note! This method can give some peculiar results, since ImageTTFBBox() returns the total - * bounding box of a text, where ImageTTF() writes the text on the baseline of the text, that - * is 'g', 'p', 'q' and other letters that dig under the baseline will appear to have a larger - * height than they actually do. Have a look at the tests/text.php test case - the first two - * columns, 'left and 'center', both look alright, whereas the last column, 'right', appear - * with a larger space between the first text and the second. This is because the total height - * is actually smaller by exactly the number of pixels that the 'g' digs under the baseline. - * Remove the 'g' from the text and they appear correct. - * - * @param string $text The text to get the height of - * @param bool $force Force the method to calculate the size - * @return int The height of the text - */ - function textHeight($text, $force = false) - { - if (isset($this->_font['file'])) { - $angle = 0; - if (isset($this->_font['angle'])) { - $angle = $this->_font['angle']; - } - - $linebreaks = substr_count($text, "\n"); - if (($angle == 0) && ($linebreaks == 0) && ($force === false)) { - /* - * if the angle is 0 simply return the size, due to different - * heights for example for x-axis labels, making the labels - * _not_ appear as written on the same baseline - */ - return $this->_font['size'] + 2; - } - - $height = 0; - $lines = explode("\n", $text); - foreach ($lines as $line) { - $bounds = ImageTTFBBox( - $this->_font['size'], - $angle, - $this->_font['file'], - $line - ); - - $y0 = min($bounds[1], $bounds[3], $bounds[5], $bounds[7]); - $y1 = max($bounds[1], $bounds[3], $bounds[5], $bounds[7]); - $height += abs($y0 - $y1); - } - return $height + $linebreaks * 2; - } else { - if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { - $width = 0; - $lines = explode("\n", $text); - foreach ($lines as $line) { - $width = max($width, ImageFontWidth($this->_font['font']) * strlen($line)); - } - return $width; - } else { - return ImageFontHeight($this->_font['font']) * (substr_count($text, "\n") + 1); - } - } - } - - /** - * Writes text - * - * Parameter array: - * - * 'x': int X-point of text - * - * 'y': int Y-point of text - * - * 'text': string The text to add - * - * 'alignment': array [optional] Alignment - * - * 'color': mixed [optional] The color of the text - */ - function addText($params) - { - $x0 = $this->_getX($params['x']); - $y0 = $this->_getY($params['y']); - $text = $params['text']; - $color = (isset($params['color']) ? $params['color'] : false); - $alignment = (isset($params['alignment']) ? $params['alignment'] : false); - - $text = str_replace("\r", '', $text); - - if (!is_array($alignment)) { - $alignment = array('vertical' => 'top', 'horizontal' => 'left'); - } - - if (!isset($alignment['vertical'])) { - $alignment['vertical'] = 'top'; - } - - if (!isset($alignment['horizontal'])) { - $alignment['horizontal'] = 'left'; - } - - if ($alignment['vertical'] == 'bottom') { - $y0 = $y0 - $this->textHeight($text, true); - } elseif ($alignment['vertical'] == 'center') { - $y0 = $y0 - ($this->textHeight($text, true) / 2); - } - - $lines = explode("\n", $text); - foreach ($lines as $line) { - $textWidth = $this->textWidth($line); - $textHeight = $this->textHeight($line, true); - - $x = $x0; - $y = $y0; - - $y0 += $textHeight + 2; - - if ($alignment['horizontal'] == 'right') { - $x = $x - $textWidth; - } elseif ($alignment['horizontal'] == 'center') { - $x = $x - ($textWidth / 2); - } - - if (($color === false) && (isset($this->_font['color']))) { - $color = $this->_font['color']; - } - - if ($color != 'transparent') { - if (isset($this->_font['file'])) { - if (($this->_font['angle'] < 180) && ($this->_font['angle'] >= 0)) { - $y += $textHeight; - } - if (($this->_font['angle'] >= 90) && ($this->_font['angle'] < 270)) { - $x += $textWidth; - } - - ImageTTFText( - $this->_canvas, - $this->_font['size'], - $this->_font['angle'], - $x, - $y, - $this->_color($color), - $this->_font['file'], - $line - ); - - } else { - if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { - ImageStringUp( - $this->_canvas, - $this->_font['font'], - $x, - $y + $this->textHeight($text), - $line, - $this->_color($color) - ); - } else { - ImageString( - $this->_canvas, - $this->_font['font'], - $x, - $y, - $line, - $this->_color($color) - ); - } - } - } - } - parent::addText($params); - } - - /** - * Overlay image - * - * Parameter array: - * - * 'x': int X-point of overlayed image - * - * 'y': int Y-point of overlayed image - * - * 'filename': string The filename of the image to overlay - * - * 'width': int [optional] The width of the overlayed image (resizing if possible) - * - * 'height': int [optional] The height of the overlayed image (resizing if possible) - * - * 'alignment': array [optional] Alignment - */ - function image($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $filename = $params['filename']; - $width = (isset($params['width']) ? $params['width'] : false); - $height = (isset($params['height']) ? $params['height'] : false); - $alignment = (isset($params['alignment']) ? $params['alignment'] : false); - - if (!is_array($alignment)) { - $alignment = array('vertical' => 'top', 'horizontal' => 'left'); - } - - if (!isset($alignment['vertical'])) { - $alignment['vertical'] = 'top'; - } - - if (!isset($alignment['horizontal'])) { - $alignment['horizontal'] = 'left'; - } - - if (file_exists($filename)) { - if (strtolower(substr($filename, -4)) == '.png') { - $image = ImageCreateFromPNG($filename); - } elseif (strtolower(substr($filename, -4)) == '.gif') { - $image = ImageCreateFromGIF($filename); - } else { - $image = ImageCreateFromJPEG($filename); - } - - $imgWidth = ImageSX($image); - $imgHeight = ImageSY($image); - - $outputWidth = ($width !== false ? $width : $imgWidth); - $outputHeight = ($height !== false ? $height : $imgHeight); - - if ($alignment['horizontal'] == 'right') { - $x -= $outputWidth; - } elseif ($alignment['horizontal'] == 'center') { - $x -= $outputWidth / 2; - } - - if ($alignment['vertical'] == 'bottom') { - $y -= $outputHeight; - } elseif ($alignment['vertical'] == 'center') { - $y -= $outputHeight / 2; - } - - if ((($width !== false) && ($width != $imgWidth)) || - (($height !== false) && ($height != $imgHeight))) - { - if ($this->_gd2) { - ImageCopyResampled( - $this->_canvas, - $image, - $x, - $y, - 0, - 0, - $width, - $height, - $imgWidth, - $imgHeight - ); - } else { - ImageCopyResized( - $this->_canvas, - $image, - $x, - $y, - 0, - 0, - $width, - $height, - $imgWidth, - $imgHeight - ); - } - } else { - ImageCopy( - $this->_canvas, - $image, - $x, - $y, - 0, - 0, - $imgWidth, - $imgHeight - ); - } - ImageDestroy($image); - } - parent::image($params); - } - - /** - * Get a canvas specific HTML tag. - * - * This method implicitly saves the canvas to the filename in the - * filesystem path specified and parses it as URL specified by URL path - * - * Parameter array: - * - * 'filename' string - * - * 'filepath': string Path to the file on the file system. Remember the final slash - * - * 'urlpath': string Path to the file available through an URL. Remember the final slash - * - * 'alt': string [optional] Alternative text on image - * - * 'cssclass': string [optional] The CSS Stylesheet class - * - * 'border': int [optional] The border width on the image - */ - function toHtml($params) - { - parent::toHtml($params); - return '' . $params['alt'] . '_imageMap) ? ' usemap="#' . $params['filename'] . '"' : '') . '>' . - (isset($this->_imageMap) ? "\n" . $this->_imageMap->toHtml(array('name' => $params['filename'])) : ''); - } - - /** - * Resets the canvas. - * - * Include fillstyle, linestyle, thickness and polygon - * @access private - */ - function _reset() - { - if ($this->_gd2) { - ImageSetThickness($this->_canvas, 1); - } - if ($this->_tileImage != null) { - ImageDestroy($this->_tileImage); - $this->_tileImage = null; - } - parent::_reset(); - $this->_font = array('font' => 1, 'color' => 'black'); - } - - /** - * Check which version of GD is installed - * - * @return int 0 if GD isn't installed, 1 if GD 1.x is installed and 2 if GD - * 2.x is installed - * @access private - */ - function _version() - { - $result = false; - if (function_exists('gd_info')) { - $info = gd_info(); - $version = $info['GD Version']; - } else { - ob_start(); - phpinfo(8); - $php_info = ob_get_contents(); - ob_end_clean(); - - if (ereg("]*>GD Version *<\/td>]*>([^<]*)<\/td>", - $php_info, $result)) - { - $version = $result[1]; - } - } - - if (ereg('1\.[0-9]{1,2}', $version)) { - return 1; - } elseif (ereg('2\.[0-9]{1,2}', $version)) { - return 2; - } else { - return 0; - } - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: GD.php,v 1.16 2007/06/22 20:19:54 nosey Exp $ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ + +/** + * Include file Image/Canvas.php + */ +require_once 'Image/Canvas/WithMap.php'; + +/** + * Include file Image/Canvas/Color.php + */ +require_once 'Image/Canvas/Color.php'; + +/** + * Canvas class to output using PHP GD support. + * + * @category Images + * @package Image_Canvas + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + * @abstract + */ +class Image_Canvas_GD extends Image_Canvas_WithMap +{ + + /** + * The canvas of the graph + * @var resource + * @access private + */ + var $_canvas; + + /** + * The canvas to use for tiled filling + * @var resource + * @access private + */ + var $_tileImage = null; + + /** + * Is version GD2 installed? + * @var bool + * @access private + */ + var $_gd2 = true; + + /** + * Antialiasing? + * + * Possible values 'off', 'driver' and 'native' + * + * @var string + * @access private + */ + var $_antialias = 'off'; + + var $_alpha = false; + + var $_clipping = array(); + + /** + * Create the GD canvas. + * + * Parameters available: + * + * 'width' The width of the graph on the canvas + * + * 'height' The height of the graph on the canvas + * + * 'left' The left offset of the graph on the canvas + * + * 'top' The top offset of the graph on the canvas + * + * 'antialias' = 'native' enables native GD antialiasing - this + * method has no severe impact on performance (approx +5%). Requires PHP + * 4.3.2 (with bundled GD2) + * + * 'antialias' = {true|'driver'} Image_Graph implemented method. This method + * has a severe impact on performance, drawing an antialiased line this + * way is about XX times slower, with an overall performance impact of + * about +40%. The justification for this method is that if native support + * is not available this can be used, it is also a future feature that this + * method for antialiasing will support line styles. + * + * Use antialiased for best results with a line/area chart having just a few + * datapoints. Native antialiasing does not provide a good appearance with + * short lines, as for example with smoothed charts. Antialiasing does not + * (currently) work with linestyles, neither native nor driver method! + * + * 'noalpha' = true If alpha blending is to be disabled + * + * 'filename' An image to open, on which the graph is created on + * + * 'gd' A GD resource to add the image to, use this option to continue + * working on an already existing GD resource. Make sure this is passed 'by- + * reference' (using &) + * + * 'usemap' Initialize an image map + * + * 'gd' and 'filename' are mutually exclusive with 'gd' as preference + * + * 'width' and 'height' are required unless 'filename' or 'gd' are + * specified, in which case the width and height are taken as the actual + * image width/height. If the latter is the case and 'left' and/or 'top' was + * also specified, the actual 'width'/'height' are altered so that the graph + * fits inside the canvas (i.e 'height' = actual height - top, etc.) + * + * @param array $param Parameter array + */ + function Image_Canvas_GD($param) + { + include_once 'Image/Canvas/Color.php'; + + parent::Image_Canvas_WithMap($param); + + $this->_gd2 = ($this->_version() == 2); + $this->_font = array('font' => 1, 'color' => 'black'); + + if ((isset($param['gd'])) && (is_resource($param['gd']))) { + $this->_canvas =& $param['gd']; + } elseif (isset($param['filename'])) { + $this->_canvas =& $this->_getGD($param['filename']); + } else { + if ($this->_gd2) { + $this->_canvas = ImageCreateTrueColor( + $this->_width, + $this->_height + ); + if ((!isset($param['noalpha'])) || ($param['noalpha'] !== true)) { + ImageAlphaBlending($this->_canvas, true); + $this->_alpha = true; + } + } else { + $this->_canvas = ImageCreate($this->_width, $this->_height); + } + } + + if (isset($param['antialias'])) { + $this->_antialias = $param['antialias']; + } + + if ($this->_antialias === true) { + $this->_antialias = 'driver'; + } + + if (($this->_gd2) && ($this->_antialias === 'native') && (function_exists('ImageAntialias'))) { + ImageAntialias($this->_canvas, true); + } + } + + /** + * Get an GD image resource from a file + * + * @param string $filename + * @return mixed The GD image resource + * @access private + */ + function &_getGD($filename) + { + $info = getimagesize($filename); + + $result = null; + switch($info[2]) { + case IMG_PNG: + $result =& ImageCreateFromPNG($filename); + break; + + case IMG_JPG: + $result =& ImageCreateFromJPEG($filename); + break; + + case IMG_GIF: + $result =& ImageCreateFromGIF($filename); + break; + } + return $result; + } + + /** + * Get the color index for the RGB color + * + * @param int $color The color + * @return int The GD image index of the color + * @access private + */ + function _color($color = false) + { + if (($color === false) || ($color === 'opague') || ($color === 'transparent')) { + return ImageColorTransparent($this->_canvas); + } else { + return Image_Canvas_Color::allocateColor($this->_canvas, $color); + } + } + + /** + * Get the GD applicable linestyle + * + * @param mixed $lineStyle The line style to return, false if the one + * explicitly set + * @return mixed A GD compatible linestyle + * @access private + */ + function _getLineStyle($lineStyle = false) + { + if ($this->_gd2) { + ImageSetThickness($this->_canvas, $this->_thickness); + } + + if ($lineStyle == 'transparent') { + return false; + } elseif ($lineStyle === false) { + if (is_array($this->_lineStyle)) { + $colors = array(); + foreach ($this->_lineStyle as $color) { + if ($color === 'transparent') { + $color = false; + } + $colors[] = $this->_color($color); + } + ImageSetStyle($this->_canvas, $colors); + return IMG_COLOR_STYLED; + } else { + return $this->_color($this->_lineStyle); + } + } else { + return $this->_color($lineStyle); + } + } + + /** + * Get the GD applicable fillstyle + * + * @param mixed $fillStyle The fillstyle to return, false if the one + * explicitly set + * @return mixed A GD compatible fillstyle + * @access private + */ + function _getFillStyle($fillStyle = false, $x0 = 0, $y0 = 0, $x1 = 0, $y1 = 0) + { + if ($this->_tileImage != null) { + ImageDestroy($this->_tileImage); + $this->_tileImage = null; + } + if ($fillStyle == 'transparent') { + return false; + } elseif ($fillStyle === false) { + if (is_resource($this->_fillStyle)) { + $x = min($x0, $x1); + $y = min($y0, $y1); + $w = abs($x1 - $x0) + 1; + $h = abs($y1 - $y0) + 1; + if ($this->_gd2) { + $this->_tileImage = ImageCreateTrueColor( + $this->getWidth(), + $this->getHeight() + ); + + ImageCopyResampled( + $this->_tileImage, + $this->_fillStyle, + $x, + $y, + 0, + 0, + $w, + $h, + ImageSX($this->_fillStyle), + ImageSY($this->_fillStyle) + ); + } else { + $this->_tileImage = ImageCreate( + $this->getWidth(), + $this->getHeight() + ); + + ImageCopyResized( + $this->_tileImage, + $this->_fillStyle, + $x, + $y, + 0, + 0, + $w, + $h, + ImageSX($this->_fillStyle), + ImageSY($this->_fillStyle) + ); + } + ImageSetTile($this->_canvas, $this->_tileImage); + return IMG_COLOR_TILED; + } elseif ((is_array($this->_fillStyle)) && (isset($this->_fillStyle['direction']))) { + $width = abs($x1 - $x0) + 1; + $height = abs($y1 - $y0) + 1; + + switch ($this->_fillStyle['direction']) { + case 'horizontal': + $count = $width; + break; + + case 'vertical': + $count = $height; + break; + + case 'horizontal_mirror': + $count = $width / 2; + break; + + case 'vertical_mirror': + $count = $height / 2; + break; + + case 'diagonal_tl_br': + case 'diagonal_bl_tr': + $count = sqrt($width * $width + $height * $height); + break; + + case 'radial': + $count = max($width, $height, sqrt($width * $width + $height * $height)) + 1; + break; + + } + + $count = round($count); + + if ($this->_gd2) { + $this->_tileImage = ImageCreateTrueColor( + $this->getWidth(), + $this->getHeight() + ); + } else { + $this->_tileImage = ImageCreate( + $this->getWidth(), + $this->getHeight() + ); + } + + + $startColor = Image_Canvas_Color::color2RGB( + ($this->_fillStyle['direction'] == 'radial' ? + $this->_fillStyle['end'] : + $this->_fillStyle['start'] + ) + ); + $endColor = Image_Canvas_Color::color2RGB( + ($this->_fillStyle['direction'] == 'radial' ? + $this->_fillStyle['start'] : + $this->_fillStyle['end'] + ) + ); + + $redIncrement = ($endColor[0] - $startColor[0]) / $count; + $greenIncrement = ($endColor[1] - $startColor[1]) / $count; + $blueIncrement = ($endColor[2] - $startColor[2]) / $count; + + $color = false; + for ($i = 0; $i < $count; $i ++) { + unset($color); + if ($i == 0) { + $color = $startColor; + unset($color[3]); + } else { + $color[0] = round(($redIncrement * $i) + + $redIncrement + $startColor[0]); + $color[1] = round(($greenIncrement * $i) + + $greenIncrement + $startColor[1]); + $color[2] = round(($blueIncrement * $i) + + $blueIncrement + $startColor[2]); + } + $color = Image_Canvas_Color::allocateColor( + $this->_tileImage, + $color + ); + + switch ($this->_fillStyle['direction']) { + case 'horizontal': + ImageLine($this->_tileImage, + $x0 + $i, + $y0, + $x0 + $i, + $y1, $color); + break; + + case 'vertical': + ImageLine($this->_tileImage, + $x0, + $y1 - $i, + $x1, + $y1 - $i, $color); + break; + + case 'horizontal_mirror': + if (($x0 + $i) <= ($x1 - $i)) { + ImageLine($this->_tileImage, + $x0 + $i, + $y0, + $x0 + $i, + $y1, $color); + + ImageLine($this->_tileImage, + $x1 - $i, + $y0, + $x1 - $i, + $y1, $color); + } + break; + + case 'vertical_mirror': + if (($y0 + $i) <= ($y1 - $i)) { + ImageLine($this->_tileImage, + $x0, + $y0 + $i, + $x1, + $y0 + $i, $color); + ImageLine($this->_tileImage, + $x0, + $y1 - $i, + $x1, + $y1 - $i, $color); + } + break; + + case 'diagonal_tl_br': + if (($i > $width) && ($i > $height)) { + $polygon = array ( + $x1, $y0 + $i - $width - 1, + $x1, $y1, + $x0 + $i - $height - 1, $y1); + } elseif ($i > $width) { + $polygon = array ( + $x0, $y0 + $i, + $x0, $y1, + $x1, $y1, + $x1, $y0 + $i - $width - 1); + } elseif ($i > $height) { + $polygon = array ( + $x0 + $i - $height - 1, $y1, + $x1, $y1, + $x1, $y0, + $x0 + $i, $y0); + } else { + $polygon = array ( + $x0, $y0 + $i, + $x0, $y1, + $x1, $y1, + $x1, $y0, + $x0 + $i, $y0); + } + ImageFilledPolygon( + $this->_tileImage, + $polygon, + count($polygon) / 2, + $color + ); + break; + + case 'diagonal_bl_tr': + if (($i > $width) && ($i > $height)) { + $polygon = array ( + $x1, $y1 - $i + $width - 1, + $x1, $y0, + $x0 + $i - $height - 1, $y0); + } elseif ($i > $width) { + $polygon = array ( + $x0, $y1 - $i, + $x0, $y0, + $x1, $y0, + $x1, $y1 - $i + $width - 1); + } elseif ($i > $height) { + $polygon = array ( + $x0 + $i - $height - 1, $y0, + $x1, $y0, + $x1, $y1, + $x0 + $i, $y1); + } else { + $polygon = array ( + $x0, $y1 - $i, + $x0, $y0, + $x1, $y0, + $x1, $y1, + $x0 + $i, $y1); + } + ImageFilledPolygon( + $this->_tileImage, + $polygon, + count($polygon) / 2, + $color + ); + break; + + case 'radial': + if (($this->_gd2) && ($i < $count)) { + ImageFilledEllipse( + $this->_tileImage, + $x0 + $width / 2, + $y0 + $height / 2, + $count - $i, + $count - $i, + $color + ); + } + break; + } + } + ImageSetTile($this->_canvas, $this->_tileImage); + return IMG_COLOR_TILED; + } else { + return $this->_color($this->_fillStyle); + } + } else { + return $this->_color($fillStyle); + } + } + + /** + * Sets an image that should be used for filling + * + * @param string $filename The filename of the image to fill with + */ + function setFillImage($filename) + { + $this->_fillStyle =& $this->_getGD($filename); + } + + /** + * Sets the font options. + * + * The $font array may have the following entries: + * + * 'ttf' = the .ttf file (either the basename, filename or full path) + * If 'ttf' is specified, then the following can be specified + * + * 'size' = size in pixels + * + * 'angle' = the angle with which to write the text + * + * @param array $font The font options. + */ + function setFont($fontOptions) + { + parent::setFont($fontOptions); + + if (isset($this->_font['ttf'])) { + $this->_font['file'] = str_replace('\\', '/', Image_Canvas_Tool::fontMap($this->_font['ttf'])); + } elseif (!isset($this->_font['font'])) { + $this->_font['font'] = 1; + } + + if (!isset($this->_font['color'])) { + $this->_font['color'] = 'black'; + } + + if ((isset($this->_font['angle'])) && ($this->_font['angle'] === false)) { + $this->_font['angle'] = 0; + } + } + + /** + * Calculate pixels on a line + * + * @param int $x0 X start point + * @param int $y0 X start point + * @param int $x1 X end point + * @param int $y1 Y end point + * @return array An associated array of x,y points with all pixels on the + * line + * @access private + */ + function &_linePixels($x0, $y0, $x1, $y1) + { + $pixels = array(); + if (abs($x0 - $x1) > abs($y0 - $y1)) { + if ($x1 != $x0) { + $m = ($y1 - $y0) / ($x1 - $x0); + } else { + $m = 0; + } + $b = $y0 - $m * $x0; + $strx = min($x0, $x1); + $endx = max($x0, $x1); + for ($x = $strx; $x <= $endx; $x++) { + $pixels[] = array('X' => $x, 'Y' => ($m * $x + $b)); + } + } else { + if ($y1 != $y0) { + $m = ($x1 - $x0) / ($y1 - $y0); + } else { + $m = 0; + } + $b = $x0 - $m * $y0; + $stry = min($y0, $y1); + $endy = max($y0, $y1); + for ($y = $stry; $y <= $endy; $y++) { + $pixels[] = array('X' => ($m * $y + $b), 'Y' => $y); + } + } + return $pixels; + } + + /** + * Draws an antialiased line + * + * @param int $x0 X start point + * @param int $y0 X start point + * @param int $x1 X end point + * @param int $y1 Y end point + * @param mixed $color The line color, can be omitted + * @access private + */ + function _antialiasedLine($x0, $y0, $x1, $y1, $color = false) + { + if (($line = $this->_getLineStyle($color)) !== false) { + if ($line >= 0) { + $line = ImageColorsForIndex($this->_canvas, $line); + $pixels = &$this->_linePixels($x0, $y0, $x1, $y1); + foreach ($pixels as $point) { + $this->_antialiasedPixel($point['X'], $point['Y'], $line); + } + unset($pixels); + } + } + } + + + /** + * Draws an antialiased pixel + * + * @param int $x X point + * @param int $y Y point + * @param mixed $color The pixel color + * @access private + */ + function _antialiasedPixel($x, $y, $color) + { + $fx = floor($x); + $fy = floor($y); + $cx = ceil($x); + $cy = ceil($y); + $xa = $x - $fx; + $xb = $cx - $x; + $ya = $y - $fy; + $yb = $cy - $y; + if (($cx == $fx) && ($cy == $fy)) { + $this->_antialisedSubPixel($fx, $fy, 0.0, 1.0, $color); + } else { + $this->_antialisedSubPixel($fx, $fy, $xa + $ya, $xb + $yb, $color); + if ($cy != $fy) { + $this->_antialisedSubPixel($fx, $cy, $xa + $yb, $xb + $ya, $color); + } + if ($cx != $fx) { + $this->_antialisedSubPixel($cx, $fy, $xb + $ya, $xa + $yb, $color); + if ($cy != $fy) { + $this->_antialisedSubPixel($cx, $cy, $xb + $yb, $xa + $ya, $color); + } + } + } + } + + /** + * Antialias'es the pixel around x,y with weights a,b + * + * @param int $x X point + * @param int $y Y point + * @param int $a The weight of the current color + * @param int $b The weight of the applied/wanted color + * @param mixed $color The pixel color + * @access private + */ + function _antialisedSubPixel($x, $y, $a, $b, $color) + { + $x = $this->_getX($x); + $y = $this->_getX($y); + if (($x >=0 ) && ($y >= 0) && ($x < $this->getWidth()) && ($y < $this->getHeight())) { + $tempColor = ImageColorsForIndex($this->_canvas, ImageColorAt($this->_canvas, $x, $y)); + + $newColor[0] = min(255, round($tempColor['red'] * $a + $color['red'] * $b)); + $newColor[1] = min(255, round($tempColor['green'] * $a + $color['green'] * $b)); + $newColor[2] = min(255, round($tempColor['blue'] * $a + $color['blue'] * $b)); + //$newColor[3] = 0; + $color = '#'; + foreach ($newColor as $acolor) { + $color .= sprintf('%02s', dechex($acolor)); + } + $newColor = $this->_color($color);//,'rgb(' . $newColor[0] . ',' . $newColor[1] . ',' . $newColor[2] .')'; + + ImageSetPixel($this->_canvas, $x, $y, $newColor); + } + } + + + /** + * Draw a line end + * + * Parameter array: + * + * 'x': int X point + * + * 'y': int Y point + * + * 'end': string The end type of the end + * + * 'size': int The size of the end + * + * 'color': string The color of the end + * + * 'angle': int [optional] The angle with which to draw the end + * + * @param array $params Parameter array + */ + function drawEnd($params) + { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $size = $params['size']; + //var_dump($params); + $angle = deg2rad((isset($params['angle']) ? $params['angle'] : 0)); + $pi2 = pi() / 2; + switch ($params['end']) { + case 'lollipop': + case 'circle': + $this->ellipse( + array( + 'x' => $x, + 'y' => $y, + 'rx' => $size / 2, + 'ry' => $size / 2, + 'fill' => $params['color'], + 'line' => $params['color'] + ) + ); + break; + case 'diamond': + $x0 = round($params['x'] + cos($angle) * $size * 0.65); + $y0 = round($params['y'] - sin($angle) * $size * 0.65); + $shape = array( + $x0 + round(cos($angle) * $size * 0.65), + $y0 - round(sin($angle) * $size * 0.65), + $x0 + round(cos($angle + $pi2) * $size * 0.65), + $y0 - round(sin($angle + $pi2) * $size * 0.65), + $x0 + round(cos($angle + pi()) * $size * 0.65), + $y0 - round(sin($angle + pi()) * $size * 0.65), + $x0 + round(cos($angle + 3 * $pi2) * $size * 0.65), + $y0 - round(sin($angle + 3 * $pi2) * $size * 0.65) + ); + break; + case 'line': + $this->line( + array( + 'x0' => $x + round(cos($angle + $pi2) * $size / 2), + 'y0' => $y - round(sin($angle + $pi2) * $size / 2), + 'x1' => $x + round(cos($angle + 3 * $pi2) * $size / 2), + 'y1' => $y - round(sin($angle + 3 * $pi2) * $size / 2), + 'color' => $params['color'] + ) + ); + break; + case 'box': + case 'rectangle': + $x0 = round($params['x'] + cos($angle) * $size / 2); + $y0 = round($params['y'] - sin($angle) * $size / 2); + $pi4 = pi() / 4; + $shape = array( + $x0 + round(cos($angle + $pi4) * $size / 2), + $y0 - round(sin($angle + $pi4) * $size / 2), + $x0 + round(cos($angle + $pi2 + $pi4) * $size / 2), + $y0 - round(sin($angle + $pi2 + $pi4) * $size / 2), + $x0 + round(cos($angle + pi() + $pi4) * $size / 2), + $y0 - round(sin($angle + pi() + $pi4) * $size / 2), + $x0 + round(cos($angle + 3 * $pi2 + $pi4) * $size / 2), + $y0 - round(sin($angle + 3 * $pi2 + $pi4) * $size / 2) + ); + break; + case 'arrow': + $shape = array( + $x + cos($angle) * $size, + $y - sin($angle) * $size, + $x + cos($angle + $pi2) * $size * 0.4, + $y - sin($angle + $pi2) * $size * 0.4, + $x + cos($angle + 3 * $pi2) * $size * 0.4, + $y - sin($angle + 3 * $pi2) * $size * 0.4, + ); + break; + case 'arrow2': + $shape = array( + $x + round(cos($angle) * $size), + $y - round(sin($angle) * $size), + $x + round(cos($angle + $pi2 + deg2rad(45)) * $size), + $y - round(sin($angle + $pi2 + deg2rad(45)) * $size), + $x, + $y, + $x + round(cos($angle + 3 * $pi2 - deg2rad(45)) * $size), + $y - round(sin($angle + 3 * $pi2 - deg2rad(45)) * $size), + ); + break; + } + + if (isset($shape)) { + // output the shape + if (($fill = $this->_getFillStyle($params['color'])) !== false) { + ImageFilledPolygon($this->_canvas, $shape, count($shape)/2, $fill); + } + } + parent::drawEnd($params); + } + + /** + * Draw a line + * + * Parameter array: + * + * 'x0': int X start point + * + * 'y0': int Y start point + * + * 'x1': int X end point + * + * 'y1': int Y end point + * + * 'color': mixed [optional] The line color + * + * @param array $params Parameter array + */ + function line($params) + { + $x0 = $this->_getX($params['x0']); + $y0 = $this->_getY($params['y0']); + $x1 = $this->_getX($params['x1']); + $y1 = $this->_getY($params['y1']); + $color = (isset($params['color']) ? $params['color'] : false); + + $x0 = $this->_getX($x0); + $y0 = $this->_getY($y0); + $x1 = $this->_getX($x1); + $y1 = $this->_getY($y1); + if (($this->_antialias === 'driver') && ($x0 != $x1) && ($y0 != $y1)) { + $this->_antialiasedLine($x0, $y0, $x1, $y1, $color); + } elseif (($line = $this->_getLineStyle($color)) !== false) { + ImageLine($this->_canvas, $x0, $y0, $x1, $y1, $line); + } + parent::line($params); + } + + /** + * Parameter array: + * + * 'connect': bool [optional] Specifies whether the start point should be + * connected to the endpoint (closed polygon) or not (connected line) + * + * 'fill': mixed [optional] The fill color + * + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function polygon($params) + { + include_once 'Image/Canvas/Tool.php'; + + $connectEnds = (isset($params['connect']) ? $params['connect'] : false); + $fillColor = (isset($params['fill']) ? $params['fill'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + if (!$connectEnds) { + $fillColor = 'transparent'; + } + $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor); + + $lastPoint = false; + foreach ($this->_polygon as $point) { + if (($lastPoint) && (isset($lastPoint['P1X'])) && + (isset($lastPoint['P1Y'])) && (isset($lastPoint['P2X'])) && + (isset($lastPoint['P2Y']))) + { + $dx = abs($point['X'] - $lastPoint['X']); + $dy = abs($point['Y'] - $lastPoint['Y']); + $d = sqrt($dx * $dx + $dy * $dy); + if ($d > 0) { + $interval = 1 / $d; + for ($t = 0; $t <= 1; $t = $t + $interval) { + $x = Image_Canvas_Tool::bezier( + $t, + $lastPoint['X'], + $lastPoint['P1X'], + $lastPoint['P2X'], + $point['X'] + ); + + $y = Image_Canvas_Tool::bezier( + $t, + $lastPoint['Y'], + $lastPoint['P1Y'], + $lastPoint['P2Y'], + $point['Y'] + ); + + if (!isset($low['X'])) { + $low['X'] = $x; + } else { + $low['X'] = min($x, $low['X']); + } + if (!isset($high['X'])) { + $high['X'] = $x; + } else { + $high['X'] = max($x, $high['X']); + } + if (!isset($low['Y'])) { + $low['Y'] = $y; + } else { + $low['Y'] = min($y, $low['Y']); + } + if (!isset($high['Y'])) { + $high['Y'] = $y; + } else { + $high['Y'] = max($y, $high['Y']); + } + $polygon[] = $x; + $polygon[] = $y; + } + if (($t - $interval) < 1) { + $x = Image_Canvas_Tool::bezier( + 1, + $lastPoint['X'], + $lastPoint['P1X'], + $lastPoint['P2X'], + $point['X'] + ); + + $y = Image_Canvas_Tool::bezier( + 1, + $lastPoint['Y'], + $lastPoint['P1Y'], + $lastPoint['P2Y'], + $point['Y'] + ); + + $polygon[] = $x; + $polygon[] = $y; + } + } + } else { + if (!isset($low['X'])) { + $low['X'] = $point['X']; + } else { + $low['X'] = min($point['X'], $low['X']); + } + if (!isset($high['X'])) { + $high['X'] = $point['X']; + } else { + $high['X'] = max($point['X'], $high['X']); + } + if (!isset($low['Y'])) { + $low['Y'] = $point['Y']; + } else { + $low['Y'] = min($point['Y'], $low['Y']); + } + if (!isset($high['Y'])) { + $high['Y'] = $point['Y']; + } else { + $high['Y'] = max($point['Y'], $high['Y']); + } + + $polygon[] = $point['X']; + $polygon[] = $point['Y']; + } + $lastPoint = $point; + } + + if ((isset($polygon)) && (is_array($polygon))) { + if ($connectEnds) { + if (($fill = $this->_getFillStyle($fillColor, $low['X'], $low['Y'], $high['X'], $high['Y'])) !== false) { + ImageFilledPolygon($this->_canvas, $polygon, count($polygon)/2, $fill); + } + if ($this->_antialias === 'driver') { + $pfirst = $p0 = false; + reset($polygon); + + while (list(, $x) = each($polygon)) { + list(, $y) = each($polygon); + if ($p0 !== false) { + $this->_antialiasedLine($p0['X'], $p0['Y'], $x, $y, $lineColor); + } + if ($pfirst === false) { + $pfirst = array('X' => $x, 'Y' => $y); + } + $p0 = array('X' => $x, 'Y' => $y);; + } + + $this->_antialiasedLine($p0['X'], $p0['Y'], $pfirst['X'], $pfirst['Y'], $lineColor); + } elseif (($line = $this->_getLineStyle($lineColor)) !== false) { + ImagePolygon($this->_canvas, $polygon, count($polygon)/2, $line); + } + } else { + $prev_point = false; + if ($this->_antialias === 'driver') { + reset($polygon); + while (list(, $x) = each($polygon)) { + list(, $y) = each($polygon); + if ($prev_point) { + $this->_antialiasedLine( + $prev_point['X'], + $prev_point['Y'], + $x, + $y, + $lineColor + ); + } + $prev_point = array('X' => $x, 'Y' => $y);; + } + } elseif (($line = $this->_getLineStyle($lineColor)) !== false) { + reset($polygon); + while (list(, $x) = each($polygon)) { + list(, $y) = each($polygon); + if ($prev_point) { + ImageLine( + $this->_canvas, + $prev_point['X'], + $prev_point['Y'], + $x, + $y, + $line + ); + } + $prev_point = array('X' => $x, 'Y' => $y);; + } + } + } + } + + parent::polygon($params); + } + + /** + * Draw a rectangle + * + * Parameter array: + * + * 'x0': int X start point + * + * 'y0': int Y start point + * + * 'x1': int X end point + * + * 'y1': int Y end point + * + * 'fill': mixed [optional] The fill color + * + * 'line': mixed [optional] The line color + * + * @param array $params Parameter array + */ + function rectangle($params) + { + $x0 = $this->_getX($params['x0']); + $y0 = $this->_getY($params['y0']); + $x1 = $this->_getX($params['x1']); + $y1 = $this->_getY($params['y1']); + $fillColor = (isset($params['fill']) ? $params['fill'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + if (($fill = $this->_getFillStyle($fillColor, $x0, $y0, $x1, $y1)) !== false) { + ImageFilledRectangle($this->_canvas, $x0, $y0, $x1, $y1, $fill); + } + + if (($line = $this->_getLineStyle($lineColor)) !== false) { + ImageRectangle($this->_canvas, $x0, $y0, $x1, $y1, $line); + } + + parent::rectangle($params); + } + + /** + * Draw an ellipse + * + * Parameter array: + * + * 'x': int X center point + * + * 'y': int Y center point + * + * 'rx': int X radius + * + * 'ry': int Y radius + * + * 'fill': mixed [optional] The fill color + * + * 'line': mixed [optional] The line color + * + * @param array $params Parameter array + */ + function ellipse($params) + { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $rx = $this->_getX($params['rx']); + $ry = $this->_getY($params['ry']); + $fillColor = (isset($params['fill']) ? $params['fill'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + if (($fill = $this->_getFillStyle($fillColor, $x - $rx, $y - $ry, $x + $rx, $y + $ry)) !== false) { + ImageFilledEllipse($this->_canvas, $x, $y, $rx * 2, $ry * 2, $fill); + } + + if (($line = $this->_getLineStyle($lineColor)) !== false) { + ImageEllipse($this->_canvas, $x, $y, $rx * 2, $ry * 2, $line); + } + parent::ellipse($params); + } + + /** + * Draw a pie slice + * + * Parameter array: + * + * 'x': int X center point + * + * 'y': int Y center point + * + * 'rx': int X radius + * + * 'ry': int Y radius + * + * 'v1': int The starting angle (in degrees) + * + * 'v2': int The end angle (in degrees) + * + * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) + * + * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) + * + * 'fill': mixed [optional] The fill color + * + * 'line': mixed [optional] The line color + * + * @param array $params Parameter array + */ + function pieslice($params) + { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $rx = $params['rx']; + $ry = $params['ry']; + $v1 = $params['v1']; + $v2 = $params['v2']; + $srx = (isset($params['srx']) ? $params['srx'] : 0); + $sry = (isset($params['sry']) ? $params['sry'] : 0); + $fillColor = (isset($params['fill']) ? $params['fill'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + $dA = 0.1; + + if (($srx !== false) && ($sry !== false)) { + $angle = max($v1, $v2); + while ($angle >= min($v1, $v2)) { + $polygon[] = ($x + $srx * cos(deg2rad($angle % 360))); + $polygon[] = ($y + $sry * sin(deg2rad($angle % 360))); + $angle -= $dA; + } + if (($angle + $dA) > min($v1, $v2)) { + $polygon[] = ($x + $srx * cos(deg2rad(min($v1, $v2) % 360))); + $polygon[] = ($y + $sry * sin(deg2rad(min($v1, $v2) % 360))); + } + } else { + $polygon[] = $x; + $polygon[] = $y; + } + + $angle = min($v1, $v2); + while ($angle <= max($v1, $v2)) { + $polygon[] = ($x + $rx * cos(deg2rad($angle % 360))); + $polygon[] = ($y + $ry * sin(deg2rad($angle % 360))); + $angle += $dA; + } + + if (($angle - $dA) < max($v1, $v2)) { + $polygon[] = ($x + $rx * cos(deg2rad(max($v1, $v2) % 360))); + $polygon[] = ($y + $ry * sin(deg2rad(max($v1, $v2) % 360))); + } + + if ((($fill = $this->_getFillStyle($fillColor, $x - $rx - 1, $y - $ry - 1, $x + $rx + 1, $y + $ry + 1)) !== false) && (count($polygon) > 2)) { + ImageFilledPolygon($this->_canvas, $polygon, count($polygon) / 2, $fill); + } + + if (($line = $this->_getLineStyle($lineColor)) !== false) { + ImagePolygon($this->_canvas, $polygon, count($polygon) / 2, $line); + } + + parent::pieSlice($params); + } + + /** + * Get the width of a text, + * + * @param string $text The text to get the width of + * @return int The width of the text + */ + function textWidth($text) + { + if (isset($this->_font['file'])) { + $angle = 0; + if (isset($this->_font['angle'])) { + $angle = $this->_font['angle']; + } + + $width = 0; + $lines = explode("\n", $text); + foreach ($lines as $line) { + $bounds = ImageTTFBBox( + $this->_font['size'], + $angle, + $this->_font['file'], + $text + ); + + $x0 = min($bounds[0], $bounds[2], $bounds[4], $bounds[6]); + $x1 = max($bounds[0], $bounds[2], $bounds[4], $bounds[6]); + $width = max(abs($x0 - $x1), $width); + } + return $width; + } else { + if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { + return ImageFontHeight($this->_font['font']) * (substr_count($text, "\n") + 1); + } else { + $width = 0; + $lines = explode("\n", $text); + foreach ($lines as $line) { + $width = max($width, ImageFontWidth($this->_font['font']) * strlen($line)); + } + return $width; + } + } + } + + /** + * Get the height of a text. + * + * Note! This method can give some peculiar results, since ImageTTFBBox() returns the total + * bounding box of a text, where ImageTTF() writes the text on the baseline of the text, that + * is 'g', 'p', 'q' and other letters that dig under the baseline will appear to have a larger + * height than they actually do. Have a look at the tests/text.php test case - the first two + * columns, 'left and 'center', both look alright, whereas the last column, 'right', appear + * with a larger space between the first text and the second. This is because the total height + * is actually smaller by exactly the number of pixels that the 'g' digs under the baseline. + * Remove the 'g' from the text and they appear correct. + * + * @param string $text The text to get the height of + * @param bool $force Force the method to calculate the size + * @return int The height of the text + */ + function textHeight($text, $force = false) + { + if (isset($this->_font['file'])) { + $angle = 0; + if (isset($this->_font['angle'])) { + $angle = $this->_font['angle']; + } + + $linebreaks = substr_count($text, "\n"); + if (($angle == 0) && ($force === false)) { + /* + * if the angle is 0 simply return the size, due to different + * heights for example for x-axis labels, making the labels + * _not_ appear as written on the same baseline + */ + return $this->_font['size'] + ($this->_font['size'] + 2) * $linebreaks; + } + + $height = 0; + $lines = explode("\n", $text); + foreach ($lines as $line) { + $bounds = ImageTTFBBox( + $this->_font['size'], + $angle, + $this->_font['file'], + $line + ); + + $y0 = min($bounds[1], $bounds[3], $bounds[5], $bounds[7]); + $y1 = max($bounds[1], $bounds[3], $bounds[5], $bounds[7]); + $height += abs($y0 - $y1); + } + return $height + $linebreaks * 2; + } else { + if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { + $width = 0; + $lines = explode("\n", $text); + foreach ($lines as $line) { + $width = max($width, ImageFontWidth($this->_font['font']) * strlen($line)); + } + return $width; + } else { + return ImageFontHeight($this->_font['font']) * (substr_count($text, "\n") + 1); + } + } + } + + /** + * Calculated the absolute bottom-left position of the text, by simulating + * the calculation of the baseline drop. + * @param int $x The relative x position to write the text + * @param int $y The relative y position to write the text + * @param string $text The text to write + * @param array $align The alignment of the text relative to (x, y) + * @returns array An array containing the absolute x and y positions + * @access private + */ + function _getAbsolutePosition($x, $y, $text, $align) + { + if ($this->_font['angle'] > 0) { + $w0 = $this->textWidth($text); + $h0 = $this->textHeight($text); + + if ($align['vertical'] == 'bottom') { + $dy = $y - $h0; + } + else if ($align['vertical'] == 'center') { + $dy = $y - $h0 / 2; + } + else if ($align['vertical'] == 'top') { + $dy = $y; + } + + if ($align['horizontal'] == 'right') { + $dx = $x - $w0; + } + else if ($align['horizontal'] == 'center') { + $dx = $x - $w0 / 2; + } + else if ($align['horizontal'] == 'left') { + $dx = $x; + } + + if (($this->_font['angle'] < 180) && ($this->_font['angle'] >= 0)) { + $dy += $h0; + } + if (($this->_font['angle'] >= 90) && ($this->_font['angle'] < 270)) { + $dx += $w0; + } + } + else { + // get the maximum size of normal text above base line - sampled by 'Al' + $size1 = imagettfbbox($this->_font['size'], 0, $this->_font['file'], 'Al'); + $height1 = abs($size1[7] - $size1[1]); + + // get the maximum size of all text above base and below line - sampled by 'AlgjpqyQ' + $size2 = imagettfbbox($this->_font['size'], 0, $this->_font['file'], 'AlgjpqyQ'); + $height2 = abs($size2[7] - $size2[1]); + + // get the size of the text, simulating height above baseline beinh max, by sampling using 'Al' + $size = imagettfbbox($this->_font['size'], 0, $this->_font['file'], 'Al' . $text); + $height = abs($size[7] - $size[1]); + + // if all text is above baseline, i.e. height of text compares to max height above (within 10%) + if (abs($height - $height1)/$height1 < 0.1) { + $dHeight = 0; + } + else { + $dHeight = abs($height2 - $height1); + } + + // specifies the bottom-left corner! + $dx = $x + sin(deg2rad($this->_font['angle'])) * $dHeight; + $dy = $y - cos(deg2rad($this->_font['angle'])) * $dHeight; + + if ($align['vertical'] == 'top') { + $dy += $height; + } + else if ($align['vertical'] == 'center') { + $dy += ($height + $dHeight) / 2; + } + else if ($align['vertical'] == 'bottom') { + $dy += $dHeight; + } + + if ($align['horizontal'] == 'center') { + $factor = 0.5; + } + else if ($align['horizontal'] == 'right') { + $factor = 1; + } + else { + $factor = 0; + } + + if ($factor != 0) { + $size = imagettfbbox($this->_font['size'], 0, $this->_font['file'], $text); + $w0 = abs($size[2] - $size[0]); + $dx -= cos(deg2rad($this->_font['angle'])) * $w0 * $factor; + $dy += sin(deg2rad($this->_font['angle'])) * $w0 * $factor; + } + } + + return array('x' => $dx, 'y' => $dy); + } + + /** + * Writes text + * + * Parameter array: + * + * 'x': int X-point of text + * + * 'y': int Y-point of text + * + * 'text': string The text to add + * + * 'alignment': array [optional] Alignment + * + * 'color': mixed [optional] The color of the text + */ + function addText($params) + { + $x0 = $this->_getX($params['x']); + $y0 = $this->_getY($params['y']); + $text = $params['text']; + $color = (isset($params['color']) ? $params['color'] : false); + $alignment = (isset($params['alignment']) ? $params['alignment'] : false); + + $text = str_replace("\r", '', $text); + + if (!is_array($alignment)) { + $alignment = array('vertical' => 'top', 'horizontal' => 'left'); + } + + if (!isset($alignment['vertical'])) { + $alignment['vertical'] = 'top'; + } + + if (!isset($alignment['horizontal'])) { + $alignment['horizontal'] = 'left'; + } + + if (isset($this->_font['size'])) { + $textHeight = $this->_font['size'] + 2; + } + else { + $textHeight = $this->textHeight('A'); + } + $lines = explode("\n", $text); + foreach ($lines as $line) { + $x = $x0; + $y = $y0; + + $y0 += $textHeight + 2; + + if (($color === false) && (isset($this->_font['color']))) { + $color = $this->_font['color']; + } + + if ($color != 'transparent') { + if (isset($this->_font['file'])) { + $result = $this->_getAbsolutePosition($x, $y, $line, $alignment); + ImageTTFText( + $this->_canvas, + $this->_font['size'], + $this->_font['angle'], + $result['x'], + $result['y'], + $this->_color($color), + $this->_font['file'], + $line + ); + + } else { + $width = $this->textWidth($line); + $height = $this->textHeight($line); + if ($alignment['horizontal'] == 'right') { + $x -= $width; + } + else if ($alignment['horizontal'] == 'center') { + $x -= $width / 2; + } + if ($alignment['vertical'] == 'bottom') { + $y -= $height; + } + else if ($alignment['vertical'] == 'center') { + $y -= $height / 2; + } + if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { + ImageStringUp( + $this->_canvas, + $this->_font['font'], + $x, + $y + $this->textHeight($text), + $line, + $this->_color($color) + ); + } else { + ImageString( + $this->_canvas, + $this->_font['font'], + $x, + $y, + $line, + $this->_color($color) + ); + } + } + } + } + parent::addText($params); + } + + /** + * Overlay image + * + * Parameter array: + * + * 'x': int X-point of overlayed image + * + * 'y': int Y-point of overlayed image + * + * 'filename': string The filename of the image to overlay + * + * 'width': int [optional] The width of the overlayed image (resizing if possible) + * + * 'height': int [optional] The height of the overlayed image (resizing if possible) + * + * 'alignment': array [optional] Alignment + */ + function image($params) + { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $filename = $params['filename']; + $width = (isset($params['width']) ? $params['width'] : false); + $height = (isset($params['height']) ? $params['height'] : false); + $alignment = (isset($params['alignment']) ? $params['alignment'] : false); + + if (!is_array($alignment)) { + $alignment = array('vertical' => 'top', 'horizontal' => 'left'); + } + + if (!isset($alignment['vertical'])) { + $alignment['vertical'] = 'top'; + } + + if (!isset($alignment['horizontal'])) { + $alignment['horizontal'] = 'left'; + } + + if (file_exists($filename)) { + if (strtolower(substr($filename, -4)) == '.png') { + $image = ImageCreateFromPNG($filename); + } elseif (strtolower(substr($filename, -4)) == '.gif') { + $image = ImageCreateFromGIF($filename); + } else { + $image = ImageCreateFromJPEG($filename); + } + + $imgWidth = ImageSX($image); + $imgHeight = ImageSY($image); + + $outputWidth = ($width !== false ? $width : $imgWidth); + $outputHeight = ($height !== false ? $height : $imgHeight); + + if ($alignment['horizontal'] == 'right') { + $x -= $outputWidth; + } elseif ($alignment['horizontal'] == 'center') { + $x -= $outputWidth / 2; + } + + if ($alignment['vertical'] == 'bottom') { + $y -= $outputHeight; + } elseif ($alignment['vertical'] == 'center') { + $y -= $outputHeight / 2; + } + + if ((($width !== false) && ($width != $imgWidth)) || + (($height !== false) && ($height != $imgHeight))) + { + if ($this->_gd2) { + ImageCopyResampled( + $this->_canvas, + $image, + $x, + $y, + 0, + 0, + $width, + $height, + $imgWidth, + $imgHeight + ); + } else { + ImageCopyResized( + $this->_canvas, + $image, + $x, + $y, + 0, + 0, + $width, + $height, + $imgWidth, + $imgHeight + ); + } + } else { + ImageCopy( + $this->_canvas, + $image, + $x, + $y, + 0, + 0, + $imgWidth, + $imgHeight + ); + } + ImageDestroy($image); + } + parent::image($params); + } + + /** + * Set clipping to occur + * + * Parameter array: + * + * 'x0': int X point of Upper-left corner + * 'y0': int X point of Upper-left corner + * 'x1': int X point of lower-right corner + * 'y1': int Y point of lower-right corner + */ + function setClipping($params = false) + { + if ($params === false) { + $index = count($this->_clipping) - 1; + if (isset($this->_clipping[$index])) { + $params = $this->_clipping[$index]; + $canvas = $params['canvas']; + ImageCopy( + $canvas, + $this->_canvas, + min($params['x0'], $params['x1']), + min($params['y0'], $params['y1']), + min($params['x0'], $params['x1']), + min($params['y0'], $params['y1']), + abs($params['x1'] - $params['x0'] + 1), + abs($params['y1'] - $params['y0'] + 1) + ); + $this->_canvas = $canvas; + unset($this->_clipping[$index]); + } + } + else { + $params['canvas'] = $this->_canvas; + + if ($this->_gd2) { + $this->_canvas = ImageCreateTrueColor( + $this->_width, + $this->_height + ); + if ($this->_alpha) { + ImageAlphaBlending($this->_canvas, true); + } + } else { + $this->_canvas = ImageCreate($this->_width, $this->_height); + } + + if (($this->_gd2) && ($this->_antialias === 'native')) { + ImageAntialias($this->_canvas, true); + } + + ImageCopy($this->_canvas, $params['canvas'], 0, 0, 0, 0, $this->_width, $this->_height); + + $this->_clipping[count($this->_clipping)] = $params; + } + } + + /** + * Get a canvas specific HTML tag. + * + * This method implicitly saves the canvas to the filename in the + * filesystem path specified and parses it as URL specified by URL path + * + * Parameter array: + * + * 'filename' string + * + * 'filepath': string Path to the file on the file system. Remember the final slash + * + * 'urlpath': string Path to the file available through an URL. Remember the final slash + * + * 'alt': string [optional] Alternative text on image + * + * 'cssclass': string [optional] The CSS Stylesheet class + * + * 'border': int [optional] The border width on the image + */ + function toHtml($params) + { + parent::toHtml($params); + return '' . $params['alt'] . '_imageMap) ? ' usemap="#' . $params['filename'] . '"' : '') . '>' . + (isset($this->_imageMap) ? "\n" . $this->_imageMap->toHtml(array('name' => $params['filename'])) : ''); + } + + /** + * Resets the canvas. + * + * Include fillstyle, linestyle, thickness and polygon + * @access private + */ + function _reset() + { + if ($this->_gd2) { + ImageSetThickness($this->_canvas, 1); + } + if ($this->_tileImage != null) { + ImageDestroy($this->_tileImage); + $this->_tileImage = null; + } + parent::_reset(); + $this->_font = array('font' => 1, 'color' => 'black'); + } + + /** + * Check which version of GD is installed + * + * @return int 0 if GD isn't installed, 1 if GD 1.x is installed and 2 if GD + * 2.x is installed + * @access private + */ + function _version() + { + $result = false; + if (function_exists('gd_info')) { + $info = gd_info(); + $version = $info['GD Version']; + } else { + ob_start(); + phpinfo(8); + $php_info = ob_get_contents(); + ob_end_clean(); + + if (ereg("]*>GD Version *<\/td>]*>([^<]*)<\/td>", + $php_info, $result)) + { + $version = $result[1]; + } else { + $version = null; + } + } + + if (ereg('1\.[0-9]{1,2}', $version)) { + return 1; + } elseif (ereg('2\.[0-9]{1,2}', $version)) { + return 2; + } else { + return 0; + } + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Canvas/GD/JPG.php b/includes/pear/Image/Canvas/GD/JPG.php index 392fd6bd..f8c6f7b4 100644 --- a/includes/pear/Image/Canvas/GD/JPG.php +++ b/includes/pear/Image/Canvas/GD/JPG.php @@ -1,119 +1,119 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: JPG.php,v 1.2 2005/08/24 20:37:34 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -/** - * Include file Image/Canvas/GD.php - */ -require_once 'Image/Canvas/GD.php'; - -/** - * JPEG Canvas class. - * - * @category Images - * @package Image_Canvas - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ -class Image_Canvas_GD_JPG extends Image_Canvas_GD -{ - - /** - * The JPEG quality - * @var int - * @access private - */ - var $_quality = 75; - - /** - * Create the JPEG canvas - * - * Additional parameters other than those available for common {@link - * Image_Graph_Canvas_GD} class are: - * - * 'quality' The JPEG quality in as a percentage value from 0 (lowest - * quality, smallest file) to 100 (highest quality, biggest file) - * - * @param array $param Parameter array - */ - function Image_Canvas_GD_JPG($param) - { - parent::Image_Canvas_GD($param); - - if (isset($param['quality'])) { - $this->_quality = max(0, min(100, $param['quality'])); - } - - $this->rectangle( - array( - 'x0' => $this->_left, - 'y0' => $this->_top, - 'x1' => $this->_left + $this->_width - 1, - 'y1' => $this->_top + $this->_height - 1, - 'fill' => 'white', - 'line' => 'transparent' - ) - ); - } - - /** - * Output the result of the canvas - * - * @param array $param Parameter array - * @abstract - */ - function show($param = false) - { - parent::show($param); - header('Content-type: image/jpg'); - header('Content-Disposition: inline; filename = \"'. basename($_SERVER['PHP_SELF'], '.php') . '.jpg\"'); - ImageJPEG($this->_canvas, '', $this->_quality); - ImageDestroy($this->_canvas); - } - - /** - * Output the result of the canvas - * - * @param array $param Parameter array - * @abstract - */ - function save($param = false) - { - parent::save($param); - ImageJPEG($this->_canvas, $param['filename'], $this->_quality); - ImageDestroy($this->_canvas); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: JPG.php,v 1.2 2005/08/24 20:37:34 nosey Exp $ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ + +/** + * Include file Image/Canvas/GD.php + */ +require_once 'Image/Canvas/GD.php'; + +/** + * JPEG Canvas class. + * + * @category Images + * @package Image_Canvas + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ +class Image_Canvas_GD_JPG extends Image_Canvas_GD +{ + + /** + * The JPEG quality + * @var int + * @access private + */ + var $_quality = 75; + + /** + * Create the JPEG canvas + * + * Additional parameters other than those available for common {@link + * Image_Graph_Canvas_GD} class are: + * + * 'quality' The JPEG quality in as a percentage value from 0 (lowest + * quality, smallest file) to 100 (highest quality, biggest file) + * + * @param array $param Parameter array + */ + function Image_Canvas_GD_JPG($param) + { + parent::Image_Canvas_GD($param); + + if (isset($param['quality'])) { + $this->_quality = max(0, min(100, $param['quality'])); + } + + $this->rectangle( + array( + 'x0' => $this->_left, + 'y0' => $this->_top, + 'x1' => $this->_left + $this->_width - 1, + 'y1' => $this->_top + $this->_height - 1, + 'fill' => 'white', + 'line' => 'transparent' + ) + ); + } + + /** + * Output the result of the canvas + * + * @param array $param Parameter array + * @abstract + */ + function show($param = false) + { + parent::show($param); + header('Content-type: image/jpg'); + header('Content-Disposition: inline; filename = \"'. basename($_SERVER['PHP_SELF'], '.php') . '.jpg\"'); + ImageJPEG($this->_canvas, '', $this->_quality); + ImageDestroy($this->_canvas); + } + + /** + * Output the result of the canvas + * + * @param array $param Parameter array + * @abstract + */ + function save($param = false) + { + parent::save($param); + ImageJPEG($this->_canvas, $param['filename'], $this->_quality); + ImageDestroy($this->_canvas); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Canvas/GD/PNG.php b/includes/pear/Image/Canvas/GD/PNG.php index 5659d8b2..45d9f81f 100644 --- a/includes/pear/Image/Canvas/GD/PNG.php +++ b/includes/pear/Image/Canvas/GD/PNG.php @@ -1,125 +1,125 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: PNG.php,v 1.3 2005/08/24 20:37:34 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -/** - * Include file Image/Canvas/GD.php - */ -require_once 'Image/Canvas/GD.php'; - -/** - * PNG Canvas class. - * - * @category Images - * @package Image_Canvas - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ -class Image_Canvas_GD_PNG extends Image_Canvas_GD -{ - - /** - * Create the PNG canvas - * - * @param array $param Parameter array - */ - function Image_Canvas_GD_PNG($param) - { - parent::Image_Canvas_GD($param); - - if ((isset($param['transparent'])) && ($param['transparent']) && - ($this->_gd2) - ) { - if ($param['transparent'] === true) { - $transparent = '#123ABD'; - } else { - $transparent = $param['transparent']; - } - $color = $this->_color($transparent); - $trans = ImageColorTransparent($this->_canvas, $color); - - $this->rectangle( - array( - 'x0' => $this->_left, - 'y0' => $this->_top, - 'x1' => $this->_left + $this->_width - 1, - 'y1' => $this->_top + $this->_height - 1, - 'fill' => 'opague', - 'line' => 'transparent' - ) - ); - } else { - $this->rectangle( - array( - 'x0' => $this->_left, - 'y0' => $this->_top, - 'x1' => $this->_left + $this->_width - 1, - 'y1' => $this->_top + $this->_height - 1, - 'fill' => 'white', - 'line' => 'transparent' - ) - ); - } - } - - /** - * Output the result of the canvas - * - * @param array $param Parameter array - * @abstract - */ - function show($param = false) - { - parent::show($param); - header('Content-type: image/png'); - header('Content-Disposition: inline; filename = \"'. basename($_SERVER['PHP_SELF'], '.php') . '.png\"'); - ImagePNG($this->_canvas); - ImageDestroy($this->_canvas); - } - - /** - * Output the result of the canvas - * - * @param array $param Parameter array - * @abstract - */ - function save($param = false) - { - parent::save($param); - ImagePNG($this->_canvas, $param['filename']); - ImageDestroy($this->_canvas); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: PNG.php,v 1.3 2005/08/24 20:37:34 nosey Exp $ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ + +/** + * Include file Image/Canvas/GD.php + */ +require_once 'Image/Canvas/GD.php'; + +/** + * PNG Canvas class. + * + * @category Images + * @package Image_Canvas + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ +class Image_Canvas_GD_PNG extends Image_Canvas_GD +{ + + /** + * Create the PNG canvas + * + * @param array $param Parameter array + */ + function Image_Canvas_GD_PNG($param) + { + parent::Image_Canvas_GD($param); + + if ((isset($param['transparent'])) && ($param['transparent']) && + ($this->_gd2) + ) { + if ($param['transparent'] === true) { + $transparent = '#123ABD'; + } else { + $transparent = $param['transparent']; + } + $color = $this->_color($transparent); + $trans = ImageColorTransparent($this->_canvas, $color); + + $this->rectangle( + array( + 'x0' => $this->_left, + 'y0' => $this->_top, + 'x1' => $this->_left + $this->_width - 1, + 'y1' => $this->_top + $this->_height - 1, + 'fill' => 'opague', + 'line' => 'transparent' + ) + ); + } else { + $this->rectangle( + array( + 'x0' => $this->_left, + 'y0' => $this->_top, + 'x1' => $this->_left + $this->_width - 1, + 'y1' => $this->_top + $this->_height - 1, + 'fill' => 'white', + 'line' => 'transparent' + ) + ); + } + } + + /** + * Output the result of the canvas + * + * @param array $param Parameter array + * @abstract + */ + function show($param = false) + { + parent::show($param); + header('Content-type: image/png'); + header('Content-Disposition: inline; filename = \"'. basename($_SERVER['PHP_SELF'], '.php') . '.png\"'); + ImagePNG($this->_canvas); + ImageDestroy($this->_canvas); + } + + /** + * Output the result of the canvas + * + * @param array $param Parameter array + * @abstract + */ + function save($param = false) + { + parent::save($param); + ImagePNG($this->_canvas, $param['filename']); + ImageDestroy($this->_canvas); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Canvas/ImageMap.php b/includes/pear/Image/Canvas/ImageMap.php index 925de9fb..811fe41c 100644 --- a/includes/pear/Image/Canvas/ImageMap.php +++ b/includes/pear/Image/Canvas/ImageMap.php @@ -1,354 +1,354 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: ImageMap.php,v 1.6 2005/08/17 17:59:11 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -/** - * Class for handling output as a HTML imagemap - * - * @category Images - * @package Image_Canvas - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - * @since version 0.2.0 - */ -class Image_Canvas_ImageMap extends Image_Canvas -{ - - /** - * The image map (if any) - * @var array - * @access private - */ - var $_map = array(); - - /** - * Add a map tag - * @param string $shape The shape, either rect, circle or polygon - * @param string $coords The list of coordinates for the shape - * @param array $params Parameter array - */ - function _addMapTag($shape, $coords, $params) - { - if (isset($params['url'])) { - $url = $params['url']; - $target = (isset($params['target']) ? $params['target'] : false); - $alt = (isset($params['alt']) ? $params['alt'] : false); - - $tags = ''; - if (isset($params['htmltags'])) { - foreach ($params['htmltags'] as $key => $value) { - $tags .= ' '; - if (strpos($value, '"') >= 0) { - $tags .= $key . '=\'' . $value . '\''; - } else { - $tags .= $key . '="' . $value . '"'; - } - } - } - - $this->_map[] = - '' . $alt . ''; - } - } - - /** - * Draw a line - * - * Parameter array: - * 'x0': int X start point - * 'y0': int Y start point - * 'x1': int X end point - * 'y1': int Y end point - * 'color': mixed [optional] The line color - * 'mapsize': int [optional] The size of the image map (surrounding the line) - * @param array $params Parameter array - */ - function line($params) - { - if (isset($params['url'])) { - $mapsize = (isset($params['mapsize']) ? $params['mapsize'] : 2); - $this->_addMapTag( - 'polygon', - $this->_getX($params['x0'] - $mapsize) . ',' . - $this->_getY($params['y0'] - $mapsize) . ',' . - $this->_getX($params['x1'] + $mapsize) . ',' . - $this->_getY($params['y1'] - $mapsize) . ',' . - - $this->_getX($params['x1'] + $mapsize) . ',' . - $this->_getY($params['y1'] + $mapsize) . ',' . - $this->_getX($params['x0'] - $mapsize) . ',' . - $this->_getY($params['y0'] + $mapsize), - $params - ); - } - parent::line($params); - } - - /** - * Draws a polygon - * - * Parameter array: - * 'connect': bool [optional] Specifies whether the start point should be - * connected to the endpoint (closed polygon) or not (connected line) - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * 'map_vertices': bool [optional] Specifies whether the image map should map the vertices instead of the polygon as a whole - * 'url': string [optional] URL to link the polygon as a whole to (also used for default in case 'map_vertices' is used) - * 'alt': string [optional] Alternative text to show in the image map (also used for default in case 'map_vertices' is used) - * 'target': string [optional] The link target on the image map (also used for default in case 'map_vertices' is used) - * @param array $params Parameter array - */ - function polygon($params) - { - if ((isset($params['map_vertices'])) && ($params['map_vertices'] === true)) { - $mapsize = (isset($params['mapsize']) ? $params['mapsize'] : 2); - foreach ($this->_polygon as $point) { - $vertex_param = $params; - if (isset($point['url'])) { - $vertex_param['url'] = $point['url']; - } - if (isset($point['target'])) { - $vertex_param['target'] = $point['target']; - } - if (isset($point['alt'])) { - $vertex_param['alt'] = $point['alt']; - } - $vertex_mapsize = $mapsize; - if (isset($point['mapsize'])) { - $vertex_mapsize = $point['mapsize']; - } - if (isset($point['htmltags'])) { - $vertex_param['htmltags'] = $point['htmltags']; - } - $this->_addMapTag( - 'circle', - $this->_getX($point['X']) . ',' . - $this->_getY($point['Y']) . ',' . - $mapsize, - $vertex_param - ); - } - } - else if (isset($params['url'])) { - $points = ''; - foreach ($this->_polygon as $point) { - if ($points != '') { - $points .= ','; - } - $points .= $this->_getX($point['X']) . ',' . $this->_getY($point['Y']); - } - $this->_addMapTag('polygon', $points, $params); - } - parent::polygon($params); - } - - /** - * Draw a rectangle - * - * Parameter array: - * 'x0': int X start point - * 'y0': int Y start point - * 'x1': int X end point - * 'y1': int Y end point - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function rectangle($params) - { - if (isset($params['url'])) { - $this->_addMapTag( - 'rect', - $this->_getX($params['x0']) . ',' . - $this->_getY($params['y0']) . ',' . - $this->_getX($params['x1']) . ',' . - $this->_getY($params['y1']), - $params - ); - } - parent::rectangle($params); - } - - /** - * Draw an ellipse - * - * Parameter array: - * 'x': int X center point - * 'y': int Y center point - * 'rx': int X radius - * 'ry': int Y radius - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function ellipse($params) - { - if (isset($params['url'])) { - if ($params['rx'] == $params['ry']) { - $this->_addMapTag( - 'circle', - $this->_getX($params['x']) . ',' . - $this->_getY($params['y']) . ',' . - $this->_getX($params['rx']), - $params - ); - } else { - $points = ''; - for ($v = 0; $v <= 360; $v += 30) { - if ($points != '') { - $points .= ','; - } - $points .= - round($this->_getX($params['x']) + $this->_getX($params['rx']) * cos(deg2rad($v % 360))) . ',' . - round($this->_getY($params['y']) + $this->_getX($params['ry']) * sin(deg2rad($v % 360))); - } - $this->_addMapTag( - 'polygon', - $points, - $params - ); - } - } - parent::ellipse($params); - } - - /** - * Draw a pie slice - * - * Parameter array: - * 'x': int X center point - * 'y': int Y center point - * 'rx': int X radius - * 'ry': int Y radius - * 'v1': int The starting angle (in degrees) - * 'v2': int The end angle (in degrees) - * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) - * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function pieslice($params) - { - if (isset($params['url'])) { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $rx = $params['rx']; - $ry = $params['ry']; - $v1a = $params['v1']; - $v2a = $params['v2']; - $v1 = min($v1a, $v2a); - $v2 = max($v1a, $v2a); - $srx = (isset($params['srx']) ? $params['srx'] : 0); - $sry = (isset($params['sry']) ? $params['sry'] : 0); - - $points = - round(($x + $srx * cos(deg2rad($v1 % 360)))) . ',' . - round(($y + $sry * sin(deg2rad($v1 % 360)))) . ','; - - for ($v = $v1; $v < $v2; $v += 30) { - $points .= - round(($x + $rx * cos(deg2rad($v % 360)))) . ',' . - round(($y + $ry * sin(deg2rad($v % 360)))) . ','; - } - - $points .= - round(($x + $rx * cos(deg2rad($v2 % 360)))) . ',' . - round(($y + $ry * sin(deg2rad($v2 % 360)))); - - if (($srx != 0) || ($sry != 0)) { - $points .= ','; - for ($v = $v2; $v > $v1; $v -= 30) { - $points .= - round(($x + $srx * cos(deg2rad($v % 360)))) . ',' . - round(($y + $sry * sin(deg2rad($v % 360)))) . ','; - } - - } - - $this->_addMapTag('polygon', $points, $params); - } - parent::pieslice($params); - } - - /** - * Output the result of the canvas to the browser - * - * @param array $params Parameter array, the contents and meaning depends on the actual Canvas - * @abstract - */ - function show($params = false) - { - parent::show($params); - if (count($this->_map) > 0) { - print $this->toHtml($params); - } - } - - /** - * Save the result of the canvas to a file - * - * Parameter array: - * 'filename': string The file to output to - * @param array $params Parameter array, the contents and meaning depends on the actual Canvas - * @abstract - */ - function save($params = false) - { - parent::save($params); - $file = fopen($param['filename'], 'w+'); - fwrite($file, $this->toHtml($params)); - fclose($file); - } - - /** - * Get a canvas specific HTML tag. - * - * Parameter array: - * 'name': string The name of the image map - */ - function toHtml($params) - { - if (count($this->_map) > 0) { - return '' . "\n\t" . implode($this->_map, "\n\t") . "\n"; - } - return ''; - } -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: ImageMap.php,v 1.8 2006/10/24 18:58:16 nosey Exp $ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ + +/** + * Class for handling output as a HTML imagemap + * + * @category Images + * @package Image_Canvas + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + * @since version 0.2.0 + */ +class Image_Canvas_ImageMap extends Image_Canvas +{ + + /** + * The image map (if any) + * @var array + * @access private + */ + var $_map = array(); + + /** + * Add a map tag + * @param string $shape The shape, either rect, circle or polygon + * @param string $coords The list of coordinates for the shape + * @param array $params Parameter array + */ + function _addMapTag($shape, $coords, $params) + { + if (isset($params['url'])) { + $url = $params['url']; + $target = (isset($params['target']) ? $params['target'] : false); + $alt = (isset($params['alt']) ? $params['alt'] : false); + + $tags = ''; + if (isset($params['htmltags'])) { + foreach ($params['htmltags'] as $key => $value) { + $tags .= ' '; + if (strpos($value, '"') !== false) { + $tags .= $key . '=\'' . $value . '\''; + } else { + $tags .= $key . '="' . $value . '"'; + } + } + } + + $this->_map[] = + '' . $alt . ''; + } + } + + /** + * Draw a line + * + * Parameter array: + * 'x0': int X start point + * 'y0': int Y start point + * 'x1': int X end point + * 'y1': int Y end point + * 'color': mixed [optional] The line color + * 'mapsize': int [optional] The size of the image map (surrounding the line) + * @param array $params Parameter array + */ + function line($params) + { + if (isset($params['url'])) { + $mapsize = (isset($params['mapsize']) ? $params['mapsize'] : 2); + $this->_addMapTag( + 'polygon', + $this->_getX($params['x0'] - $mapsize) . ',' . + $this->_getY($params['y0'] - $mapsize) . ',' . + $this->_getX($params['x1'] + $mapsize) . ',' . + $this->_getY($params['y1'] - $mapsize) . ',' . + + $this->_getX($params['x1'] + $mapsize) . ',' . + $this->_getY($params['y1'] + $mapsize) . ',' . + $this->_getX($params['x0'] - $mapsize) . ',' . + $this->_getY($params['y0'] + $mapsize), + $params + ); + } + parent::line($params); + } + + /** + * Draws a polygon + * + * Parameter array: + * 'connect': bool [optional] Specifies whether the start point should be + * connected to the endpoint (closed polygon) or not (connected line) + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * 'map_vertices': bool [optional] Specifies whether the image map should map the vertices instead of the polygon as a whole + * 'url': string [optional] URL to link the polygon as a whole to (also used for default in case 'map_vertices' is used) + * 'alt': string [optional] Alternative text to show in the image map (also used for default in case 'map_vertices' is used) + * 'target': string [optional] The link target on the image map (also used for default in case 'map_vertices' is used) + * @param array $params Parameter array + */ + function polygon($params) + { + if ((isset($params['map_vertices'])) && ($params['map_vertices'] === true)) { + $mapsize = (isset($params['mapsize']) ? $params['mapsize'] : 2); + foreach ($this->_polygon as $point) { + $vertex_param = $params; + if (isset($point['url'])) { + $vertex_param['url'] = $point['url']; + } + if (isset($point['target'])) { + $vertex_param['target'] = $point['target']; + } + if (isset($point['alt'])) { + $vertex_param['alt'] = $point['alt']; + } + $vertex_mapsize = $mapsize; + if (isset($point['mapsize'])) { + $vertex_mapsize = $point['mapsize']; + } + if (isset($point['htmltags'])) { + $vertex_param['htmltags'] = $point['htmltags']; + } + $this->_addMapTag( + 'circle', + $this->_getX($point['X']) . ',' . + $this->_getY($point['Y']) . ',' . + $mapsize, + $vertex_param + ); + } + } + else if (isset($params['url'])) { + $points = ''; + foreach ($this->_polygon as $point) { + if ($points != '') { + $points .= ','; + } + $points .= $this->_getX($point['X']) . ',' . $this->_getY($point['Y']); + } + $this->_addMapTag('polygon', $points, $params); + } + parent::polygon($params); + } + + /** + * Draw a rectangle + * + * Parameter array: + * 'x0': int X start point + * 'y0': int Y start point + * 'x1': int X end point + * 'y1': int Y end point + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function rectangle($params) + { + if (isset($params['url'])) { + $this->_addMapTag( + 'rect', + $this->_getX($params['x0']) . ',' . + $this->_getY($params['y0']) . ',' . + $this->_getX($params['x1']) . ',' . + $this->_getY($params['y1']), + $params + ); + } + parent::rectangle($params); + } + + /** + * Draw an ellipse + * + * Parameter array: + * 'x': int X center point + * 'y': int Y center point + * 'rx': int X radius + * 'ry': int Y radius + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function ellipse($params) + { + if (isset($params['url'])) { + if ($params['rx'] == $params['ry']) { + $this->_addMapTag( + 'circle', + $this->_getX($params['x']) . ',' . + $this->_getY($params['y']) . ',' . + $this->_getX($params['rx']), + $params + ); + } else { + $points = ''; + for ($v = 0; $v <= 360; $v += 30) { + if ($points != '') { + $points .= ','; + } + $points .= + round($this->_getX($params['x']) + $this->_getX($params['rx']) * cos(deg2rad($v % 360))) . ',' . + round($this->_getY($params['y']) + $this->_getX($params['ry']) * sin(deg2rad($v % 360))); + } + $this->_addMapTag( + 'polygon', + $points, + $params + ); + } + } + parent::ellipse($params); + } + + /** + * Draw a pie slice + * + * Parameter array: + * 'x': int X center point + * 'y': int Y center point + * 'rx': int X radius + * 'ry': int Y radius + * 'v1': int The starting angle (in degrees) + * 'v2': int The end angle (in degrees) + * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) + * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function pieslice($params) + { + if (isset($params['url'])) { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $rx = $params['rx']; + $ry = $params['ry']; + $v1a = $params['v1']; + $v2a = $params['v2']; + $v1 = min($v1a, $v2a); + $v2 = max($v1a, $v2a); + $srx = (isset($params['srx']) ? $params['srx'] : 0); + $sry = (isset($params['sry']) ? $params['sry'] : 0); + + $points = + round(($x + $srx * cos(deg2rad($v1 % 360)))) . ',' . + round(($y + $sry * sin(deg2rad($v1 % 360)))) . ','; + + for ($v = $v1; $v < $v2; $v += 30) { + $points .= + round(($x + $rx * cos(deg2rad($v % 360)))) . ',' . + round(($y + $ry * sin(deg2rad($v % 360)))) . ','; + } + + $points .= + round(($x + $rx * cos(deg2rad($v2 % 360)))) . ',' . + round(($y + $ry * sin(deg2rad($v2 % 360)))); + + if (($srx != 0) || ($sry != 0)) { + $points .= ','; + for ($v = $v2; $v > $v1; $v -= 30) { + $points .= + round(($x + $srx * cos(deg2rad($v % 360)))) . ',' . + round(($y + $sry * sin(deg2rad($v % 360)))) . ','; + } + + } + + $this->_addMapTag('polygon', $points, $params); + } + parent::pieslice($params); + } + + /** + * Output the result of the canvas to the browser + * + * @param array $params Parameter array, the contents and meaning depends on the actual Canvas + * @abstract + */ + function show($params = false) + { + parent::show($params); + if (count($this->_map) > 0) { + print $this->toHtml($params); + } + } + + /** + * Save the result of the canvas to a file + * + * Parameter array: + * 'filename': string The file to output to + * @param array $params Parameter array, the contents and meaning depends on the actual Canvas + * @abstract + */ + function save($params = false) + { + parent::save($params); + $file = fopen($params['filename'], 'w+'); + fwrite($file, $this->toHtml($params)); + fclose($file); + } + + /** + * Get a canvas specific HTML tag. + * + * Parameter array: + * 'name': string The name of the image map + */ + function toHtml($params) + { + if (count($this->_map) > 0) { + return '' . "\n\t" . implode($this->_map, "\n\t") . "\n"; + } + return ''; + } +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Canvas/PDF.php b/includes/pear/Image/Canvas/PDF.php index b8fc9040..f5cc34a4 100644 --- a/includes/pear/Image/Canvas/PDF.php +++ b/includes/pear/Image/Canvas/PDF.php @@ -1,1007 +1,1012 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: PDF.php,v 1.5 2005/10/28 09:54:40 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -/** - * Include file Image/Canvas.php - */ -require_once 'Image/Canvas.php'; - -/** - * Include file Image/Canvas/Color.php - */ -require_once 'Image/Canvas/Color.php'; - -/** - * PDF Canvas class. - * - * @category Images - * @package Image_Canvas - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ -class Image_Canvas_PDF extends Image_Canvas -{ - - /** - * The PDF document - * @var resource - * @access private - */ - var $_pdf; - - /** - * The major version of PDFlib - * @var int - * @access private - */ - var $_pdflib; - - /** - * The font - * @var mixed - * @access private - */ - var $_pdfFont = false; - - /** - * The width of the page - * @var int - * @access private - */ - var $_pageWidth; - - /** - * The height of the page - * @var int - * @access private - */ - var $_pageHeight; - - /** - * Create the PDF canvas. - * - * Parameters available: - * - * 'page' Specify the page/paper format for the graph's page, available - * formats are: A0, A1, A2, A3, A4, A5, A6, B5, letter, legal, ledger, - * 11x17, cd_front, inlay, inlay_nosides - * - * 'align' Alignment of the graph on the page, available options are: - * topleft, topcenter, topright, leftcenter, center, rightcenter, - * leftbottom, centerbottom, rightbottom - * - * 'orientation' Specifies the paper orientation, default is 'portrait' and - * 'landscape' is also supported. - * - * 'creator' The creator tag of the PDF/graph - * - * 'author' The author tag of the PDF/graph - * - * 'title' The title tag of the PDF/graph - * - * 'width' The width of the graph on the page - * - * 'height' The height of the graph on the page - * - * 'left' The left offset of the graph on the page - * - * 'top' The top offset of the graph on the page - * - * 'filename' The PDF file to open/add page to, using 'filename' requires - * the commercial version of PDFlib (http://www.pdflib.com/), this has for - * obvious ($ 450) reasons not been tested - * - * 'pdf' An existing PDFlib PDF document to add the page to - * - * 'add_page' (true/false) Used together with 'pdf', to specify whether the - * canvas should add a new graph page (true) or create the graph on the - * current page (false), default is 'true' - * - * The 'page' and 'width' & 'height' can be mutually omitted, if 'page' is - * omitted the page is created using dimensions of width x height, and if - * width and height are omitted the page dimensions are used for the graph. - * - * If 'pdf' is specified, 'filename', 'creator', 'author' and 'title' has no - * effect. - * - * 'left' and 'top' are overridden by 'align' - * - * It is required either to specify 'width' & 'height' or 'page'. - * - * The PDF format/PDFlib has some limitations on the capabilities, which - * means some functionality available using other canvass (fx. alpha - * blending and gradient fills) are not supported with PDF (see Canvas.txt - * in the docs/ folder for further details) - * - * @param array $param Parameter array - */ - function Image_Canvas_PDF($param) - { - if (isset($param['page'])) { - switch (strtoupper($param['page'])) { - case 'A0': - $this->_pageWidth = 2380; - $this->_pageHeight = 3368; - break; - - case 'A1': - $this->_pageWidth = 1684; - $this->_pageHeight = 2380; - break; - - case 'A2': - $this->_pageWidth = 1190; - $this->_pageHeight = 1684; - break; - - case 'A3': - $this->_pageWidth = 842; - $this->_pageHeight = 1190; - break; - - case 'A4': - $this->_pageWidth = 595; - $this->_pageHeight = 842; - break; - - case 'A5': - $this->_pageWidth = 421; - $this->_pageHeight = 595; - break; - - case 'A6': - $this->_pageWidth = 297; - $this->_pageHeight = 421; - break; - - case 'B5': - $this->_pageWidth = 501; - $this->_pageHeight = 709; - break; - - case 'LETTER': - $this->_pageWidth = 612; - $this->_pageHeight = 792; - break; - - case 'LEGAL': - $this->_pageWidth = 612; - $this->_pageHeight = 1008; - break; - - case 'LEDGER': - $this->_pageWidth = 1224; - $this->_pageHeight = 792; - break; - - case '11X17': - $this->_pageWidth = 792; - $this->_pageHeight = 1224; - break; - - case 'CD_FRONT': - $this->_pageWidth = 337; - $this->_pageHeight = 337; - break; - - case 'INLAY': - $this->_pageWidth = 425; - $this->_pageHeight = 332; - break; - - case 'INLAY_NOSIDES': - $this->_pageWidth = 390; - $this->_pageHeight = 332; - break; - } - } - - if ((isset($param['orientation'])) && (strtoupper($param['orientation']) == 'LANDSCAPE')) { - $w = $this->_pageWidth; - $this->_pageWidth = $this->_pageHeight; - $this->_pageHeight = $w; - } - - parent::Image_Canvas($param); - - if (!$this->_pageWidth) { - $this->_pageWidth = $this->_width; - } elseif (!$this->_width) { - $this->_width = $this->_pageWidth; - } - - if (!$this->_pageHeight) { - $this->_pageHeight = $this->_height; - } elseif (!$this->_height) { - $this->_height = $this->_pageHeight; - } - - $this->_width = min($this->_width, $this->_pageWidth); - $this->_height = min($this->_height, $this->_pageHeight); - - if ((isset($param['align'])) && - (($this->_width != $this->_pageWidth) || ($this->_height != $this->_pageHeight)) - ) { - switch (strtoupper($param['align'])) { - case 'TOPLEFT': - $this->_top = 0; - $this->_left = 0; - break; - - case 'TOPCENTER': - $this->_top = 0; - $this->_left = ($this->_pageWidth - $this->_width) / 2; - break; - - case 'TOPRIGHT': - $this->_top = 0; - $this->_left = $this->_pageWidth - $this->_width; - break; - - case 'LEFTCENTER': - $this->_top = ($this->_pageHeight - $this->_height) / 2; - $this->_left = 0; - break; - - case 'CENTER': - $this->_top = ($this->_pageHeight - $this->_height) / 2; - $this->_left = ($this->_pageWidth - $this->_width) / 2; - break; - - case 'RIGHTCENTER': - $this->_top = ($this->_pageHeight - $this->_height) / 2; - $this->_left = $this->_pageWidth - $this->_width; - break; - - case 'LEFTBOTTOM': - $this->_top = $this->_pageHeight - $this->_height; - $this->_left = 0; - break; - - case 'CENTERBOTTOM': - $this->_top = $this->_pageHeight - $this->_height; - $this->_left = ($this->_pageWidth - $this->_width) / 2; - break; - - case 'RIGHTBOTTOM': - $this->_top = $this->_pageHeight - $this->_height; - $this->_left = $this->_pageWidth - $this->_width; - break; - } - } - - $this->_pdflib = $this->_version(); - - $addPage = true; - if ((isset($param['pdf'])) && (is_resource($param['pdf']))) { - $this->_pdf =& $param['pdf']; - if ((isset($param['add_page'])) && ($param['add_page'] === false)) { - $addPage = false; - } - } else { - $this->_pdf = pdf_new(); - - if (isset($param['filename'])) { - pdf_open_file($this->_pdf, $param['filename']); - } else { - pdf_open_file($this->_pdf, ''); - } - - pdf_set_parameter($this->_pdf, 'warning', 'true'); - - pdf_set_info($this->_pdf, 'Creator', (isset($param['creator']) ? $param['creator'] : 'PEAR::Image_Canvas')); - pdf_set_info($this->_pdf, 'Author', (isset($param['author']) ? $param['author'] : 'Jesper Veggerby')); - pdf_set_info($this->_pdf, 'Title', (isset($param['title']) ? $param['title'] : 'Image_Canvas')); - } - - if ($addPage) { - pdf_begin_page($this->_pdf, $this->_pageWidth, $this->_pageHeight); - } - $this->_reset(); - } - - /** - * Get the x-point from the relative to absolute coordinates - * - * @param float $x The relative x-coordinate (in percentage of total width) - * @return float The x-coordinate as applied to the canvas - * @access private - */ - function _getX($x) - { - return $this->_left + $x; - } - - /** - * Get the y-point from the relative to absolute coordinates - * - * @param float $y The relative y-coordinate (in percentage of total width) - * @return float The y-coordinate as applied to the canvas - * @access private - */ - function _getY($y) - { - return $this->_pageHeight - ($this->_top + $y); - } - - /** - * Get the color index for the RGB color - * - * @param int $color The color - * @return int The GD image index of the color - * @access private - */ - function _color($color = false) - { - if (($color === false) || ($color === 'opague') || ($color === 'transparent')) { - return false; - } else { - $color = Image_Canvas_Color::color2RGB($color); - $color[0] = $color[0]/255; - $color[1] = $color[1]/255; - $color[2] = $color[2]/255; - return $color; - } - } - - /** - * Get the PDF linestyle - * - * @param mixed $lineStyle The line style to return, false if the one - * explicitly set - * @return bool True if set (so that a line should be drawn) - * @access private - */ - function _setLineStyle($lineStyle = false) - { - if ($lineStyle === false) { - $lineStyle = $this->_lineStyle; - } - - if (($lineStyle == 'transparent') || ($lineStyle === false)) { - return false; - } - - if (is_array($lineStyle)) { - // TODO Implement linestyles in PDFlib (using pdf_setcolor(.., 'pattern'...); ? - reset($lineStyle); - $lineStyle = current($lineStyle); - } - - $color = $this->_color($lineStyle); - - pdf_setlinewidth($this->_pdf, $this->_thickness); - if ($this->_pdflib < 4) { - pdf_setrgbcolor_stroke($this->_pdf, $color[0]/255, $color[1]/255, $color[2]/255); - } else { - pdf_setcolor($this->_pdf, 'stroke', 'rgb', $color[0], $color[1], $color[2], 0); - } - return true; - } - - /** - * Set the PDF fill style - * - * @param mixed $fillStyle The fillstyle to return, false if the one - * explicitly set - * @return bool True if set (so that a line should be drawn) - * @access private - */ - function _setFillStyle($fillStyle = false) - { - if ($fillStyle === false) { - $fillStyle = $this->_fillStyle; - } - - if (($fillStyle == 'transparent') || ($fillStyle === false)) { - return false; - } - - $color = $this->_color($fillStyle); - - if ($this->_pdflib < 4) { - pdf_setrgbcolor_fill($this->_pdf, $color[0]/255, $color[1]/255, $color[2]/255); - } else { - pdf_setcolor($this->_pdf, 'fill', 'rgb', $color[0], $color[1], $color[2], 0); - } - return true; - } - - /** - * Set the PDF font - * - * @access private - */ - function _setFont() - { - $this->_pdfFont = false; - if (isset($this->_font['name'])) { - pdf_set_parameter($this->_pdf, 'FontOutline', $this->_font['name'] . '=' . $this->_font['file']); - $this->_pdfFont = pdf_findfont($this->_pdf, $this->_font['name'], $this->_font['encoding'], 1); - - if ($this->_pdfFont) { - pdf_setfont($this->_pdf, $this->_pdfFont, $this->_font['size']); - $this->_setFillStyle($this->_font['color']); - } - } else { - $this->_setFillStyle('black'); - } - } - - /** - * Sets an image that should be used for filling. - * - * Image filling is not supported with PDF, filling 'transparent' - * - * @param string $filename The filename of the image to fill with - */ - function setFillImage($filename) - { - $this->_fillStyle = 'transparent'; - } - - /** - * Sets a gradient fill - * - * Gradient filling is not supported with PDF, end color used as solid fill. - * - * @param array $gradient Gradient fill options - */ - function setGradientFill($gradient) - { - $this->_fillStyle = $gradient['end']; - } - - /** - * Sets the font options. - * - * The $font array may have the following entries: - * - * 'ttf' = the .ttf file (either the basename, filename or full path) - * If 'ttf' is specified, then the following can be specified - * - * 'size' = size in pixels - * - * 'angle' = the angle with which to write the text - * - * @param array $font The font options. - */ - function setFont($fontOptions) - { - parent::setFont($fontOptions); - - if (!isset($this->_font['size'])) { - $this->_font['size'] = 12; - } - - if (!isset($this->_font['encoding'])) { - $this->_font['encoding'] = 'winansi'; - } - - if (!isset($this->_font['color'])) { - $this->_font['color'] = 'black'; - } - } - - /** - * Resets the canvas. - * - * Includes fillstyle, linestyle, thickness and polygon - * - * @access private - */ - function _reset() - { - pdf_initgraphics($this->_pdf); - parent::_reset(); - } - - /** - * Draw a line - * - * Parameter array: - * 'x0': int X start point - * 'y0': int Y start point - * 'x1': int X end point - * 'y1': int Y end point - * 'color': mixed [optional] The line color - * @param array $params Parameter array - */ - function line($params) - { - $color = (isset($params['color']) ? $params['color'] : false); - if ($this->_setLineStyle($color)) { - pdf_moveto($this->_pdf, $this->_getX($params['x0']), $this->_getY($params['y0'])); - pdf_lineto($this->_pdf, $this->_getX($params['x1']), $this->_getY($params['x1'])); - pdf_stroke($this->_pdf); - } - parent::line($params); - } - - /** - * Parameter array: - * 'connect': bool [optional] Specifies whether the start point should be - * connected to the endpoint (closed polygon) or not (connected line) - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function polygon($params = array()) - { - $connectEnds = (isset($params['connect']) ? $params['connect'] : false); - $fillColor = (isset($params['fill']) ? $params['line'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - $line = $this->_setLineStyle($lineColor); - $fill = false; - if ($connectEnds) { - $fill = $this->_setFillStyle($fillColor); - } - - $first = true; - foreach ($this->_polygon as $point) { - if ($first === true) { - pdf_moveto($this->_pdf, $point['X'], $point['Y']); - $first = $point; - } else { - if (isset($last['P1X'])) { - pdf_curveto($this->_pdf, - $last['P1X'], - $last['P1Y'], - $last['P2X'], - $last['P2Y'], - $point['X'], - $point['Y'] - ); - } else { - pdf_lineto($this->_pdf, - $point['X'], - $point['Y'] - ); - } - } - $last = $point; - } - - if ($connectEnds) { - if (isset($last['P1X'])) { - pdf_curveto($this->_pdf, - $last['P1X'], - $last['P1Y'], - $last['P2X'], - $last['P2Y'], - $first['X'], - $first['Y'] - ); - } else { - pdf_lineto($this->_pdf, - $first['X'], - $first['Y'] - ); - } - } - - if (($line) && ($fill)) { - pdf_fill_stroke($this->_pdf); - } elseif ($line) { - pdf_stroke($this->_pdf); - } elseif ($fill) { - pdf_fill($this->_pdf); - } - parent::polygon($params); - } - - /** - * Draw a rectangle - * - * Parameter array: - * 'x0': int X start point - * 'y0': int Y start point - * 'x1': int X end point - * 'y1': int Y end point - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function rectangle($params) - { - $x0 = $this->_getX($params['x0']); - $y0 = $this->_getY($params['y0']); - $x1 = $this->_getX($params['x1']); - $y1 = $this->_getY($params['y1']); - $fillColor = (isset($params['fill']) ? $params['line'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - $line = $this->_setLineStyle($lineColor); - $fill = $this->_setFillStyle($fillColor); - if (($line) || ($fill)) { - pdf_rect($this->_pdf, $this->_getX(min($x0, $x1)), $this->_getY(max($y0, $y1)), abs($x1 - $x0), abs($y1 - $y0)); - if (($line) && ($fill)) { - pdf_fill_stroke($this->_pdf); - } elseif ($line) { - pdf_stroke($this->_pdf); - } elseif ($fill) { - pdf_fill($this->_pdf); - } - } - parent::rectangle($params); - } - - /** - * Draw an ellipse - * - * Parameter array: - * 'x': int X center point - * 'y': int Y center point - * 'rx': int X radius - * 'ry': int Y radius - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function ellipse($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $rx = $this->_getX($params['rx']); - $ry = $this->_getY($params['ry']); - $fillColor = (isset($params['fill']) ? $params['line'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - $line = $this->_setLineStyle($lineColor); - $fill = $this->_setFillStyle($fillColor); - if (($line) || ($fill)) { - if ($rx == $ry) { - pdf_circle($this->_pdf, $this->_getX($x), $this->_getY($y), $rx); - } else { - pdf_moveto($this->_pdf, $this->_getX($x - $rx), $this->_getY($y)); - pdf_curveto($this->_pdf, - $this->_getX($x - $rx), $this->_getY($y), - $this->_getX($x - $rx), $this->_getY($y - $ry), - $this->_getX($x), $this->_getY($y - $ry) - ); - pdf_curveto($this->_pdf, - $this->_getX($x), $this->_getY($y - $ry), - $this->_getX($x + $rx), $this->_getY($y - $ry), - $this->_getX($x + $rx), $this->_getY($y) - ); - pdf_curveto($this->_pdf, - $this->_getX($x + $rx), $this->_getY($y), - $this->_getX($x + $rx), $this->_getY($y + $ry), - $this->_getX($x), $this->_getY($y + $ry) - ); - pdf_curveto($this->_pdf, - $this->_getX($x), $this->_getY($y + $ry), - $this->_getX($x - $rx), $this->_getY($y + $ry), - $this->_getX($x - $rx), $this->_getY($y) - ); - } - - if (($line) && ($fill)) { - pdf_fill_stroke($this->_pdf); - } elseif ($line) { - pdf_stroke($this->_pdf); - } elseif ($fill) { - pdf_fill($this->_pdf); - } - } - parent::ellipse($params); - } - - /** - * Draw a pie slice - * - * Parameter array: - * 'x': int X center point - * 'y': int Y center point - * 'rx': int X radius - * 'ry': int Y radius - * 'v1': int The starting angle (in degrees) - * 'v2': int The end angle (in degrees) - * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) - * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function pieslice($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $rx = $this->_getX($params['rx']); - $ry = $this->_getY($params['ry']); - $v1 = $this->_getX($params['v1']); - $v2 = $this->_getY($params['v2']); - $srx = $this->_getX($params['srx']); - $sry = $this->_getY($params['sry']); - $fillColor = (isset($params['fill']) ? $params['line'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - // TODO Implement PDFLIB::pieSlice() - parent::pieslice($params); - } - - /** - * Get the width of a text, - * - * @param string $text The text to get the width of - * @return int The width of the text - */ - function textWidth($text) - { - if ($this->_pdfFont === false) { - return $this->_font['size'] * 0.7 * strlen($text); - } else { - return pdf_stringwidth($this->_pdf, $text, $this->_pdfFont, $this->_font['size']); - } - } - - /** - * Get the height of a text, - * - * @param string $text The text to get the height of - * @return int The height of the text - */ - function textHeight($text) - { - if (isset($this->_font['size'])) { - return $this->_font['size']; - } else { - return 12; - } - } - - /** - * Writes text - * - * Parameter array: - * 'x': int X-point of text - * 'y': int Y-point of text - * 'text': string The text to add - * 'alignment': array [optional] Alignment - * 'color': mixed [optional] The color of the text - */ - function addText($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $text = $params['text']; - $color = (isset($params['color']) ? $params['color'] : false); - $alignment = (isset($params['alignment']) ? $params['alignment'] : false); - - $this->_setFont(); - - $textWidth = $this->textWidth($text); - $textHeight = $this->textHeight($text); - - if (!is_array($alignment)) { - $alignment = array('vertical' => 'top', 'horizontal' => 'left'); - } - - if (!isset($alignment['vertical'])) { - $alignment['vertical'] = 'top'; - } - - if (!isset($alignment['horizontal'])) { - $alignment['horizontal'] = 'left'; - } - - if ($alignment['horizontal'] == 'right') { - $x = $x - $textWidth; - } elseif ($alignment['horizontal'] == 'center') { - $x = $x - ($textWidth / 2); - } - - if ($alignment['vertical'] == 'top') { - $y = $y + $textHeight; - } elseif ($alignment['vertical'] == 'center') { - $y = $y + ($textHeight / 2); - } - - if (($color === false) && (isset($this->_font['color']))) { - $color = $this->_font['color']; - } - - pdf_show_xy($this->_pdf, $text, $this->_getX($x), $this->_getY($y)); - - parent::addText($params); - } - - /** - * Overlay image - * - * Parameter array: - * 'x': int X-point of overlayed image - * 'y': int Y-point of overlayed image - * 'filename': string The filename of the image to overlay - * 'width': int [optional] The width of the overlayed image (resizing if possible) - * 'height': int [optional] The height of the overlayed image (resizing if possible) - * 'alignment': array [optional] Alignment - */ - function image($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $filename = $params['filename']; - $width = (isset($params['width']) ? $params['width'] : false); - $height = (isset($params['height']) ? $params['height'] : false); - $alignment = (isset($params['alignment']) ? $params['alignment'] : false); - - if (substr($filename, -4) == '.png') { - $type = 'png'; - } elseif (substr($filename, -4) == '.jpg') { - $type = 'jpeg'; - } - - $image = pdf_load_image($this->_pdf, $type, realpath($filename), ''); - $width_ = pdf_get_value($this->_pdf, 'imagewidth', $image); - $height_ = pdf_get_value($this->_pdf, 'imageheight', $image); - - $outputWidth = ($width !== false ? $width : $width_); - $outputHeight = ($height !== false ? $height : $height_); - - if (!is_array($alignment)) { - $alignment = array('vertical' => 'top', 'horizontal' => 'left'); - } - - if (!isset($alignment['vertical'])) { - $alignment['vertical'] = 'top'; - } - - if (!isset($alignment['horizontal'])) { - $alignment['horizontal'] = 'left'; - } - - if ($alignment['horizontal'] == 'right') { - $x -= $outputWidth; - } elseif ($alignment['horizontal'] == 'center') { - $x -= $outputWidth / 2; - } - - if ($alignment['vertical'] == 'top') { - $y += $outputHeight; - } elseif ($alignment['vertical'] == 'center') { - $y += $outputHeight / 2; - } - - if (($width === false) && ($height === false)) { - $scale = 1; - } else { - $scale = max(($height/$height_), ($width/$width_)); - } - - pdf_place_image($this->_pdf, $image, $this->_getX($x), $this->_getY($y), $scale); - pdf_close_image($this->_pdf, $image); - - parent::image($params); - } - - /** - * Output the result of the canvas - * - * @param array $param Parameter array - * @abstract - */ - function show($param = false) - { - parent::show($param); - pdf_end_page($this->_pdf); - pdf_close($this->_pdf); - - $buf = pdf_get_buffer($this->_pdf); - $len = strlen($buf); - - header('Content-type: application/pdf'); - header('Content-Length: ' . $len); - header('Content-Disposition: inline; filename=image_graph.pdf'); - print $buf; - - pdf_delete($this->_pdf); - } - - /** - * Output the result of the canvas - * - * @param array $param Parameter array - * @abstract - */ - function save($param = false) - { - parent::save($param); - pdf_end_page($this->_pdf); - pdf_close($this->_pdf); - - $buf = pdf_get_buffer($this->_pdf); - $len = strlen($buf); - - $fp = @fopen($param['filename'], 'wb'); - if ($fp) { - fwrite($fp, $buf, strlen($buf)); - fclose($fp); - } - pdf_delete($this->_pdf); - } - - /** - * Get a canvas specific HTML tag. - * - * This method implicitly saves the canvas to the filename in the - * filesystem path specified and parses it as URL specified by URL path - * - * Parameter array: - * 'filename': string - * 'filepath': string Path to the file on the file system. Remember the final slash - * 'urlpath': string Path to the file available through an URL. Remember the final slash - * 'title': string The url title - */ - function toHtml($params) - { - parent::toHtml($params); - return '' . $params['title'] . ''; - } - - /** - * Check which major version of PDFlib is installed - * - * @return int The mahor version number of PDFlib - * @access private - */ - function _version() - { - $result = false; - if (function_exists('pdf_get_majorversion')) { - $version = pdf_get_majorversion(); - } else { - ob_start(); - phpinfo(8); - $php_info = ob_get_contents(); - ob_end_clean(); - - if (ereg("]*>PDFlib GmbH Version *<\/td>]*>([^<]*)<\/td>", - $php_info, $result)) - { - $version = $result[1]; - } - } - - if (ereg('([0-9]{1,2})\.[0-9]{1,2}(\.[0-9]{1,2})?', trim($version), $result)) { - return $result[1]; - } else { - return 0; - } - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: PDF.php,v 1.6 2006/04/11 21:12:41 nosey Exp $ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ + +/** + * Include file Image/Canvas.php + */ +require_once 'Image/Canvas.php'; + +/** + * Include file Image/Canvas/Color.php + */ +require_once 'Image/Canvas/Color.php'; + +/** + * PDF Canvas class. + * + * @category Images + * @package Image_Canvas + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ +class Image_Canvas_PDF extends Image_Canvas +{ + + /** + * The PDF document + * @var resource + * @access private + */ + var $_pdf; + + /** + * The major version of PDFlib + * @var int + * @access private + */ + var $_pdflib; + + /** + * The font + * @var mixed + * @access private + */ + var $_pdfFont = false; + + /** + * The width of the page + * @var int + * @access private + */ + var $_pageWidth; + + /** + * The height of the page + * @var int + * @access private + */ + var $_pageHeight; + + /** + * Create the PDF canvas. + * + * Parameters available: + * + * 'page' Specify the page/paper format for the graph's page, available + * formats are: A0, A1, A2, A3, A4, A5, A6, B5, letter, legal, ledger, + * 11x17, cd_front, inlay, inlay_nosides + * + * 'align' Alignment of the graph on the page, available options are: + * topleft, topcenter, topright, leftcenter, center, rightcenter, + * leftbottom, centerbottom, rightbottom + * + * 'orientation' Specifies the paper orientation, default is 'portrait' and + * 'landscape' is also supported. + * + * 'creator' The creator tag of the PDF/graph + * + * 'author' The author tag of the PDF/graph + * + * 'title' The title tag of the PDF/graph + * + * 'width' The width of the graph on the page + * + * 'height' The height of the graph on the page + * + * 'left' The left offset of the graph on the page + * + * 'top' The top offset of the graph on the page + * + * 'filename' The PDF file to open/add page to, using 'filename' requires + * the commercial version of PDFlib (http://www.pdflib.com/), this has for + * obvious ($ 450) reasons not been tested + * + * 'pdf' An existing PDFlib PDF document to add the page to + * + * 'add_page' (true/false) Used together with 'pdf', to specify whether the + * canvas should add a new graph page (true) or create the graph on the + * current page (false), default is 'true' + * + * The 'page' and 'width' & 'height' can be mutually omitted, if 'page' is + * omitted the page is created using dimensions of width x height, and if + * width and height are omitted the page dimensions are used for the graph. + * + * If 'pdf' is specified, 'filename', 'creator', 'author' and 'title' has no + * effect. + * + * 'left' and 'top' are overridden by 'align' + * + * It is required either to specify 'width' & 'height' or 'page'. + * + * The PDF format/PDFlib has some limitations on the capabilities, which + * means some functionality available using other canvass (fx. alpha + * blending and gradient fills) are not supported with PDF (see Canvas.txt + * in the docs/ folder for further details) + * + * @param array $param Parameter array + */ + function Image_Canvas_PDF($param) + { + if (isset($param['page'])) { + switch (strtoupper($param['page'])) { + case 'A0': + $this->_pageWidth = 2380; + $this->_pageHeight = 3368; + break; + + case 'A1': + $this->_pageWidth = 1684; + $this->_pageHeight = 2380; + break; + + case 'A2': + $this->_pageWidth = 1190; + $this->_pageHeight = 1684; + break; + + case 'A3': + $this->_pageWidth = 842; + $this->_pageHeight = 1190; + break; + + case 'A4': + $this->_pageWidth = 595; + $this->_pageHeight = 842; + break; + + case 'A5': + $this->_pageWidth = 421; + $this->_pageHeight = 595; + break; + + case 'A6': + $this->_pageWidth = 297; + $this->_pageHeight = 421; + break; + + case 'B5': + $this->_pageWidth = 501; + $this->_pageHeight = 709; + break; + + case 'LETTER': + $this->_pageWidth = 612; + $this->_pageHeight = 792; + break; + + case 'LEGAL': + $this->_pageWidth = 612; + $this->_pageHeight = 1008; + break; + + case 'LEDGER': + $this->_pageWidth = 1224; + $this->_pageHeight = 792; + break; + + case '11X17': + $this->_pageWidth = 792; + $this->_pageHeight = 1224; + break; + + case 'CD_FRONT': + $this->_pageWidth = 337; + $this->_pageHeight = 337; + break; + + case 'INLAY': + $this->_pageWidth = 425; + $this->_pageHeight = 332; + break; + + case 'INLAY_NOSIDES': + $this->_pageWidth = 390; + $this->_pageHeight = 332; + break; + } + } + + if ((isset($param['orientation'])) && (strtoupper($param['orientation']) == 'LANDSCAPE')) { + $w = $this->_pageWidth; + $this->_pageWidth = $this->_pageHeight; + $this->_pageHeight = $w; + } + + parent::Image_Canvas($param); + + if (!$this->_pageWidth) { + $this->_pageWidth = $this->_width; + } elseif (!$this->_width) { + $this->_width = $this->_pageWidth; + } + + if (!$this->_pageHeight) { + $this->_pageHeight = $this->_height; + } elseif (!$this->_height) { + $this->_height = $this->_pageHeight; + } + + $this->_width = min($this->_width, $this->_pageWidth); + $this->_height = min($this->_height, $this->_pageHeight); + + if ((isset($param['align'])) && + (($this->_width != $this->_pageWidth) || ($this->_height != $this->_pageHeight)) + ) { + switch (strtoupper($param['align'])) { + case 'TOPLEFT': + $this->_top = 0; + $this->_left = 0; + break; + + case 'TOPCENTER': + $this->_top = 0; + $this->_left = ($this->_pageWidth - $this->_width) / 2; + break; + + case 'TOPRIGHT': + $this->_top = 0; + $this->_left = $this->_pageWidth - $this->_width; + break; + + case 'LEFTCENTER': + $this->_top = ($this->_pageHeight - $this->_height) / 2; + $this->_left = 0; + break; + + case 'CENTER': + $this->_top = ($this->_pageHeight - $this->_height) / 2; + $this->_left = ($this->_pageWidth - $this->_width) / 2; + break; + + case 'RIGHTCENTER': + $this->_top = ($this->_pageHeight - $this->_height) / 2; + $this->_left = $this->_pageWidth - $this->_width; + break; + + case 'LEFTBOTTOM': + $this->_top = $this->_pageHeight - $this->_height; + $this->_left = 0; + break; + + case 'CENTERBOTTOM': + $this->_top = $this->_pageHeight - $this->_height; + $this->_left = ($this->_pageWidth - $this->_width) / 2; + break; + + case 'RIGHTBOTTOM': + $this->_top = $this->_pageHeight - $this->_height; + $this->_left = $this->_pageWidth - $this->_width; + break; + } + } + + $addPage = true; + if ((isset($param['pdf'])) && (is_resource($param['pdf']))) { + $this->_pdf =& $param['pdf']; + if ((isset($param['add_page'])) && ($param['add_page'] === false)) { + $addPage = false; + } + } else { + $this->_pdf = pdf_new(); + + if (isset($param['filename'])) { + pdf_open_file($this->_pdf, $param['filename']); + } else { + pdf_open_file($this->_pdf, ''); + } + + pdf_set_parameter($this->_pdf, 'warning', 'true'); + + pdf_set_info($this->_pdf, 'Creator', (isset($param['creator']) ? $param['creator'] : 'PEAR::Image_Canvas')); + pdf_set_info($this->_pdf, 'Author', (isset($param['author']) ? $param['author'] : 'Jesper Veggerby')); + pdf_set_info($this->_pdf, 'Title', (isset($param['title']) ? $param['title'] : 'Image_Canvas')); + } + + if ($addPage) { + pdf_begin_page($this->_pdf, $this->_pageWidth, $this->_pageHeight); + } + $this->_reset(); + + $this->_pdflib = $this->_version(); + } + + /** + * Get the x-point from the relative to absolute coordinates + * + * @param float $x The relative x-coordinate (in percentage of total width) + * @return float The x-coordinate as applied to the canvas + * @access private + */ + function _getX($x) + { + return $this->_left + $x; + } + + /** + * Get the y-point from the relative to absolute coordinates + * + * @param float $y The relative y-coordinate (in percentage of total width) + * @return float The y-coordinate as applied to the canvas + * @access private + */ + function _getY($y) + { + return $this->_pageHeight - ($this->_top + $y); + } + + /** + * Get the color index for the RGB color + * + * @param int $color The color + * @return int The GD image index of the color + * @access private + */ + function _color($color = false) + { + if (($color === false) || ($color === 'opague') || ($color === 'transparent')) { + return false; + } else { + $color = Image_Canvas_Color::color2RGB($color); + $color[0] = $color[0]/255; + $color[1] = $color[1]/255; + $color[2] = $color[2]/255; + return $color; + } + } + + /** + * Get the PDF linestyle + * + * @param mixed $lineStyle The line style to return, false if the one + * explicitly set + * @return bool True if set (so that a line should be drawn) + * @access private + */ + function _setLineStyle($lineStyle = false) + { + if ($lineStyle === false) { + $lineStyle = $this->_lineStyle; + } + + if (($lineStyle == 'transparent') || ($lineStyle === false)) { + return false; + } + + if (is_array($lineStyle)) { + // TODO Implement linestyles in PDFlib (using pdf_setcolor(.., 'pattern'...); ? + reset($lineStyle); + $lineStyle = current($lineStyle); + } + + $color = $this->_color($lineStyle); + + pdf_setlinewidth($this->_pdf, $this->_thickness); + if ($this->_pdflib < 4) { + pdf_setrgbcolor_stroke($this->_pdf, $color[0]/255, $color[1]/255, $color[2]/255); + } else { + pdf_setcolor($this->_pdf, 'stroke', 'rgb', $color[0], $color[1], $color[2], 0); + } + return true; + } + + /** + * Set the PDF fill style + * + * @param mixed $fillStyle The fillstyle to return, false if the one + * explicitly set + * @return bool True if set (so that a line should be drawn) + * @access private + */ + function _setFillStyle($fillStyle = false) + { + if ($fillStyle === false) { + $fillStyle = $this->_fillStyle; + } + + if (($fillStyle == 'transparent') || ($fillStyle === false)) { + return false; + } + + $color = $this->_color($fillStyle); + + if ($this->_pdflib < 4) { + pdf_setrgbcolor_fill($this->_pdf, $color[0]/255, $color[1]/255, $color[2]/255); + } else { + pdf_setcolor($this->_pdf, 'fill', 'rgb', $color[0], $color[1], $color[2], 0); + } + return true; + } + + /** + * Set the PDF font + * + * @access private + */ + function _setFont() + { + $this->_pdfFont = false; + if (isset($this->_font['name'])) { + pdf_set_parameter($this->_pdf, 'FontOutline', $this->_font['name'] . '=' . $this->_font['file']); + $this->_pdfFont = pdf_findfont($this->_pdf, $this->_font['name'], $this->_font['encoding'], 1); + + if ($this->_pdfFont) { + pdf_setfont($this->_pdf, $this->_pdfFont, $this->_font['size']); + $this->_setFillStyle($this->_font['color']); + } + } else { + $this->_setFillStyle('black'); + } + } + + /** + * Sets an image that should be used for filling. + * + * Image filling is not supported with PDF, filling 'transparent' + * + * @param string $filename The filename of the image to fill with + */ + function setFillImage($filename) + { + $this->_fillStyle = 'transparent'; + } + + /** + * Sets a gradient fill + * + * Gradient filling is not supported with PDF, end color used as solid fill. + * + * @param array $gradient Gradient fill options + */ + function setGradientFill($gradient) + { + $this->_fillStyle = $gradient['end']; + } + + /** + * Sets the font options. + * + * The $font array may have the following entries: + * + * 'ttf' = the .ttf file (either the basename, filename or full path) + * If 'ttf' is specified, then the following can be specified + * + * 'size' = size in pixels + * + * 'angle' = the angle with which to write the text + * + * @param array $font The font options. + */ + function setFont($fontOptions) + { + parent::setFont($fontOptions); + + if (!isset($this->_font['size'])) { + $this->_font['size'] = 12; + } + + if (!isset($this->_font['encoding'])) { + $this->_font['encoding'] = 'winansi'; + } + + if (!isset($this->_font['color'])) { + $this->_font['color'] = 'black'; + } + } + + /** + * Resets the canvas. + * + * Includes fillstyle, linestyle, thickness and polygon + * + * @access private + */ + function _reset() + { + pdf_initgraphics($this->_pdf); + parent::_reset(); + } + + /** + * Draw a line + * + * Parameter array: + * 'x0': int X start point + * 'y0': int Y start point + * 'x1': int X end point + * 'y1': int Y end point + * 'color': mixed [optional] The line color + * @param array $params Parameter array + */ + function line($params) + { + $color = (isset($params['color']) ? $params['color'] : false); + if ($this->_setLineStyle($color)) { + pdf_moveto($this->_pdf, $this->_getX($params['x0']), $this->_getY($params['y0'])); + pdf_lineto($this->_pdf, $this->_getX($params['x1']), $this->_getY($params['y1'])); + pdf_stroke($this->_pdf); + } + parent::line($params); + } + + /** + * Parameter array: + * 'connect': bool [optional] Specifies whether the start point should be + * connected to the endpoint (closed polygon) or not (connected line) + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function polygon($params = array()) + { + $connectEnds = (isset($params['connect']) ? $params['connect'] : false); + $fillColor = (isset($params['fill']) ? $params['line'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + $line = $this->_setLineStyle($lineColor); + $fill = false; + if ($connectEnds) { + $fill = $this->_setFillStyle($fillColor); + } + + $first = true; + foreach ($this->_polygon as $point) { + if ($first === true) { + pdf_moveto($this->_pdf, $point['X'], $point['Y']); + $first = $point; + } else { + if (isset($last['P1X'])) { + pdf_curveto($this->_pdf, + $last['P1X'], + $last['P1Y'], + $last['P2X'], + $last['P2Y'], + $point['X'], + $point['Y'] + ); + } else { + pdf_lineto($this->_pdf, + $point['X'], + $point['Y'] + ); + } + } + $last = $point; + } + + if ($connectEnds) { + if (isset($last['P1X'])) { + pdf_curveto($this->_pdf, + $last['P1X'], + $last['P1Y'], + $last['P2X'], + $last['P2Y'], + $first['X'], + $first['Y'] + ); + } else { + pdf_lineto($this->_pdf, + $first['X'], + $first['Y'] + ); + } + } + + if (($line) && ($fill)) { + pdf_fill_stroke($this->_pdf); + } elseif ($line) { + pdf_stroke($this->_pdf); + } elseif ($fill) { + pdf_fill($this->_pdf); + } + parent::polygon($params); + } + + /** + * Draw a rectangle + * + * Parameter array: + * 'x0': int X start point + * 'y0': int Y start point + * 'x1': int X end point + * 'y1': int Y end point + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function rectangle($params) + { + $x0 = $this->_getX($params['x0']); + $y0 = $this->_getY($params['y0']); + $x1 = $this->_getX($params['x1']); + $y1 = $this->_getY($params['y1']); + $fillColor = (isset($params['fill']) ? $params['line'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + $line = $this->_setLineStyle($lineColor); + $fill = $this->_setFillStyle($fillColor); + if (($line) || ($fill)) { + pdf_rect($this->_pdf, min($x0, $x1), min($y0, $y1), abs($x1 - $x0), abs($y1 - $y0)); + if (($line) && ($fill)) { + pdf_fill_stroke($this->_pdf); + } elseif ($line) { + pdf_stroke($this->_pdf); + } elseif ($fill) { + pdf_fill($this->_pdf); + } + } + parent::rectangle($params); + } + + /** + * Draw an ellipse + * + * Parameter array: + * 'x': int X center point + * 'y': int Y center point + * 'rx': int X radius + * 'ry': int Y radius + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function ellipse($params) + { + $x = $params['x']; + $y = $params['y']; + $rx = $params['rx']; + $ry = $params['ry']; + $fillColor = (isset($params['fill']) ? $params['line'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + $line = $this->_setLineStyle($lineColor); + $fill = $this->_setFillStyle($fillColor); + if (($line) || ($fill)) { + if ($rx == $ry) { + pdf_circle($this->_pdf, $this->_getX($x), $this->_getY($y), $rx); + } else { + pdf_moveto($this->_pdf, $this->_getX($x - $rx), $this->_getY($y)); + pdf_curveto($this->_pdf, + $this->_getX($x - $rx), $this->_getY($y), + $this->_getX($x - $rx), $this->_getY($y - $ry), + $this->_getX($x), $this->_getY($y - $ry) + ); + pdf_curveto($this->_pdf, + $this->_getX($x), $this->_getY($y - $ry), + $this->_getX($x + $rx), $this->_getY($y - $ry), + $this->_getX($x + $rx), $this->_getY($y) + ); + pdf_curveto($this->_pdf, + $this->_getX($x + $rx), $this->_getY($y), + $this->_getX($x + $rx), $this->_getY($y + $ry), + $this->_getX($x), $this->_getY($y + $ry) + ); + pdf_curveto($this->_pdf, + $this->_getX($x), $this->_getY($y + $ry), + $this->_getX($x - $rx), $this->_getY($y + $ry), + $this->_getX($x - $rx), $this->_getY($y) + ); + } + + if (($line) && ($fill)) { + pdf_fill_stroke($this->_pdf); + } elseif ($line) { + pdf_stroke($this->_pdf); + } elseif ($fill) { + pdf_fill($this->_pdf); + } + } + parent::ellipse($params); + } + + /** + * Draw a pie slice + * + * Parameter array: + * 'x': int X center point + * 'y': int Y center point + * 'rx': int X radius + * 'ry': int Y radius + * 'v1': int The starting angle (in degrees) + * 'v2': int The end angle (in degrees) + * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) + * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function pieslice($params) + { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $rx = $this->_getX($params['rx']); + $ry = $this->_getY($params['ry']); + $v1 = $this->_getX($params['v1']); + $v2 = $this->_getY($params['v2']); + $srx = $this->_getX($params['srx']); + $sry = $this->_getY($params['sry']); + $fillColor = (isset($params['fill']) ? $params['line'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + // TODO Implement PDFLIB::pieSlice() + parent::pieslice($params); + } + + /** + * Get the width of a text, + * + * @param string $text The text to get the width of + * @return int The width of the text + */ + function textWidth($text) + { + if ($this->_pdfFont === false) { + return $this->_font['size'] * 0.7 * strlen($text); + } else { + return pdf_stringwidth($this->_pdf, $text, $this->_pdfFont, $this->_font['size']); + } + } + + /** + * Get the height of a text, + * + * @param string $text The text to get the height of + * @return int The height of the text + */ + function textHeight($text) + { + if (isset($this->_font['size'])) { + return $this->_font['size']; + } else { + return 12; + } + } + + /** + * Writes text + * + * Parameter array: + * 'x': int X-point of text + * 'y': int Y-point of text + * 'text': string The text to add + * 'alignment': array [optional] Alignment + * 'color': mixed [optional] The color of the text + */ + function addText($params) + { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $text = $params['text']; + $color = (isset($params['color']) ? $params['color'] : false); + $alignment = (isset($params['alignment']) ? $params['alignment'] : false); + + $this->_setFont(); + + $textWidth = $this->textWidth($text); + $textHeight = $this->textHeight($text); + + if (!is_array($alignment)) { + $alignment = array('vertical' => 'top', 'horizontal' => 'left'); + } + + if (!isset($alignment['vertical'])) { + $alignment['vertical'] = 'top'; + } + + if (!isset($alignment['horizontal'])) { + $alignment['horizontal'] = 'left'; + } + + if ($alignment['horizontal'] == 'right') { + $x = $x - $textWidth; + } elseif ($alignment['horizontal'] == 'center') { + $x = $x - ($textWidth / 2); + } + + $y -= $textHeight; + + if ($alignment['vertical'] == 'bottom') { + $y = $y + $textHeight; + } elseif ($alignment['vertical'] == 'center') { + $y = $y + ($textHeight / 2); + } + + if (($color === false) && (isset($this->_font['color']))) { + $color = $this->_font['color']; + } + + pdf_show_xy($this->_pdf, $text, $x, $y); + + parent::addText($params); + } + + /** + * Overlay image + * + * Parameter array: + * 'x': int X-point of overlayed image + * 'y': int Y-point of overlayed image + * 'filename': string The filename of the image to overlay + * 'width': int [optional] The width of the overlayed image (resizing if possible) + * 'height': int [optional] The height of the overlayed image (resizing if possible) + * 'alignment': array [optional] Alignment + */ + function image($params) + { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $filename = $params['filename']; + $width = (isset($params['width']) ? $params['width'] : false); + $height = (isset($params['height']) ? $params['height'] : false); + $alignment = (isset($params['alignment']) ? $params['alignment'] : false); + + if (substr($filename, -4) == '.png') { + $type = 'png'; + } elseif (substr($filename, -4) == '.jpg') { + $type = 'jpeg'; + } + + $image = pdf_load_image($this->_pdf, $type, realpath($filename), ''); + $width_ = pdf_get_value($this->_pdf, 'imagewidth', $image); + $height_ = pdf_get_value($this->_pdf, 'imageheight', $image); + + $outputWidth = ($width !== false ? $width : $width_); + $outputHeight = ($height !== false ? $height : $height_); + + if (!is_array($alignment)) { + $alignment = array('vertical' => 'top', 'horizontal' => 'left'); + } + + if (!isset($alignment['vertical'])) { + $alignment['vertical'] = 'top'; + } + + if (!isset($alignment['horizontal'])) { + $alignment['horizontal'] = 'left'; + } + + if ($alignment['horizontal'] == 'right') { + $x -= $outputWidth; + } elseif ($alignment['horizontal'] == 'center') { + $x -= $outputWidth / 2; + } + + if ($alignment['vertical'] == 'top') { + $y += $outputHeight; + } elseif ($alignment['vertical'] == 'center') { + $y += $outputHeight / 2; + } + + if (($width === false) && ($height === false)) { + $scale = 1; + } else { + $scale = max(($height/$height_), ($width/$width_)); + } + + pdf_place_image($this->_pdf, $image, $x, $y, $scale); + pdf_close_image($this->_pdf, $image); + + parent::image($params); + } + + /** + * Output the result of the canvas + * + * @param array $param Parameter array + * @abstract + */ + function show($param = false) + { + parent::show($param); + pdf_end_page($this->_pdf); + pdf_close($this->_pdf); + + $buf = pdf_get_buffer($this->_pdf); + $len = strlen($buf); + + header('Content-type: application/pdf'); + header('Content-Length: ' . $len); + header('Content-Disposition: inline; filename=image_graph.pdf'); + print $buf; + + pdf_delete($this->_pdf); + } + + /** + * Output the result of the canvas + * + * @param array $param Parameter array + * @abstract + */ + function save($param = false) + { + parent::save($param); + pdf_end_page($this->_pdf); + pdf_close($this->_pdf); + + $buf = pdf_get_buffer($this->_pdf); + $len = strlen($buf); + + $fp = @fopen($param['filename'], 'wb'); + if ($fp) { + fwrite($fp, $buf, strlen($buf)); + fclose($fp); + } + pdf_delete($this->_pdf); + } + + /** + * Get a canvas specific HTML tag. + * + * This method implicitly saves the canvas to the filename in the + * filesystem path specified and parses it as URL specified by URL path + * + * Parameter array: + * 'filename': string + * 'filepath': string Path to the file on the file system. Remember the final slash + * 'urlpath': string Path to the file available through an URL. Remember the final slash + * 'title': string The url title + */ + function toHtml($params) + { + parent::toHtml($params); + return '' . $params['title'] . ''; + } + + /** + * Check which major version of PDFlib is installed + * + * @return int The mahor version number of PDFlib + * @access private + */ + function _version() + { + $result = false; + $version = ''; + if (function_exists('pdf_get_majorversion')) { + $version = pdf_get_majorversion(); + } else if (function_exists('pdf_get_value')) { + $version = pdf_get_value($this->_pdf, 'major', 0); + } else { + ob_start(); + phpinfo(8); + $php_info = ob_get_contents(); + ob_end_clean(); + + if (ereg("]*>PDFlib GmbH Version *<\/td>]*>([^<]*)<\/td>", + $php_info, $result)) + { + $version = $result[1]; + } + } + + if (ereg('([0-9]{1,2})\.[0-9]{1,2}(\.[0-9]{1,2})?', trim($version), $result)) { + return $result[1]; + } else { + return $version; + } + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Canvas/SVG.php b/includes/pear/Image/Canvas/SVG.php index d5f06845..f1c928a1 100644 --- a/includes/pear/Image/Canvas/SVG.php +++ b/includes/pear/Image/Canvas/SVG.php @@ -1,885 +1,979 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: SVG.php,v 1.9 2005/11/08 19:00:35 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -/** - * Include file Image/Canvas.php - */ -require_once 'Image/Canvas.php'; - -/** - * Include file Image/Canvas/Color.php - */ -require_once 'Image/Canvas/Color.php'; - -/** - * SVG Canvas class. - * - * @category Images - * @package Image_Canvas - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ -class Image_Canvas_SVG extends Image_Canvas -{ - - /** - * The SVG elements - * @var string - * @access private - */ - var $_elements = ''; - - /** - * The SVG defines - * @var string - * @access private - */ - var $_defs = ''; - - /** - * The current indention level - * @var string - * @access private - */ - var $_indent = ' '; - - /** - * A unieuq id counter - * @var int - * @access private - */ - var $_id = 1; - - /** - * The current group ids - * @var array - * @access private - */ - var $_groupIDs = array(); - - /** - * Create the SVG canvas. - * - * Parameters available: - * - * 'width' The width of the graph - * - * 'height' The height of the graph - * - * @param array $param Parameter array - */ - function Image_Canvas_SVG($param) - { - parent::Image_Canvas($param); - $this->_reset(); - } - - /** - * Add a SVG "element" to the output - * - * @param string $element The element - * @access private - */ - function _addElement($element, $params = array()) { - $elementdata = $this->_indent . $element . "\n"; - - if (isset($params['url'])) { - $url = $params['url']; - $target = (isset($params['target']) ? $params['target'] : false); - $alt = (isset($params['alt']) ? $params['alt'] : false); - - $tags = ''; - if (isset($params['htmltags'])) { - foreach ($params['htmltags'] as $key => $value) { - $tags .= ' '; - if (strpos($value, '"') >= 0) { - $tags .= $key . '=\'' . $value . '\''; - } else { - $tags .= $key . '="' . $value . '"'; - } - } - } - - $elementdata = - $this->_indent . '' . "\n" . - ' ' . $elementdata . - $this->_indent . '' . "\n"; - } - - - $this->_elements .= $elementdata; - } - - /** - * Add a SVG "define" to the output - * - * @param string $def The define - * @access private - */ - function _addDefine($def) { - $this->_defs .= ' ' . $def . "\n"; - } - - /** - * Get the color index for the RGB color - * - * @param int $color The color - * @return int A SVG compatible color - * @access private - */ - function _color($color = false) - { - if ($color === false) { - return 'transparent'; - } else { - $color = Image_Canvas_Color::color2RGB($color); - return 'rgb(' . $color[0] . ',' . $color[1] . ',' . $color[2] . ')'; - } - } - - /** - * Get the opacity for the RGB color - * - * @param int $color The color - * @return int A SVG compatible opacity value - * @access private - */ - function _opacity($color = false) - { - if ($color === false) { - return false; - } else { - $color = Image_Canvas_Color::color2RGB($color); - if ($color[3] != 255) { - return sprintf('%0.1f', $color[3]/255); - } else { - return false; - } - } - } - - /** - * Get the SVG applicable linestyle - * - * @param mixed $lineStyle The line style to return, false if the one - * explicitly set - * @return mixed A SVG compatible linestyle - * @access private - */ - function _getLineStyle($lineStyle = false) - { - $result = ''; - if ($lineStyle === false) { - $lineStyle = $this->_lineStyle; - } - - // TODO Linestyles (i.e. fx. dotted) does not work - - if (($lineStyle != 'transparent') && ($lineStyle !== false)) { - $result = 'stroke-width:' . $this->_thickness . ';'; - $result .= 'stroke:' .$this->_color($lineStyle) . ';'; - if ($opacity = $this->_opacity($lineStyle)) { - $result .= 'stroke-opacity:' . $opacity . ';'; - } - } - return $result; - } - - /** - * Get the SVG applicable fillstyle - * - * @param mixed $fillStyle The fillstyle to return, false if the one - * explicitly set - * @return mixed A SVG compatible fillstyle - * @access private - */ - function _getFillStyle($fillStyle = false) - { - $result = ''; - if ($fillStyle === false) { - $fillStyle = $this->_fillStyle; - } - - if (is_array($fillStyle)) { - if ($fillStyle['type'] == 'gradient') { - $id = 'gradient_' . ($this->_id++); - $startColor = $this->_color($fillStyle['start']); - $endColor = $this->_color($fillStyle['end']); - $startOpacity = $this->_opacity($fillStyle['start']); - $endOpacity = $this->_opacity($fillStyle['end']); - - switch ($fillStyle['direction']) { - case 'horizontal': - case 'horizontal_mirror': - $x1 = '0%'; - $y1 = '0%'; - $x2 = '100%'; - $y2 = '0%'; - break; - - case 'vertical': - case 'vertical_mirror': - $x1 = '0%'; - $y1 = '100%'; - $x2 = '0%'; - $y2 = '0%'; - break; - - case 'diagonal_tl_br': - $x1 = '0%'; - $y1 = '0%'; - $x2 = '100%'; - $y2 = '100%'; - break; - - case 'diagonal_bl_tr': - $x1 = '0%'; - $y1 = '100%'; - $x2 = '100%'; - $y2 = '0%'; - break; - - case 'radial': - $cx = '50%'; - $cy = '50%'; - $r = '100%'; - $fx = '50%'; - $fy = '50%'; - break; - - } - - if ($fillStyle['direction'] == 'radial') { - $this->_addDefine( - '' - ); - $this->_addDefine( - ' ' - ); - $this->_addDefine( - ' ' - ); - $this->_addDefine( - '' - ); - } elseif (($fillStyle['direction'] == 'vertical_mirror') || - ($fillStyle['direction'] == 'horizontal_mirror')) - { - $this->_addDefine( - '' - ); - $this->_addDefine( - ' ' - ); - $this->_addDefine( - ' ' - ); - $this->_addDefine( - ' ' - ); - $this->_addDefine( - '' - ); - } else { - $this->_addDefine( - '' - ); - $this->_addDefine( - ' ' - ); - $this->_addDefine( - ' ' - ); - $this->_addDefine( - '' - ); - } - - return 'fill:url(#' . $id . ');'; - } - } elseif (($fillStyle != 'transparent') && ($fillStyle !== false)) { - $result = 'fill:' . $this->_color($fillStyle) . ';'; - if ($opacity = $this->_opacity($fillStyle)) { - $result .= 'fill-opacity:' . $opacity . ';'; - } - return $result; - } else { - return 'fill:none;'; - } - } - - /** - * Sets an image that should be used for filling - * - * @param string $filename The filename of the image to fill with - */ - function setFillImage($filename) - { - } - - /** - * Sets a gradient fill - * - * @param array $gradient Gradient fill options - */ - function setGradientFill($gradient) - { - $this->_fillStyle = $gradient; - $this->_fillStyle['type'] = 'gradient'; - } - - /** - * Sets the font options. - * - * The $font array may have the following entries: - * 'type' = 'ttf' (TrueType) or omitted for default
- * If 'type' = 'ttf' then the following can be specified
- * 'size' = size in pixels
- * 'angle' = the angle with which to write the text - * 'file' = the .ttf file (either the basename, filename or full path) - * - * @param array $font The font options. - */ - function setFont($fontOptions) - { - parent::setFont($fontOptions); - if (!isset($this->_font['size'])) { - $this->_font['size'] = 10; - } - } - - /** - * Parameter array: - * 'x0': int X start point - * 'y0': int Y start point - * 'x1': int X end point - * 'y1': int Y end point - * 'color': mixed [optional] The line color - * @param array $params Parameter array - */ - function line($params) - { - $x0 = $this->_getX($params['x0']); - $y0 = $this->_getY($params['y0']); - $x1 = $this->_getX($params['x1']); - $y1 = $this->_getY($params['y1']); - $color = (isset($params['color']) ? $params['color'] : false); - - $style = $this->_getLineStyle($color) . $this->_getFillStyle('transparent'); - if ($style != '') { - $this->_addElement( - '', - $params - ); - } - parent::line($params); - } - - /** - * Parameter array: - * 'connect': bool [optional] Specifies whether the start point should be - * connected to the endpoint (closed polygon) or not (connected line) - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function polygon($params = array()) - { - $connectEnds = (isset($params['connect']) ? $params['connect'] : false); - $fillColor = (isset($params['fill']) ? $params['line'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - if (!$connectEnds) { - $fillColor = 'transparent'; - } - $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor); - - $first = true; - $spline = false; - $lastpoint = false; - foreach($this->_polygon as $point) { - if ($first) { - $points = 'M'; - } elseif (!$spline) { - $points .= ' L'; - } - - if (($spline) && ($lastpoint !== false)) { - $points .= ' ' .round($lastpoint['P1X']) . ',' . round($lastpoint['P1Y']) . ' ' . - round($lastpoint['P2X']) . ',' . round($lastpoint['P2Y']); - } - - $points .= ' ' . round($point['X']) . ',' . round($point['Y']); - - if ((isset($point['P1X'])) && (isset($point['P1Y'])) && - (isset($point['P2X'])) && (isset($point['P2Y']))) - { - if (($first) || (!$spline)) { - $points .= ' C'; - } - $lastpoint = $point; - $spline = true; - } else { - $spline = false; - } - $first = false; - } - if ($connectEnds) { - $point .= ' Z'; - } - $this->_addElement( - '', - $params - ); - - parent::polygon($params); - } - - /** - * Draw a rectangle - * - * Parameter array: - * 'x0': int X start point - * 'y0': int Y start point - * 'x1': int X end point - * 'y1': int Y end point - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function rectangle($params) - { - $x0 = min($this->_getX($params['x0']), $this->_getX($params['x1'])); - $y0 = min($this->_getY($params['y0']), $this->_getY($params['y1'])); - $x1 = max($this->_getX($params['x0']), $this->_getX($params['x1'])); - $y1 = max($this->_getY($params['y0']), $this->_getY($params['y1'])); - $fillColor = (isset($params['fill']) ? $params['line'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor); - if ($style != '') { - $this->_addElement( - '', - $params - ); - } - parent::rectangle($params); - } - - /** - * Draw an ellipse - * - * Parameter array: - * 'x': int X center point - * 'y': int Y center point - * 'rx': int X radius - * 'ry': int Y radius - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function ellipse($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $rx = $this->_getX($params['rx']); - $ry = $this->_getY($params['ry']); - $fillColor = (isset($params['fill']) ? $params['line'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor); - if ($style != '') { - $this->_addElement( - '', - $params - ); - } - parent::ellipse($params); - } - - /** - * Draw a pie slice - * - * Parameter array: - * 'x': int X center point - * 'y': int Y center point - * 'rx': int X radius - * 'ry': int Y radius - * 'v1': int The starting angle (in degrees) - * 'v2': int The end angle (in degrees) - * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) - * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function pieslice($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $rx = $this->_getX($params['rx']); - $ry = $this->_getY($params['ry']); - $v1 = $this->_getX($params['v1']); - $v2 = $this->_getY($params['v2']); - $srx = (isset($params['srx']) ? $this->_getX($params['srx']) : false); - $sry = (isset($params['sry']) ? $this->_getX($params['sry']) : false); - $fillColor = (isset($params['fill']) ? $params['line'] : false); - $lineColor = (isset($params['line']) ? $params['line'] : false); - - $dv = max($v2, $v1) - min($v2, $v1); - if ($dv >= 360) { - $this->ellipse($params); - } - else { - $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor); - if ($style != '') { - $x1 = ($x + $rx * cos(deg2rad(min($v1, $v2) % 360))); - $y1 = ($y + $ry * sin(deg2rad(min($v1, $v2) % 360))); - $x2 = ($x + $rx * cos(deg2rad(max($v1, $v2) % 360))); - $y2 = ($y + $ry * sin(deg2rad(max($v1, $v2) % 360))); - $this->_addElement( - '', - $params - ); - } - - parent::pieslice($params); - } - } - - /** - * Get the width of a text, - * - * @param string $text The text to get the width of - * @return int The width of the text - */ - function textWidth($text) - { - if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { - return $this->_font['size']; - } else { - return round($this->_font['size'] * 0.7 * strlen($text)); - } - } - - /** - * Get the height of a text, - * - * @param string $text The text to get the height of - * @return int The height of the text - */ - function textHeight($text) - { - if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { - return round($this->_font['size'] * 0.7 * strlen($text)); - } else { - return $this->_font['size']; - } - } - - /** - * Writes text - * - * Parameter array: - * 'x': int X-point of text - * 'y': int Y-point of text - * 'text': string The text to add - * 'alignment': array [optional] Alignment - * 'color': mixed [optional] The color of the text - */ - function addText($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $text = $params['text']; - $color = (isset($params['color']) ? $params['color'] : false); - $alignment = (isset($params['alignment']) ? $params['alignment'] : false); - - $textHeight = $this->textHeight($text); - - if (!is_array($alignment)) { - $alignment = array('vertical' => 'top', 'horizontal' => 'left'); - } - - if (!isset($alignment['vertical'])) { - $alignment['vertical'] = 'top'; - } - - if (!isset($alignment['horizontal'])) { - $alignment['horizontal'] = 'left'; - } - - $align = ''; - - if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { - $align .= 'writing-mode: tb-rl;'; - - if ($alignment['vertical'] == 'bottom') { - $align .= 'text-anchor:end;'; - //$y = $y + $textHeight; - } elseif ($alignment['vertical'] == 'center') { - //$y = $y + ($textHeight / 2); - $align .= 'text-anchor:middle;'; - } - } else { - if ($alignment['horizontal'] == 'right') { - $align .= 'text-anchor:end;'; - } elseif ($alignment['horizontal'] == 'center') { - $align .= 'text-anchor:middle;'; - } - - if ($alignment['vertical'] == 'top') { - $y = $y + $textHeight; - } elseif ($alignment['vertical'] == 'center') { - $y = $y + ($textHeight / 2); - } - } - - if (($color === false) && (isset($this->_font['color']))) { - $color = $this->_font['color']; - } - - $textColor = $this->_color($color); - $textOpacity = $this->_opacity($color); - - $this->_addElement( - '_font['angle']) && ($this->_font['angle'] > 0) ? - 'rotate="' . $this->_font['angle'] . '" ' : - '' - ) .*/ - 'style="' . - (isset($this->_font['name']) ? - 'font-family:' . $this->_font['name'] . ';' : '') . - 'font-size:' . $this->_font['size'] . 'px;fill=' . - $textColor . ($textOpacity ? ';fill-opacity:' . - $textOpacity : - '' - ) . ';' . $align . '">' . - htmlspecialchars($text) . - '', - $params - ); - parent::addText($params); - } - - /** - * Overlay image - * - * Parameter array: - * 'x': int X-point of overlayed image - * 'y': int Y-point of overlayed image - * 'filename': string The filename of the image to overlay - * 'width': int [optional] The width of the overlayed image (resizing if possible) - * 'height': int [optional] The height of the overlayed image (resizing if possible) - * 'alignment': array [optional] Alignment - */ - function image($params) - { - $x = $this->_getX($params['x']); - $y = $this->_getY($params['y']); - $filename = $params['filename']; - - list($width, $height, $type, $attr) = getimagesize($filename); - $width = (isset($params['width']) ? $params['width'] : $width); - $height = (isset($params['height']) ? $params['height'] : $height); - $alignment = (isset($params['alignment']) ? $params['alignment'] : false); - - $file = fopen($filename, 'rb'); - $filedata = fread($file, filesize($filename)); - fclose($file); - - $data = 'data:' . image_type_to_mime_type($type) . ';base64,' . base64_encode($filedata); - $this->_addElement( - '', - $params - ); - parent::image($params); - } - - /** - * Start a group. - * - * What this does, depends on the canvas/format. - * - * @param string $name The name of the group - */ - function startGroup($name = false) - { - $name = strtolower(str_replace(' ', '_', $name)); - if (in_array($name, $this->_groupIDs)) { - $name .= $this->_id; - $this->_id++; - } - $this->_groupIDs[] = $name; - $this->_addElement(''); - $this->_indent .= ' '; - } - - /** - * End the "current" group. - * - * What this does, depends on the canvas/format. - */ - function endGroup() - { - $this->_indent = substr($this->_indent, 0, -4); - $this->_addElement(''); - } - - /** - * Output the result of the canvas - * - * @param array $param Parameter array - */ - function show($param = false) - { - parent::show($param); - $output = '' . "\n" . - '' . "\n" . - '' . "\n" . - ($this->_defs ? - ' ' . "\n" . - $this->_defs . - ' ' . "\n" : - '' - ) . - $this->_elements . - ''; - - header('Content-Type: image/svg+xml'); - header('Content-Disposition: inline; filename = "' . basename($_SERVER['PHP_SELF'], '.php') . '.svg"'); - print $output; - } - - /** - * Output the result of the canvas - * - * @param array $param Parameter array - */ - function save($param = false) - { - parent::save($param); - $output = '' . "\n" . - '' . "\n" . - '' . "\n" . - ($this->_defs ? - ' ' . "\n" . - $this->_defs . - ' ' . "\n" : - '' - ) . - $this->_elements . - ''; - - $file = fopen($param['filename'], 'w+'); - fwrite($file, $output); - fclose($file); - } - - /** - * Get a canvas specific HTML tag. - * - * This method implicitly saves the canvas to the filename in the - * filesystem path specified and parses it as URL specified by URL path - * - * Parameter array: - * 'filename': string - * 'filepath': string Path to the file on the file system. Remember the final slash - * 'urlpath': string Path to the file available through an URL. Remember the final slash - * 'width': int The width in pixels - * 'height': int The height in pixels - */ - function toHtml($params) - { - parent::toHtml($params); - return ''; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: SVG.php,v 1.17 2007/06/22 20:15:35 nosey Exp $ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ + +/** + * Include file Image/Canvas.php + */ +require_once 'Image/Canvas.php'; + +/** + * Include file Image/Canvas/Color.php + */ +require_once 'Image/Canvas/Color.php'; + +/** + * SVG Canvas class. + * + * @category Images + * @package Image_Canvas + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ +class Image_Canvas_SVG extends Image_Canvas +{ + + /** + * The SVG elements + * @var string + * @access private + */ + var $_elements = ''; + + /** + * The SVG defines + * @var string + * @access private + */ + var $_defs = ''; + + /** + * The current indention level + * @var string + * @access private + */ + var $_indent = ' '; + + /** + * A unieuq id counter + * @var int + * @access private + */ + var $_id = 1; + + /** + * The current group ids + * @var array + * @access private + */ + var $_groupIDs = array(); + + /** + * The XML encoding (default iso-8859-1) + * @var string + * @access private + */ + var $_encoding = 'iso-8859-1'; + + /** + * Create the SVG canvas. + * + * Parameters available: + * + * 'width' The width of the graph + * + * 'height' The height of the graph + * + * 'encoding' The encoding of the SVG document + * + * @param array $param Parameter array + */ + function Image_Canvas_SVG($params) + { + parent::Image_Canvas($params); + $this->_reset(); + + if (isset($params['encoding'])) { + $this->_encoding = $params['encoding']; + } + } + + /** + * Add a SVG "element" to the output + * + * @param string $element The element + * @access private + */ + function _addElement($element, $params = array()) { + $elementdata = $this->_indent . $element . "\n"; + + if (isset($params['url'])) { + $url = $params['url']; + $target = (isset($params['target']) ? $params['target'] : false); + $alt = (isset($params['alt']) ? $params['alt'] : false); + + $tags = ''; + if (isset($params['htmltags'])) { + foreach ($params['htmltags'] as $key => $value) { + $tags .= ' '; + if (strpos($value, '"') >= 0) { + $tags .= $key . '=\'' . $value . '\''; + } else { + $tags .= $key . '="' . $value . '"'; + } + } + } + + $elementdata = + $this->_indent . '' . "\n" . + ' ' . $elementdata . + $this->_indent . '' . "\n"; + } + + + $this->_elements .= $elementdata; + } + + /** + * Add a SVG "define" to the output + * + * @param string $def The define + * @access private + */ + function _addDefine($def) { + $this->_defs .= ' ' . $def . "\n"; + } + + /** + * Get the color index for the RGB color + * + * @param int $color The color + * @return int A SVG compatible color + * @access private + */ + function _color($color = false) + { + if ($color === false) { + return 'transparent'; + } else { + $color = Image_Canvas_Color::color2RGB($color); + return 'rgb(' . $color[0] . ',' . $color[1] . ',' . $color[2] . ')'; + } + } + + /** + * Get the opacity for the RGB color + * + * @param int $color The color + * @return int A SVG compatible opacity value + * @access private + */ + function _opacity($color = false) + { + if ($color === false) { + return false; + } else { + $color = Image_Canvas_Color::color2RGB($color); + if ($color[3] != 255) { + return sprintf('%0.1f', $color[3]/255); + } else { + return false; + } + } + } + + /** + * Get the SVG applicable linestyle + * + * @param mixed $lineStyle The line style to return, false if the one + * explicitly set + * @return mixed A SVG compatible linestyle + * @access private + */ + function _getLineStyle($lineStyle = false) + { + $result = ''; + if ($lineStyle === false) { + $lineStyle = $this->_lineStyle; + } + + // TODO Linestyles (i.e. fx. dotted) does not work + + if (($lineStyle != 'transparent') && ($lineStyle !== false)) { + $result = 'stroke-width:' . $this->_thickness . ';'; + $result .= 'stroke:' .$this->_color($lineStyle) . ';'; + if ($opacity = $this->_opacity($lineStyle)) { + $result .= 'stroke-opacity:' . $opacity . ';'; + } + } + return $result; + } + + /** + * Get the SVG applicable fillstyle + * + * @param mixed $fillStyle The fillstyle to return, false if the one + * explicitly set + * @return mixed A SVG compatible fillstyle + * @access private + */ + function _getFillStyle($fillStyle = false) + { + $result = ''; + if ($fillStyle === false) { + $fillStyle = $this->_fillStyle; + } + + if (is_array($fillStyle)) { + if ($fillStyle['type'] == 'gradient') { + $id = 'gradient_' . ($this->_id++); + $startColor = $this->_color($fillStyle['start']); + $endColor = $this->_color($fillStyle['end']); + $startOpacity = $this->_opacity($fillStyle['start']); + $endOpacity = $this->_opacity($fillStyle['end']); + + switch ($fillStyle['direction']) { + case 'horizontal': + case 'horizontal_mirror': + $x1 = '0%'; + $y1 = '0%'; + $x2 = '100%'; + $y2 = '0%'; + break; + + case 'vertical': + case 'vertical_mirror': + $x1 = '0%'; + $y1 = '100%'; + $x2 = '0%'; + $y2 = '0%'; + break; + + case 'diagonal_tl_br': + $x1 = '0%'; + $y1 = '0%'; + $x2 = '100%'; + $y2 = '100%'; + break; + + case 'diagonal_bl_tr': + $x1 = '0%'; + $y1 = '100%'; + $x2 = '100%'; + $y2 = '0%'; + break; + + case 'radial': + $cx = '50%'; + $cy = '50%'; + $r = '100%'; + $fx = '50%'; + $fy = '50%'; + break; + + } + + if ($fillStyle['direction'] == 'radial') { + $this->_addDefine( + '' + ); + $this->_addDefine( + ' ' + ); + $this->_addDefine( + ' ' + ); + $this->_addDefine( + '' + ); + } elseif (($fillStyle['direction'] == 'vertical_mirror') || + ($fillStyle['direction'] == 'horizontal_mirror')) + { + $this->_addDefine( + '' + ); + $this->_addDefine( + ' ' + ); + $this->_addDefine( + ' ' + ); + $this->_addDefine( + ' ' + ); + $this->_addDefine( + '' + ); + } else { + $this->_addDefine( + '' + ); + $this->_addDefine( + ' ' + ); + $this->_addDefine( + ' ' + ); + $this->_addDefine( + '' + ); + } + + return 'fill:url(#' . $id . ');'; + } + } elseif (($fillStyle != 'transparent') && ($fillStyle !== false)) { + $result = 'fill:' . $this->_color($fillStyle) . ';'; + if ($opacity = $this->_opacity($fillStyle)) { + $result .= 'fill-opacity:' . $opacity . ';'; + } + return $result; + } else { + return 'fill:none;'; + } + } + + /** + * Sets an image that should be used for filling + * + * @param string $filename The filename of the image to fill with + */ + function setFillImage($filename) + { + } + + /** + * Sets a gradient fill + * + * @param array $gradient Gradient fill options + */ + function setGradientFill($gradient) + { + $this->_fillStyle = $gradient; + $this->_fillStyle['type'] = 'gradient'; + } + + /** + * Sets the font options. + * + * The $font array may have the following entries: + * 'type' = 'ttf' (TrueType) or omitted for default
+ * If 'type' = 'ttf' then the following can be specified
+ * 'size' = size in pixels
+ * 'angle' = the angle with which to write the text + * 'file' = the .ttf file (either the basename, filename or full path) + * + * @param array $font The font options. + */ + function setFont($fontOptions) + { + parent::setFont($fontOptions); + if (!isset($this->_font['size'])) { + $this->_font['size'] = 10; + } + } + + /** + * Parameter array: + * 'x0': int X start point + * 'y0': int Y start point + * 'x1': int X end point + * 'y1': int Y end point + * 'color': mixed [optional] The line color + * @param array $params Parameter array + */ + function line($params) + { + $x0 = $this->_getX($params['x0']); + $y0 = $this->_getY($params['y0']); + $x1 = $this->_getX($params['x1']); + $y1 = $this->_getY($params['y1']); + $color = (isset($params['color']) ? $params['color'] : false); + + $attrs = (isset($params['attrs']) && is_array($params['attrs'])) ? $this->_getAttributes($params['attrs']) : null; + + $style = $this->_getLineStyle($color) . $this->_getFillStyle('transparent'); + if ($style != '') { + $this->_addElement( + '', + $params + ); + } + parent::line($params); + } + + /** + * Parameter array: + * 'connect': bool [optional] Specifies whether the start point should be + * connected to the endpoint (closed polygon) or not (connected line) + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function polygon($params = array()) + { + $connectEnds = (isset($params['connect']) ? $params['connect'] : false); + $fillColor = (isset($params['fill']) ? $params['line'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + if (!$connectEnds) { + $fillColor = 'transparent'; + } + $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor); + + $attrs = (isset($params['attrs']) && is_array($params['attrs'])) ? $this->_getAttributes($params['attrs']) : null; + + $first = true; + $spline = false; + $lastpoint = false; + foreach($this->_polygon as $point) { + if ($first) { + $points = 'M'; + } elseif (!$spline) { + $points .= ' L'; + } + + if (($spline) && ($lastpoint !== false)) { + $points .= ' ' .round($lastpoint['P1X']) . ',' . round($lastpoint['P1Y']) . ' ' . + round($lastpoint['P2X']) . ',' . round($lastpoint['P2Y']); + } + + $points .= ' ' . round($point['X']) . ',' . round($point['Y']); + + if ((isset($point['P1X'])) && (isset($point['P1Y'])) && + (isset($point['P2X'])) && (isset($point['P2Y']))) + { + if (($first) || (!$spline)) { + $points .= ' C'; + } + $lastpoint = $point; + $spline = true; + } else { + $spline = false; + } + $first = false; + } + if ($connectEnds) { + $points .= ' Z'; + } + $this->_addElement( + '', + $params + ); + + parent::polygon($params); + } + + /** + * Draw a rectangle + * + * Parameter array: + * 'x0': int X start point + * 'y0': int Y start point + * 'x1': int X end point + * 'y1': int Y end point + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function rectangle($params) + { + $x0 = min($this->_getX($params['x0']), $this->_getX($params['x1'])); + $y0 = min($this->_getY($params['y0']), $this->_getY($params['y1'])); + $x1 = max($this->_getX($params['x0']), $this->_getX($params['x1'])); + $y1 = max($this->_getY($params['y0']), $this->_getY($params['y1'])); + $fillColor = (isset($params['fill']) ? $params['line'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + $attrs = (isset($params['attrs']) && is_array($params['attrs'])) ? $this->_getAttributes($params['attrs']) : null; + + $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor); + if ($style != '') { + $this->_addElement( + '', + $params + ); + } + parent::rectangle($params); + } + + /** + * Draw an ellipse + * + * Parameter array: + * 'x': int X center point + * 'y': int Y center point + * 'rx': int X radius + * 'ry': int Y radius + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function ellipse($params) + { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $rx = $this->_getX($params['rx']); + $ry = $this->_getY($params['ry']); + $fillColor = (isset($params['fill']) ? $params['line'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + $attrs = (isset($params['attrs']) && is_array($params['attrs'])) ? $this->_getAttributes($params['attrs']) : null; + + $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor); + if ($style != '') { + $this->_addElement( + '', + $params + ); + } + parent::ellipse($params); + } + + /** + * Draw a pie slice + * + * Parameter array: + * 'x': int X center point + * 'y': int Y center point + * 'rx': int X radius + * 'ry': int Y radius + * 'v1': int The starting angle (in degrees) + * 'v2': int The end angle (in degrees) + * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) + * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function pieslice($params) + { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $rx = $this->_getX($params['rx']); + $ry = $this->_getY($params['ry']); + $v1 = $this->_getX($params['v1']); + $v2 = $this->_getY($params['v2']); + $srx = (isset($params['srx']) ? $this->_getX($params['srx']) : false); + $sry = (isset($params['sry']) ? $this->_getX($params['sry']) : false); + $fillColor = (isset($params['fill']) ? $params['line'] : false); + $lineColor = (isset($params['line']) ? $params['line'] : false); + + $attrs = (isset($params['attrs']) && is_array($params['attrs'])) ? $this->_getAttributes($params['attrs']) : null; + + $dv = max($v2, $v1) - min($v2, $v1); + if ($dv >= 360) { + $this->ellipse($params); + } + else { + $style = $this->_getLineStyle($lineColor) . $this->_getFillStyle($fillColor); + if ($style != '') { + $x1 = ($x + $rx * cos(deg2rad(min($v1, $v2) % 360))); + $y1 = ($y + $ry * sin(deg2rad(min($v1, $v2) % 360))); + $x2 = ($x + $rx * cos(deg2rad(max($v1, $v2) % 360))); + $y2 = ($y + $ry * sin(deg2rad(max($v1, $v2) % 360))); + $this->_addElement( + '', + $params + ); + } + + parent::pieslice($params); + } + } + + /** + * Get the width of a text, + * + * @param string $text The text to get the width of + * @return int The width of the text + */ + function textWidth($text) + { + if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { + return $this->_font['size']; + } else { + return round($this->_font['size'] * 0.7 * strlen($text)); + } + } + + /** + * Get the height of a text, + * + * @param string $text The text to get the height of + * @return int The height of the text + */ + function textHeight($text) + { + if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { + return round($this->_font['size'] * 0.7 * strlen($text)); + } else { + return $this->_font['size']; + } + } + + /** + * Writes text + * + * Parameter array: + * 'x': int X-point of text + * 'y': int Y-point of text + * 'text': string The text to add + * 'alignment': array [optional] Alignment + * 'color': mixed [optional] The color of the text + */ + function addText($params) + { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $text = $params['text']; + $color = (isset($params['color']) ? $params['color'] : false); + $alignment = (isset($params['alignment']) ? $params['alignment'] : false); + + $attrs = (isset($params['attrs']) && is_array($params['attrs'])) ? $this->_getAttributes($params['attrs']) : null; + + $textHeight = $this->textHeight($text); + + if (!is_array($alignment)) { + $alignment = array('vertical' => 'top', 'horizontal' => 'left'); + } + + if (!isset($alignment['vertical'])) { + $alignment['vertical'] = 'top'; + } + + if (!isset($alignment['horizontal'])) { + $alignment['horizontal'] = 'left'; + } + + $align = ''; + + if ((isset($this->_font['vertical'])) && ($this->_font['vertical'])) { +// $align .= 'writing-mode: tb-rl;'; + + if ($alignment['vertical'] == 'bottom') { + $align .= 'text-anchor:end;'; + //$y = $y + $textHeight; + } elseif ($alignment['vertical'] == 'center') { + //$y = $y + ($textHeight / 2); + $align .= 'text-anchor:middle;'; + } + } else { + if ($alignment['horizontal'] == 'right') { + $align .= 'text-anchor:end;'; + } elseif ($alignment['horizontal'] == 'center') { + $align .= 'text-anchor:middle;'; + } + + if ($alignment['vertical'] == 'top') { + $y = $y + $textHeight; + } elseif ($alignment['vertical'] == 'center') { + $y = $y + ($textHeight / 2); + } + } + + if (($color === false) && (isset($this->_font['color']))) { + $color = $this->_font['color']; + } + + $textColor = $this->_color($color); + $textOpacity = $this->_opacity($color); + + $this->_addElement( + '' . "\n" . + $this->_indent . ' _font['angle']) && ($this->_font['angle'] > 0) ? + 'transform="rotate(' . (($this->_font['angle'] + 180) % 360) . ')" ' : + '' + ) . + 'style="' . + (isset($this->_font['name']) ? + 'font-family:' . $this->_font['name'] . ';' : '') . + 'font-size:' . $this->_font['size'] . 'px;fill:' . + $textColor . ($textOpacity ? ';fill-opacity:' . + $textOpacity : + '' + ) . ';' . $align . '"' . + ($attrs ? ' ' . $attrs : '') . + '>' . + htmlspecialchars($text) . + '' . "\n" . + $this->_indent . '', + $params + ); + parent::addText($params); + } + + /** + * Overlay image + * + * Parameter array: + * 'x': int X-point of overlayed image + * 'y': int Y-point of overlayed image + * 'filename': string The filename of the image to overlay + * 'width': int [optional] The width of the overlayed image (resizing if possible) + * 'height': int [optional] The height of the overlayed image (resizing if possible) + * 'alignment': array [optional] Alignment + */ + function image($params) + { + $x = $this->_getX($params['x']); + $y = $this->_getY($params['y']); + $filename = $params['filename']; + + $attrs = (isset($params['attrs']) && is_array($params['attrs'])) ? $this->_getAttributes($params['attrs']) : null; + + list($width, $height, $type, $attr) = getimagesize($filename); + $width = (isset($params['width']) ? $params['width'] : $width); + $height = (isset($params['height']) ? $params['height'] : $height); + $alignment = (isset($params['alignment']) ? $params['alignment'] : false); + + $file = fopen($filename, 'rb'); + $filedata = fread($file, filesize($filename)); + fclose($file); + + $data = 'data:' . image_type_to_mime_type($type) . ';base64,' . base64_encode($filedata); + + $this->_addElement( + '', + $params + ); + parent::image($params); + } + + /** + * Start a group. + * + * What this does, depends on the canvas/format. + * + * @param string $name The name of the group + */ + function startGroup($name = false) + { + $name = strtolower(str_replace(' ', '_', $name)); + if (in_array($name, $this->_groupIDs)) { + $name .= $this->_id; + $this->_id++; + } + $this->_groupIDs[] = $name; + $this->_addElement(''); + $this->_indent .= ' '; + } + + /** + * End the "current" group. + * + * What this does, depends on the canvas/format. + */ + function endGroup() + { + $this->_indent = substr($this->_indent, 0, -4); + $this->_addElement(''); + } + + /** + * Output the result of the canvas + * + * @param array $param Parameter array + */ + function show($param = false) + { + parent::show($param); + + $attrs = (isset($param['attrs']) && is_array($param['attrs'])) ? $this->_getAttributes($param['attrs']) : null; + + $output = $this->getData($param); + + header('Content-Type: image/svg+xml'); + header('Content-Disposition: inline; filename = "' . basename($_SERVER['PHP_SELF'], '.php') . '.svg"'); + print $output; + } + + /** + * Output the result of the canvas + * + * @param array $param Parameter array + */ + function save($param = false) + { + parent::save($param); + + $output = $this->getData($param); + + $file = fopen($param['filename'], 'w+'); + fwrite($file, $output); + fclose($file); + } + + + /** + * Get SVG data + * + * @param array $param Parameter array + * + * @return string + */ + function getData($param = false) + { + $attrs = (isset($param['attrs']) && is_array($param['attrs'])) ? $this->_getAttributes($param['attrs']) : null; + + return '_encoding . '"?>' . "\n" . + '' . "\n" . + '' . "\n" . + ($this->_defs ? + ' ' . "\n" . + $this->_defs . + ' ' . "\n" : + '' + ) . + $this->_elements . + ''; + } + + /** + * Set clipping to occur + * + * Parameter array: + * + * 'x0': int X point of Upper-left corner + * 'y0': int X point of Upper-left corner + * 'x1': int X point of lower-right corner + * 'y1': int Y point of lower-right corner + */ + function setClipping($params = false) + { + if ($params === false) { + $this->_addElement(''); + } + else { + $group = "clipping_" . $this->_id; + $this->_id++; + $this->_addElement(''); + + $this->_addDefine(''); + $this->_addDefine(' '); + $this->_addDefine(''); + } + } + + /** + * Get a canvas specific HTML tag. + * + * This method implicitly saves the canvas to the filename in the + * filesystem path specified and parses it as URL specified by URL path + * + * Parameter array: + * 'filename': string + * 'filepath': string Path to the file on the file system. Remember the final slash + * 'urlpath': string Path to the file available through an URL. Remember the final slash + * 'width': int The width in pixels + * 'height': int The height in pixels + */ + function toHtml($params) + { + parent::toHtml($params); + return ''; + } + + /** + * Converts array of attributes to string + * + * @param array $attrs Attributes array + * @return array + */ + function _getAttributes($attrs) + { + $string = ''; + + foreach ($attrs as $key => $value) { + $string .= ' ' . $key . '="' . $value . '"'; + } + + return $string; + } +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Canvas/Tool.php b/includes/pear/Image/Canvas/Tool.php index 7252f478..fb1393a9 100644 --- a/includes/pear/Image/Canvas/Tool.php +++ b/includes/pear/Image/Canvas/Tool.php @@ -1,217 +1,217 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Tool.php,v 1.3 2005/08/22 20:52:11 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -/** - * This class contains a set of tool-functions. - * - * These functions are all to be called statically - * - * @category Images - * @package Image_Canvas - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - * @abstract - */ -class Image_Canvas_Tool -{ - - /** - * Maps a font name to an actual font file (fx. a .ttf file) - * - * Used to translate names (i.e. 'Courier New' to 'cour.ttf' or - * '/Windows/Fonts/Cour.ttf') - * - * Font names are translated using the tab-separated file - * Image/Canvas/Tool/fontmap.txt. - * - * The translated font-name (or the original if no translation) exists is - * then returned if it is an existing file, otherwise the file is searched - * first in the path specified by IMAGE_CANVAS_SYSTEM_FONT_PATH defined in - * Image/Canvas.php, then in the Image/Canvas/Fonts folder. If a font is - * still not found and the name is not beginning with a '/' the search is - * left to the library, otherwise the font is deemed non-existing. - * - * @param string $name The name of the font - * @param string $type The needed file type of the font - * @return string The filename of the font - * @static - */ - function fontMap($name, $type = '.ttf') - { - static $_fontMap; - - if (!is_array($_fontMap)) { - if (file_exists($fontmap = (dirname(__FILE__) . '/Fonts/fontmap.txt'))) { - $file = file($fontmap); - foreach($file as $fontmapping) { - list($fontname, $filenames) = explode(',', $fontmapping, 2); - $fontname = trim($fontname); - $filenames = trim($filenames); - $filenames = explode(',', $filenames); - foreach ($filenames as $filename) { - $type_pos = strrpos($filename, '.'); - $type = substr($filename, $type_pos); - $_fontMap[$fontname][$type] = $filename; - } - } - } - } - - $type = strtolower($type); - - if ((isset($_fontMap[$name])) && (isset($_fontMap[$name][$type]))) { - $filename = $_fontMap[$name][$type]; - } else { - $filename = $name; - } - - if (substr($filename, -strlen($type)) !== $type) { - $filename .= $type; - } - - $result = false; - if (file_exists($filename)) { - $result = $filename; - } elseif (file_exists($file = (IMAGE_CANVAS_SYSTEM_FONT_PATH . $filename))) { - $result = $file; - } elseif (file_exists($file = (dirname(__FILE__) . '/Fonts/' . $filename))) { - $result = $file; - } elseif (substr($name, 0, 1) !== '/') { - // leave it to the library to find the font - $result = $name; - } - - return str_replace('\\', '/', $result); - } - - /** - * Return the average of 2 points - * - * @param double P1 1st point - * @param double P2 2nd point - * @return double The average of P1 and P2 - * @static - */ - function mid($p1, $p2) - { - return ($p1 + $p2) / 2; - } - - /** - * Mirrors P1 in P2 by a amount of Factor - * - * @param double $p1 1st point, point to mirror - * @param double $o2 2nd point, mirror point - * @param double $factor Mirror factor, 0 returns $p2, 1 returns a pure - * mirror, ie $p1 on the exact other side of $p2 - * @return double $p1 mirrored in $p2 by Factor - * @static - */ - function mirror($p1, $p2, $factor = 1) - { - return $p2 + $factor * ($p2 - $p1); - } - - /** - * Calculates a Bezier control point, this function must be called for BOTH - * X and Y coordinates (will it work for 3D coordinates!?) - * - * @param double $p1 1st point - * @param double $p2 Point to - * @param double $factor Mirror factor, 0 returns P2, 1 returns a pure - * mirror, i.e. P1 on the exact other side of P2 - * @return double P1 mirrored in P2 by Factor - * @static - */ - function controlPoint($p1, $p2, $factor, $smoothFactor = 0.75) - { - $sa = Image_Canvas_Tool::mirror($p1, $p2, $smoothFactor); - $sb = Image_Canvas_Tool::mid($p2, $sa); - - $m = Image_Canvas_Tool::mid($p2, $factor); - - $pC = Image_Canvas_Tool::mid($sb, $m); - - return $pC; - } - - /** - * Calculates a Bezier point, this function must be called for BOTH X and Y - * coordinates (will it work for 3D coordinates!?) - * - * @param double $t A position between $p2 and $p3, value between 0 and 1 - * @param double $p1 Point to use for calculating control points - * @param double $p2 Point 1 to calculate bezier curve between - * @param double $p3 Point 2 to calculate bezier curve between - * @param double $p4 Point to use for calculating control points - * @return double The bezier value of the point t between $p2 and $p3 using - * $p1 and $p4 to calculate control points - * @static - */ - function bezier($t, $p1, $p2, $p3, $p4) - { - // (1-t)^3*p1 + 3*(1-t)^2*t*p2 + 3*(1-t)*t^2*p3 + t^3*p4 - return pow(1 - $t, 3) * $p1 + - 3 * pow(1 - $t, 2) * $t * $p2 + - 3 * (1 - $t) * pow($t, 2) * $p3 + - pow($t, 3) * $p4; - } - - /** - * Gets the angle / slope of a line relative to horizontal (left -> right) - * - * @param double $x0 The starting x point - * @param double $y0 The starting y point - * @param double $x1 The ending x point - * @param double $y1 The ending y point - * @param double The angle in degrees of the line - * @static - */ - function getAngle($x0, $y0, $x1, $y1) - { - - $dx = ($x1 - $x0); - $dy = ($y1 - $y0); - $l = sqrt($dx * $dx + $dy * $dy); - $v = rad2deg(asin(($y0 - $y1) / $l)); - if ($dx < 0) { - $v = 180 - $v; - } - return $v; - - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Tool.php,v 1.3 2005/08/22 20:52:11 nosey Exp $ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ + +/** + * This class contains a set of tool-functions. + * + * These functions are all to be called statically + * + * @category Images + * @package Image_Canvas + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + * @abstract + */ +class Image_Canvas_Tool +{ + + /** + * Maps a font name to an actual font file (fx. a .ttf file) + * + * Used to translate names (i.e. 'Courier New' to 'cour.ttf' or + * '/Windows/Fonts/Cour.ttf') + * + * Font names are translated using the tab-separated file + * Image/Canvas/Tool/fontmap.txt. + * + * The translated font-name (or the original if no translation) exists is + * then returned if it is an existing file, otherwise the file is searched + * first in the path specified by IMAGE_CANVAS_SYSTEM_FONT_PATH defined in + * Image/Canvas.php, then in the Image/Canvas/Fonts folder. If a font is + * still not found and the name is not beginning with a '/' the search is + * left to the library, otherwise the font is deemed non-existing. + * + * @param string $name The name of the font + * @param string $type The needed file type of the font + * @return string The filename of the font + * @static + */ + function fontMap($name, $type = '.ttf') + { + static $_fontMap; + + if (!is_array($_fontMap)) { + if (file_exists($fontmap = (dirname(__FILE__) . '/Fonts/fontmap.txt'))) { + $file = file($fontmap); + foreach($file as $fontmapping) { + list($fontname, $filenames) = explode(',', $fontmapping, 2); + $fontname = trim($fontname); + $filenames = trim($filenames); + $filenames = explode(',', $filenames); + foreach ($filenames as $filename) { + $type_pos = strrpos($filename, '.'); + $type = substr($filename, $type_pos); + $_fontMap[$fontname][$type] = $filename; + } + } + } + } + + $type = strtolower($type); + + if ((isset($_fontMap[$name])) && (isset($_fontMap[$name][$type]))) { + $filename = $_fontMap[$name][$type]; + } else { + $filename = $name; + } + + if (substr($filename, -strlen($type)) !== $type) { + $filename .= $type; + } + + $result = false; + if (file_exists($filename)) { + $result = $filename; + } elseif (file_exists($file = (IMAGE_CANVAS_SYSTEM_FONT_PATH . $filename))) { + $result = $file; + } elseif (file_exists($file = (dirname(__FILE__) . '/Fonts/' . $filename))) { + $result = $file; + } elseif (substr($name, 0, 1) !== '/') { + // leave it to the library to find the font + $result = $name; + } + + return str_replace('\\', '/', $result); + } + + /** + * Return the average of 2 points + * + * @param double P1 1st point + * @param double P2 2nd point + * @return double The average of P1 and P2 + * @static + */ + function mid($p1, $p2) + { + return ($p1 + $p2) / 2; + } + + /** + * Mirrors P1 in P2 by a amount of Factor + * + * @param double $p1 1st point, point to mirror + * @param double $o2 2nd point, mirror point + * @param double $factor Mirror factor, 0 returns $p2, 1 returns a pure + * mirror, ie $p1 on the exact other side of $p2 + * @return double $p1 mirrored in $p2 by Factor + * @static + */ + function mirror($p1, $p2, $factor = 1) + { + return $p2 + $factor * ($p2 - $p1); + } + + /** + * Calculates a Bezier control point, this function must be called for BOTH + * X and Y coordinates (will it work for 3D coordinates!?) + * + * @param double $p1 1st point + * @param double $p2 Point to + * @param double $factor Mirror factor, 0 returns P2, 1 returns a pure + * mirror, i.e. P1 on the exact other side of P2 + * @return double P1 mirrored in P2 by Factor + * @static + */ + function controlPoint($p1, $p2, $factor, $smoothFactor = 0.75) + { + $sa = Image_Canvas_Tool::mirror($p1, $p2, $smoothFactor); + $sb = Image_Canvas_Tool::mid($p2, $sa); + + $m = Image_Canvas_Tool::mid($p2, $factor); + + $pC = Image_Canvas_Tool::mid($sb, $m); + + return $pC; + } + + /** + * Calculates a Bezier point, this function must be called for BOTH X and Y + * coordinates (will it work for 3D coordinates!?) + * + * @param double $t A position between $p2 and $p3, value between 0 and 1 + * @param double $p1 Point to use for calculating control points + * @param double $p2 Point 1 to calculate bezier curve between + * @param double $p3 Point 2 to calculate bezier curve between + * @param double $p4 Point to use for calculating control points + * @return double The bezier value of the point t between $p2 and $p3 using + * $p1 and $p4 to calculate control points + * @static + */ + function bezier($t, $p1, $p2, $p3, $p4) + { + // (1-t)^3*p1 + 3*(1-t)^2*t*p2 + 3*(1-t)*t^2*p3 + t^3*p4 + return pow(1 - $t, 3) * $p1 + + 3 * pow(1 - $t, 2) * $t * $p2 + + 3 * (1 - $t) * pow($t, 2) * $p3 + + pow($t, 3) * $p4; + } + + /** + * Gets the angle / slope of a line relative to horizontal (left -> right) + * + * @param double $x0 The starting x point + * @param double $y0 The starting y point + * @param double $x1 The ending x point + * @param double $y1 The ending y point + * @param double The angle in degrees of the line + * @static + */ + function getAngle($x0, $y0, $x1, $y1) + { + + $dx = ($x1 - $x0); + $dy = ($y1 - $y0); + $l = sqrt($dx * $dx + $dy * $dy); + $v = rad2deg(asin(($y0 - $y1) / $l)); + if ($dx < 0) { + $v = 180 - $v; + } + return $v; + + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Canvas/WithMap.php b/includes/pear/Image/Canvas/WithMap.php index 3206af4b..b9689757 100644 --- a/includes/pear/Image/Canvas/WithMap.php +++ b/includes/pear/Image/Canvas/WithMap.php @@ -1,278 +1,278 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: WithMap.php,v 1.3 2005/08/24 20:37:35 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -/** - * Class for handling different output formats including a HTML image map - * - * @category Images - * @package Image_Canvas - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - * @since version 0.2.0 - * @abstract - */ -class Image_Canvas_WithMap extends Image_Canvas -{ - - /** - * The image map - * @var Image_Canvas_ImageMap - * @access private - */ - var $_imageMap = null; - - /** - * Create the canvas. - * - * Parameters available: - * - * 'width' The width of the graph on the canvas - * - * 'height' The height of the graph on the canvas - * - * 'left' The left offset of the graph on the canvas - * - * 'top' The top offset of the graph on the canvas - * - * 'usemap' Initialize an image map - * - * @param array $params Parameter array - * @abstract - */ - function Image_Canvas_WithMap($params) - { - parent::Image_Canvas($params); - - if ((isset($params['usemap'])) && ($params['usemap'] === true)) { - $this->_imageMap =& Image_Canvas::factory( - 'ImageMap', - array( - 'left' => $this->_left, - 'top' => $this->_top, - 'width' => $this->_width, - 'height' => $this->_height - ) - ); - } - } - /** - * Draw a line - * - * Parameter array: - * 'x0': int X start point - * 'y0': int Y start point - * 'x1': int X end point - * 'y1': int Y end point - * 'color': mixed [optional] The line color - * @param array $params Parameter array - */ - function line($params) - { - if (isset($this->_imageMap)) { - $this->_imageMap->line($params); - } - parent::line($params); - } - - /** - * Adds vertex to a polygon - * - * Parameter array: - * 'x': int X point - * 'y': int Y point - * @param array $params Parameter array - */ - function addVertex($params) - { - if (isset($this->_imageMap)) { - $this->_imageMap->addVertex($params); - } - parent::addVertex($params); - } - - /** - * Adds "splined" vertex to a polygon - * - * Parameter array: - * 'x': int X point - * 'y': int Y point - * 'p1x': X Control point 1 - * 'p1y': Y Control point 1 - * 'p2x': X Control point 2 - * 'p2y': Y Control point 2 - * @param array $params Parameter array - */ - function addSpline($params) - { - if (isset($this->_imageMap)) { - $this->_imageMap->addSpline($params); - } - parent::addSpline($params); - } - - /** - * Draws a polygon - * - * Parameter array: - * 'connect': bool [optional] Specifies whether the start point should be - * connected to the endpoint (closed polygon) or not (connected line) - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function polygon($params) - { - if (isset($this->_imageMap)) { - $this->_imageMap->polygon($params); - } - parent::polygon($params); - } - - /** - * Draw a rectangle - * - * Parameter array: - * 'x0': int X start point - * 'y0': int Y start point - * 'x1': int X end point - * 'y1': int Y end point - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function rectangle($params) - { - if (isset($this->_imageMap)) { - $this->_imageMap->rectangle($params); - } - parent::rectangle($params); - } - - /** - * Draw an ellipse - * - * Parameter array: - * 'x': int X center point - * 'y': int Y center point - * 'rx': int X radius - * 'ry': int Y radius - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function ellipse($params) - { - if (isset($this->_imageMap)) { - $this->_imageMap->ellipse($params); - } - parent::ellipse($params); - } - - /** - * Draw a pie slice - * - * Parameter array: - * 'x': int X center point - * 'y': int Y center point - * 'rx': int X radius - * 'ry': int Y radius - * 'v1': int The starting angle (in degrees) - * 'v2': int The end angle (in degrees) - * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) - * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) - * 'fill': mixed [optional] The fill color - * 'line': mixed [optional] The line color - * @param array $params Parameter array - */ - function pieslice($params) - { - if (isset($this->_imageMap)) { - $this->_imageMap->pieslice($params); - } - parent::pieslice($params); - } - - /** - * Writes text - * - * Parameter array: - * 'x': int X-point of text - * 'y': int Y-point of text - * 'text': string The text to add - * 'alignment': array [optional] Alignment - * 'color': mixed [optional] The color of the text - */ - function addText($params) - { - if (isset($this->_imageMap)) { - $this->_imageMap->addText($params); - } - parent::addText($params); - } - - /** - * Overlay image - * - * Parameter array: - * 'x': int X-point of overlayed image - * 'y': int Y-point of overlayed image - * 'filename': string The filename of the image to overlay - * 'width': int [optional] The width of the overlayed image (resizing if possible) - * 'height': int [optional] The height of the overlayed image (resizing if possible) - * 'alignment': array [optional] Alignment - */ - function image($params) - { - if (isset($this->_imageMap)) { - $this->_imageMap->image($params); - } - parent::image($params); - } - - /** - * Get the imagemap - * @return Image_Graph_ImageMap The image map (or false if none) - */ - function &getImageMap() - { - $result = null; - if (isset($this->_imageMap)) { - $result =& $this->_imageMap; - } - return $result; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: WithMap.php,v 1.3 2005/08/24 20:37:35 nosey Exp $ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + */ + +/** + * Class for handling different output formats including a HTML image map + * + * @category Images + * @package Image_Canvas + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 + * @since version 0.2.0 + * @abstract + */ +class Image_Canvas_WithMap extends Image_Canvas +{ + + /** + * The image map + * @var Image_Canvas_ImageMap + * @access private + */ + var $_imageMap = null; + + /** + * Create the canvas. + * + * Parameters available: + * + * 'width' The width of the graph on the canvas + * + * 'height' The height of the graph on the canvas + * + * 'left' The left offset of the graph on the canvas + * + * 'top' The top offset of the graph on the canvas + * + * 'usemap' Initialize an image map + * + * @param array $params Parameter array + * @abstract + */ + function Image_Canvas_WithMap($params) + { + parent::Image_Canvas($params); + + if ((isset($params['usemap'])) && ($params['usemap'] === true)) { + $this->_imageMap =& Image_Canvas::factory( + 'ImageMap', + array( + 'left' => $this->_left, + 'top' => $this->_top, + 'width' => $this->_width, + 'height' => $this->_height + ) + ); + } + } + /** + * Draw a line + * + * Parameter array: + * 'x0': int X start point + * 'y0': int Y start point + * 'x1': int X end point + * 'y1': int Y end point + * 'color': mixed [optional] The line color + * @param array $params Parameter array + */ + function line($params) + { + if (isset($this->_imageMap)) { + $this->_imageMap->line($params); + } + parent::line($params); + } + + /** + * Adds vertex to a polygon + * + * Parameter array: + * 'x': int X point + * 'y': int Y point + * @param array $params Parameter array + */ + function addVertex($params) + { + if (isset($this->_imageMap)) { + $this->_imageMap->addVertex($params); + } + parent::addVertex($params); + } + + /** + * Adds "splined" vertex to a polygon + * + * Parameter array: + * 'x': int X point + * 'y': int Y point + * 'p1x': X Control point 1 + * 'p1y': Y Control point 1 + * 'p2x': X Control point 2 + * 'p2y': Y Control point 2 + * @param array $params Parameter array + */ + function addSpline($params) + { + if (isset($this->_imageMap)) { + $this->_imageMap->addSpline($params); + } + parent::addSpline($params); + } + + /** + * Draws a polygon + * + * Parameter array: + * 'connect': bool [optional] Specifies whether the start point should be + * connected to the endpoint (closed polygon) or not (connected line) + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function polygon($params) + { + if (isset($this->_imageMap)) { + $this->_imageMap->polygon($params); + } + parent::polygon($params); + } + + /** + * Draw a rectangle + * + * Parameter array: + * 'x0': int X start point + * 'y0': int Y start point + * 'x1': int X end point + * 'y1': int Y end point + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function rectangle($params) + { + if (isset($this->_imageMap)) { + $this->_imageMap->rectangle($params); + } + parent::rectangle($params); + } + + /** + * Draw an ellipse + * + * Parameter array: + * 'x': int X center point + * 'y': int Y center point + * 'rx': int X radius + * 'ry': int Y radius + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function ellipse($params) + { + if (isset($this->_imageMap)) { + $this->_imageMap->ellipse($params); + } + parent::ellipse($params); + } + + /** + * Draw a pie slice + * + * Parameter array: + * 'x': int X center point + * 'y': int Y center point + * 'rx': int X radius + * 'ry': int Y radius + * 'v1': int The starting angle (in degrees) + * 'v2': int The end angle (in degrees) + * 'srx': int [optional] Starting X-radius of the pie slice (i.e. for a doughnut) + * 'sry': int [optional] Starting Y-radius of the pie slice (i.e. for a doughnut) + * 'fill': mixed [optional] The fill color + * 'line': mixed [optional] The line color + * @param array $params Parameter array + */ + function pieslice($params) + { + if (isset($this->_imageMap)) { + $this->_imageMap->pieslice($params); + } + parent::pieslice($params); + } + + /** + * Writes text + * + * Parameter array: + * 'x': int X-point of text + * 'y': int Y-point of text + * 'text': string The text to add + * 'alignment': array [optional] Alignment + * 'color': mixed [optional] The color of the text + */ + function addText($params) + { + if (isset($this->_imageMap)) { + $this->_imageMap->addText($params); + } + parent::addText($params); + } + + /** + * Overlay image + * + * Parameter array: + * 'x': int X-point of overlayed image + * 'y': int Y-point of overlayed image + * 'filename': string The filename of the image to overlay + * 'width': int [optional] The width of the overlayed image (resizing if possible) + * 'height': int [optional] The height of the overlayed image (resizing if possible) + * 'alignment': array [optional] Alignment + */ + function image($params) + { + if (isset($this->_imageMap)) { + $this->_imageMap->image($params); + } + parent::image($params); + } + + /** + * Get the imagemap + * @return Image_Graph_ImageMap The image map (or false if none) + */ + function &getImageMap() + { + $result = null; + if (isset($this->_imageMap)) { + $result =& $this->_imageMap; + } + return $result; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Color.php b/includes/pear/Image/Color.php index 471f6f24..bf658362 100644 --- a/includes/pear/Image/Color.php +++ b/includes/pear/Image/Color.php @@ -1,719 +1,723 @@ - - * @author Andrew Morton - * @copyright 2003-2005 The PHP Group - * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Color.php,v 1.15 2005/09/12 19:12:02 drewish Exp $ - * @link http://pear.php.net/package/Image_Color - */ - -/** - * Image_Color handles color conversion and mixing. - * - * The class is quick, simple to use, and does its job fairly well but it's got - * some code smells: - * - Call setColors() for some functions but not others. - * - Different functions expect different color formats. setColors() only - * accepts hex while allocateColor() will accept named or hex (provided the - * hex ones start with the # character). - * - Some conversions go in only one direction, ie HSV->RGB but no RGB->HSV. - * I'm going to try to straighten out some of this but I'll be hard to do so - * without breaking backwards compatibility. - * - * @category Image - * @package Image_Color - * @author Jason Lotito - * @author Andrew Morton - * @copyright 2003-2005 The PHP Group - * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 0.1.2 - * @link http://pear.php.net/package/Image_Color - */ -class Image_Color -{ - /** - * First color that the class handles for ranges and mixes. - * @var array - * @access public - * @see setColors() - */ - var $color1 = array(); - - /** - * Second color that the class handles for ranges and mixes. - * @var array - * @access public - * @see setColors() - */ - var $color2 = array(); - - /** - * Boolean value for determining whether colors outputted should be limited - * to the web safe pallet or not. - * - * @var boolean - * @access private - * @see setWebSafe() - */ - var $_websafeb = false; - - /** - * Mix two colors together by finding their average. If the colors are not - * passed as parameters, the class's colors will be mixed instead. - * - * @param string $col1 The first color you want to mix - * @param string $col2 The second color you want to mix - * @return string The mixed color. - * @access public - * @author Jason Lotito - * @uses _setColors() to assign the colors if any are passed to the - * class. - */ - function mixColors($col1 = false, $col2 = false) - { - if ($col1) { - $this->_setColors($col1, $col2); - } - - // after finding the average, it will be a float. add 0.5 and then - // cast to an integer to properly round it to an integer. - $color3[0] = (int) ((($this->color1[0] + $this->color2[0]) / 2) + 0.5); - $color3[1] = (int) ((($this->color1[1] + $this->color2[1]) / 2) + 0.5); - $color3[2] = (int) ((($this->color1[2] + $this->color2[2]) / 2) + 0.5); - - if ($this->_websafeb) { - array_walk($color3, '_makeWebSafe'); - } - - return Image_Color::rgb2hex($color3); - } - - /** - * Determines whether colors the returned by this class will be rounded to - * the nearest web safe value. - * - * @param boolean $bool Indicates if colors should be limited to the - * websafe pallet. - * @return void - * @access public - * @author Jason Lotito - */ - function setWebSafe($bool = true) - { - $this->_websafeb = (boolean) $bool; - } - - /** - * Set the two colors this class uses for mixing and ranges. - * - * @param string $col1 The first color in hex format - * @param string $col2 The second color in hex format - * @return void - * @access public - * @author Jason Lotito - */ - function setColors($col1, $col2) - { - $this->_setColors($col1, $col2); - } - - /** - * Get the range of colors between the class's two colors, given a degree. - * - * @param integer $degrees How large a 'step' we should take between the - * colors. - * @return array Returns an array of hex strings, one element for each - * color. - * @access public - * @author Jason Lotito - * @todo Allow for degrees for individual parts of the colors. - */ - function getRange($degrees = 2) - { - if ($degrees == 0) { - $degrees = 1; - } - - // The degrees give us how much we should advance each color at each - // phase of the loop. This way, the advance is equal throughout all - // the colors. - - $red_steps = ($this->color2[0] - $this->color1[0]) / $degrees; - $green_steps = ($this->color2[1] - $this->color1[1]) / $degrees; - $blue_steps = ($this->color2[2] - $this->color1[2]) / $degrees; - - $allcolors = array(); - - /** - * The loop stops once any color has gone beyond the end color. - */ - - // Loop through all the degrees between the colors - for ($x = 0; $x < $degrees; $x++) { - $col[0] = $red_steps * $x; - $col[1] = $green_steps * $x; - $col[2] = $blue_steps * $x; - - // Loop through each R, G, and B - for ($i = 0; $i < 3; $i++) { - $partcolor = $this->color1[$i] + $col[$i]; - // If the color is less than 256 - if ($partcolor < 256) { - // Makes sure the colors is not less than 0 - if ($partcolor > -1) { - $newcolor[$i] = $partcolor; - } else { - $newcolor[$i] = 0; - } - // Color was greater than 255 - } else { - $newcolor[$i] = 255; - } - } - - if ($this->_websafeb) { - array_walk($newcolor, '_makeWebSafe'); - } - - $allcolors[] = Image_Color::rgb2hex($newcolor); - } - - return $allcolors; - } - - /** - * Change the lightness of the class's two colors. - * - * @param integer $degree The degree of the change. Positive values - * lighten the color while negative values will darken it. - * @return void - * @access public - * @author Jason Lotito - * @uses Image_Color::$color1 as an input and return value. - * @uses Image_Color::$color2 as an input and return value. - */ - function changeLightness($degree = 10) - { - $color1 =& $this->color1; - $color2 =& $this->color2; - + + * @author Andrew Morton + * @copyright 2003-2005 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Color.php,v 1.17 2008/10/26 18:27:10 clockwerx Exp $ + * @link http://pear.php.net/package/Image_Color + */ + +/** + * Image_Color handles color conversion and mixing. + * + * The class is quick, simple to use, and does its job fairly well but it's got + * some code smells: + * - Call setColors() for some functions but not others. + * - Different functions expect different color formats. setColors() only + * accepts hex while allocateColor() will accept named or hex (provided the + * hex ones start with the # character). + * - Some conversions go in only one direction, ie HSV->RGB but no RGB->HSV. + * I'm going to try to straighten out some of this but I'll be hard to do so + * without breaking backwards compatibility. + * + * @category Image + * @package Image_Color + * @author Jason Lotito + * @author Andrew Morton + * @copyright 2003-2005 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 0.1.2 + * @link http://pear.php.net/package/Image_Color + */ +class Image_Color +{ + /** + * First color that the class handles for ranges and mixes. + * @var array + * @access public + * @see setColors() + */ + var $color1 = array(); + + /** + * Second color that the class handles for ranges and mixes. + * @var array + * @access public + * @see setColors() + */ + var $color2 = array(); + + /** + * Boolean value for determining whether colors outputted should be limited + * to the web safe pallet or not. + * + * @var boolean + * @access private + * @see setWebSafe() + */ + var $_websafeb = false; + + /** + * Mix two colors together by finding their average. If the colors are not + * passed as parameters, the class's colors will be mixed instead. + * + * @param string $col1 The first color you want to mix + * @param string $col2 The second color you want to mix + * @return string The mixed color. + * @access public + * @author Jason Lotito + * @uses _setColors() to assign the colors if any are passed to the + * class. + */ + function mixColors($col1 = false, $col2 = false) + { + if ($col1) { + $this->_setColors($col1, $col2); + } + + // after finding the average, it will be a float. add 0.5 and then + // cast to an integer to properly round it to an integer. + $color3[0] = (int) ((($this->color1[0] + $this->color2[0]) / 2) + 0.5); + $color3[1] = (int) ((($this->color1[1] + $this->color2[1]) / 2) + 0.5); + $color3[2] = (int) ((($this->color1[2] + $this->color2[2]) / 2) + 0.5); + + if ($this->_websafeb) { + array_walk($color3, '_makeWebSafe'); + } + + return Image_Color::rgb2hex($color3); + } + + /** + * Determines whether colors the returned by this class will be rounded to + * the nearest web safe value. + * + * @param boolean $bool Indicates if colors should be limited to the + * websafe pallet. + * @return void + * @access public + * @author Jason Lotito + */ + function setWebSafe($bool = true) + { + $this->_websafeb = (boolean) $bool; + } + + /** + * Set the two colors this class uses for mixing and ranges. + * + * @param string $col1 The first color in hex format + * @param string $col2 The second color in hex format + * @return void + * @access public + * @author Jason Lotito + */ + function setColors($col1, $col2) + { + $this->_setColors($col1, $col2); + } + + /** + * Get the range of colors between the class's two colors, given a degree. + * + * @param integer $degrees How large a 'step' we should take between the + * colors. + * @return array Returns an array of hex strings, one element for each + * color. + * @access public + * @author Jason Lotito + * @todo Allow for degrees for individual parts of the colors. + */ + function getRange($degrees = 2) + { + if ($degrees == 0) { + $degrees = 1; + } + + // The degrees give us how much we should advance each color at each + // phase of the loop. This way, the advance is equal throughout all + // the colors. + + $red_steps = ($this->color2[0] - $this->color1[0]) / $degrees; + $green_steps = ($this->color2[1] - $this->color1[1]) / $degrees; + $blue_steps = ($this->color2[2] - $this->color1[2]) / $degrees; + + $allcolors = array(); + + /** + * The loop stops once any color has gone beyond the end color. + */ + + // Loop through all the degrees between the colors + for ($x = 0; $x < $degrees; $x++) { + $col[0] = $red_steps * $x; + $col[1] = $green_steps * $x; + $col[2] = $blue_steps * $x; + + // Loop through each R, G, and B + for ($i = 0; $i < 3; $i++) { + $partcolor = $this->color1[$i] + $col[$i]; + // If the color is less than 256 + if ($partcolor < 256) { + // Makes sure the colors is not less than 0 + if ($partcolor > -1) { + $newcolor[$i] = $partcolor; + } else { + $newcolor[$i] = 0; + } + // Color was greater than 255 + } else { + $newcolor[$i] = 255; + } + } + + if ($this->_websafeb) { + array_walk($newcolor, '_makeWebSafe'); + } + + $allcolors[] = Image_Color::rgb2hex($newcolor); + } + + return $allcolors; + } + + /** + * Change the lightness of the class's two colors. + * + * @param integer $degree The degree of the change. Positive values + * lighten the color while negative values will darken it. + * @return void + * @access public + * @author Jason Lotito + * @uses Image_Color::$color1 as an input and return value. + * @uses Image_Color::$color2 as an input and return value. + */ + function changeLightness($degree = 10) + { + $color1 =& $this->color1; + $color2 =& $this->color2; + for ($x = 0; $x < 3; $x++) { - if (($color1[$x] + $degree) < 256) { - if (($color1[$x] + $degree) > -1) { - $color1[$x] += $degree; - } else { - $color1[$x] = 0; + if (isset($color1[$x])) { + if (($color1[$x] + $degree) < 256) { + if (($color1[$x] + $degree) > -1) { + $color1[$x] += $degree; + } else { + $color1[$x] = 0; + } + } else { + $color1[$x] = 255; } - } else { - $color1[$x] = 255; - } + } - if (($color2[$x] + $degree) < 256) { - if (($color2[$x] + $degree) > -1) { - $color2[$x] += $degree; - } else { - $color2[$x] = 0; + if (isset($color2[$x])) { + if (($color2[$x] + $degree) < 256) { + if (($color2[$x] + $degree) > -1) { + $color2[$x] += $degree; + } else { + $color2[$x] = 0; + } + } else { + $color2[$x] = 255; } - } else { - $color2[$x] = 255; - } - } - } - - /** - * Determine if a light or dark text color would be more readable on a - * background of a given color. This is determined by the G(reen) value of - * RGB. You can change the dark and the light colors from their default - * black and white. - * - * @param string $color The hex color to analyze - * @param string $light The light color value to return if we should - * have light text. - * @param string $dark The dark color value to return if we should have - * dark text. - * @return string The light or dark value which would make the text most - * readable. - * @access public - * @static - * @author Jason Lotito - */ - function getTextColor($color, $light = '#FFFFFF', $dark = '#000000') - { - $color = Image_Color::_splitColor($color); - if ($color[1] > hexdec('66')) { - return $dark; - } else { - return $light; - } - } - - - /** - * Internal method to set the colors. - * - * @param string $col1 First color, either a name or hex value - * @param string $col2 Second color, either a name or hex value - * @return void - * @access private - * @author Jason Lotito - */ - function _setColors($col1, $col2) - { - if ($col1) { - $this->color1 = Image_Color::_splitColor($col1); - } - if ($col2) { - $this->color2 = Image_Color::_splitColor($col2); - } - } - - /** - * Given a color, properly split it up into a 3 element RGB array. - * - * @param string $color The color. - * @return array A three element RGB array. - * @access private - * @static - * @author Jason Lotito - */ - function _splitColor($color) - { - $color = str_replace('#', '', $color); - $c[] = hexdec(substr($color, 0, 2)); - $c[] = hexdec(substr($color, 2, 2)); - $c[] = hexdec(substr($color, 4, 2)); - return $c; - } - - /** - * This is deprecated. Use rgb2hex() instead. - * @access private - * @deprecated Function deprecated after 1.0.1 - * @see rgb2hex(). - */ - function _returnColor ( $color ) - { - return Image_Color::rgb2hex($color); - } - - /** - * Convert an RGB array to a hex string. - * - * @param array $color 3 element RGB array. - * @return string Hex color string. - * @access public - * @static - * @author Jason Lotito - * @see hex2rgb() - */ - function rgb2hex($color) - { - return sprintf('%02X%02X%02X',$color[0],$color[1],$color[2]); - } - - /** - * Convert a hex color string into an RGB array. An extra fourth element - * will be returned with the original hex value. - * - * @param string $hex Hex color string. - * @return array RGB color array with an extra 'hex' element containing - * the original hex string. - * @access public - * @static - * @author Jason Lotito - * @see rgb2hex() - */ - function hex2rgb($hex) - { - $return = Image_Color::_splitColor($hex); - $return['hex'] = $hex; - return $return; - } - - /** - * Convert an HSV (Hue, Saturation, Brightness) value to RGB. - * - * @param integer $h Hue - * @param integer $s Saturation - * @param integer $v Brightness - * @return array RGB array. - * @access public - * @static - * @author Jason Lotito - * @uses hsv2hex() to convert the HSV value to Hex. - * @uses hex2rgb() to convert the Hex value to RGB. - */ - function hsv2rgb($h, $s, $v) - { - return Image_Color::hex2rgb(Image_Color::hsv2hex($h, $s, $v)); - } - - /** - * Convert HSV (Hue, Saturation, Brightness) to a hex color string. - * - * Originally written by Jurgen Schwietering. Integrated into the class by - * Jason Lotito. - * - * @param integer $h Hue - * @param integer $s Saturation - * @param integer $v Brightness - * @return string The hex string. - * @access public - * @static - * @author Jurgen Schwietering - * @uses rgb2hex() to convert the return value to a hex string. - */ - function hsv2hex($h, $s, $v) - { - $s /= 256.0; - $v /= 256.0; - if ($s == 0.0) { - $r = $g = $b = $v; - return ''; - } else { - $h = $h / 256.0 * 6.0; - $i = floor($h); - $f = $h - $i; - - $v *= 256.0; - $p = (integer)($v * (1.0 - $s)); - $q = (integer)($v * (1.0 - $s * $f)); - $t = (integer)($v * (1.0 - $s * (1.0 - $f))); - switch($i) { - case 0: - $r = $v; - $g = $t; - $b = $p; - break; - - case 1: - $r = $q; - $g = $v; - $b = $p; - break; - - case 2: - $r = $p; - $g = $v; - $b = $t; - break; - - case 3: - $r = $p; - $g = $q; - $b = $v; - break; - - case 4: - $r = $t; - $g = $p; - $b = $v; - break; - - default: - $r = $v; - $g = $p; - $b = $q; - break; - } - } - return $this->rgb2hex(array($r, $g, $b)); - } - - /** - * Allocates a color in the given image. - * - * User defined color specifications get translated into an array of RGB - * values. - * - * @param resource $img Image handle - * @param string|array $color Name or hex string or an RGB array. - * @return resource Image color handle. - * @access public - * @static - * @uses ImageColorAllocate() to allocate the color. - * @uses color2RGB() to parse the color into RGB values. - */ - function allocateColor(&$img, $color) { - $color = Image_Color::color2RGB($color); - - return ImageColorAllocate($img, $color[0], $color[1], $color[2]); - } - - /** - * Convert a named or hex color string to an RGB array. If the color begins - * with the # character it will be treated as a hex value. Everything else - * will be treated as a named color. If the named color is not known, black - * will be returned. - * - * @param string $color - * @return array RGB color - * @access public - * @static - * @author Laurent Laville - * @uses hex2rgb() to convert colors begining with the # character. - * @uses namedColor2RGB() to convert everything not starting with a #. - */ - function color2RGB($color) - { - $c = array(); - - if ($color{0} == '#') { - $c = Image_Color::hex2rgb($color); - } else { - $c = Image_Color::namedColor2RGB($color); - } - - return $c; - } - - /** - * Convert a named color to an RGB array. If the color is unknown black - * is returned. - * - * @param string $color Case insensitive color name. - * @return array RGB color array. If the color was unknown, the result - * will be black. - * @access public - * @static - * @author Sebastian Bergmann - */ - function namedColor2RGB($color) - { - static $colornames; - - if (!isset($colornames)) { - $colornames = array( - 'aliceblue' => array(240, 248, 255), - 'antiquewhite' => array(250, 235, 215), - 'aqua' => array( 0, 255, 255), - 'aquamarine' => array(127, 255, 212), - 'azure' => array(240, 255, 255), - 'beige' => array(245, 245, 220), - 'bisque' => array(255, 228, 196), - 'black' => array( 0, 0, 0), - 'blanchedalmond' => array(255, 235, 205), - 'blue' => array( 0, 0, 255), - 'blueviolet' => array(138, 43, 226), - 'brown' => array(165, 42, 42), - 'burlywood' => array(222, 184, 135), - 'cadetblue' => array( 95, 158, 160), - 'chartreuse' => array(127, 255, 0), - 'chocolate' => array(210, 105, 30), - 'coral' => array(255, 127, 80), - 'cornflowerblue' => array(100, 149, 237), - 'cornsilk' => array(255, 248, 220), - 'crimson' => array(220, 20, 60), - 'cyan' => array( 0, 255, 255), - 'darkblue' => array( 0, 0, 13), - 'darkcyan' => array( 0, 139, 139), - 'darkgoldenrod' => array(184, 134, 11), - 'darkgray' => array(169, 169, 169), - 'darkgreen' => array( 0, 100, 0), - 'darkkhaki' => array(189, 183, 107), - 'darkmagenta' => array(139, 0, 139), - 'darkolivegreen' => array( 85, 107, 47), - 'darkorange' => array(255, 140, 0), - 'darkorchid' => array(153, 50, 204), - 'darkred' => array(139, 0, 0), - 'darksalmon' => array(233, 150, 122), - 'darkseagreen' => array(143, 188, 143), - 'darkslateblue' => array( 72, 61, 139), - 'darkslategray' => array( 47, 79, 79), - 'darkturquoise' => array( 0, 206, 209), - 'darkviolet' => array(148, 0, 211), - 'deeppink' => array(255, 20, 147), - 'deepskyblue' => array( 0, 191, 255), - 'dimgray' => array(105, 105, 105), - 'dodgerblue' => array( 30, 144, 255), - 'firebrick' => array(178, 34, 34), - 'floralwhite' => array(255, 250, 240), - 'forestgreen' => array( 34, 139, 34), - 'fuchsia' => array(255, 0, 255), - 'gainsboro' => array(220, 220, 220), - 'ghostwhite' => array(248, 248, 255), - 'gold' => array(255, 215, 0), - 'goldenrod' => array(218, 165, 32), - 'gray' => array(128, 128, 128), - 'green' => array( 0, 128, 0), - 'greenyellow' => array(173, 255, 47), - 'honeydew' => array(240, 255, 240), - 'hotpink' => array(255, 105, 180), - 'indianred' => array(205, 92, 92), - 'indigo' => array(75, 0, 130), - 'ivory' => array(255, 255, 240), - 'khaki' => array(240, 230, 140), - 'lavender' => array(230, 230, 250), - 'lavenderblush' => array(255, 240, 245), - 'lawngreen' => array(124, 252, 0), - 'lemonchiffon' => array(255, 250, 205), - 'lightblue' => array(173, 216, 230), - 'lightcoral' => array(240, 128, 128), - 'lightcyan' => array(224, 255, 255), - 'lightgoldenrodyellow' => array(250, 250, 210), - 'lightgreen' => array(144, 238, 144), - 'lightgrey' => array(211, 211, 211), - 'lightpink' => array(255, 182, 193), - 'lightsalmon' => array(255, 160, 122), - 'lightseagreen' => array( 32, 178, 170), - 'lightskyblue' => array(135, 206, 250), - 'lightslategray' => array(119, 136, 153), - 'lightsteelblue' => array(176, 196, 222), - 'lightyellow' => array(255, 255, 224), - 'lime' => array( 0, 255, 0), - 'limegreen' => array( 50, 205, 50), - 'linen' => array(250, 240, 230), - 'magenta' => array(255, 0, 255), - 'maroon' => array(128, 0, 0), - 'mediumaquamarine' => array(102, 205, 170), - 'mediumblue' => array( 0, 0, 205), - 'mediumorchid' => array(186, 85, 211), - 'mediumpurple' => array(147, 112, 219), - 'mediumseagreen' => array( 60, 179, 113), - 'mediumslateblue' => array(123, 104, 238), - 'mediumspringgreen' => array( 0, 250, 154), - 'mediumturquoise' => array(72, 209, 204), - 'mediumvioletred' => array(199, 21, 133), - 'midnightblue' => array( 25, 25, 112), - 'mintcream' => array(245, 255, 250), - 'mistyrose' => array(255, 228, 225), - 'moccasin' => array(255, 228, 181), - 'navajowhite' => array(255, 222, 173), - 'navy' => array( 0, 0, 128), - 'oldlace' => array(253, 245, 230), - 'olive' => array(128, 128, 0), - 'olivedrab' => array(107, 142, 35), - 'orange' => array(255, 165, 0), - 'orangered' => array(255, 69, 0), - 'orchid' => array(218, 112, 214), - 'palegoldenrod' => array(238, 232, 170), - 'palegreen' => array(152, 251, 152), - 'paleturquoise' => array(175, 238, 238), - 'palevioletred' => array(219, 112, 147), - 'papayawhip' => array(255, 239, 213), - 'peachpuff' => array(255, 218, 185), - 'peru' => array(205, 133, 63), - 'pink' => array(255, 192, 203), - 'plum' => array(221, 160, 221), - 'powderblue' => array(176, 224, 230), - 'purple' => array(128, 0, 128), - 'red' => array(255, 0, 0), - 'rosybrown' => array(188, 143, 143), - 'royalblue' => array( 65, 105, 225), - 'saddlebrown' => array(139, 69, 19), - 'salmon' => array(250, 128, 114), - 'sandybrown' => array(244, 164, 96), - 'seagreen' => array( 46, 139, 87), - 'seashell' => array(255, 245, 238), - 'sienna' => array(160, 82, 45), - 'silver' => array(192, 192, 192), - 'skyblue' => array(135, 206, 235), - 'slateblue' => array(106, 90, 205), - 'slategray' => array(112, 128, 144), - 'snow' => array(255, 250, 250), - 'springgreen' => array( 0, 255, 127), - 'steelblue' => array( 70, 130, 180), - 'tan' => array(210, 180, 140), - 'teal' => array( 0, 128, 128), - 'thistle' => array(216, 191, 216), - 'tomato' => array(255, 99, 71), - 'turquoise' => array( 64, 224, 208), - 'violet' => array(238, 130, 238), - 'wheat' => array(245, 222, 179), - 'white' => array(255, 255, 255), - 'whitesmoke' => array(245, 245, 245), - 'yellow' => array(255, 255, 0), - 'yellowgreen' => array(154, 205, 50) - ); - } - - $color = strtolower($color); - - if (isset($colornames[$color])) { - return $colornames[$color]; - } else { - return array(0, 0, 0); - } - } - - /** - * Convert an RGB percentage string into an RGB array. - * - * @param string $color Percentage color string like "50%,20%,100%". - * @return array RGB color array. - * @access public - * @static - */ - function percentageColor2RGB($color) - { - // remove spaces - $color = str_replace(' ', '', $color); - // remove the percent signs - $color = str_replace('%', '', $color); - // split the string by commas - $color = explode(',', $color); - - $ret = array(); - foreach ($color as $k => $v) { - // range checks - if ($v <= 0) { - $ret[$k] = 0; - } else if ($v <= 100) { - // add 0.5 then cast to an integer to round the value. - $ret[$k] = (integer) ((2.55 * $v) + 0.5); - } else { - $ret[$k] = 255; - } - } - - return $ret; - } -} - -// For Array Walk -// {{{ -/** - * Function for array_walk() to round colors to the closest web safe value. - * - * @param integer $color One channel of an RGB color. - * @return integer The websafe equivalent of the color channel. - * @author Jason Lotito - * @author Andrew Morton - * @access private - * @static - */ -function _makeWebSafe(&$color) -{ - if ($color < 0x1a) { - $color = 0x00; - } else if ($color < 0x4d) { - $color = 0x33; - } else if ($color < 0x80) { - $color = 0x66; - } else if ($color < 0xB3) { - $color = 0x99; - } else if ($color < 0xE6) { - $color = 0xCC; - } else { - $color = 0xFF; - } - return $color; -} -// }}} - -?> + } + } + } + + /** + * Determine if a light or dark text color would be more readable on a + * background of a given color. This is determined by the G(reen) value of + * RGB. You can change the dark and the light colors from their default + * black and white. + * + * @param string $color The hex color to analyze + * @param string $light The light color value to return if we should + * have light text. + * @param string $dark The dark color value to return if we should have + * dark text. + * @return string The light or dark value which would make the text most + * readable. + * @access public + * @static + * @author Jason Lotito + */ + function getTextColor($color, $light = '#FFFFFF', $dark = '#000000') + { + $color = Image_Color::_splitColor($color); + if ($color[1] > hexdec('66')) { + return $dark; + } else { + return $light; + } + } + + + /** + * Internal method to set the colors. + * + * @param string $col1 First color, either a name or hex value + * @param string $col2 Second color, either a name or hex value + * @return void + * @access private + * @author Jason Lotito + */ + function _setColors($col1, $col2) + { + if ($col1) { + $this->color1 = Image_Color::_splitColor($col1); + } + if ($col2) { + $this->color2 = Image_Color::_splitColor($col2); + } + } + + /** + * Given a color, properly split it up into a 3 element RGB array. + * + * @param string $color The color. + * @return array A three element RGB array. + * @access private + * @static + * @author Jason Lotito + */ + function _splitColor($color) + { + $color = str_replace('#', '', $color); + $c[] = hexdec(substr($color, 0, 2)); + $c[] = hexdec(substr($color, 2, 2)); + $c[] = hexdec(substr($color, 4, 2)); + return $c; + } + + /** + * This is deprecated. Use rgb2hex() instead. + * @access private + * @deprecated Function deprecated after 1.0.1 + * @see rgb2hex(). + */ + function _returnColor ( $color ) + { + return Image_Color::rgb2hex($color); + } + + /** + * Convert an RGB array to a hex string. + * + * @param array $color 3 element RGB array. + * @return string Hex color string. + * @access public + * @static + * @author Jason Lotito + * @see hex2rgb() + */ + function rgb2hex($color) + { + return sprintf('%02X%02X%02X',$color[0],$color[1],$color[2]); + } + + /** + * Convert a hex color string into an RGB array. An extra fourth element + * will be returned with the original hex value. + * + * @param string $hex Hex color string. + * @return array RGB color array with an extra 'hex' element containing + * the original hex string. + * @access public + * @static + * @author Jason Lotito + * @see rgb2hex() + */ + function hex2rgb($hex) + { + $return = Image_Color::_splitColor($hex); + $return['hex'] = $hex; + return $return; + } + + /** + * Convert an HSV (Hue, Saturation, Brightness) value to RGB. + * + * @param integer $h Hue + * @param integer $s Saturation + * @param integer $v Brightness + * @return array RGB array. + * @access public + * @static + * @author Jason Lotito + * @uses hsv2hex() to convert the HSV value to Hex. + * @uses hex2rgb() to convert the Hex value to RGB. + */ + function hsv2rgb($h, $s, $v) + { + return Image_Color::hex2rgb(Image_Color::hsv2hex($h, $s, $v)); + } + + /** + * Convert HSV (Hue, Saturation, Brightness) to a hex color string. + * + * Originally written by Jurgen Schwietering. Integrated into the class by + * Jason Lotito. + * + * @param integer $h Hue + * @param integer $s Saturation + * @param integer $v Brightness + * @return string The hex string. + * @access public + * @static + * @author Jurgen Schwietering + * @uses rgb2hex() to convert the return value to a hex string. + */ + function hsv2hex($h, $s, $v) + { + $s /= 256.0; + $v /= 256.0; + if ($s == 0.0) { + $r = $g = $b = $v; + return ''; + } else { + $h = $h / 256.0 * 6.0; + $i = floor($h); + $f = $h - $i; + + $v *= 256.0; + $p = (integer)($v * (1.0 - $s)); + $q = (integer)($v * (1.0 - $s * $f)); + $t = (integer)($v * (1.0 - $s * (1.0 - $f))); + switch($i) { + case 0: + $r = $v; + $g = $t; + $b = $p; + break; + + case 1: + $r = $q; + $g = $v; + $b = $p; + break; + + case 2: + $r = $p; + $g = $v; + $b = $t; + break; + + case 3: + $r = $p; + $g = $q; + $b = $v; + break; + + case 4: + $r = $t; + $g = $p; + $b = $v; + break; + + default: + $r = $v; + $g = $p; + $b = $q; + break; + } + } + return Image_Color::rgb2hex(array($r, $g, $b)); + } + + /** + * Allocates a color in the given image. + * + * User defined color specifications get translated into an array of RGB + * values. + * + * @param resource $img Image handle + * @param string|array $color Name or hex string or an RGB array. + * @return resource Image color handle. + * @access public + * @static + * @uses ImageColorAllocate() to allocate the color. + * @uses color2RGB() to parse the color into RGB values. + */ + function allocateColor(&$img, $color) { + $color = Image_Color::color2RGB($color); + + return ImageColorAllocate($img, $color[0], $color[1], $color[2]); + } + + /** + * Convert a named or hex color string to an RGB array. If the color begins + * with the # character it will be treated as a hex value. Everything else + * will be treated as a named color. If the named color is not known, black + * will be returned. + * + * @param string $color + * @return array RGB color + * @access public + * @static + * @author Laurent Laville + * @uses hex2rgb() to convert colors begining with the # character. + * @uses namedColor2RGB() to convert everything not starting with a #. + */ + function color2RGB($color) + { + $c = array(); + + if ($color{0} == '#') { + $c = Image_Color::hex2rgb($color); + } else { + $c = Image_Color::namedColor2RGB($color); + } + + return $c; + } + + /** + * Convert a named color to an RGB array. If the color is unknown black + * is returned. + * + * @param string $color Case insensitive color name. + * @return array RGB color array. If the color was unknown, the result + * will be black. + * @access public + * @static + * @author Sebastian Bergmann + */ + function namedColor2RGB($color) + { + static $colornames; + + if (!isset($colornames)) { + $colornames = array( + 'aliceblue' => array(240, 248, 255), + 'antiquewhite' => array(250, 235, 215), + 'aqua' => array( 0, 255, 255), + 'aquamarine' => array(127, 255, 212), + 'azure' => array(240, 255, 255), + 'beige' => array(245, 245, 220), + 'bisque' => array(255, 228, 196), + 'black' => array( 0, 0, 0), + 'blanchedalmond' => array(255, 235, 205), + 'blue' => array( 0, 0, 255), + 'blueviolet' => array(138, 43, 226), + 'brown' => array(165, 42, 42), + 'burlywood' => array(222, 184, 135), + 'cadetblue' => array( 95, 158, 160), + 'chartreuse' => array(127, 255, 0), + 'chocolate' => array(210, 105, 30), + 'coral' => array(255, 127, 80), + 'cornflowerblue' => array(100, 149, 237), + 'cornsilk' => array(255, 248, 220), + 'crimson' => array(220, 20, 60), + 'cyan' => array( 0, 255, 255), + 'darkblue' => array( 0, 0, 13), + 'darkcyan' => array( 0, 139, 139), + 'darkgoldenrod' => array(184, 134, 11), + 'darkgray' => array(169, 169, 169), + 'darkgreen' => array( 0, 100, 0), + 'darkkhaki' => array(189, 183, 107), + 'darkmagenta' => array(139, 0, 139), + 'darkolivegreen' => array( 85, 107, 47), + 'darkorange' => array(255, 140, 0), + 'darkorchid' => array(153, 50, 204), + 'darkred' => array(139, 0, 0), + 'darksalmon' => array(233, 150, 122), + 'darkseagreen' => array(143, 188, 143), + 'darkslateblue' => array( 72, 61, 139), + 'darkslategray' => array( 47, 79, 79), + 'darkturquoise' => array( 0, 206, 209), + 'darkviolet' => array(148, 0, 211), + 'deeppink' => array(255, 20, 147), + 'deepskyblue' => array( 0, 191, 255), + 'dimgray' => array(105, 105, 105), + 'dodgerblue' => array( 30, 144, 255), + 'firebrick' => array(178, 34, 34), + 'floralwhite' => array(255, 250, 240), + 'forestgreen' => array( 34, 139, 34), + 'fuchsia' => array(255, 0, 255), + 'gainsboro' => array(220, 220, 220), + 'ghostwhite' => array(248, 248, 255), + 'gold' => array(255, 215, 0), + 'goldenrod' => array(218, 165, 32), + 'gray' => array(128, 128, 128), + 'green' => array( 0, 128, 0), + 'greenyellow' => array(173, 255, 47), + 'honeydew' => array(240, 255, 240), + 'hotpink' => array(255, 105, 180), + 'indianred' => array(205, 92, 92), + 'indigo' => array(75, 0, 130), + 'ivory' => array(255, 255, 240), + 'khaki' => array(240, 230, 140), + 'lavender' => array(230, 230, 250), + 'lavenderblush' => array(255, 240, 245), + 'lawngreen' => array(124, 252, 0), + 'lemonchiffon' => array(255, 250, 205), + 'lightblue' => array(173, 216, 230), + 'lightcoral' => array(240, 128, 128), + 'lightcyan' => array(224, 255, 255), + 'lightgoldenrodyellow' => array(250, 250, 210), + 'lightgreen' => array(144, 238, 144), + 'lightgrey' => array(211, 211, 211), + 'lightpink' => array(255, 182, 193), + 'lightsalmon' => array(255, 160, 122), + 'lightseagreen' => array( 32, 178, 170), + 'lightskyblue' => array(135, 206, 250), + 'lightslategray' => array(119, 136, 153), + 'lightsteelblue' => array(176, 196, 222), + 'lightyellow' => array(255, 255, 224), + 'lime' => array( 0, 255, 0), + 'limegreen' => array( 50, 205, 50), + 'linen' => array(250, 240, 230), + 'magenta' => array(255, 0, 255), + 'maroon' => array(128, 0, 0), + 'mediumaquamarine' => array(102, 205, 170), + 'mediumblue' => array( 0, 0, 205), + 'mediumorchid' => array(186, 85, 211), + 'mediumpurple' => array(147, 112, 219), + 'mediumseagreen' => array( 60, 179, 113), + 'mediumslateblue' => array(123, 104, 238), + 'mediumspringgreen' => array( 0, 250, 154), + 'mediumturquoise' => array(72, 209, 204), + 'mediumvioletred' => array(199, 21, 133), + 'midnightblue' => array( 25, 25, 112), + 'mintcream' => array(245, 255, 250), + 'mistyrose' => array(255, 228, 225), + 'moccasin' => array(255, 228, 181), + 'navajowhite' => array(255, 222, 173), + 'navy' => array( 0, 0, 128), + 'oldlace' => array(253, 245, 230), + 'olive' => array(128, 128, 0), + 'olivedrab' => array(107, 142, 35), + 'orange' => array(255, 165, 0), + 'orangered' => array(255, 69, 0), + 'orchid' => array(218, 112, 214), + 'palegoldenrod' => array(238, 232, 170), + 'palegreen' => array(152, 251, 152), + 'paleturquoise' => array(175, 238, 238), + 'palevioletred' => array(219, 112, 147), + 'papayawhip' => array(255, 239, 213), + 'peachpuff' => array(255, 218, 185), + 'peru' => array(205, 133, 63), + 'pink' => array(255, 192, 203), + 'plum' => array(221, 160, 221), + 'powderblue' => array(176, 224, 230), + 'purple' => array(128, 0, 128), + 'red' => array(255, 0, 0), + 'rosybrown' => array(188, 143, 143), + 'royalblue' => array( 65, 105, 225), + 'saddlebrown' => array(139, 69, 19), + 'salmon' => array(250, 128, 114), + 'sandybrown' => array(244, 164, 96), + 'seagreen' => array( 46, 139, 87), + 'seashell' => array(255, 245, 238), + 'sienna' => array(160, 82, 45), + 'silver' => array(192, 192, 192), + 'skyblue' => array(135, 206, 235), + 'slateblue' => array(106, 90, 205), + 'slategray' => array(112, 128, 144), + 'snow' => array(255, 250, 250), + 'springgreen' => array( 0, 255, 127), + 'steelblue' => array( 70, 130, 180), + 'tan' => array(210, 180, 140), + 'teal' => array( 0, 128, 128), + 'thistle' => array(216, 191, 216), + 'tomato' => array(255, 99, 71), + 'turquoise' => array( 64, 224, 208), + 'violet' => array(238, 130, 238), + 'wheat' => array(245, 222, 179), + 'white' => array(255, 255, 255), + 'whitesmoke' => array(245, 245, 245), + 'yellow' => array(255, 255, 0), + 'yellowgreen' => array(154, 205, 50) + ); + } + + $color = strtolower($color); + + if (isset($colornames[$color])) { + return $colornames[$color]; + } else { + return array(0, 0, 0); + } + } + + /** + * Convert an RGB percentage string into an RGB array. + * + * @param string $color Percentage color string like "50%,20%,100%". + * @return array RGB color array. + * @access public + * @static + */ + function percentageColor2RGB($color) + { + // remove spaces + $color = str_replace(' ', '', $color); + // remove the percent signs + $color = str_replace('%', '', $color); + // split the string by commas + $color = explode(',', $color); + + $ret = array(); + foreach ($color as $k => $v) { + // range checks + if ($v <= 0) { + $ret[$k] = 0; + } else if ($v <= 100) { + // add 0.5 then cast to an integer to round the value. + $ret[$k] = (integer) ((2.55 * $v) + 0.5); + } else { + $ret[$k] = 255; + } + } + + return $ret; + } +} + +// For Array Walk +// {{{ +/** + * Function for array_walk() to round colors to the closest web safe value. + * + * @param integer $color One channel of an RGB color. + * @return integer The websafe equivalent of the color channel. + * @author Jason Lotito + * @author Andrew Morton + * @access private + * @static + */ +function _makeWebSafe(&$color) +{ + if ($color < 0x1a) { + $color = 0x00; + } else if ($color < 0x4d) { + $color = 0x33; + } else if ($color < 0x80) { + $color = 0x66; + } else if ($color < 0xB3) { + $color = 0x99; + } else if ($color < 0xE6) { + $color = 0xCC; + } else { + $color = 0xFF; + } + return $color; +} +// }}} + +?> diff --git a/includes/pear/Image/Graph.php b/includes/pear/Image/Graph.php index d352382a..7fbdd695 100644 --- a/includes/pear/Image/Graph.php +++ b/includes/pear/Image/Graph.php @@ -1,853 +1,851 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Graph.php,v 1.57 2005/10/05 20:51:22 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - - -/** - * Include PEAR.php - */ -require_once 'PEAR.php'; - -/** - * Include file Image/Graph/Element.php - */ -require_once 'Image/Graph/Element.php'; - -/** - * Include file Image/Graph/Constants.php - */ -require_once 'Image/Graph/Constants.php'; - -/** - * Main class for the graph creation. - * - * This is the main class, it manages the canvas and performs the final output - * by sequentialy making the elements output their results. The final output is - * handled using the {@link Image_Canvas} classes which makes it possible - * to use different engines (fx GD, PDFlib, libswf, etc) for output to several - * formats with a non-intersecting API. - * - * This class also handles coordinates and the correct managment of setting the - * correct coordinates on child elements. - * - * @category Images - * @package Image_Graph - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph extends Image_Graph_Element -{ - - /** - * Show generation time on graph - * @var bool - * @access private - */ - var $_showTime = false; - - /** - * Display errors on the canvas - * @var boolean - * @access private - */ - var $_displayErrors = false; - - /** - * Image_Graph [Constructor]. - * - * If passing the 3 parameters they are defined as follows:' - * - * Fx.: - * - * $Graph =& new Image_Graph(400, 300); - * - * or using the factory method: - * - * $Graph =& Image_Graph::factory('graph', array(400, 300)); - * - * This causes a 'png' canvas to be created by default. - * - * Otherwise use a single parameter either as an associated array or passing - * the canvas along to the constructor: - * - * 1) Create a new canvas with the following parameters: - * - * 'canvas' - The canvas type, can be any of 'gd', 'jpg', 'png' or 'svg' - * (more to come) - if omitted the default is 'gd' - * - * 'width' - The width of the graph - * - * 'height' - The height of the graph - * - * An example of this usage: - * - * $Graph =& Image_Graph::factory('graph', array(array('width' => 400, - * 'height' => 300, 'canvas' => 'jpg'))); - * - * NB! In thïs case remember the "double" array (see {@link Image_Graph:: - * factory()}) - * - * 2) Use the canvas specified, pass a valid Image_Canvas as - * parameter. Remember to pass by reference, i. e. &$canvas, fx.: - * - * $Graph =& new Image_Graph($Canvas); - * - * or using the factory method: - * - * $Graph =& Image_Graph::factory('graph', $Canvas)); - * - * @param mixed $params The width of the graph, an indexed array - * describing a new canvas or a valid {@link Image_Canvas} object - * @param int $height The height of the graph in pixels - * @param bool $createTransparent Specifies whether the graph should be - * created with a transparent background (fx for PNG's - note: transparent - * PNG's is not supported by Internet Explorer!) - */ - function Image_Graph($params, $height = false, $createTransparent = false) - { - parent::Image_Graph_Element(); - - $this->setFont(Image_Graph::factory('Image_Graph_Font')); - - if (defined('IMAGE_GRAPH_DEFAULT_CANVAS_TYPE')) { - $canvasType = IMAGE_GRAPH_DEFAULT_CANVAS_TYPE; - } else { - $canvasType = 'png'; // use GD as default, if nothing else is specified - } - - if (is_array($params)) { - if (isset($params['canvas'])) { - $canvasType = $params['canvas']; - } - - $width = 0; - $height = 0; - - if (isset($params['width'])) { - $width = $params['width']; - } - - if (isset($params['height'])) { - $height = $params['height']; - } - } elseif (is_a($params, 'Image_Canvas')) { - $this->_canvas =& $params; - $width = $this->_canvas->getWidth(); - $height = $this->_canvas->getHeight(); - } - - if (is_int($params)) { - $width = $params; - } - - if ($this->_canvas == null) { - include_once 'Image/Canvas.php'; - $this->_canvas =& - Image_Canvas::factory( - $canvasType, - array('width' => $width, 'height' => $height) - ); - } - - $this->_setCoords(0, 0, $width - 1, $height - 1); - } - - /** - * Gets the canvas for this graph. - * - * The canvas is set by either passing it to the constructor {@link - * Image_Graph::ImageGraph()} or using the {@link Image_Graph::setCanvas()} - * method. - * - * @return Image_Canvas The canvas used by this graph - * @access private - * @since 0.3.0dev2 - */ - function &_getCanvas() - { - return $this->_canvas; - } - - /** - * Sets the canvas for this graph. - * - * Calling this method makes this graph use the newly specified canvas for - * handling output. This method should be called whenever multiple - * 'outputs' are required. Invoke this method after calls to {@link - * Image_Graph:: done()} has been performed, to switch canvass. - * - * @param Image_Canvas $canvas The new canvas - * @return Image_Canvas The new canvas - * @since 0.3.0dev2 - */ - function &setCanvas(&$canvas) - { - if (!is_a($this->_canvas, 'Image_Canvas')) { - return $this->_error('The canvas introduced is not an Image_Canvas object'); - } - - $this->_canvas =& $canvas; - $this->_setCoords( - 0, - 0, - $this->_canvas->getWidth() - 1, - $this->_canvas->getHeight() - 1 - ); - return $this->_canvas; - } - - /** - * Gets a very precise timestamp - * - * @return The number of seconds to a lot of decimals - * @access private - */ - function _getMicroTime() - { - list($usec, $sec) = explode(' ', microtime()); - return ((float)$usec + (float)$sec); - } - - /** - * Gets the width of this graph. - * - * The width is returned as 'defined' by the canvas. - * - * @return int the width of this graph - */ - function width() - { - return $this->_canvas->getWidth(); - } - - /** - * Gets the height of this graph. - * - * The height is returned as 'defined' by the canvas. - * - * @return int the height of this graph - */ - function height() - { - return $this->_canvas->getHeight(); - } - - /** - * Enables displaying of errors on the output. - * - * Use this method to enforce errors to be displayed on the output. Calling - * this method makes PHP uses this graphs error handler as default {@link - * Image_Graph::_default_error_handler()}. - */ - function displayErrors() - { - $this->_displayErrors = true; - set_error_handler(array(&$this, '_default_error_handler')); - } - - /** - * Sets the log method for this graph. - * - * Use this method to enable logging. This causes any errors caught - * by either the error handler {@see Image_Graph::displayErrors()} - * or explicitly by calling {@link Image_Graph_Common::_error()} be - * logged using the specified logging method. - * - * If a filename is specified as log method, a Log object is created (using - * the 'file' handler), with a handle of 'Image_Graph Error Log'. - * - * Logging requires {@link Log}. - * - * @param mixed $log The log method, either a Log object or filename to log - * to - * @since 0.3.0dev2 - */ - function setLog($log) - { - } - - /** - * Factory method to create Image_Graph objects. - * - * Used for 'lazy including', i.e. loading only what is necessary, when it - * is necessary. If only one parameter is required for the constructor of - * the class simply pass this parameter as the $params parameter, unless the - * parameter is an array or a reference to a value, in that case you must - * 'enclose' the parameter in an array. Similar if the constructor takes - * more than one parameter specify the parameters in an array, i.e - * - * Image_Graph::factory('MyClass', array($param1, $param2, &$param3)); - * - * Variables that need to be passed by reference *must* have the & - * before the variable, i.e: - * - * Image_Graph::factory('line', &$Dataset); - * - * or - * - * Image_graph::factory('bar', array(array(&$Dataset1, &$Dataset2), - * 'stacked')); - * - * Class name can be either of the following: - * - * 1 The 'real' Image_Graph class name, i.e. Image_Graph_Plotarea or - * Image_Graph_Plot_Line - * - * 2 Short class name (leave out Image_Graph) and retain case, i.e. - * Plotarea, Plot_Line *not* plot_line - * - * 3 Class name 'alias', the following are supported: - * - * 'graph' = Image_Graph - * - * 'plotarea' = Image_Graph_Plotarea - * - * 'line' = Image_Graph_Plot_Line - * - * 'area' = Image_Graph_Plot_Area - * - * 'bar' = Image_Graph_Plot_Bar - * - * 'pie' = Image_Graph_Plot_Pie - * - * 'radar' = Image_Graph_Plot_Radar - * - * 'step' = Image_Graph_Plot_Step - * - * 'impulse' = Image_Graph_Plot_Impulse - * - * 'dot' or 'scatter' = Image_Graph_Plot_Dot - * - * 'smooth_line' = Image_Graph_Plot_Smoothed_Line - * - * 'smooth_area' = Image_Graph_Plot_Smoothed_Area - - * 'dataset' = Image_Graph_Dataset_Trivial - * - * 'random' = Image_Graph_Dataset_Random - * - * 'function' = Image_Graph_Dataset_Function - * - * 'vector' = Image_Graph_Dataset_VectorFunction - * - * 'category' = Image_Graph_Axis_Category - * - * 'axis' = Image_Graph_Axis - * - * 'axis_log' = Image_Graph_Axis_Logarithmic - * - * 'title' = Image_Graph_Title - * - * 'line_grid' = Image_Graph_Grid_Lines - * - * 'bar_grid' = Image_Graph_Grid_Bars - * - * 'polar_grid' = Image_Graph_Grid_Polar - * - * 'legend' = Image_Graph_Legend - * - * 'font' = Image_Graph_Font - * - * 'ttf_font' = Image_Graph_Font - * - * 'Image_Graph_Font_TTF' = Image_Graph_Font (to maintain BC with Image_Graph_Font_TTF) - * - * 'gradient' = Image_Graph_Fill_Gradient - * - * 'icon_marker' = Image_Graph_Marker_Icon - * - * 'value_marker' = Image_Graph_Marker_Value - * - * @param string $class The class for the new object - * @param mixed $params The paramaters to pass to the constructor - * @return object A new object for the class - * @static - */ - function &factory($class, $params = null) - { - static $Image_Graph_classAliases = array( - 'graph' => 'Image_Graph', - 'plotarea' => 'Image_Graph_Plotarea', - - 'line' => 'Image_Graph_Plot_Line', - 'area' => 'Image_Graph_Plot_Area', - 'bar' => 'Image_Graph_Plot_Bar', - 'smooth_line' => 'Image_Graph_Plot_Smoothed_Line', - 'smooth_area' => 'Image_Graph_Plot_Smoothed_Area', - 'pie' => 'Image_Graph_Plot_Pie', - 'radar' => 'Image_Graph_Plot_Radar', - 'step' => 'Image_Graph_Plot_Step', - 'impulse' => 'Image_Graph_Plot_Impulse', - 'dot' => 'Image_Graph_Plot_Dot', - 'scatter' => 'Image_Graph_Plot_Dot', - - 'dataset' => 'Image_Graph_Dataset_Trivial', - 'random' => 'Image_Graph_Dataset_Random', - 'function' => 'Image_Graph_Dataset_Function', - 'vector' => 'Image_Graph_Dataset_VectorFunction', - - 'category' => 'Image_Graph_Axis_Category', - 'axis' => 'Image_Graph_Axis', - 'axis_log' => 'Image_Graph_Axis_Logarithmic', - - 'title' => 'Image_Graph_Title', - - 'line_grid' => 'Image_Graph_Grid_Lines', - 'bar_grid' => 'Image_Graph_Grid_Bars', - 'polar_grid' => 'Image_Graph_Grid_Polar', - - 'legend' => 'Image_Graph_Legend', - 'font' => 'Image_Graph_Font', - 'ttf_font' => 'Image_Graph_Font', - 'Image_Graph_Font_TTF' => 'Image_Graph_Font', // BC with Image_Graph_Font_TTF - 'gradient' => 'Image_Graph_Fill_Gradient', - - 'icon_marker' => 'Image_Graph_Marker_Icon', - 'value_marker' => 'Image_Graph_Marker_Value' - ); - - if (substr($class, 0, 11) != 'Image_Graph') { - if (isset($Image_Graph_classAliases[$class])) { - $class = $Image_Graph_classAliases[$class]; - } else { - $class = 'Image_Graph_' . $class; - } - } - - include_once str_replace('_', '/', $class) . '.php'; - - $obj = null; - - if (is_array($params)) { - switch (count($params)) { - case 1: - $obj =& new $class( - $params[0] - ); - break; - - case 2: - $obj =& new $class( - $params[0], - $params[1] - ); - break; - - case 3: - $obj =& new $class( - $params[0], - $params[1], - $params[2] - ); - break; - - case 4: - $obj =& new $class( - $params[0], - $params[1], - $params[2], - $params[3] - ); - break; - - case 5: - $obj =& new $class( - $params[0], - $params[1], - $params[2], - $params[3], - $params[4] - ); - break; - - case 6: - $obj =& new $class( - $params[0], - $params[1], - $params[2], - $params[3], - $params[4], - $params[5] - ); - break; - - case 7: - $obj =& new $class( - $params[0], - $params[1], - $params[2], - $params[3], - $params[4], - $params[5], - $params[6] - ); - break; - - case 8: - $obj =& new $class( - $params[0], - $params[1], - $params[2], - $params[3], - $params[4], - $params[5], - $params[6], - $params[7] - ); - break; - - case 9: - $obj =& new $class( - $params[0], - $params[1], - $params[2], - $params[3], - $params[4], - $params[5], - $params[6], - $params[7], - $params[8] - ); - break; - - case 10: - $obj =& new $class( - $params[0], - $params[1], - $params[2], - $params[3], - $params[4], - $params[5], - $params[6], - $params[7], - $params[8], - $params[9] - ); - break; - - default: - $obj =& new $class(); - break; - - } - } else { - if ($params == null) { - $obj =& new $class(); - } else { - $obj =& new $class($params); - } - } - return $obj; - } - - /** - * Factory method to create layouts. - * - * This method is used for easy creation, since using {@link Image_Graph:: - * factory()} does not work with passing newly created objects from - * Image_Graph::factory() as reference, this is something that is - * fortunately fixed in PHP5. Also used for 'lazy including', i.e. loading - * only what is necessary, when it is necessary. - * - * Use {@link Image_Graph::horizontal()} or {@link Image_Graph::vertical()} - * instead for easier access. - * - * @param mixed $layout The type of layout, can be either 'Vertical' - * or 'Horizontal' (case sensitive) - * @param Image_Graph_Element $part1 The 1st part of the layout - * @param Image_Graph_Element $part2 The 2nd part of the layout - * @param int $percentage The percentage of the layout to split at - * @return Image_Graph_Layout The newly created layout object - * @static - */ - function &layoutFactory($layout, &$part1, &$part2, $percentage = 50) - { - if (($layout != 'Vertical') && ($layout != 'Horizontal')) { - return $this->_error('Layouts must be either \'Horizontal\' or \'Vertical\''); - } - - if (!(is_a($part1, 'Image_Graph_Element'))) { - return $this->_error('Part 1 is not a valid Image_Graph element'); - } - - if (!(is_a($part2, 'Image_Graph_Element'))) { - return $this->_error('Part 2 is not a valid Image_Graph element'); - } - - if ((!is_numeric($percentage)) || ($percentage < 0) || ($percentage > 100)) { - return $this->_error('Percentage has to be a number between 0 and 100'); - } - - include_once "Image/Graph/Layout/$layout.php"; - $class = "Image_Graph_Layout_$layout"; - $obj =& new $class($part1, $part2, $percentage); - return $obj; - } - - /** - * Factory method to create horizontal layout. - * - * See {@link Image_Graph::layoutFactory()} - * - * @param Image_Graph_Element $part1 The 1st (left) part of the layout - * @param Image_Graph_Element $part2 The 2nd (right) part of the layout - * @param int $percentage The percentage of the layout to split at - * (percentage of total height from the left side) - * @return Image_Graph_Layout The newly created layout object - * @static - */ - function &horizontal(&$part1, &$part2, $percentage = 50) - { - $obj =& Image_Graph::layoutFactory('Horizontal', $part1, $part2, $percentage); - return $obj; - } - - /** - * Factory method to create vertical layout. - * - * See {@link Image_Graph::layoutFactory()} - * - * @param Image_Graph_Element $part1 The 1st (top) part of the layout - * @param Image_Graph_Element $part2 The 2nd (bottom) part of the layout - * @param int $percentage The percentage of the layout to split at - * (percentage of total width from the top edge) - * @return Image_Graph_Layout The newly created layout object - * @static - */ - function &vertical(&$part1, &$part2, $percentage = 50) - { - $obj =& Image_Graph::layoutFactory('Vertical', $part1, $part2, $percentage); - return $obj; - } - - /** - * The error handling routine set by set_error_handler(). - * - * This method is used internaly by Image_Graph and PHP as a proxy for {@link - * Image_Graph::_error()}. - * - * @param string $error_type The type of error being handled. - * @param string $error_msg The error message being handled. - * @param string $error_file The file in which the error occurred. - * @param integer $error_line The line in which the error occurred. - * @param string $error_context The context in which the error occurred. - * @access private - */ - function _default_error_handler($error_type, $error_msg, $error_file, $error_line, $error_context) - { - switch( $error_type ) { - case E_ERROR: - $level = 'error'; - break; - - case E_USER_ERROR: - $level = 'user error'; - break; - - case E_WARNING: - $level = 'warning'; - break; - - case E_USER_WARNING: - $level = 'user warning'; - break; - - case E_NOTICE: - $level = 'notice'; - break; - - case E_USER_NOTICE: - $level = 'user notice'; - break; - - default: - $level = '(unknown)'; - break; - - } - - $this->_error("PHP $level: $error_msg", - array( - 'type' => $error_type, - 'file' => $error_file, - 'line' => $error_line, - 'context' => $error_context - ) - ); - } - - /** - * Displays the errors on the error stack. - * - * Invoking this method cause all errors on the error stack to be displayed - * on the graph-output, by calling the {@link Image_Graph::_displayError()} - * method. - * - * @access private - */ - function _displayErrors() - { - return true; - } - - /** - * Display an error from the error stack. - * - * This method writes error messages caught from the {@link Image_Graph:: - * _default_error_handler()} if {@Image_Graph::displayErrors()} was invoked, - * and the error explicitly set by the system using {@link - * Image_Graph_Common::_error()}. - * - * @param int $x The horizontal position of the error message - * @param int $y The vertical position of the error message - * @param array $error The error context - * - * @access private - */ - function _displayError($x, $y, $error) - { - } - - /** - * Outputs this graph using the canvas. - * - * This causes the graph to make all elements perform their output. Their - * result is 'written' to the output using the canvas, which also performs - * the actual output, fx. it being to a file or directly to the browser - * (in the latter case, the canvas will also make sure the correct HTTP - * headers are sent, making the browser handle the output correctly, if - * supported by it). - * - * Parameters are the ones supported by the canvas, common ones are: - * - * 'filename' To output to a file instead of browser - * - * 'tohtml' Return a HTML string that encompasses the current graph/canvas - this - * implies an implicit save using the following parameters: 'filename' The "temporary" - * filename of the graph, 'filepath' A path in the file system where Image_Graph can - * store the output (this file must be in DOCUMENT_ROOT scope), 'urlpath' The URL that the - * 'filepath' corresponds to (i.e. filepath + filename must be reachable from a browser using - * urlpath + filename) - * - * @param mixed $param The output parameters to pass to the canvas - * @return bool Was the output 'good' (true) or 'bad' (false). - */ - function done($param = false) - { - $result = $this->_reset(); - if (PEAR::isError($result)) { - return $result; - } - return $this->_done($param); - } - - /** - * Outputs this graph using the canvas. - * - * This causes the graph to make all elements perform their output. Their - * result is 'written' to the output using the canvas, which also performs - * the actual output, fx. it being to a file or directly to the browser - * (in the latter case, the canvas will also make sure the correct HTTP - * headers are sent, making the browser handle the output correctly, if - * supported by it). - * - * @param mixed $param The output parameters to pass to the canvas - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done($param = false) - { - $timeStart = $this->_getMicroTime(); - - if ($this->_shadow) { - $this->setPadding(20); - $this->_setCoords( - $this->_left, - $this->_top, - $this->_right - 10, - $this->_bottom - 10); - } - - $result = $this->_updateCoords(); - if (PEAR::isError($result)) { - return $result; - } - - if ($this->_getBackground()) { - $this->_canvas->rectangle( - array( - 'x0' => $this->_left, - 'y0' => $this->_top, - 'x1' => $this->_right, - 'y1' => $this->_bottom - ) - ); - } - - $result = parent::_done(); - if (PEAR::isError($result)) { - return $result; - } - - if ($this->_displayErrors) { - $this->_displayErrors(); - } - - $timeEnd = $this->_getMicroTime(); - - if (($this->_showTime) || - ((isset($param['showtime'])) && ($param['showtime'] === true)) - ) { - $text = 'Generated in ' . - sprintf('%0.3f', $timeEnd - $timeStart) . ' sec'; - $this->write( - $this->_right, - $this->_bottom, - $text, - IMAGE_GRAPH_ALIGN_RIGHT + IMAGE_GRAPH_ALIGN_BOTTOM, - array('color' => 'red') - ); - } - - if (isset($param['filename'])) { - if ((isset($param['tohtml'])) && ($param['tohtml'])) { - return $this->_canvas->toHtml($param); - } - else { - return $this->_canvas->save($param); - } - } else { - return $this->_canvas->show($param); - } - } -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Graph.php,v 1.58 2005/11/27 18:48:05 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + + +/** + * Include PEAR.php + */ +require_once 'PEAR.php'; + +/** + * Include file Image/Graph/Element.php + */ +require_once 'Image/Graph/Element.php'; + +/** + * Include file Image/Graph/Constants.php + */ +require_once 'Image/Graph/Constants.php'; + +/** + * Main class for the graph creation. + * + * This is the main class, it manages the canvas and performs the final output + * by sequentialy making the elements output their results. The final output is + * handled using the {@link Image_Canvas} classes which makes it possible + * to use different engines (fx GD, PDFlib, libswf, etc) for output to several + * formats with a non-intersecting API. + * + * This class also handles coordinates and the correct managment of setting the + * correct coordinates on child elements. + * + * @category Images + * @package Image_Graph + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph extends Image_Graph_Element +{ + + /** + * Show generation time on graph + * @var bool + * @access private + */ + var $_showTime = false; + + /** + * Display errors on the canvas + * @var boolean + * @access private + */ + var $_displayErrors = false; + + /** + * Image_Graph [Constructor]. + * + * If passing the 3 parameters they are defined as follows:' + * + * Fx.: + * + * $Graph =& new Image_Graph(400, 300); + * + * or using the factory method: + * + * $Graph =& Image_Graph::factory('graph', array(400, 300)); + * + * This causes a 'png' canvas to be created by default. + * + * Otherwise use a single parameter either as an associated array or passing + * the canvas along to the constructor: + * + * 1) Create a new canvas with the following parameters: + * + * 'canvas' - The canvas type, can be any of 'gd', 'jpg', 'png' or 'svg' + * (more to come) - if omitted the default is 'gd' + * + * 'width' - The width of the graph + * + * 'height' - The height of the graph + * + * An example of this usage: + * + * $Graph =& Image_Graph::factory('graph', array(array('width' => 400, + * 'height' => 300, 'canvas' => 'jpg'))); + * + * NB! In thïs case remember the "double" array (see {@link Image_Graph:: + * factory()}) + * + * 2) Use the canvas specified, pass a valid Image_Canvas as + * parameter. Remember to pass by reference, i. e. &$canvas, fx.: + * + * $Graph =& new Image_Graph($Canvas); + * + * or using the factory method: + * + * $Graph =& Image_Graph::factory('graph', $Canvas)); + * + * @param mixed $params The width of the graph, an indexed array + * describing a new canvas or a valid {@link Image_Canvas} object + * @param int $height The height of the graph in pixels + * @param bool $createTransparent Specifies whether the graph should be + * created with a transparent background (fx for PNG's - note: transparent + * PNG's is not supported by Internet Explorer!) + */ + function Image_Graph($params, $height = false, $createTransparent = false) + { + parent::Image_Graph_Element(); + + $this->setFont(Image_Graph::factory('Image_Graph_Font')); + + if (defined('IMAGE_GRAPH_DEFAULT_CANVAS_TYPE')) { + $canvasType = IMAGE_GRAPH_DEFAULT_CANVAS_TYPE; + } else { + $canvasType = 'png'; // use GD as default, if nothing else is specified + } + + if (is_array($params)) { + if (isset($params['canvas'])) { + $canvasType = $params['canvas']; + } + + $width = 0; + $height = 0; + + if (isset($params['width'])) { + $width = $params['width']; + } + + if (isset($params['height'])) { + $height = $params['height']; + } + } elseif (is_a($params, 'Image_Canvas')) { + $this->_canvas =& $params; + $width = $this->_canvas->getWidth(); + $height = $this->_canvas->getHeight(); + } elseif (is_numeric($params)) { + $width = $params; + } + + if ($this->_canvas == null) { + include_once 'Image/Canvas.php'; + $this->_canvas =& + Image_Canvas::factory( + $canvasType, + array('width' => $width, 'height' => $height) + ); + } + + $this->_setCoords(0, 0, $width - 1, $height - 1); + } + + /** + * Gets the canvas for this graph. + * + * The canvas is set by either passing it to the constructor {@link + * Image_Graph::ImageGraph()} or using the {@link Image_Graph::setCanvas()} + * method. + * + * @return Image_Canvas The canvas used by this graph + * @access private + * @since 0.3.0dev2 + */ + function &_getCanvas() + { + return $this->_canvas; + } + + /** + * Sets the canvas for this graph. + * + * Calling this method makes this graph use the newly specified canvas for + * handling output. This method should be called whenever multiple + * 'outputs' are required. Invoke this method after calls to {@link + * Image_Graph:: done()} has been performed, to switch canvass. + * + * @param Image_Canvas $canvas The new canvas + * @return Image_Canvas The new canvas + * @since 0.3.0dev2 + */ + function &setCanvas(&$canvas) + { + if (!is_a($this->_canvas, 'Image_Canvas')) { + return $this->_error('The canvas introduced is not an Image_Canvas object'); + } + + $this->_canvas =& $canvas; + $this->_setCoords( + 0, + 0, + $this->_canvas->getWidth() - 1, + $this->_canvas->getHeight() - 1 + ); + return $this->_canvas; + } + + /** + * Gets a very precise timestamp + * + * @return The number of seconds to a lot of decimals + * @access private + */ + function _getMicroTime() + { + list($usec, $sec) = explode(' ', microtime()); + return ((float)$usec + (float)$sec); + } + + /** + * Gets the width of this graph. + * + * The width is returned as 'defined' by the canvas. + * + * @return int the width of this graph + */ + function width() + { + return $this->_canvas->getWidth(); + } + + /** + * Gets the height of this graph. + * + * The height is returned as 'defined' by the canvas. + * + * @return int the height of this graph + */ + function height() + { + return $this->_canvas->getHeight(); + } + + /** + * Enables displaying of errors on the output. + * + * Use this method to enforce errors to be displayed on the output. Calling + * this method makes PHP uses this graphs error handler as default {@link + * Image_Graph::_default_error_handler()}. + */ + function displayErrors() + { + $this->_displayErrors = true; + set_error_handler(array(&$this, '_default_error_handler')); + } + + /** + * Sets the log method for this graph. + * + * Use this method to enable logging. This causes any errors caught + * by either the error handler {@see Image_Graph::displayErrors()} + * or explicitly by calling {@link Image_Graph_Common::_error()} be + * logged using the specified logging method. + * + * If a filename is specified as log method, a Log object is created (using + * the 'file' handler), with a handle of 'Image_Graph Error Log'. + * + * Logging requires {@link Log}. + * + * @param mixed $log The log method, either a Log object or filename to log + * to + * @since 0.3.0dev2 + */ + function setLog($log) + { + } + + /** + * Factory method to create Image_Graph objects. + * + * Used for 'lazy including', i.e. loading only what is necessary, when it + * is necessary. If only one parameter is required for the constructor of + * the class simply pass this parameter as the $params parameter, unless the + * parameter is an array or a reference to a value, in that case you must + * 'enclose' the parameter in an array. Similar if the constructor takes + * more than one parameter specify the parameters in an array, i.e + * + * Image_Graph::factory('MyClass', array($param1, $param2, &$param3)); + * + * Variables that need to be passed by reference *must* have the & + * before the variable, i.e: + * + * Image_Graph::factory('line', &$Dataset); + * + * or + * + * Image_graph::factory('bar', array(array(&$Dataset1, &$Dataset2), + * 'stacked')); + * + * Class name can be either of the following: + * + * 1 The 'real' Image_Graph class name, i.e. Image_Graph_Plotarea or + * Image_Graph_Plot_Line + * + * 2 Short class name (leave out Image_Graph) and retain case, i.e. + * Plotarea, Plot_Line *not* plot_line + * + * 3 Class name 'alias', the following are supported: + * + * 'graph' = Image_Graph + * + * 'plotarea' = Image_Graph_Plotarea + * + * 'line' = Image_Graph_Plot_Line + * + * 'area' = Image_Graph_Plot_Area + * + * 'bar' = Image_Graph_Plot_Bar + * + * 'pie' = Image_Graph_Plot_Pie + * + * 'radar' = Image_Graph_Plot_Radar + * + * 'step' = Image_Graph_Plot_Step + * + * 'impulse' = Image_Graph_Plot_Impulse + * + * 'dot' or 'scatter' = Image_Graph_Plot_Dot + * + * 'smooth_line' = Image_Graph_Plot_Smoothed_Line + * + * 'smooth_area' = Image_Graph_Plot_Smoothed_Area + + * 'dataset' = Image_Graph_Dataset_Trivial + * + * 'random' = Image_Graph_Dataset_Random + * + * 'function' = Image_Graph_Dataset_Function + * + * 'vector' = Image_Graph_Dataset_VectorFunction + * + * 'category' = Image_Graph_Axis_Category + * + * 'axis' = Image_Graph_Axis + * + * 'axis_log' = Image_Graph_Axis_Logarithmic + * + * 'title' = Image_Graph_Title + * + * 'line_grid' = Image_Graph_Grid_Lines + * + * 'bar_grid' = Image_Graph_Grid_Bars + * + * 'polar_grid' = Image_Graph_Grid_Polar + * + * 'legend' = Image_Graph_Legend + * + * 'font' = Image_Graph_Font + * + * 'ttf_font' = Image_Graph_Font + * + * 'Image_Graph_Font_TTF' = Image_Graph_Font (to maintain BC with Image_Graph_Font_TTF) + * + * 'gradient' = Image_Graph_Fill_Gradient + * + * 'icon_marker' = Image_Graph_Marker_Icon + * + * 'value_marker' = Image_Graph_Marker_Value + * + * @param string $class The class for the new object + * @param mixed $params The paramaters to pass to the constructor + * @return object A new object for the class + * @static + */ + function &factory($class, $params = null) + { + static $Image_Graph_classAliases = array( + 'graph' => 'Image_Graph', + 'plotarea' => 'Image_Graph_Plotarea', + + 'line' => 'Image_Graph_Plot_Line', + 'area' => 'Image_Graph_Plot_Area', + 'bar' => 'Image_Graph_Plot_Bar', + 'smooth_line' => 'Image_Graph_Plot_Smoothed_Line', + 'smooth_area' => 'Image_Graph_Plot_Smoothed_Area', + 'pie' => 'Image_Graph_Plot_Pie', + 'radar' => 'Image_Graph_Plot_Radar', + 'step' => 'Image_Graph_Plot_Step', + 'impulse' => 'Image_Graph_Plot_Impulse', + 'dot' => 'Image_Graph_Plot_Dot', + 'scatter' => 'Image_Graph_Plot_Dot', + + 'dataset' => 'Image_Graph_Dataset_Trivial', + 'random' => 'Image_Graph_Dataset_Random', + 'function' => 'Image_Graph_Dataset_Function', + 'vector' => 'Image_Graph_Dataset_VectorFunction', + + 'category' => 'Image_Graph_Axis_Category', + 'axis' => 'Image_Graph_Axis', + 'axis_log' => 'Image_Graph_Axis_Logarithmic', + + 'title' => 'Image_Graph_Title', + + 'line_grid' => 'Image_Graph_Grid_Lines', + 'bar_grid' => 'Image_Graph_Grid_Bars', + 'polar_grid' => 'Image_Graph_Grid_Polar', + + 'legend' => 'Image_Graph_Legend', + 'font' => 'Image_Graph_Font', + 'ttf_font' => 'Image_Graph_Font', + 'Image_Graph_Font_TTF' => 'Image_Graph_Font', // BC with Image_Graph_Font_TTF + 'gradient' => 'Image_Graph_Fill_Gradient', + + 'icon_marker' => 'Image_Graph_Marker_Icon', + 'value_marker' => 'Image_Graph_Marker_Value' + ); + + if (substr($class, 0, 11) != 'Image_Graph') { + if (isset($Image_Graph_classAliases[$class])) { + $class = $Image_Graph_classAliases[$class]; + } else { + $class = 'Image_Graph_' . $class; + } + } + + include_once str_replace('_', '/', $class) . '.php'; + + $obj = null; + + if (is_array($params)) { + switch (count($params)) { + case 1: + $obj =& new $class( + $params[0] + ); + break; + + case 2: + $obj =& new $class( + $params[0], + $params[1] + ); + break; + + case 3: + $obj =& new $class( + $params[0], + $params[1], + $params[2] + ); + break; + + case 4: + $obj =& new $class( + $params[0], + $params[1], + $params[2], + $params[3] + ); + break; + + case 5: + $obj =& new $class( + $params[0], + $params[1], + $params[2], + $params[3], + $params[4] + ); + break; + + case 6: + $obj =& new $class( + $params[0], + $params[1], + $params[2], + $params[3], + $params[4], + $params[5] + ); + break; + + case 7: + $obj =& new $class( + $params[0], + $params[1], + $params[2], + $params[3], + $params[4], + $params[5], + $params[6] + ); + break; + + case 8: + $obj =& new $class( + $params[0], + $params[1], + $params[2], + $params[3], + $params[4], + $params[5], + $params[6], + $params[7] + ); + break; + + case 9: + $obj =& new $class( + $params[0], + $params[1], + $params[2], + $params[3], + $params[4], + $params[5], + $params[6], + $params[7], + $params[8] + ); + break; + + case 10: + $obj =& new $class( + $params[0], + $params[1], + $params[2], + $params[3], + $params[4], + $params[5], + $params[6], + $params[7], + $params[8], + $params[9] + ); + break; + + default: + $obj =& new $class(); + break; + + } + } else { + if ($params == null) { + $obj =& new $class(); + } else { + $obj =& new $class($params); + } + } + return $obj; + } + + /** + * Factory method to create layouts. + * + * This method is used for easy creation, since using {@link Image_Graph:: + * factory()} does not work with passing newly created objects from + * Image_Graph::factory() as reference, this is something that is + * fortunately fixed in PHP5. Also used for 'lazy including', i.e. loading + * only what is necessary, when it is necessary. + * + * Use {@link Image_Graph::horizontal()} or {@link Image_Graph::vertical()} + * instead for easier access. + * + * @param mixed $layout The type of layout, can be either 'Vertical' + * or 'Horizontal' (case sensitive) + * @param Image_Graph_Element $part1 The 1st part of the layout + * @param Image_Graph_Element $part2 The 2nd part of the layout + * @param int $percentage The percentage of the layout to split at + * @return Image_Graph_Layout The newly created layout object + * @static + */ + function &layoutFactory($layout, &$part1, &$part2, $percentage = 50) + { + if (($layout != 'Vertical') && ($layout != 'Horizontal')) { + return $this->_error('Layouts must be either \'Horizontal\' or \'Vertical\''); + } + + if (!(is_a($part1, 'Image_Graph_Element'))) { + return $this->_error('Part 1 is not a valid Image_Graph element'); + } + + if (!(is_a($part2, 'Image_Graph_Element'))) { + return $this->_error('Part 2 is not a valid Image_Graph element'); + } + + if ((!is_numeric($percentage)) || ($percentage < 0) || ($percentage > 100)) { + return $this->_error('Percentage has to be a number between 0 and 100'); + } + + include_once "Image/Graph/Layout/$layout.php"; + $class = "Image_Graph_Layout_$layout"; + $obj =& new $class($part1, $part2, $percentage); + return $obj; + } + + /** + * Factory method to create horizontal layout. + * + * See {@link Image_Graph::layoutFactory()} + * + * @param Image_Graph_Element $part1 The 1st (left) part of the layout + * @param Image_Graph_Element $part2 The 2nd (right) part of the layout + * @param int $percentage The percentage of the layout to split at + * (percentage of total height from the left side) + * @return Image_Graph_Layout The newly created layout object + * @static + */ + function &horizontal(&$part1, &$part2, $percentage = 50) + { + $obj =& Image_Graph::layoutFactory('Horizontal', $part1, $part2, $percentage); + return $obj; + } + + /** + * Factory method to create vertical layout. + * + * See {@link Image_Graph::layoutFactory()} + * + * @param Image_Graph_Element $part1 The 1st (top) part of the layout + * @param Image_Graph_Element $part2 The 2nd (bottom) part of the layout + * @param int $percentage The percentage of the layout to split at + * (percentage of total width from the top edge) + * @return Image_Graph_Layout The newly created layout object + * @static + */ + function &vertical(&$part1, &$part2, $percentage = 50) + { + $obj =& Image_Graph::layoutFactory('Vertical', $part1, $part2, $percentage); + return $obj; + } + + /** + * The error handling routine set by set_error_handler(). + * + * This method is used internaly by Image_Graph and PHP as a proxy for {@link + * Image_Graph::_error()}. + * + * @param string $error_type The type of error being handled. + * @param string $error_msg The error message being handled. + * @param string $error_file The file in which the error occurred. + * @param integer $error_line The line in which the error occurred. + * @param string $error_context The context in which the error occurred. + * @access private + */ + function _default_error_handler($error_type, $error_msg, $error_file, $error_line, $error_context) + { + switch( $error_type ) { + case E_ERROR: + $level = 'error'; + break; + + case E_USER_ERROR: + $level = 'user error'; + break; + + case E_WARNING: + $level = 'warning'; + break; + + case E_USER_WARNING: + $level = 'user warning'; + break; + + case E_NOTICE: + $level = 'notice'; + break; + + case E_USER_NOTICE: + $level = 'user notice'; + break; + + default: + $level = '(unknown)'; + break; + + } + + $this->_error("PHP $level: $error_msg", + array( + 'type' => $error_type, + 'file' => $error_file, + 'line' => $error_line, + 'context' => $error_context + ) + ); + } + + /** + * Displays the errors on the error stack. + * + * Invoking this method cause all errors on the error stack to be displayed + * on the graph-output, by calling the {@link Image_Graph::_displayError()} + * method. + * + * @access private + */ + function _displayErrors() + { + return true; + } + + /** + * Display an error from the error stack. + * + * This method writes error messages caught from the {@link Image_Graph:: + * _default_error_handler()} if {@Image_Graph::displayErrors()} was invoked, + * and the error explicitly set by the system using {@link + * Image_Graph_Common::_error()}. + * + * @param int $x The horizontal position of the error message + * @param int $y The vertical position of the error message + * @param array $error The error context + * + * @access private + */ + function _displayError($x, $y, $error) + { + } + + /** + * Outputs this graph using the canvas. + * + * This causes the graph to make all elements perform their output. Their + * result is 'written' to the output using the canvas, which also performs + * the actual output, fx. it being to a file or directly to the browser + * (in the latter case, the canvas will also make sure the correct HTTP + * headers are sent, making the browser handle the output correctly, if + * supported by it). + * + * Parameters are the ones supported by the canvas, common ones are: + * + * 'filename' To output to a file instead of browser + * + * 'tohtml' Return a HTML string that encompasses the current graph/canvas - this + * implies an implicit save using the following parameters: 'filename' The "temporary" + * filename of the graph, 'filepath' A path in the file system where Image_Graph can + * store the output (this file must be in DOCUMENT_ROOT scope), 'urlpath' The URL that the + * 'filepath' corresponds to (i.e. filepath + filename must be reachable from a browser using + * urlpath + filename) + * + * @param mixed $param The output parameters to pass to the canvas + * @return bool Was the output 'good' (true) or 'bad' (false). + */ + function done($param = false) + { + $result = $this->_reset(); + if (PEAR::isError($result)) { + return $result; + } + return $this->_done($param); + } + + /** + * Outputs this graph using the canvas. + * + * This causes the graph to make all elements perform their output. Their + * result is 'written' to the output using the canvas, which also performs + * the actual output, fx. it being to a file or directly to the browser + * (in the latter case, the canvas will also make sure the correct HTTP + * headers are sent, making the browser handle the output correctly, if + * supported by it). + * + * @param mixed $param The output parameters to pass to the canvas + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done($param = false) + { + $timeStart = $this->_getMicroTime(); + + if ($this->_shadow) { + $this->setPadding(20); + $this->_setCoords( + $this->_left, + $this->_top, + $this->_right - 10, + $this->_bottom - 10); + } + + $result = $this->_updateCoords(); + if (PEAR::isError($result)) { + return $result; + } + + if ($this->_getBackground()) { + $this->_canvas->rectangle( + array( + 'x0' => $this->_left, + 'y0' => $this->_top, + 'x1' => $this->_right, + 'y1' => $this->_bottom + ) + ); + } + + $result = parent::_done(); + if (PEAR::isError($result)) { + return $result; + } + + if ($this->_displayErrors) { + $this->_displayErrors(); + } + + $timeEnd = $this->_getMicroTime(); + + if (($this->_showTime) || + ((isset($param['showtime'])) && ($param['showtime'] === true)) + ) { + $text = 'Generated in ' . + sprintf('%0.3f', $timeEnd - $timeStart) . ' sec'; + $this->write( + $this->_right, + $this->_bottom, + $text, + IMAGE_GRAPH_ALIGN_RIGHT + IMAGE_GRAPH_ALIGN_BOTTOM, + array('color' => 'red') + ); + } + + if (isset($param['filename'])) { + if ((isset($param['tohtml'])) && ($param['tohtml'])) { + return $this->_canvas->toHtml($param); + } + else { + return $this->_canvas->save($param); + } + } else { + return $this->_canvas->show($param); + } + } +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Axis.php b/includes/pear/Image/Graph/Axis.php index 70bd03dd..13544fc3 100644 --- a/includes/pear/Image/Graph/Axis.php +++ b/includes/pear/Image/Graph/Axis.php @@ -1,1643 +1,1690 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Axis.php,v 1.33 2005/10/05 20:51:22 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Plotarea/Element.php - */ -require_once 'Image/Graph/Plotarea/Element.php'; - -/** - * Diplays a normal linear axis (either X- or Y-axis). - * - * @category Images - * @package Image_Graph - * @subpackage Axis - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ - class Image_Graph_Axis extends Image_Graph_Plotarea_Element -{ - - /** - * The type of the axis, possible values are: - *
    - *
  • IMAGE_GRAPH_AXIS_X / IMAGE_GRAPH_AXIS_HORIZONTAL - *
  • IMAGE_GRAPH_AXIS_Y / IMAGE_GRAPH_AXIS_VERTICAL / - * IMAGE_GRAPH_AXIS_Y_SECONDARY - *
- * @var int - * @access private - */ - var $_type; - - /** - * The minimum value the axis displays - * @var int - * @access private - */ - var $_minimum = false; - - /** - * The minimum value the axis has been explicitly set by the user - * @var bool - * @access private - */ - var $_minimumSet = false; - - /** - * The maximum value the axis displays - * @var int - * @access private - */ - var $_maximum = false; - - /** - * The maximum value the axis has been explicitly set by the user - * @var bool - * @access private - */ - var $_maximumSet = false; - - /** - * The value span of the axis. - * This is primarily included for performance reasons - * @var double - * @access private - */ - var $_axisSpan = false; - - /** - * The value span of the axis. - * This is primarily included for performance reasons - * @var double - * @access private - */ - var $_axisValueSpan = false; - - /** - * The axis padding. - * The index 'low' specifies the padding for the low axis values (when not - * inverted), i.e. to the left on an x-axis and on the bottom of an y-axis, - * vice versa for 'high'. - * - * Axis padding does not make sense on a normal linear y-axis with a 'y-min' - * of 0 since this corresponds to displaying a small part of the y-axis - * below 0! - * - * @var array - * @access private - */ - var $_axisPadding = array('low' => 0, 'high' => 0); - - /** - * The number of "pixels" representing 1 unit on the axis - * - * This is primarily included for performance reasons - * @var double - * @access private - */ - var $_delta = false; - - /** - * Specify if the axis should label the minimum value - * @var bool - * @access private - */ - var $_showLabelMinimum = true; - - /** - * Specify if the axis should label 0 (zero) - * @var bool - * @access private - */ - var $_showLabelZero = false; - - /** - * Specify if the axis should label the maximum value - * @var bool - * @access private - */ - var $_showLabelMaximum = true; - - /** - * Show arrow heads at the 'end' of the axis, default: false - * @var bool - * @access private - */ - var $_showArrow = false; - - /** - * Intersection data of axis - * @var array - * @access private - */ - var $_intersect = array('value' => 'default', 'axis' => 'default'); - - /** - * The fixed size of the axis (i.e. width for y-axis, height for x-axis) - * @var mixed - * @access private - */ - var $_fixedSize = false; - - /** - * The label options - * - * Should text be shows, preferences for ticks. The indexes start at level - * 1, which is chosen for readability - * @var array - * @access private - */ - var $_labelOptions = array( - 1 => array( - 'interval' => 1, - 'type' => 'auto', - 'tick' => array('start' => -2, 'end' => 2), - 'showtext' => true, - 'showoffset' => false, - 'font' => array(), - 'offset' => 0, - 'position' => 'outside' - ) - ); - - /** - * The labels that are shown. - * - * This is used to make values show only once... - * @access private - */ - var $_labelText = array(); - - /** - * A data preprocessor for formatting labels, fx showing dates as a standard - * date instead of Unix time stamp - * @var Image_Graph_DatePreProcessor - * @access private - * @see Image_Graph_DataPreProcessor - */ - var $_dataPreProcessor = null; - - /** - * Point marked in the axis - * @var array - * @access private - */ - var $_marks = array(); - - /** - * Specifies whether the values should be 'pushed' by 0.5 - * @var bool - * @access private - */ - var $_pushValues = false; - - /** - * The title of this axis - * @var string - * @access private - */ - var $_title = ''; - - /** - * The font used for the title of this axis - * @var Image_Graph_Font - * @access private - */ - var $_titleFont = false; - - /** - * Invert the axis (i.e. if an y-axis normally displays minimum values at - * the bottom, they are not displayed at the top - * @var bool - * @access private - * @since 0.3.0dev3 - */ - var $_invert = false; - - /** - * Transpose the axis (i.e. is a normal y-axis transposed, so thats it's not show - * vertically as normally expected, but instead horizontally) - * @var bool - * @access private - */ - var $_transpose = false; - - /** - * Image_Graph_Axis [Constructor]. - * Normally a manual creation should not be necessary, axis are created - * automatically by the {@link Image_Graph_Plotarea} constructor unless - * explicitly defined otherwise - * - * @param int $type The type (direction) of the Axis, use IMAGE_GRAPH_AXIS_X - * for an X-axis (default, may be omitted) and IMAGE_GRAPH_AXIS_Y for Y- - * axis) - */ - function Image_Graph_Axis($type = IMAGE_GRAPH_AXIS_X) - { - parent::Image_Graph_Element(); - $this->_type = $type; - $this->_fillStyle = 'black'; - } - - /** - * Push the values by 0.5 (for bar and step chart) - * - * @access private - */ - function _pushValues() - { - $this->_pushValues = true; - } - - /** - * Sets the axis padding for a given position ('low' or 'high') - * @param string $where The position - * @param int $value The number of pixels to "pad" - * @access private - */ - function _setAxisPadding($where, $value) - { - $this->_axisPadding[$where] = $value; - } - - /** - * Gets the font of the title. - * - * If not font has been set, the parent font is propagated through it's - * children. - * - * @return array An associated array used for canvas - * @access private - */ - function _getTitleFont() - { - if ($this->_titleFont === false) { - if ($this->_defaultFontOptions !== false) { - return $this->_defaultFontOptions; - } else { - return $this->_getFont(); - } - } else { - if (is_object($this->_titleFont)) { - return $this->_titleFont->_getFont(); - } elseif (is_array($this->_titleFont)) { - return $this->_getFont($this->_titleFont); - } elseif (is_int($this->_titleFont)) { - return $this->_getFont(array('size' => $this->_titleFont)); - } - } - return array(); - } - - /** - * Shows a label for the the specified values. - * - * Allowed values are combinations of: - *
    - *
  • IMAGE_GRAPH_LABEL_MINIMUM - *
  • IMAGE_GRAPH_LABEL_ZERO - *
  • IMAGE_GRAPH_LABEL_MAXIMUM - *
- * By default none of these are shows on the axis - * - * @param int $value The values to show labels for - */ - function showLabel($value) - { - $this->_showLabelMinimum = ($value & IMAGE_GRAPH_LABEL_MINIMUM); - $this->_showLabelZero = ($value & IMAGE_GRAPH_LABEL_ZERO); - $this->_showLabelMaximum = ($value & IMAGE_GRAPH_LABEL_MAXIMUM); - } - - /** - * Sets a data preprocessor for formatting the axis labels - * - * @param Image_Graph_DataPreprocessor $dataPreProcessor The data preprocessor - * @see Image_Graph_DataPreprocessor - */ - function setDataPreProcessor(& $dataPreProcessor) - { - $this->_dataPreProcessor =& $dataPreProcessor; - } - - /** - * Gets the minimum value the axis will show - * - * @return double The minumum value - * @access private - */ - function _getMinimum() - { - return $this->_minimum; - } - - /** - * Gets the maximum value the axis will show - * - * @return double The maximum value - * @access private - */ - function _getMaximum() - { - return $this->_maximum; - } - - /** - * Sets the minimum value the axis will show - * - * @param double $minimum The minumum value to use on the axis - * @access private - */ - function _setMinimum($minimum) - { - if ($this->_minimum === false) { - $this->forceMinimum($minimum, false); - } else { - $this->forceMinimum(min($this->_minimum, $minimum), false); - } - } - - /** - * Sets the maximum value the axis will show - * - * @param double $maximum The maximum value to use on the axis - * @access private - */ - function _setMaximum($maximum) - { - if ($this->_maximum === false) { - $this->forceMaximum($maximum, false); - } else { - $this->forceMaximum(max($this->_maximum, $maximum), false); - } - } - - /** - * Forces the minimum value of the axis - * - * @param double $minimum The minumum value to use on the axis - * @param bool $userEnforce This value should not be set, used internally - */ - function forceMinimum($minimum, $userEnforce = true) - { - if (($userEnforce) || (!$this->_minimumSet)) { - $this->_minimum = $minimum; - $this->_minimumSet = $userEnforce; - } - $this->_calcLabelInterval(); - } - - /** - * Forces the maximum value of the axis - * - * @param double $maximum The maximum value to use on the axis - * @param bool $userEnforce This value should not be set, used internally - */ - function forceMaximum($maximum, $userEnforce = true) - { - if (($userEnforce) || (!$this->_maximumSet)) { - $this->_maximum = $maximum; - $this->_maximumSet = $userEnforce; - } - $this->_calcLabelInterval(); - } - - /** - * Show an arrow head on the 'end' of the axis - */ - function showArrow() - { - $this->_showArrow = true; - } - - /** - * Do not show an arrow head on the 'end' of the axis (default) - */ - function hideArrow() - { - $this->_showArrow = false; - } - - /** - * Return the label distance. - * - * @param int $level The label level to return the distance of - * @return int The distance between 2 adjacent labels - * @access private - */ - function _labelDistance($level = 1) - { - $l1 = $this->_getNextLabel(false, $level); - $l2 = $this->_getNextLabel($l1, $level);; - return abs($this->_point($l2) - $this->_point($l1)); - } - - /** - * Sets an interval for when labels are shown on the axis. - * - * By default 'auto' is used, forcing the axis to calculate a approximate - * best label interval to be used. Specify an array to use user-defined - * values for labels. - * - * @param mixed $labelInterval The interval with which labels are shown - * @param int $level The label level to set the interval on - */ - function setLabelInterval($labelInterval = 'auto', $level = 1) - { - if (!isset($this->_labelOptions[$level])) { - $this->_labelOptions[$level] = array(); - } - - if ($labelInterval === 'auto') { - $this->_labelOptions[$level]['type'] = 'auto'; - $this->_calcLabelInterval(); - } else { - $this->_labelOptions[$level]['type'] = 'manual'; - $this->_labelOptions[$level]['interval'] = $labelInterval; - } - } - - /** - * Sets options for the label at a specific level. - * - * Possible options are: - * - * 'showtext' true or false whether label text should be shown or not - * - * 'showoffset' should the label be shown at an offset, i.e. should the - * label be shown at a position so that it does not overlap with prior - * levels. Only applies to multilevel labels with text - * - * 'font' The font options as an associated array - * - * 'position' The position at which the labels are written ('inside' or - * 'outside' the axis). NB! This relative position only applies to the - * default location of the axis, i.e. if an x-axis is inverted then - * 'outside' still refers to the "left" side of a normal y-axis (since this - * is normally 'outside') but the actual output will be labels on the - * "inside"! - * - * 'format' To format the label text according to a sprintf statement - * - * 'dateformat' To format the label as a date, fx. j. M Y = 29. Jun 2005 - * - * @param string $option The label option name (see detailed description - * for possible values) - * @param mixed $value The value for the option - * @param int $level The label level to set the interval on - */ - function setLabelOption($option, $value, $level = 1) - { - if (!isset($this->_labelOptions[$level])) { - $this->_labelOptions[$level] = array('type' => 'auto'); - } - - $this->_labelOptions[$level][$option] = $value; - } - - /** - * Sets options for the label at a specific level. - * - * The possible options are specified in {@link Image_Graph_Axis:: - * setLabelOption()}. - * - * @param array $options An assciated array with label options - * @param int $level The label level to set the interval on - */ - function setLabelOptions($options, $level = 1) - { - if (is_array($options)) { - if (isset($this->_labelOptions[$level])) { - $this->_labelOptions[$level] = array_merge($this->_labelOptions[$level], $options); - } else { - $this->_labelOptions[$level] = $options; - } - - } - } - - /** - * Sets the title of this axis. - * - * This is used as an alternative (maybe better) method, than using layout's - * for axis-title generation. - * - * To use the current propagated font, but just set it vertically, simply - * pass 'vertical' as second parameter for vertical alignment down-to-up or - * 'vertical2' for up-to-down alignment. - * - * @param string $title The title of this axis - * @param Image_Graph_Font $font The font used for the title - * @since 0.3.0dev2 - */ - function setTitle($title, $font = false) - { - $this->_title = $title; - if ($font === 'vertical') { - $this->_titleFont = array('vertical' => true, 'angle' => 90); - } elseif ($font === 'vertical2') { - $this->_titleFont = array('vertical' => true, 'angle' => 270); - } else { - $this->_titleFont =& $font; - } - } - - /** - * Sets a fixed "size" for the axis. - * - * If the axis is any type of y-axis the size relates to the width of the - * axis, if an x-axis is concerned the size is the height. - * - * @param int $size The fixed size of the axis - * @since 0.3.0dev5 - */ - function setFixedSize($size) - { - $this->_fixedSize = $size; - } - - /** - * Preprocessor for values, ie for using logarithmic axis - * - * @param double $value The value to preprocess - * @return double The preprocessed value - * @access private - */ - function _value($value) - { - return $value - $this->_getMinimum() + ($this->_pushValues ? 0.5 : 0); - } - - /** - * Apply the dataset to the axis - * - * @param Image_Graph_Dataset $dataset The dataset - * @access private - */ - function _applyDataset(&$dataset) - { - if ($this->_type == IMAGE_GRAPH_AXIS_X) { - $this->_setMinimum($dataset->minimumX()); - $this->_setMaximum($dataset->maximumX()); - } else { - $this->_setMinimum($dataset->minimumY()); - $this->_setMaximum($dataset->maximumY()); - } - } - - /** - * Get the pixel position represented by a value on the canvas - * - * @param double $value the value to get the pixel-point for - * @return double The pixel position along the axis - * @access private - */ - function _point($value) - { - if ((($this->_type == IMAGE_GRAPH_AXIS_X) && (!$this->_transpose)) || - (($this->_type != IMAGE_GRAPH_AXIS_X) && ($this->_transpose))) - { - if ($this->_invert) { - return max($this->_left, $this->_right - $this->_axisPadding['high'] - $this->_delta * $this->_value($value)); - } else { - return min($this->_right, $this->_left + $this->_axisPadding['low'] + $this->_delta * $this->_value($value)); - } - } else { - if ($this->_invert) { - return min($this->_bottom, $this->_top + $this->_axisPadding['high'] + $this->_delta * $this->_value($value)); - } else { - return max($this->_top, $this->_bottom - $this->_axisPadding['low'] - $this->_delta * $this->_value($value)); - } - } - } - - - /** - * Get the axis intersection pixel position - * - * This is only to be called prior to output! I.e. between the user - * invokation of Image_Graph::done() and any actual output is performed. - * This is because it can change the axis range. - * - * @param double $value the intersection value to get the pixel-point for - * @return double The pixel position along the axis - * @access private - */ - function _intersectPoint($value) - { - - if (($value === 'min') || ($value < $this->_getMinimum())) { - if ($this->_type == IMAGE_GRAPH_AXIS_X) { - if ($this->_invert) { - return ($this->_transpose ? $this->_top : $this->_right); - } else { - return ($this->_transpose ? $this->_bottom : $this->_left); - } - } else { - if ($this->_invert) { - return ($this->_transpose ? $this->_right : $this->_top); - } else { - return ($this->_transpose ? $this->_left : $this->_bottom); - } - } - } elseif (($value === 'max') || ($value > $this->_getMaximum())) { - if ($this->_type == IMAGE_GRAPH_AXIS_X) { - if ($this->_invert) { - return ($this->_transpose ? $this->_bottom : $this->_left); - } else { - return ($this->_transpose ? $this->_top : $this->_right); - } - } else { - if ($this->_invert) { - return ($this->_transpose ? $this->_left : $this->_bottom); - } else { - return ($this->_transpose ? $this->_right : $this->_top); - } - } - } - - return $this->_point($value); - } - - /** - * Calculate the delta value (the number of pixels representing one unit - * on the axis) - * - * @return double The label interval - * @access private - */ - function _calcDelta() - { - if ($this->_axisValueSpan == 0) { - $this->_delta = false; - } elseif ($this->_type == IMAGE_GRAPH_AXIS_X) { - $this->_delta = (($this->_transpose ? $this->height() : $this->width()) - ($this->_axisPadding['low'] + $this->_axisPadding['high'])) / $this->_axisValueSpan; - } else { - $this->_delta = (($this->_transpose ? $this->width() : $this->height()) - ($this->_axisPadding['low'] + $this->_axisPadding['high'])) / $this->_axisValueSpan; - } - } - - /** - * Calculate the label interval - * - * If explicitly defined this will be calucated to an approximate best. - * - * @return double The label interval - * @access private - */ - function _calcLabelInterval() - { - $min = $this->_getMinimum(); - $max = $this->_getMaximum(); - - $this->_axisValueSpan = $this->_axisSpan = abs($max - $min); - - if ((!empty($min)) && (!empty($max)) && ($min > $max)) { - $this->_labelOptions[1]['interval'] = 1; - return true; - } - - $span = 0; - foreach($this->_labelOptions as $level => $labelOptions) { - if ((!isset($labelOptions['type'])) || ($labelOptions['type'] !== 'auto')) { - $span = false; - } elseif ($level == 1) { - $span = $this->_axisValueSpan; - } else { - $l1 = $this->_getNextLabel(false, $level - 1); - $l2 = $this->_getNextLabel($l1, $level - 1); - if ((!is_numeric($l1)) || (!is_numeric($l2))) { - $span == false; - } else { - $span = $l2 - $l1; - } - } - - if ($span !== false) { - $interval = pow(10, floor(log10($span))); - - if ($interval == 0) { - $interval = 1; - } - - if ((($span) / $interval) < 3) { - $interval = $interval / 4; - } elseif ((($span) / $interval) < 5) { - $interval = $interval / 2; - } elseif ((($span) / $interval) > 10) { - $interval = $interval * 2; - } - - if (($interval -floor($interval) == 0.5) && ($interval != 0.5)) { - $interval = floor($interval); - } - - // just to be 100% sure that an interval of 0 is not returned some - // additional checks are performed - if ($interval == 0) { - $interval = ($span) / 5; - } - - if ($interval == 0) { - $interval = 1; - } - - $this->_labelOptions[$level]['interval'] = $interval; - } - } - } - - /** - * Get next label point - * - * @param doubt $currentLabel The current label, if omitted or false, the - * first is returned - * @param int $level The label level to get the next label from - * @return double The next label point - * @access private - */ - function _getNextLabel($currentLabel = false, $level = 1) - { - if (!isset($this->_labelOptions[$level])) { - return false; - } - - if (is_array($this->_labelOptions[$level]['interval'])) { - if ($currentLabel === false) { - reset($this->_labelOptions[$level]['interval']); - } - - if (list(, $label) = each($this->_labelOptions[$level]['interval'])) { - return $label; - } else { - return false; - } - } else { - $li = $this->_labelInterval($level); - if (($this->_axisSpan == 0) || ($this->_axisValueSpan == 0) || - ($li == 0) - ) { - return false; - } - - $labelInterval = $this->_axisSpan / ($this->_axisValueSpan / $li); - - if ($labelInterval == 0) { - return false; - } - - if ($currentLabel === false) { - $label = ((int) ($this->_getMinimum() / $labelInterval)) * - $labelInterval - $labelInterval; - while ($label < $this->_getMinimum()) { - $label += $labelInterval; - } - return $label; - } else { - if ($currentLabel + $labelInterval > $this->_getMaximum()) { - return false; - } else { - return $currentLabel + $labelInterval; - } - } - } - } - - /** - * Get the interval with which labels are shown on the axis. - * - * If explicitly defined this will be calucated to an approximate best. - * - * @param int $level The label level to get the label interval for - * @return double The label interval - * @access private - */ - function _labelInterval($level = 1) - { - if ((!isset($this->_labelOptions[$level])) || - (!isset($this->_labelOptions[$level]['interval'])) - ) { - return 1; - } - - return (is_array($this->_labelOptions[$level]['interval']) - ? 1 - : $this->_labelOptions[$level]['interval'] - ); - } - - /** - * Get the size in pixels of the axis. - * - * For an x-axis this is the width of the axis including labels, and for an - * y-axis it is the corrresponding height - * - * @return int The size of the axis - * @access private - */ - function _size() - { - if (!$this->_visible) { - return 0; - } - - if ($this->_fixedSize !== false) { - return $this->_fixedSize; - } - - krsort($this->_labelOptions); - - $totalMaxSize = 0; - - foreach ($this->_labelOptions as $level => $labelOptions) { - if ((isset($labelOptions['showoffset'])) && ($labelOptions['showoffset'] === true)) { - $this->_labelOptions[$level]['offset'] += $totalMaxSize; - } elseif (!isset($this->_labelOptions[$level]['offset'])) { - $this->_labelOptions[$level]['offset'] = 0; - } - if ( - (isset($labelOptions['showtext'])) && - ($labelOptions['showtext'] === true) && - ( - (!isset($labelOptions['position'])) || - ($labelOptions['position'] == 'outside') - ) - ) { - if (isset($labelOptions['font'])) { - $font = $this->_getFont($labelOptions['font']); - } else { - if ($this->_defaultFontOptions !== false) { - $font = $this->_defaultFontOptions; - } else { - $font = $this->_getFont(); - } - } - $this->_canvas->setFont($font); - - $value = false; - $maxSize = 0; - while (($value = $this->_getNextLabel($value, $level)) !== false) { - if ((abs($value) > 0.0001) && ($value > $this->_getMinimum()) && - ($value < $this->_getMaximum())) - { - if (is_object($this->_dataPreProcessor)) { - $labelText = $this->_dataPreProcessor->_process($value); - } elseif (isset($labelOptions['format'])) { - $labelText = sprintf($labelOptions['format'], $value); - } elseif (isset($labelOptions['dateformat'])) { - $labelText = date($labelOptions['dateformat'], $value); - } else { - $labelText = $value; - } - - if ((($this->_type == IMAGE_GRAPH_AXIS_X) && (!$this->_transpose)) || - (($this->_type != IMAGE_GRAPH_AXIS_X) && ($this->_transpose))) - { - $maxSize = max($maxSize, $this->_canvas->textHeight($labelText)); - } else { - $maxSize = max($maxSize, $this->_canvas->textWidth($labelText)); - } - } - } - if ((isset($labelOptions['showoffset'])) && ($labelOptions['showoffset'] === true)) { - $totalMaxSize += $maxSize; - } else { - $totalMaxSize = max($totalMaxSize, $maxSize); - } - } - } - - if ($this->_title) { - $this->_canvas->setFont($this->_getTitleFont()); - - if ((($this->_type == IMAGE_GRAPH_AXIS_X) && (!$this->_transpose)) || - (($this->_type != IMAGE_GRAPH_AXIS_X) && ($this->_transpose))) - { - $totalMaxSize += $this->_canvas->textHeight($this->_title); - } else { - $totalMaxSize += $this->_canvas->textWidth($this->_title); - } - $totalMaxSize += 10; - } - - return $totalMaxSize + 3; - } - - /** - * Adds a mark to the axis at the specified value - * - * @param double $value The value - * @param double $value2 The second value (for a ranged mark) - */ - function addMark($value, $value2 = false, $text = false) - { - if ($value2 === false) { - $this->_marks[] = $value; - } else { - $this->_marks[] = array($value, $value2); - } - } - - /** - * Is the axis numeric or not? - * - * @return bool True if numeric, false if not - * @access private - */ - function _isNumeric() - { - return true; - } - - /** - * Set the major tick appearance. - * - * The positions are specified in pixels relative to the axis, meaning that - * a value of -1 for start will draw the major tick 'line' starting at 1 - * pixel outside (negative) value the axis (i.e. below an x-axis and to the - * left of a normal y-axis). - * - * @param int $start The start position relative to the axis - * @param int $end The end position relative to the axis - * @param int $level The label level to set the tick options for - * @since 0.3.0dev2 - */ - function setTickOptions($start, $end, $level = 1) - { - if (!isset($this->_labelOptions[$level])) { - $this->_labelOptions[$level] = array(); - } - - $this->_labelOptions[$level]['tick'] = array( - 'start' => $start, - 'end' => $end - ); - } - - /** - * Invert the axis direction - * - * If the minimum values are normally displayed fx. at the bottom setting - * axis inversion to true, will cause the minimum values to be displayed at - * the top and maximum at the bottom. - * - * @param bool $invert True if the axis is to be inverted, false if not - * @since 0.3.0dev3 - */ - function setInverted($invert) - { - $this->_invert = $invert; - } - - /** - * Set axis intersection. - * - * Sets the value at which the axis intersects other axis, fx. at which Y- - * value the x-axis intersects the y-axis (normally at 0). - * - * Possible values are 'default', 'min', 'max' or a number between axis min - * and max (the value will automatically be limited to this range). - * - * For a coordinate system with 2 y-axis, the x-axis can either intersect - * the primary or the secondary y-axis. To make the x-axis intersect the - * secondary y-axis at a given value pass IMAGE_GRAPH_AXIS_Y_SECONDARY as - * second parameter. - * - * @param mixed $intersection The value at which the axis intersect the - * 'other' axis - * @param mixed $axis The axis to intersect. Only applies to x-axis with - * both a primary and secondary y-axis available. - * @since 0.3.0dev2 - */ - function setAxisIntersection($intersection, $axis = 'default') - { - if ($axis == 'x') { - $axis = IMAGE_GRAPH_AXIS_X; - } elseif ($axis == 'y') { - $axis = IMAGE_GRAPH_AXIS_Y; - } elseif ($axis == 'ysec') { - $axis = IMAGE_GRAPH_AXIS_Y_SECONDARY; - } - $this->_intersect = array( - 'value' => $intersection, - 'axis' => $axis - ); - } - - /** - * Get axis intersection data. - * - * @return array An array with the axis intersection data. - * @since 0.3.0dev2 - * @access private - */ - function _getAxisIntersection() - { - $value = $this->_intersect['value']; - $axis = $this->_intersect['axis']; - if (($this->_type == IMAGE_GRAPH_AXIS_Y) - || ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) - ) { - $axis = IMAGE_GRAPH_AXIS_X; - } elseif ($axis == 'default') { - $axis = IMAGE_GRAPH_AXIS_Y; - } - - if ($value === 'default') { - switch ($this->_type) { - case IMAGE_GRAPH_AXIS_Y: - $value = 'min'; - break; - case IMAGE_GRAPH_AXIS_Y_SECONDARY: - $value = 'max'; - break; - case IMAGE_GRAPH_AXIS_X: - $value = 0; - break; - } - } - - return array('value' => $value, 'axis' => $axis); - } - - /** - * Resets the elements - * - * @access private - */ - function _reset() - { - parent::_reset(); - $this->_labelText = array(); - } - - /** - * Output an axis tick mark. - * - * @param int $value The value to output - * @param int $level The label level to draw the tick for - * @access private - */ - function _drawTick($value, $level = 1) - { - if (isset($this->_labelOptions[$level])) { - $labelOptions = $this->_labelOptions[$level]; - $labelPosition = $this->_point($value); - - if (isset($labelOptions['offset'])) { - $offset = $labelOptions['offset']; - } else { - $offset = 0; - } - - if ((isset($labelOptions['showtext'])) && ($labelOptions['showtext'] === true)) { - if (is_object($this->_dataPreProcessor)) { - $labelText = $this->_dataPreProcessor->_process($value); - } elseif (isset($labelOptions['format'])) { - $labelText = sprintf($labelOptions['format'], $value); - } elseif (isset($labelOptions['dateformat'])) { - $labelText = date($labelOptions['dateformat'], $value); - } else { - $labelText = $value; - } - - if (!in_array($labelText, $this->_labelText)) { - $this->_labelText[] = $labelText; - - if (isset($labelOptions['font'])) { - $font = $this->_getFont($labelOptions['font']); - } else { - if ($this->_defaultFontOptions !== false) { - $font = $this->_defaultFontOptions; - } else { - $font = $this->_getFont(); - } - } - $this->_canvas->setFont($font); - - if ( - (isset($labelOptions['position'])) && - ($labelOptions['position'] == 'inside') - ) { - $labelInside = true; - } else { - $labelInside = false; - } - - if ($this->_type == IMAGE_GRAPH_AXIS_Y) { - if ($this->_transpose) { - if ($labelInside) { - $this->write( - $labelPosition, - $this->_top - 3 - $offset, - $labelText, - IMAGE_GRAPH_ALIGN_BOTTOM | IMAGE_GRAPH_ALIGN_CENTER_X, - $font - ); - } else { - $this->write( - $labelPosition, - $this->_top + 3 + $offset, - $labelText, - IMAGE_GRAPH_ALIGN_TOP | IMAGE_GRAPH_ALIGN_CENTER_X, - $font - ); - } - } - else { - if ($labelInside) { - $this->write( - $this->_right + 3 + $offset, - $labelPosition, - $labelText, - IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, - $font - ); - } else { - $this->write( - $this->_right - 3 - $offset, - $labelPosition, - $labelText, - IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_RIGHT, - $font - ); - } - } - } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) { - if ($this->_transpose) { - if ($labelInside) { - $this->write( - $labelPosition, - $this->_bottom + 3 + $offset, - $labelText, - IMAGE_GRAPH_ALIGN_TOP | IMAGE_GRAPH_ALIGN_CENTER_X, - $font - ); - } else { - $this->write( - $labelPosition, - $this->_bottom - 3 - $offset, - $labelText, - IMAGE_GRAPH_ALIGN_BOTTOM | IMAGE_GRAPH_ALIGN_CENTER_X, - $font - ); - } - } - else { - if ($labelInside) { - $this->write( - $this->_left - 3 - $offset, - $labelPosition, - $labelText, - IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_RIGHT, - $font - ); - } else { - $this->write( - $this->_left + 3 + $offset, - $labelPosition, - $labelText, - IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, - $font - ); - } - } - } else { - if ($this->_transpose) { - if ($labelInside) { - $this->write( - $this->_right + 3 + $offset, - $labelPosition, - $labelText, - IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, - $font - ); - } else { - $this->write( - $this->_right - 3 - $offset, - $labelPosition, - $labelText, - IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_RIGHT, - $font - ); - } - } - else { - if ($labelInside === true) { - $this->write( - $labelPosition, - $this->_top - 3 - $offset, - $labelText, - IMAGE_GRAPH_ALIGN_CENTER_X | IMAGE_GRAPH_ALIGN_BOTTOM, - $font - ); - } else { - $this->write( - $labelPosition, - $this->_top + 3 + $offset, - $labelText, - IMAGE_GRAPH_ALIGN_CENTER_X | IMAGE_GRAPH_ALIGN_TOP, - $font - ); - } - } - } - } - } - - if (isset($this->_labelOptions[$level]['tick'])) { - $tickStart = $this->_labelOptions[$level]['tick']['start']; - $tickEnd = $this->_labelOptions[$level]['tick']['end']; - } else { - $tickStart = -2; - $tickEnd = 2; - } - - $this->_getLineStyle(); - if ($this->_type == IMAGE_GRAPH_AXIS_Y) { - if ($tickStart === 'auto') { - $tickStart = -$offset; - } - if ($this->_transpose) { - $this->_canvas->line( - array( - 'x0' => $labelPosition, - 'y0' => $this->_top + $tickStart, - 'x1' => $labelPosition, - 'y1' => $this->_top + $tickEnd - ) - ); - } - else { - $this->_canvas->line( - array( - 'x0' => $this->_right + $tickStart, - 'y0' => $labelPosition, - 'x1' => $this->_right + $tickEnd, - 'y1' => $labelPosition - ) - ); - } - } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) { - if ($tickStart === 'auto') { - $tickStart = $offset; - } - if ($this->_transpose) { - $this->_canvas->line( - array( - 'x0' => $labelPosition, - 'y0' => $this->_bottom - $tickStart, - 'x1' => $labelPosition, - 'y1' => $this->_bottom - $tickEnd - ) - ); - } - else { - $this->_canvas->line( - array( - 'x0' => $this->_left - $tickStart, - 'y0' => $labelPosition, - 'x1' => $this->_left - $tickEnd, - 'y1' => $labelPosition - ) - ); - } - } else { - if ($tickStart === 'auto') { - $tickStart = $offset; - } - if ($this->_transpose) { - $this->_canvas->line( - array( - 'x0' => $this->_right + $tickStart, - 'y0' => $labelPosition, - 'x1' => $this->_right + $tickEnd, - 'y1' => $labelPosition - ) - ); - } - else { - $this->_canvas->line( - array( - 'x0' => $labelPosition, - 'y0' => $this->_top - $tickStart, - 'x1' => $labelPosition, - 'y1' => $this->_top - $tickEnd - ) - ); - } - } - } - } - - /** - * Draws axis lines. - * - * @access private - */ - function _drawAxisLines() - { - if ($this->_type == IMAGE_GRAPH_AXIS_X) { - $this->_getLineStyle(); - $this->_getFillStyle(); - - if ($this->_transpose) { - $data = array( - 'x0' => $this->_right, - 'y0' => $this->_top, - 'x1' => $this->_right, - 'y1' => $this->_bottom - ); - } else { - $data = array( - 'x0' => $this->_left, - 'y0' => $this->_top, - 'x1' => $this->_right, - 'y1' => $this->_top - ); - } - - if ($this->_showArrow) { - $data['end1'] = 'arrow2'; - $data['size1'] = 7; - } - - $this->_canvas->line($data); - - if ($this->_title) { - if (!$this->_transpose) { - $y = $this->_bottom; - $x = $this->_left + $this->width() / 2; - $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_CENTER_X + IMAGE_GRAPH_ALIGN_BOTTOM, $this->_getTitleFont()); - } - else { - $y = $this->_top + $this->height() / 2; - $x = $this->_left; - $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_LEFT + IMAGE_GRAPH_ALIGN_CENTER_Y, $this->_getTitleFont()); - } - } - } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) { - $this->_getLineStyle(); - $this->_getFillStyle(); - - if ($this->_transpose) { - $data = array( - 'x0' => $this->_left, - 'y0' => $this->_bottom, - 'x1' => $this->_right, - 'y1' => $this->_bottom - ); - } else { - $data = array( - 'x0' => $this->_left, - 'y0' => $this->_bottom, - 'x1' => $this->_left, - 'y1' => $this->_top - ); - } - if ($this->_showArrow) { - $data['end1'] = 'arrow2'; - $data['size1'] = 7; - } - $this->_canvas->line($data); - - if ($this->_title) { - if ($this->_transpose) { - $y = $this->_top; - $x = $this->_left + $this->width() / 2; - $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_CENTER_X + IMAGE_GRAPH_ALIGN_TOP, $this->_getTitleFont()); - } - else { - $y = $this->_top + $this->height() / 2; - $x = $this->_right; - $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_RIGHT + IMAGE_GRAPH_ALIGN_CENTER_Y, $this->_getTitleFont()); - } - } - } else { - $this->_getLineStyle(); - $this->_getFillStyle(); - - if ($this->_transpose) { - $data = array( - 'x0' => $this->_left, - 'y0' => $this->_top, - 'x1' => $this->_right, - 'y1' => $this->_top - ); - } else { - $data = array( - 'x0' => $this->_right, - 'y0' => $this->_bottom, - 'x1' => $this->_right, - 'y1' => $this->_top - ); - } - if ($this->_showArrow) { - $data['end1'] = 'arrow2'; - $data['size1'] = 7; - } - $this->_canvas->line($data); - - if ($this->_title) { - if ($this->_transpose) { - $y = $this->_bottom; - $x = $this->_left + $this->width() / 2; - $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_CENTER_X + IMAGE_GRAPH_ALIGN_BOTTOM, $this->_getTitleFont()); - } - else { - $y = $this->_top + $this->height() / 2; - $x = $this->_left; - $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_LEFT + IMAGE_GRAPH_ALIGN_CENTER_Y, $this->_getTitleFont()); - } - } - } - } - - /** - * Causes the object to update all sub elements coordinates - * - * (Image_Graph_Common, does not itself have coordinates, this is basically - * an abstract method) - * - * @access private - */ - function _updateCoords() - { - parent::_updateCoords(); - $this->_calcDelta(); - } - - /** - * Output the axis - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - $this->_canvas->startGroup(get_class($this)); - - if (parent::_done() === false) { - return false; - } - - $this->_drawAxisLines(); - - $this->_canvas->startGroup(get_class($this) . '_ticks'); - ksort($this->_labelOptions); - foreach ($this->_labelOptions as $level => $labelOption) { - $value = false; - while (($value = $this->_getNextLabel($value, $level)) !== false) { - if ((((abs($value) > 0.0001) || ($this->_showLabelZero)) && - (($value > $this->_getMinimum()) || ($this->_showLabelMinimum)) && - (($value < $this->_getMaximum()) || ($this->_showLabelMaximum))) && - ($value >= $this->_getMinimum()) && ($value <= $this->_getMaximum()) - ) { - $this->_drawTick($value, $level); - } - } - } - $this->_canvas->endGroup(); - - $tickStart = -3; - $tickEnd = 2; - - foreach ($this->_marks as $mark) { - if (is_array($mark)) { - if ($this->_type == IMAGE_GRAPH_AXIS_X) { - if ($this->_transpose) { - $x0 = $this->_right + $tickStart; - $y0 = $this->_point($mark[1]); - $x1 = $this->_right + $tickEnd; - $y1 = $this->_point($mark[0]); - } - else { - $x0 = $this->_point($mark[0]); - $y0 = $this->_top + $tickStart; - $x1 = $this->_point($mark[1]); - $y1 = $this->_top + $tickEnd; - } - } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y) { - if ($this->_transpose) { - $x0 = $this->_point($mark[0]); - $y0 = $this->_top + $tickStart; - $x1 = $this->_point($mark[1]); - $y1 = $this->_top + $tickEnd; - } - else { - $x0 = $this->_right + $tickStart; - $y0 = $this->_point($mark[1]); - $x1 = $this->_right + $tickEnd; - $y1 = $this->_point($mark[0]); - } - } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) { - if ($this->_transpose) { - $x0 = $this->_point($mark[0]); - $y0 = $this->_bottom + $tickStart; - $x1 = $this->_point($mark[1]); - $y1 = $this->_bottom + $tickEnd; - } - else { - $x0 = $this->_left + $tickStart; - $y0 = $this->_point($mark[1]); - $x1 = $this->_left + $tickEnd; - $y1 = $this->_point($mark[0]); - } - } - $this->_getFillStyle(); - $this->_getLineStyle(); - $this->_canvas->rectangle(array('x0' => $x0, 'y0' => $y0, 'x1' => $x1, 'y1' => $y1)); - } else { - if ($this->_type == IMAGE_GRAPH_AXIS_X) { - if ($this->_transpose) { - $x0 = $this->_right + 5; - $y0 = $this->_point($mark); - $x1 = $this->_right + 15; - $y1 = $y0; - } - else { - $x0 = $this->_point($mark); - $y0 = $this->_top - 5; - $x1 = $x0; - $y1 = $this->_top - 15; - } - } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y) { - if ($this->_transpose) { - $x0 = $this->_point($mark); - $y0 = $this->_top - 5; - $x1 = $x0; - $y1 = $this->_top - 15; - } - else { - $x0 = $this->_right + 5; - $y0 = $this->_point($mark); - $x1 = $this->_right + 15; - $y1 = $y0; - } - } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) { - if ($this->_transpose) { - $x0 = $this->_point($mark); - $y0 = $this->_bottom + 5; - $x1 = $x0; - $y1 = $this->_bottom + 15; - } - else { - $x0 = $this->_left - 5; - $y0 = $this->_point($mark); - $x1 = $this->_left - 15; - $y1 = $y0; - } - } - $this->_getFillStyle(); - $this->_getLineStyle(); - $this->_canvas->line( - array( - 'x0' => $x0, - 'y0' => $y0, - 'x1' => $x1, - 'y1' => $y1, - 'end0' => 'arrow2', - 'size0' => 5 - ) - ); - } - } - $this->_canvas->endGroup(); - - return true; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Axis.php,v 1.35 2006/02/28 22:48:07 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plotarea/Element.php + */ +require_once 'Image/Graph/Plotarea/Element.php'; + +/** + * Diplays a normal linear axis (either X- or Y-axis). + * + * @category Images + * @package Image_Graph + * @subpackage Axis + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ + class Image_Graph_Axis extends Image_Graph_Plotarea_Element +{ + + /** + * The type of the axis, possible values are: + *
    + *
  • IMAGE_GRAPH_AXIS_X / IMAGE_GRAPH_AXIS_HORIZONTAL + *
  • IMAGE_GRAPH_AXIS_Y / IMAGE_GRAPH_AXIS_VERTICAL / + * IMAGE_GRAPH_AXIS_Y_SECONDARY + *
+ * @var int + * @access private + */ + var $_type; + + /** + * The minimum value the axis displays + * @var int + * @access private + */ + var $_minimum = false; + + /** + * The minimum value the axis has been explicitly set by the user + * @var bool + * @access private + */ + var $_minimumSet = false; + + /** + * The maximum value the axis displays + * @var int + * @access private + */ + var $_maximum = false; + + /** + * The maximum value the axis has been explicitly set by the user + * @var bool + * @access private + */ + var $_maximumSet = false; + + /** + * The value span of the axis. + * This is primarily included for performance reasons + * @var double + * @access private + */ + var $_axisSpan = false; + + /** + * The value span of the axis. + * This is primarily included for performance reasons + * @var double + * @access private + */ + var $_axisValueSpan = false; + + /** + * The axis padding. + * The index 'low' specifies the padding for the low axis values (when not + * inverted), i.e. to the left on an x-axis and on the bottom of an y-axis, + * vice versa for 'high'. + * + * Axis padding does not make sense on a normal linear y-axis with a 'y-min' + * of 0 since this corresponds to displaying a small part of the y-axis + * below 0! + * + * @var array + * @access private + */ + var $_axisPadding = array('low' => 0, 'high' => 0); + + /** + * The number of "pixels" representing 1 unit on the axis + * + * This is primarily included for performance reasons + * @var double + * @access private + */ + var $_delta = false; + + /** + * Specify if the axis should label the minimum value + * @var bool + * @access private + */ + var $_showLabelMinimum = true; + + /** + * Specify if the axis should label 0 (zero) + * @var bool + * @access private + */ + var $_showLabelZero = false; + + /** + * Specify if the axis should label the maximum value + * @var bool + * @access private + */ + var $_showLabelMaximum = true; + + /** + * Show arrow heads at the 'end' of the axis, default: false + * @var bool + * @access private + */ + var $_showArrow = false; + + /** + * Intersection data of axis + * @var array + * @access private + */ + var $_intersect = array('value' => 'default', 'axis' => 'default'); + + /** + * The fixed size of the axis (i.e. width for y-axis, height for x-axis) + * @var mixed + * @access private + */ + var $_fixedSize = false; + + /** + * The label options + * + * Should text be shows, preferences for ticks. The indexes start at level + * 1, which is chosen for readability + * @var array + * @access private + */ + var $_labelOptions = array( + 1 => array( + 'interval' => 1, + 'type' => 'auto', + 'tick' => array( + 'start' => -2, + 'end' => 2, + 'color' => false // default color + ), + 'showtext' => true, + 'showoffset' => false, + 'font' => array(), + 'offset' => 0, + 'position' => 'outside', + ) + ); + + /** + * The labels that are shown. + * + * This is used to make values show only once... + * @access private + */ + var $_labelText = array(); + + /** + * A data preprocessor for formatting labels, fx showing dates as a standard + * date instead of Unix time stamp + * @var Image_Graph_DatePreProcessor + * @access private + * @see Image_Graph_DataPreProcessor + */ + var $_dataPreProcessor = null; + + /** + * Point marked in the axis + * @var array + * @access private + */ + var $_marks = array(); + + /** + * Specifies whether the values should be 'pushed' by 0.5 + * @var bool + * @access private + */ + var $_pushValues = false; + + /** + * The title of this axis + * @var string + * @access private + */ + var $_title = ''; + + /** + * The font used for the title of this axis + * @var Image_Graph_Font + * @access private + */ + var $_titleFont = false; + + /** + * Invert the axis (i.e. if an y-axis normally displays minimum values at + * the bottom, they are not displayed at the top + * @var bool + * @access private + * @since 0.3.0dev3 + */ + var $_invert = false; + + /** + * Transpose the axis (i.e. is a normal y-axis transposed, so thats it's not show + * vertically as normally expected, but instead horizontally) + * @var bool + * @access private + */ + var $_transpose = false; + + /** + * Image_Graph_Axis [Constructor]. + * Normally a manual creation should not be necessary, axis are created + * automatically by the {@link Image_Graph_Plotarea} constructor unless + * explicitly defined otherwise + * + * @param int $type The type (direction) of the Axis, use IMAGE_GRAPH_AXIS_X + * for an X-axis (default, may be omitted) and IMAGE_GRAPH_AXIS_Y for Y- + * axis) + */ + function Image_Graph_Axis($type = IMAGE_GRAPH_AXIS_X) + { + parent::Image_Graph_Element(); + $this->_type = $type; + $this->_fillStyle = 'black'; + } + + /** + * Push the values by 0.5 (for bar and step chart) + * + * @access private + */ + function _pushValues() + { + $this->_pushValues = true; + } + + /** + * Sets the axis padding for a given position ('low' or 'high') + * @param string $where The position + * @param int $value The number of pixels to "pad" + * @access private + */ + function _setAxisPadding($where, $value) + { + $this->_axisPadding[$where] = $value; + } + + /** + * Gets the font of the title. + * + * If not font has been set, the parent font is propagated through it's + * children. + * + * @return array An associated array used for canvas + * @access private + */ + function _getTitleFont() + { + if ($this->_titleFont === false) { + if ($this->_defaultFontOptions !== false) { + return $this->_defaultFontOptions; + } else { + return $this->_getFont(); + } + } else { + if (is_object($this->_titleFont)) { + return $this->_titleFont->_getFont(); + } elseif (is_array($this->_titleFont)) { + return $this->_getFont($this->_titleFont); + } elseif (is_int($this->_titleFont)) { + return $this->_getFont(array('size' => $this->_titleFont)); + } + } + return array(); + } + + /** + * Shows a label for the the specified values. + * + * Allowed values are combinations of: + *
    + *
  • IMAGE_GRAPH_LABEL_MINIMUM + *
  • IMAGE_GRAPH_LABEL_ZERO + *
  • IMAGE_GRAPH_LABEL_MAXIMUM + *
+ * By default none of these are shows on the axis + * + * @param int $value The values to show labels for + */ + function showLabel($value) + { + $this->_showLabelMinimum = ($value & IMAGE_GRAPH_LABEL_MINIMUM); + $this->_showLabelZero = ($value & IMAGE_GRAPH_LABEL_ZERO); + $this->_showLabelMaximum = ($value & IMAGE_GRAPH_LABEL_MAXIMUM); + } + + /** + * Sets a data preprocessor for formatting the axis labels + * + * @param Image_Graph_DataPreprocessor $dataPreProcessor The data preprocessor + * @see Image_Graph_DataPreprocessor + */ + function setDataPreProcessor(& $dataPreProcessor) + { + $this->_dataPreProcessor =& $dataPreProcessor; + } + + /** + * Gets the minimum value the axis will show + * + * @return double The minumum value + * @access private + */ + function _getMinimum() + { + return $this->_minimum; + } + + /** + * Gets the maximum value the axis will show + * + * @return double The maximum value + * @access private + */ + function _getMaximum() + { + return $this->_maximum; + } + + /** + * Sets the minimum value the axis will show + * + * @param double $minimum The minumum value to use on the axis + * @access private + */ + function _setMinimum($minimum) + { + if ($this->_minimum === false) { + $this->forceMinimum($minimum, false); + } else { + $this->forceMinimum(min($this->_minimum, $minimum), false); + } + } + + /** + * Sets the maximum value the axis will show + * + * @param double $maximum The maximum value to use on the axis + * @access private + */ + function _setMaximum($maximum) + { + if ($this->_maximum === false) { + $this->forceMaximum($maximum, false); + } else { + $this->forceMaximum(max($this->_maximum, $maximum), false); + } + } + + /** + * Forces the minimum value of the axis + * + * @param double $minimum The minumum value to use on the axis + * @param bool $userEnforce This value should not be set, used internally + */ + function forceMinimum($minimum, $userEnforce = true) + { + if (($userEnforce) || (!$this->_minimumSet)) { + $this->_minimum = $minimum; + $this->_minimumSet = $userEnforce; + } + $this->_calcLabelInterval(); + } + + /** + * Forces the maximum value of the axis + * + * @param double $maximum The maximum value to use on the axis + * @param bool $userEnforce This value should not be set, used internally + */ + function forceMaximum($maximum, $userEnforce = true) + { + if (($userEnforce) || (!$this->_maximumSet)) { + $this->_maximum = $maximum; + $this->_maximumSet = $userEnforce; + } + $this->_calcLabelInterval(); + } + + /** + * Show an arrow head on the 'end' of the axis + */ + function showArrow() + { + $this->_showArrow = true; + } + + /** + * Do not show an arrow head on the 'end' of the axis (default) + */ + function hideArrow() + { + $this->_showArrow = false; + } + + /** + * Return the label distance. + * + * @param int $level The label level to return the distance of + * @return int The distance between 2 adjacent labels + * @access private + */ + function _labelDistance($level = 1) + { + $l1 = $this->_getNextLabel(false, $level); + $l2 = $this->_getNextLabel($l1, $level);; + return abs($this->_point($l2) - $this->_point($l1)); + } + + /** + * Sets an interval for when labels are shown on the axis. + * + * By default 'auto' is used, forcing the axis to calculate a approximate + * best label interval to be used. Specify an array to use user-defined + * values for labels. + * + * @param mixed $labelInterval The interval with which labels are shown + * @param int $level The label level to set the interval on + */ + function setLabelInterval($labelInterval = 'auto', $level = 1) + { + if (!isset($this->_labelOptions[$level])) { + $this->_labelOptions[$level] = array(); + } + + if ($labelInterval === 'auto') { + $this->_labelOptions[$level]['type'] = 'auto'; + $this->_calcLabelInterval(); + } else { + $this->_labelOptions[$level]['type'] = 'manual'; + $this->_labelOptions[$level]['interval'] = $labelInterval; + } + } + + /** + * Sets options for the label at a specific level. + * + * Possible options are: + * + * 'showtext' true or false whether label text should be shown or not + * + * 'showoffset' should the label be shown at an offset, i.e. should the + * label be shown at a position so that it does not overlap with prior + * levels. Only applies to multilevel labels with text + * + * 'font' The font options as an associated array + * + * 'position' The position at which the labels are written ('inside' or + * 'outside' the axis). NB! This relative position only applies to the + * default location of the axis, i.e. if an x-axis is inverted then + * 'outside' still refers to the "left" side of a normal y-axis (since this + * is normally 'outside') but the actual output will be labels on the + * "inside"! + * + * 'format' To format the label text according to a sprintf statement + * + * 'dateformat' To format the label as a date, fx. j. M Y = 29. Jun 2005 + * + * @param string $option The label option name (see detailed description + * for possible values) + * @param mixed $value The value for the option + * @param int $level The label level to set the interval on + */ + function setLabelOption($option, $value, $level = 1) + { + if (!isset($this->_labelOptions[$level])) { + $this->_labelOptions[$level] = array('type' => 'auto'); + } + + $this->_labelOptions[$level][$option] = $value; + } + + /** + * Sets options for the label at a specific level. + * + * The possible options are specified in {@link Image_Graph_Axis:: + * setLabelOption()}. + * + * @param array $options An assciated array with label options + * @param int $level The label level to set the interval on + */ + function setLabelOptions($options, $level = 1) + { + if (is_array($options)) { + if (isset($this->_labelOptions[$level])) { + $this->_labelOptions[$level] = array_merge($this->_labelOptions[$level], $options); + } else { + $this->_labelOptions[$level] = $options; + } + + } + } + + /** + * Sets the title of this axis. + * + * This is used as an alternative (maybe better) method, than using layout's + * for axis-title generation. + * + * To use the current propagated font, but just set it vertically, simply + * pass 'vertical' as second parameter for vertical alignment down-to-up or + * 'vertical2' for up-to-down alignment. + * + * @param string $title The title of this axis + * @param Image_Graph_Font $font The font used for the title + * @since 0.3.0dev2 + */ + function setTitle($title, $font = false) + { + $this->_title = $title; + if ($font === 'vertical') { + $this->_titleFont = array('vertical' => true, 'angle' => 90); + } elseif ($font === 'vertical2') { + $this->_titleFont = array('vertical' => true, 'angle' => 270); + } else { + $this->_titleFont =& $font; + } + } + + /** + * Sets a fixed "size" for the axis. + * + * If the axis is any type of y-axis the size relates to the width of the + * axis, if an x-axis is concerned the size is the height. + * + * @param int $size The fixed size of the axis + * @since 0.3.0dev5 + */ + function setFixedSize($size) + { + $this->_fixedSize = $size; + } + + /** + * Preprocessor for values, ie for using logarithmic axis + * + * @param double $value The value to preprocess + * @return double The preprocessed value + * @access private + */ + function _value($value) + { + return $value - $this->_getMinimum() + ($this->_pushValues ? 0.5 : 0); + } + + /** + * Apply the dataset to the axis + * + * @param Image_Graph_Dataset $dataset The dataset + * @access private + */ + function _applyDataset(&$dataset) + { + if ($this->_type == IMAGE_GRAPH_AXIS_X) { + $this->_setMinimum($dataset->minimumX()); + $this->_setMaximum($dataset->maximumX()); + } else { + $this->_setMinimum($dataset->minimumY()); + $this->_setMaximum($dataset->maximumY()); + } + } + + /** + * Get the pixel position represented by a value on the canvas + * + * @param double $value the value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _point($value) + { + if ((($this->_type == IMAGE_GRAPH_AXIS_X) && (!$this->_transpose)) || + (($this->_type != IMAGE_GRAPH_AXIS_X) && ($this->_transpose))) + { + if ($this->_invert) { + return max($this->_left, $this->_right - $this->_axisPadding['high'] - $this->_delta * $this->_value($value)); + } else { + return min($this->_right, $this->_left + $this->_axisPadding['low'] + $this->_delta * $this->_value($value)); + } + } else { + if ($this->_invert) { + return min($this->_bottom, $this->_top + $this->_axisPadding['high'] + $this->_delta * $this->_value($value)); + } else { + return max($this->_top, $this->_bottom - $this->_axisPadding['low'] - $this->_delta * $this->_value($value)); + } + } + } + + + /** + * Get the axis intersection pixel position + * + * This is only to be called prior to output! I.e. between the user + * invokation of Image_Graph::done() and any actual output is performed. + * This is because it can change the axis range. + * + * @param double $value the intersection value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _intersectPoint($value) + { + + if (($value === 'min') || ($value < $this->_getMinimum())) { + if ($this->_type == IMAGE_GRAPH_AXIS_X) { + if ($this->_invert) { + return ($this->_transpose ? $this->_top : $this->_right); + } else { + return ($this->_transpose ? $this->_bottom : $this->_left); + } + } else { + if ($this->_invert) { + return ($this->_transpose ? $this->_right : $this->_top); + } else { + return ($this->_transpose ? $this->_left : $this->_bottom); + } + } + } elseif (($value === 'max') || ($value > $this->_getMaximum())) { + if ($this->_type == IMAGE_GRAPH_AXIS_X) { + if ($this->_invert) { + return ($this->_transpose ? $this->_bottom : $this->_left); + } else { + return ($this->_transpose ? $this->_top : $this->_right); + } + } else { + if ($this->_invert) { + return ($this->_transpose ? $this->_left : $this->_bottom); + } else { + return ($this->_transpose ? $this->_right : $this->_top); + } + } + } + + return $this->_point($value); + } + + /** + * Calculate the delta value (the number of pixels representing one unit + * on the axis) + * + * @return double The label interval + * @access private + */ + function _calcDelta() + { + if ($this->_axisValueSpan == 0) { + $this->_delta = false; + } elseif ($this->_type == IMAGE_GRAPH_AXIS_X) { + $this->_delta = (($this->_transpose ? $this->height() : $this->width()) - ($this->_axisPadding['low'] + $this->_axisPadding['high'])) / ($this->_axisValueSpan + ($this->_pushValues ? 1 : 0)); + } else { + $this->_delta = (($this->_transpose ? $this->width() : $this->height()) - ($this->_axisPadding['low'] + $this->_axisPadding['high'])) / ($this->_axisValueSpan + ($this->_pushValues ? 1 : 0)); + } + } + + /** + * Calculate the label interval + * + * If explicitly defined this will be calucated to an approximate best. + * + * @return double The label interval + * @access private + */ + function _calcLabelInterval() + { + $min = $this->_getMinimum(); + $max = $this->_getMaximum(); + + $this->_axisValueSpan = $this->_axisSpan = abs($max - $min); + + if ((!empty($min)) && (!empty($max)) && ($min > $max)) { + $this->_labelOptions[1]['interval'] = 1; + return true; + } + + $span = 0; + foreach($this->_labelOptions as $level => $labelOptions) { + if ((!isset($labelOptions['type'])) || ($labelOptions['type'] !== 'auto')) { + $span = false; + } elseif ($level == 1) { + $span = $this->_axisValueSpan; + } else { + $l1 = $this->_getNextLabel(false, $level - 1); + $l2 = $this->_getNextLabel($l1, $level - 1); + if ((!is_numeric($l1)) || (!is_numeric($l2))) { + $span == false; + } else { + $span = $l2 - $l1; + } + } + + if ($span !== false) { + $interval = pow(10, floor(log10($span))); + + if ($interval == 0) { + $interval = 1; + } + + if ((($span) / $interval) < 3) { + $interval = $interval / 4; + } elseif ((($span) / $interval) < 5) { + $interval = $interval / 2; + } elseif ((($span) / $interval) > 10) { + $interval = $interval * 2; + } + + if (($interval -floor($interval) == 0.5) && ($interval != 0.5)) { + $interval = floor($interval); + } + + // just to be 100% sure that an interval of 0 is not returned some + // additional checks are performed + if ($interval == 0) { + $interval = ($span) / 5; + } + + if ($interval == 0) { + $interval = 1; + } + + $this->_labelOptions[$level]['interval'] = $interval; + } + } + } + + /** + * Get next label point + * + * @param doubt $currentLabel The current label, if omitted or false, the + * first is returned + * @param int $level The label level to get the next label from + * @return double The next label point + * @access private + */ + function _getNextLabel($currentLabel = false, $level = 1) + { + if (!isset($this->_labelOptions[$level])) { + return false; + } + + if (is_array($this->_labelOptions[$level]['interval'])) { + if ($currentLabel === false) { + reset($this->_labelOptions[$level]['interval']); + } + + if (list(, $label) = each($this->_labelOptions[$level]['interval'])) { + return $label; + } else { + return false; + } + } else { + $li = $this->_labelInterval($level); + if (($this->_axisSpan == 0) || ($this->_axisValueSpan == 0) || + ($li == 0) + ) { + return false; + } + + $labelInterval = $this->_axisSpan / ($this->_axisValueSpan / $li); + + if ($labelInterval == 0) { + return false; + } + + if ($currentLabel === false) { + $label = ((int) ($this->_getMinimum() / $labelInterval)) * + $labelInterval - $labelInterval; + while ($label < $this->_getMinimum()) { + $label += $labelInterval; + } + return $label; + } else { + if ($currentLabel + $labelInterval > $this->_getMaximum()) { + return false; + } else { + return $currentLabel + $labelInterval; + } + } + } + } + + /** + * Get the interval with which labels are shown on the axis. + * + * If explicitly defined this will be calucated to an approximate best. + * + * @param int $level The label level to get the label interval for + * @return double The label interval + * @access private + */ + function _labelInterval($level = 1) + { + if ((!isset($this->_labelOptions[$level])) || + (!isset($this->_labelOptions[$level]['interval'])) + ) { + return 1; + } + + return (is_array($this->_labelOptions[$level]['interval']) + ? 1 + : $this->_labelOptions[$level]['interval'] + ); + } + + /** + * Get the size in pixels of the axis. + * + * For an x-axis this is the width of the axis including labels, and for an + * y-axis it is the corrresponding height + * + * @return int The size of the axis + * @access private + */ + function _size() + { + if (!$this->_visible) { + return 0; + } + + if ($this->_fixedSize !== false) { + return $this->_fixedSize; + } + + krsort($this->_labelOptions); + + $totalMaxSize = 0; + + foreach ($this->_labelOptions as $level => $labelOptions) { + if ((isset($labelOptions['showoffset'])) && ($labelOptions['showoffset'] === true)) { + $this->_labelOptions[$level]['offset'] += $totalMaxSize; + } elseif (!isset($this->_labelOptions[$level]['offset'])) { + $this->_labelOptions[$level]['offset'] = 0; + } + if ( + (isset($labelOptions['showtext'])) && + ($labelOptions['showtext'] === true) && + ( + (!isset($labelOptions['position'])) || + ($labelOptions['position'] == 'outside') + ) + ) { + if (isset($labelOptions['font'])) { + $font = $this->_getFont($labelOptions['font']); + } else { + if ($this->_defaultFontOptions !== false) { + $font = $this->_defaultFontOptions; + } else { + $font = $this->_getFont(); + } + } + $this->_canvas->setFont($font); + + $value = false; + $maxSize = 0; + while (($value = $this->_getNextLabel($value, $level)) !== false) { + if ((abs($value) > 0.0001) && ($value > $this->_getMinimum()) && + ($value < $this->_getMaximum())) + { + if (is_object($this->_dataPreProcessor)) { + $labelText = $this->_dataPreProcessor->_process($value); + } elseif (isset($labelOptions['format'])) { + $labelText = sprintf($labelOptions['format'], $value); + } elseif (isset($labelOptions['dateformat'])) { + $labelText = date($labelOptions['dateformat'], $value); + } else { + $labelText = $value; + } + + if ((($this->_type == IMAGE_GRAPH_AXIS_X) && (!$this->_transpose)) || + (($this->_type != IMAGE_GRAPH_AXIS_X) && ($this->_transpose))) + { + $maxSize = max($maxSize, $this->_canvas->textHeight($labelText)); + } else { + $maxSize = max($maxSize, $this->_canvas->textWidth($labelText)); + } + } + } + if ((isset($labelOptions['showoffset'])) && ($labelOptions['showoffset'] === true)) { + $totalMaxSize += $maxSize; + } else { + $totalMaxSize = max($totalMaxSize, $maxSize); + } + } + } + + if ($this->_title) { + $this->_canvas->setFont($this->_getTitleFont()); + + if ((($this->_type == IMAGE_GRAPH_AXIS_X) && (!$this->_transpose)) || + (($this->_type != IMAGE_GRAPH_AXIS_X) && ($this->_transpose))) + { + $totalMaxSize += $this->_canvas->textHeight($this->_title); + } else { + $totalMaxSize += $this->_canvas->textWidth($this->_title); + } + $totalMaxSize += 10; + } + + return $totalMaxSize + 3; + } + + /** + * Adds a mark to the axis at the specified value + * + * @param double $value The value + * @param double $value2 The second value (for a ranged mark) + */ + function addMark($value, $value2 = false, $text = false) + { + if ($value2 === false) { + $this->_marks[] = $value; + } else { + $this->_marks[] = array($value, $value2); + } + } + + /** + * Is the axis numeric or not? + * + * @return bool True if numeric, false if not + * @access private + */ + function _isNumeric() + { + return true; + } + + /** + * Set the major tick appearance. + * + * The positions are specified in pixels relative to the axis, meaning that + * a value of -1 for start will draw the major tick 'line' starting at 1 + * pixel outside (negative) value the axis (i.e. below an x-axis and to the + * left of a normal y-axis). + * + * @param int $start The start position relative to the axis + * @param int $end The end position relative to the axis + * @param int $level The label level to set the tick options for + * @since 0.3.0dev2 + */ + function setTickOptions($start, $end, $level = 1) + { + if (!isset($this->_labelOptions[$level])) { + $this->_labelOptions[$level] = array(); + } + + $this->_labelOptions[$level]['tick'] = array( + 'start' => $start, + 'end' => $end + ); + } + + /** + * Invert the axis direction + * + * If the minimum values are normally displayed fx. at the bottom setting + * axis inversion to true, will cause the minimum values to be displayed at + * the top and maximum at the bottom. + * + * @param bool $invert True if the axis is to be inverted, false if not + * @since 0.3.0dev3 + */ + function setInverted($invert) + { + $this->_invert = $invert; + } + + /** + * Set axis intersection. + * + * Sets the value at which the axis intersects other axis, fx. at which Y- + * value the x-axis intersects the y-axis (normally at 0). + * + * Possible values are 'default', 'min', 'max' or a number between axis min + * and max (the value will automatically be limited to this range). + * + * For a coordinate system with 2 y-axis, the x-axis can either intersect + * the primary or the secondary y-axis. To make the x-axis intersect the + * secondary y-axis at a given value pass IMAGE_GRAPH_AXIS_Y_SECONDARY as + * second parameter. + * + * @param mixed $intersection The value at which the axis intersect the + * 'other' axis + * @param mixed $axis The axis to intersect. Only applies to x-axis with + * both a primary and secondary y-axis available. + * @since 0.3.0dev2 + */ + function setAxisIntersection($intersection, $axis = 'default') + { + if ($axis == 'x') { + $axis = IMAGE_GRAPH_AXIS_X; + } elseif ($axis == 'y') { + $axis = IMAGE_GRAPH_AXIS_Y; + } elseif ($axis == 'ysec') { + $axis = IMAGE_GRAPH_AXIS_Y_SECONDARY; + } + $this->_intersect = array( + 'value' => $intersection, + 'axis' => $axis + ); + } + + /** + * Get axis intersection data. + * + * @return array An array with the axis intersection data. + * @since 0.3.0dev2 + * @access private + */ + function _getAxisIntersection() + { + $value = $this->_intersect['value']; + $axis = $this->_intersect['axis']; + if (($this->_type == IMAGE_GRAPH_AXIS_Y) + || ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) + ) { + $axis = IMAGE_GRAPH_AXIS_X; + } elseif ($axis == 'default') { + $axis = IMAGE_GRAPH_AXIS_Y; + } + + if ($value === 'default') { + switch ($this->_type) { + case IMAGE_GRAPH_AXIS_Y: + $value = 'min'; + break; + case IMAGE_GRAPH_AXIS_Y_SECONDARY: + $value = 'max'; + break; + case IMAGE_GRAPH_AXIS_X: + $value = 0; + break; + } + } + + return array('value' => $value, 'axis' => $axis); + } + + /** + * Resets the elements + * + * @access private + */ + function _reset() + { + parent::_reset(); + $this->_labelText = array(); + } + + /** + * Output an axis tick mark. + * + * @param int $value The value to output + * @param int $level The label level to draw the tick for + * @access private + */ + function _drawTick($value, $level = 1) + { + if (isset($this->_labelOptions[$level])) { + $labelOptions = $this->_labelOptions[$level]; + $labelPosition = $this->_point($value); + + if (isset($labelOptions['offset'])) { + $offset = $labelOptions['offset']; + } else { + $offset = 0; + } + + if ((isset($labelOptions['showtext'])) && ($labelOptions['showtext'] === true)) { + if (is_object($this->_dataPreProcessor)) { + $labelText = $this->_dataPreProcessor->_process($value); + } elseif (isset($labelOptions['format'])) { + $labelText = sprintf($labelOptions['format'], $value); + } elseif (isset($labelOptions['dateformat'])) { + $labelText = date($labelOptions['dateformat'], $value); + } else { + $labelText = $value; + } + + if (!in_array($labelText, $this->_labelText)) { + $this->_labelText[] = $labelText; + + if (isset($labelOptions['font'])) { + $font = $this->_getFont($labelOptions['font']); + } else { + if ($this->_defaultFontOptions !== false) { + $font = $this->_defaultFontOptions; + } else { + $font = $this->_getFont(); + } + } + $this->_canvas->setFont($font); + + if ( + (isset($labelOptions['position'])) && + ($labelOptions['position'] == 'inside') + ) { + $labelInside = true; + } else { + $labelInside = false; + } + + if ($this->_type == IMAGE_GRAPH_AXIS_Y) { + if ($this->_transpose) { + if ($labelInside) { + $this->write( + $labelPosition, + $this->_top - 3 - $offset, + $labelText, + IMAGE_GRAPH_ALIGN_BOTTOM | IMAGE_GRAPH_ALIGN_CENTER_X, + $font + ); + } else { + $this->write( + $labelPosition, + $this->_top + 6 + $offset + $font['size'] * (substr_count($labelText, "\n") + 1), + $labelText, + IMAGE_GRAPH_ALIGN_BOTTOM | IMAGE_GRAPH_ALIGN_CENTER_X, + $font + ); + } + } + else { + if ($labelInside) { + $this->write( + $this->_right + 3 + $offset, + $labelPosition, + $labelText, + IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, + $font + ); + } else { + $this->write( + $this->_right - 3 - $offset, + $labelPosition, + $labelText, + IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_RIGHT, + $font + ); + } + } + } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) { + if ($this->_transpose) { + if ($labelInside) { + $this->write( + $labelPosition, + $this->_bottom + 6 + $offset + $font['size'] * (substr_count($labelText, "\n") + 1), + $labelText, + IMAGE_GRAPH_ALIGN_BOTTOM | IMAGE_GRAPH_ALIGN_CENTER_X, + $font + ); + } else { + $this->write( + $labelPosition, + $this->_bottom - 3 - $offset, + $labelText, + IMAGE_GRAPH_ALIGN_BOTTOM | IMAGE_GRAPH_ALIGN_CENTER_X, + $font + ); + } + } + else { + if ($labelInside) { + $this->write( + $this->_left - 3 - $offset, + $labelPosition, + $labelText, + IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_RIGHT, + $font + ); + } else { + $this->write( + $this->_left + 3 + $offset, + $labelPosition, + $labelText, + IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, + $font + ); + } + } + } else { + if ($this->_transpose) { + if ($labelInside) { + $this->write( + $this->_right + 3 + $offset, + $labelPosition, + $labelText, + IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, + $font + ); + } else { + $this->write( + $this->_right - 3 - $offset, + $labelPosition, + $labelText, + IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_RIGHT, + $font + ); + } + } + else { + if ($labelInside === true) { + $this->write( + $labelPosition, + $this->_top - 3 - $offset, + $labelText, + IMAGE_GRAPH_ALIGN_CENTER_X | IMAGE_GRAPH_ALIGN_BOTTOM, + $font + ); + } else { + $this->write( + $labelPosition, + $this->_top + 6 + $offset + $font['size'] * (substr_count($labelText, "\n") + 1), + $labelText, + IMAGE_GRAPH_ALIGN_CENTER_X | IMAGE_GRAPH_ALIGN_BOTTOM, + $font + ); + } + } + } + } + } + + $tickColor = false; + if (isset($this->_labelOptions[$level]['tick'])) { + if (isset($this->_labelOptions[$level]['tick']['start'])) { + $tickStart = $this->_labelOptions[$level]['tick']['start']; + } else { + $tickStart = false; + } + + if (isset($this->_labelOptions[$level]['tick']['end'])) { + $tickEnd = $this->_labelOptions[$level]['tick']['end']; + } else { + $tickEnd = false; + } + + if ((isset($this->_labelOptions[$level]['tick']['color'])) && ($this->_labelOptions[$level]['tick']['color'] !== false)) { + $tickColor = $this->_labelOptions[$level]['tick']['color']; + } + } + + if ($tickStart === false) { + $tickStart = -2; + } + + if ($tickEnd === false) { + $tickEnd = 2; + } + + if ($tickColor !== false) { + $this->_canvas->setLineColor($tickColor); + } + else { + $this->_getLineStyle(); + } + + if ($this->_type == IMAGE_GRAPH_AXIS_Y) { + if ($tickStart === 'auto') { + $tickStart = -$offset; + } + if ($this->_transpose) { + $this->_canvas->line( + array( + 'x0' => $labelPosition, + 'y0' => $this->_top + $tickStart, + 'x1' => $labelPosition, + 'y1' => $this->_top + $tickEnd + ) + ); + } + else { + $this->_canvas->line( + array( + 'x0' => $this->_right + $tickStart, + 'y0' => $labelPosition, + 'x1' => $this->_right + $tickEnd, + 'y1' => $labelPosition + ) + ); + } + } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) { + if ($tickStart === 'auto') { + $tickStart = $offset; + } + if ($this->_transpose) { + $this->_canvas->line( + array( + 'x0' => $labelPosition, + 'y0' => $this->_bottom - $tickStart, + 'x1' => $labelPosition, + 'y1' => $this->_bottom - $tickEnd + ) + ); + } + else { + $this->_canvas->line( + array( + 'x0' => $this->_left - $tickStart, + 'y0' => $labelPosition, + 'x1' => $this->_left - $tickEnd, + 'y1' => $labelPosition + ) + ); + } + } else { + if ($tickStart === 'auto') { + $tickStart = $offset; + } + if ($this->_transpose) { + $this->_canvas->line( + array( + 'x0' => $this->_right + $tickStart, + 'y0' => $labelPosition, + 'x1' => $this->_right + $tickEnd, + 'y1' => $labelPosition + ) + ); + } + else { + $this->_canvas->line( + array( + 'x0' => $labelPosition, + 'y0' => $this->_top - $tickStart, + 'x1' => $labelPosition, + 'y1' => $this->_top - $tickEnd + ) + ); + } + } + } + } + + /** + * Draws axis lines. + * + * @access private + */ + function _drawAxisLines() + { + if ($this->_type == IMAGE_GRAPH_AXIS_X) { + $this->_getLineStyle(); + $this->_getFillStyle(); + + if ($this->_transpose) { + $data = array( + 'x0' => $this->_right, + 'y0' => $this->_top, + 'x1' => $this->_right, + 'y1' => $this->_bottom + ); + } else { + $data = array( + 'x0' => $this->_left, + 'y0' => $this->_top, + 'x1' => $this->_right, + 'y1' => $this->_top + ); + } + + if ($this->_showArrow) { + if ($this->_getMaximum() <= 0) { + $data['end0'] = 'arrow2'; + $data['size0'] = 7; + } + else { + $data['end1'] = 'arrow2'; + $data['size1'] = 7; + } + } + + $this->_canvas->line($data); + + if ($this->_title) { + if (!$this->_transpose) { + $y = $this->_bottom; + $x = $this->_left + $this->width() / 2; + $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_CENTER_X + IMAGE_GRAPH_ALIGN_BOTTOM, $this->_getTitleFont()); + } + else { + $y = $this->_top + $this->height() / 2; + $x = $this->_left; + $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_LEFT + IMAGE_GRAPH_ALIGN_CENTER_Y, $this->_getTitleFont()); + } + } + } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) { + $this->_getLineStyle(); + $this->_getFillStyle(); + + if ($this->_transpose) { + $data = array( + 'x0' => $this->_left, + 'y0' => $this->_bottom, + 'x1' => $this->_right, + 'y1' => $this->_bottom + ); + } else { + $data = array( + 'x0' => $this->_left, + 'y0' => $this->_bottom, + 'x1' => $this->_left, + 'y1' => $this->_top + ); + } + if ($this->_showArrow) { + if ($this->_getMaximum() <= 0) { + $data['end0'] = 'arrow2'; + $data['size0'] = 7; + } + else { + $data['end1'] = 'arrow2'; + $data['size1'] = 7; + } + } + $this->_canvas->line($data); + + if ($this->_title) { + if ($this->_transpose) { + $y = $this->_top; + $x = $this->_left + $this->width() / 2; + $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_CENTER_X + IMAGE_GRAPH_ALIGN_TOP, $this->_getTitleFont()); + } + else { + $y = $this->_top + $this->height() / 2; + $x = $this->_right; + $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_RIGHT + IMAGE_GRAPH_ALIGN_CENTER_Y, $this->_getTitleFont()); + } + } + } else { + $this->_getLineStyle(); + $this->_getFillStyle(); + + if ($this->_transpose) { + $data = array( + 'x0' => $this->_left, + 'y0' => $this->_top, + 'x1' => $this->_right, + 'y1' => $this->_top + ); + } else { + $data = array( + 'x0' => $this->_right, + 'y0' => $this->_bottom, + 'x1' => $this->_right, + 'y1' => $this->_top + ); + } + if ($this->_showArrow) { + if ($this->_getMaximum() <= 0) { + $data['end0'] = 'arrow2'; + $data['size0'] = 7; + } + else { + $data['end1'] = 'arrow2'; + $data['size1'] = 7; + } + } + $this->_canvas->line($data); + + if ($this->_title) { + if ($this->_transpose) { + $y = $this->_bottom; + $x = $this->_left + $this->width() / 2; + $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_CENTER_X + IMAGE_GRAPH_ALIGN_BOTTOM, $this->_getTitleFont()); + } + else { + $y = $this->_top + $this->height() / 2; + $x = $this->_left; + $this->write($x, $y, $this->_title, IMAGE_GRAPH_ALIGN_LEFT + IMAGE_GRAPH_ALIGN_CENTER_Y, $this->_getTitleFont()); + } + } + } + } + + /** + * Causes the object to update all sub elements coordinates + * + * (Image_Graph_Common, does not itself have coordinates, this is basically + * an abstract method) + * + * @access private + */ + function _updateCoords() + { + parent::_updateCoords(); + $this->_calcDelta(); + } + + /** + * Output the axis + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + $this->_canvas->startGroup(get_class($this)); + + if (parent::_done() === false) { + return false; + } + + $this->_drawAxisLines(); + + $this->_canvas->startGroup(get_class($this) . '_ticks'); + ksort($this->_labelOptions); + foreach ($this->_labelOptions as $level => $labelOption) { + $value = false; + while (($value = $this->_getNextLabel($value, $level)) !== false) { + if ((((abs($value) > 0.0001) || ($this->_showLabelZero)) && + (($value > $this->_getMinimum()) || ($this->_showLabelMinimum)) && + (($value < $this->_getMaximum()) || ($this->_showLabelMaximum))) && + ($value >= $this->_getMinimum()) && ($value <= $this->_getMaximum()) + ) { + $this->_drawTick($value, $level); + } + } + } + $this->_canvas->endGroup(); + + $tickStart = -3; + $tickEnd = 2; + + foreach ($this->_marks as $mark) { + if (is_array($mark)) { + if ($this->_type == IMAGE_GRAPH_AXIS_X) { + if ($this->_transpose) { + $x0 = $this->_right + $tickStart; + $y0 = $this->_point($mark[1]); + $x1 = $this->_right + $tickEnd; + $y1 = $this->_point($mark[0]); + } + else { + $x0 = $this->_point($mark[0]); + $y0 = $this->_top + $tickStart; + $x1 = $this->_point($mark[1]); + $y1 = $this->_top + $tickEnd; + } + } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y) { + if ($this->_transpose) { + $x0 = $this->_point($mark[0]); + $y0 = $this->_top + $tickStart; + $x1 = $this->_point($mark[1]); + $y1 = $this->_top + $tickEnd; + } + else { + $x0 = $this->_right + $tickStart; + $y0 = $this->_point($mark[1]); + $x1 = $this->_right + $tickEnd; + $y1 = $this->_point($mark[0]); + } + } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) { + if ($this->_transpose) { + $x0 = $this->_point($mark[0]); + $y0 = $this->_bottom + $tickStart; + $x1 = $this->_point($mark[1]); + $y1 = $this->_bottom + $tickEnd; + } + else { + $x0 = $this->_left + $tickStart; + $y0 = $this->_point($mark[1]); + $x1 = $this->_left + $tickEnd; + $y1 = $this->_point($mark[0]); + } + } + $this->_getFillStyle(); + $this->_getLineStyle(); + $this->_canvas->rectangle(array('x0' => $x0, 'y0' => $y0, 'x1' => $x1, 'y1' => $y1)); + } else { + if ($this->_type == IMAGE_GRAPH_AXIS_X) { + if ($this->_transpose) { + $x0 = $this->_right + 5; + $y0 = $this->_point($mark); + $x1 = $this->_right + 15; + $y1 = $y0; + } + else { + $x0 = $this->_point($mark); + $y0 = $this->_top - 5; + $x1 = $x0; + $y1 = $this->_top - 15; + } + } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y) { + if ($this->_transpose) { + $x0 = $this->_point($mark); + $y0 = $this->_top - 5; + $x1 = $x0; + $y1 = $this->_top - 15; + } + else { + $x0 = $this->_right + 5; + $y0 = $this->_point($mark); + $x1 = $this->_right + 15; + $y1 = $y0; + } + } elseif ($this->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY) { + if ($this->_transpose) { + $x0 = $this->_point($mark); + $y0 = $this->_bottom + 5; + $x1 = $x0; + $y1 = $this->_bottom + 15; + } + else { + $x0 = $this->_left - 5; + $y0 = $this->_point($mark); + $x1 = $this->_left - 15; + $y1 = $y0; + } + } + $this->_getFillStyle(); + $this->_getLineStyle(); + $this->_canvas->line( + array( + 'x0' => $x0, + 'y0' => $y0, + 'x1' => $x1, + 'y1' => $y1, + 'end0' => 'arrow2', + 'size0' => 5 + ) + ); + } + } + $this->_canvas->endGroup(); + + return true; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Axis/Category.php b/includes/pear/Image/Graph/Axis/Category.php index 98d80354..e92bab61 100644 --- a/includes/pear/Image/Graph/Axis/Category.php +++ b/includes/pear/Image/Graph/Axis/Category.php @@ -1,426 +1,437 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Category.php,v 1.17 2005/10/05 20:51:23 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Axis.php - */ -require_once 'Image/Graph/Axis.php'; - -/** - * A normal axis thats displays labels with a 'interval' of 1. - * This is basically a normal axis where the range is - * the number of labels defined, that is the range is explicitly defined - * when constructing the axis. - * - * @category Images - * @package Image_Graph - * @subpackage Axis - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Axis_Category extends Image_Graph_Axis -{ - - /** - * The labels shown on the axis - * @var array - * @access private - */ - var $_labels = false; - - /** - * Image_Graph_Axis_Category [Constructor]. - * - * @param int $type The type (direction) of the Axis - */ - function Image_Graph_Axis_Category($type = IMAGE_GRAPH_AXIS_X) - { - parent::Image_Graph_Axis($type); - $this->_labels = array(); - $this->setlabelInterval(1); - } - - /** - * Gets the minimum value the axis will show. - * - * This is always 0 - * - * @return double The minumum value - * @access private - */ - function _getMinimum() - { - return 0; - } - - /** - * Gets the maximum value the axis will show. - * - * This is always the number of labels passed to the constructor. - * - * @return double The maximum value - * @access private - */ - function _getMaximum() - { - return count($this->_labels) - ($this->_pushValues ? 0 : 1); - } - - /** - * Sets the minimum value the axis will show. - * - * A minimum cannot be set on a SequentialAxis, it is always 0. - * - * @param double Minimum The minumum value to use on the axis - * @access private - */ - function _setMinimum($minimum) - { - } - - /** - * Sets the maximum value the axis will show - * - * A maximum cannot be set on a SequentialAxis, it is always the number - * of labels passed to the constructor. - * - * @param double Maximum The maximum value to use on the axis - * @access private - */ - function _setMaximum($maximum) - { - } - - /** - * Forces the minimum value of the axis - * - * A minimum cannot be set on a SequentialAxis, it is always 0. - * - * @param double $minimum The minumum value to use on the axis - */ - function forceMinimum($minimum, $userEnforce = true) - { - } - - /** - * Forces the maximum value of the axis - * - * A maximum cannot be set on a SequentialAxis, it is always the number - * of labels passed to the constructor. - * - * @param double $maximum The maximum value to use on the axis - */ - function forceMaximum($maximum, $userEnforce = true) - { - } - - /** - * Sets an interval for where labels are shown on the axis. - * - * The label interval is rounded to nearest integer value - * - * @param double $labelInterval The interval with which labels are shown - */ - function setLabelInterval($labelInterval = 'auto', $level = 1) - { - if ($labelInterval == 'auto') { - parent::setLabelInterval(1); - } else { - parent::setLabelInterval(round($labelInterval)); - } - } - - /** - * Preprocessor for values, ie for using logarithmic axis - * - * @param double $value The value to preprocess - * @return double The preprocessed value - * @access private - */ - function _value($value) - { -// $the_value = array_search($value, $this->_labels); - if (isset($this->_labels[$value])) { - $the_value = $this->_labels[$value]; - if ($the_value !== false) { - return $the_value + ($this->_pushValues ? 0.5 : 0); - } else { - return 0; - } - } - } - - - /** - * Get the minor label interval with which axis label ticks are drawn. - * - * For a sequential axis this is always disabled (i.e false) - * - * @return double The minor label interval, always false - * @access private - */ - function _minorLabelInterval() - { - return false; - } - - /** - * Get the size in pixels of the axis. - * - * For an x-axis this is the width of the axis including labels, and for an - * y-axis it is the corrresponding height - * - * @return int The size of the axis - * @access private - */ - function _size() - { - if (!$this->_visible) { - return 0; - } - - $this->_canvas->setFont($this->_getFont()); - - $maxSize = 0; - foreach($this->_labels as $label => $id) { - $labelPosition = $this->_point($label); - - if (is_object($this->_dataPreProcessor)) { - $labelText = $this->_dataPreProcessor->_process($label); - } else { - $labelText = $label; - } - - if ((($this->_type == IMAGE_GRAPH_AXIS_X) && (!$this->_transpose)) || - (($this->_type != IMAGE_GRAPH_AXIS_X) && ($this->_transpose))) - { - $maxSize = max($maxSize, $this->_canvas->textHeight($labelText)); - } else { - $maxSize = max($maxSize, $this->_canvas->textWidth($labelText)); - } - } - - if ($this->_title) { - $this->_canvas->setFont($this->_getTitleFont()); - - if ((($this->_type == IMAGE_GRAPH_AXIS_X) && (!$this->_transpose)) || - (($this->_type != IMAGE_GRAPH_AXIS_X) && ($this->_transpose))) - { - $maxSize += $this->_canvas->textHeight($this->_title); - } else { - $maxSize += $this->_canvas->textWidth($this->_title); - } - $maxSize += 10; - } - return $maxSize +3; - } - - /** - * Apply the dataset to the axis. - * - * This calculates the order of the categories, which is very important - * for fx. line plots, so that the line does not "go backwards", consider - * these X-sets:

- * 1: (1, 2, 3, 4, 5, 6)
- * 2: (0, 1, 2, 3, 4, 5, 6, 7)

- * If they are not ordered, but simply appended, the categories on the axis - * would be:

- * X: (1, 2, 3, 4, 5, 6, 0, 7)

- * Which would render the a line for the second plot to show incorrectly. - * Instead this algorithm, uses and 'value- is- before' method to see that - * the 0 is before a 1 in the second set, and that it should also be before - * a 1 in the X set. Hence:

- * X: (0, 1, 2, 3, 4, 5, 6, 7) - * - * @param Image_Graph_Dataset $dataset The dataset - * @access private - */ - function _applyDataset(&$dataset) - { - $newLabels = array(); - $allLabels = array(); - - $dataset->_reset(); - $count = 0; - $count_new = 0; - while ($point = $dataset->_next()) { - if ($this->_type == IMAGE_GRAPH_AXIS_X) { - $data = $point['X']; - } else { - $data = $point['Y']; - } - if (!isset($this->_labels[$data])) { - $newLabels[$data] = $count_new++; - //$this->_labels[] = $data; - } - $allLabels[$data] = $count++; - } - - if (count($this->_labels) == 0) { - $this->_labels = $newLabels; - } elseif ((is_array($newLabels)) && (count($newLabels) > 0)) { - // get all intersecting labels - $intersect = array_intersect(array_keys($allLabels), array_keys($this->_labels)); - // traverse all new and find their relative position withing the - // intersec, fx value X0 is before X1 in the intersection, which - // means that X0 should be placed before X1 in the label array - foreach($newLabels as $newLabel => $id) { - $key = $allLabels[$newLabel]; - reset($intersect); - $this_value = false; - // intersect indexes are the same as in allLabels! - $first = true; - while ((list($id, $value) = each($intersect)) && - ($this_value === false)) - { - if (($first) && ($id > $key)) { - $this_value = $value; - } elseif ($id >= $key) { - $this_value = $value; - } - $first = false; - } - - if ($this_value === false) { - // the new label was not found before anything in the - // intersection -> append it - $this->_labels[$newLabel] = count($this->_labels); - } else { - // the new label was found before $this_value in the - // intersection, insert the label before this position in - // the label array -// $key = $this->_labels[$this_value]; - $keys = array_keys($this->_labels); - $key = array_search($this_value, $keys); - $pre = array_slice($keys, 0, $key); - $pre[] = $newLabel; - $post = array_slice($keys, $key); - $this->_labels = array_flip(array_merge($pre, $post)); - } - } - unset($keys); - } - - $labels = array_keys($this->_labels); - $i = 0; - foreach ($labels as $label) { - $this->_labels[$label] = $i++; - } - -// $this->_labels = array_values(array_unique($this->_labels)); - $this->_calcLabelInterval(); - } - - /** - * Return the label distance. - * - * @return int The distance between 2 adjacent labels - * @access private - */ - function _labelDistance($level = 1) - { - reset($this->_labels); - list($l1) = each($this->_labels); - list($l2) = each($this->_labels); - return abs($this->_point($l2) - $this->_point($l1)); - } - - /** - * Get next label point - * - * @param doubt $point The current point, if omitted or false, the first is - * returned - * @return double The next label point - * @access private - */ - function _getNextLabel($currentLabel = false, $level = 1) - { - if ($currentLabel === false) { - reset($this->_labels); - } - $result = false; - $count = ($currentLabel === false ? $this->_labelInterval() - 1 : 0); - while ($count < $this->_labelInterval()) { - $result = (list($label) = each($this->_labels)); - $count++; - } - if ($result) { - return $label; - } else { - return false; - } - } - - /** - * Is the axis numeric or not? - * - * @return bool True if numeric, false if not - * @access private - */ - function _isNumeric() - { - return false; - } - - /** - * Output the axis - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - $result = true; - if (Image_Graph_Element::_done() === false) { - $result = false; - } - - $this->_canvas->startGroup(get_class($this)); - - $this->_drawAxisLines(); - - $this->_canvas->startGroup(get_class($this) . '_ticks'); - $label = false; - while (($label = $this->_getNextLabel($label)) !== false) { - $this->_drawTick($label); - } - $this->_canvas->endGroup(); - - $this->_canvas->endGroup(); - - return $result; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Category.php,v 1.19 2006/03/02 12:15:17 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Axis.php + */ +require_once 'Image/Graph/Axis.php'; + +/** + * A normal axis thats displays labels with a 'interval' of 1. + * This is basically a normal axis where the range is + * the number of labels defined, that is the range is explicitly defined + * when constructing the axis. + * + * @category Images + * @package Image_Graph + * @subpackage Axis + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Axis_Category extends Image_Graph_Axis +{ + + /** + * The labels shown on the axis + * @var array + * @access private + */ + var $_labels = false; + + /** + * Image_Graph_Axis_Category [Constructor]. + * + * @param int $type The type (direction) of the Axis + */ + function Image_Graph_Axis_Category($type = IMAGE_GRAPH_AXIS_X) + { + parent::Image_Graph_Axis($type); + $this->_labels = array(); + $this->setlabelInterval(1); + } + + /** + * Gets the minimum value the axis will show. + * + * This is always 0 + * + * @return double The minumum value + * @access private + */ + function _getMinimum() + { + return 0; + } + + /** + * Gets the maximum value the axis will show. + * + * This is always the number of labels passed to the constructor. + * + * @return double The maximum value + * @access private + */ + function _getMaximum() + { + return count($this->_labels) - 1; + } + + /** + * Sets the minimum value the axis will show. + * + * A minimum cannot be set on a SequentialAxis, it is always 0. + * + * @param double Minimum The minumum value to use on the axis + * @access private + */ + function _setMinimum($minimum) + { + } + + /** + * Sets the maximum value the axis will show + * + * A maximum cannot be set on a SequentialAxis, it is always the number + * of labels passed to the constructor. + * + * @param double Maximum The maximum value to use on the axis + * @access private + */ + function _setMaximum($maximum) + { + } + + /** + * Forces the minimum value of the axis + * + * A minimum cannot be set on this type of axis + * + * To modify the labels which are displayed on the axis, instead use + * setLabelInterval($labels) where $labels is an array containing the + * values/labels the axis should display. Note! Only values in + * this array will then be displayed on the graph! + * + * @param double $minimum A minimum cannot be set on this type of axis + */ + function forceMinimum($minimum, $userEnforce = true) + { + } + + /** + * Forces the maximum value of the axis + * + * A maximum cannot be set on this type of axis + * + * To modify the labels which are displayed on the axis, instead use + * setLabelInterval($labels) where $labels is an array containing the + * values/labels the axis should display. Note! Only values in + * this array will then be displayed on the graph! + * + * @param double $maximum A maximum cannot be set on this type of axis + */ + function forceMaximum($maximum, $userEnforce = true) + { + } + + /** + * Sets an interval for where labels are shown on the axis. + * + * The label interval is rounded to nearest integer value. + * + * @param double $labelInterval The interval with which labels are shown + */ + function setLabelInterval($labelInterval = 'auto', $level = 1) + { + if (is_array($labelInterval)) { + parent::setLabelInterval($labelInterval); + } elseif ($labelInterval == 'auto') { + parent::setLabelInterval(1); + } else { + parent::setLabelInterval(round($labelInterval)); + } + } + + /** + * Preprocessor for values, ie for using logarithmic axis + * + * @param double $value The value to preprocess + * @return double The preprocessed value + * @access private + */ + function _value($value) + { +// $the_value = array_search($value, $this->_labels); + if (isset($this->_labels[$value])) { + $the_value = $this->_labels[$value]; + if ($the_value !== false) { + return $the_value + ($this->_pushValues ? 0.5 : 0); + } else { + return 0; + } + } + } + + + /** + * Get the minor label interval with which axis label ticks are drawn. + * + * For a sequential axis this is always disabled (i.e false) + * + * @return double The minor label interval, always false + * @access private + */ + function _minorLabelInterval() + { + return false; + } + + /** + * Get the size in pixels of the axis. + * + * For an x-axis this is the width of the axis including labels, and for an + * y-axis it is the corrresponding height + * + * @return int The size of the axis + * @access private + */ + function _size() + { + if (!$this->_visible) { + return 0; + } + + $this->_canvas->setFont($this->_getFont()); + + $maxSize = 0; + foreach($this->_labels as $label => $id) { + $labelPosition = $this->_point($label); + + if (is_object($this->_dataPreProcessor)) { + $labelText = $this->_dataPreProcessor->_process($label); + } else { + $labelText = $label; + } + + if ((($this->_type == IMAGE_GRAPH_AXIS_X) && (!$this->_transpose)) || + (($this->_type != IMAGE_GRAPH_AXIS_X) && ($this->_transpose))) + { + $maxSize = max($maxSize, $this->_canvas->textHeight($labelText)); + } else { + $maxSize = max($maxSize, $this->_canvas->textWidth($labelText)); + } + } + + if ($this->_title) { + $this->_canvas->setFont($this->_getTitleFont()); + + if ((($this->_type == IMAGE_GRAPH_AXIS_X) && (!$this->_transpose)) || + (($this->_type != IMAGE_GRAPH_AXIS_X) && ($this->_transpose))) + { + $maxSize += $this->_canvas->textHeight($this->_title); + } else { + $maxSize += $this->_canvas->textWidth($this->_title); + } + $maxSize += 10; + } + return $maxSize +3; + } + + /** + * Apply the dataset to the axis. + * + * This calculates the order of the categories, which is very important + * for fx. line plots, so that the line does not "go backwards", consider + * these X-sets:

+ * 1: (1, 2, 3, 4, 5, 6)
+ * 2: (0, 1, 2, 3, 4, 5, 6, 7)

+ * If they are not ordered, but simply appended, the categories on the axis + * would be:

+ * X: (1, 2, 3, 4, 5, 6, 0, 7)

+ * Which would render the a line for the second plot to show incorrectly. + * Instead this algorithm, uses and 'value- is- before' method to see that + * the 0 is before a 1 in the second set, and that it should also be before + * a 1 in the X set. Hence:

+ * X: (0, 1, 2, 3, 4, 5, 6, 7) + * + * @param Image_Graph_Dataset $dataset The dataset + * @access private + */ + function _applyDataset(&$dataset) + { + $newLabels = array(); + $allLabels = array(); + + $dataset->_reset(); + $count = 0; + $count_new = 0; + while ($point = $dataset->_next()) { + if ($this->_type == IMAGE_GRAPH_AXIS_X) { + $data = $point['X']; + } else { + $data = $point['Y']; + } + if (!isset($this->_labels[$data])) { + $newLabels[$data] = $count_new++; + //$this->_labels[] = $data; + } + $allLabels[$data] = $count++; + } + + if (count($this->_labels) == 0) { + $this->_labels = $newLabels; + } elseif ((is_array($newLabels)) && (count($newLabels) > 0)) { + // get all intersecting labels + $intersect = array_intersect(array_keys($allLabels), array_keys($this->_labels)); + // traverse all new and find their relative position withing the + // intersec, fx value X0 is before X1 in the intersection, which + // means that X0 should be placed before X1 in the label array + foreach($newLabels as $newLabel => $id) { + $key = $allLabels[$newLabel]; + reset($intersect); + $this_value = false; + // intersect indexes are the same as in allLabels! + $first = true; + while ((list($id, $value) = each($intersect)) && + ($this_value === false)) + { + if (($first) && ($id > $key)) { + $this_value = $value; + } elseif ($id >= $key) { + $this_value = $value; + } + $first = false; + } + + if ($this_value === false) { + // the new label was not found before anything in the + // intersection -> append it + $this->_labels[$newLabel] = count($this->_labels); + } else { + // the new label was found before $this_value in the + // intersection, insert the label before this position in + // the label array +// $key = $this->_labels[$this_value]; + $keys = array_keys($this->_labels); + $key = array_search($this_value, $keys); + $pre = array_slice($keys, 0, $key); + $pre[] = $newLabel; + $post = array_slice($keys, $key); + $this->_labels = array_flip(array_merge($pre, $post)); + } + } + unset($keys); + } + + $labels = array_keys($this->_labels); + $i = 0; + foreach ($labels as $label) { + $this->_labels[$label] = $i++; + } + +// $this->_labels = array_values(array_unique($this->_labels)); + $this->_calcLabelInterval(); + } + + /** + * Return the label distance. + * + * @return int The distance between 2 adjacent labels + * @access private + */ + function _labelDistance($level = 1) + { + reset($this->_labels); + list($l1) = each($this->_labels); + list($l2) = each($this->_labels); + return abs($this->_point($l2) - $this->_point($l1)); + } + + /** + * Get next label point + * + * @param doubt $point The current point, if omitted or false, the first is + * returned + * @return double The next label point + * @access private + */ + function _getNextLabel($currentLabel = false, $level = 1) + { + if ($currentLabel === false) { + reset($this->_labels); + } + $result = false; + $count = ($currentLabel === false ? $this->_labelInterval() - 1 : 0); + while ($count < $this->_labelInterval()) { + $result = (list($label) = each($this->_labels)); + $count++; + } + if ($result) { + return $label; + } else { + return false; + } + } + + /** + * Is the axis numeric or not? + * + * @return bool True if numeric, false if not + * @access private + */ + function _isNumeric() + { + return false; + } + + /** + * Output the axis + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + $result = true; + if (Image_Graph_Element::_done() === false) { + $result = false; + } + + $this->_canvas->startGroup(get_class($this)); + + $this->_drawAxisLines(); + + $this->_canvas->startGroup(get_class($this) . '_ticks'); + $label = false; + while (($label = $this->_getNextLabel($label)) !== false) { + $this->_drawTick($label); + } + $this->_canvas->endGroup(); + + $this->_canvas->endGroup(); + + return $result; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Axis/Logarithmic.php b/includes/pear/Image/Graph/Axis/Logarithmic.php index 8567a7e0..e6f1f964 100644 --- a/includes/pear/Image/Graph/Axis/Logarithmic.php +++ b/includes/pear/Image/Graph/Axis/Logarithmic.php @@ -1,175 +1,152 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Logarithmic.php,v 1.13 2005/09/25 17:52:17 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Axis.php - */ -require_once 'Image/Graph/Axis.php'; - -/** - * Diplays a logarithmic axis (either X- or Y-axis). - * - * @category Images - * @package Image_Graph - * @subpackage Axis - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Axis_Logarithmic extends Image_Graph_Axis -{ - - /** - * Image_Graph_AxisLogarithmic [Constructor]. - * - * Normally a manual creation should not be necessary, axis are - * created automatically by the {@link Image_Graph_Plotarea} constructor - * unless explicitly defined otherwise - * - * @param int $type The type (direction) of the Axis, use IMAGE_GRAPH_AXIS_X - * for an X-axis (default, may be omitted) and IMAGE_GRAPH_AXIS_Y for Y- - * axis) - */ - function Image_Graph_Axis_Logarithmic($type = IMAGE_GRAPH_AXIS_X) - { - parent::Image_Graph_Axis($type); - $this->showLabel(IMAGE_GRAPH_LABEL_MINIMUM + IMAGE_GRAPH_LABEL_MAXIMUM); - } - - /** - * Calculate the label interval - * - * If explicitly defined this will be calucated to an approximate best. - * - * @return double The label interval - * @access private - */ - function _calcLabelInterval() - { - $result = parent::_calcLabelInterval(); - $this->_axisValueSpan = $this->_value($this->_axisSpan); - return $result; - } - - /** - * Forces the minimum value of the axis. - * - * For an logarithimc axis this is always 0 - * - * @param double $minimum The minumum value to use on the axis - */ - function forceMinimum($minimum) - { - parent::forceMinimum(0); - } - - /** - * Gets the minimum value the axis will show. - * - * For an logarithimc axis this is always 0 - * - * @return double The minumum value - * @access private - */ - function _getMinimum() - { - return 0; - } - - /** - * Preprocessor for values, ie for using logarithmic axis - * - * @param double $value The value to preprocess - * @return double The preprocessed value - * @access private - */ - function _value($value) - { - return log10($value); - } - - /** - * Get next label point - * - * @param doubt $point The current point, if omitted or false, the first is - * returned - * @return double The next label point - * @access private - */ - function _getNextLabel($currentLabel = false, $level = 1) - { - if (is_array($this->_labelOptions[$level]['interval'])) { - return parent::_getNextLabel($currentLabel, $level); - } - - if ($currentLabel !== false) { - $value = log10($currentLabel); - $base = floor($value); - $frac = $value - $base; - for ($i = 2; $i < 10; $i++) { - if ($frac <= (log10($i)-0.01)) { - $label = pow(10, $base)*$i; - if ($label > $this->_getMaximum()) { - return false; - } else { - return $label; - } - } - } - return pow(10, $base+1); - } - - return 1; - } - - /** - * Get the axis intersection pixel position - * - * This is only to be called prior to output! I.e. between the user - * invokation of Image_Graph::done() and any actual output is performed. - * This is because it can change the axis range. - * - * @param double $value the intersection value to get the pixel-point for - * @return double The pixel position along the axis - * @access private - */ - function _intersectPoint($value) - { - if (($value <= 0) && ($value !== 'max') && ($value !== 'min')) { - $value = 1; - } - return parent::_intersectPoint($value); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Logarithmic.php,v 1.15 2006/03/02 12:35:57 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Axis.php + */ +require_once 'Image/Graph/Axis.php'; + +/** + * Diplays a logarithmic axis (either X- or Y-axis). + * + * @category Images + * @package Image_Graph + * @subpackage Axis + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Axis_Logarithmic extends Image_Graph_Axis +{ + + /** + * Image_Graph_AxisLogarithmic [Constructor]. + * + * Normally a manual creation should not be necessary, axis are + * created automatically by the {@link Image_Graph_Plotarea} constructor + * unless explicitly defined otherwise + * + * @param int $type The type (direction) of the Axis, use IMAGE_GRAPH_AXIS_X + * for an X-axis (default, may be omitted) and IMAGE_GRAPH_AXIS_Y for Y- + * axis) + */ + function Image_Graph_Axis_Logarithmic($type = IMAGE_GRAPH_AXIS_X) + { + parent::Image_Graph_Axis($type); + $this->showLabel(IMAGE_GRAPH_LABEL_MINIMUM + IMAGE_GRAPH_LABEL_MAXIMUM); + $this->_minimum = 1; + $this->_minimumSet = true; + } + + /** + * Calculate the label interval + * + * If explicitly defined this will be calucated to an approximate best. + * + * @return double The label interval + * @access private + */ + function _calcLabelInterval() + { + $result = parent::_calcLabelInterval(); + $this->_axisValueSpan = $this->_value($this->_axisSpan); + return $result; + } + + /** + * Preprocessor for values, ie for using logarithmic axis + * + * @param double $value The value to preprocess + * @return double The preprocessed value + * @access private + */ + function _value($value) + { + return log10($value) - log10($this->_minimum); + } + + /** + * Get next label point + * + * @param doubt $point The current point, if omitted or false, the first is + * returned + * @return double The next label point + * @access private + */ + function _getNextLabel($currentLabel = false, $level = 1) + { + if (is_array($this->_labelOptions[$level]['interval'])) { + return parent::_getNextLabel($currentLabel, $level); + } + + if ($currentLabel !== false) { + $value = log10($currentLabel); + $base = floor($value); + $frac = $value - $base; + for ($i = 2; $i < 10; $i++) { + if ($frac <= (log10($i)-0.01)) { + $label = pow(10, $base)*$i; + if ($label > $this->_getMaximum()) { + return false; + } else { + return $label; + } + } + } + return pow(10, $base+1); + } + + return max(1, $this->_minimum); + } + + /** + * Get the axis intersection pixel position + * + * This is only to be called prior to output! I.e. between the user + * invokation of Image_Graph::done() and any actual output is performed. + * This is because it can change the axis range. + * + * @param double $value the intersection value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _intersectPoint($value) + { + if (($value <= 0) && ($value !== 'max') && ($value !== 'min')) { + $value = 1; + } + return parent::_intersectPoint($value); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Axis/Marker/Area.php b/includes/pear/Image/Graph/Axis/Marker/Area.php index 30a31dee..4b688fdb 100644 --- a/includes/pear/Image/Graph/Axis/Marker/Area.php +++ b/includes/pear/Image/Graph/Axis/Marker/Area.php @@ -1,156 +1,156 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Area.php,v 1.11 2005/08/24 20:36:04 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Grid.php - */ -require_once 'Image/Graph/Grid.php'; - -/** - * Display a grid - * - * {@link Image_Graph_Grid} - * - * @category Images - * @package Image_Graph - * @subpackage Grid - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Axis_Marker_Area extends Image_Graph_Grid -{ - - /** - * The lower bound - * @var double - * @access private - */ - var $_lower = false; - - /** - * The upper bound - * @var double - * @access private - */ - var $_upper = false; - - /** - * [Constructor] - */ - function Image_Graph_Axis_Marker_Area() - { - parent::Image_Graph_Grid(); - $this->_lineStyle = false; - } - - /** - * Sets the lower bound of the area (value on the axis) - * - * @param double $lower the lower bound - */ - function setLowerBound($lower) - { - $this->_lower = $lower; - } - - /** - * Sets the upper bound of the area (value on the axis) - * - * @param double $upper the upper bound - */ - function setUpperBound($upper) - { - $this->_upper = $upper; - } - - /** - * Output the grid - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (parent::_done() === false) { - return false; - } - - if (!$this->_primaryAxis) { - return false; - } - - $this->_canvas->startGroup(get_class($this)); - - $i = 0; - - $this->_lower = max($this->_primaryAxis->_getMinimum(), $this->_lower); - $this->_upper = min($this->_primaryAxis->_getMaximum(), $this->_upper); - - $secondaryPoints = $this->_getSecondaryAxisPoints(); - - reset($secondaryPoints); - list ($id, $previousSecondaryValue) = each($secondaryPoints); - while (list ($id, $secondaryValue) = each($secondaryPoints)) { - if ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_X) { - $p1 = array ('Y' => $secondaryValue, 'X' => $this->_lower); - $p2 = array ('Y' => $previousSecondaryValue, 'X' => $this->_lower); - $p3 = array ('Y' => $previousSecondaryValue, 'X' => $this->_upper); - $p4 = array ('Y' => $secondaryValue, 'X' => $this->_upper); - } else { - $p1 = array ('X' => $secondaryValue, 'Y' => $this->_lower); - $p2 = array ('X' => $previousSecondaryValue, 'Y' => $this->_lower); - $p3 = array ('X' => $previousSecondaryValue, 'Y' => $this->_upper); - $p4 = array ('X' => $secondaryValue, 'Y' => $this->_upper); - } - - $this->_canvas->addVertex(array('x' => $this->_pointX($p1), 'y' => $this->_pointY($p1))); - $this->_canvas->addVertex(array('x' => $this->_pointX($p2), 'y' => $this->_pointY($p2))); - $this->_canvas->addVertex(array('x' => $this->_pointX($p3), 'y' => $this->_pointY($p3))); - $this->_canvas->addVertex(array('x' => $this->_pointX($p4), 'y' => $this->_pointY($p4))); - - $previousSecondaryValue = $secondaryValue; - - $this->_getLineStyle(); - $this->_getFillStyle(); - $this->_canvas->polygon(array('connect' => true)); - } - - $this->_canvas->endGroup(); - - return true; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Area.php,v 1.11 2005/08/24 20:36:04 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Grid.php + */ +require_once 'Image/Graph/Grid.php'; + +/** + * Display a grid + * + * {@link Image_Graph_Grid} + * + * @category Images + * @package Image_Graph + * @subpackage Grid + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Axis_Marker_Area extends Image_Graph_Grid +{ + + /** + * The lower bound + * @var double + * @access private + */ + var $_lower = false; + + /** + * The upper bound + * @var double + * @access private + */ + var $_upper = false; + + /** + * [Constructor] + */ + function Image_Graph_Axis_Marker_Area() + { + parent::Image_Graph_Grid(); + $this->_lineStyle = false; + } + + /** + * Sets the lower bound of the area (value on the axis) + * + * @param double $lower the lower bound + */ + function setLowerBound($lower) + { + $this->_lower = $lower; + } + + /** + * Sets the upper bound of the area (value on the axis) + * + * @param double $upper the upper bound + */ + function setUpperBound($upper) + { + $this->_upper = $upper; + } + + /** + * Output the grid + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + if (!$this->_primaryAxis) { + return false; + } + + $this->_canvas->startGroup(get_class($this)); + + $i = 0; + + $this->_lower = max($this->_primaryAxis->_getMinimum(), $this->_lower); + $this->_upper = min($this->_primaryAxis->_getMaximum(), $this->_upper); + + $secondaryPoints = $this->_getSecondaryAxisPoints(); + + reset($secondaryPoints); + list ($id, $previousSecondaryValue) = each($secondaryPoints); + while (list ($id, $secondaryValue) = each($secondaryPoints)) { + if ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_X) { + $p1 = array ('Y' => $secondaryValue, 'X' => $this->_lower); + $p2 = array ('Y' => $previousSecondaryValue, 'X' => $this->_lower); + $p3 = array ('Y' => $previousSecondaryValue, 'X' => $this->_upper); + $p4 = array ('Y' => $secondaryValue, 'X' => $this->_upper); + } else { + $p1 = array ('X' => $secondaryValue, 'Y' => $this->_lower); + $p2 = array ('X' => $previousSecondaryValue, 'Y' => $this->_lower); + $p3 = array ('X' => $previousSecondaryValue, 'Y' => $this->_upper); + $p4 = array ('X' => $secondaryValue, 'Y' => $this->_upper); + } + + $this->_canvas->addVertex(array('x' => $this->_pointX($p1), 'y' => $this->_pointY($p1))); + $this->_canvas->addVertex(array('x' => $this->_pointX($p2), 'y' => $this->_pointY($p2))); + $this->_canvas->addVertex(array('x' => $this->_pointX($p3), 'y' => $this->_pointY($p3))); + $this->_canvas->addVertex(array('x' => $this->_pointX($p4), 'y' => $this->_pointY($p4))); + + $previousSecondaryValue = $secondaryValue; + + $this->_getLineStyle(); + $this->_getFillStyle(); + $this->_canvas->polygon(array('connect' => true)); + } + + $this->_canvas->endGroup(); + + return true; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Axis/Marker/Line.php b/includes/pear/Image/Graph/Axis/Marker/Line.php index b1b5c6ee..be3b5bec 100644 --- a/includes/pear/Image/Graph/Axis/Marker/Line.php +++ b/includes/pear/Image/Graph/Axis/Marker/Line.php @@ -1,124 +1,124 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Line.php,v 1.11 2005/08/03 21:21:58 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Grid.php - */ -require_once 'Image/Graph/Grid.php'; - -/** - * Display a grid - * - * {@link Image_Graph_Grid} - * - * @category Images - * @package Image_Graph - * @subpackage Grid - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Axis_Marker_Line extends Image_Graph_Grid -{ - - /** - * The value - * @var double - * @access private - */ - var $_value = false; - - /** - * Sets the value of the line marker (value on the axis) - * - * @param double $value the value - */ - function setValue($value) - { - $this->_value = $value; - } - - /** - * Output the grid - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (parent::_done() === false) { - return false; - } - - if (!$this->_primaryAxis) { - return false; - } - - $this->_canvas->startGroup(get_class($this)); - - $i = 0; - - $this->_value = min($this->_primaryAxis->_getMaximum(), max($this->_primaryAxis->_getMinimum(), $this->_value)); - - $secondaryPoints = $this->_getSecondaryAxisPoints(); - - reset($secondaryPoints); - list ($id, $previousSecondaryValue) = each($secondaryPoints); - while (list ($id, $secondaryValue) = each($secondaryPoints)) { - if ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_X) { - $p1 = array ('X' => $this->_value, 'Y' => $secondaryValue); - $p2 = array ('X' => $this->_value, 'Y' => $previousSecondaryValue); - } else { - $p1 = array ('X' => $secondaryValue, 'Y' => $this->_value); - $p2 = array ('X' => $previousSecondaryValue, 'Y' => $this->_value); - } - - $x1 = $this->_pointX($p1); - $y1 = $this->_pointY($p1); - $x2 = $this->_pointX($p2); - $y2 = $this->_pointY($p2); - - $previousSecondaryValue = $secondaryValue; - - $this->_getLineStyle(); - $this->_canvas->line(array('x0' => $x1, 'y0' => $y1, 'x1' => $x2, 'y1' => $y2)); - } - - $this->_canvas->endGroup(); - - return true; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Line.php,v 1.11 2005/08/03 21:21:58 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Grid.php + */ +require_once 'Image/Graph/Grid.php'; + +/** + * Display a grid + * + * {@link Image_Graph_Grid} + * + * @category Images + * @package Image_Graph + * @subpackage Grid + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Axis_Marker_Line extends Image_Graph_Grid +{ + + /** + * The value + * @var double + * @access private + */ + var $_value = false; + + /** + * Sets the value of the line marker (value on the axis) + * + * @param double $value the value + */ + function setValue($value) + { + $this->_value = $value; + } + + /** + * Output the grid + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + if (!$this->_primaryAxis) { + return false; + } + + $this->_canvas->startGroup(get_class($this)); + + $i = 0; + + $this->_value = min($this->_primaryAxis->_getMaximum(), max($this->_primaryAxis->_getMinimum(), $this->_value)); + + $secondaryPoints = $this->_getSecondaryAxisPoints(); + + reset($secondaryPoints); + list ($id, $previousSecondaryValue) = each($secondaryPoints); + while (list ($id, $secondaryValue) = each($secondaryPoints)) { + if ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_X) { + $p1 = array ('X' => $this->_value, 'Y' => $secondaryValue); + $p2 = array ('X' => $this->_value, 'Y' => $previousSecondaryValue); + } else { + $p1 = array ('X' => $secondaryValue, 'Y' => $this->_value); + $p2 = array ('X' => $previousSecondaryValue, 'Y' => $this->_value); + } + + $x1 = $this->_pointX($p1); + $y1 = $this->_pointY($p1); + $x2 = $this->_pointX($p2); + $y2 = $this->_pointY($p2); + + $previousSecondaryValue = $secondaryValue; + + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x1, 'y0' => $y1, 'x1' => $x2, 'y1' => $y2)); + } + + $this->_canvas->endGroup(); + + return true; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Axis/Radar.php b/includes/pear/Image/Graph/Axis/Radar.php index 6a1b95c1..18d9f12f 100644 --- a/includes/pear/Image/Graph/Axis/Radar.php +++ b/includes/pear/Image/Graph/Axis/Radar.php @@ -1,204 +1,204 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Radar.php,v 1.6 2005/08/03 21:22:11 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Axis/Category.php - */ -require_once 'Image/Graph/Axis/Category.php'; - -/** - * Displays an 'X'-axis in a radar plot chart. - * - * This axis maps the number of elements in the dataset to a angle (from 0- - * 360 degrees). Displaying the axis consist of drawing a number of lines from - * center to the edge of the 'circle' than encloses the radar plot. The labels - * are drawn on the 'ends' of these radial lines. - * - * @category Images - * @package Image_Graph - * @subpackage Axis - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Axis_Radar extends Image_Graph_Axis_Category -{ - - /** - * Specifies the number of pixels, the labels is offsetted from the end of - * the axis - * - * @var int - * @access private - */ - var $_distanceFromEnd = 5; - - /** - * Gets the minimum value the axis will show. - * - * This is always 0 - * - * @return double The minumum value - * @access private - */ - function _getMinimum() - { - return 0; - } - - /** - * Gets the maximum value the axis will show. - * - * This is always the number of labels passed to the constructor. - * - * @return double The maximum value - * @access private - */ - function _getMaximum() - { - return count($this->_labels); - } - - /** - * Calculate the delta value (the number of pixels representing one unit - * on the axis) - * - * @return double The label interval - * @access private - */ - function _calcDelta() - { - if (abs($this->_getMaximum() - $this->_getMinimum()) == 0) { - $this->_delta = false; - } else { - $this->_delta = 360 / ($this->_getMaximum() - $this->_getMinimum()); - } - } - - /** - * Get the pixel position represented by a value on the canvas - * - * @param double $value the value to get the pixel-point for - * @return double The pixel position along the axis - * @access private - */ - function _point($value) - { - return (90 + (int) ($this->_value($value) * $this->_delta)) % 360; - } - - /** - * Get the size in pixels of the axis. - * - * For a radar plot this is always 0 - * - * @return int The size of the axis - * @access private - */ - function _size() - { - return 0; - } - - /** - * Sets the distance from the end of the category lines to the label. - * - * @param int $distance The distance in pixels - */ - function setDistanceFromEnd($distance = 5) - { - $this->_distanceFromEnd = $distance; - } - - /** - * Draws axis lines. - * - * @access private - */ - function _drawAxisLines() - { - } - - /** - * Output an axis tick mark. - * - * @param int $value The value to output - * @access private - */ - function _drawTick($value, $level = 1) - { - $centerX = (int) (($this->_left + $this->_right) / 2); - $centerY = (int) (($this->_top + $this->_bottom) / 2); - - $radius = min($this->height(), $this->width()) / 2; - - $endPoint = array ('X' => $value, 'Y' => '#max#'); - $dX = $this->_pointX($endPoint); - $dY = $this->_pointY($endPoint); - - $offX = ($dX - $centerX); - $offY = ($dY - $centerY); - - $hyp = sqrt($offX*$offX + $offY*$offY); - if ($hyp != 0) { - $scale = $this->_distanceFromEnd / $hyp; - } else { - $scale = 1; - } - - $adX = $dX + $offX * $scale; - $adY = $dY + $offY * $scale; - - if (is_object($this->_dataPreProcessor)) { - $labelText = $this->_dataPreProcessor->_process($value); - } else { - $labelText = $value; - } - - if ((abs($dX - $centerX) < 1.5) && ($dY < $centerY)) { - $align = IMAGE_GRAPH_ALIGN_BOTTOM + IMAGE_GRAPH_ALIGN_CENTER_X; - } elseif ((abs($dX - $centerX) < 1.5) && ($dY > $centerY)) { - $align = IMAGE_GRAPH_ALIGN_TOP + IMAGE_GRAPH_ALIGN_CENTER_X; - } elseif ($dX < $centerX) { - $align = IMAGE_GRAPH_ALIGN_RIGHT + IMAGE_GRAPH_ALIGN_CENTER_Y; - } else { - $align = IMAGE_GRAPH_ALIGN_LEFT + IMAGE_GRAPH_ALIGN_CENTER_Y; - } - $this->write($adX, $adY, $labelText, $align); - - $this->_getLineStyle(); - $this->_canvas->line(array('x0' => $centerX, 'y0' => $centerY, 'x1' => $dX, 'y1' => $dY)); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Radar.php,v 1.6 2005/08/03 21:22:11 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Axis/Category.php + */ +require_once 'Image/Graph/Axis/Category.php'; + +/** + * Displays an 'X'-axis in a radar plot chart. + * + * This axis maps the number of elements in the dataset to a angle (from 0- + * 360 degrees). Displaying the axis consist of drawing a number of lines from + * center to the edge of the 'circle' than encloses the radar plot. The labels + * are drawn on the 'ends' of these radial lines. + * + * @category Images + * @package Image_Graph + * @subpackage Axis + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Axis_Radar extends Image_Graph_Axis_Category +{ + + /** + * Specifies the number of pixels, the labels is offsetted from the end of + * the axis + * + * @var int + * @access private + */ + var $_distanceFromEnd = 5; + + /** + * Gets the minimum value the axis will show. + * + * This is always 0 + * + * @return double The minumum value + * @access private + */ + function _getMinimum() + { + return 0; + } + + /** + * Gets the maximum value the axis will show. + * + * This is always the number of labels passed to the constructor. + * + * @return double The maximum value + * @access private + */ + function _getMaximum() + { + return count($this->_labels); + } + + /** + * Calculate the delta value (the number of pixels representing one unit + * on the axis) + * + * @return double The label interval + * @access private + */ + function _calcDelta() + { + if (abs($this->_getMaximum() - $this->_getMinimum()) == 0) { + $this->_delta = false; + } else { + $this->_delta = 360 / ($this->_getMaximum() - $this->_getMinimum()); + } + } + + /** + * Get the pixel position represented by a value on the canvas + * + * @param double $value the value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _point($value) + { + return (90 + (int) ($this->_value($value) * $this->_delta)) % 360; + } + + /** + * Get the size in pixels of the axis. + * + * For a radar plot this is always 0 + * + * @return int The size of the axis + * @access private + */ + function _size() + { + return 0; + } + + /** + * Sets the distance from the end of the category lines to the label. + * + * @param int $distance The distance in pixels + */ + function setDistanceFromEnd($distance = 5) + { + $this->_distanceFromEnd = $distance; + } + + /** + * Draws axis lines. + * + * @access private + */ + function _drawAxisLines() + { + } + + /** + * Output an axis tick mark. + * + * @param int $value The value to output + * @access private + */ + function _drawTick($value, $level = 1) + { + $centerX = (int) (($this->_left + $this->_right) / 2); + $centerY = (int) (($this->_top + $this->_bottom) / 2); + + $radius = min($this->height(), $this->width()) / 2; + + $endPoint = array ('X' => $value, 'Y' => '#max#'); + $dX = $this->_pointX($endPoint); + $dY = $this->_pointY($endPoint); + + $offX = ($dX - $centerX); + $offY = ($dY - $centerY); + + $hyp = sqrt($offX*$offX + $offY*$offY); + if ($hyp != 0) { + $scale = $this->_distanceFromEnd / $hyp; + } else { + $scale = 1; + } + + $adX = $dX + $offX * $scale; + $adY = $dY + $offY * $scale; + + if (is_object($this->_dataPreProcessor)) { + $labelText = $this->_dataPreProcessor->_process($value); + } else { + $labelText = $value; + } + + if ((abs($dX - $centerX) < 1.5) && ($dY < $centerY)) { + $align = IMAGE_GRAPH_ALIGN_BOTTOM + IMAGE_GRAPH_ALIGN_CENTER_X; + } elseif ((abs($dX - $centerX) < 1.5) && ($dY > $centerY)) { + $align = IMAGE_GRAPH_ALIGN_TOP + IMAGE_GRAPH_ALIGN_CENTER_X; + } elseif ($dX < $centerX) { + $align = IMAGE_GRAPH_ALIGN_RIGHT + IMAGE_GRAPH_ALIGN_CENTER_Y; + } else { + $align = IMAGE_GRAPH_ALIGN_LEFT + IMAGE_GRAPH_ALIGN_CENTER_Y; + } + $this->write($adX, $adY, $labelText, $align); + + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $centerX, 'y0' => $centerY, 'x1' => $dX, 'y1' => $dY)); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Common.php b/includes/pear/Image/Graph/Common.php index be671e23..d9e428d4 100644 --- a/includes/pear/Image/Graph/Common.php +++ b/includes/pear/Image/Graph/Common.php @@ -1,308 +1,313 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Common.php,v 1.14 2005/10/05 20:51:21 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -if (!function_exists('is_a')) { - - /** - * Check if an object is of a given class, this function is available as of PHP 4.2.0, so if it exist it will not be declared - * - * @link http://www.php.net/manual/en/function.is-a.php PHP.net Online Manual for function is_a() - * @param object $object The object to check class for - * @param string $class_name The name of the class to check the object for - * @return bool Returns TRUE if the object is of this class or has this class as one of its parents - */ - function is_a($object, $class_name) - { - if (empty ($object)) { - return false; - } - $object = is_object($object) ? get_class($object) : $object; - if (strtolower($object) == strtolower($class_name)) { - return true; - } - return is_a(get_parent_class($object), $class_name); - } -} - -/** - * Include file Image/Canvas.php - */ -require_once 'Image/Canvas.php'; - -/** - * The ultimate ancestor of all Image_Graph classes. - * - * This class contains common functionality needed by all Image_Graph classes. - * - * @category Images - * @package Image_Graph - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - * @abstract - */ -class Image_Graph_Common -{ - - /** - * The parent container of the current Image_Graph object - * - * @var Image_Graph_Common - * @access private - */ - var $_parent = null; - - /** - * The sub-elements of the current Image_Graph container object - * - * @var array - * @access private - */ - var $_elements; - - /** - * The canvas for output. - * - * Enables support for multiple output formats. - * - * @var Image_Canvas - * @access private - */ - var $_canvas = null; - - /** - * Is the object visible? - * - * @var bool - * @access private - */ - var $_visible = true; - - /** - * Constructor [Image_Graph_Common] - */ - function Image_Graph_Common() - { - } - - /** - * Resets the elements - * - * @access private - */ - function _reset() - { - if (is_array($this->_elements)) { - $keys = array_keys($this->_elements); - foreach ($keys as $key) { - if (is_object($this->_elements[$key])) { - $this->_elements[$key]->_setParent($this); - @$result =& $this->_elements[$key]->_reset(); - if (PEAR::isError($result)) { - return $result; - } - } - } - unset($keys); - } - return true; - } - - /** - * Sets the parent. The parent chain should ultimately be a GraPHP object - * - * @see Image_Graph_Common - * @param Image_Graph_Common $parent The parent - * @access private - */ - function _setParent(& $parent) - { - $this->_parent =& $parent; - $this->_canvas =& $this->_parent->_getCanvas(); - - if (is_array($this->_elements)) { - $keys = array_keys($this->_elements); - foreach ($keys as $key) { - if (is_object($this->_elements[$key])) { - $this->_elements[$key]->_setParent($this); - } - } - unset($keys); - } - } - - /** - * Hide the element - */ - function hide() - { - $this->_visible = false; - } - - /** - * Get the canvas - * - * @return Image_Canvas The canvas - * @access private - */ - function &_getCanvas() - { - if (($this->_canvas !== null) || ($this->_canvas !== false)) { - return $this->_canvas; - } elseif (is_a($this->_parent, 'Image_Graph_Common')) { - $this->_canvas =& $this->_parent->_getCanvas(); - return $this->_canvas; - } else { - $this->_error('Invalid canvas'); - $result = null; - return $result; - } - } - - /** - * Adds an element to the objects element list. - * - * The new Image_Graph_elements parent is automatically set. - * - * @param Image_Graph_Common $element The new Image_Graph_element - * @return Image_Graph_Common The new Image_Graph_element - */ - function &add(& $element) - { - if (!is_a($element, 'Image_Graph_Font')) { - $this->_elements[] = &$element; - } - $element->_setParent($this); - return $element; - } - - /** - * Creates an object from the class and adds it to the objects element list. - * - * Creates an object from the class specified and adds it to the objects - * element list. If only one parameter is required for the constructor of - * the class simply pass this parameter as the $params parameter, unless the - * parameter is an array or a reference to a value, in that case you must - * 'enclose' the parameter in an array. Similar if the constructor takes - * more than one parameter specify the parameters in an array. - * - * @see Image_Graph::factory() - * @param string $class The class for the object - * @param mixed $params The paramaters to pass to the constructor - * @return Image_Graph_Common The new Image_Graph_element - */ - function &addNew($class, $params = null, $additional = false) - { - include_once 'Image/Graph.php'; - $element =& Image_Graph::factory($class, $params); - if ($additional === false) { - $obj =& $this->add($element); - } else { - $obj =& $this->add($element, $additional); - } - return $obj; - } - - /** - * Shows an error message box on the canvas - * - * @param string $text The error text - * @param array $params An array containing error specific details - * @param int $error_code Error code - * @access private - */ - function _error($text, $params = false, $error_code = IMAGE_GRAPH_ERROR_GENERIC) - { - foreach ($params as $name => $key) { - if (isset($parameters)) { - $parameters .= ' '; - } - $parameters .= $name . '=' . $key; - } - $error =& PEAR::raiseError( - $text . - ($error_code != IMAGE_GRAPH_ERROR_GENERIC ? ' error:' . IMAGE_GRAPH_ERROR_GENERIC : '') . - (isset($parameters) ? ' parameters:[' . $parameters . ']' : '') - ); - } - - /** - * Causes the object to update all sub elements coordinates - * - * (Image_Graph_Common, does not itself have coordinates, this is basically - * an abstract method) - * - * @access private - */ - function _updateCoords() - { - if (is_array($this->_elements)) { - $keys = array_keys($this->_elements); - foreach ($keys as $key) { - if (is_object($this->_elements[$key])) { - $this->_elements[$key]->_updateCoords(); - } - } - unset($keys); - } - return true; - } - - /** - * Causes output to canvas - * - * The last method to call. Calling Done causes output to the canvas. All - * sub elements done() method will be invoked - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (($this->_canvas == null) || (!is_a($this->_canvas, 'Image_Canvas'))) { - return false; - } - - if (is_array($this->_elements)) { - $keys = array_keys($this->_elements); - foreach ($keys as $key) { - if (($this->_elements[$key]->_visible) && ($this->_elements[$key]->_done() === false)) { - return false; - } - } - unset($keys); - } - return true; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Common.php,v 1.16 2006/02/28 22:48:07 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +if (!function_exists('is_a')) { + + /** + * Check if an object is of a given class, this function is available as of PHP 4.2.0, so if it exist it will not be declared + * + * @link http://www.php.net/manual/en/function.is-a.php PHP.net Online Manual for function is_a() + * @param object $object The object to check class for + * @param string $class_name The name of the class to check the object for + * @return bool Returns TRUE if the object is of this class or has this class as one of its parents + */ + function is_a($object, $class_name) + { + if (empty ($object)) { + return false; + } + $object = is_object($object) ? get_class($object) : $object; + if (strtolower($object) == strtolower($class_name)) { + return true; + } + return is_a(get_parent_class($object), $class_name); + } +} + +/** + * Include file Image/Canvas.php + */ +require_once 'Image/Canvas.php'; + +/** + * The ultimate ancestor of all Image_Graph classes. + * + * This class contains common functionality needed by all Image_Graph classes. + * + * @category Images + * @package Image_Graph + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + * @abstract + */ +class Image_Graph_Common +{ + + /** + * The parent container of the current Image_Graph object + * + * @var Image_Graph_Common + * @access private + */ + var $_parent = null; + + /** + * The sub-elements of the current Image_Graph container object + * + * @var array + * @access private + */ + var $_elements; + + /** + * The canvas for output. + * + * Enables support for multiple output formats. + * + * @var Image_Canvas + * @access private + */ + var $_canvas = null; + + /** + * Is the object visible? + * + * @var bool + * @access private + */ + var $_visible = true; + + /** + * Constructor [Image_Graph_Common] + */ + function Image_Graph_Common() + { + } + + /** + * Resets the elements + * + * @access private + */ + function _reset() + { + if (is_array($this->_elements)) { + $keys = array_keys($this->_elements); + foreach ($keys as $key) { + if (is_object($this->_elements[$key])) { + $this->_elements[$key]->_setParent($this); + $result =& $this->_elements[$key]->_reset(); + if (PEAR::isError($result)) { + return $result; + } + } + } + unset($keys); + } + return true; + } + + /** + * Sets the parent. The parent chain should ultimately be a GraPHP object + * + * @see Image_Graph_Common + * @param Image_Graph_Common $parent The parent + * @access private + */ + function _setParent(& $parent) + { + $this->_parent =& $parent; + $this->_canvas =& $this->_parent->_getCanvas(); + + if (is_array($this->_elements)) { + $keys = array_keys($this->_elements); + foreach ($keys as $key) { + if (is_object($this->_elements[$key])) { + $this->_elements[$key]->_setParent($this); + } + } + unset($keys); + } + } + + /** + * Hide the element + */ + function hide() + { + $this->_visible = false; + } + + /** + * Get the canvas + * + * @return Image_Canvas The canvas + * @access private + */ + function &_getCanvas() + { + if (($this->_canvas !== null) || ($this->_canvas !== false)) { + return $this->_canvas; + } elseif (is_a($this->_parent, 'Image_Graph_Common')) { + $this->_canvas =& $this->_parent->_getCanvas(); + return $this->_canvas; + } else { + $this->_error('Invalid canvas'); + $result = null; + return $result; + } + } + + /** + * Adds an element to the objects element list. + * + * The new Image_Graph_elements parent is automatically set. + * + * @param Image_Graph_Common $element The new Image_Graph_element + * @return Image_Graph_Common The new Image_Graph_element + */ + function &add(& $element) + { + if (!is_a($element, 'Image_Graph_Font')) { + $this->_elements[] = &$element; + } + $element->_setParent($this); + return $element; + } + + /** + * Creates an object from the class and adds it to the objects element list. + * + * Creates an object from the class specified and adds it to the objects + * element list. If only one parameter is required for the constructor of + * the class simply pass this parameter as the $params parameter, unless the + * parameter is an array or a reference to a value, in that case you must + * 'enclose' the parameter in an array. Similar if the constructor takes + * more than one parameter specify the parameters in an array. + * + * @see Image_Graph::factory() + * @param string $class The class for the object + * @param mixed $params The paramaters to pass to the constructor + * @return Image_Graph_Common The new Image_Graph_element + */ + function &addNew($class, $params = null, $additional = false) + { + include_once 'Image/Graph.php'; + $element =& Image_Graph::factory($class, $params); + if ($additional === false) { + $obj =& $this->add($element); + } else { + $obj =& $this->add($element, $additional); + } + return $obj; + } + + /** + * Shows an error message box on the canvas + * + * @param string $text The error text + * @param array $params An array containing error specific details + * @param int $error_code Error code + * @access private + */ + function _error($text, $params = false, $error_code = IMAGE_GRAPH_ERROR_GENERIC) + { + if ((is_array($params)) && (count($params) > 0)) { + foreach ($params as $name => $key) { + if (isset($parameters)) { + $parameters .= ' '; + } + else { + $parameters = ''; + } + $parameters .= $name . '=' . $key; + } + } + $error =& PEAR::raiseError( + $text . + ($error_code != IMAGE_GRAPH_ERROR_GENERIC ? ' error:' . IMAGE_GRAPH_ERROR_GENERIC : '') . + (isset($parameters) ? ' parameters:[' . $parameters . ']' : '') + ); + } + + /** + * Causes the object to update all sub elements coordinates + * + * (Image_Graph_Common, does not itself have coordinates, this is basically + * an abstract method) + * + * @access private + */ + function _updateCoords() + { + if (is_array($this->_elements)) { + $keys = array_keys($this->_elements); + foreach ($keys as $key) { + if (is_object($this->_elements[$key])) { + $this->_elements[$key]->_updateCoords(); + } + } + unset($keys); + } + return true; + } + + /** + * Causes output to canvas + * + * The last method to call. Calling Done causes output to the canvas. All + * sub elements done() method will be invoked + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (($this->_canvas == null) || (!is_a($this->_canvas, 'Image_Canvas'))) { + return false; + } + + if (is_array($this->_elements)) { + $keys = array_keys($this->_elements); + foreach ($keys as $key) { + if (($this->_elements[$key]->_visible) && ($this->_elements[$key]->_done() === false)) { + return false; + } + } + unset($keys); + } + return true; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Config.php b/includes/pear/Image/Graph/Config.php index f5385556..aa5ddf5e 100644 --- a/includes/pear/Image/Graph/Config.php +++ b/includes/pear/Image/Graph/Config.php @@ -1,30 +1,30 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Config.php,v 1.7 2005/08/03 21:21:52 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Config.php,v 1.7 2005/08/03 21:21:52 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Constants.php b/includes/pear/Image/Graph/Constants.php index 030f36d6..669be4de 100644 --- a/includes/pear/Image/Graph/Constants.php +++ b/includes/pear/Image/Graph/Constants.php @@ -1,225 +1,225 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Constants.php,v 1.7 2005/08/03 21:21:52 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Font.php - */ -require_once 'Image/Graph/Font.php'; - -// Constant declarations - -/** - * Defines an X (horizontal) axis - */ -define('IMAGE_GRAPH_AXIS_X', 1); - -/** - * Defines an Y (vertical) axis - */ -define('IMAGE_GRAPH_AXIS_Y', 2); - -/** - * Defines an Y (vertical) axis - */ -define('IMAGE_GRAPH_AXIS_Y_SECONDARY', 3); - -/** - * Defines an horizontal (X) axis - */ -define('IMAGE_GRAPH_AXIS_HORIZONTAL', 1); - -/** - * Defines an vertical (Y) axis - */ -define('IMAGE_GRAPH_AXIS_VERTICAL', 2); - -/** - * Define if label should be shown for axis minimum value - */ -define('IMAGE_GRAPH_LABEL_MINIMUM', 1); - -/** - * Define if label should be shown for axis 0 (zero) value - */ -define('IMAGE_GRAPH_LABEL_ZERO', 2); - -/** - * Define if label should be shown for axis maximum value - */ -define('IMAGE_GRAPH_LABEL_MAXIMUM', 4); - -/** - * Defines a horizontal gradient fill - */ -define('IMAGE_GRAPH_GRAD_HORIZONTAL', 1); - -/** - * Defines a vertical gradient fill - */ -define('IMAGE_GRAPH_GRAD_VERTICAL', 2); - -/** - * Defines a horizontally mirrored gradient fill - */ -define('IMAGE_GRAPH_GRAD_HORIZONTAL_MIRRORED', 3); - -/** - * Defines a vertically mirrored gradient fill - */ -define('IMAGE_GRAPH_GRAD_VERTICAL_MIRRORED', 4); - -/** - * Defines a diagonal gradient fill from top-left to bottom-right - */ -define('IMAGE_GRAPH_GRAD_DIAGONALLY_TL_BR', 5); - -/** - * Defines a diagonal gradient fill from bottom-left to top-right - */ -define('IMAGE_GRAPH_GRAD_DIAGONALLY_BL_TR', 6); - -/** - * Defines a radial gradient fill - */ -define('IMAGE_GRAPH_GRAD_RADIAL', 7); - -/** - * Defines the default builtin font - */ -define('IMAGE_GRAPH_FONT', 1); - -/** - * Defines a X value should be used - */ -define('IMAGE_GRAPH_VALUE_X', 0); - -/** - * Defines a Y value should be used - */ -define('IMAGE_GRAPH_VALUE_Y', 1); - -/** - * Defines a min X% value should be used - */ -define('IMAGE_GRAPH_PCT_X_MIN', 2); - -/** - * Defines a max X% value should be used - */ -define('IMAGE_GRAPH_PCT_X_MAX', 3); - -/** - * Defines a min Y% value should be used - */ -define('IMAGE_GRAPH_PCT_Y_MIN', 4); - -/** - * Defines a max Y% value should be used - */ -define('IMAGE_GRAPH_PCT_Y_MAX', 5); - -/** - * Defines a total Y% value should be used - */ -define('IMAGE_GRAPH_PCT_Y_TOTAL', 6); - -/** - * Defines a ID value should be used - */ -define('IMAGE_GRAPH_POINT_ID', 7); - -/** - * Align text left - */ -define('IMAGE_GRAPH_ALIGN_LEFT', 0x1); - -/** - * Align text right - */ -define('IMAGE_GRAPH_ALIGN_RIGHT', 0x2); - -/** - * Align text center x (horizontal) - */ -define('IMAGE_GRAPH_ALIGN_CENTER_X', 0x4); - -/** - * Align text top - */ -define('IMAGE_GRAPH_ALIGN_TOP', 0x8); - -/** - * Align text bottom - */ -define('IMAGE_GRAPH_ALIGN_BOTTOM', 0x10); - -/** - * Align text center y (vertical) - */ -define('IMAGE_GRAPH_ALIGN_CENTER_Y', 0x20); - -/** - * Align text center (both x and y) - */ -define('IMAGE_GRAPH_ALIGN_CENTER', IMAGE_GRAPH_ALIGN_CENTER_X + IMAGE_GRAPH_ALIGN_CENTER_Y); - -/** - * Align text top left - */ -define('IMAGE_GRAPH_ALIGN_TOP_LEFT', IMAGE_GRAPH_ALIGN_TOP + IMAGE_GRAPH_ALIGN_LEFT); - -/** - * Align text top right - */ -define('IMAGE_GRAPH_ALIGN_TOP_RIGHT', IMAGE_GRAPH_ALIGN_TOP + IMAGE_GRAPH_ALIGN_RIGHT); - -/** - * Align text bottom left - */ -define('IMAGE_GRAPH_ALIGN_BOTTOM_LEFT', IMAGE_GRAPH_ALIGN_BOTTOM + IMAGE_GRAPH_ALIGN_LEFT); - -/** - * Align text bottom right - */ -define('IMAGE_GRAPH_ALIGN_BOTTOM_RIGHT', IMAGE_GRAPH_ALIGN_BOTTOM + IMAGE_GRAPH_ALIGN_RIGHT); - -/** - * Align vertical - */ -define('IMAGE_GRAPH_ALIGN_VERTICAL', IMAGE_GRAPH_ALIGN_TOP); - -/** - * Align horizontal - */ -define('IMAGE_GRAPH_ALIGN_HORIZONTAL', IMAGE_GRAPH_ALIGN_LEFT); - -// Error codes -define('IMAGE_GRAPH_ERROR_GENERIC', 0); - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Constants.php,v 1.7 2005/08/03 21:21:52 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Font.php + */ +require_once 'Image/Graph/Font.php'; + +// Constant declarations + +/** + * Defines an X (horizontal) axis + */ +define('IMAGE_GRAPH_AXIS_X', 1); + +/** + * Defines an Y (vertical) axis + */ +define('IMAGE_GRAPH_AXIS_Y', 2); + +/** + * Defines an Y (vertical) axis + */ +define('IMAGE_GRAPH_AXIS_Y_SECONDARY', 3); + +/** + * Defines an horizontal (X) axis + */ +define('IMAGE_GRAPH_AXIS_HORIZONTAL', 1); + +/** + * Defines an vertical (Y) axis + */ +define('IMAGE_GRAPH_AXIS_VERTICAL', 2); + +/** + * Define if label should be shown for axis minimum value + */ +define('IMAGE_GRAPH_LABEL_MINIMUM', 1); + +/** + * Define if label should be shown for axis 0 (zero) value + */ +define('IMAGE_GRAPH_LABEL_ZERO', 2); + +/** + * Define if label should be shown for axis maximum value + */ +define('IMAGE_GRAPH_LABEL_MAXIMUM', 4); + +/** + * Defines a horizontal gradient fill + */ +define('IMAGE_GRAPH_GRAD_HORIZONTAL', 1); + +/** + * Defines a vertical gradient fill + */ +define('IMAGE_GRAPH_GRAD_VERTICAL', 2); + +/** + * Defines a horizontally mirrored gradient fill + */ +define('IMAGE_GRAPH_GRAD_HORIZONTAL_MIRRORED', 3); + +/** + * Defines a vertically mirrored gradient fill + */ +define('IMAGE_GRAPH_GRAD_VERTICAL_MIRRORED', 4); + +/** + * Defines a diagonal gradient fill from top-left to bottom-right + */ +define('IMAGE_GRAPH_GRAD_DIAGONALLY_TL_BR', 5); + +/** + * Defines a diagonal gradient fill from bottom-left to top-right + */ +define('IMAGE_GRAPH_GRAD_DIAGONALLY_BL_TR', 6); + +/** + * Defines a radial gradient fill + */ +define('IMAGE_GRAPH_GRAD_RADIAL', 7); + +/** + * Defines the default builtin font + */ +define('IMAGE_GRAPH_FONT', 1); + +/** + * Defines a X value should be used + */ +define('IMAGE_GRAPH_VALUE_X', 0); + +/** + * Defines a Y value should be used + */ +define('IMAGE_GRAPH_VALUE_Y', 1); + +/** + * Defines a min X% value should be used + */ +define('IMAGE_GRAPH_PCT_X_MIN', 2); + +/** + * Defines a max X% value should be used + */ +define('IMAGE_GRAPH_PCT_X_MAX', 3); + +/** + * Defines a min Y% value should be used + */ +define('IMAGE_GRAPH_PCT_Y_MIN', 4); + +/** + * Defines a max Y% value should be used + */ +define('IMAGE_GRAPH_PCT_Y_MAX', 5); + +/** + * Defines a total Y% value should be used + */ +define('IMAGE_GRAPH_PCT_Y_TOTAL', 6); + +/** + * Defines a ID value should be used + */ +define('IMAGE_GRAPH_POINT_ID', 7); + +/** + * Align text left + */ +define('IMAGE_GRAPH_ALIGN_LEFT', 0x1); + +/** + * Align text right + */ +define('IMAGE_GRAPH_ALIGN_RIGHT', 0x2); + +/** + * Align text center x (horizontal) + */ +define('IMAGE_GRAPH_ALIGN_CENTER_X', 0x4); + +/** + * Align text top + */ +define('IMAGE_GRAPH_ALIGN_TOP', 0x8); + +/** + * Align text bottom + */ +define('IMAGE_GRAPH_ALIGN_BOTTOM', 0x10); + +/** + * Align text center y (vertical) + */ +define('IMAGE_GRAPH_ALIGN_CENTER_Y', 0x20); + +/** + * Align text center (both x and y) + */ +define('IMAGE_GRAPH_ALIGN_CENTER', IMAGE_GRAPH_ALIGN_CENTER_X + IMAGE_GRAPH_ALIGN_CENTER_Y); + +/** + * Align text top left + */ +define('IMAGE_GRAPH_ALIGN_TOP_LEFT', IMAGE_GRAPH_ALIGN_TOP + IMAGE_GRAPH_ALIGN_LEFT); + +/** + * Align text top right + */ +define('IMAGE_GRAPH_ALIGN_TOP_RIGHT', IMAGE_GRAPH_ALIGN_TOP + IMAGE_GRAPH_ALIGN_RIGHT); + +/** + * Align text bottom left + */ +define('IMAGE_GRAPH_ALIGN_BOTTOM_LEFT', IMAGE_GRAPH_ALIGN_BOTTOM + IMAGE_GRAPH_ALIGN_LEFT); + +/** + * Align text bottom right + */ +define('IMAGE_GRAPH_ALIGN_BOTTOM_RIGHT', IMAGE_GRAPH_ALIGN_BOTTOM + IMAGE_GRAPH_ALIGN_RIGHT); + +/** + * Align vertical + */ +define('IMAGE_GRAPH_ALIGN_VERTICAL', IMAGE_GRAPH_ALIGN_TOP); + +/** + * Align horizontal + */ +define('IMAGE_GRAPH_ALIGN_HORIZONTAL', IMAGE_GRAPH_ALIGN_LEFT); + +// Error codes +define('IMAGE_GRAPH_ERROR_GENERIC', 0); + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/DataPreprocessor.php b/includes/pear/Image/Graph/DataPreprocessor.php index 6bdf37aa..1806d81b 100644 --- a/includes/pear/Image/Graph/DataPreprocessor.php +++ b/includes/pear/Image/Graph/DataPreprocessor.php @@ -1,74 +1,74 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: DataPreprocessor.php,v 1.7 2005/08/24 20:35:55 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Data preprocessor used for preformatting a data. - * - * A data preprocessor is used in cases where a value from a dataset or label must be - * displayed in another format or way than entered. This could for example be the need - * to display X-values as a date instead of 1, 2, 3, .. or even worse unix-timestamps. - * It could also be when a {@link Image_Graph_Marker_Value} needs to display values as percentages - * with 1 decimal digit instead of the default formatting (fx. 12.01271 -> 12.0%). - * - * @category Images - * @package Image_Graph - * @subpackage DataPreprocessor - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - * @abstract - */ -class Image_Graph_DataPreprocessor -{ - - /** - * Image_Graph_DataPreprocessor [Constructor]. - */ - function Image_Graph_DataPreprocessor() - { - } - - /** - * Process the value - * - * @param var $value The value to process/format - * @return string The processed value - * @access private - */ - function _process($value) - { - return $value; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: DataPreprocessor.php,v 1.7 2005/08/24 20:35:55 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Data preprocessor used for preformatting a data. + * + * A data preprocessor is used in cases where a value from a dataset or label must be + * displayed in another format or way than entered. This could for example be the need + * to display X-values as a date instead of 1, 2, 3, .. or even worse unix-timestamps. + * It could also be when a {@link Image_Graph_Marker_Value} needs to display values as percentages + * with 1 decimal digit instead of the default formatting (fx. 12.01271 -> 12.0%). + * + * @category Images + * @package Image_Graph + * @subpackage DataPreprocessor + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + * @abstract + */ +class Image_Graph_DataPreprocessor +{ + + /** + * Image_Graph_DataPreprocessor [Constructor]. + */ + function Image_Graph_DataPreprocessor() + { + } + + /** + * Process the value + * + * @param var $value The value to process/format + * @return string The processed value + * @access private + */ + function _process($value) + { + return $value; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/DataPreprocessor/Array.php b/includes/pear/Image/Graph/DataPreprocessor/Array.php index 4586055a..6a6b808d 100644 --- a/includes/pear/Image/Graph/DataPreprocessor/Array.php +++ b/includes/pear/Image/Graph/DataPreprocessor/Array.php @@ -1,103 +1,103 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Array.php,v 1.6 2005/08/24 20:35:59 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/DataPreprocessor.php - */ -require_once 'Image/Graph/DataPreprocessor.php'; - -/** - * Format data as looked up in an array. - * - * ArrayData is useful when a numercal value is to be translated to - * something thats cannot directly be calculated from this value, this could for - * example be a dataset meant to plot population of various countries. Since x- - * values are numerical and they should really be country names, but there is no - * linear correlation between the number and the name, we use an array to 'map' - * the numbers to the name, i.e. $array[0] = 'Denmark'; $array[1] = 'Sweden'; - * ..., where the indexes are the numerical values from the dataset. This is NOT - * usefull when the x-values are a large domain, i.e. to map unix timestamps to - * date-strings for an x-axis. This is because the x-axis will selecte arbitrary - * values for labels, which would in principle require the ArrayData to hold - * values for every unix timestamp. However ArrayData can still be used to solve - * such a situation, since one can use another value for X-data in the dataset - * and then map this (smaller domain) value to a date. That is we for example - * instead of using the unix-timestamp we use value 0 to represent the 1st date, - * 1 to represent the next date, etc. - * - * @category Images - * @package Image_Graph - * @subpackage DataPreprocessor - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_DataPreprocessor_Array extends Image_Graph_DataPreprocessor -{ - - /** - * The data label array - * @var array - * @access private - */ - var $_dataArray; - - /** - * Image_Graph_ArrayData [Constructor]. - * - * @param array $array The array to use as a lookup table - */ - function Image_Graph_DataPreprocessor_Array($array) - { - parent::Image_Graph_DataPreprocessor(); - $this->_dataArray = $array; - } - - /** - * Process the value - * - * @param var $value The value to process/format - * @return string The processed value - * @access private - */ - function _process($value) - { - if ((is_array($this->_dataArray)) && (isset ($this->_dataArray[$value]))) { - return $this->_dataArray[$value]; - } else { - return $value; - } - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Array.php,v 1.6 2005/08/24 20:35:59 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/DataPreprocessor.php + */ +require_once 'Image/Graph/DataPreprocessor.php'; + +/** + * Format data as looked up in an array. + * + * ArrayData is useful when a numercal value is to be translated to + * something thats cannot directly be calculated from this value, this could for + * example be a dataset meant to plot population of various countries. Since x- + * values are numerical and they should really be country names, but there is no + * linear correlation between the number and the name, we use an array to 'map' + * the numbers to the name, i.e. $array[0] = 'Denmark'; $array[1] = 'Sweden'; + * ..., where the indexes are the numerical values from the dataset. This is NOT + * usefull when the x-values are a large domain, i.e. to map unix timestamps to + * date-strings for an x-axis. This is because the x-axis will selecte arbitrary + * values for labels, which would in principle require the ArrayData to hold + * values for every unix timestamp. However ArrayData can still be used to solve + * such a situation, since one can use another value for X-data in the dataset + * and then map this (smaller domain) value to a date. That is we for example + * instead of using the unix-timestamp we use value 0 to represent the 1st date, + * 1 to represent the next date, etc. + * + * @category Images + * @package Image_Graph + * @subpackage DataPreprocessor + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_DataPreprocessor_Array extends Image_Graph_DataPreprocessor +{ + + /** + * The data label array + * @var array + * @access private + */ + var $_dataArray; + + /** + * Image_Graph_ArrayData [Constructor]. + * + * @param array $array The array to use as a lookup table + */ + function Image_Graph_DataPreprocessor_Array($array) + { + parent::Image_Graph_DataPreprocessor(); + $this->_dataArray = $array; + } + + /** + * Process the value + * + * @param var $value The value to process/format + * @return string The processed value + * @access private + */ + function _process($value) + { + if ((is_array($this->_dataArray)) && (isset ($this->_dataArray[$value]))) { + return $this->_dataArray[$value]; + } else { + return $value; + } + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/DataPreprocessor/Currency.php b/includes/pear/Image/Graph/DataPreprocessor/Currency.php index 35aa96f2..eb24e175 100644 --- a/includes/pear/Image/Graph/DataPreprocessor/Currency.php +++ b/includes/pear/Image/Graph/DataPreprocessor/Currency.php @@ -1,66 +1,66 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Currency.php,v 1.6 2005/08/24 20:35:59 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/DataPreprocessor/Formatted.php - */ -require_once 'Image/Graph/DataPreprocessor/Formatted.php'; - -/** - * Format data as a currency. - * - * Uses the {@link Image_Graph_DataPreprocessor_Formatted} to represent the - * values as a currency, i.e. 10 => € 10.00 - * - * @category Images - * @package Image_Graph - * @subpackage DataPreprocessor - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_DataPreprocessor_Currency extends Image_Graph_DataPreprocessor_Formatted -{ - - /** - * Image_Graph_CurrencyData [Constructor]. - * - * @param string $currencySymbol The symbol representing the currency - */ - function Image_Graph_DataPreprocessor_Currency($currencySymbol) - { - parent::Image_Graph_DataPreprocessor_Formatted("$currencySymbol %0.2f"); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Currency.php,v 1.6 2005/08/24 20:35:59 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/DataPreprocessor/Formatted.php + */ +require_once 'Image/Graph/DataPreprocessor/Formatted.php'; + +/** + * Format data as a currency. + * + * Uses the {@link Image_Graph_DataPreprocessor_Formatted} to represent the + * values as a currency, i.e. 10 => € 10.00 + * + * @category Images + * @package Image_Graph + * @subpackage DataPreprocessor + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_DataPreprocessor_Currency extends Image_Graph_DataPreprocessor_Formatted +{ + + /** + * Image_Graph_CurrencyData [Constructor]. + * + * @param string $currencySymbol The symbol representing the currency + */ + function Image_Graph_DataPreprocessor_Currency($currencySymbol) + { + parent::Image_Graph_DataPreprocessor_Formatted("$currencySymbol %0.2f"); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/DataPreprocessor/Date.php b/includes/pear/Image/Graph/DataPreprocessor/Date.php index e522b6d3..4fe83af8 100644 --- a/includes/pear/Image/Graph/DataPreprocessor/Date.php +++ b/includes/pear/Image/Graph/DataPreprocessor/Date.php @@ -1,90 +1,90 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Date.php,v 1.6 2005/08/24 20:35:59 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/DataPreprocessor.php - */ -require_once 'Image/Graph/DataPreprocessor.php'; - -/** - * Formats Unix timestamp as a date using specified format. - * - * @category Images - * @package Image_Graph - * @subpackage DataPreprocessor - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_DataPreprocessor_Date extends Image_Graph_DataPreprocessor -{ - - /** - * The format of the Unix time stamp. - * See PHP - * Manual for a description - * @var string - * @access private - */ - var $_format; - - /** - * Create a DateData preprocessor [Constructor] - * - * @param string $format See {@link http://www.php.net/manual/en/function.date.php - * PHP Manual} for a description - */ - function Image_Graph_DataPreprocessor_Date($format) - { - parent::Image_Graph_DataPreprocessor(); - $this->_format = $format; - } - - /** - * Process the value - * - * @param var $value The value to process/format - * @return string The processed value - * @access private - */ - function _process($value) - { - if (!$value) { - return false; - } else { - return date($this->_format, $value); - } - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Date.php,v 1.6 2005/08/24 20:35:59 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/DataPreprocessor.php + */ +require_once 'Image/Graph/DataPreprocessor.php'; + +/** + * Formats Unix timestamp as a date using specified format. + * + * @category Images + * @package Image_Graph + * @subpackage DataPreprocessor + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_DataPreprocessor_Date extends Image_Graph_DataPreprocessor +{ + + /** + * The format of the Unix time stamp. + * See PHP + * Manual for a description + * @var string + * @access private + */ + var $_format; + + /** + * Create a DateData preprocessor [Constructor] + * + * @param string $format See {@link http://www.php.net/manual/en/function.date.php + * PHP Manual} for a description + */ + function Image_Graph_DataPreprocessor_Date($format) + { + parent::Image_Graph_DataPreprocessor(); + $this->_format = $format; + } + + /** + * Process the value + * + * @param var $value The value to process/format + * @return string The processed value + * @access private + */ + function _process($value) + { + if (!$value) { + return false; + } else { + return date($this->_format, $value); + } + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/DataPreprocessor/Formatted.php b/includes/pear/Image/Graph/DataPreprocessor/Formatted.php index d5fec662..499b14c2 100644 --- a/includes/pear/Image/Graph/DataPreprocessor/Formatted.php +++ b/includes/pear/Image/Graph/DataPreprocessor/Formatted.php @@ -1,90 +1,90 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Formatted.php,v 1.6 2005/08/24 20:35:59 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/DataPreprocessor.php - */ -require_once 'Image/Graph/DataPreprocessor.php'; - -/** - * Format data using a (s)printf pattern. - * - * This method is useful when data must displayed using a simple (s) printf - * pattern as described in the {@link http://www.php. net/manual/en/function. - * sprintf.php PHP manual} - * - * @category Images - * @package Image_Graph - * @subpackage DataPreprocessor - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_DataPreprocessor_Formatted extends Image_Graph_DataPreprocessor -{ - - /** - * A (s)printf format string. - * See {@link http://www.php.net/manual/en/function.sprintf.php PHP Manual} - * for a description - * @var string - * @access private - */ - var $_format; - - /** - * Create a (s)printf format data preprocessor - * - * @param string $format See {@link http://www.php.net/manual/en/function.sprintf.php - * PHP Manual} for a description - */ - function Image_Graph_DataPreprocessor_Formatted($format) - { - parent::Image_Graph_DataPreprocessor(); - $this->_format = $format; - } - - /** - * Process the value - * - * @param var $value The value to process/format - * @return string The processed value - * @access private - */ - function _process($value) - { - return sprintf($this->_format, $value); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Formatted.php,v 1.6 2005/08/24 20:35:59 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/DataPreprocessor.php + */ +require_once 'Image/Graph/DataPreprocessor.php'; + +/** + * Format data using a (s)printf pattern. + * + * This method is useful when data must displayed using a simple (s) printf + * pattern as described in the {@link http://www.php. net/manual/en/function. + * sprintf.php PHP manual} + * + * @category Images + * @package Image_Graph + * @subpackage DataPreprocessor + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_DataPreprocessor_Formatted extends Image_Graph_DataPreprocessor +{ + + /** + * A (s)printf format string. + * See {@link http://www.php.net/manual/en/function.sprintf.php PHP Manual} + * for a description + * @var string + * @access private + */ + var $_format; + + /** + * Create a (s)printf format data preprocessor + * + * @param string $format See {@link http://www.php.net/manual/en/function.sprintf.php + * PHP Manual} for a description + */ + function Image_Graph_DataPreprocessor_Formatted($format) + { + parent::Image_Graph_DataPreprocessor(); + $this->_format = $format; + } + + /** + * Process the value + * + * @param var $value The value to process/format + * @return string The processed value + * @access private + */ + function _process($value) + { + return sprintf($this->_format, $value); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/DataPreprocessor/Function.php b/includes/pear/Image/Graph/DataPreprocessor/Function.php index ba1bacbc..d08025b8 100644 --- a/includes/pear/Image/Graph/DataPreprocessor/Function.php +++ b/includes/pear/Image/Graph/DataPreprocessor/Function.php @@ -1,92 +1,92 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Function.php,v 1.6 2005/08/24 20:35:59 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/DataPreprocessor.php - */ -require_once 'Image/Graph/DataPreprocessor.php'; - -/** - * Formatting a value using a userdefined function. - * - * Use this method to convert/format a value to a 'displayable' lable using a (perhaps) - * more complex function. An example could be (not very applicable though) if one would - * need for values to be displayed on the reverse order, i.e. 1234 would be displayed as - * 4321, then this method can solve this by creating the function that converts the value - * and use the FunctionData datapreprocessor to make Image_Graph use this function. - * - * @category Images - * @package Image_Graph - * @subpackage DataPreprocessor - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_DataPreprocessor_Function extends Image_Graph_DataPreprocessor -{ - - /** - * The name of the PHP function - * @var string - * @access private - */ - var $_dataFunction; - - /** - * Create a FunctionData preprocessor - * - * @param string $function The name of the PHP function to use as - * a preprocessor, this function must take a single parameter and return a - * formatted version of this parameter - */ - function Image_Graph_DataPreprocessor_Function($function) - { - parent::Image_Graph_DataPreprocessor(); - $this->_dataFunction = $function; - } - - /** - * Process the value - * - * @param var $value The value to process/format - * @return string The processed value - * @access private - */ - function _process($value) - { - $function = $this->_dataFunction; - return $function ($value); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Function.php,v 1.7 2005/11/11 17:53:44 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/DataPreprocessor.php + */ +require_once 'Image/Graph/DataPreprocessor.php'; + +/** + * Formatting a value using a userdefined function. + * + * Use this method to convert/format a value to a 'displayable' lable using a (perhaps) + * more complex function. An example could be (not very applicable though) if one would + * need for values to be displayed on the reverse order, i.e. 1234 would be displayed as + * 4321, then this method can solve this by creating the function that converts the value + * and use the FunctionData datapreprocessor to make Image_Graph use this function. + * + * @category Images + * @package Image_Graph + * @subpackage DataPreprocessor + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_DataPreprocessor_Function extends Image_Graph_DataPreprocessor +{ + + /** + * The name of the PHP function + * @var string + * @access private + */ + var $_dataFunction; + + /** + * Create a FunctionData preprocessor + * + * @param string $function The name of the PHP function to use as + * a preprocessor, this function must take a single parameter and return a + * formatted version of this parameter + */ + function Image_Graph_DataPreprocessor_Function($function) + { + parent::Image_Graph_DataPreprocessor(); + $this->_dataFunction = $function; + } + + /** + * Process the value + * + * @param var $value The value to process/format + * @return string The processed value + * @access private + */ + function _process($value) + { + $function = $this->_dataFunction; + return call_user_func($function, $value); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/DataPreprocessor/NumberText.php b/includes/pear/Image/Graph/DataPreprocessor/NumberText.php index b380c041..6c4c9ef2 100644 --- a/includes/pear/Image/Graph/DataPreprocessor/NumberText.php +++ b/includes/pear/Image/Graph/DataPreprocessor/NumberText.php @@ -1,89 +1,89 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: NumberText.php,v 1.6 2005/08/24 20:35:59 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/DataPreprocessor.php - */ -require_once 'Image/Graph/DataPreprocessor.php'; - -/** - * Formatting a number as its written in languages supported by Numbers_Words. - * - * Used to display values as text, i.e. 123 is displayed as one hundred and twenty three. - * Requires Numbers_Words - * - * @category Images - * @package Image_Graph - * @subpackage DataPreprocessor - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_DataPreprocessor_NumberText extends Image_Graph_DataPreprocessor -{ - - /** - * The language identifier - * @var string - * @access private - */ - var $_language; - - /** - * Image_Graph_NumberText [Constructor]. - * - * Supported languages see {@link http://pear.php.net/package/Numbers_Words Numbers_Words} - * - * @param string $langugage The language identifier for the language. - */ - function Image_Graph_DataPreprocessor_NumberText($language = 'en_US') - { - parent::Image_Graph_DataPreprocessor(); - $this->_language = $language; - require_once 'Numbers/Words.php'; - } - - /** - * Process the value - * - * @param var $value The value to process/format - * @return string The processed value - * @access private - */ - function _process($value) - { - return Numbers_Words::toWords($value, $this->_language); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: NumberText.php,v 1.6 2005/08/24 20:35:59 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/DataPreprocessor.php + */ +require_once 'Image/Graph/DataPreprocessor.php'; + +/** + * Formatting a number as its written in languages supported by Numbers_Words. + * + * Used to display values as text, i.e. 123 is displayed as one hundred and twenty three. + * Requires Numbers_Words + * + * @category Images + * @package Image_Graph + * @subpackage DataPreprocessor + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_DataPreprocessor_NumberText extends Image_Graph_DataPreprocessor +{ + + /** + * The language identifier + * @var string + * @access private + */ + var $_language; + + /** + * Image_Graph_NumberText [Constructor]. + * + * Supported languages see {@link http://pear.php.net/package/Numbers_Words Numbers_Words} + * + * @param string $langugage The language identifier for the language. + */ + function Image_Graph_DataPreprocessor_NumberText($language = 'en_US') + { + parent::Image_Graph_DataPreprocessor(); + $this->_language = $language; + require_once 'Numbers/Words.php'; + } + + /** + * Process the value + * + * @param var $value The value to process/format + * @return string The processed value + * @access private + */ + function _process($value) + { + return Numbers_Words::toWords($value, $this->_language); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/DataPreprocessor/RomanNumerals.php b/includes/pear/Image/Graph/DataPreprocessor/RomanNumerals.php index 4368d92e..29831adf 100644 --- a/includes/pear/Image/Graph/DataPreprocessor/RomanNumerals.php +++ b/includes/pear/Image/Graph/DataPreprocessor/RomanNumerals.php @@ -1,79 +1,79 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: RomanNumerals.php,v 1.6 2005/08/24 20:35:59 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/DataPreprocessor.php - */ -require_once 'Image/Graph/DataPreprocessor.php'; - -/** - * Formatting a value as a roman numerals. - * - * Values are formatted as roman numeral, i.e. 1 = I, 2 = II, 9 = IX, 2004 = MMIV. - * Requires Numbers_Roman - * - * @category Images - * @package Image_Graph - * @subpackage DataPreprocessor - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_DataPreprocessor_RomanNumerals extends Image_Graph_DataPreprocessor -{ - - /** - * Create a RomanNumerals preprocessor - * - * See {@link http://pear.php.net/package/Numbers_Roman Numbers_Roman} - */ - function Image_Graph_DataPreprocessor_RomanNumerals() - { - parent::Image_Graph_DataPreprocessor(); - include_once 'Numbers/Roman.php'; - } - - /** - * Process the value - * - * @param var $value The value to process/format - * @return string The processed value - * @access private - */ - function _process($value) - { - return Numbers_Roman::toNumeral($value); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: RomanNumerals.php,v 1.6 2005/08/24 20:35:59 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/DataPreprocessor.php + */ +require_once 'Image/Graph/DataPreprocessor.php'; + +/** + * Formatting a value as a roman numerals. + * + * Values are formatted as roman numeral, i.e. 1 = I, 2 = II, 9 = IX, 2004 = MMIV. + * Requires Numbers_Roman + * + * @category Images + * @package Image_Graph + * @subpackage DataPreprocessor + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_DataPreprocessor_RomanNumerals extends Image_Graph_DataPreprocessor +{ + + /** + * Create a RomanNumerals preprocessor + * + * See {@link http://pear.php.net/package/Numbers_Roman Numbers_Roman} + */ + function Image_Graph_DataPreprocessor_RomanNumerals() + { + parent::Image_Graph_DataPreprocessor(); + include_once 'Numbers/Roman.php'; + } + + /** + * Process the value + * + * @param var $value The value to process/format + * @return string The processed value + * @access private + */ + function _process($value) + { + return Numbers_Roman::toNumeral($value); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/DataPreprocessor/Sequential.php b/includes/pear/Image/Graph/DataPreprocessor/Sequential.php index 23f8f00a..8305339a 100644 --- a/includes/pear/Image/Graph/DataPreprocessor/Sequential.php +++ b/includes/pear/Image/Graph/DataPreprocessor/Sequential.php @@ -1,67 +1,67 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Sequential.php,v 1.5 2005/02/21 20:49:50 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/DataPreprocessor/Array.php - */ -require_once 'Image/Graph/DataPreprocessor/Array.php'; - -/** - * Formatting values using a sequential data label array, ie. returning the - * 'next label' when asked for any label. - * - * @category Images - * @package Image_Graph - * @subpackage DataPreprocessor - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_DataPreprocessor_Sequential extends Image_Graph_DataPreprocessor_Array -{ - - /** - * Process the value - * - * @param var $value The value to process/format - * @return string The processed value - * @access private - */ - function _process($value) - { - list ($id, $value) = each($this->_dataArray); - return $value; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Sequential.php,v 1.5 2005/02/21 20:49:50 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/DataPreprocessor/Array.php + */ +require_once 'Image/Graph/DataPreprocessor/Array.php'; + +/** + * Formatting values using a sequential data label array, ie. returning the + * 'next label' when asked for any label. + * + * @category Images + * @package Image_Graph + * @subpackage DataPreprocessor + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_DataPreprocessor_Sequential extends Image_Graph_DataPreprocessor_Array +{ + + /** + * Process the value + * + * @param var $value The value to process/format + * @return string The processed value + * @access private + */ + function _process($value) + { + list ($id, $value) = each($this->_dataArray); + return $value; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/DataSelector.php b/includes/pear/Image/Graph/DataSelector.php index f3b6a3f0..ce50ac58 100644 --- a/includes/pear/Image/Graph/DataSelector.php +++ b/includes/pear/Image/Graph/DataSelector.php @@ -1,67 +1,67 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: DataSelector.php,v 1.7 2005/08/24 20:35:56 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Filter used for selecting which data to show as markers - * - * @category Images - * @package Image_Graph - * @subpackage DataSelector - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_DataSelector -{ - - /** - * Image_Graph_DataSelector [Constructor] - */ - function Image_Graph_DataSelector() - { - } - - /** - * Check if a specified value should be 'selected', ie shown as a marker - * - * @param array $values The values to check - * @return bool True if the Values should cause a marker to be shown, false if not - * @access private - */ - function _select($values) - { - return true; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: DataSelector.php,v 1.7 2005/08/24 20:35:56 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Filter used for selecting which data to show as markers + * + * @category Images + * @package Image_Graph + * @subpackage DataSelector + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_DataSelector +{ + + /** + * Image_Graph_DataSelector [Constructor] + */ + function Image_Graph_DataSelector() + { + } + + /** + * Check if a specified value should be 'selected', ie shown as a marker + * + * @param array $values The values to check + * @return bool True if the Values should cause a marker to be shown, false if not + * @access private + */ + function _select($values) + { + return true; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/DataSelector/EveryNthPoint.php b/includes/pear/Image/Graph/DataSelector/EveryNthPoint.php index 4b9658e9..20d9f980 100644 --- a/includes/pear/Image/Graph/DataSelector/EveryNthPoint.php +++ b/includes/pear/Image/Graph/DataSelector/EveryNthPoint.php @@ -1,97 +1,97 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: EveryNthPoint.php,v 1.6 2005/08/24 20:35:59 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/DataSelector.php - */ -require_once 'Image/Graph/DataSelector.php'; - -/** - * Filter out all points except every Nth point. - * - * Use this dataselector if you have a large number of datapoints, but only want to - * show markers for a small number of them, say every 10th. - * - * @category Images - * @package Image_Graph - * @subpackage DataSelector - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_DataSelector_EveryNthPoint extends Image_Graph_DataSelector -{ - - /** - * The number of points checked - * @var int - * @access private - */ - var $_pointNum = 0; - - /** - * The number of points between every 'show', default: 10 - * @var int - * @access private - */ - var $_pointInterval = 10; - - /** - * EvertNthPoint [Constructor] - * - * @param int $pointInterval The number of points between every 'show', - * default: 10 - */ - function Image_Graph_DataSelector_EveryNthpoint($pointInterval = 10) - { - parent::Image_Graph_DataSelector(); - $this->_pointInterval = $pointInterval; - } - - /** - * Check if a specified value should be 'selected', ie shown as a marker - * - * @param array $values The values to check - * @return bool True if the Values should cause a marker to be shown, - * false if not - * @access private - */ - function _select($values) - { - $oldPointNum = $this->_pointNum; - $this->_pointNum++; - return (($oldPointNum % $this->_pointInterval) == 0); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: EveryNthPoint.php,v 1.6 2005/08/24 20:35:59 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/DataSelector.php + */ +require_once 'Image/Graph/DataSelector.php'; + +/** + * Filter out all points except every Nth point. + * + * Use this dataselector if you have a large number of datapoints, but only want to + * show markers for a small number of them, say every 10th. + * + * @category Images + * @package Image_Graph + * @subpackage DataSelector + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_DataSelector_EveryNthPoint extends Image_Graph_DataSelector +{ + + /** + * The number of points checked + * @var int + * @access private + */ + var $_pointNum = 0; + + /** + * The number of points between every 'show', default: 10 + * @var int + * @access private + */ + var $_pointInterval = 10; + + /** + * EvertNthPoint [Constructor] + * + * @param int $pointInterval The number of points between every 'show', + * default: 10 + */ + function Image_Graph_DataSelector_EveryNthpoint($pointInterval = 10) + { + parent::Image_Graph_DataSelector(); + $this->_pointInterval = $pointInterval; + } + + /** + * Check if a specified value should be 'selected', ie shown as a marker + * + * @param array $values The values to check + * @return bool True if the Values should cause a marker to be shown, + * false if not + * @access private + */ + function _select($values) + { + $oldPointNum = $this->_pointNum; + $this->_pointNum++; + return (($oldPointNum % $this->_pointInterval) == 0); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/DataSelector/NoZeros.php b/includes/pear/Image/Graph/DataSelector/NoZeros.php index 00d8cf24..3432a8b0 100644 --- a/includes/pear/Image/Graph/DataSelector/NoZeros.php +++ b/includes/pear/Image/Graph/DataSelector/NoZeros.php @@ -1,68 +1,68 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: NoZeros.php,v 1.5 2005/02/21 20:49:58 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/DataSelector.php - */ -require_once 'Image/Graph/DataSelector.php'; - -/** - * Filter out all zero's. - * - * Display all Y-values as markers, except those with Y = 0 - * - * @category Images - * @package Image_Graph - * @subpackage DataSelector - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_DataSelector_NoZeros extends Image_Graph_DataSelector -{ - - /** - * Check if a specified value should be 'selected', ie shown as a marker - * - * @param array $values The values to check - * @return bool True if the Values should cause a marker to be shown, false - * if not - * @access private - */ - function _select($values) - { - return ($values['Y'] != 0); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: NoZeros.php,v 1.5 2005/02/21 20:49:58 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/DataSelector.php + */ +require_once 'Image/Graph/DataSelector.php'; + +/** + * Filter out all zero's. + * + * Display all Y-values as markers, except those with Y = 0 + * + * @category Images + * @package Image_Graph + * @subpackage DataSelector + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_DataSelector_NoZeros extends Image_Graph_DataSelector +{ + + /** + * Check if a specified value should be 'selected', ie shown as a marker + * + * @param array $values The values to check + * @return bool True if the Values should cause a marker to be shown, false + * if not + * @access private + */ + function _select($values) + { + return ($values['Y'] != 0); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/DataSelector/Values.php b/includes/pear/Image/Graph/DataSelector/Values.php index b93051ae..516b2b17 100644 --- a/includes/pear/Image/Graph/DataSelector/Values.php +++ b/includes/pear/Image/Graph/DataSelector/Values.php @@ -1,90 +1,90 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Values.php,v 1.2 2005/10/05 20:51:21 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/DataSelector.php - */ -require_once 'Image/Graph/DataSelector.php'; - -/** - * Filter out all but the specified values. - * - * @category Images - * @package Image_Graph - * @subpackage DataSelector - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_DataSelector_Values extends Image_Graph_DataSelector { - - /** - * The array with values that should be included - * @var array - * @access private - */ - var $_values; - - /** - * ValueArray [Constructor] - * - * @param array $valueArray The array to use as filter (default empty) - */ - function &Image_Graph_DataSelector_Values($values) - { - parent::Image_Graph_DataSelector(); - $this->_values = $values; - } - - /** - * Sets the array to use - */ - function setValueArray($values) - { - $this->_values = $values; - } - - /** - * Check if a specified value should be 'selected', ie shown as a marker - * - * @param array $values The values to check - * @return bool True if the Values should cause a marker to be shown, false - * if not - * @access private - */ - function _select($values) - { - return ( in_array($values['Y'], $this->_values) ); - } -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Values.php,v 1.2 2005/10/05 20:51:21 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/DataSelector.php + */ +require_once 'Image/Graph/DataSelector.php'; + +/** + * Filter out all but the specified values. + * + * @category Images + * @package Image_Graph + * @subpackage DataSelector + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_DataSelector_Values extends Image_Graph_DataSelector { + + /** + * The array with values that should be included + * @var array + * @access private + */ + var $_values; + + /** + * ValueArray [Constructor] + * + * @param array $valueArray The array to use as filter (default empty) + */ + function &Image_Graph_DataSelector_Values($values) + { + parent::Image_Graph_DataSelector(); + $this->_values = $values; + } + + /** + * Sets the array to use + */ + function setValueArray($values) + { + $this->_values = $values; + } + + /** + * Check if a specified value should be 'selected', ie shown as a marker + * + * @param array $values The values to check + * @return bool True if the Values should cause a marker to be shown, false + * if not + * @access private + */ + function _select($values) + { + return ( in_array($values['Y'], $this->_values) ); + } +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Dataset.php b/includes/pear/Image/Graph/Dataset.php index 65d1b422..9854ef38 100644 --- a/includes/pear/Image/Graph/Dataset.php +++ b/includes/pear/Image/Graph/Dataset.php @@ -1,483 +1,483 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Dataset.php,v 1.10 2005/08/24 20:35:55 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - - -/** - * Data set used to represent a data collection to plot in a chart - * - * @category Images - * @package Image_Graph - * @subpackage Dataset - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - * @abstract - */ -class Image_Graph_Dataset -{ - - /** - * The pointer of the data set - * @var int - * @access private - */ - var $_posX = 0; - - /** - * The minimum X value of the dataset - * @var int - * @access private - */ - var $_minimumX = 0; - - /** - * The maximum X value of the dataset - * @var int - * @access private - */ - var $_maximumX = 0; - - /** - * The minimum Y value of the dataset - * @var int - * @access private - */ - var $_minimumY = 0; - - /** - * The maximum Y value of the dataset - * @var int - * @access private - */ - var $_maximumY = 0; - - /** - * The number of points in the dataset - * @var int - * @access private - */ - var $_count = 0; - - /** - * The name of the dataset, used for legending - * @var string - * @access private - */ - var $_name = ''; - - /** - * Image_Graph_Dataset [Constructor] - */ - function Image_Graph_Dataset() - { - } - - /** - * Sets the name of the data set, used for legending - * - * @param string $name The name of the dataset - */ - function setName($name) - { - $this->_name = $name; - } - - /** - * Add a point to the dataset - * - * $ID can contain either the ID of the point, i.e. 'DK', 123, 'George', etc. or it can contain - * values used for creation of the HTML image map. This is achieved using is an an associated array - * with the following values: - * - * 'url' The URL to create the link to - * - * 'alt' [optional] The alt text on the link - * - * 'target' [optional] The target of the link - * - * 'htmltags' [optional] An associated array with html tags (tag as key), fx. 'onMouseOver' => 'history.go(-1);', 'id' => 'thelink' - * - * @param int $x The X value to add - * @param int $y The Y value to add, can be omited - * @param var $ID The ID of the point - */ - function addPoint($x, $y = false, $ID = false) - { - if ($y !== null) { - if (is_array($y)) { - $maxY = max($y); - $minY = min($y); - } else { - $maxY = $y; - $minY = $y; - } - } - - if ($this->_count) { - $this->_minimumX = min($x, $this->_minimumX); - $this->_maximumX = max($x, $this->_maximumX); - if ($y !== null) { - $this->_minimumY = min($minY, $this->_minimumY); - $this->_maximumY = max($maxY, $this->_maximumY); - } - } else { - $this->_minimumX = $x; - $this->_maximumX = $x; - if ($y !== null) { - $this->_minimumY = $minY; - $this->_maximumY = $maxY; - } - } - - $this->_count++; - } - - /** - * The number of values in the dataset - * - * @return int The number of values in the dataset - */ - function count() - { - return $this->_count; - } - - /** - * Gets a X point from the dataset - * - * @param var $x The variable to return an X value from, fx in a vector - * function data set - * @return var The X value of the variable - * @access private - */ - function _getPointX($x) - { - return $x; - } - - /** - * Gets a Y point from the dataset - * - * @param var $x The variable to return an Y value from, fx in a vector - * function data set - * @return var The Y value of the variable - * @access private - */ - function _getPointY($x) - { - return $x; - } - - /** - * Gets a ID from the dataset - * - * @param var $x The variable to return an Y value from, fx in a vector - * function data set - * @return var The ID value of the variable - * @access private - */ - function _getPointID($x) - { - return false; - } - - /** - * Gets point data from the dataset - * - * @param var $x The variable to return an Y value from, fx in a vector - * function data set - * @return array The data for the point - * @access private - */ - function _getPointData($x) - { - return false; - } - - /** - * The minimum X value - * - * @return var The minimum X value - */ - function minimumX() - { - return $this->_minimumX; - } - - /** - * The maximum X value - * - * @return var The maximum X value - */ - function maximumX() - { - return $this->_maximumX; - } - - /** - * The minimum Y value - * - * @return var The minimum Y value - */ - function minimumY() - { - return $this->_minimumY; - } - - /** - * The maximum Y value - * - * @return var The maximum Y value - */ - function maximumY() - { - return $this->_maximumY; - } - - /** - * The first point - * - * @return array The last point - */ - function first() - { - return array('X' => $this->minimumX(), 'Y' => $this->minimumY()); - } - - /** - * The last point - * - * @return array The first point - */ - function last() - { - return array('X' => $this->maximumX(), 'Y' => $this->maximumY()); - } - - /** - * The minimum X value - * - * @param var $value The minimum X value - * @access private - */ - function _setMinimumX($value) - { - $this->_minimumX = $value; - } - - /** - * The maximum X value - * - * @param var $value The maximum X value - * @access private - */ - function _setMaximumX($value) - { - $this->_maximumX = $value; - } - - /** - * The minimum Y value - * - * @param var $value The minimum X value - * @access private - */ - function _setMinimumY($value) - { - $this->_minimumY = $value; - } - - /** - * The maximum Y value - * - * @param var $value The maximum X value - * @access private - */ - function _setMaximumY($value) - { - $this->_maximumY = $value; - } - - /** - * The interval between 2 adjacent X values - * - * @return var The interval - * @access private - */ - function _stepX() - { - return 1; - } - - /** - * The interval between 2 adjacent Y values - * - * @return var The interval - * @access private - */ - function _stepY() - { - return 1; - } - - /** - * Reset the intertal dataset pointer - * - * @return var The first X value - * @access private - */ - function _reset() - { - $this->_posX = $this->_minimumX; - return $this->_posX; - } - - /** - * Get a point close to the internal pointer - * - * @param int Step Number of points next to the internal pointer, negative - * Step is towards lower X values, positive towards higher X values - * @return array The point - * @access private - */ - function _nearby($step = 0) - { - $x = $this->_getPointX($this->_posX + $this->_stepX() * $step); - $y = $this->_getPointY($this->_posX + $this->_stepX() * $step); - $ID = $this->_getPointID($this->_posX + $this->_stepX() * $step); - $data = $this->_getPointData($this->_posX + $this->_stepX() * $step); - if (($x === false) || ($y === false)) { - return false; - } else { - return array ('X' => $x, 'Y' => $y, 'ID' => $ID, 'data' => $data); - } - } - - /** - * Get the next point the internal pointer refers to and advance the pointer - * - * @return array The next point - * @access private - */ - function _next() - { - if ($this->_posX > $this->_maximumX) { - return false; - } - - $x = $this->_getPointX($this->_posX); - $y = $this->_getPointY($this->_posX); - $ID = $this->_getPointID($this->_posX); - $data = $this->_getPointData($this->_posX); - $this->_posX += $this->_stepX(); - - return array ('X' => $x, 'Y' => $y, 'ID' => $ID, 'data' => $data); - } - - /** - * Get the average of the dataset's Y points - * - * @return var The Y-average across the dataset - * @access private - */ - function _averageY() - { - $posX = $this->_minimumX; - $count = 0; - $total = 0; - while ($posX < $this->_maximumX) { - $count ++; - $total += $this->_getPointY($posX); - $posX += $this->_stepX(); - } - - if ($count != 0) { - return $total / $count; - } else { - return false; - } - } - - /** - * Get the median of the array passed Y points - * - * @param array $data The data-array to get the median from - * @param int $quartile The quartile to return the median from - * @return var The Y-median across the dataset from the specified quartile - * @access private - */ - function _median($data, $quartile = 'second') - { - sort($data); - $point = (count($data) - 1) / 2; - - if ($quartile == 'first') { - $lowPoint = 0; - $highPoint = floor($point); - } elseif ($quartile == 'third') { - $lowPoint = round($point); - $highPoint = count($data) - 1; - } else { - $lowPoint = 0; - $highPoint = count($data) - 1; - } - - $point = ($lowPoint + $highPoint) / 2; - - if (floor($point) != $point) { - $point = floor($point); - return ($data[$point] + $data[($point + 1)]) / 2; - } else { - return $data[$point]; - } - } - - /** - * Get the median of the datasets Y points - * - * @param int $quartile The quartile to return the median from - * @return var The Y-median across the dataset from the specified quartile - * @access private - */ - function _medianY($quartile = 'second') - { - $pointsY = array(); - $posX = $this->_minimumX; - while ($posX <= $this->_maximumX) { - $pointsY[] = $this->_getPointY($posX); - $posX += $this->_stepX(); - } - return $this->_median($pointsY, $quartile); - } - -} + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Dataset.php,v 1.10 2005/08/24 20:35:55 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + + +/** + * Data set used to represent a data collection to plot in a chart + * + * @category Images + * @package Image_Graph + * @subpackage Dataset + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + * @abstract + */ +class Image_Graph_Dataset +{ + + /** + * The pointer of the data set + * @var int + * @access private + */ + var $_posX = 0; + + /** + * The minimum X value of the dataset + * @var int + * @access private + */ + var $_minimumX = 0; + + /** + * The maximum X value of the dataset + * @var int + * @access private + */ + var $_maximumX = 0; + + /** + * The minimum Y value of the dataset + * @var int + * @access private + */ + var $_minimumY = 0; + + /** + * The maximum Y value of the dataset + * @var int + * @access private + */ + var $_maximumY = 0; + + /** + * The number of points in the dataset + * @var int + * @access private + */ + var $_count = 0; + + /** + * The name of the dataset, used for legending + * @var string + * @access private + */ + var $_name = ''; + + /** + * Image_Graph_Dataset [Constructor] + */ + function Image_Graph_Dataset() + { + } + + /** + * Sets the name of the data set, used for legending + * + * @param string $name The name of the dataset + */ + function setName($name) + { + $this->_name = $name; + } + + /** + * Add a point to the dataset + * + * $ID can contain either the ID of the point, i.e. 'DK', 123, 'George', etc. or it can contain + * values used for creation of the HTML image map. This is achieved using is an an associated array + * with the following values: + * + * 'url' The URL to create the link to + * + * 'alt' [optional] The alt text on the link + * + * 'target' [optional] The target of the link + * + * 'htmltags' [optional] An associated array with html tags (tag as key), fx. 'onMouseOver' => 'history.go(-1);', 'id' => 'thelink' + * + * @param int $x The X value to add + * @param int $y The Y value to add, can be omited + * @param var $ID The ID of the point + */ + function addPoint($x, $y = false, $ID = false) + { + if ($y !== null) { + if (is_array($y)) { + $maxY = max($y); + $minY = min($y); + } else { + $maxY = $y; + $minY = $y; + } + } + + if ($this->_count) { + $this->_minimumX = min($x, $this->_minimumX); + $this->_maximumX = max($x, $this->_maximumX); + if ($y !== null) { + $this->_minimumY = min($minY, $this->_minimumY); + $this->_maximumY = max($maxY, $this->_maximumY); + } + } else { + $this->_minimumX = $x; + $this->_maximumX = $x; + if ($y !== null) { + $this->_minimumY = $minY; + $this->_maximumY = $maxY; + } + } + + $this->_count++; + } + + /** + * The number of values in the dataset + * + * @return int The number of values in the dataset + */ + function count() + { + return $this->_count; + } + + /** + * Gets a X point from the dataset + * + * @param var $x The variable to return an X value from, fx in a vector + * function data set + * @return var The X value of the variable + * @access private + */ + function _getPointX($x) + { + return $x; + } + + /** + * Gets a Y point from the dataset + * + * @param var $x The variable to return an Y value from, fx in a vector + * function data set + * @return var The Y value of the variable + * @access private + */ + function _getPointY($x) + { + return $x; + } + + /** + * Gets a ID from the dataset + * + * @param var $x The variable to return an Y value from, fx in a vector + * function data set + * @return var The ID value of the variable + * @access private + */ + function _getPointID($x) + { + return false; + } + + /** + * Gets point data from the dataset + * + * @param var $x The variable to return an Y value from, fx in a vector + * function data set + * @return array The data for the point + * @access private + */ + function _getPointData($x) + { + return false; + } + + /** + * The minimum X value + * + * @return var The minimum X value + */ + function minimumX() + { + return $this->_minimumX; + } + + /** + * The maximum X value + * + * @return var The maximum X value + */ + function maximumX() + { + return $this->_maximumX; + } + + /** + * The minimum Y value + * + * @return var The minimum Y value + */ + function minimumY() + { + return $this->_minimumY; + } + + /** + * The maximum Y value + * + * @return var The maximum Y value + */ + function maximumY() + { + return $this->_maximumY; + } + + /** + * The first point + * + * @return array The last point + */ + function first() + { + return array('X' => $this->minimumX(), 'Y' => $this->minimumY()); + } + + /** + * The last point + * + * @return array The first point + */ + function last() + { + return array('X' => $this->maximumX(), 'Y' => $this->maximumY()); + } + + /** + * The minimum X value + * + * @param var $value The minimum X value + * @access private + */ + function _setMinimumX($value) + { + $this->_minimumX = $value; + } + + /** + * The maximum X value + * + * @param var $value The maximum X value + * @access private + */ + function _setMaximumX($value) + { + $this->_maximumX = $value; + } + + /** + * The minimum Y value + * + * @param var $value The minimum X value + * @access private + */ + function _setMinimumY($value) + { + $this->_minimumY = $value; + } + + /** + * The maximum Y value + * + * @param var $value The maximum X value + * @access private + */ + function _setMaximumY($value) + { + $this->_maximumY = $value; + } + + /** + * The interval between 2 adjacent X values + * + * @return var The interval + * @access private + */ + function _stepX() + { + return 1; + } + + /** + * The interval between 2 adjacent Y values + * + * @return var The interval + * @access private + */ + function _stepY() + { + return 1; + } + + /** + * Reset the intertal dataset pointer + * + * @return var The first X value + * @access private + */ + function _reset() + { + $this->_posX = $this->_minimumX; + return $this->_posX; + } + + /** + * Get a point close to the internal pointer + * + * @param int Step Number of points next to the internal pointer, negative + * Step is towards lower X values, positive towards higher X values + * @return array The point + * @access private + */ + function _nearby($step = 0) + { + $x = $this->_getPointX($this->_posX + $this->_stepX() * $step); + $y = $this->_getPointY($this->_posX + $this->_stepX() * $step); + $ID = $this->_getPointID($this->_posX + $this->_stepX() * $step); + $data = $this->_getPointData($this->_posX + $this->_stepX() * $step); + if (($x === false) || ($y === false)) { + return false; + } else { + return array ('X' => $x, 'Y' => $y, 'ID' => $ID, 'data' => $data); + } + } + + /** + * Get the next point the internal pointer refers to and advance the pointer + * + * @return array The next point + * @access private + */ + function _next() + { + if ($this->_posX > $this->_maximumX) { + return false; + } + + $x = $this->_getPointX($this->_posX); + $y = $this->_getPointY($this->_posX); + $ID = $this->_getPointID($this->_posX); + $data = $this->_getPointData($this->_posX); + $this->_posX += $this->_stepX(); + + return array ('X' => $x, 'Y' => $y, 'ID' => $ID, 'data' => $data); + } + + /** + * Get the average of the dataset's Y points + * + * @return var The Y-average across the dataset + * @access private + */ + function _averageY() + { + $posX = $this->_minimumX; + $count = 0; + $total = 0; + while ($posX < $this->_maximumX) { + $count ++; + $total += $this->_getPointY($posX); + $posX += $this->_stepX(); + } + + if ($count != 0) { + return $total / $count; + } else { + return false; + } + } + + /** + * Get the median of the array passed Y points + * + * @param array $data The data-array to get the median from + * @param int $quartile The quartile to return the median from + * @return var The Y-median across the dataset from the specified quartile + * @access private + */ + function _median($data, $quartile = 'second') + { + sort($data); + $point = (count($data) - 1) / 2; + + if ($quartile == 'first') { + $lowPoint = 0; + $highPoint = floor($point); + } elseif ($quartile == 'third') { + $lowPoint = round($point); + $highPoint = count($data) - 1; + } else { + $lowPoint = 0; + $highPoint = count($data) - 1; + } + + $point = ($lowPoint + $highPoint) / 2; + + if (floor($point) != $point) { + $point = floor($point); + return ($data[$point] + $data[($point + 1)]) / 2; + } else { + return $data[$point]; + } + } + + /** + * Get the median of the datasets Y points + * + * @param int $quartile The quartile to return the median from + * @return var The Y-median across the dataset from the specified quartile + * @access private + */ + function _medianY($quartile = 'second') + { + $pointsY = array(); + $posX = $this->_minimumX; + while ($posX <= $this->_maximumX) { + $pointsY[] = $this->_getPointY($posX); + $posX += $this->_stepX(); + } + return $this->_median($pointsY, $quartile); + } + +} ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Dataset/Function.php b/includes/pear/Image/Graph/Dataset/Function.php index 1510e3ef..735a3527 100644 --- a/includes/pear/Image/Graph/Dataset/Function.php +++ b/includes/pear/Image/Graph/Dataset/Function.php @@ -1,147 +1,147 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Function.php,v 1.7 2005/08/24 20:35:57 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Dataset.php - */ -require_once 'Image/Graph/Dataset.php'; - -/** - * Function data set, points are generated by calling an external function. - * - * The function must be a single variable function and return a the result, - * builtin functions that are fx sin() or cos(). User defined function can be - * used if they are such, i.e: function myFunction($variable) - * - * @category Images - * @package Image_Graph - * @subpackage Dataset - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Dataset_Function extends Image_Graph_Dataset -{ - - /** - * The name of the function - * @var string - * @access private - */ - var $_dataFunction; - - /** - * Image_Graph_FunctionDataset [Constructor] - * - * @param double $minimumX The minimum X value - * @param double $maximumX The maximum X value - * @param string $function The name of the function, if must be a single - * parameter function like fx sin(x) or cos(x) - * @param int $points The number of points to create - */ - function Image_Graph_Dataset_Function($minimumX, $maximumX, $function, $points) - { - parent::Image_Graph_Dataset(); - $this->_minimumX = $minimumX; - $this->_maximumX = $maximumX; - $this->_dataFunction = $function; - $this->_count = $points; - $this->_calculateMaxima(); - } - - /** - * Add a point to the dataset. - * - * You can't add points to a function dataset - * - * @param int $x The X value to add - * @param int $y The Y value to add, can be omited - * @param var $ID The ID of the point - */ - function addPoint($x, $y = false, $ID = false) - { - } - - /** - * Gets a Y point from the dataset - * - * @param var $x The variable to apply the function to - * @return var The function applied to the X value - * @access private - */ - function _getPointY($x) - { - $function = $this->_dataFunction; - return $function ($x); - } - - /** - * The number of values in the dataset - * - * @return int The number of values in the dataset - * @access private - */ - function _count() - { - return $this->_count; - } - - /** - * The interval between 2 adjacent Y values - * - * @return var The interval - * @access private - */ - function _stepX() - { - return ($this->_maximumX - $this->_minimumX) / $this->_count(); - } - - /** - * Calculates the Y extrema of the function - * - * @access private - */ - function _calculateMaxima() - { - $x = $this->_minimumX; - while ($x <= $this->_maximumX) { - $y = $this->_getPointY($x); - $this->_minimumY = min($y, $this->_minimumY); - $this->_maximumY = max($y, $this->_maximumY); - $x += $this->_stepX(); - } - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Function.php,v 1.7 2005/08/24 20:35:57 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Dataset.php + */ +require_once 'Image/Graph/Dataset.php'; + +/** + * Function data set, points are generated by calling an external function. + * + * The function must be a single variable function and return a the result, + * builtin functions that are fx sin() or cos(). User defined function can be + * used if they are such, i.e: function myFunction($variable) + * + * @category Images + * @package Image_Graph + * @subpackage Dataset + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Dataset_Function extends Image_Graph_Dataset +{ + + /** + * The name of the function + * @var string + * @access private + */ + var $_dataFunction; + + /** + * Image_Graph_FunctionDataset [Constructor] + * + * @param double $minimumX The minimum X value + * @param double $maximumX The maximum X value + * @param string $function The name of the function, if must be a single + * parameter function like fx sin(x) or cos(x) + * @param int $points The number of points to create + */ + function Image_Graph_Dataset_Function($minimumX, $maximumX, $function, $points) + { + parent::Image_Graph_Dataset(); + $this->_minimumX = $minimumX; + $this->_maximumX = $maximumX; + $this->_dataFunction = $function; + $this->_count = $points; + $this->_calculateMaxima(); + } + + /** + * Add a point to the dataset. + * + * You can't add points to a function dataset + * + * @param int $x The X value to add + * @param int $y The Y value to add, can be omited + * @param var $ID The ID of the point + */ + function addPoint($x, $y = false, $ID = false) + { + } + + /** + * Gets a Y point from the dataset + * + * @param var $x The variable to apply the function to + * @return var The function applied to the X value + * @access private + */ + function _getPointY($x) + { + $function = $this->_dataFunction; + return $function ($x); + } + + /** + * The number of values in the dataset + * + * @return int The number of values in the dataset + * @access private + */ + function _count() + { + return $this->_count; + } + + /** + * The interval between 2 adjacent Y values + * + * @return var The interval + * @access private + */ + function _stepX() + { + return ($this->_maximumX - $this->_minimumX) / $this->_count(); + } + + /** + * Calculates the Y extrema of the function + * + * @access private + */ + function _calculateMaxima() + { + $x = $this->_minimumX; + while ($x <= $this->_maximumX) { + $y = $this->_getPointY($x); + $this->_minimumY = min($y, $this->_minimumY); + $this->_maximumY = max($y, $this->_maximumY); + $x += $this->_stepX(); + } + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Dataset/Random.php b/includes/pear/Image/Graph/Dataset/Random.php index 23dbb4ba..580abd22 100644 --- a/includes/pear/Image/Graph/Dataset/Random.php +++ b/includes/pear/Image/Graph/Dataset/Random.php @@ -1,77 +1,77 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Random.php,v 1.6 2005/08/24 20:35:57 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Dataset/Trivial.php - */ -require_once 'Image/Graph/Dataset/Trivial.php'; - -/** - * Random data set, points are generated by random. - * - * This dataset is mostly (if not solely) used for demo-purposes. - * - * @category Images - * @package Image_Graph - * @subpackage Dataset - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Dataset_Random extends Image_Graph_Dataset_Trivial -{ - - /** - * RandomDataset [Constructor] - * - * @param int $count The number of points to create - * @param double $minimum The minimum value the random set can be - * @param double $maximum The maximum value the random set can be - * @param bool $includeZero Whether 0 should be included or not as an X - * value, may be omitted, default: false - */ - function Image_Graph_Dataset_Random($count, $minimum, $maximum, $includeZero = false) - { - parent::Image_Graph_Dataset_Trivial(); - $i = 0; - while ($i < $count) { - $this->addPoint( - $ixc = ($includeZero ? $i : $i +1), - rand($minimum, $maximum) - ); - $i ++; - } - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Random.php,v 1.6 2005/08/24 20:35:57 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Dataset/Trivial.php + */ +require_once 'Image/Graph/Dataset/Trivial.php'; + +/** + * Random data set, points are generated by random. + * + * This dataset is mostly (if not solely) used for demo-purposes. + * + * @category Images + * @package Image_Graph + * @subpackage Dataset + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Dataset_Random extends Image_Graph_Dataset_Trivial +{ + + /** + * RandomDataset [Constructor] + * + * @param int $count The number of points to create + * @param double $minimum The minimum value the random set can be + * @param double $maximum The maximum value the random set can be + * @param bool $includeZero Whether 0 should be included or not as an X + * value, may be omitted, default: false + */ + function Image_Graph_Dataset_Random($count, $minimum, $maximum, $includeZero = false) + { + parent::Image_Graph_Dataset_Trivial(); + $i = 0; + while ($i < $count) { + $this->addPoint( + $ixc = ($includeZero ? $i : $i +1), + rand($minimum, $maximum) + ); + $i ++; + } + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Dataset/Sequential.php b/includes/pear/Image/Graph/Dataset/Sequential.php index 4451f38e..df51b70e 100644 --- a/includes/pear/Image/Graph/Dataset/Sequential.php +++ b/includes/pear/Image/Graph/Dataset/Sequential.php @@ -1,114 +1,114 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Sequential.php,v 1.7 2005/08/24 20:35:58 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Dataset/Trivial.php - */ -require_once 'Image/Graph/Dataset/Trivial.php'; - -/** - * Sequential data set, simply add points (y) 1 by 1. - * - * This is a single point (1D) dataset, all points are of the type (0, y1), (1, - * y2), (2, y3)... Where the X-value is implicitly incremented. This is useful - * for example for barcharts, where you could fx. use an {@link - * Image_Graph_Dataset_Array} datapreprocessor to make sence of the x-values. - * - * @category Images - * @package Image_Graph - * @subpackage Dataset - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Dataset_Sequential extends Image_Graph_Dataset_Trivial -{ - - /** - * Image_Graph_SequentialDataset [Constructor] - */ - function Image_Graph_Dataset_Sequential($dataArray = false) - { - parent::Image_Graph_Dataset_Trivial(); - if (is_array($dataArray)) { - reset($dataArray); - foreach ($dataArray as $value) { - $this->addPoint($value); - } - } - } - - /** - * Add a point to the dataset - * - * @param int $y The Y value to add, can be omited - * @param var $ID The ID of the point - */ - function addPoint($y, $ID = false) - { - parent::addPoint($this->count(), $y); - } - - /** - * Gets a X point from the dataset - * - * @param var $x The variable to return an X value from, fx in a - * vector function data set - * @return var The X value of the variable - * @access private - */ - function _getPointX($x) - { - return ((int) $x); - } - - /** - * The minimum X value - * @return var The minimum X value - */ - function minimumX() - { - return 0; - } - - /** - * The maximum X value - * @return var The maximum X value - */ - function maximumX() - { - return $this->count(); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Sequential.php,v 1.7 2005/08/24 20:35:58 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Dataset/Trivial.php + */ +require_once 'Image/Graph/Dataset/Trivial.php'; + +/** + * Sequential data set, simply add points (y) 1 by 1. + * + * This is a single point (1D) dataset, all points are of the type (0, y1), (1, + * y2), (2, y3)... Where the X-value is implicitly incremented. This is useful + * for example for barcharts, where you could fx. use an {@link + * Image_Graph_Dataset_Array} datapreprocessor to make sence of the x-values. + * + * @category Images + * @package Image_Graph + * @subpackage Dataset + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Dataset_Sequential extends Image_Graph_Dataset_Trivial +{ + + /** + * Image_Graph_SequentialDataset [Constructor] + */ + function Image_Graph_Dataset_Sequential($dataArray = false) + { + parent::Image_Graph_Dataset_Trivial(); + if (is_array($dataArray)) { + reset($dataArray); + foreach ($dataArray as $value) { + $this->addPoint($value); + } + } + } + + /** + * Add a point to the dataset + * + * @param int $y The Y value to add, can be omited + * @param var $ID The ID of the point + */ + function addPoint($y, $ID = false) + { + parent::addPoint($this->count(), $y); + } + + /** + * Gets a X point from the dataset + * + * @param var $x The variable to return an X value from, fx in a + * vector function data set + * @return var The X value of the variable + * @access private + */ + function _getPointX($x) + { + return ((int) $x); + } + + /** + * The minimum X value + * @return var The minimum X value + */ + function minimumX() + { + return 0; + } + + /** + * The maximum X value + * @return var The maximum X value + */ + function maximumX() + { + return $this->count(); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Dataset/Trivial.php b/includes/pear/Image/Graph/Dataset/Trivial.php index eb7907cc..05f7f92f 100644 --- a/includes/pear/Image/Graph/Dataset/Trivial.php +++ b/includes/pear/Image/Graph/Dataset/Trivial.php @@ -1,260 +1,260 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Trivial.php,v 1.10 2005/09/25 18:08:56 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Dataset.php - */ -require_once 'Image/Graph/Dataset.php'; - -/** - * Trivial data set, simply add points (x, y) 1 by 1 - * - * @category Images - * @package Image_Graph - * @subpackage Dataset - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Dataset_Trivial extends Image_Graph_Dataset -{ - - /** - * Data storage - * @var array - * @access private - */ - var $_data; - - /** - * Image_Graph_Dataset_Trivial [Constructor] - * - * Pass an associated array ($data[$x] = $y) to the constructor for easy - * data addition. Alternatively (if multiple entries with same x value is - * required) pass an array with (x, y) values: $data[$id] = array('x' => $x, - * 'y' => $y); - * - * NB! If passing the 1st type array at this point, the x-values will also - * be used for ID tags, i.e. when using {@link Image_Graph_Fill_Array}. In - * the 2nd type the key/index of the "outermost" array will be the id tag - * (i.e. $id in the example) - * - * @param array $dataArray An associated array with values to the dataset - */ - function Image_Graph_Dataset_Trivial($dataArray = false) - { - parent::Image_Graph_Dataset(); - $this->_data = array (); - if (is_array($dataArray)) { - reset($dataArray); - $keys = array_keys($dataArray); - foreach ($keys as $x) { - $y =& $dataArray[$x]; - if ((is_array($y)) && (isset($y['x'])) && (isset($y['y']))) { - $this->addPoint($y['x'], $y['y'], (isset($y['id']) ? $y['id'] : $x)); - } else { - $this->addPoint($x, $y, $x); - } - } - } - } - - /** - * Add a point to the dataset - * - * $ID can contain either the ID of the point, i.e. 'DK', 123, 'George', etc. or it can contain - * values used for creation of the HTML image map. This is achieved using is an an associated array - * with the following values: - * - * 'url' The URL to create the link to - * - * 'alt' [optional] The alt text on the link - * - * 'target' [optional] The target of the link - * - * 'htmltags' [optional] An associated array with html tags (tag as key), fx. 'onMouseOver' => 'history.go(-1);', 'id' => 'thelink' - * - * @param int $x The X value to add - * @param int $y The Y value to add, can be omited - * @param var $ID The ID of the point - */ - function addPoint($x, $y = false, $ID = false) - { - parent::addPoint($x, $y, $ID); - - if (is_array($ID)) { - $data = $ID; - $ID = (isset($data['id']) ? $data['id'] : false); - } else { - $data = false; - } - - $this->_data[] = array ('X' => $x, 'Y' => $y, 'ID' => $ID, 'data' => $data); - if (!is_numeric($x)) { - $this->_maximumX = count($this->_data); - } - } - - /** - * The first point - * - * @return array The last point - */ - function first() - { - reset($this->_data); - return current($this->_data); - } - - /** - * The last point - * - * @return array The first point - */ - function last() - { - return end($this->_data); - } - - /** - * Gets a X point from the dataset - * - * @param var $x The variable to return an X value from, fx in a - * vector function data set - * @return var The X value of the variable - * @access private - */ - function _getPointX($x) - { - if (isset($this->_data[$x])) { - return $this->_data[$x]['X']; - } else { - return false; - } - } - - /** - * Gets a Y point from the dataset - * - * @param var $x The variable to return an Y value from, fx in a - * vector function data set - * @return var The Y value of the variable - * @access private - */ - function _getPointY($x) - { - if (isset($this->_data[$x])) { - return $this->_data[$x]['Y']; - } else { - return false; - } - } - - /** - * Gets a ID from the dataset - * - * @param var $x The variable to return an Y value from, fx in a - * vector function data set - * @return var The ID value of the variable - * @access private - */ - function _getPointID($x) - { - if (isset($this->_data[$x])) { - return $this->_data[$x]['ID']; - } else { - return false; - } - } - - /** - * Gets point data from the dataset - * - * @param var $x The variable to return an Y value from, fx in a vector - * function data set - * @return array The data for the point - * @access private - */ - function _getPointData($x) - { - if (isset($this->_data[$x])) { - return $this->_data[$x]['data']; - } else { - return false; - } - } - - /** - * The number of values in the dataset - * - * @return int The number of values in the dataset - */ - function count() - { - return count($this->_data); - } - - /** - * Reset the intertal dataset pointer - * - * @return var The first X value - * @access private - */ - function _reset() - { - $this->_posX = 0; - return $this->_posX; - } - - /** - * Get the next point the internal pointer refers to and advance the pointer - * - * @return array The next point - * @access private - */ - function _next() - { - if ($this->_posX >= $this->count()) { - return false; - } - $x = $this->_getPointX($this->_posX); - $y = $this->_getPointY($this->_posX); - $ID = $this->_getPointID($this->_posX); - $data = $this->_getPointData($this->_posX); - $this->_posX += $this->_stepX(); - - return array('X' => $x, 'Y' => $y, 'ID' => $ID, 'data' => $data); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Trivial.php,v 1.10 2005/09/25 18:08:56 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Dataset.php + */ +require_once 'Image/Graph/Dataset.php'; + +/** + * Trivial data set, simply add points (x, y) 1 by 1 + * + * @category Images + * @package Image_Graph + * @subpackage Dataset + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Dataset_Trivial extends Image_Graph_Dataset +{ + + /** + * Data storage + * @var array + * @access private + */ + var $_data; + + /** + * Image_Graph_Dataset_Trivial [Constructor] + * + * Pass an associated array ($data[$x] = $y) to the constructor for easy + * data addition. Alternatively (if multiple entries with same x value is + * required) pass an array with (x, y) values: $data[$id] = array('x' => $x, + * 'y' => $y); + * + * NB! If passing the 1st type array at this point, the x-values will also + * be used for ID tags, i.e. when using {@link Image_Graph_Fill_Array}. In + * the 2nd type the key/index of the "outermost" array will be the id tag + * (i.e. $id in the example) + * + * @param array $dataArray An associated array with values to the dataset + */ + function Image_Graph_Dataset_Trivial($dataArray = false) + { + parent::Image_Graph_Dataset(); + $this->_data = array (); + if (is_array($dataArray)) { + reset($dataArray); + $keys = array_keys($dataArray); + foreach ($keys as $x) { + $y =& $dataArray[$x]; + if ((is_array($y)) && (isset($y['x'])) && (isset($y['y']))) { + $this->addPoint($y['x'], $y['y'], (isset($y['id']) ? $y['id'] : $x)); + } else { + $this->addPoint($x, $y, $x); + } + } + } + } + + /** + * Add a point to the dataset + * + * $ID can contain either the ID of the point, i.e. 'DK', 123, 'George', etc. or it can contain + * values used for creation of the HTML image map. This is achieved using is an an associated array + * with the following values: + * + * 'url' The URL to create the link to + * + * 'alt' [optional] The alt text on the link + * + * 'target' [optional] The target of the link + * + * 'htmltags' [optional] An associated array with html tags (tag as key), fx. 'onMouseOver' => 'history.go(-1);', 'id' => 'thelink' + * + * @param int $x The X value to add + * @param int $y The Y value to add, can be omited + * @param var $ID The ID of the point + */ + function addPoint($x, $y = false, $ID = false) + { + parent::addPoint($x, $y, $ID); + + if (is_array($ID)) { + $data = $ID; + $ID = (isset($data['id']) ? $data['id'] : false); + } else { + $data = false; + } + + $this->_data[] = array ('X' => $x, 'Y' => $y, 'ID' => $ID, 'data' => $data); + if (!is_numeric($x)) { + $this->_maximumX = count($this->_data); + } + } + + /** + * The first point + * + * @return array The last point + */ + function first() + { + reset($this->_data); + return current($this->_data); + } + + /** + * The last point + * + * @return array The first point + */ + function last() + { + return end($this->_data); + } + + /** + * Gets a X point from the dataset + * + * @param var $x The variable to return an X value from, fx in a + * vector function data set + * @return var The X value of the variable + * @access private + */ + function _getPointX($x) + { + if (isset($this->_data[$x])) { + return $this->_data[$x]['X']; + } else { + return false; + } + } + + /** + * Gets a Y point from the dataset + * + * @param var $x The variable to return an Y value from, fx in a + * vector function data set + * @return var The Y value of the variable + * @access private + */ + function _getPointY($x) + { + if (isset($this->_data[$x])) { + return $this->_data[$x]['Y']; + } else { + return false; + } + } + + /** + * Gets a ID from the dataset + * + * @param var $x The variable to return an Y value from, fx in a + * vector function data set + * @return var The ID value of the variable + * @access private + */ + function _getPointID($x) + { + if (isset($this->_data[$x])) { + return $this->_data[$x]['ID']; + } else { + return false; + } + } + + /** + * Gets point data from the dataset + * + * @param var $x The variable to return an Y value from, fx in a vector + * function data set + * @return array The data for the point + * @access private + */ + function _getPointData($x) + { + if (isset($this->_data[$x])) { + return $this->_data[$x]['data']; + } else { + return false; + } + } + + /** + * The number of values in the dataset + * + * @return int The number of values in the dataset + */ + function count() + { + return count($this->_data); + } + + /** + * Reset the intertal dataset pointer + * + * @return var The first X value + * @access private + */ + function _reset() + { + $this->_posX = 0; + return $this->_posX; + } + + /** + * Get the next point the internal pointer refers to and advance the pointer + * + * @return array The next point + * @access private + */ + function _next() + { + if ($this->_posX >= $this->count()) { + return false; + } + $x = $this->_getPointX($this->_posX); + $y = $this->_getPointY($this->_posX); + $ID = $this->_getPointID($this->_posX); + $data = $this->_getPointData($this->_posX); + $this->_posX += $this->_stepX(); + + return array('X' => $x, 'Y' => $y, 'ID' => $ID, 'data' => $data); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Dataset/VectorFunction.php b/includes/pear/Image/Graph/Dataset/VectorFunction.php index 62f274fb..dabe73d4 100644 --- a/includes/pear/Image/Graph/Dataset/VectorFunction.php +++ b/includes/pear/Image/Graph/Dataset/VectorFunction.php @@ -1,185 +1,185 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: VectorFunction.php,v 1.6 2005/08/24 20:35:57 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Dataset.php - */ -require_once 'Image/Graph/Dataset.php'; - -/** - * Vector Function data set. - * - * Points are generated by calling 2 external functions, fx. x = sin(t) and y = - * cos(t) - * - * @category Images - * @package Image_Graph - * @subpackage Dataset - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Dataset_VectorFunction extends Image_Graph_Dataset -{ - - /** - * The name of the X function - * @var string - * @access private - */ - var $_functionX; - - /** - * The name of the Y function - * @var string - * @access private - */ - var $_functionY; - - /** - * The minimum of the vector function variable - * @var double - * @access private - */ - var $_minimumT; - - /** - * The maximum of the vector function variable - * @var double - * @access private - */ - var $_maximumT; - - /** - * Image_Graph_VectorFunctionDataset [Constructor] - * - * @param double $minimumT The minimum value of the vector function variable - * @param double $maximumT The maximum value of the vector function variable - * @param string $functionX The name of the X function, if must be a single - * parameter function like fx sin(x) or cos(x) - * @param string $functionY The name of the Y function, if must be a single - * parameter function like fx sin(x) or cos(x) - * @param int $points The number of points to create - */ - function Image_Graph_Dataset_VectorFunction($minimumT, $maximumT, $functionX, $functionY, $points) - { - parent::Image_Graph_Dataset(); - $this->_minimumT = $minimumT; - $this->_maximumT = $maximumT; - $this->_functionX = $functionX; - $this->_functionY = $functionY; - $this->_count = $points; - $this->_calculateMaxima(); - } - - /** - * Add a point to the dataset - * - * @param int $x The X value to add - * @param int $y The Y value to add, can be omited - * @param var $ID The ID of the point - */ - function addPoint($x, $y = false, $ID = false) - { - } - - /** - * Gets a X point from the dataset - * - * @param var $x The variable to apply the X function to - * @return var The X function applied to the X value - * @access private - */ - function _getPointX($x) - { - $functionX = $this->_functionX; - return $functionX ($x); - } - - /** - * Gets a Y point from the dataset - * - * @param var $x The variable to apply the Y function to - * @return var The Y function applied to the X value - * @access private - */ - function _getPointY($x) - { - $functionY = $this->_functionY; - return $functionY ($x); - } - - /** - * Reset the intertal dataset pointer - * - * @return var The first T value - * @access private - */ - function _reset() - { - $this->_posX = $this->_minimumT; - return $this->_posX; - } - - /** - * The interval between 2 adjacent T values - * - * @return var The interval - * @access private - */ - function _stepX() - { - return ($this->_maximumT - $this->_minimumT) / $this->count(); - } - - /** - * Calculates the X and Y extrema of the functions - * - * @access private - */ - function _calculateMaxima() - { - $t = $this->_minimumT; - while ($t <= $this->_maximumT) { - $x = $this->_getPointX($t); - $y = $this->_getPointY($t); - $this->_minimumX = min($x, $this->_minimumX); - $this->_maximumX = max($x, $this->_maximumX); - $this->_minimumY = min($y, $this->_minimumY); - $this->_maximumY = max($y, $this->_maximumY); - $t += $this->_stepX(); - } - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: VectorFunction.php,v 1.6 2005/08/24 20:35:57 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Dataset.php + */ +require_once 'Image/Graph/Dataset.php'; + +/** + * Vector Function data set. + * + * Points are generated by calling 2 external functions, fx. x = sin(t) and y = + * cos(t) + * + * @category Images + * @package Image_Graph + * @subpackage Dataset + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Dataset_VectorFunction extends Image_Graph_Dataset +{ + + /** + * The name of the X function + * @var string + * @access private + */ + var $_functionX; + + /** + * The name of the Y function + * @var string + * @access private + */ + var $_functionY; + + /** + * The minimum of the vector function variable + * @var double + * @access private + */ + var $_minimumT; + + /** + * The maximum of the vector function variable + * @var double + * @access private + */ + var $_maximumT; + + /** + * Image_Graph_VectorFunctionDataset [Constructor] + * + * @param double $minimumT The minimum value of the vector function variable + * @param double $maximumT The maximum value of the vector function variable + * @param string $functionX The name of the X function, if must be a single + * parameter function like fx sin(x) or cos(x) + * @param string $functionY The name of the Y function, if must be a single + * parameter function like fx sin(x) or cos(x) + * @param int $points The number of points to create + */ + function Image_Graph_Dataset_VectorFunction($minimumT, $maximumT, $functionX, $functionY, $points) + { + parent::Image_Graph_Dataset(); + $this->_minimumT = $minimumT; + $this->_maximumT = $maximumT; + $this->_functionX = $functionX; + $this->_functionY = $functionY; + $this->_count = $points; + $this->_calculateMaxima(); + } + + /** + * Add a point to the dataset + * + * @param int $x The X value to add + * @param int $y The Y value to add, can be omited + * @param var $ID The ID of the point + */ + function addPoint($x, $y = false, $ID = false) + { + } + + /** + * Gets a X point from the dataset + * + * @param var $x The variable to apply the X function to + * @return var The X function applied to the X value + * @access private + */ + function _getPointX($x) + { + $functionX = $this->_functionX; + return $functionX ($x); + } + + /** + * Gets a Y point from the dataset + * + * @param var $x The variable to apply the Y function to + * @return var The Y function applied to the X value + * @access private + */ + function _getPointY($x) + { + $functionY = $this->_functionY; + return $functionY ($x); + } + + /** + * Reset the intertal dataset pointer + * + * @return var The first T value + * @access private + */ + function _reset() + { + $this->_posX = $this->_minimumT; + return $this->_posX; + } + + /** + * The interval between 2 adjacent T values + * + * @return var The interval + * @access private + */ + function _stepX() + { + return ($this->_maximumT - $this->_minimumT) / $this->count(); + } + + /** + * Calculates the X and Y extrema of the functions + * + * @access private + */ + function _calculateMaxima() + { + $t = $this->_minimumT; + while ($t <= $this->_maximumT) { + $x = $this->_getPointX($t); + $y = $this->_getPointY($t); + $this->_minimumX = min($x, $this->_minimumX); + $this->_maximumX = max($x, $this->_maximumX); + $this->_minimumY = min($y, $this->_minimumY); + $this->_maximumY = max($y, $this->_maximumY); + $t += $this->_stepX(); + } + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Element.php b/includes/pear/Image/Graph/Element.php index d040a52c..fb9dfe34 100644 --- a/includes/pear/Image/Graph/Element.php +++ b/includes/pear/Image/Graph/Element.php @@ -1,727 +1,763 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Element.php,v 1.16 2005/08/03 21:21:52 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Common.php - */ -require_once 'Image/Graph/Common.php'; - -/** - * Representation of a element. - * - * The Image_Graph_Element can be drawn on the canvas, ie it has coordinates, - * {@link Image_Graph_Line}, {@link Image_Graph_Fill}, border and background - - * although not all of these may apply to all children. - * - * @category Images - * @package Image_Graph - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - * @abstract - */ -class Image_Graph_Element extends Image_Graph_Common -{ - - /** - * The leftmost pixel of the element on the canvas - * @var int - * @access private - */ - var $_left = 0; - - /** - * The topmost pixel of the element on the canvas - * @var int - * @access private - */ - var $_top = 0; - - /** - * The rightmost pixel of the element on the canvas - * @var int - * @access private - */ - var $_right = 0; - - /** - * The bottommost pixel of the element on the canvas - * @var int - * @access private - */ - var $_bottom = 0; - - /** - * Background of the element. Default: None - * @var FillStyle - * @access private - */ - var $_background = null; - - /** - * Borderstyle of the element. Default: None - * @var LineStyle - * @access private - */ - var $_borderStyle = null; - - /** - * Line style of the element. Default: None - * @var LineStyle - * @access private - */ - var $_lineStyle = 'black'; - - /** - * Fill style of the element. Default: None - * @var FillStyle - * @access private - */ - var $_fillStyle = 'white'; - - /** - * Font of the element. Default: Standard font - FONT - * @var Font - * @access private - * @see $IMAGE_GRAPH_FONT - */ - var $_font = null; - - /** - * Font options - * @var array - * @access private - */ - var $_fontOptions = array(); - - /** - * Default font options - * - * This option is included for performance reasons. The value is calculated - * before output and reused in default cases to avoid unnecessary recursive - * calls. - * - * @var array - * @access private - */ - var $_defaultFontOptions = false; - - /** - * Shadows options of the element - * @var mixed - * @access private - */ - var $_shadow = false; - - /** - * The padding displayed on the element - * @var int - * @access private - */ - var $_padding = 0; - - /** - * Sets the background fill style of the element - * - * @param Image_Graph_Fill $background The background - * @see Image_Graph_Fill - */ - function setBackground(& $background) - { - if (!is_a($background, 'Image_Graph_Fill')) { - $this->_error( - 'Could not set background for ' . get_class($this) . ': ' . - get_class($background), array('background' => &$background) - ); - } else { - $this->_background =& $background; - $this->add($background); - } - } - - /** - * Shows shadow on the element - */ - function showShadow($color = 'black@0.2', $size = 5) - { - $this->_shadow = array( - 'color' => $color, - 'size' => $size - ); - } - - /** - * Sets the background color of the element. - * - * See colors.txt in the docs/ folder for a list of available named colors. - * - * @param mixed $color The color - */ - function setBackgroundColor($color) - { - $this->_background = $color; - } - - /** - * Gets the background fill style of the element - * - * @return int A GD fillstyle representing the background style - * @see Image_Graph_Fill - * @access private - */ - function _getBackground() - { - if (is_object($this->_background)) { - $this->_canvas->setFill($this->_background->_getFillStyle()); - } elseif ($this->_background != null) { - $this->_canvas->setFill($this->_background); - } else { - return false; - } - return true; - } - - /** - * Sets the border line style of the element - * - * @param Image_Graph_Line $borderStyle The line style of the border - * @see Image_Graph_Line - */ - function setBorderStyle(& $borderStyle) - { - if (!is_a($borderStyle, 'Image_Graph_Line')) { - $this->_error( - 'Could not set border style for ' . get_class($this) . ': ' . - get_class($borderStyle), array('borderstyle' => &$borderStyle) - ); - } else { - $this->_borderStyle =& $borderStyle; - $this->add($borderStyle); - } - } - - /** - * Sets the border color of the element. - * - * See colors.txt in the docs/ folder for a list of available named colors. - * @param mixed $color The color - */ - function setBorderColor($color) - { - $this->_borderStyle = $color; - } - - /** - * Gets the border line style of the element - * - * @return int A GD linestyle representing the borders line style - * @see Image_Graph_Line - * @access private - */ - function _getBorderStyle() - { - if (is_object($this->_borderStyle)) { - $result = $this->_borderStyle->_getLineStyle(); - $this->_canvas->setLineThickness($result['thickness']); - $this->_canvas->setLineColor($result['color']); - } elseif ($this->_borderStyle != null) { - $this->_canvas->setLineThickness(1); - $this->_canvas->setLineColor($this->_borderStyle); - } else { - return false; - } - return true; - } - - /** - * Sets the line style of the element - * - * @param Image_Graph_Line $lineStyle The line style of the element - * @see Image_Graph_Line - */ - function setLineStyle(& $lineStyle) - { - if (!is_object($lineStyle)) { - $this->_error( - 'Could not set line style for ' . get_class($this) . ': ' . - get_class($lineStyle), array('linestyle' => &$lineStyle) - ); - } else { - $this->_lineStyle =& $lineStyle; - $this->add($lineStyle); - } - } - - /** - * Sets the line color of the element. - * - * See colors.txt in the docs/ folder for a list of available named colors. - * - * @param mixed $color The color - */ - function setLineColor($color) - { - $this->_lineStyle = $color; - } - - /** - * Gets the line style of the element - * - * @return int A GD linestyle representing the line style - * @see Image_Graph_Line - * @access private - */ - function _getLineStyle($ID = false) - { - if (is_object($this->_lineStyle)) { - $result = $this->_lineStyle->_getLineStyle($ID); - if (is_array($result)) { - $this->_canvas->setLineThickness($result['thickness']); - $this->_canvas->setLineColor($result['color']); - } else { - $this->_canvas->setLineThickness(1); - $this->_canvas->setLineColor($result); - } - } elseif ($this->_lineStyle != null) { - $this->_canvas->setLineThickness(1); - $this->_canvas->setLineColor($this->_lineStyle); - } else { - return false; - } - return true; - } - - /** - * Sets the fill style of the element - * - * @param Image_Graph_Fill $fillStyle The fill style of the element - * @see Image_Graph_Fill - */ - function setFillStyle(& $fillStyle) - { - if (!is_a($fillStyle, 'Image_Graph_Fill')) { - $this->_error( - 'Could not set fill style for ' . get_class($this) . ': ' . - get_class($fillStyle), array('fillstyle' => &$fillStyle) - ); - } else { - $this->_fillStyle =& $fillStyle; - $this->add($fillStyle); - } - } - - /** - * Sets the fill color of the element. - * - * See colors.txt in the docs/ folder for a list of available named colors. - * - * @param mixed $color The color - */ - function setFillColor($color) - { - $this->_fillStyle = $color; - } - - - /** - * Gets the fill style of the element - * - * @return int A GD filestyle representing the fill style - * @see Image_Graph_Fill - * @access private - */ - function _getFillStyle($ID = false) - { - if (is_object($this->_fillStyle)) { - $this->_canvas->setFill($this->_fillStyle->_getFillStyle($ID)); - } elseif ($this->_fillStyle != null) { - $this->_canvas->setFill($this->_fillStyle); - } else { - return false; - } - return true; - } - - /** - * Gets the font of the element. - * - * If not font has been set, the parent font is propagated through it's - * children. - * - * @return array An associated array used for canvas - * @access private - */ - function _getFont($options = false) - { - if (($options === false) && ($this->_defaultFontOptions !== false)) { - return $this->_defaultFontOptions; - } - - if ($options === false) { - $saveDefault = true; - } else { - $saveDefault = false; - } - - if ($options === false) { - $options = $this->_fontOptions; - } else { - $options = array_merge($this->_fontOptions, $options); - } - - if ($this->_font == null) { - $result = $this->_parent->_getFont($options); - } else { - $result = $this->_font->_getFont($options); - } - - if ((isset($result['size'])) && (isset($result['size_rel']))) { - $result['size'] += $result['size_rel']; - unset($result['size_rel']); - } - - if ($saveDefault) { - $this->_defaultFontOptions = $result; - } - - return $result; - } - - /** - * Sets the font of the element - * - * @param Image_Graph_Font $font The font of the element - * @see Image_Graph_Font - */ - function setFont(& $font) - { - if (!is_a($font, 'Image_Graph_Font')) { - $this->_error('Invalid font set on ' . get_class($this)); - } else { - $this->_font =& $font; - $this->add($font); - } - } - - /** - * Sets the font size - * - * @param int $size The size of the font - */ - function setFontSize($size) - { - $this->_fontOptions['size'] = $size; - } - - /** - * Sets the font angle - * - * @param int $angle The angle of the font - */ - function setFontAngle($angle) - { - if ($angle == 'vertical') { - $this->_fontOptions['vertical'] = true; - $this->_fontOptions['angle'] = 90; - } else { - $this->_fontOptions['angle'] = $angle; - } - } - - /** - * Sets the font color - * - * @param mixed $color The color of the font - */ - function setFontColor($color) - { - $this->_fontOptions['color'] = $color; - } - - /** - * Sets the coordinates of the element - * - * @param int $left The leftmost pixel of the element on the canvas - * @param int $top The topmost pixel of the element on the canvas - * @param int $right The rightmost pixel of the element on the canvas - * @param int $bottom The bottommost pixel of the element on the canvas - * @access private - */ - function _setCoords($left, $top, $right, $bottom) - { - if ($left === false) { - $left = $this->_left; - } - - if ($top === false) { - $top = $this->_top; - } - - if ($right === false) { - $right = $this->_right; - } - - if ($bottom === false) { - $bottom = $this->_bottom; - } - - $this->_left = min($left, $right); - $this->_top = min($top, $bottom); - $this->_right = max($left, $right); - $this->_bottom = max($top, $bottom); - } - - /** - * Moves the element - * - * @param int $deltaX Number of pixels to move the element to the right - * (negative values move to the left) - * @param int $deltaY Number of pixels to move the element downwards - * (negative values move upwards) - * @access private - */ - function _move($deltaX, $deltaY) - { - $this->_left += $deltaX; - $this->_right += $deltaX; - $this->_top += $deltaY; - $this->_bottom += $deltaY; - } - - /** - * Sets the width of the element relative to the left side - * - * @param int $width Number of pixels the element should be in width - * @access private - */ - function _setWidth($width) - { - $this->_right = $this->_left + $width; - } - - /** - * Sets the height of the element relative to the top - * - * @param int $width Number of pixels the element should be in height - * @access private - */ - function _setHeight($height) - { - $this->_bottom = $this->_top + $height; - } - - /** - * Sets padding of the element - * - * @param int $padding Number of pixels the element should be padded with - */ - function setPadding($padding) - { - $this->_padding = $padding; - } - - /** - * The width of the element on the canvas - * - * @return int Number of pixels representing the width of the element - */ - function width() - { - return abs($this->_right - $this->_left) + 1; - } - - /** - * The height of the element on the canvas - * - * @return int Number of pixels representing the height of the element - */ - function height() - { - return abs($this->_bottom - $this->_top) + 1; - } - - /** - * Left boundary of the background fill area - * - * @return int Leftmost position on the canvas - * @access private - */ - function _fillLeft() - { - return $this->_left + $this->_padding; - } - - /** - * Top boundary of the background fill area - * - * @return int Topmost position on the canvas - * @access private - */ - function _fillTop() - { - return $this->_top + $this->_padding; - } - - /** - * Right boundary of the background fill area - * - * @return int Rightmost position on the canvas - * @access private - */ - function _fillRight() - { - return $this->_right - $this->_padding; - } - - /** - * Bottom boundary of the background fill area - * - * @return int Bottommost position on the canvas - * @access private - */ - function _fillBottom() - { - return $this->_bottom - $this->_padding; - } - - /** - * Returns the filling width of the element on the canvas - * - * @return int Filling width - * @access private - */ - function _fillWidth() - { - return $this->_fillRight() - $this->_fillLeft() + 1; - } - - /** - * Returns the filling height of the element on the canvas - * - * @return int Filling height - * @access private - */ - function _fillHeight() - { - return $this->_fillBottom() - $this->_fillTop() + 1; - } - - /** - * Draws a shadow 'around' the element - * - * Not implemented yet. - * - * @access private - */ - function _displayShadow() - { - if (is_array($this->_shadow)) { - $this->_canvas->startGroup(get_class($this) . '_shadow'); - $this->_canvas->setFillColor($this->_shadow['color']); - $this->_canvas->addVertex(array('x' => $this->_right + 1, 'y' => $this->_top + $this->_shadow['size'])); - $this->_canvas->addVertex(array('x' => $this->_right + $this->_shadow['size'], 'y' => $this->_top + $this->_shadow['size'])); - $this->_canvas->addVertex(array('x' => $this->_right + $this->_shadow['size'], 'y' => $this->_bottom + $this->_shadow['size'])); - $this->_canvas->addVertex(array('x' => $this->_left + $this->_shadow['size'], 'y' => $this->_bottom + $this->_shadow['size'])); - $this->_canvas->addVertex(array('x' => $this->_left + $this->_shadow['size'], 'y' => $this->_bottom + 1)); - $this->_canvas->addVertex(array('x' => $this->_right + 1, 'y' => $this->_bottom + 1)); - $this->_canvas->polygon(array('connect' => true)); - $this->_canvas->endGroup(); - } - } - - /** - * Writes text to the canvas. - * - * @param int $x The x position relative to alignment - * @param int $y The y position relative to alignment - * @param string $text The text - * @param int $alignmen The text alignment (both vertically and horizontally) - */ - function write($x, $y, $text, $alignment = false, $font = false) - { - if (($font === false) && ($this->_defaultFontOptions !== false)) { - $font = $this->_defaultFontOptions; - } else { - $font = $this->_getFont($font); - } - - if ($alignment === false) { - $alignment = IMAGE_GRAPH_ALIGN_LEFT + IMAGE_GRAPH_ALIGN_TOP; - } - - $align = array(); - - if (($alignment & IMAGE_GRAPH_ALIGN_TOP) != 0) { - $align['vertical'] = 'top'; - } else if (($alignment & IMAGE_GRAPH_ALIGN_BOTTOM) != 0) { - $align['vertical'] = 'bottom'; - } else { - $align['vertical'] = 'center'; - } - - if (($alignment & IMAGE_GRAPH_ALIGN_LEFT) != 0) { - $align['horizontal'] = 'left'; - } else if (($alignment & IMAGE_GRAPH_ALIGN_RIGHT) != 0) { - $align['horizontal'] = 'right'; - } else { - $align['horizontal'] = 'center'; - } - - $this->_canvas->setFont($font); - $this->_canvas->addText(array('x' => $x, 'y' => $y, 'text' => $text, 'alignment' => $align)); - } - - /** - * Output the element to the canvas - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @see Image_Graph_Common - * @access private - */ - function _done() - { - $background = $this->_getBackground(); - $border = $this->_getBorderStyle(); - if (($background) || ($border)) { - $this->_canvas->rectangle(array('x0' => $this->_left, 'y0' => $this->_top, 'x1' => $this->_right, 'y1' => $this->_bottom)); - } - - $result = parent::_done(); - - if ($this->_shadow !== false) { - $this->_displayShadow(); - } - - return $result; - } - -} + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Element.php,v 1.18 2006/02/28 22:48:07 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Common.php + */ +require_once 'Image/Graph/Common.php'; + +/** + * Representation of a element. + * + * The Image_Graph_Element can be drawn on the canvas, ie it has coordinates, + * {@link Image_Graph_Line}, {@link Image_Graph_Fill}, border and background - + * although not all of these may apply to all children. + * + * @category Images + * @package Image_Graph + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + * @abstract + */ +class Image_Graph_Element extends Image_Graph_Common +{ + + /** + * The leftmost pixel of the element on the canvas + * @var int + * @access private + */ + var $_left = 0; + + /** + * The topmost pixel of the element on the canvas + * @var int + * @access private + */ + var $_top = 0; + + /** + * The rightmost pixel of the element on the canvas + * @var int + * @access private + */ + var $_right = 0; + + /** + * The bottommost pixel of the element on the canvas + * @var int + * @access private + */ + var $_bottom = 0; + + /** + * Background of the element. Default: None + * @var FillStyle + * @access private + */ + var $_background = null; + + /** + * Borderstyle of the element. Default: None + * @var LineStyle + * @access private + */ + var $_borderStyle = null; + + /** + * Line style of the element. Default: None + * @var LineStyle + * @access private + */ + var $_lineStyle = 'black'; + + /** + * Fill style of the element. Default: None + * @var FillStyle + * @access private + */ + var $_fillStyle = 'white'; + + /** + * Font of the element. Default: Standard font - FONT + * @var Font + * @access private + * @see $IMAGE_GRAPH_FONT + */ + var $_font = null; + + /** + * Font options + * @var array + * @access private + */ + var $_fontOptions = array(); + + /** + * Default font options + * + * This option is included for performance reasons. The value is calculated + * before output and reused in default cases to avoid unnecessary recursive + * calls. + * + * @var array + * @access private + */ + var $_defaultFontOptions = false; + + /** + * Shadows options of the element + * @var mixed + * @access private + */ + var $_shadow = false; + + /** + * The padding displayed on the element + * @var int + * @access private + */ + var $_padding = array('left' => 0, 'top' => 0, 'right' => 0, 'bottom' => 0); + + /** + * Sets the background fill style of the element + * + * @param Image_Graph_Fill $background The background + * @see Image_Graph_Fill + */ + function setBackground(& $background) + { + if (!is_a($background, 'Image_Graph_Fill')) { + $this->_error( + 'Could not set background for ' . get_class($this) . ': ' . + get_class($background), array('background' => &$background) + ); + } else { + $this->_background =& $background; + $this->add($background); + } + } + + /** + * Shows shadow on the element + */ + function showShadow($color = 'black@0.2', $size = 5) + { + $this->_shadow = array( + 'color' => $color, + 'size' => $size + ); + } + + /** + * Sets the background color of the element. + * + * See colors.txt in the docs/ folder for a list of available named colors. + * + * @param mixed $color The color + */ + function setBackgroundColor($color) + { + $this->_background = $color; + } + + /** + * Gets the background fill style of the element + * + * @return int A GD fillstyle representing the background style + * @see Image_Graph_Fill + * @access private + */ + function _getBackground() + { + if (is_object($this->_background)) { + $this->_canvas->setFill($this->_background->_getFillStyle()); + } elseif ($this->_background != null) { + $this->_canvas->setFill($this->_background); + } else { + return false; + } + return true; + } + + /** + * Sets the border line style of the element + * + * @param Image_Graph_Line $borderStyle The line style of the border + * @see Image_Graph_Line + */ + function setBorderStyle(& $borderStyle) + { + if (!is_a($borderStyle, 'Image_Graph_Line')) { + $this->_error( + 'Could not set border style for ' . get_class($this) . ': ' . + get_class($borderStyle), array('borderstyle' => &$borderStyle) + ); + } else { + $this->_borderStyle =& $borderStyle; + $this->add($borderStyle); + } + } + + /** + * Sets the border color of the element. + * + * See colors.txt in the docs/ folder for a list of available named colors. + * @param mixed $color The color + */ + function setBorderColor($color) + { + $this->_borderStyle = $color; + } + + /** + * Gets the border line style of the element + * + * @return int A GD linestyle representing the borders line style + * @see Image_Graph_Line + * @access private + */ + function _getBorderStyle() + { + if (is_object($this->_borderStyle)) { + $result = $this->_borderStyle->_getLineStyle(); + $this->_canvas->setLineThickness($result['thickness']); + $this->_canvas->setLineColor($result['color']); + } elseif ($this->_borderStyle != null) { + $this->_canvas->setLineThickness(1); + $this->_canvas->setLineColor($this->_borderStyle); + } else { + return false; + } + return true; + } + + /** + * Sets the line style of the element + * + * @param Image_Graph_Line $lineStyle The line style of the element + * @see Image_Graph_Line + */ + function setLineStyle(& $lineStyle) + { + if (!is_object($lineStyle)) { + $this->_error( + 'Could not set line style for ' . get_class($this) . ': ' . + get_class($lineStyle), array('linestyle' => &$lineStyle) + ); + } else { + $this->_lineStyle =& $lineStyle; + $this->add($lineStyle); + } + } + + /** + * Sets the line color of the element. + * + * See colors.txt in the docs/ folder for a list of available named colors. + * + * @param mixed $color The color + */ + function setLineColor($color) + { + $this->_lineStyle = $color; + } + + /** + * Gets the line style of the element + * + * @return int A GD linestyle representing the line style + * @see Image_Graph_Line + * @access private + */ + function _getLineStyle($ID = false) + { + if (is_object($this->_lineStyle)) { + $result = $this->_lineStyle->_getLineStyle($ID); + if (is_array($result)) { + $this->_canvas->setLineThickness($result['thickness']); + $this->_canvas->setLineColor($result['color']); + } else { + $this->_canvas->setLineThickness(1); + $this->_canvas->setLineColor($result); + } + } elseif ($this->_lineStyle != null) { + $this->_canvas->setLineThickness(1); + $this->_canvas->setLineColor($this->_lineStyle); + } else { + return false; + } + return true; + } + + /** + * Sets the fill style of the element + * + * @param Image_Graph_Fill $fillStyle The fill style of the element + * @see Image_Graph_Fill + */ + function setFillStyle(& $fillStyle) + { + if (!is_a($fillStyle, 'Image_Graph_Fill')) { + $this->_error( + 'Could not set fill style for ' . get_class($this) . ': ' . + get_class($fillStyle), array('fillstyle' => &$fillStyle) + ); + } else { + $this->_fillStyle =& $fillStyle; + $this->add($fillStyle); + } + } + + /** + * Sets the fill color of the element. + * + * See colors.txt in the docs/ folder for a list of available named colors. + * + * @param mixed $color The color + */ + function setFillColor($color) + { + $this->_fillStyle = $color; + } + + + /** + * Gets the fill style of the element + * + * @return int A GD filestyle representing the fill style + * @see Image_Graph_Fill + * @access private + */ + function _getFillStyle($ID = false) + { + if (is_object($this->_fillStyle)) { + $this->_canvas->setFill($this->_fillStyle->_getFillStyle($ID)); + } elseif ($this->_fillStyle != null) { + $this->_canvas->setFill($this->_fillStyle); + } else { + return false; + } + return true; + } + + /** + * Gets the font of the element. + * + * If not font has been set, the parent font is propagated through it's + * children. + * + * @return array An associated array used for canvas + * @access private + */ + function _getFont($options = false) + { + if (($options === false) && ($this->_defaultFontOptions !== false)) { + return $this->_defaultFontOptions; + } + + if ($options === false) { + $saveDefault = true; + } else { + $saveDefault = false; + } + + if ($options === false) { + $options = $this->_fontOptions; + } else { + $options = array_merge($this->_fontOptions, $options); + } + + if ($this->_font == null) { + $result = $this->_parent->_getFont($options); + } else { + $result = $this->_font->_getFont($options); + } + + if ((isset($result['size'])) && (isset($result['size_rel']))) { + $result['size'] += $result['size_rel']; + unset($result['size_rel']); + } + + if ($saveDefault) { + $this->_defaultFontOptions = $result; + } + + return $result; + } + + /** + * Sets the font of the element + * + * @param Image_Graph_Font $font The font of the element + * @see Image_Graph_Font + */ + function setFont(& $font) + { + if (!is_a($font, 'Image_Graph_Font')) { + $this->_error('Invalid font set on ' . get_class($this)); + } else { + $this->_font =& $font; + $this->add($font); + } + } + + /** + * Sets the font size + * + * @param int $size The size of the font + */ + function setFontSize($size) + { + $this->_fontOptions['size'] = $size; + } + + /** + * Sets the font angle + * + * @param int $angle The angle of the font + */ + function setFontAngle($angle) + { + if ($angle == 'vertical') { + $this->_fontOptions['vertical'] = true; + $this->_fontOptions['angle'] = 90; + } else { + $this->_fontOptions['angle'] = $angle; + } + } + + /** + * Sets the font color + * + * @param mixed $color The color of the font + */ + function setFontColor($color) + { + $this->_fontOptions['color'] = $color; + } + + /** + * Clip the canvas to the coordinates of the element + * + * @param $enable bool Whether clipping should be enabled or disabled + * @access protected + */ + function _clip($enable) + { + $this->_canvas->setClipping( + ($enable ? + array( + 'x0' => min($this->_left, $this->_right), + 'y0' => min($this->_top, $this->_bottom), + 'x1' => max($this->_left, $this->_right), + 'y1' => max($this->_top, $this->_bottom) + ) + : false + ) + ); + } + + /** + * Sets the coordinates of the element + * + * @param int $left The leftmost pixel of the element on the canvas + * @param int $top The topmost pixel of the element on the canvas + * @param int $right The rightmost pixel of the element on the canvas + * @param int $bottom The bottommost pixel of the element on the canvas + * @access private + */ + function _setCoords($left, $top, $right, $bottom) + { + if ($left === false) { + $left = $this->_left; + } + + if ($top === false) { + $top = $this->_top; + } + + if ($right === false) { + $right = $this->_right; + } + + if ($bottom === false) { + $bottom = $this->_bottom; + } + + $this->_left = min($left, $right); + $this->_top = min($top, $bottom); + $this->_right = max($left, $right); + $this->_bottom = max($top, $bottom); + } + + /** + * Moves the element + * + * @param int $deltaX Number of pixels to move the element to the right + * (negative values move to the left) + * @param int $deltaY Number of pixels to move the element downwards + * (negative values move upwards) + * @access private + */ + function _move($deltaX, $deltaY) + { + $this->_left += $deltaX; + $this->_right += $deltaX; + $this->_top += $deltaY; + $this->_bottom += $deltaY; + } + + /** + * Sets the width of the element relative to the left side + * + * @param int $width Number of pixels the element should be in width + * @access private + */ + function _setWidth($width) + { + $this->_right = $this->_left + $width; + } + + /** + * Sets the height of the element relative to the top + * + * @param int $width Number of pixels the element should be in height + * @access private + */ + function _setHeight($height) + { + $this->_bottom = $this->_top + $height; + } + + /** + * Sets padding of the element + * + * @param mixed $padding Number of pixels the element should be padded with + * or an array of paddings (left, top, right and bottom as index) + */ + function setPadding($padding) + { + if (is_array($padding)) { + $this->_padding = array(); + $this->_padding['left'] = (isset($padding['left']) ? $padding['left'] : 0); + $this->_padding['top'] = (isset($padding['top']) ? $padding['top'] : 0); + $this->_padding['right'] = (isset($padding['right']) ? $padding['right'] : 0); + $this->_padding['bottom'] = (isset($padding['bottom']) ? $padding['bottom'] : 0); + } + else { + $this->_padding = array( + 'left' => $padding, + 'top' => $padding, + 'right' => $padding, + 'bottom' => $padding + ); + } + } + + /** + * The width of the element on the canvas + * + * @return int Number of pixels representing the width of the element + */ + function width() + { + return abs($this->_right - $this->_left) + 1; + } + + /** + * The height of the element on the canvas + * + * @return int Number of pixels representing the height of the element + */ + function height() + { + return abs($this->_bottom - $this->_top) + 1; + } + + /** + * Left boundary of the background fill area + * + * @return int Leftmost position on the canvas + * @access private + */ + function _fillLeft() + { + return $this->_left + $this->_padding['left']; + } + + /** + * Top boundary of the background fill area + * + * @return int Topmost position on the canvas + * @access private + */ + function _fillTop() + { + return $this->_top + $this->_padding['top']; + } + + /** + * Right boundary of the background fill area + * + * @return int Rightmost position on the canvas + * @access private + */ + function _fillRight() + { + return $this->_right - $this->_padding['right']; + } + + /** + * Bottom boundary of the background fill area + * + * @return int Bottommost position on the canvas + * @access private + */ + function _fillBottom() + { + return $this->_bottom - $this->_padding['bottom']; + } + + /** + * Returns the filling width of the element on the canvas + * + * @return int Filling width + * @access private + */ + function _fillWidth() + { + return $this->_fillRight() - $this->_fillLeft() + 1; + } + + /** + * Returns the filling height of the element on the canvas + * + * @return int Filling height + * @access private + */ + function _fillHeight() + { + return $this->_fillBottom() - $this->_fillTop() + 1; + } + + /** + * Draws a shadow 'around' the element + * + * Not implemented yet. + * + * @access private + */ + function _displayShadow() + { + if (is_array($this->_shadow)) { + $this->_canvas->startGroup(get_class($this) . '_shadow'); + $this->_canvas->setFillColor($this->_shadow['color']); + $this->_canvas->addVertex(array('x' => $this->_right + 1, 'y' => $this->_top + $this->_shadow['size'])); + $this->_canvas->addVertex(array('x' => $this->_right + $this->_shadow['size'], 'y' => $this->_top + $this->_shadow['size'])); + $this->_canvas->addVertex(array('x' => $this->_right + $this->_shadow['size'], 'y' => $this->_bottom + $this->_shadow['size'])); + $this->_canvas->addVertex(array('x' => $this->_left + $this->_shadow['size'], 'y' => $this->_bottom + $this->_shadow['size'])); + $this->_canvas->addVertex(array('x' => $this->_left + $this->_shadow['size'], 'y' => $this->_bottom + 1)); + $this->_canvas->addVertex(array('x' => $this->_right + 1, 'y' => $this->_bottom + 1)); + $this->_canvas->polygon(array('connect' => true)); + $this->_canvas->endGroup(); + } + } + + /** + * Writes text to the canvas. + * + * @param int $x The x position relative to alignment + * @param int $y The y position relative to alignment + * @param string $text The text + * @param int $alignmen The text alignment (both vertically and horizontally) + */ + function write($x, $y, $text, $alignment = false, $font = false) + { + if (($font === false) && ($this->_defaultFontOptions !== false)) { + $font = $this->_defaultFontOptions; + } else { + $font = $this->_getFont($font); + } + + if ($alignment === false) { + $alignment = IMAGE_GRAPH_ALIGN_LEFT + IMAGE_GRAPH_ALIGN_TOP; + } + + $align = array(); + + if (($alignment & IMAGE_GRAPH_ALIGN_TOP) != 0) { + $align['vertical'] = 'top'; + } else if (($alignment & IMAGE_GRAPH_ALIGN_BOTTOM) != 0) { + $align['vertical'] = 'bottom'; + } else { + $align['vertical'] = 'center'; + } + + if (($alignment & IMAGE_GRAPH_ALIGN_LEFT) != 0) { + $align['horizontal'] = 'left'; + } else if (($alignment & IMAGE_GRAPH_ALIGN_RIGHT) != 0) { + $align['horizontal'] = 'right'; + } else { + $align['horizontal'] = 'center'; + } + + $this->_canvas->setFont($font); + $this->_canvas->addText(array('x' => $x, 'y' => $y, 'text' => $text, 'alignment' => $align)); + } + + /** + * Output the element to the canvas + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @see Image_Graph_Common + * @access private + */ + function _done() + { + $background = $this->_getBackground(); + $border = $this->_getBorderStyle(); + if (($background) || ($border)) { + $this->_canvas->rectangle(array('x0' => $this->_left, 'y0' => $this->_top, 'x1' => $this->_right, 'y1' => $this->_bottom)); + } + + $result = parent::_done(); + + if ($this->_shadow !== false) { + $this->_displayShadow(); + } + + return $result; + } + +} ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Figure/Circle.php b/includes/pear/Image/Graph/Figure/Circle.php index 262368ae..26006ffd 100644 --- a/includes/pear/Image/Graph/Figure/Circle.php +++ b/includes/pear/Image/Graph/Figure/Circle.php @@ -1,64 +1,64 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Circle.php,v 1.6 2005/08/24 20:36:01 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Figure/Ellipse.php - */ -require_once 'Image/Graph/Figure/Ellipse.php'; - -/** - * Circle to draw on the canvas - * - * @category Images - * @package Image_Graph - * @subpackage Figure - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Figure_Circle extends Image_Graph_Figure_Ellipse -{ - - /** - * Image_Graph_Circle [Constructor] - * - * @param int $x The center pixel of the circle on the canvas - * @param int $y The center pixel of the circle on the canvas - * @param int $radius The radius in pixels of the circle - */ - function Image_Graph_Figure_Circle($x, $y, $radius) - { - parent::Image_Graph_Ellipse($x, $y, $radius, $radius); - } - -} + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Circle.php,v 1.6 2005/08/24 20:36:01 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Figure/Ellipse.php + */ +require_once 'Image/Graph/Figure/Ellipse.php'; + +/** + * Circle to draw on the canvas + * + * @category Images + * @package Image_Graph + * @subpackage Figure + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Figure_Circle extends Image_Graph_Figure_Ellipse +{ + + /** + * Image_Graph_Circle [Constructor] + * + * @param int $x The center pixel of the circle on the canvas + * @param int $y The center pixel of the circle on the canvas + * @param int $radius The radius in pixels of the circle + */ + function Image_Graph_Figure_Circle($x, $y, $radius) + { + parent::Image_Graph_Ellipse($x, $y, $radius, $radius); + } + +} ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Figure/Ellipse.php b/includes/pear/Image/Graph/Figure/Ellipse.php index 7c1e39f8..1e4ccc87 100644 --- a/includes/pear/Image/Graph/Figure/Ellipse.php +++ b/includes/pear/Image/Graph/Figure/Ellipse.php @@ -1,97 +1,97 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Ellipse.php,v 1.9 2005/08/24 20:36:00 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Element.php - */ -require_once 'Image/Graph/Element.php'; - -/** - * Ellipse to draw on the canvas - * - * @category Images - * @package Image_Graph - * @subpackage Figure - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Figure_Ellipse extends Image_Graph_Element -{ - - /** - * Ellipse [Constructor] - * - * @param int $x The center pixel of the ellipse on the canvas - * @param int $y The center pixel of the ellipse on the canvas - * @param int $radiusX The width in pixels of the box on the canvas - * @param int $radiusY The height in pixels of the box on the canvas - */ - function Image_Graph_Figure_Ellipse($x, $y, $radiusX, $radiusY) - { - parent::Image_Graph_Element(); - $this->_setCoords($x - $radiusX, $y - $radiusY, $x + $radiusX, $y + $radiusY); - } - - /** - * Output the ellipse - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (parent::_done() === false) { - return false; - } - - $this->_canvas->startGroup(get_class($this)); - - $this->_getFillStyle(); - $this->_getLineStyle(); - $this->_canvas->ellipse( - array( - 'x' => ($this->_left + $this->_right) / 2, - 'y' => ($this->_top + $this->_bottom) / 2, - 'rx' => $this->width(), - 'ry' => $this->height() - ) - ); - - $this->_canvas->endGroup(); - - return true; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Ellipse.php,v 1.9 2005/08/24 20:36:00 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Element.php + */ +require_once 'Image/Graph/Element.php'; + +/** + * Ellipse to draw on the canvas + * + * @category Images + * @package Image_Graph + * @subpackage Figure + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Figure_Ellipse extends Image_Graph_Element +{ + + /** + * Ellipse [Constructor] + * + * @param int $x The center pixel of the ellipse on the canvas + * @param int $y The center pixel of the ellipse on the canvas + * @param int $radiusX The width in pixels of the box on the canvas + * @param int $radiusY The height in pixels of the box on the canvas + */ + function Image_Graph_Figure_Ellipse($x, $y, $radiusX, $radiusY) + { + parent::Image_Graph_Element(); + $this->_setCoords($x - $radiusX, $y - $radiusY, $x + $radiusX, $y + $radiusY); + } + + /** + * Output the ellipse + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + $this->_canvas->startGroup(get_class($this)); + + $this->_getFillStyle(); + $this->_getLineStyle(); + $this->_canvas->ellipse( + array( + 'x' => ($this->_left + $this->_right) / 2, + 'y' => ($this->_top + $this->_bottom) / 2, + 'rx' => $this->width(), + 'ry' => $this->height() + ) + ); + + $this->_canvas->endGroup(); + + return true; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Figure/Polygon.php b/includes/pear/Image/Graph/Figure/Polygon.php index 15e0f1c7..e2ff6079 100644 --- a/includes/pear/Image/Graph/Figure/Polygon.php +++ b/includes/pear/Image/Graph/Figure/Polygon.php @@ -1,94 +1,94 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Polygon.php,v 1.8 2005/08/03 21:21:57 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Element.php - */ -require_once 'Image/Graph/Element.php'; - -/** - * Polygon to draw on the canvas - * - * @category Images - * @package Image_Graph - * @subpackage Figure - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Figure_Polygon extends Image_Graph_Element -{ - - /** - * Polygon vertices - * - * @var array - * @access private - */ - var $_polygon = array (); - - /** - * Add a vertex to the polygon - * - * @param int $x X-coordinate - * @param int $y Y-coordinate - */ - function addVertex($x, $y) - { - $this->_canvas->addVertex(array('x' => $x, 'y' => $y)); - } - - /** - * Output the polygon - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (parent::_done() === false) { - return false; - } - - $this->_canvas->startGroup(get_class($this)); - - $this->_getFillStyle(); - $this->_getLineStyle(); - $this->_canvas->polygon(array('connect' => true)); - - $this->_canvas->endGroup(); - return true; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Polygon.php,v 1.8 2005/08/03 21:21:57 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Element.php + */ +require_once 'Image/Graph/Element.php'; + +/** + * Polygon to draw on the canvas + * + * @category Images + * @package Image_Graph + * @subpackage Figure + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Figure_Polygon extends Image_Graph_Element +{ + + /** + * Polygon vertices + * + * @var array + * @access private + */ + var $_polygon = array (); + + /** + * Add a vertex to the polygon + * + * @param int $x X-coordinate + * @param int $y Y-coordinate + */ + function addVertex($x, $y) + { + $this->_canvas->addVertex(array('x' => $x, 'y' => $y)); + } + + /** + * Output the polygon + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + $this->_canvas->startGroup(get_class($this)); + + $this->_getFillStyle(); + $this->_getLineStyle(); + $this->_canvas->polygon(array('connect' => true)); + + $this->_canvas->endGroup(); + return true; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Figure/Rectangle.php b/includes/pear/Image/Graph/Figure/Rectangle.php index e5c2901c..6b3bd4e5 100644 --- a/includes/pear/Image/Graph/Figure/Rectangle.php +++ b/includes/pear/Image/Graph/Figure/Rectangle.php @@ -1,96 +1,96 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Rectangle.php,v 1.9 2005/08/24 20:36:01 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Element.php - */ -require_once 'Image/Graph/Element.php'; - -/** - * Rectangle to draw on the canvas - * - * @category Images - * @package Image_Graph - * @subpackage Figure - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Figure_Rectangle extends Image_Graph_Element -{ - - /** - * Rectangle [Construcor] - * - * @param int $x The leftmost pixel of the box on the canvas - * @param int $y The topmost pixel of the box on the canvas - * @param int $width The width in pixels of the box on the canvas - * @param int $height The height in pixels of the box on the canvas - */ - function Image_Graph_Figure_Rectangle($x, $y, $width, $height) - { - parent::Image_Graph_Element(); - $this->_setCoords($x, $y, $x + $width, $y + $height); - } - - /** - * Output the box - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (parent::_done() === false) { - return false; - } - - $this->_canvas->startGroup(get_class($this)); - - $this->_getFillStyle(); - $this->_getLineStyle(); - $this->_canvas->rectangle( - array( - 'x0' => $this->_left, - 'y0' => $this->_top, - 'x1' => $this->_right, - 'y1' => $this->_bottom - ) - ); - - $this->_canvas->endGroup(); - - return true; - } - -} + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Rectangle.php,v 1.9 2005/08/24 20:36:01 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Element.php + */ +require_once 'Image/Graph/Element.php'; + +/** + * Rectangle to draw on the canvas + * + * @category Images + * @package Image_Graph + * @subpackage Figure + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Figure_Rectangle extends Image_Graph_Element +{ + + /** + * Rectangle [Construcor] + * + * @param int $x The leftmost pixel of the box on the canvas + * @param int $y The topmost pixel of the box on the canvas + * @param int $width The width in pixels of the box on the canvas + * @param int $height The height in pixels of the box on the canvas + */ + function Image_Graph_Figure_Rectangle($x, $y, $width, $height) + { + parent::Image_Graph_Element(); + $this->_setCoords($x, $y, $x + $width, $y + $height); + } + + /** + * Output the box + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + $this->_canvas->startGroup(get_class($this)); + + $this->_getFillStyle(); + $this->_getLineStyle(); + $this->_canvas->rectangle( + array( + 'x0' => $this->_left, + 'y0' => $this->_top, + 'x1' => $this->_right, + 'y1' => $this->_bottom + ) + ); + + $this->_canvas->endGroup(); + + return true; + } + +} ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Fill.php b/includes/pear/Image/Graph/Fill.php index b7fadc99..69e3e229 100644 --- a/includes/pear/Image/Graph/Fill.php +++ b/includes/pear/Image/Graph/Fill.php @@ -1,63 +1,63 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Fill.php,v 1.6 2005/02/21 20:49:46 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Element.php - */ -require_once 'Image/Graph/Element.php'; - -/** - * Style used for filling elements. - * - * @category Images - * @package Image_Graph - * @subpackage Fill - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - * @abstract - */ -class Image_Graph_Fill extends Image_Graph_Common -{ - - /** - * Resets the fillstyle - * - * @access private - */ - function _reset() - { - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Fill.php,v 1.6 2005/02/21 20:49:46 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Element.php + */ +require_once 'Image/Graph/Element.php'; + +/** + * Style used for filling elements. + * + * @category Images + * @package Image_Graph + * @subpackage Fill + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + * @abstract + */ +class Image_Graph_Fill extends Image_Graph_Common +{ + + /** + * Resets the fillstyle + * + * @access private + */ + function _reset() + { + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Fill/Array.php b/includes/pear/Image/Graph/Fill/Array.php index d76124f8..0ade5c19 100644 --- a/includes/pear/Image/Graph/Fill/Array.php +++ b/includes/pear/Image/Graph/Fill/Array.php @@ -1,137 +1,137 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Array.php,v 1.8 2005/08/24 20:36:03 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Fill.php - */ -require_once 'Image/Graph/Fill.php'; - -/** - * A sequential array of fillstyles. - * - * This is used for filling multiple objects within the same element with - * different styles. This is done by adding multiple fillstyles to a FillArrray - * structure. The fillarray will then when requested return the 'next' fillstyle - * in sequential order. It is possible to specify ID tags to each fillstyle, - * which is used to make sure some data uses a specific fillstyle (i.e. in a - * multiple-/stackedbarchart you name the {@link Image_Graph_Dataset}s and uses - * this name as ID tag when adding the dataset's associated fillstyle to the - * fillarray. - * - * @category Images - * @package Image_Graph - * @subpackage Fill - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Fill_Array extends Image_Graph_Fill -{ - - /** - * The fill array - * @var array - * @access private - */ - var $_fillStyles = array (); - - /** - * Resets the fillstyle - * - * @access private - */ - function _reset() - { - reset($this->_fillStyles); - } - - /** - * Add a fill style to the array - * - * @param Image_Graph_Fill $style The style to add - * @param string $id The id or name of the style - */ - function &add(& $style, $id = '') - { - if ($id == '') { - $this->_fillStyles[] =& $style; - } else { - $this->_fillStyles[$id] =& $style; - } - reset($this->_fillStyles); - return $style; - } - - /** - * Add a color to the array - * - * @param int $color The color - * @param string $id The id or name of the color - */ - function addColor($color, $id = false) - { - if ($id !== false) { - $this->_fillStyles[$id] = $color; - } else { - $this->_fillStyles[] = $color; - } - reset($this->_fillStyles); - } - - /** - * Return the fillstyle - * - * @return int A GD fillstyle - * @access private - */ - function _getFillStyle($ID = false) - { - if (($ID === false) || (!isset($this->_fillStyles[$ID]))) { - $ID = key($this->_fillStyles); - if (!next($this->_fillStyles)) { - reset($this->_fillStyles); - } - } - $fillStyle =& $this->_fillStyles[$ID]; - - if (is_object($fillStyle)) { - return $fillStyle->_getFillStyle($ID); - } elseif ($fillStyle !== null) { - return $fillStyle; - } else { - return parent::_getFillStyle($ID); - } - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Array.php,v 1.8 2005/08/24 20:36:03 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Fill.php + */ +require_once 'Image/Graph/Fill.php'; + +/** + * A sequential array of fillstyles. + * + * This is used for filling multiple objects within the same element with + * different styles. This is done by adding multiple fillstyles to a FillArrray + * structure. The fillarray will then when requested return the 'next' fillstyle + * in sequential order. It is possible to specify ID tags to each fillstyle, + * which is used to make sure some data uses a specific fillstyle (i.e. in a + * multiple-/stackedbarchart you name the {@link Image_Graph_Dataset}s and uses + * this name as ID tag when adding the dataset's associated fillstyle to the + * fillarray. + * + * @category Images + * @package Image_Graph + * @subpackage Fill + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Fill_Array extends Image_Graph_Fill +{ + + /** + * The fill array + * @var array + * @access private + */ + var $_fillStyles = array (); + + /** + * Resets the fillstyle + * + * @access private + */ + function _reset() + { + reset($this->_fillStyles); + } + + /** + * Add a fill style to the array + * + * @param Image_Graph_Fill $style The style to add + * @param string $id The id or name of the style + */ + function &add(& $style, $id = '') + { + if ($id == '') { + $this->_fillStyles[] =& $style; + } else { + $this->_fillStyles[$id] =& $style; + } + reset($this->_fillStyles); + return $style; + } + + /** + * Add a color to the array + * + * @param int $color The color + * @param string $id The id or name of the color + */ + function addColor($color, $id = false) + { + if ($id !== false) { + $this->_fillStyles[$id] = $color; + } else { + $this->_fillStyles[] = $color; + } + reset($this->_fillStyles); + } + + /** + * Return the fillstyle + * + * @return int A GD fillstyle + * @access private + */ + function _getFillStyle($ID = false) + { + if (($ID === false) || (!isset($this->_fillStyles[$ID]))) { + $ID = key($this->_fillStyles); + if (!next($this->_fillStyles)) { + reset($this->_fillStyles); + } + } + $fillStyle =& $this->_fillStyles[$ID]; + + if (is_object($fillStyle)) { + return $fillStyle->_getFillStyle($ID); + } elseif ($fillStyle !== null) { + return $fillStyle; + } else { + return parent::_getFillStyle($ID); + } + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Fill/Gradient.php b/includes/pear/Image/Graph/Fill/Gradient.php index e12b805a..5b39fff8 100644 --- a/includes/pear/Image/Graph/Fill/Gradient.php +++ b/includes/pear/Image/Graph/Fill/Gradient.php @@ -1,149 +1,149 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Gradient.php,v 1.15 2005/08/24 20:36:03 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Fill/Image.php - */ -require_once 'Image/Graph/Fill/Image.php'; - -/** - * Fill using a gradient color. - * This creates a scaled fillstyle with colors flowing gradiently between 2 - * specified RGB values. Several directions are supported: - * - * 1 Vertically (IMAGE_GRAPH_GRAD_VERTICAL) - * - * 2 Horizontally (IMAGE_GRAPH_GRAD_HORIZONTAL) - * - * 3 Mirrored vertically (the color grades from a- b-a vertically) - * (IMAGE_GRAPH_GRAD_VERTICAL_MIRRORED) - * - * 4 Mirrored horizontally (the color grades from a-b-a horizontally) - * IMAGE_GRAPH_GRAD_HORIZONTAL_MIRRORED - * - * 5 Diagonally from top-left to right-bottom - * (IMAGE_GRAPH_GRAD_DIAGONALLY_TL_BR) - * - * 6 Diagonally from bottom-left to top-right - * (IMAGE_GRAPH_GRAD_DIAGONALLY_BL_TR) - * - * 7 Radially (concentric circles in the center) (IMAGE_GRAPH_GRAD_RADIAL) - * - * @category Images - * @package Image_Graph - * @subpackage Fill - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Fill_Gradient extends Image_Graph_Fill //Image_Graph_Fill_Image -{ - - /** - * The direction of the gradient - * @var int - * @access private - */ - var $_direction; - - /** - * The first color to gradient - * @var mixed - * @access private - */ - var $_startColor; - - /** - * The last color to gradient - * @var mixed - * @access private - */ - var $_endColor; - - /** - * Image_Graph_GradientFill [Constructor] - * - * @param int $direction The direction of the gradient - * @param mixed $startColor The value of the starting color - * @param mixed $endColor The value of the ending color - */ - function Image_Graph_Fill_Gradient($direction, $startColor, $endColor) - { - parent::Image_Graph_Fill(); - $this->_direction = $direction; - $this->_startColor = $startColor; - $this->_endColor = $endColor; - } - - /** - * Return the fillstyle - * - * @return int A GD fillstyle - * @access private - */ - function _getFillStyle($ID = false) - { - switch ($this->_direction) { - case IMAGE_GRAPH_GRAD_HORIZONTAL: - $direction = 'horizontal'; - break; - case IMAGE_GRAPH_GRAD_VERTICAL: - $direction = 'vertical'; - break; - case IMAGE_GRAPH_GRAD_HORIZONTAL_MIRRORED: - $direction = 'horizontal_mirror'; - break; - case IMAGE_GRAPH_GRAD_VERTICAL_MIRRORED: - $direction = 'vertical_mirror'; - break; - case IMAGE_GRAPH_GRAD_DIAGONALLY_TL_BR: - $direction = 'diagonal_tl_br'; - break; - case IMAGE_GRAPH_GRAD_DIAGONALLY_BL_TR: - $direction = 'diagonal_bl_tr'; - break; - case IMAGE_GRAPH_GRAD_RADIAL: - $direction = 'radial'; - break; - } - - return array( - 'type' => 'gradient', - 'start' => $this->_startColor, - 'end' => $this->_endColor, - 'direction' => $direction - ); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Gradient.php,v 1.15 2005/08/24 20:36:03 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Fill/Image.php + */ +require_once 'Image/Graph/Fill/Image.php'; + +/** + * Fill using a gradient color. + * This creates a scaled fillstyle with colors flowing gradiently between 2 + * specified RGB values. Several directions are supported: + * + * 1 Vertically (IMAGE_GRAPH_GRAD_VERTICAL) + * + * 2 Horizontally (IMAGE_GRAPH_GRAD_HORIZONTAL) + * + * 3 Mirrored vertically (the color grades from a- b-a vertically) + * (IMAGE_GRAPH_GRAD_VERTICAL_MIRRORED) + * + * 4 Mirrored horizontally (the color grades from a-b-a horizontally) + * IMAGE_GRAPH_GRAD_HORIZONTAL_MIRRORED + * + * 5 Diagonally from top-left to right-bottom + * (IMAGE_GRAPH_GRAD_DIAGONALLY_TL_BR) + * + * 6 Diagonally from bottom-left to top-right + * (IMAGE_GRAPH_GRAD_DIAGONALLY_BL_TR) + * + * 7 Radially (concentric circles in the center) (IMAGE_GRAPH_GRAD_RADIAL) + * + * @category Images + * @package Image_Graph + * @subpackage Fill + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Fill_Gradient extends Image_Graph_Fill //Image_Graph_Fill_Image +{ + + /** + * The direction of the gradient + * @var int + * @access private + */ + var $_direction; + + /** + * The first color to gradient + * @var mixed + * @access private + */ + var $_startColor; + + /** + * The last color to gradient + * @var mixed + * @access private + */ + var $_endColor; + + /** + * Image_Graph_GradientFill [Constructor] + * + * @param int $direction The direction of the gradient + * @param mixed $startColor The value of the starting color + * @param mixed $endColor The value of the ending color + */ + function Image_Graph_Fill_Gradient($direction, $startColor, $endColor) + { + parent::Image_Graph_Fill(); + $this->_direction = $direction; + $this->_startColor = $startColor; + $this->_endColor = $endColor; + } + + /** + * Return the fillstyle + * + * @return int A GD fillstyle + * @access private + */ + function _getFillStyle($ID = false) + { + switch ($this->_direction) { + case IMAGE_GRAPH_GRAD_HORIZONTAL: + $direction = 'horizontal'; + break; + case IMAGE_GRAPH_GRAD_VERTICAL: + $direction = 'vertical'; + break; + case IMAGE_GRAPH_GRAD_HORIZONTAL_MIRRORED: + $direction = 'horizontal_mirror'; + break; + case IMAGE_GRAPH_GRAD_VERTICAL_MIRRORED: + $direction = 'vertical_mirror'; + break; + case IMAGE_GRAPH_GRAD_DIAGONALLY_TL_BR: + $direction = 'diagonal_tl_br'; + break; + case IMAGE_GRAPH_GRAD_DIAGONALLY_BL_TR: + $direction = 'diagonal_bl_tr'; + break; + case IMAGE_GRAPH_GRAD_RADIAL: + $direction = 'radial'; + break; + } + + return array( + 'type' => 'gradient', + 'start' => $this->_startColor, + 'end' => $this->_endColor, + 'direction' => $direction + ); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Fill/Image.php b/includes/pear/Image/Graph/Fill/Image.php index 101b47d5..832f1eda 100644 --- a/includes/pear/Image/Graph/Fill/Image.php +++ b/includes/pear/Image/Graph/Fill/Image.php @@ -1,97 +1,97 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Image.php,v 1.7 2005/08/24 20:36:03 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Fill.php - */ -require_once 'Image/Graph/Fill.php'; - -/** - * Fill using an image. - * - * @category Images - * @package Image_Graph - * @subpackage Fill - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Fill_Image extends Image_Graph_Fill -{ - - /** - * The file name - * @var stirng - * @access private - */ - var $_filename; - - /** - * The GD Image resource - * @var resource - * @access private - */ - var $_image; - - /** - * Resize the image to the bounding box of the area to fill - * @var bool - * @access private - */ - var $_resize = true; - - /** - * Image_Graph_ImageFill [Constructor] - * - * @param string $filename The filename and path of the image to use for filling - */ - function Image_Graph_Fill_Image($filename) - { - parent::Image_Graph_Fill(); - $this->_filename = $filename; - } - - /** - * Return the fillstyle - * - * @param (something) $ID (Add description) - * @return int A GD fillstyle - * @access private - */ - function _getFillStyle($ID = false) - { - return $this->_filename; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Image.php,v 1.7 2005/08/24 20:36:03 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Fill.php + */ +require_once 'Image/Graph/Fill.php'; + +/** + * Fill using an image. + * + * @category Images + * @package Image_Graph + * @subpackage Fill + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Fill_Image extends Image_Graph_Fill +{ + + /** + * The file name + * @var stirng + * @access private + */ + var $_filename; + + /** + * The GD Image resource + * @var resource + * @access private + */ + var $_image; + + /** + * Resize the image to the bounding box of the area to fill + * @var bool + * @access private + */ + var $_resize = true; + + /** + * Image_Graph_ImageFill [Constructor] + * + * @param string $filename The filename and path of the image to use for filling + */ + function Image_Graph_Fill_Image($filename) + { + parent::Image_Graph_Fill(); + $this->_filename = $filename; + } + + /** + * Return the fillstyle + * + * @param (something) $ID (Add description) + * @return int A GD fillstyle + * @access private + */ + function _getFillStyle($ID = false) + { + return $this->_filename; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Font.php b/includes/pear/Image/Graph/Font.php index 141b5db5..cb1d4884 100644 --- a/includes/pear/Image/Graph/Font.php +++ b/includes/pear/Image/Graph/Font.php @@ -1,158 +1,158 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Font.php,v 1.8 2005/08/24 20:35:55 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Common.php - */ -require_once 'Image/Graph/Common.php'; - -/** - * A font. - * - * @category Images - * @package Image_Graph - * @subpackage Text - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - * @abstract - */ -class Image_Graph_Font extends Image_Graph_Common -{ - - /** - * The name of the font - * @var string - * @access private - */ - var $_name = false; - - /** - * The angle of the output - * @var int - * @access private - */ - var $_angle = false; - - /** - * The size of the font - * @var int - * @access private - */ - var $_size = 11; - - /** - * The color of the font - * @var Color - * @access private - */ - var $_color = 'black'; - - /** - * Image_Graph_Font [Constructor] - */ - function Image_Graph_Font($name = false, $size = false) - { - parent::Image_Graph_Common(); - if ($name !== false) { - $this->_name = $name; - } - if ($size !== false) { - $this->_size = $size; - } - } - - /** - * Set the color of the font - * - * @param mixed $color The color object of the Font - */ - function setColor($color) - { - $this->_color = $color; - } - - /** - * Set the angle slope of the output font. - * - * 0 = normal, 90 = bottom and up, 180 = upside down, 270 = top and down - * - * @param int $angle The angle in degrees to slope the text - */ - function setAngle($angle) - { - $this->_angle = $angle; - } - - /** - * Set the size of the font - * - * @param int $size The size in pixels of the font - */ - function setSize($size) - { - $this->_size = $size; - } - - /** - * Get the font 'array' - * - * @return array The font 'summary' to pass to the canvas - * @access private - */ - function _getFont($options = false) - { - if ($options === false) { - $options = array(); - } - - if ($this->_name !== false) { - $options['name'] = $this->_name; - } - - if (!isset($options['color'])) { - $options['color'] = $this->_color; - } - - if (!isset($options['size'])) { - $options['size'] = $this->_size; - } - - if ((!isset($options['angle'])) && ($this->_angle !== false)) { - $options['angle'] = $this->_angle; - } - return $options; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Font.php,v 1.8 2005/08/24 20:35:55 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Common.php + */ +require_once 'Image/Graph/Common.php'; + +/** + * A font. + * + * @category Images + * @package Image_Graph + * @subpackage Text + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + * @abstract + */ +class Image_Graph_Font extends Image_Graph_Common +{ + + /** + * The name of the font + * @var string + * @access private + */ + var $_name = false; + + /** + * The angle of the output + * @var int + * @access private + */ + var $_angle = false; + + /** + * The size of the font + * @var int + * @access private + */ + var $_size = 11; + + /** + * The color of the font + * @var Color + * @access private + */ + var $_color = 'black'; + + /** + * Image_Graph_Font [Constructor] + */ + function Image_Graph_Font($name = false, $size = false) + { + parent::Image_Graph_Common(); + if ($name !== false) { + $this->_name = $name; + } + if ($size !== false) { + $this->_size = $size; + } + } + + /** + * Set the color of the font + * + * @param mixed $color The color object of the Font + */ + function setColor($color) + { + $this->_color = $color; + } + + /** + * Set the angle slope of the output font. + * + * 0 = normal, 90 = bottom and up, 180 = upside down, 270 = top and down + * + * @param int $angle The angle in degrees to slope the text + */ + function setAngle($angle) + { + $this->_angle = $angle; + } + + /** + * Set the size of the font + * + * @param int $size The size in pixels of the font + */ + function setSize($size) + { + $this->_size = $size; + } + + /** + * Get the font 'array' + * + * @return array The font 'summary' to pass to the canvas + * @access private + */ + function _getFont($options = false) + { + if ($options === false) { + $options = array(); + } + + if ($this->_name !== false) { + $options['name'] = $this->_name; + } + + if (!isset($options['color'])) { + $options['color'] = $this->_color; + } + + if (!isset($options['size'])) { + $options['size'] = $this->_size; + } + + if ((!isset($options['angle'])) && ($this->_angle !== false)) { + $options['angle'] = $this->_angle; + } + return $options; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Grid.php b/includes/pear/Image/Graph/Grid.php index fc9cd055..196a3324 100644 --- a/includes/pear/Image/Graph/Grid.php +++ b/includes/pear/Image/Graph/Grid.php @@ -1,175 +1,175 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Grid.php,v 1.8 2005/02/21 20:49:47 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Element.php - */ -require_once 'Image/Graph/Element.php'; - -/** - * A grid displayed on the plotarea. - * - * A grid is associated with a primary and a secondary axis. The grid is - * displayed in context of the primary axis' label interval - meaning that a - * grid for an Y-axis displays a grid for every label on the y-axis (fx. a {@link - * Image_Graph_Grid_Lines}, which displays horizontal lines for every label on - * the y-axis from the x-axis minimum to the x-axis maximum). You should always - * add the grid as one of the first elements to the plotarea. This is due to the - * fact that elements are 'outputted' in the order they are added, i.e. if an - * grid is added *after* a chart, the grid will be displayed on top of the chart - * which is (probably) not desired. - * - * @category Images - * @package Image_Graph - * @subpackage Grid - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - * @abstract - */ -class Image_Graph_Grid extends Image_Graph_Plotarea_Element -{ - - /** - * The primary axis: the grid 'refers' to - * @var Axis - * @access private - */ - var $_primaryAxis = null; - - /** - * The secondary axis - * @var Axis - * @access private - */ - var $_secondaryAxis = null; - - /** - * Set the primary axis: the grid should 'refer' to - * - * @param Image_Graph_Axis $axis The axis - * @access private - */ - function _setPrimaryAxis(& $axis) - { - $this->_primaryAxis =& $axis; - } - - /** - * Set the secondary axis - * - * @param Image_Graph_Axis $axis The axis - * @access private - */ - function _setSecondaryAxis(& $axis) - { - $this->_secondaryAxis =& $axis; - } - - /** - * Get the points on the secondary axis that the grid should 'connect' - * - * @return array The secondary data values that should mark the grid 'end points' - * @access private - */ - function _getSecondaryAxisPoints() - { - if (is_a($this->_secondaryAxis, 'Image_Graph_Axis_Radar')) { - $secondaryValue = false; - $firstValue = $secondaryValue; - while (($secondaryValue = $this->_secondaryAxis->_getNextLabel($secondaryValue)) !== false) { - $secondaryAxisPoints[] = $secondaryValue; - } - $secondaryAxisPoints[] = $firstValue; - } else { - $secondaryAxisPoints = array ('#min#', '#max#'); - } - return $secondaryAxisPoints; - } - - /** - * Get the X pixel position represented by a value - * - * @param double $point the value to get the pixel-point for - * @return double The pixel position along the axis - * @access private - */ - function _pointX($point) - { - if (($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y) || - ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY)) - { - $point['AXIS_Y'] = $this->_primaryAxis->_type; - } else { - $point['AXIS_Y'] = $this->_secondaryAxis->_type; - } - return parent::_pointX($point); - } - - /** - * Get the Y pixel position represented by a value - * - * @param double $point the value to get the pixel-point for - * @return double The pixel position along the axis - * @access private - */ - function _pointY($point) - { - if (($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y) || - ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY)) - { - $point['AXIS_Y'] = $this->_primaryAxis->_type; - } else { - $point['AXIS_Y'] = $this->_secondaryAxis->_type; - } - return parent::_pointY($point); - } - - /** - * Causes the object to update all sub elements coordinates. - * - * @access private - */ - function _updateCoords() - { - $this->_setCoords( - $this->_parent->_plotLeft, - $this->_parent->_plotTop, - $this->_parent->_plotRight, - $this->_parent->_plotBottom - ); - parent::_updateCoords(); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Grid.php,v 1.8 2005/02/21 20:49:47 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Element.php + */ +require_once 'Image/Graph/Element.php'; + +/** + * A grid displayed on the plotarea. + * + * A grid is associated with a primary and a secondary axis. The grid is + * displayed in context of the primary axis' label interval - meaning that a + * grid for an Y-axis displays a grid for every label on the y-axis (fx. a {@link + * Image_Graph_Grid_Lines}, which displays horizontal lines for every label on + * the y-axis from the x-axis minimum to the x-axis maximum). You should always + * add the grid as one of the first elements to the plotarea. This is due to the + * fact that elements are 'outputted' in the order they are added, i.e. if an + * grid is added *after* a chart, the grid will be displayed on top of the chart + * which is (probably) not desired. + * + * @category Images + * @package Image_Graph + * @subpackage Grid + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + * @abstract + */ +class Image_Graph_Grid extends Image_Graph_Plotarea_Element +{ + + /** + * The primary axis: the grid 'refers' to + * @var Axis + * @access private + */ + var $_primaryAxis = null; + + /** + * The secondary axis + * @var Axis + * @access private + */ + var $_secondaryAxis = null; + + /** + * Set the primary axis: the grid should 'refer' to + * + * @param Image_Graph_Axis $axis The axis + * @access private + */ + function _setPrimaryAxis(& $axis) + { + $this->_primaryAxis =& $axis; + } + + /** + * Set the secondary axis + * + * @param Image_Graph_Axis $axis The axis + * @access private + */ + function _setSecondaryAxis(& $axis) + { + $this->_secondaryAxis =& $axis; + } + + /** + * Get the points on the secondary axis that the grid should 'connect' + * + * @return array The secondary data values that should mark the grid 'end points' + * @access private + */ + function _getSecondaryAxisPoints() + { + if (is_a($this->_secondaryAxis, 'Image_Graph_Axis_Radar')) { + $secondaryValue = false; + $firstValue = $secondaryValue; + while (($secondaryValue = $this->_secondaryAxis->_getNextLabel($secondaryValue)) !== false) { + $secondaryAxisPoints[] = $secondaryValue; + } + $secondaryAxisPoints[] = $firstValue; + } else { + $secondaryAxisPoints = array ('#min#', '#max#'); + } + return $secondaryAxisPoints; + } + + /** + * Get the X pixel position represented by a value + * + * @param double $point the value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointX($point) + { + if (($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y) || + ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY)) + { + $point['AXIS_Y'] = $this->_primaryAxis->_type; + } else { + $point['AXIS_Y'] = $this->_secondaryAxis->_type; + } + return parent::_pointX($point); + } + + /** + * Get the Y pixel position represented by a value + * + * @param double $point the value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointY($point) + { + if (($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y) || + ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y_SECONDARY)) + { + $point['AXIS_Y'] = $this->_primaryAxis->_type; + } else { + $point['AXIS_Y'] = $this->_secondaryAxis->_type; + } + return parent::_pointY($point); + } + + /** + * Causes the object to update all sub elements coordinates. + * + * @access private + */ + function _updateCoords() + { + $this->_setCoords( + $this->_parent->_plotLeft, + $this->_parent->_plotTop, + $this->_parent->_plotRight, + $this->_parent->_plotBottom + ); + parent::_updateCoords(); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Grid/Bars.php b/includes/pear/Image/Graph/Grid/Bars.php index dada02a9..35b548bb 100644 --- a/includes/pear/Image/Graph/Grid/Bars.php +++ b/includes/pear/Image/Graph/Grid/Bars.php @@ -1,117 +1,117 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Bars.php,v 1.10 2005/09/14 20:27:25 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Grid.php - */ -require_once 'Image/Graph/Grid.php'; - -/** - * Display alternating bars on the plotarea. - * - * {@link Image_Graph_Grid} - * - * @category Images - * @package Image_Graph - * @subpackage Grid - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Grid_Bars extends Image_Graph_Grid -{ - - /** - * Output the grid - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (parent::_done() === false) { - return false; - } - - if (!$this->_primaryAxis) { - return false; - } - - $this->_canvas->startGroup(get_class($this)); - - $i = 0; - $value = false; - - $previousValue = 0; - - $secondaryPoints = $this->_getSecondaryAxisPoints(); - - while (($value = $this->_primaryAxis->_getNextLabel($value)) !== false) { - if ($i == 1) { - reset($secondaryPoints); - list ($id, $previousSecondaryValue) = each($secondaryPoints); - while (list ($id, $secondaryValue) = each($secondaryPoints)) { - if ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_X) { - $p1 = array ('Y' => $secondaryValue, 'X' => $value); - $p2 = array ('Y' => $previousSecondaryValue, 'X' => $value); - $p3 = array ('Y' => $previousSecondaryValue, 'X' => $previousValue); - $p4 = array ('Y' => $secondaryValue, 'X' => $previousValue); - } else { - $p1 = array ('X' => $secondaryValue, 'Y' => $value); - $p2 = array ('X' => $previousSecondaryValue, 'Y' => $value); - $p3 = array ('X' => $previousSecondaryValue, 'Y' => $previousValue); - $p4 = array ('X' => $secondaryValue, 'Y' => $previousValue); - } - - $this->_canvas->addVertex(array('x' => $this->_pointX($p1), 'y' => $this->_pointY($p1))); - $this->_canvas->addVertex(array('x' => $this->_pointX($p2), 'y' => $this->_pointY($p2))); - $this->_canvas->addVertex(array('x' => $this->_pointX($p3), 'y' => $this->_pointY($p3))); - $this->_canvas->addVertex(array('x' => $this->_pointX($p4), 'y' => $this->_pointY($p4))); - - $this->_getFillStyle(); - $this->_canvas->polygon(array('connect' => true)); - - $previousSecondaryValue = $secondaryValue; - } - } - $i = 1 - $i; - $previousValue = $value; - } - - $this->_canvas->endGroup(); - - return true; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Bars.php,v 1.10 2005/09/14 20:27:25 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Grid.php + */ +require_once 'Image/Graph/Grid.php'; + +/** + * Display alternating bars on the plotarea. + * + * {@link Image_Graph_Grid} + * + * @category Images + * @package Image_Graph + * @subpackage Grid + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Grid_Bars extends Image_Graph_Grid +{ + + /** + * Output the grid + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + if (!$this->_primaryAxis) { + return false; + } + + $this->_canvas->startGroup(get_class($this)); + + $i = 0; + $value = false; + + $previousValue = 0; + + $secondaryPoints = $this->_getSecondaryAxisPoints(); + + while (($value = $this->_primaryAxis->_getNextLabel($value)) !== false) { + if ($i == 1) { + reset($secondaryPoints); + list ($id, $previousSecondaryValue) = each($secondaryPoints); + while (list ($id, $secondaryValue) = each($secondaryPoints)) { + if ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_X) { + $p1 = array ('Y' => $secondaryValue, 'X' => $value); + $p2 = array ('Y' => $previousSecondaryValue, 'X' => $value); + $p3 = array ('Y' => $previousSecondaryValue, 'X' => $previousValue); + $p4 = array ('Y' => $secondaryValue, 'X' => $previousValue); + } else { + $p1 = array ('X' => $secondaryValue, 'Y' => $value); + $p2 = array ('X' => $previousSecondaryValue, 'Y' => $value); + $p3 = array ('X' => $previousSecondaryValue, 'Y' => $previousValue); + $p4 = array ('X' => $secondaryValue, 'Y' => $previousValue); + } + + $this->_canvas->addVertex(array('x' => $this->_pointX($p1), 'y' => $this->_pointY($p1))); + $this->_canvas->addVertex(array('x' => $this->_pointX($p2), 'y' => $this->_pointY($p2))); + $this->_canvas->addVertex(array('x' => $this->_pointX($p3), 'y' => $this->_pointY($p3))); + $this->_canvas->addVertex(array('x' => $this->_pointX($p4), 'y' => $this->_pointY($p4))); + + $this->_getFillStyle(); + $this->_canvas->polygon(array('connect' => true)); + + $previousSecondaryValue = $secondaryValue; + } + } + $i = 1 - $i; + $previousValue = $value; + } + + $this->_canvas->endGroup(); + + return true; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Grid/Lines.php b/includes/pear/Image/Graph/Grid/Lines.php index 61b7611b..e4dc4e97 100644 --- a/includes/pear/Image/Graph/Grid/Lines.php +++ b/includes/pear/Image/Graph/Grid/Lines.php @@ -1,114 +1,114 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Lines.php,v 1.10 2005/08/24 20:36:04 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Grid.php - */ -require_once 'Image/Graph/Grid.php'; - -/** - * Display a line grid on the plotarea. - * - * {@link Image_Graph_Grid} - * - * @category Images - * @package Image_Graph - * @subpackage Grid - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Grid_Lines extends Image_Graph_Grid -{ - - /** - * GridLines [Constructor] - */ - function Image_Graph_Grid_Lines() - { - parent::Image_Graph_Grid(); - $this->_lineStyle = 'lightgrey'; - } - - /** - * Output the grid - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (parent::_done() === false) { - return false; - } - - if (!$this->_primaryAxis) { - return false; - } - - $this->_canvas->startGroup(get_class($this)); - - $value = false; - - $secondaryPoints = $this->_getSecondaryAxisPoints(); - - while (($value = $this->_primaryAxis->_getNextLabel($value)) !== false) { - reset($secondaryPoints); - list ($id, $previousSecondaryValue) = each($secondaryPoints); - while (list ($id, $secondaryValue) = each($secondaryPoints)) { - if ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y) { - $p1 = array ('X' => $secondaryValue, 'Y' => $value); - $p2 = array ('X' => $previousSecondaryValue, 'Y' => $value); - } else { - $p1 = array ('X' => $value, 'Y' => $secondaryValue); - $p2 = array ('X' => $value, 'Y' => $previousSecondaryValue); - } - - $x1 = $this->_pointX($p1); - $y1 = $this->_pointY($p1); - $x2 = $this->_pointX($p2); - $y2 = $this->_pointY($p2); - - $previousSecondaryValue = $secondaryValue; - - $this->_getLineStyle(); - $this->_canvas->line(array('x0' => $x1, 'y0' => $y1, 'x1' => $x2, 'y1' => $y2)); - } - } - - $this->_canvas->endGroup(); - - return true; - } - -} + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Lines.php,v 1.10 2005/08/24 20:36:04 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Grid.php + */ +require_once 'Image/Graph/Grid.php'; + +/** + * Display a line grid on the plotarea. + * + * {@link Image_Graph_Grid} + * + * @category Images + * @package Image_Graph + * @subpackage Grid + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Grid_Lines extends Image_Graph_Grid +{ + + /** + * GridLines [Constructor] + */ + function Image_Graph_Grid_Lines() + { + parent::Image_Graph_Grid(); + $this->_lineStyle = 'lightgrey'; + } + + /** + * Output the grid + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + if (!$this->_primaryAxis) { + return false; + } + + $this->_canvas->startGroup(get_class($this)); + + $value = false; + + $secondaryPoints = $this->_getSecondaryAxisPoints(); + + while (($value = $this->_primaryAxis->_getNextLabel($value)) !== false) { + reset($secondaryPoints); + list ($id, $previousSecondaryValue) = each($secondaryPoints); + while (list ($id, $secondaryValue) = each($secondaryPoints)) { + if ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y) { + $p1 = array ('X' => $secondaryValue, 'Y' => $value); + $p2 = array ('X' => $previousSecondaryValue, 'Y' => $value); + } else { + $p1 = array ('X' => $value, 'Y' => $secondaryValue); + $p2 = array ('X' => $value, 'Y' => $previousSecondaryValue); + } + + $x1 = $this->_pointX($p1); + $y1 = $this->_pointY($p1); + $x2 = $this->_pointX($p2); + $y2 = $this->_pointY($p2); + + $previousSecondaryValue = $secondaryValue; + + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x1, 'y0' => $y1, 'x1' => $x2, 'y1' => $y2)); + } + } + + $this->_canvas->endGroup(); + + return true; + } + +} ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Grid/Polar.php b/includes/pear/Image/Graph/Grid/Polar.php index 7491afe6..bc978ae6 100644 --- a/includes/pear/Image/Graph/Grid/Polar.php +++ b/includes/pear/Image/Graph/Grid/Polar.php @@ -1,111 +1,111 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Polar.php,v 1.10 2005/08/24 20:36:04 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - * @since File available since Release 0.3.0dev2 - */ - -/** - * Include file Image/Graph/Grid.php - */ -require_once 'Image/Graph/Grid.php'; - -/** - * Display a line grid on the plotarea. - * - * {@link Image_Graph_Grid} - * - * @category Images - * @package Image_Graph - * @subpackage Grid - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - * @since Class available since Release 0.3.0dev2 - */ -class Image_Graph_Grid_Polar extends Image_Graph_Grid -{ - - /** - * GridLines [Constructor] - */ - function Image_Graph_Grid_Polar() - { - parent::Image_Graph_Grid(); - $this->_lineStyle = 'lightgrey'; - } - - /** - * Output the grid - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (parent::_done() === false) { - return false; - } - - if (!$this->_primaryAxis) { - return false; - } - - $this->_canvas->startGroup(get_class($this)); - - $value = false; - - $p0 = array ('X' => '#min#', 'Y' => '#min#'); - if ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y) { - $p1 = array ('X' => '#min#', 'Y' => '#max#'); - $r0 = abs($this->_pointY($p1) - $this->_pointY($p0)); - } else { - $p1 = array ('X' => '#max#', 'Y' => '#min#'); - $r0 = abs($this->_pointX($p1) - $this->_pointX($p0)); - } - - $cx = $this->_pointX($p0); - $cy = $this->_pointY($p0); - - $span = $this->_primaryAxis->_axisSpan; - - while (($value = $this->_primaryAxis->_getNextLabel($value)) !== false) { - $r = $r0 * ($value - $this->_primaryAxis->_getMinimum()) / $span; - - $this->_getLineStyle(); - $this->_canvas->ellipse(array('x' => $cx, 'y' => $cy, 'rx' => $r, 'ry' => $r)); - } - - $this->_canvas->endGroup(); - - return true; - } - -} + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Polar.php,v 1.10 2005/08/24 20:36:04 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + * @since File available since Release 0.3.0dev2 + */ + +/** + * Include file Image/Graph/Grid.php + */ +require_once 'Image/Graph/Grid.php'; + +/** + * Display a line grid on the plotarea. + * + * {@link Image_Graph_Grid} + * + * @category Images + * @package Image_Graph + * @subpackage Grid + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + * @since Class available since Release 0.3.0dev2 + */ +class Image_Graph_Grid_Polar extends Image_Graph_Grid +{ + + /** + * GridLines [Constructor] + */ + function Image_Graph_Grid_Polar() + { + parent::Image_Graph_Grid(); + $this->_lineStyle = 'lightgrey'; + } + + /** + * Output the grid + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + if (!$this->_primaryAxis) { + return false; + } + + $this->_canvas->startGroup(get_class($this)); + + $value = false; + + $p0 = array ('X' => '#min#', 'Y' => '#min#'); + if ($this->_primaryAxis->_type == IMAGE_GRAPH_AXIS_Y) { + $p1 = array ('X' => '#min#', 'Y' => '#max#'); + $r0 = abs($this->_pointY($p1) - $this->_pointY($p0)); + } else { + $p1 = array ('X' => '#max#', 'Y' => '#min#'); + $r0 = abs($this->_pointX($p1) - $this->_pointX($p0)); + } + + $cx = $this->_pointX($p0); + $cy = $this->_pointY($p0); + + $span = $this->_primaryAxis->_axisSpan; + + while (($value = $this->_primaryAxis->_getNextLabel($value)) !== false) { + $r = $r0 * ($value - $this->_primaryAxis->_getMinimum()) / $span; + + $this->_getLineStyle(); + $this->_canvas->ellipse(array('x' => $cx, 'y' => $cy, 'rx' => $r, 'ry' => $r)); + } + + $this->_canvas->endGroup(); + + return true; + } + +} ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Images/Maps/README b/includes/pear/Image/Graph/Images/Maps/README index 1b984bbb..df5a7bfd 100644 --- a/includes/pear/Image/Graph/Images/Maps/README +++ b/includes/pear/Image/Graph/Images/Maps/README @@ -1,17 +1,17 @@ -In this folder the files for the Image_Graph_Plot_Map are located. They should be the -following format: - -[map name].png -[map name].txt - -The [map name].png (fx. europe.png) is the actual image presenting the map. The -[map name].txt file is the location -> (x,y) conversion table. In this file the -named locations is written on every line with the x and y coordinates after the -name (with a TAB), i.e.: - -Denmark 10 30 -England 4 30 - -Where Denmark will be 'located' on (10, 30) on the map, and England at (4, 30). - +In this folder the files for the Image_Graph_Plot_Map are located. They should be the +following format: + +[map name].png +[map name].txt + +The [map name].png (fx. europe.png) is the actual image presenting the map. The +[map name].txt file is the location -> (x,y) conversion table. In this file the +named locations is written on every line with the x and y coordinates after the +name (with a TAB), i.e.: + +Denmark 10 30 +England 4 30 + +Where Denmark will be 'located' on (10, 30) on the map, and England at (4, 30). + No maps are released by default due to we want to avoid possible copyright issues. \ No newline at end of file diff --git a/includes/pear/Image/Graph/Layout.php b/includes/pear/Image/Graph/Layout.php index 1496bf44..c6543deb 100644 --- a/includes/pear/Image/Graph/Layout.php +++ b/includes/pear/Image/Graph/Layout.php @@ -1,219 +1,219 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Layout.php,v 1.11 2005/09/14 20:27:25 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Plotarea/Element.php - */ -require_once 'Image/Graph/Plotarea/Element.php'; - -/** - * Defines an area of the graph that can be layout'ed. - * - * Any class that extends this abstract class can be used within a layout on the canvas. - * - * @category Images - * @package Image_Graph - * @subpackage Layout - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - * @abstract - */ -class Image_Graph_Layout extends Image_Graph_Plotarea_Element -{ - - /** - * Has the coordinates already been updated? - * @var bool - * @access private - */ - var $_updated = false; - - /** - * Alignment of the area for each vertice (left, top, right, bottom) - * @var array - * @access private - */ - var $_alignSize = array ('left' => 0, 'top' => 0, 'right' => 0, 'bottom' => 0); - - /** - * Image_Graph_Layout [Constructor] - */ - function Image_Graph_Layout() - { - parent::Image_Graph_Element(); - $this->_padding = 2; - } - - /** - * Resets the elements - * - * @access private - */ - function _reset() - { - parent::_reset(); - $this->_updated = false; - } - - /** - * Calculate the edge offset for a specific edge - * @param array $alignSize The alignment of the edge - * @param int $offset The offset/posision of the at 0% edge - * @param int $total The total size (width or height) of the element - * @param int $multiplier +/- 1 if the edge should pushed either toward more - * negative or positive values - * @since 0.3.0dev2 - * @access private - */ - function _calcEdgeOffset($alignSize, $offset, $total, $multiplier) - { - if ($alignSize['unit'] == 'percentage') { - return $offset + $multiplier * ($total * $alignSize['value'] / 100); - } elseif ($alignSize['unit'] == 'pixels') { - if (($alignSize['value'] == 'auto_part1') || ($alignSize['value'] == 'auto_part2')) { - $alignSize['value'] = $multiplier * $this->_parent->_getAbsolute($alignSize['value']); - } - if ($alignSize['value'] < 0) { - return $offset + $multiplier * ($total + $alignSize['value']); - } else { - return $offset + $multiplier * $alignSize['value']; - } - } - return $offset; - } - - /** - * Calculate the edges - * - * @access private - */ - function _calcEdges() - { - if ((is_array($this->_alignSize)) && (!$this->_updated)) { - $left = $this->_calcEdgeOffset( - $this->_alignSize['left'], - $this->_parent->_fillLeft(), - $this->_parent->_fillWidth(), - +1 - ); - $top = $this->_calcEdgeOffset( - $this->_alignSize['top'], - $this->_parent->_fillTop(), - $this->_parent->_fillHeight(), - +1 - ); - $right = $this->_calcEdgeOffset( - $this->_alignSize['right'], - $this->_parent->_fillRight(), - $this->_parent->_fillWidth(), - -1 - ); - $bottom = $this->_calcEdgeOffset( - $this->_alignSize['bottom'], - $this->_parent->_fillBottom(), - $this->_parent->_fillHeight(), - -1 - ); - - $this->_setCoords( - $left + $this->_padding, - $top + $this->_padding, - $right - $this->_padding, - $bottom - $this->_padding - ); - } - } - - /** - * Update coordinates - * - * @access private - */ - function _updateCoords() - { - $this->_calcEdges(); - parent::_updateCoords(); - } - - /** - * Pushes an edge of area a specific distance 'into' the canvas - * - * @param int $edge The edge of the canvas to align relative to - * @param int $size The number of pixels or the percentage of the canvas total size to occupy relative to the selected alignment edge - * @access private - */ - function _push($edge, $size = '100%') - { - $result = array(); - if (ereg("([0-9]*)\%", $size, $result)) { - $this->_alignSize[$edge] = array( - 'value' => min(100, max(0, $result[1])), - 'unit' => 'percentage' - ); - } else { - $this->_alignSize[$edge] = array( - 'value' => $size, - 'unit' => 'pixels' - ); - } - } - - /** - * Sets the coordinates of the element - * - * @param int $left The leftmost pixel of the element on the canvas - * @param int $top The topmost pixel of the element on the canvas - * @param int $right The rightmost pixel of the element on the canvas - * @param int $bottom The bottommost pixel of the element on the canvas - * @access private - */ - function _setCoords($left, $top, $right, $bottom) - { - parent::_setCoords($left, $top, $right, $bottom); - $this->_updated = true; - } - - /** - * Returns the calculated "auto" size - * - * @return int The calculated auto size - * @access private - */ - function _getAutoSize() - { - return false; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Layout.php,v 1.12 2006/02/28 22:48:07 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plotarea/Element.php + */ +require_once 'Image/Graph/Plotarea/Element.php'; + +/** + * Defines an area of the graph that can be layout'ed. + * + * Any class that extends this abstract class can be used within a layout on the canvas. + * + * @category Images + * @package Image_Graph + * @subpackage Layout + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + * @abstract + */ +class Image_Graph_Layout extends Image_Graph_Plotarea_Element +{ + + /** + * Has the coordinates already been updated? + * @var bool + * @access private + */ + var $_updated = false; + + /** + * Alignment of the area for each vertice (left, top, right, bottom) + * @var array + * @access private + */ + var $_alignSize = array ('left' => 0, 'top' => 0, 'right' => 0, 'bottom' => 0); + + /** + * Image_Graph_Layout [Constructor] + */ + function Image_Graph_Layout() + { + parent::Image_Graph_Element(); + $this->_padding = array('left' => 2, 'top' => 2, 'right' => 2, 'bottom' => 2); + } + + /** + * Resets the elements + * + * @access private + */ + function _reset() + { + parent::_reset(); + $this->_updated = false; + } + + /** + * Calculate the edge offset for a specific edge + * @param array $alignSize The alignment of the edge + * @param int $offset The offset/posision of the at 0% edge + * @param int $total The total size (width or height) of the element + * @param int $multiplier +/- 1 if the edge should pushed either toward more + * negative or positive values + * @since 0.3.0dev2 + * @access private + */ + function _calcEdgeOffset($alignSize, $offset, $total, $multiplier) + { + if ($alignSize['unit'] == 'percentage') { + return $offset + $multiplier * ($total * $alignSize['value'] / 100); + } elseif ($alignSize['unit'] == 'pixels') { + if (($alignSize['value'] == 'auto_part1') || ($alignSize['value'] == 'auto_part2')) { + $alignSize['value'] = $multiplier * $this->_parent->_getAbsolute($alignSize['value']); + } + if ($alignSize['value'] < 0) { + return $offset + $multiplier * ($total + $alignSize['value']); + } else { + return $offset + $multiplier * $alignSize['value']; + } + } + return $offset; + } + + /** + * Calculate the edges + * + * @access private + */ + function _calcEdges() + { + if ((is_array($this->_alignSize)) && (!$this->_updated)) { + $left = $this->_calcEdgeOffset( + $this->_alignSize['left'], + $this->_parent->_fillLeft(), + $this->_parent->_fillWidth(), + +1 + ); + $top = $this->_calcEdgeOffset( + $this->_alignSize['top'], + $this->_parent->_fillTop(), + $this->_parent->_fillHeight(), + +1 + ); + $right = $this->_calcEdgeOffset( + $this->_alignSize['right'], + $this->_parent->_fillRight(), + $this->_parent->_fillWidth(), + -1 + ); + $bottom = $this->_calcEdgeOffset( + $this->_alignSize['bottom'], + $this->_parent->_fillBottom(), + $this->_parent->_fillHeight(), + -1 + ); + + $this->_setCoords( + $left + $this->_padding['left'], + $top + $this->_padding['top'], + $right - $this->_padding['right'], + $bottom - $this->_padding['bottom'] + ); + } + } + + /** + * Update coordinates + * + * @access private + */ + function _updateCoords() + { + $this->_calcEdges(); + parent::_updateCoords(); + } + + /** + * Pushes an edge of area a specific distance 'into' the canvas + * + * @param int $edge The edge of the canvas to align relative to + * @param int $size The number of pixels or the percentage of the canvas total size to occupy relative to the selected alignment edge + * @access private + */ + function _push($edge, $size = '100%') + { + $result = array(); + if (ereg("([0-9]*)\%", $size, $result)) { + $this->_alignSize[$edge] = array( + 'value' => min(100, max(0, $result[1])), + 'unit' => 'percentage' + ); + } else { + $this->_alignSize[$edge] = array( + 'value' => $size, + 'unit' => 'pixels' + ); + } + } + + /** + * Sets the coordinates of the element + * + * @param int $left The leftmost pixel of the element on the canvas + * @param int $top The topmost pixel of the element on the canvas + * @param int $right The rightmost pixel of the element on the canvas + * @param int $bottom The bottommost pixel of the element on the canvas + * @access private + */ + function _setCoords($left, $top, $right, $bottom) + { + parent::_setCoords($left, $top, $right, $bottom); + $this->_updated = true; + } + + /** + * Returns the calculated "auto" size + * + * @return int The calculated auto size + * @access private + */ + function _getAutoSize() + { + return false; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Layout/Horizontal.php b/includes/pear/Image/Graph/Layout/Horizontal.php index 21773dbd..44d42db1 100644 --- a/includes/pear/Image/Graph/Layout/Horizontal.php +++ b/includes/pear/Image/Graph/Layout/Horizontal.php @@ -1,186 +1,186 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Horizontal.php,v 1.10 2005/08/24 20:35:58 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Layout.php - */ -require_once 'Image/Graph/Layout.php'; - -/** - * Layout for displaying two elements side by side. - * - * This splits the area contained by this element in two, side by side by - * a specified percentage (relative to the left side). A layout can be nested. - * Fx. a HorizontalLayout can layout two {@link Image_Graph_Layout_Vertical}s to - * make a 2 by 2 matrix of 'element-areas'. - * - * @category Images - * @package Image_Graph - * @subpackage Layout - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Layout_Horizontal extends Image_Graph_Layout -{ - - /** - * Part1 of the layout - * @var GraPHPElemnt - * @access private - */ - var $_part1 = false; - - /** - * Part2 of the layout - * @var GraPHPElemnt - * @access private - */ - var $_part2 = false; - - /** - * The percentage of the graph where the split occurs - * @var int - * @access private - */ - var $_percentage; - - /** - * An absolute position where the split occurs - * @var int - * @access private - */ - var $_absolute; - - /** - * HorizontalLayout [Constructor] - * - * @param Image_Graph_Element $part1 The 1st part of the layout - * @param Image_Graph_Element $part2 The 2nd part of the layout - * @param int $percentage The percentage of the layout to split at - */ - function Image_Graph_Layout_Horizontal(& $part1, & $part2, $percentage = 50) - { - parent::Image_Graph_Layout(); - if (!is_a($part1, 'Image_Graph_Layout')) { - $this->_error( - 'Cannot create layout on non-layouable parts: ' . get_class($part1), - array('part1' => &$part1, 'part2' => &$part2) - ); - } elseif (!is_a($part2, 'Image_Graph_Layout')) { - $this->_error( - 'Cannot create layout on non-layouable parts: ' . get_class($part2), - array('part1' => &$part1, 'part2' => &$part2) - ); - } else { - $this->_part1 =& $part1; - $this->_part2 =& $part2; - $this->add($this->_part1); - $this->add($this->_part2); - }; - if ($percentage === 'auto') { - $this->_percentage = false; - $this->_absolute = 'runtime'; - } else { - $this->_absolute = false; - $this->_percentage = max(0, min(100, $percentage)); - } - $this->_split(); - $this->_padding = 0; - } - - /** - * Gets the absolute size of one of the parts. - * - * @param string $part The name of the part - auto_part(1|2) - * @return int The number of pixels the edge should be pushed - * @since 0.3.0dev2 - * @access private - */ - function _getAbsolute(&$part) - { - $part1Size = $this->_part1->_getAutoSize(); - $part2Size = $this->_part2->_getAutoSize(); - $this->_percentage = false; - if (($part1Size !== false) and ($part2Size !== false)) { - $width = $this->_fillWidth() * $part1Size / ($part1Size + $part2Size); - } elseif ($part1Size !== false) { - $width = $part1Size; - } elseif ($part2Size !== false) { - $width = -$part2Size; - } else { - $width = $this->_fillWidth() / 2; - } - if ($part == 'auto_part2') { - $width = -$width; - } - - return $width; - } - - /** - * Splits the layout between the parts, by the specified percentage - * - * @access private - */ - function _split() - { - if (($this->_part1) && ($this->_part2)) { - if ($this->_percentage !== false) { - $split1 = 100 - $this->_percentage; - $split2 = $this->_percentage; - $this->_part1->_push('right', "$split1%"); - $this->_part2->_push('left', "$split2%"); - } else { - $this->_part1->_push('right', 'auto_part1'); - $this->_part2->_push('left', 'auto_part2'); - } - } - } - - /** - * Output the layout to the canvas - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (($this->_part1) && ($this->_part2)) { - return (($this->_part1->_done()) && ($this->_part2->_done())); - } - return true; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Horizontal.php,v 1.11 2006/02/28 22:48:07 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Layout.php + */ +require_once 'Image/Graph/Layout.php'; + +/** + * Layout for displaying two elements side by side. + * + * This splits the area contained by this element in two, side by side by + * a specified percentage (relative to the left side). A layout can be nested. + * Fx. a HorizontalLayout can layout two {@link Image_Graph_Layout_Vertical}s to + * make a 2 by 2 matrix of 'element-areas'. + * + * @category Images + * @package Image_Graph + * @subpackage Layout + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Layout_Horizontal extends Image_Graph_Layout +{ + + /** + * Part1 of the layout + * @var GraPHPElemnt + * @access private + */ + var $_part1 = false; + + /** + * Part2 of the layout + * @var GraPHPElemnt + * @access private + */ + var $_part2 = false; + + /** + * The percentage of the graph where the split occurs + * @var int + * @access private + */ + var $_percentage; + + /** + * An absolute position where the split occurs + * @var int + * @access private + */ + var $_absolute; + + /** + * HorizontalLayout [Constructor] + * + * @param Image_Graph_Element $part1 The 1st part of the layout + * @param Image_Graph_Element $part2 The 2nd part of the layout + * @param int $percentage The percentage of the layout to split at + */ + function Image_Graph_Layout_Horizontal(& $part1, & $part2, $percentage = 50) + { + parent::Image_Graph_Layout(); + if (!is_a($part1, 'Image_Graph_Layout')) { + $this->_error( + 'Cannot create layout on non-layouable parts: ' . get_class($part1), + array('part1' => &$part1, 'part2' => &$part2) + ); + } elseif (!is_a($part2, 'Image_Graph_Layout')) { + $this->_error( + 'Cannot create layout on non-layouable parts: ' . get_class($part2), + array('part1' => &$part1, 'part2' => &$part2) + ); + } else { + $this->_part1 =& $part1; + $this->_part2 =& $part2; + $this->add($this->_part1); + $this->add($this->_part2); + }; + if ($percentage === 'auto') { + $this->_percentage = false; + $this->_absolute = 'runtime'; + } else { + $this->_absolute = false; + $this->_percentage = max(0, min(100, $percentage)); + } + $this->_split(); + $this->_padding = array('left' => 0, 'top' => 0, 'right' => 0, 'bottom' => 0); + } + + /** + * Gets the absolute size of one of the parts. + * + * @param string $part The name of the part - auto_part(1|2) + * @return int The number of pixels the edge should be pushed + * @since 0.3.0dev2 + * @access private + */ + function _getAbsolute(&$part) + { + $part1Size = $this->_part1->_getAutoSize(); + $part2Size = $this->_part2->_getAutoSize(); + $this->_percentage = false; + if (($part1Size !== false) and ($part2Size !== false)) { + $width = $this->_fillWidth() * $part1Size / ($part1Size + $part2Size); + } elseif ($part1Size !== false) { + $width = $part1Size; + } elseif ($part2Size !== false) { + $width = -$part2Size; + } else { + $width = $this->_fillWidth() / 2; + } + if ($part == 'auto_part2') { + $width = -$width; + } + + return $width; + } + + /** + * Splits the layout between the parts, by the specified percentage + * + * @access private + */ + function _split() + { + if (($this->_part1) && ($this->_part2)) { + if ($this->_percentage !== false) { + $split1 = 100 - $this->_percentage; + $split2 = $this->_percentage; + $this->_part1->_push('right', "$split1%"); + $this->_part2->_push('left', "$split2%"); + } else { + $this->_part1->_push('right', 'auto_part1'); + $this->_part2->_push('left', 'auto_part2'); + } + } + } + + /** + * Output the layout to the canvas + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (($this->_part1) && ($this->_part2)) { + return (($this->_part1->_done()) && ($this->_part2->_done())); + } + return true; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Layout/Matrix.php b/includes/pear/Image/Graph/Layout/Matrix.php index 5ad98455..376503ac 100644 --- a/includes/pear/Image/Graph/Layout/Matrix.php +++ b/includes/pear/Image/Graph/Layout/Matrix.php @@ -1,201 +1,201 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Matrix.php,v 1.8 2005/08/24 20:35:58 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Layout.php - */ -require_once 'Image/Graph/Layout.php'; - -/** - * Layout for displaying elements in a matix. - * - * @category Images - * @package Image_Graph - * @subpackage Layout - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Layout_Matrix extends Image_Graph_Layout -{ - - /** - * Layout matrix - * @var array - * @access private - */ - var $_matrix = false; - - /** - * The number of rows - * @var int - * @access private - */ - var $_rows = false; - - /** - * The number of columns - * @var int - * @access private - */ - var $_cols = false; - - /** - * Image_Graph_Layout_Matrix [Constructor] - * - * @param int $rows The number of rows - * @param int $cols The number of cols - * @param bool $autoCreate Specifies whether the matrix should automatically - * be filled with newly created Image_Graph_Plotares objects, or they will - * be added manually - */ - function Image_Graph_Layout_Matrix($rows, $cols, $autoCreate = true) - { - parent::Image_Graph_Layout(); - - $this->_rows = $rows; - $this->_cols = $cols; - if (($this->_rows > 0) && ($this->_cols > 0)) { - $this->_matrix = array(array()); - for ($i = 0; $i < $this->_rows; $i++) { - for ($j = 0; $j < $this->_cols; $j++) { - if ($autoCreate) { - $this->_matrix[$i][$j] =& $this->addNew('plotarea'); - $this->_pushEdges($i, $j); - } else { - $this->_matrix[$i][$j] = false; - } - } - } - } - } - - /** - * Pushes the edges on the specified position in the matrix - * - * @param int $row The row - * @param int $col The column - * @access private - */ - function _pushEdges($row, $col) - { - if ((isset($this->_matrix[$row])) && (isset($this->_matrix[$row][$col]))) { - $height = 100/$this->_rows; - $width = 100/$this->_cols; - if ($col > 0) { - $this->_matrix[$row][$col]->_push('left', round($col*$width) . '%'); - } - if ($col+1 < $this->_cols) { - $this->_matrix[$row][$col]->_push('right', round(100-($col+1)*$width) . '%'); - } - if ($row > 0) { - $this->_matrix[$row][$col]->_push('top', round($row*$height) . '%'); - } - if ($row+1 < $this->_rows) { - $this->_matrix[$row][$col]->_push('bottom', round(100-($row+1)*$height) . '%'); - } - } - } - - /** - * Get the area on the specified position in the matrix - * - * @param int $row The row - * @param int $col The column - * @return Image_Graph_Layout The element of position ($row, $col) in the - * matrix - */ - function &getEntry($row, $col) - { - if ((isset($this->_matrix[$row])) && (isset($this->_matrix[$row][$col]))) { - return $this->_matrix[$row][$col]; - } else { - $result = null; - return $result; - } - } - - /** - * Get the area on the specified position in the matrix - * - * @param int $row The row - * @param int $col The column - * @param Image_Graph_Layout $element The element to set in the position - * ($row, $col) in the matrix - */ - function setEntry($row, $col, &$element) - { - $this->_matrix[$row][$col] =& $element; - $this->_pushEdges($row, $col); - } - - /** - * Update coordinates - * - * @access private - */ - function _updateCoords() - { - for ($i = 0; $i < $this->_rows; $i++) { - for ($j = 0; $j < $this->_cols; $j++) { - $element =& $this->getEntry($i, $j); - $this->add($element); - } - } - parent::_updateCoords(); - } - - /** - * Output the layout to the canvas - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - $result = true; - for ($i = 0; $i < $this->_rows; $i++) { - for ($j = 0; $j < $this->_cols; $j++) { - $element =& $this->getEntry($i, $j); - if ($element) { - if (!$element->_done()) { - $result = false; - } - } - } - } - return $result; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Matrix.php,v 1.8 2005/08/24 20:35:58 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Layout.php + */ +require_once 'Image/Graph/Layout.php'; + +/** + * Layout for displaying elements in a matix. + * + * @category Images + * @package Image_Graph + * @subpackage Layout + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Layout_Matrix extends Image_Graph_Layout +{ + + /** + * Layout matrix + * @var array + * @access private + */ + var $_matrix = false; + + /** + * The number of rows + * @var int + * @access private + */ + var $_rows = false; + + /** + * The number of columns + * @var int + * @access private + */ + var $_cols = false; + + /** + * Image_Graph_Layout_Matrix [Constructor] + * + * @param int $rows The number of rows + * @param int $cols The number of cols + * @param bool $autoCreate Specifies whether the matrix should automatically + * be filled with newly created Image_Graph_Plotares objects, or they will + * be added manually + */ + function Image_Graph_Layout_Matrix($rows, $cols, $autoCreate = true) + { + parent::Image_Graph_Layout(); + + $this->_rows = $rows; + $this->_cols = $cols; + if (($this->_rows > 0) && ($this->_cols > 0)) { + $this->_matrix = array(array()); + for ($i = 0; $i < $this->_rows; $i++) { + for ($j = 0; $j < $this->_cols; $j++) { + if ($autoCreate) { + $this->_matrix[$i][$j] =& $this->addNew('plotarea'); + $this->_pushEdges($i, $j); + } else { + $this->_matrix[$i][$j] = false; + } + } + } + } + } + + /** + * Pushes the edges on the specified position in the matrix + * + * @param int $row The row + * @param int $col The column + * @access private + */ + function _pushEdges($row, $col) + { + if ((isset($this->_matrix[$row])) && (isset($this->_matrix[$row][$col]))) { + $height = 100/$this->_rows; + $width = 100/$this->_cols; + if ($col > 0) { + $this->_matrix[$row][$col]->_push('left', round($col*$width) . '%'); + } + if ($col+1 < $this->_cols) { + $this->_matrix[$row][$col]->_push('right', round(100-($col+1)*$width) . '%'); + } + if ($row > 0) { + $this->_matrix[$row][$col]->_push('top', round($row*$height) . '%'); + } + if ($row+1 < $this->_rows) { + $this->_matrix[$row][$col]->_push('bottom', round(100-($row+1)*$height) . '%'); + } + } + } + + /** + * Get the area on the specified position in the matrix + * + * @param int $row The row + * @param int $col The column + * @return Image_Graph_Layout The element of position ($row, $col) in the + * matrix + */ + function &getEntry($row, $col) + { + if ((isset($this->_matrix[$row])) && (isset($this->_matrix[$row][$col]))) { + return $this->_matrix[$row][$col]; + } else { + $result = null; + return $result; + } + } + + /** + * Get the area on the specified position in the matrix + * + * @param int $row The row + * @param int $col The column + * @param Image_Graph_Layout $element The element to set in the position + * ($row, $col) in the matrix + */ + function setEntry($row, $col, &$element) + { + $this->_matrix[$row][$col] =& $element; + $this->_pushEdges($row, $col); + } + + /** + * Update coordinates + * + * @access private + */ + function _updateCoords() + { + for ($i = 0; $i < $this->_rows; $i++) { + for ($j = 0; $j < $this->_cols; $j++) { + $element =& $this->getEntry($i, $j); + $this->add($element); + } + } + parent::_updateCoords(); + } + + /** + * Output the layout to the canvas + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + $result = true; + for ($i = 0; $i < $this->_rows; $i++) { + for ($j = 0; $j < $this->_cols; $j++) { + $element =& $this->getEntry($i, $j); + if ($element) { + if (!$element->_done()) { + $result = false; + } + } + } + } + return $result; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Layout/Vertical.php b/includes/pear/Image/Graph/Layout/Vertical.php index e61019ca..4315e905 100644 --- a/includes/pear/Image/Graph/Layout/Vertical.php +++ b/includes/pear/Image/Graph/Layout/Vertical.php @@ -1,108 +1,108 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Vertical.php,v 1.6 2005/02/21 20:49:55 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Layout/Horizontal.php - */ -require_once 'Image/Graph/Layout/Horizontal.php'; - -/** - * Layout for displaying two elements on top of each other. - * - * This splits the area contained by this element in two on top of each other - * by a specified percentage (relative to the top). A layout can be nested. - * Fx. a {@link Image_Graph_Layout_Horizontal} can layout two VerticalLayout's to - * make a 2 by 2 matrix of 'element-areas'. - * - * @category Images - * @package Image_Graph - * @subpackage Layout - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Layout_Vertical extends Image_Graph_Layout_Horizontal -{ - - /** - * Gets the absolute size of one of the parts. - * - * @param string $part The name of the part - auto_part(1|2) - * @return int The number of pixels the edge should be pushed - * @since 0.3.0dev2 - * @access private - */ - function _getAbsolute(&$part) - { - $part1Size = $this->_part1->_getAutoSize(); - $part2Size = $this->_part2->_getAutoSize(); - $this->_percentage = false; - if (($part1Size !== false) and ($part2Size !== false)) { - $height = $this->_fillHeight() * $part1Size / ($part1Size + $part2Size); - } elseif ($part1Size !== false) { - $height = $part1Size; - } elseif ($part2Size !== false) { - $height = -$part2Size; - } else { - $height = $this->_fillHeight() / 2; - } - - if ($part == 'auto_part2') { -// $height = $this->_fillHeight() - $height; - } - - return $height; - } - - /** - * Splits the layout between the parts, by the specified percentage - * - * @access private - */ - function _split() - { - if (($this->_part1) && ($this->_part2)) { - if ($this->_percentage !== false) { - $split1 = 100 - $this->_percentage; - $split2 = $this->_percentage; - $this->_part1->_push('bottom', "$split1%"); - $this->_part2->_push('top', "$split2%"); - } else { - $this->_part1->_push('bottom', 'auto_part1'); - $this->_part2->_push('top', 'auto_part2'); - } - } - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Vertical.php,v 1.6 2005/02/21 20:49:55 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Layout/Horizontal.php + */ +require_once 'Image/Graph/Layout/Horizontal.php'; + +/** + * Layout for displaying two elements on top of each other. + * + * This splits the area contained by this element in two on top of each other + * by a specified percentage (relative to the top). A layout can be nested. + * Fx. a {@link Image_Graph_Layout_Horizontal} can layout two VerticalLayout's to + * make a 2 by 2 matrix of 'element-areas'. + * + * @category Images + * @package Image_Graph + * @subpackage Layout + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Layout_Vertical extends Image_Graph_Layout_Horizontal +{ + + /** + * Gets the absolute size of one of the parts. + * + * @param string $part The name of the part - auto_part(1|2) + * @return int The number of pixels the edge should be pushed + * @since 0.3.0dev2 + * @access private + */ + function _getAbsolute(&$part) + { + $part1Size = $this->_part1->_getAutoSize(); + $part2Size = $this->_part2->_getAutoSize(); + $this->_percentage = false; + if (($part1Size !== false) and ($part2Size !== false)) { + $height = $this->_fillHeight() * $part1Size / ($part1Size + $part2Size); + } elseif ($part1Size !== false) { + $height = $part1Size; + } elseif ($part2Size !== false) { + $height = -$part2Size; + } else { + $height = $this->_fillHeight() / 2; + } + + if ($part == 'auto_part2') { +// $height = $this->_fillHeight() - $height; + } + + return $height; + } + + /** + * Splits the layout between the parts, by the specified percentage + * + * @access private + */ + function _split() + { + if (($this->_part1) && ($this->_part2)) { + if ($this->_percentage !== false) { + $split1 = 100 - $this->_percentage; + $split2 = $this->_percentage; + $this->_part1->_push('bottom', "$split1%"); + $this->_part2->_push('top', "$split2%"); + } else { + $this->_part1->_push('bottom', 'auto_part1'); + $this->_part2->_push('top', 'auto_part2'); + } + } + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Legend.php b/includes/pear/Image/Graph/Legend.php index 077cd1c5..d2023692 100644 --- a/includes/pear/Image/Graph/Legend.php +++ b/includes/pear/Image/Graph/Legend.php @@ -1,385 +1,385 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Legend.php,v 1.15 2005/09/30 18:59:18 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Layout.php - */ -require_once 'Image/Graph/Layout.php'; - -/** - * Displays a legend for a plotarea. - * - * A legend can be displayed in two ways: - * - * 1 As an overlayed box within the plotarea - * - * 2 Layout'ed on the canvas smewhere next to the plotarea. - * - * @category Images - * @package Image_Graph - * @subpackage Legend - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Legend extends Image_Graph_Layout -{ - - /** - * Alignment of the text - * @var int - * @access private - */ - var $_alignment = false; - - /** - * The plotarea(s) to show the legend for - * @var array - * @access private - */ - var $_plotareas = array(); - - /** - * Should markers be shown or not on this legend - * @var bool - * @access private - */ - var $_showMarker = false; - - /** - * Image_Graph_Legend [Constructor] - */ - function Image_Graph_Legend() - { - parent::Image_Graph_Layout(); - $this->_padding = 5; - } - - /** - * The number of actual plots in the plot area - * - * @return int The number of plotes - * @access private - */ - function _plotCount() - { - $count = 0; - $keys = array_keys($this->_plotareas); - foreach($keys as $key) { - $plotarea =& $this->_plotareas[$key]; - if (is_a($plotarea, 'Image_Graph_Plotarea')) { - $keys2 = array_keys($plotarea->_elements); - foreach ($keys2 as $key) { - $element =& $plotarea->_elements[$key]; - if (is_a($element, 'Image_Graph_Plot')) { - $count ++; - } - } - unset($keys2); - } - } - unset($keys); - return $count; - } - - /** - * Get a default parameter array for legendSamples - * @param bool $simulate Whether the array should be used for simulation or - * not - * @return array Default parameter array - * @access private - */ - function _parameterArray($simulate = false) - { - $param['left'] = $this->_left + $this->_padding; - $param['top'] = $this->_top + $this->_padding; - $param['right'] = $this->_right - $this->_padding; - $param['bottom'] = $this->_bottom - $this->_padding; - $param['align'] = $this->_alignment; - $param['x'] = $this->_left + $this->_padding; - $param['y'] = $this->_top + $this->_padding; - $param['width'] = 16; - $param['height'] = 16; - $param['show_marker'] = $this->_showMarker; - $param['maxwidth'] = 0; - $param['font'] = $this->_getFont(); - if ($simulate) { - $param['simulate'] = true; - } - - return $param; - } - - /** - * The height of the element on the canvas - * - * @return int Number of pixels representing the height of the element - * @access private - */ - function _height() - { - $parent = (is_object($this->_parent) ? get_class($this->_parent) : $this->_parent); - - if (strtolower($parent) == 'image_graph_plotarea') { - $param = $this->_parameterArray(true); - $param['align'] = IMAGE_GRAPH_ALIGN_VERTICAL; - $param0 = $param; - $keys = array_keys($this->_plotareas); - foreach($keys as $key) { - $plotarea =& $this->_plotareas[$key]; - $keys2 = array_keys($plotarea->_elements); - foreach($keys2 as $key) { - $element =& $plotarea->_elements[$key]; - if (is_a($element, 'Image_Graph_Plot')) { - $element->_legendSample($param); - } - } - unset($keys2); - } - unset($keys); - return abs($param['y'] - $param0['y']) + 2*$this->_padding; - } else { - return parent::height(); - } - } - - /** - * The width of the element on the canvas - * - * @return int Number of pixels representing the width of the element - * @access private - */ - function _width() - { - $parent = (is_object($this->_parent) ? get_class($this->_parent) : $this->_parent); - - if (strtolower($parent) == 'image_graph_plotarea') { - $param = $this->_parameterArray(true); - $param['align'] = IMAGE_GRAPH_ALIGN_VERTICAL; - $keys = array_keys($this->_plotareas); - foreach($keys as $key) { - $plotarea =& $this->_plotareas[$key]; - $keys2 = array_keys($plotarea->_elements); - foreach($keys2 as $key) { - $element =& $plotarea->_elements[$key]; - if (is_a($element, 'Image_Graph_Plot')) { - $element->_legendSample($param); - } - } - unset($keys2); - } - unset($keys); - return $param['maxwidth']; - } else { - return parent::width(); - } - } - - /** - * Set the alignment of the legend - * - * @param int $alignment The alignment - */ - function setAlignment($alignment) - { - $this->_alignment = $alignment; - } - - /** - * Update coordinates - * - * @access private - */ - function _updateCoords() - { - parent::_updateCoords(); - - $parent = (is_object($this->_parent) ? get_class($this->_parent) : $this->_parent); - - if (strtolower($parent) == 'image_graph_plotarea') { - $w = $this->_width(); - $h = $this->_height(); - - if ($this->_alignment === false) { - $this->_alignment = IMAGE_GRAPH_ALIGN_TOP + IMAGE_GRAPH_ALIGN_RIGHT; - } - - if (($this->_alignment & IMAGE_GRAPH_ALIGN_BOTTOM) != 0) { - $y = $this->_parent->_fillBottom() - $h - $this->_padding; - } else { - $y = $this->_parent->_fillTop() + $this->_padding; - } - - if (($this->_alignment & IMAGE_GRAPH_ALIGN_LEFT) != 0) { - $x = $this->_parent->_fillLeft() + $this->_padding; - } else { - $x = $this->_parent->_fillRight() - $w - $this->_padding; - } - - $this->_setCoords($x, $y, $x + $w, $y + $h); - } - } - - /** - * Sets Plotarea - * - * @param Image_Graph_Plotarea $plotarea The plotarea - */ - function setPlotarea(& $plotarea) - { - if (is_a($plotarea, 'Image_Graph_Plotarea')) { - $this->_plotareas[] =& $plotarea; - } - } - - /** - * Sets the parent. The parent chain should ultimately be a GraPHP object - * - * @see Image_Graph - * @param Image_Graph_Common $parent The parent - * @access private - */ - function _setParent(& $parent) - { - parent::_setParent($parent); - if (count($this->_plotareas) == 0) { - $this->setPlotarea($parent); - } - } - - /** - * Set if this legends should show markers - * - * @param bool $showMarker True if markers are to be shown, false is not - */ - function setShowMarker($showMarker) - { - $this->_showMarker = $showMarker; - } - - - /** - * Output the plot - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - - if (Image_Graph_Element::_done() === false) { - return false; - } - - $this->_canvas->startGroup(get_class($this)); - - $param = $this->_parameterArray(); - - $parent = (is_object($this->_parent) ? - get_class($this->_parent) : - $this->_parent - ); - - if (strtolower($parent) == 'image_graph_plotarea') { - $this->_getFillStyle(); - $this->_getLineStyle(); - $this->_canvas->rectangle( - array( - 'x0' => $this->_left, - 'y0' => $this->_top, - 'x1' => $this->_right, - 'y1' => $this->_bottom - ) - ); - - $param = $this->_parameterArray(); - - $keys = array_keys($this->_plotareas); - foreach($keys as $key) { - $plotarea =& $this->_plotareas[$key]; - $keys2 = array_keys($plotarea->_elements); - foreach($keys2 as $key) { - $element =& $plotarea->_elements[$key]; - if (is_a($element, 'Image_Graph_Plot')) { - $element->_legendSample($param); - } - } - unset($keys2); - } - unset($keys); - } else { - $param0 = $param; - $param0['simulate'] = true; - $keys = array_keys($this->_plotareas); - foreach($keys as $key) { - $plotarea =& $this->_plotareas[$key]; - $keys2 = array_keys($plotarea->_elements); - foreach($keys2 as $key) { - $element =& $plotarea->_elements[$key]; - if (is_a($element, 'Image_Graph_Plot')) { - $element->_legendSample($param0); - } - } - unset($keys2); - } - unset($keys); - if (($this->_alignment & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) { - if ($param0['x'] == $param['x']) { - $param['y'] = $param['y'] + ($this->_height() - ($param0['y'] - $param['y']))/2; - } - } else { - if ($param0['y'] == $param['y']) { - $param['x'] = $param['x'] + ($this->_width() - ($param0['x'] - $param['x']))/2; - } - } - - $keys = array_keys($this->_plotareas); - foreach($keys as $key) { - $plotarea =& $this->_plotareas[$key]; - $keys2 = array_keys($plotarea->_elements); - foreach($keys2 as $key) { - $element =& $plotarea->_elements[$key]; - if (is_a($element, 'Image_Graph_Plot')) { - $element->_legendSample($param); - } - } - unset($keys2); - } - unset($keys); - } - - $this->_canvas->endGroup(); - - return true; - } -} + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Legend.php,v 1.16 2006/02/28 22:48:07 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Layout.php + */ +require_once 'Image/Graph/Layout.php'; + +/** + * Displays a legend for a plotarea. + * + * A legend can be displayed in two ways: + * + * 1 As an overlayed box within the plotarea + * + * 2 Layout'ed on the canvas smewhere next to the plotarea. + * + * @category Images + * @package Image_Graph + * @subpackage Legend + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Legend extends Image_Graph_Layout +{ + + /** + * Alignment of the text + * @var int + * @access private + */ + var $_alignment = false; + + /** + * The plotarea(s) to show the legend for + * @var array + * @access private + */ + var $_plotareas = array(); + + /** + * Should markers be shown or not on this legend + * @var bool + * @access private + */ + var $_showMarker = false; + + /** + * Image_Graph_Legend [Constructor] + */ + function Image_Graph_Legend() + { + parent::Image_Graph_Layout(); + $this->_padding = array('left' => 5, 'top' => 5, 'right' => 5, 'bottom' => 5); + } + + /** + * The number of actual plots in the plot area + * + * @return int The number of plotes + * @access private + */ + function _plotCount() + { + $count = 0; + $keys = array_keys($this->_plotareas); + foreach($keys as $key) { + $plotarea =& $this->_plotareas[$key]; + if (is_a($plotarea, 'Image_Graph_Plotarea')) { + $keys2 = array_keys($plotarea->_elements); + foreach ($keys2 as $key) { + $element =& $plotarea->_elements[$key]; + if (is_a($element, 'Image_Graph_Plot')) { + $count ++; + } + } + unset($keys2); + } + } + unset($keys); + return $count; + } + + /** + * Get a default parameter array for legendSamples + * @param bool $simulate Whether the array should be used for simulation or + * not + * @return array Default parameter array + * @access private + */ + function _parameterArray($simulate = false) + { + $param['left'] = $this->_left + $this->_padding['left']; + $param['top'] = $this->_top + $this->_padding['top']; + $param['right'] = $this->_right - $this->_padding['right']; + $param['bottom'] = $this->_bottom - $this->_padding['bottom']; + $param['align'] = $this->_alignment; + $param['x'] = $this->_left + $this->_padding['left']; + $param['y'] = $this->_top + $this->_padding['top']; + $param['width'] = 16; + $param['height'] = 16; + $param['show_marker'] = $this->_showMarker; + $param['maxwidth'] = 0; + $param['font'] = $this->_getFont(); + if ($simulate) { + $param['simulate'] = true; + } + + return $param; + } + + /** + * The height of the element on the canvas + * + * @return int Number of pixels representing the height of the element + * @access private + */ + function _height() + { + $parent = (is_object($this->_parent) ? get_class($this->_parent) : $this->_parent); + + if (strtolower($parent) == 'image_graph_plotarea') { + $param = $this->_parameterArray(true); + $param['align'] = IMAGE_GRAPH_ALIGN_VERTICAL; + $param0 = $param; + $keys = array_keys($this->_plotareas); + foreach($keys as $key) { + $plotarea =& $this->_plotareas[$key]; + $keys2 = array_keys($plotarea->_elements); + foreach($keys2 as $key) { + $element =& $plotarea->_elements[$key]; + if (is_a($element, 'Image_Graph_Plot')) { + $element->_legendSample($param); + } + } + unset($keys2); + } + unset($keys); + return abs($param['y'] - $param0['y']) + $this->_padding['top'] + $this->_padding['bottom']; + } else { + return parent::height(); + } + } + + /** + * The width of the element on the canvas + * + * @return int Number of pixels representing the width of the element + * @access private + */ + function _width() + { + $parent = (is_object($this->_parent) ? get_class($this->_parent) : $this->_parent); + + if (strtolower($parent) == 'image_graph_plotarea') { + $param = $this->_parameterArray(true); + $param['align'] = IMAGE_GRAPH_ALIGN_VERTICAL; + $keys = array_keys($this->_plotareas); + foreach($keys as $key) { + $plotarea =& $this->_plotareas[$key]; + $keys2 = array_keys($plotarea->_elements); + foreach($keys2 as $key) { + $element =& $plotarea->_elements[$key]; + if (is_a($element, 'Image_Graph_Plot')) { + $element->_legendSample($param); + } + } + unset($keys2); + } + unset($keys); + return $param['maxwidth']; + } else { + return parent::width(); + } + } + + /** + * Set the alignment of the legend + * + * @param int $alignment The alignment + */ + function setAlignment($alignment) + { + $this->_alignment = $alignment; + } + + /** + * Update coordinates + * + * @access private + */ + function _updateCoords() + { + parent::_updateCoords(); + + $parent = (is_object($this->_parent) ? get_class($this->_parent) : $this->_parent); + + if (strtolower($parent) == 'image_graph_plotarea') { + $w = $this->_width(); + $h = $this->_height(); + + if ($this->_alignment === false) { + $this->_alignment = IMAGE_GRAPH_ALIGN_TOP + IMAGE_GRAPH_ALIGN_RIGHT; + } + + if (($this->_alignment & IMAGE_GRAPH_ALIGN_BOTTOM) != 0) { + $y = $this->_parent->_fillBottom() - $h - $this->_padding['bottom']; + } else { + $y = $this->_parent->_fillTop() + $this->_padding['top']; + } + + if (($this->_alignment & IMAGE_GRAPH_ALIGN_LEFT) != 0) { + $x = $this->_parent->_fillLeft() + $this->_padding['left']; + } else { + $x = $this->_parent->_fillRight() - $w - $this->_padding['right']; + } + + $this->_setCoords($x, $y, $x + $w, $y + $h); + } + } + + /** + * Sets Plotarea + * + * @param Image_Graph_Plotarea $plotarea The plotarea + */ + function setPlotarea(& $plotarea) + { + if (is_a($plotarea, 'Image_Graph_Plotarea')) { + $this->_plotareas[] =& $plotarea; + } + } + + /** + * Sets the parent. The parent chain should ultimately be a GraPHP object + * + * @see Image_Graph + * @param Image_Graph_Common $parent The parent + * @access private + */ + function _setParent(& $parent) + { + parent::_setParent($parent); + if (count($this->_plotareas) == 0) { + $this->setPlotarea($parent); + } + } + + /** + * Set if this legends should show markers + * + * @param bool $showMarker True if markers are to be shown, false is not + */ + function setShowMarker($showMarker) + { + $this->_showMarker = $showMarker; + } + + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + + if (Image_Graph_Element::_done() === false) { + return false; + } + + $this->_canvas->startGroup(get_class($this)); + + $param = $this->_parameterArray(); + + $parent = (is_object($this->_parent) ? + get_class($this->_parent) : + $this->_parent + ); + + if (strtolower($parent) == 'image_graph_plotarea') { + $this->_getFillStyle(); + $this->_getLineStyle(); + $this->_canvas->rectangle( + array( + 'x0' => $this->_left, + 'y0' => $this->_top, + 'x1' => $this->_right, + 'y1' => $this->_bottom + ) + ); + + $param = $this->_parameterArray(); + + $keys = array_keys($this->_plotareas); + foreach($keys as $key) { + $plotarea =& $this->_plotareas[$key]; + $keys2 = array_keys($plotarea->_elements); + foreach($keys2 as $key) { + $element =& $plotarea->_elements[$key]; + if (is_a($element, 'Image_Graph_Plot')) { + $element->_legendSample($param); + } + } + unset($keys2); + } + unset($keys); + } else { + $param0 = $param; + $param0['simulate'] = true; + $keys = array_keys($this->_plotareas); + foreach($keys as $key) { + $plotarea =& $this->_plotareas[$key]; + $keys2 = array_keys($plotarea->_elements); + foreach($keys2 as $key) { + $element =& $plotarea->_elements[$key]; + if (is_a($element, 'Image_Graph_Plot')) { + $element->_legendSample($param0); + } + } + unset($keys2); + } + unset($keys); + if (($this->_alignment & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) { + if ($param0['x'] == $param['x']) { + $param['y'] = $param['y'] + ($this->_height() - ($param0['y'] - $param['y']))/2; + } + } else { + if ($param0['y'] == $param['y']) { + $param['x'] = $param['x'] + ($this->_width() - ($param0['x'] - $param['x']))/2; + } + } + + $keys = array_keys($this->_plotareas); + foreach($keys as $key) { + $plotarea =& $this->_plotareas[$key]; + $keys2 = array_keys($plotarea->_elements); + foreach($keys2 as $key) { + $element =& $plotarea->_elements[$key]; + if (is_a($element, 'Image_Graph_Plot')) { + $element->_legendSample($param); + } + } + unset($keys2); + } + unset($keys); + } + + $this->_canvas->endGroup(); + + return true; + } +} ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Line/Array.php b/includes/pear/Image/Graph/Line/Array.php index 92281d93..cb9ac535 100644 --- a/includes/pear/Image/Graph/Line/Array.php +++ b/includes/pear/Image/Graph/Line/Array.php @@ -1,129 +1,129 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Array.php,v 1.7 2005/02/21 20:49:42 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Common.php - */ -require_once 'Image/Graph/Common.php'; - -/** - * A sequential array of linestyles. - * - * This is used for multiple objects within the same element with different line - * styles. This is done by adding multiple line styles to a LineArrray - * structure. The linearray will then when requested return the 'next' linestyle - * in sequential order. It is possible to specify ID tags to each linestyle, - * which is used to make sure some data uses a specific linestyle (i.e. in a - * multiple-/stackedbarchart you name the {@link Image_Graph_Dataset}s and uses - * this name as ID tag when adding the dataset's associated linestyle to the - * linearray. - * - * @category Images - * @package Image_Graph - * @subpackage Line - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Line_Array extends Image_Graph_Common -{ - - /** - * The fill array - * @var array - * @access private - */ - var $_lineStyles = array (); - - /** - * Add a line style to the array - * - * @param Image_Graph_Line $style The style to add - */ - function add(& $style, $id = false) - { - if (is_a($style, 'Image_Graph_Element')) { - parent::add($style); - } - if ($id === false) { - $this->_lineStyles[] =& $style; - } else { - $this->_lineStyles[$id] =& $style; - } - reset($this->_lineStyles); - - } - - /** - * Add a color to the array - * - * @param int $color The color - * @param string $id The id or name of the color - */ - function addColor($color, $id = false) - { - if ($id !== false) { - $this->_lineStyles[$id] = $color; - } else { - $this->_lineStyles[] = $color; - } - reset($this->_lineStyles); - } - - /** - * Return the linestyle - * - * @return int A GD Linestyle - * @access private - */ - function _getLineStyle($ID = false) - { - if (($ID === false) || (!isset($this->_lineStyles[$ID]))) { - $ID = key($this->_lineStyles); - if (!next($this->_lineStyles)) { - reset($this->_lineStyles); - } - } - $lineStyle =& $this->_lineStyles[$ID]; - - if (is_object($lineStyle)) { - return $lineStyle->_getLineStyle($ID); - } elseif ($lineStyle !== null) { - return $lineStyle; - } else { - return parent::_getLineStyle($ID); - } - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Array.php,v 1.7 2005/02/21 20:49:42 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Common.php + */ +require_once 'Image/Graph/Common.php'; + +/** + * A sequential array of linestyles. + * + * This is used for multiple objects within the same element with different line + * styles. This is done by adding multiple line styles to a LineArrray + * structure. The linearray will then when requested return the 'next' linestyle + * in sequential order. It is possible to specify ID tags to each linestyle, + * which is used to make sure some data uses a specific linestyle (i.e. in a + * multiple-/stackedbarchart you name the {@link Image_Graph_Dataset}s and uses + * this name as ID tag when adding the dataset's associated linestyle to the + * linearray. + * + * @category Images + * @package Image_Graph + * @subpackage Line + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Line_Array extends Image_Graph_Common +{ + + /** + * The fill array + * @var array + * @access private + */ + var $_lineStyles = array (); + + /** + * Add a line style to the array + * + * @param Image_Graph_Line $style The style to add + */ + function add(& $style, $id = false) + { + if (is_a($style, 'Image_Graph_Element')) { + parent::add($style); + } + if ($id === false) { + $this->_lineStyles[] =& $style; + } else { + $this->_lineStyles[$id] =& $style; + } + reset($this->_lineStyles); + + } + + /** + * Add a color to the array + * + * @param int $color The color + * @param string $id The id or name of the color + */ + function addColor($color, $id = false) + { + if ($id !== false) { + $this->_lineStyles[$id] = $color; + } else { + $this->_lineStyles[] = $color; + } + reset($this->_lineStyles); + } + + /** + * Return the linestyle + * + * @return int A GD Linestyle + * @access private + */ + function _getLineStyle($ID = false) + { + if (($ID === false) || (!isset($this->_lineStyles[$ID]))) { + $ID = key($this->_lineStyles); + if (!next($this->_lineStyles)) { + reset($this->_lineStyles); + } + } + $lineStyle =& $this->_lineStyles[$ID]; + + if (is_object($lineStyle)) { + return $lineStyle->_getLineStyle($ID); + } elseif ($lineStyle !== null) { + return $lineStyle; + } else { + return parent::_getLineStyle($ID); + } + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Line/Dashed.php b/includes/pear/Image/Graph/Line/Dashed.php index 1a60dc2c..3e903ab1 100644 --- a/includes/pear/Image/Graph/Line/Dashed.php +++ b/includes/pear/Image/Graph/Line/Dashed.php @@ -1,76 +1,76 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Dashed.php,v 1.6 2005/08/24 20:35:52 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Line/Formatted.php - */ -require_once 'Image/Graph/Line/Formatted.php'; - -/** - * Dashed line style. - * - * This style displays as a short line with a shorter space afterwards, i.e - * 4px color1, 2px color2, 4px color1, etc. - * - * @category Images - * @package Image_Graph - * @subpackage Line - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Line_Dashed extends Image_Graph_Line_Formatted -{ - - /** - * Image_Graph_DashedLine [Constructor] - * - * @param mixed $color1 The color for the 'dashes' - * @param mixed $color2 The color for the 'spaces' - */ - function Image_Graph_Line_Dashed($color1, $color2) - { - parent::Image_Graph_Line_Formatted( - array( - $color1, - $color1, - $color1, - $color1, - $color2, - $color2 - ) - ); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Dashed.php,v 1.6 2005/08/24 20:35:52 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Line/Formatted.php + */ +require_once 'Image/Graph/Line/Formatted.php'; + +/** + * Dashed line style. + * + * This style displays as a short line with a shorter space afterwards, i.e + * 4px color1, 2px color2, 4px color1, etc. + * + * @category Images + * @package Image_Graph + * @subpackage Line + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Line_Dashed extends Image_Graph_Line_Formatted +{ + + /** + * Image_Graph_DashedLine [Constructor] + * + * @param mixed $color1 The color for the 'dashes' + * @param mixed $color2 The color for the 'spaces' + */ + function Image_Graph_Line_Dashed($color1, $color2) + { + parent::Image_Graph_Line_Formatted( + array( + $color1, + $color1, + $color1, + $color1, + $color2, + $color2 + ) + ); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Line/Dotted.php b/includes/pear/Image/Graph/Line/Dotted.php index 9bf05d87..f78c3d9d 100644 --- a/includes/pear/Image/Graph/Line/Dotted.php +++ b/includes/pear/Image/Graph/Line/Dotted.php @@ -1,67 +1,67 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Dotted.php,v 1.6 2005/08/24 20:35:52 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Line/Formatted.php - */ -require_once 'Image/Graph/Line/Formatted.php'; - -/** - * Dotted line style. - * - * This style displays as a short line with a shorter space afterwards, i.e - * 1px color1, 1px color2, 1px color1, etc. - * - * @category Images - * @package Image_Graph - * @subpackage Line - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Line_Dotted extends Image_Graph_Line_Formatted -{ - - /** - * DottedLine [Constructor] - * - * @param mixed $color1 The color representing the dots - * @param mixed $color2 The color representing the spaces - */ - function Image_Graph_Line_Dotted($color1, $color2) - { - parent::Image_Graph_Line_Formatted(array ($color1, $color2)); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Dotted.php,v 1.6 2005/08/24 20:35:52 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Line/Formatted.php + */ +require_once 'Image/Graph/Line/Formatted.php'; + +/** + * Dotted line style. + * + * This style displays as a short line with a shorter space afterwards, i.e + * 1px color1, 1px color2, 1px color1, etc. + * + * @category Images + * @package Image_Graph + * @subpackage Line + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Line_Dotted extends Image_Graph_Line_Formatted +{ + + /** + * DottedLine [Constructor] + * + * @param mixed $color1 The color representing the dots + * @param mixed $color2 The color representing the spaces + */ + function Image_Graph_Line_Dotted($color1, $color2) + { + parent::Image_Graph_Line_Formatted(array ($color1, $color2)); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Line/Formatted.php b/includes/pear/Image/Graph/Line/Formatted.php index 58c819ff..0759724d 100644 --- a/includes/pear/Image/Graph/Line/Formatted.php +++ b/includes/pear/Image/Graph/Line/Formatted.php @@ -1,90 +1,90 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Formatted.php,v 1.6 2005/08/24 20:35:51 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Line/Solid.php - */ -require_once 'Image/Graph/Line/Solid.php'; - -/** - * Formatted user defined line style. - * - * Use this to create a user defined line style. Specify an array of colors that are to - * be used for displaying the line. - * - * @category Images - * @package Image_Graph - * @subpackage Line - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Line_Formatted extends Image_Graph_Line_Solid -{ - - /** - * The style of the line - * - * @var array - * @access private - */ - var $_style; - - /** - * Image_Graph_FormattedLine [Constructor] - * - * @param array $style The style of the line - */ - function Image_Graph_Line_Formatted($style) - { - parent::Image_Graph_Line_Solid(reset($style)); - $this->_style = $style; - } - - /** - * Gets the line style of the element - * - * @return int A GD linestyle representing the line style - * @see Image_Graph_Line - * @access private - */ - function _getLineStyle() - { - return array( - 'color' => $this->_style, - 'thickness' => $this->_thickness - ); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Formatted.php,v 1.6 2005/08/24 20:35:51 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Line/Solid.php + */ +require_once 'Image/Graph/Line/Solid.php'; + +/** + * Formatted user defined line style. + * + * Use this to create a user defined line style. Specify an array of colors that are to + * be used for displaying the line. + * + * @category Images + * @package Image_Graph + * @subpackage Line + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Line_Formatted extends Image_Graph_Line_Solid +{ + + /** + * The style of the line + * + * @var array + * @access private + */ + var $_style; + + /** + * Image_Graph_FormattedLine [Constructor] + * + * @param array $style The style of the line + */ + function Image_Graph_Line_Formatted($style) + { + parent::Image_Graph_Line_Solid(reset($style)); + $this->_style = $style; + } + + /** + * Gets the line style of the element + * + * @return int A GD linestyle representing the line style + * @see Image_Graph_Line + * @access private + */ + function _getLineStyle() + { + return array( + 'color' => $this->_style, + 'thickness' => $this->_thickness + ); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Line/Solid.php b/includes/pear/Image/Graph/Line/Solid.php index ffbe685d..4239d348 100644 --- a/includes/pear/Image/Graph/Line/Solid.php +++ b/includes/pear/Image/Graph/Line/Solid.php @@ -1,105 +1,105 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Solid.php,v 1.6 2005/08/24 20:35:51 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Common.php - */ -require_once 'Image/Graph/Common.php'; - -/** - * Simple colored line style. - * - * Use a color for line style. - * - * @category Images - * @package Image_Graph - * @subpackage Line - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Line_Solid extends Image_Graph_Common -{ - - /** - * The thickness of the line (requires GD 2) - * @var int - * @access private - */ - var $_thickness = 1; - - /** - * The color of the line - * @var mixed - * @access private - */ - var $_color; - - /** - * Image_Graph_SolidLine [Constructor] - * - * @param mixed $color The color of the line - */ - function Image_Graph_Line_Solid($color) - { - parent::Image_Graph_Common(); - $this->_color = $color; - } - - /** - * Set the thickness of the linestyle - * - * @param int $thickness The line width in pixels - */ - function setThickness($thickness) - { - $this->_thickness = $thickness; - } - - /** - * Gets the line style of the element - * - * @return int A GD linestyle representing the line style - * @see Image_Graph_Line - * @access private - */ - function _getLineStyle() - { - return array( - 'color' => $this->_color, - 'thickness' => $this->_thickness - ); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Solid.php,v 1.6 2005/08/24 20:35:51 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Common.php + */ +require_once 'Image/Graph/Common.php'; + +/** + * Simple colored line style. + * + * Use a color for line style. + * + * @category Images + * @package Image_Graph + * @subpackage Line + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Line_Solid extends Image_Graph_Common +{ + + /** + * The thickness of the line (requires GD 2) + * @var int + * @access private + */ + var $_thickness = 1; + + /** + * The color of the line + * @var mixed + * @access private + */ + var $_color; + + /** + * Image_Graph_SolidLine [Constructor] + * + * @param mixed $color The color of the line + */ + function Image_Graph_Line_Solid($color) + { + parent::Image_Graph_Common(); + $this->_color = $color; + } + + /** + * Set the thickness of the linestyle + * + * @param int $thickness The line width in pixels + */ + function setThickness($thickness) + { + $this->_thickness = $thickness; + } + + /** + * Gets the line style of the element + * + * @return int A GD linestyle representing the line style + * @see Image_Graph_Line + * @access private + */ + function _getLineStyle() + { + return array( + 'color' => $this->_color, + 'thickness' => $this->_thickness + ); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Logo.php b/includes/pear/Image/Graph/Logo.php index 6093b13e..fea5d986 100644 --- a/includes/pear/Image/Graph/Logo.php +++ b/includes/pear/Image/Graph/Logo.php @@ -1,153 +1,153 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Logo.php,v 1.9 2005/08/24 20:35:56 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Element.php - */ -require_once 'Image/Graph/Element.php'; - -/** - * Displays a logo on the canvas. - * - * By default the logo is displayed in the top-right corner of the canvas. - * - * @category Images - * @package Image_Graph - * @subpackage Logo - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Logo extends Image_Graph_Element -{ - - /** - * The file name - * @var stirng - * @access private - */ - var $_filename; - - /** - * The GD Image resource - * @var resource - * @access private - */ - var $_image; - - /** - * Alignment of the logo - * @var int - * @access private - */ - var $_alignment; - - /** - * Logo [Constructor] - * - * @param string $filename The filename and path of the image to use for logo - */ - function Image_Graph_Logo($filename, $alignment = IMAGE_GRAPH_ALIGN_TOP_RIGHT) - { - parent::Image_Graph_Element(); - $this->_filename = $filename; - $this->_alignment = $alignment; - } - - /** - * Sets the parent. The parent chain should ultimately be a GraPHP object - * - * @see Image_Graph - * @param Image_Graph_Common $parent The parent - * @access private - */ - function _setParent(& $parent) - { - parent::_setParent($parent); - $this->_setCoords( - $this->_parent->_left, - $this->_parent->_top, - $this->_parent->_right, - $this->_parent->_bottom - ); - } - - /** - * Output the logo - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (parent::_done() === false) { - return false; - } - - $align = array(); - - if ($this->_alignment & IMAGE_GRAPH_ALIGN_LEFT) { - $x = $this->_parent->_left + 2; - $align['horizontal'] = 'left'; - } elseif ($this->_alignment & IMAGE_GRAPH_ALIGN_RIGHT) { - $x = $this->_parent->_right - 2; - $align['horizontal'] = 'right'; - } else { - $x = ($this->_parent->_left + $this->_parent->_right) / 2; - $align['horizontal'] = 'center'; - } - - if ($this->_alignment & IMAGE_GRAPH_ALIGN_TOP) { - $y = $this->_parent->_top + 2; - $align['vertical'] = 'top'; - } elseif ($this->_alignment & IMAGE_GRAPH_ALIGN_BOTTOM) { - $y = $this->_parent->_bottom - 2; - $align['vertical'] = 'bottom'; - } else { - $y = ($this->_parent->_top + $this->_parent->_bottom) / 2; - $align['vertical'] = 'center'; - } - - $this->_canvas->image( - array( - 'x' => $x, - 'y' => $y, - 'filename' => $this->_filename, - 'alignment' => $align - ) - ); - return true; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Logo.php,v 1.9 2005/08/24 20:35:56 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Element.php + */ +require_once 'Image/Graph/Element.php'; + +/** + * Displays a logo on the canvas. + * + * By default the logo is displayed in the top-right corner of the canvas. + * + * @category Images + * @package Image_Graph + * @subpackage Logo + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Logo extends Image_Graph_Element +{ + + /** + * The file name + * @var stirng + * @access private + */ + var $_filename; + + /** + * The GD Image resource + * @var resource + * @access private + */ + var $_image; + + /** + * Alignment of the logo + * @var int + * @access private + */ + var $_alignment; + + /** + * Logo [Constructor] + * + * @param string $filename The filename and path of the image to use for logo + */ + function Image_Graph_Logo($filename, $alignment = IMAGE_GRAPH_ALIGN_TOP_RIGHT) + { + parent::Image_Graph_Element(); + $this->_filename = $filename; + $this->_alignment = $alignment; + } + + /** + * Sets the parent. The parent chain should ultimately be a GraPHP object + * + * @see Image_Graph + * @param Image_Graph_Common $parent The parent + * @access private + */ + function _setParent(& $parent) + { + parent::_setParent($parent); + $this->_setCoords( + $this->_parent->_left, + $this->_parent->_top, + $this->_parent->_right, + $this->_parent->_bottom + ); + } + + /** + * Output the logo + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + $align = array(); + + if ($this->_alignment & IMAGE_GRAPH_ALIGN_LEFT) { + $x = $this->_parent->_left + 2; + $align['horizontal'] = 'left'; + } elseif ($this->_alignment & IMAGE_GRAPH_ALIGN_RIGHT) { + $x = $this->_parent->_right - 2; + $align['horizontal'] = 'right'; + } else { + $x = ($this->_parent->_left + $this->_parent->_right) / 2; + $align['horizontal'] = 'center'; + } + + if ($this->_alignment & IMAGE_GRAPH_ALIGN_TOP) { + $y = $this->_parent->_top + 2; + $align['vertical'] = 'top'; + } elseif ($this->_alignment & IMAGE_GRAPH_ALIGN_BOTTOM) { + $y = $this->_parent->_bottom - 2; + $align['vertical'] = 'bottom'; + } else { + $y = ($this->_parent->_top + $this->_parent->_bottom) / 2; + $align['vertical'] = 'center'; + } + + $this->_canvas->image( + array( + 'x' => $x, + 'y' => $y, + 'filename' => $this->_filename, + 'alignment' => $align + ) + ); + return true; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Marker.php b/includes/pear/Image/Graph/Marker.php index 4bad1540..7e445d66 100644 --- a/includes/pear/Image/Graph/Marker.php +++ b/includes/pear/Image/Graph/Marker.php @@ -1,123 +1,123 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Marker.php,v 1.8 2005/02/21 20:49:47 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Plotarea/Element.php - */ -require_once 'Image/Graph/Plotarea/Element.php'; - -/** - * Data point marker. - * - * The data point marker is used for marking the datapoints on a graph with some - * visual label, fx. a cross, a text box with the value or an icon. - * - * @category Images - * @package Image_Graph - * @subpackage Marker - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - * @abstract - */ -class Image_Graph_Marker extends Image_Graph_Plotarea_Element -{ - - /** - * Secondary marker - * @var Marker - * @access private - */ - var $_secondaryMarker = false; - - /** - * The 'size' of the marker, the meaning depends on the specific Marker - * implementation - * @var int - * @access private - */ - var $_size = 6; - - /** - * Set the 'size' of the marker - * - * @param int $size The 'size' of the marker, the meaning depends on the - * specific Marker implementation - */ - function setSize($size) - { - $this->_size = $size; - } - - /** - * Set the secondary marker - * - * @param Marker $secondaryMarker The secondary marker - */ - function setSecondaryMarker(& $secondaryMarker) - { - $this->_secondaryMarker =& $secondaryMarker; - $this->_secondaryMarker->_setParent($this); - } - - /** - * Draw the marker on the canvas - * - * @param int $x The X (horizontal) position (in pixels) of the marker on - * the canvas - * @param int $y The Y (vertical) position (in pixels) of the marker on the - * canvas - * @param array $values The values representing the data the marker 'points' - * to - * @access private - */ - function _drawMarker($x, $y, $values = false) - { - if (is_a($this->_secondaryMarker, 'Image_Graph_Marker')) { - $this->_secondaryMarker->_drawMarker($x, $y, $values); - } - } - - /** - * Output to the canvas - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - return true; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Marker.php,v 1.8 2005/02/21 20:49:47 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plotarea/Element.php + */ +require_once 'Image/Graph/Plotarea/Element.php'; + +/** + * Data point marker. + * + * The data point marker is used for marking the datapoints on a graph with some + * visual label, fx. a cross, a text box with the value or an icon. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + * @abstract + */ +class Image_Graph_Marker extends Image_Graph_Plotarea_Element +{ + + /** + * Secondary marker + * @var Marker + * @access private + */ + var $_secondaryMarker = false; + + /** + * The 'size' of the marker, the meaning depends on the specific Marker + * implementation + * @var int + * @access private + */ + var $_size = 6; + + /** + * Set the 'size' of the marker + * + * @param int $size The 'size' of the marker, the meaning depends on the + * specific Marker implementation + */ + function setSize($size) + { + $this->_size = $size; + } + + /** + * Set the secondary marker + * + * @param Marker $secondaryMarker The secondary marker + */ + function setSecondaryMarker(& $secondaryMarker) + { + $this->_secondaryMarker =& $secondaryMarker; + $this->_secondaryMarker->_setParent($this); + } + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + if (is_a($this->_secondaryMarker, 'Image_Graph_Marker')) { + $this->_secondaryMarker->_drawMarker($x, $y, $values); + } + } + + /** + * Output to the canvas + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + return true; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Marker/Array.php b/includes/pear/Image/Graph/Marker/Array.php index e958b872..73dee076 100644 --- a/includes/pear/Image/Graph/Marker/Array.php +++ b/includes/pear/Image/Graph/Marker/Array.php @@ -1,105 +1,105 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Array.php,v 1.6 2005/02/21 20:49:50 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Marker.php - */ -require_once 'Image/Graph/Marker.php'; - -/** - * A sequential array of markers. - * - * This is used for displaying different markers for datapoints on a chart. - * This is done by adding multiple markers to a MarkerArrray structure. - * The marker array will then when requested return the 'next' marker in - * sequential order. It is possible to specify ID tags to each marker, which is - * used to make sure some data uses a specific marker. - * - * @category Images - * @package Image_Graph - * @subpackage Marker - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Marker_Array extends Image_Graph_Marker -{ - - /** - * The marker array - * @var array - * @access private - */ - var $_markers = array (); - - /** - * Add a marker style to the array - * - * @param Marker $marker The marker to add - */ - function add(& $marker) - { - if (is_a($marker, 'Image_Graph_Element')) { - parent::add($marker); - } - $this->_markers[] =& $marker; - reset($this->_markers); - } - - /** - * Draw the marker on the canvas - * - * @param int $x The X (horizontal) position (in pixels) of the marker on - * the canvas - * @param int $y The Y (vertical) position (in pixels) of the marker on the - * canvas - * @param array $values The values representing the data the marker 'points' - * to - * @access private - */ - function _drawMarker($x, $y, $values = false) - { - $ID = key($this->_markers); - if (!next($this->_markers)) { - reset($this->_markers); - } - $marker =& $this->_markers[$ID]; - - if ($marker != null) { - $marker->_drawMarker($x, $y, $values); - } - parent::_drawMarker($x, $y, $values); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Array.php,v 1.6 2005/02/21 20:49:50 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * A sequential array of markers. + * + * This is used for displaying different markers for datapoints on a chart. + * This is done by adding multiple markers to a MarkerArrray structure. + * The marker array will then when requested return the 'next' marker in + * sequential order. It is possible to specify ID tags to each marker, which is + * used to make sure some data uses a specific marker. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Marker_Array extends Image_Graph_Marker +{ + + /** + * The marker array + * @var array + * @access private + */ + var $_markers = array (); + + /** + * Add a marker style to the array + * + * @param Marker $marker The marker to add + */ + function add(& $marker) + { + if (is_a($marker, 'Image_Graph_Element')) { + parent::add($marker); + } + $this->_markers[] =& $marker; + reset($this->_markers); + } + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + $ID = key($this->_markers); + if (!next($this->_markers)) { + reset($this->_markers); + } + $marker =& $this->_markers[$ID]; + + if ($marker != null) { + $marker->_drawMarker($x, $y, $values); + } + parent::_drawMarker($x, $y, $values); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Marker/Asterisk.php b/includes/pear/Image/Graph/Marker/Asterisk.php index 908ea109..632acb29 100644 --- a/includes/pear/Image/Graph/Marker/Asterisk.php +++ b/includes/pear/Image/Graph/Marker/Asterisk.php @@ -1,109 +1,109 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Asterisk.php,v 1.6 2005/08/03 21:21:55 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Marker.php - */ -require_once 'Image/Graph/Marker.php'; - -/** - * Data marker as an asterisk (*) - * - * @category Images - * @package Image_Graph - * @subpackage Marker - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Marker_Asterisk extends Image_Graph_Marker -{ - - /** - * Draw the marker on the canvas - * - * @param int $x The X (horizontal) position (in pixels) of the marker on - * the canvas - * @param int $y The Y (vertical) position (in pixels) of the marker on the - * canvas - * @param array $values The values representing the data the marker 'points' - * to - * @access private - */ - function _drawMarker($x, $y, $values = false) - { - $this->_getLineStyle(); - $this->_canvas->line( - array( - 'x0' => $x - $this->_size, - 'y0' => $y - $this->_size, - 'x1' => $x + $this->_size, - 'y1' => $y + $this->_size - ) - ); - - $this->_getLineStyle(); - $this->_canvas->line( - array( - 'x0' => $x + $this->_size, - 'y0' => $y - $this->_size, - 'x1' => $x - $this->_size, - 'y1' => $y + $this->_size - ) - ); - - $this->_getLineStyle(); - $this->_canvas->line( - array( - 'x0' => $x - $this->_size, - 'y0' => $y, - 'x1' => $x + $this->_size, - 'y1' => $y - ) - ); - - $this->_getLineStyle(); - $this->_canvas->line( - array( - 'x0' => $x, - 'y0' => $y - $this->_size, - 'x1' => $x, - 'y1' => $y + $this->_size - ) - ); - - parent::_drawMarker($x, $y, $values); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Asterisk.php,v 1.6 2005/08/03 21:21:55 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * Data marker as an asterisk (*) + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Marker_Asterisk extends Image_Graph_Marker +{ + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + $this->_getLineStyle(); + $this->_canvas->line( + array( + 'x0' => $x - $this->_size, + 'y0' => $y - $this->_size, + 'x1' => $x + $this->_size, + 'y1' => $y + $this->_size + ) + ); + + $this->_getLineStyle(); + $this->_canvas->line( + array( + 'x0' => $x + $this->_size, + 'y0' => $y - $this->_size, + 'x1' => $x - $this->_size, + 'y1' => $y + $this->_size + ) + ); + + $this->_getLineStyle(); + $this->_canvas->line( + array( + 'x0' => $x - $this->_size, + 'y0' => $y, + 'x1' => $x + $this->_size, + 'y1' => $y + ) + ); + + $this->_getLineStyle(); + $this->_canvas->line( + array( + 'x0' => $x, + 'y0' => $y - $this->_size, + 'x1' => $x, + 'y1' => $y + $this->_size + ) + ); + + parent::_drawMarker($x, $y, $values); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Marker/Average.php b/includes/pear/Image/Graph/Marker/Average.php index 7e691c27..b799d7ff 100644 --- a/includes/pear/Image/Graph/Marker/Average.php +++ b/includes/pear/Image/Graph/Marker/Average.php @@ -1,91 +1,91 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Average.php,v 1.6 2005/08/03 21:21:55 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Marker.php - */ -require_once 'Image/Graph/Marker.php'; - -/** - * A marker displaying the 'distance' to the datasets average value. - * - * @category Images - * @package Image_Graph - * @subpackage Marker - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Marker_Average extends Image_Graph_Marker -{ - - /** - * Draw the marker on the canvas - * - * @param int $x The X (horizontal) position (in pixels) of the marker on - * the canvas - * @param int $y The Y (vertical) position (in pixels) of the marker on the - * canvas - * @param array $values The values representing the data the marker 'points' - * to - * @access private - */ - function _drawMarker($x, $y, $values = false) - { - if ((isset($values['AVERAGE_Y'])) && - (is_a($this->_parent, 'Image_Graph_Plot'))) - { - $point = $this->_pointXY( - array( - 'X' => $values['APX'], - 'Y' => $values['AVERAGE_Y'] - ) - ); - $this->_getLineStyle(); - $this->_canvas->line(array('x0' => $x, 'y0' => $y, 'x1' => $point['X'], 'y1' => $point['Y'])); - - $this->_getLineStyle(); - $this->_canvas->line( - array( - 'x0' => $point['X'] - 2, - 'y0' => $point['Y'], - 'x1' => $point['X'] + 2, - 'y1' => $point['Y'] - ) - ); - } - parent::_drawMarker($x, $y, $values); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Average.php,v 1.6 2005/08/03 21:21:55 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * A marker displaying the 'distance' to the datasets average value. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Marker_Average extends Image_Graph_Marker +{ + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + if ((isset($values['AVERAGE_Y'])) && + (is_a($this->_parent, 'Image_Graph_Plot'))) + { + $point = $this->_pointXY( + array( + 'X' => $values['APX'], + 'Y' => $values['AVERAGE_Y'] + ) + ); + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x, 'y0' => $y, 'x1' => $point['X'], 'y1' => $point['Y'])); + + $this->_getLineStyle(); + $this->_canvas->line( + array( + 'x0' => $point['X'] - 2, + 'y0' => $point['Y'], + 'x1' => $point['X'] + 2, + 'y1' => $point['Y'] + ) + ); + } + parent::_drawMarker($x, $y, $values); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Marker/Box.php b/includes/pear/Image/Graph/Marker/Box.php index 25a91bcc..5b0328e1 100644 --- a/includes/pear/Image/Graph/Marker/Box.php +++ b/includes/pear/Image/Graph/Marker/Box.php @@ -1,76 +1,76 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Box.php,v 1.6 2005/08/03 21:21:55 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Marker.php - */ -require_once 'Image/Graph/Marker.php'; - -/** - * Data marker as a box - * - * @category Images - * @package Image_Graph - * @subpackage Marker - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Marker_Box extends Image_Graph_Marker -{ - - /** - * Draw the marker on the canvas - * - * @param int $x The X (horizontal) position (in pixels) of the marker on the canvas - * @param int $y The Y (vertical) position (in pixels) of the marker on the canvas - * @param array $values The values representing the data the marker 'points' to - * @access private - */ - function _drawMarker($x, $y, $values = false) - { - $this->_getFillStyle(); - $this->_getLineStyle(); - $this->_canvas->rectangle( - array( - 'x0' => $x - $this->_size, - 'y0' => $y - $this->_size, - 'x1' => $x + $this->_size, - 'y1' => $y + $this->_size - ) - ); - parent::_drawMarker($x, $y, $values); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Box.php,v 1.6 2005/08/03 21:21:55 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * Data marker as a box + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Marker_Box extends Image_Graph_Marker +{ + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the canvas + * @param array $values The values representing the data the marker 'points' to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + $this->_getFillStyle(); + $this->_getLineStyle(); + $this->_canvas->rectangle( + array( + 'x0' => $x - $this->_size, + 'y0' => $y - $this->_size, + 'x1' => $x + $this->_size, + 'y1' => $y + $this->_size + ) + ); + parent::_drawMarker($x, $y, $values); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Marker/Bubble.php b/includes/pear/Image/Graph/Marker/Bubble.php index 784d47a9..114d93bd 100644 --- a/includes/pear/Image/Graph/Marker/Bubble.php +++ b/includes/pear/Image/Graph/Marker/Bubble.php @@ -1,91 +1,91 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Bubble.php,v 1.5 2005/02/21 20:49:50 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Marker/Circle.php - */ -require_once 'Image/Graph/Marker/Circle.php'; - -/** - * Display a circle with y-value percentage as radius (require GD2). - * - * This will display a circle centered on the datapoint with a radius calculated - * as a percentage of the maximum value. I.e. the radius depends on the y-value - * of the datapoint - * - * @category Images - * @package Image_Graph - * @subpackage Marker - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Marker_Bubble extends Image_Graph_Marker_Circle -{ - - /** - * The radius of the marker when 100% - * @var int - * @access private - */ - var $_size100Pct = 40; - - /** - * Sets the maximum radius the marker can occupy - * - * @param int $radius The new Image_Graph_max radius - */ - function setMaxRadius($radius) - { - $this->_size100Pct = $radius; - } - - /** - * Draw the marker on the canvas - * - * @param int $x The X (horizontal) position (in pixels) of the marker on - * the canvas - * @param int $y The Y (vertical) position (in pixels) of the marker on the - * canvas - * @param array $values The values representing the data the marker 'points' - * to - * @access private - */ - function _drawMarker($x, $y, $values = false) - { - $this->_size = $this->_size100Pct*$values['PCT_MAX_Y']/100; - parent::_drawMarker($x, $y, $values); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Bubble.php,v 1.5 2005/02/21 20:49:50 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker/Circle.php + */ +require_once 'Image/Graph/Marker/Circle.php'; + +/** + * Display a circle with y-value percentage as radius (require GD2). + * + * This will display a circle centered on the datapoint with a radius calculated + * as a percentage of the maximum value. I.e. the radius depends on the y-value + * of the datapoint + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Marker_Bubble extends Image_Graph_Marker_Circle +{ + + /** + * The radius of the marker when 100% + * @var int + * @access private + */ + var $_size100Pct = 40; + + /** + * Sets the maximum radius the marker can occupy + * + * @param int $radius The new Image_Graph_max radius + */ + function setMaxRadius($radius) + { + $this->_size100Pct = $radius; + } + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + $this->_size = $this->_size100Pct*$values['PCT_MAX_Y']/100; + parent::_drawMarker($x, $y, $values); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Marker/Circle.php b/includes/pear/Image/Graph/Marker/Circle.php index aaa8dcdc..7851a963 100644 --- a/includes/pear/Image/Graph/Marker/Circle.php +++ b/includes/pear/Image/Graph/Marker/Circle.php @@ -1,96 +1,96 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Circle.php,v 1.6 2005/08/03 21:21:54 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Marker.php - */ -require_once 'Image/Graph/Marker.php'; - -/** - * Data marker as circle (require GD2) - * - * @category Images - * @package Image_Graph - * @subpackage Marker - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Marker_Circle extends Image_Graph_Marker -{ - - /** - * The 'size' of the marker, the meaning depends on the specific Marker - * implementation - * @var int - * @access private - */ - var $_size = 10; - - /** - * Draw the marker on the canvas - * - * @param int $x The X (horizontal) position (in pixels) of the marker on - * the canvas - * @param int $y The Y (vertical) position (in pixels) of the marker on the - * canvas - * @param array $values The values representing the data the marker 'points' to - * @access private - */ - function _drawMarker($x, $y, $values = false) - { - $this->_getFillStyle(); - $this->_getLineStyle(); - - $dA = 2*pi()/($this->_size*2); - $angle = 0; - while ($angle < 2*pi()) { - $this->_canvas->addVertex(array('x' => - $x + $this->_size*cos($angle), 'y' => - $y - $this->_size*sin($angle) - )); - $angle += $dA; - } - - $this->_canvas->addVertex(array('x' => - $x + $this->_size*cos(0), 'y' => - $y - $this->_size*sin(0) - )); - - $this->_canvas->polygon(array('connect' => true)); - - parent::_drawMarker($x, $y, $values); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Circle.php,v 1.6 2005/08/03 21:21:54 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * Data marker as circle (require GD2) + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Marker_Circle extends Image_Graph_Marker +{ + + /** + * The 'size' of the marker, the meaning depends on the specific Marker + * implementation + * @var int + * @access private + */ + var $_size = 10; + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + $this->_getFillStyle(); + $this->_getLineStyle(); + + $dA = 2*pi()/($this->_size*2); + $angle = 0; + while ($angle < 2*pi()) { + $this->_canvas->addVertex(array('x' => + $x + $this->_size*cos($angle), 'y' => + $y - $this->_size*sin($angle) + )); + $angle += $dA; + } + + $this->_canvas->addVertex(array('x' => + $x + $this->_size*cos(0), 'y' => + $y - $this->_size*sin(0) + )); + + $this->_canvas->polygon(array('connect' => true)); + + parent::_drawMarker($x, $y, $values); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Marker/Cross.php b/includes/pear/Image/Graph/Marker/Cross.php index 2a893069..853d8786 100644 --- a/includes/pear/Image/Graph/Marker/Cross.php +++ b/includes/pear/Image/Graph/Marker/Cross.php @@ -1,114 +1,114 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Cross.php,v 1.7 2005/08/03 21:21:55 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Marker.php - */ -require_once 'Image/Graph/Marker.php'; - -/** - * Data marker as a cross. - * - * @category Images - * @package Image_Graph - * @subpackage Marker - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Marker_Cross extends Image_Graph_Marker -{ - - /** - * The thickness of the plus in pixels (thickness is actually double this) - * @var int - * @access private - */ - var $_thickness = 2; - - /** - * Draw the marker on the canvas - * - * @param int $x The X (horizontal) position (in pixels) of the marker on the canvas - * @param int $y The Y (vertical) position (in pixels) of the marker on the canvas - * @param array $values The values representing the data the marker 'points' to - * @access private - */ - function _drawMarker($x, $y, $values = false) - { - if ($this->_thickness > 0) { - $this->_getLineStyle(); - $this->_getFillStyle(); - - $d1 = round(0.7071067 * $this->_size); // cos/sin(45 de>) - $d2 = round(0.7071067 * $this->_thickness); // cos/sin(45 deg) - - $this->_canvas->addVertex(array('x' => $x - $d1 - $d2, 'y' => $y - $d1 + $d2)); - $this->_canvas->addVertex(array('x' => $x - $d1 + $d2, 'y' => $y - $d1 - $d2)); - $this->_canvas->addVertex(array('x' => $x, 'y' => $y - 2 * $d2)); - $this->_canvas->addVertex(array('x' => $x + $d1 - $d2, 'y' => $y - $d1 - $d2)); - $this->_canvas->addVertex(array('x' => $x + $d1 + $d2, 'y' => $y - $d1 + $d2)); - $this->_canvas->addVertex(array('x' => $x + 2 * $d2, 'y' => $y)); - $this->_canvas->addVertex(array('x' => $x + $d1 + $d2, 'y' => $y + $d1 - $d2)); - $this->_canvas->addVertex(array('x' => $x + $d1 - $d2, 'y' => $y + $d1 + $d2)); - $this->_canvas->addVertex(array('x' => $x, 'y' => $y + 2 * $d2)); - $this->_canvas->addVertex(array('x' => $x - $d1 + $d2, 'y' => $y + $d1 + $d2)); - $this->_canvas->addVertex(array('x' => $x - $d1 - $d2, 'y' => $y + $d1 - $d2)); - $this->_canvas->addVertex(array('x' => $x - 2 * $d2, 'y' => $y)); - $this->_canvas->polygon(array('connect' => true)); - } else { - $this->_getLineStyle(); - $this->_canvas->line( - array( - 'x0' => $x - $this->_size, - 'y0' => $y - $this->_size, - 'x1' => $x + $this->_size, - 'y1' => $y + $this->_size - ) - ); - - $this->_getLineStyle(); - $this->_canvas->line( - array( - 'x0' => $x + $this->_size, - 'y0' => $y - $this->_size, - 'x1' => $x - $this->_size, - 'y1' => $y + $this->_size - ) - ); - } - parent::_drawMarker($x, $y, $values); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Cross.php,v 1.7 2005/08/03 21:21:55 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * Data marker as a cross. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Marker_Cross extends Image_Graph_Marker +{ + + /** + * The thickness of the plus in pixels (thickness is actually double this) + * @var int + * @access private + */ + var $_thickness = 2; + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the canvas + * @param array $values The values representing the data the marker 'points' to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + if ($this->_thickness > 0) { + $this->_getLineStyle(); + $this->_getFillStyle(); + + $d1 = round(0.7071067 * $this->_size); // cos/sin(45 de>) + $d2 = round(0.7071067 * $this->_thickness); // cos/sin(45 deg) + + $this->_canvas->addVertex(array('x' => $x - $d1 - $d2, 'y' => $y - $d1 + $d2)); + $this->_canvas->addVertex(array('x' => $x - $d1 + $d2, 'y' => $y - $d1 - $d2)); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y - 2 * $d2)); + $this->_canvas->addVertex(array('x' => $x + $d1 - $d2, 'y' => $y - $d1 - $d2)); + $this->_canvas->addVertex(array('x' => $x + $d1 + $d2, 'y' => $y - $d1 + $d2)); + $this->_canvas->addVertex(array('x' => $x + 2 * $d2, 'y' => $y)); + $this->_canvas->addVertex(array('x' => $x + $d1 + $d2, 'y' => $y + $d1 - $d2)); + $this->_canvas->addVertex(array('x' => $x + $d1 - $d2, 'y' => $y + $d1 + $d2)); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y + 2 * $d2)); + $this->_canvas->addVertex(array('x' => $x - $d1 + $d2, 'y' => $y + $d1 + $d2)); + $this->_canvas->addVertex(array('x' => $x - $d1 - $d2, 'y' => $y + $d1 - $d2)); + $this->_canvas->addVertex(array('x' => $x - 2 * $d2, 'y' => $y)); + $this->_canvas->polygon(array('connect' => true)); + } else { + $this->_getLineStyle(); + $this->_canvas->line( + array( + 'x0' => $x - $this->_size, + 'y0' => $y - $this->_size, + 'x1' => $x + $this->_size, + 'y1' => $y + $this->_size + ) + ); + + $this->_getLineStyle(); + $this->_canvas->line( + array( + 'x0' => $x + $this->_size, + 'y0' => $y - $this->_size, + 'x1' => $x - $this->_size, + 'y1' => $y + $this->_size + ) + ); + } + parent::_drawMarker($x, $y, $values); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Marker/Diamond.php b/includes/pear/Image/Graph/Marker/Diamond.php index b1301e06..96ded5e6 100644 --- a/includes/pear/Image/Graph/Marker/Diamond.php +++ b/includes/pear/Image/Graph/Marker/Diamond.php @@ -1,73 +1,73 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Diamond.php,v 1.6 2005/08/03 21:21:55 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Marker.php - */ -require_once 'Image/Graph/Marker.php'; - -/** - * Data marker as a diamond. - * - * @category Images - * @package Image_Graph - * @subpackage Marker - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Marker_Diamond extends Image_Graph_Marker -{ - - /** - * Draw the marker on the canvas - * - * @param int $x The X (horizontal) position (in pixels) of the marker on the canvas - * @param int $y The Y (vertical) position (in pixels) of the marker on the canvas - * @param array $values The values representing the data the marker 'points' to - * @access private - */ - function _drawMarker($x, $y, $values = false) - { - $this->_getFillStyle(); - $this->_getLineStyle(); - $this->_canvas->addVertex(array('x' => $x - $this->_size, 'y' => $y)); - $this->_canvas->addVertex(array('x' => $x, 'y' => $y - $this->_size)); - $this->_canvas->addVertex(array('x' => $x + $this->_size, 'y' => $y)); - $this->_canvas->addVertex(array('x' => $x, 'y' => $y + $this->_size)); - $this->_canvas->polygon(array('connect' => true)); - parent::_drawMarker($x, $y, $values); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Diamond.php,v 1.6 2005/08/03 21:21:55 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * Data marker as a diamond. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Marker_Diamond extends Image_Graph_Marker +{ + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the canvas + * @param array $values The values representing the data the marker 'points' to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + $this->_getFillStyle(); + $this->_getLineStyle(); + $this->_canvas->addVertex(array('x' => $x - $this->_size, 'y' => $y)); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y - $this->_size)); + $this->_canvas->addVertex(array('x' => $x + $this->_size, 'y' => $y)); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y + $this->_size)); + $this->_canvas->polygon(array('connect' => true)); + parent::_drawMarker($x, $y, $values); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Marker/Icon.php b/includes/pear/Image/Graph/Marker/Icon.php index b8d27b2f..0765942f 100644 --- a/includes/pear/Image/Graph/Marker/Icon.php +++ b/includes/pear/Image/Graph/Marker/Icon.php @@ -1,133 +1,133 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Icon.php,v 1.8 2005/08/24 20:35:53 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Marker.php - */ -require_once 'Image/Graph/Marker.php'; - -/** - * Data marker using an image as icon. - * - * @category Images - * @package Image_Graph - * @subpackage Marker - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Marker_Icon extends Image_Graph_Marker -{ - - /** - * Filename of the image icon - * @var string - * @access private - */ - var $_filename; - - /** - * X Point of the icon to use as data 'center' - * @var int - * @access private - */ - var $_pointX = 0; - - /** - * Y Point of the icon to use as data 'center' - * @var int - * @access private - */ - var $_pointY = 0; - - /** - * Create an icon marker - * - * @param string $filename The filename of the icon - * @param int $width The 'new' width of the icon if it is to be resized - * @param int $height The 'new' height of the icon if it is to be resized - */ - function Image_Graph_Marker_Icon($filename, $width = 0, $height = 0) - { - parent::Image_Graph_Marker(); - $this->_filename = $filename; - } - - /** - * Set the X 'center' point of the marker - * - * @param int $x The X 'center' point of the marker - */ - function setPointX($x) - { - $this->_pointX = $x; - } - - /** - * Set the Y 'center' point of the marker - * - * @param int $y The Y 'center' point of the marker - */ - function setPointY($y) - { - $this->_pointY = $y; - } - - /** - * Draw the marker on the canvas - * - * @param int $x The X (horizontal) position (in pixels) of the marker on - * the canvas - * @param int $y The Y (vertical) position (in pixels) of the marker on the - * canvas - * @param array $values The values representing the data the marker 'points' - * to - * @access private - */ - function _drawMarker($x, $y, $values = false) - { - parent::_drawMarker($x, $y, $values); - if ($this->_filename) { - $this->_canvas->image( - array( - 'x' => $x, - 'y' => $y, - 'filename' => $this->_filename, - 'alignment' => array('horizontal' => 'center', 'vertical' => 'center') - ) - ); - } - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Icon.php,v 1.8 2005/08/24 20:35:53 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * Data marker using an image as icon. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Marker_Icon extends Image_Graph_Marker +{ + + /** + * Filename of the image icon + * @var string + * @access private + */ + var $_filename; + + /** + * X Point of the icon to use as data 'center' + * @var int + * @access private + */ + var $_pointX = 0; + + /** + * Y Point of the icon to use as data 'center' + * @var int + * @access private + */ + var $_pointY = 0; + + /** + * Create an icon marker + * + * @param string $filename The filename of the icon + * @param int $width The 'new' width of the icon if it is to be resized + * @param int $height The 'new' height of the icon if it is to be resized + */ + function Image_Graph_Marker_Icon($filename, $width = 0, $height = 0) + { + parent::Image_Graph_Marker(); + $this->_filename = $filename; + } + + /** + * Set the X 'center' point of the marker + * + * @param int $x The X 'center' point of the marker + */ + function setPointX($x) + { + $this->_pointX = $x; + } + + /** + * Set the Y 'center' point of the marker + * + * @param int $y The Y 'center' point of the marker + */ + function setPointY($y) + { + $this->_pointY = $y; + } + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + parent::_drawMarker($x, $y, $values); + if ($this->_filename) { + $this->_canvas->image( + array( + 'x' => $x, + 'y' => $y, + 'filename' => $this->_filename, + 'alignment' => array('horizontal' => 'center', 'vertical' => 'center') + ) + ); + } + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Marker/Pinpoint.php b/includes/pear/Image/Graph/Marker/Pinpoint.php index 010a3416..f9784872 100644 --- a/includes/pear/Image/Graph/Marker/Pinpoint.php +++ b/includes/pear/Image/Graph/Marker/Pinpoint.php @@ -1,65 +1,65 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Pinpoint.php,v 1.5 2005/08/24 20:35:53 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Marker/Icon.php - */ -require_once 'Image/Graph/Marker/Icon.php'; - -/** - * Data marker using a pinpoint as marker. - * - * @category Images - * @package Image_Graph - * @subpackage Marker - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Marker_Pinpoint extends Image_Graph_Marker_Icon -{ - - /** - * Create the marker as a pin point - */ - function Image_Graph_Marker_Pinpoint() - { - parent::Image_Graph_Marker_Icon( - dirname(__FILE__).'/../Images/Icons/pinpoint.png' - ); - $this->setPointX(0); - $this->setPointY(13); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Pinpoint.php,v 1.5 2005/08/24 20:35:53 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker/Icon.php + */ +require_once 'Image/Graph/Marker/Icon.php'; + +/** + * Data marker using a pinpoint as marker. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Marker_Pinpoint extends Image_Graph_Marker_Icon +{ + + /** + * Create the marker as a pin point + */ + function Image_Graph_Marker_Pinpoint() + { + parent::Image_Graph_Marker_Icon( + dirname(__FILE__).'/../Images/Icons/pinpoint.png' + ); + $this->setPointX(0); + $this->setPointY(13); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Marker/Plus.php b/includes/pear/Image/Graph/Marker/Plus.php index 2909438d..3c3fb7a6 100644 --- a/includes/pear/Image/Graph/Marker/Plus.php +++ b/includes/pear/Image/Graph/Marker/Plus.php @@ -1,98 +1,98 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Plus.php,v 1.7 2005/08/03 21:21:54 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Marker.php - */ -require_once 'Image/Graph/Marker.php'; - -/** - * Data marker as a plus. - * - * @category Images - * @package Image_Graph - * @subpackage Marker - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Marker_Plus extends Image_Graph_Marker -{ - - /** - * The thickness of the plus in pixels (thickness is actually double this) - * @var int - * @access private - */ - var $_thickness = 2; - - /** - * Draw the marker on the canvas - * - * @param int $x The X (horizontal) position (in pixels) of the marker on - * the canvas - * @param int $y The Y (vertical) position (in pixels) of the marker on the - * canvas - * @param array $values The values representing the data the marker 'points' - * to - * @access private - */ - function _drawMarker($x, $y, $values = false) - { - if ($this->_thickness > 0) { - $this->_getLineStyle(); - $this->_getFillStyle(); - $this->_canvas->addVertex(array('x' => $x - $this->_size, 'y' => $y - $this->_thickness)); - $this->_canvas->addVertex(array('x' => $x - $this->_thickness, 'y' => $y - $this->_thickness)); - $this->_canvas->addVertex(array('x' => $x - $this->_thickness, 'y' => $y - $this->_size)); - $this->_canvas->addVertex(array('x' => $x + $this->_thickness, 'y' => $y - $this->_size)); - $this->_canvas->addVertex(array('x' => $x + $this->_thickness, 'y' => $y - $this->_thickness)); - $this->_canvas->addVertex(array('x' => $x + $this->_size, 'y' => $y - $this->_thickness)); - $this->_canvas->addVertex(array('x' => $x + $this->_size, 'y' => $y + $this->_thickness)); - $this->_canvas->addVertex(array('x' => $x + $this->_thickness, 'y' => $y + $this->_thickness)); - $this->_canvas->addVertex(array('x' => $x + $this->_thickness, 'y' => $y + $this->_size)); - $this->_canvas->addVertex(array('x' => $x - $this->_thickness, 'y' => $y + $this->_size)); - $this->_canvas->addVertex(array('x' => $x - $this->_thickness, 'y' => $y + $this->_thickness)); - $this->_canvas->addVertex(array('x' => $x - $this->_size, 'y' => $y + $this->_thickness)); - $this->_canvas->polygon(array('connect' => true)); - } else { - $this->_getLineStyle(); - $this->_canvas->line(array('x0' => $x - $this->_size, 'y0' => $y, 'x1' => $x + $this->_size, 'y1' => $y)); - $this->_getLineStyle(); - $this->_canvas->line(array('x0' => $x, 'y0' => $y - $this->_size, 'x1' => $x, 'y1' => $y + $this->_size)); - } - parent::_drawMarker($x, $y, $values); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Plus.php,v 1.7 2005/08/03 21:21:54 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * Data marker as a plus. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Marker_Plus extends Image_Graph_Marker +{ + + /** + * The thickness of the plus in pixels (thickness is actually double this) + * @var int + * @access private + */ + var $_thickness = 2; + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + if ($this->_thickness > 0) { + $this->_getLineStyle(); + $this->_getFillStyle(); + $this->_canvas->addVertex(array('x' => $x - $this->_size, 'y' => $y - $this->_thickness)); + $this->_canvas->addVertex(array('x' => $x - $this->_thickness, 'y' => $y - $this->_thickness)); + $this->_canvas->addVertex(array('x' => $x - $this->_thickness, 'y' => $y - $this->_size)); + $this->_canvas->addVertex(array('x' => $x + $this->_thickness, 'y' => $y - $this->_size)); + $this->_canvas->addVertex(array('x' => $x + $this->_thickness, 'y' => $y - $this->_thickness)); + $this->_canvas->addVertex(array('x' => $x + $this->_size, 'y' => $y - $this->_thickness)); + $this->_canvas->addVertex(array('x' => $x + $this->_size, 'y' => $y + $this->_thickness)); + $this->_canvas->addVertex(array('x' => $x + $this->_thickness, 'y' => $y + $this->_thickness)); + $this->_canvas->addVertex(array('x' => $x + $this->_thickness, 'y' => $y + $this->_size)); + $this->_canvas->addVertex(array('x' => $x - $this->_thickness, 'y' => $y + $this->_size)); + $this->_canvas->addVertex(array('x' => $x - $this->_thickness, 'y' => $y + $this->_thickness)); + $this->_canvas->addVertex(array('x' => $x - $this->_size, 'y' => $y + $this->_thickness)); + $this->_canvas->polygon(array('connect' => true)); + } else { + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x - $this->_size, 'y0' => $y, 'x1' => $x + $this->_size, 'y1' => $y)); + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x, 'y0' => $y - $this->_size, 'x1' => $x, 'y1' => $y + $this->_size)); + } + parent::_drawMarker($x, $y, $values); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Marker/Pointing.php b/includes/pear/Image/Graph/Marker/Pointing.php index f3975953..3a0d78e2 100644 --- a/includes/pear/Image/Graph/Marker/Pointing.php +++ b/includes/pear/Image/Graph/Marker/Pointing.php @@ -1,140 +1,140 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Pointing.php,v 1.8 2005/08/24 20:35:54 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Marker.php - */ -require_once 'Image/Graph/Marker.php'; - -/** - * Data marker as a 'pointing marker'. - * - * Points to the data using another marker (as start and/or end) - * - * @category Images - * @package Image_Graph - * @subpackage Marker - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Marker_Pointing extends Image_Graph_Marker -{ - - /** - * The starting marker - * @var Marker - * @access private - */ - var $_markerStart; - - /** - * The ending marker - * @var Marker - * @access private - */ - var $_markerEnd; - - /** - * The X offset from the 'data' - * @var int - * @access private - */ - var $_deltaX = -1; - - /** - * The Y offset from the 'data' - * @var int - * @access private - */ - var $_deltaY = -1; - - /** - * Create an pointing marker, ie a pin on a board - * - * @param int $deltaX The the X offset from the real 'data' point - * @param int $deltaY The the Y offset from the real 'data' point - * @param Marker $markerEnd The ending marker that represents 'the head of - * the pin' - */ - function Image_Graph_Marker_Pointing($deltaX, $deltaY, & $markerEnd) - { - parent::Image_Graph_Marker(); - $this->_deltaX = $deltaX; - $this->_deltaY = $deltaY; - $this->_markerStart = null; - $this->_markerEnd =& $markerEnd; - } - - /** - * Sets the starting marker, ie the tip of the pin on a board - * - * @param Marker $markerStart The starting marker that represents 'the tip - * of the pin' - */ - function setMarkerStart(& $markerStart) - { - $this->_markerStart =& $markerStart; - $this->_markerStart->_setParent($this); - } - - /** - * Draw the marker on the canvas - * - * @param int $x The X (horizontal) position (in pixels) of the marker on - * the canvas - * @param int $y The Y (vertical) position (in pixels) of the marker on the - * canvas - * @param array $values The values representing the data the marker 'points' - * to - * @access private - */ - function _drawMarker($x, $y, $values = false) - { - parent::_drawMarker($x, $y, $values); - if ($this->_markerStart) { - $this->_markerStart->_setParent($this); - $this->_markerStart->_drawMarker($x, $y, $values); - } - $this->_getLineStyle(); - $this->_canvas->line(array('x0' => $x, 'y0' => $y, 'x1' => $x + $this->_deltaX, 'y1' => $y + $this->_deltaY)); - $this->_markerEnd->_setParent($this); - $this->_markerEnd->_drawMarker( - $x + $this->_deltaX, - $y + $this->_deltaY, - $values - ); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Pointing.php,v 1.8 2005/08/24 20:35:54 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * Data marker as a 'pointing marker'. + * + * Points to the data using another marker (as start and/or end) + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Marker_Pointing extends Image_Graph_Marker +{ + + /** + * The starting marker + * @var Marker + * @access private + */ + var $_markerStart; + + /** + * The ending marker + * @var Marker + * @access private + */ + var $_markerEnd; + + /** + * The X offset from the 'data' + * @var int + * @access private + */ + var $_deltaX = -1; + + /** + * The Y offset from the 'data' + * @var int + * @access private + */ + var $_deltaY = -1; + + /** + * Create an pointing marker, ie a pin on a board + * + * @param int $deltaX The the X offset from the real 'data' point + * @param int $deltaY The the Y offset from the real 'data' point + * @param Marker $markerEnd The ending marker that represents 'the head of + * the pin' + */ + function Image_Graph_Marker_Pointing($deltaX, $deltaY, & $markerEnd) + { + parent::Image_Graph_Marker(); + $this->_deltaX = $deltaX; + $this->_deltaY = $deltaY; + $this->_markerStart = null; + $this->_markerEnd =& $markerEnd; + } + + /** + * Sets the starting marker, ie the tip of the pin on a board + * + * @param Marker $markerStart The starting marker that represents 'the tip + * of the pin' + */ + function setMarkerStart(& $markerStart) + { + $this->_markerStart =& $markerStart; + $this->_markerStart->_setParent($this); + } + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + parent::_drawMarker($x, $y, $values); + if ($this->_markerStart) { + $this->_markerStart->_setParent($this); + $this->_markerStart->_drawMarker($x, $y, $values); + } + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x, 'y0' => $y, 'x1' => $x + $this->_deltaX, 'y1' => $y + $this->_deltaY)); + $this->_markerEnd->_setParent($this); + $this->_markerEnd->_drawMarker( + $x + $this->_deltaX, + $y + $this->_deltaY, + $values + ); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Marker/Pointing/Angular.php b/includes/pear/Image/Graph/Marker/Pointing/Angular.php index 327974bb..c12969bf 100644 --- a/includes/pear/Image/Graph/Marker/Pointing/Angular.php +++ b/includes/pear/Image/Graph/Marker/Pointing/Angular.php @@ -1,105 +1,105 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Angular.php,v 1.5 2005/08/24 20:36:03 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Marker/Pointing.php - */ -require_once 'Image/Graph/Marker/Pointing.php'; - -/** - * Marker that points 'away' from the graph. - * - * Use this as a marker for displaying another marker pointing to the original - * point on the graph - where the 'pointer' is calculated as line orthogonal to - * a line drawn between the points neighbours to both sides (an approximate - * tangent). This should make an the pointer appear to point 'straight' out from - * the graph. The 'head' of the pointer is then another marker of any choice. - * - * @category Images - * @package Image_Graph - * @subpackage Marker - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Marker_Pointing_Angular extends Image_Graph_Marker_Pointing -{ - - /** - * The length of the angular marker - * @var int - * @access private - */ - var $_radius; - - /** - * Image_Graph_AngularPointingMarker [Constructor] - * @param int $radius The 'length' of the pointer - * @param Marker $markerEnd The ending marker that represents 'the head of - * the pin' - */ - function Image_Graph_Marker_Pointing_Angular($radius, & $markerEnd) - { - parent::Image_Graph_Marker_Pointing(0, 0, $markerEnd); - $this->_radius = $radius; - } - - /** - * Draw the marker on the canvas - * @param int $x The X (horizontal) position (in pixels) of the marker on - * the canvas - * @param int $y The Y (vertical) position (in pixels) of the marker on the - * canvas - * @param array $values The values representing the data the marker 'points' - * to - * @access private - */ - function _drawMarker($x, $y, $values = false) - { - if ((isset($values['LENGTH'])) && ($values['LENGTH'] != 0)) { - $this->_deltaX = - $values['AX'] * $this->_radius / $values['LENGTH']; - $this->_deltaY = - $values['AY'] * $this->_radius / $values['LENGTH']; - } - - if ((isset($values['NPY'])) && (isset($values['APY'])) && - (isset($values['PPY'])) && ($values['NPY'] > $values['APY']) && - ($values['PPY'] > $values['APY'])) - { - $this->_deltaX = - $this->_deltaX; - $this->_deltaY = - $this->_deltaY; - } - parent::_drawMarker($x, $y, $values); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Angular.php,v 1.5 2005/08/24 20:36:03 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker/Pointing.php + */ +require_once 'Image/Graph/Marker/Pointing.php'; + +/** + * Marker that points 'away' from the graph. + * + * Use this as a marker for displaying another marker pointing to the original + * point on the graph - where the 'pointer' is calculated as line orthogonal to + * a line drawn between the points neighbours to both sides (an approximate + * tangent). This should make an the pointer appear to point 'straight' out from + * the graph. The 'head' of the pointer is then another marker of any choice. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Marker_Pointing_Angular extends Image_Graph_Marker_Pointing +{ + + /** + * The length of the angular marker + * @var int + * @access private + */ + var $_radius; + + /** + * Image_Graph_AngularPointingMarker [Constructor] + * @param int $radius The 'length' of the pointer + * @param Marker $markerEnd The ending marker that represents 'the head of + * the pin' + */ + function Image_Graph_Marker_Pointing_Angular($radius, & $markerEnd) + { + parent::Image_Graph_Marker_Pointing(0, 0, $markerEnd); + $this->_radius = $radius; + } + + /** + * Draw the marker on the canvas + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + if ((isset($values['LENGTH'])) && ($values['LENGTH'] != 0)) { + $this->_deltaX = - $values['AX'] * $this->_radius / $values['LENGTH']; + $this->_deltaY = - $values['AY'] * $this->_radius / $values['LENGTH']; + } + + if ((isset($values['NPY'])) && (isset($values['APY'])) && + (isset($values['PPY'])) && ($values['NPY'] > $values['APY']) && + ($values['PPY'] > $values['APY'])) + { + $this->_deltaX = - $this->_deltaX; + $this->_deltaY = - $this->_deltaY; + } + parent::_drawMarker($x, $y, $values); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Marker/Pointing/Radial.php b/includes/pear/Image/Graph/Marker/Pointing/Radial.php index 391de831..185afa51 100644 --- a/includes/pear/Image/Graph/Marker/Pointing/Radial.php +++ b/includes/pear/Image/Graph/Marker/Pointing/Radial.php @@ -1,91 +1,91 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Radial.php,v 1.5 2005/08/24 20:36:03 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Marker/Pointing.php - */ -require_once 'Image/Graph/Marker/Pointing.php'; - -/** - * A pointing marker in a random angle from the data - * - * @category Images - * @package Image_Graph - * @subpackage Marker - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Marker_Pointing_Radial extends Image_Graph_Marker_Pointing -{ - - /** - * The radius of the radial marker - * @var int - * @access private - */ - var $_radius; - - /** - * Create an radial pointing marker, ie a marker on a defined distance from - * the data - * @param int $radius The 'length' of the pointer - * @param Marker $markerEnd The ending marker that represents 'the head of - * the pin' - */ - function Image_Graph_Marker_Pointing_Radial($radius, & $markerEnd) - { - parent::Image_Graph_Marker_Pointing(0, 0, $markerEnd); - $this->_radius = $radius; - } - - /** - * Draw the marker on the canvas - * @param int $x The X (horizontal) position (in pixels) of the marker on - * the canvas - * @param int $y The Y (vertical) position (in pixels) of the marker on the - * canvas - * @param array $values The values representing the data the marker 'points' - * to - * @access private - */ - function _drawMarker($x, $y, $values = false) - { - $angle = pi() * rand(0, 360) / 180; - $this->_deltaX = $this->_radius * cos($angle); - $this->_deltaY = $this->_radius * sin($angle); - parent::_drawMarker($x, $y, $values); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Radial.php,v 1.5 2005/08/24 20:36:03 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker/Pointing.php + */ +require_once 'Image/Graph/Marker/Pointing.php'; + +/** + * A pointing marker in a random angle from the data + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Marker_Pointing_Radial extends Image_Graph_Marker_Pointing +{ + + /** + * The radius of the radial marker + * @var int + * @access private + */ + var $_radius; + + /** + * Create an radial pointing marker, ie a marker on a defined distance from + * the data + * @param int $radius The 'length' of the pointer + * @param Marker $markerEnd The ending marker that represents 'the head of + * the pin' + */ + function Image_Graph_Marker_Pointing_Radial($radius, & $markerEnd) + { + parent::Image_Graph_Marker_Pointing(0, 0, $markerEnd); + $this->_radius = $radius; + } + + /** + * Draw the marker on the canvas + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + $angle = pi() * rand(0, 360) / 180; + $this->_deltaX = $this->_radius * cos($angle); + $this->_deltaY = $this->_radius * sin($angle); + parent::_drawMarker($x, $y, $values); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Marker/ReversePinpoint.php b/includes/pear/Image/Graph/Marker/ReversePinpoint.php index 5adaef44..d8d51efb 100644 --- a/includes/pear/Image/Graph/Marker/ReversePinpoint.php +++ b/includes/pear/Image/Graph/Marker/ReversePinpoint.php @@ -1,65 +1,65 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: ReversePinpoint.php,v 1.5 2005/08/24 20:35:53 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Marker/Icon.php - */ -require_once 'Image/Graph/Marker/Icon.php'; - -/** - * Data marker using a (reverse) pinpoint as marker. - * - * @category Images - * @package Image_Graph - * @subpackage Marker - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Marker_ReversePinpoint extends Image_Graph_Marker_Icon -{ - - /** - * Create the marker as a reverse pin point - */ - function Image_Graph_Marker_ReversePinpoint() - { - parent::Image_Graph_Marker_Icon( - dirname(__FILE__).'/../Images/Icons/pinpointr.png' - ); - $this->setPointX(10); - $this->setPointY(13); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: ReversePinpoint.php,v 1.5 2005/08/24 20:35:53 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker/Icon.php + */ +require_once 'Image/Graph/Marker/Icon.php'; + +/** + * Data marker using a (reverse) pinpoint as marker. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Marker_ReversePinpoint extends Image_Graph_Marker_Icon +{ + + /** + * Create the marker as a reverse pin point + */ + function Image_Graph_Marker_ReversePinpoint() + { + parent::Image_Graph_Marker_Icon( + dirname(__FILE__).'/../Images/Icons/pinpointr.png' + ); + $this->setPointX(10); + $this->setPointY(13); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Marker/Star.php b/includes/pear/Image/Graph/Marker/Star.php index 773cd927..2ce4a35d 100644 --- a/includes/pear/Image/Graph/Marker/Star.php +++ b/includes/pear/Image/Graph/Marker/Star.php @@ -1,88 +1,88 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Star.php,v 1.2 2005/08/03 21:21:54 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Marker.php - */ -require_once 'Image/Graph/Marker.php'; - -/** - * Data marker as a triangle. - * - * @category Images - * @package Image_Graph - * @subpackage Marker - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Marker_Star extends Image_Graph_Marker -{ - - /** - * Draw the marker on the canvas - * - * @param int $x The X (horizontal) position (in pixels) of the marker on - * the canvas - * @param int $y The Y (vertical) position (in pixels) of the marker on the - * canvas - * @param array $values The values representing the data the marker 'points' - * to - * @access private - */ - function _drawMarker($x, $y, $values = false) - { - $this->_getFillStyle(); - $this->_getLineStyle(); - - $d = $this->_size / 5; - $x = round($x); - $y = round($y); - - $this->_canvas->addVertex(array('x' => $x, 'y' => $y - $this->_size)); - $this->_canvas->addVertex(array('x' => $x + round($d), 'y' => $y - round($d))); - $this->_canvas->addVertex(array('x' => $x + $this->_size, 'y' => $y - round($d))); - $this->_canvas->addVertex(array('x' => $x + round(2 * $d), 'y' => $y + round($d))); - $this->_canvas->addVertex(array('x' => $x + round(3 * $d), 'y' => $y + $this->_size)); - $this->_canvas->addVertex(array('x' => $x, 'y' => $y + round(3 * $d))); - $this->_canvas->addVertex(array('x' => $x - round(3 * $d), 'y' => $y + $this->_size)); - $this->_canvas->addVertex(array('x' => $x - round(2 * $d), 'y' => $y + round($d))); - $this->_canvas->addVertex(array('x' => $x - $this->_size, 'y' => $y - round($d))); - $this->_canvas->addVertex(array('x' => $x - round($d), 'y' => $y - round($d))); - $this->_canvas->polygon(array('connect' => true)); - - parent::_drawMarker($x, $y, $values); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Star.php,v 1.2 2005/08/03 21:21:54 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * Data marker as a triangle. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Marker_Star extends Image_Graph_Marker +{ + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + $this->_getFillStyle(); + $this->_getLineStyle(); + + $d = $this->_size / 5; + $x = round($x); + $y = round($y); + + $this->_canvas->addVertex(array('x' => $x, 'y' => $y - $this->_size)); + $this->_canvas->addVertex(array('x' => $x + round($d), 'y' => $y - round($d))); + $this->_canvas->addVertex(array('x' => $x + $this->_size, 'y' => $y - round($d))); + $this->_canvas->addVertex(array('x' => $x + round(2 * $d), 'y' => $y + round($d))); + $this->_canvas->addVertex(array('x' => $x + round(3 * $d), 'y' => $y + $this->_size)); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y + round(3 * $d))); + $this->_canvas->addVertex(array('x' => $x - round(3 * $d), 'y' => $y + $this->_size)); + $this->_canvas->addVertex(array('x' => $x - round(2 * $d), 'y' => $y + round($d))); + $this->_canvas->addVertex(array('x' => $x - $this->_size, 'y' => $y - round($d))); + $this->_canvas->addVertex(array('x' => $x - round($d), 'y' => $y - round($d))); + $this->_canvas->polygon(array('connect' => true)); + + parent::_drawMarker($x, $y, $values); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Marker/Triangle.php b/includes/pear/Image/Graph/Marker/Triangle.php index 2e64912f..b40226f9 100644 --- a/includes/pear/Image/Graph/Marker/Triangle.php +++ b/includes/pear/Image/Graph/Marker/Triangle.php @@ -1,75 +1,75 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Triangle.php,v 1.6 2005/08/03 21:21:54 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Marker.php - */ -require_once 'Image/Graph/Marker.php'; - -/** - * Data marker as a triangle. - * - * @category Images - * @package Image_Graph - * @subpackage Marker - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Marker_Triangle extends Image_Graph_Marker -{ - - /** - * Draw the marker on the canvas - * - * @param int $x The X (horizontal) position (in pixels) of the marker on - * the canvas - * @param int $y The Y (vertical) position (in pixels) of the marker on the - * canvas - * @param array $values The values representing the data the marker 'points' - * to - * @access private - */ - function _drawMarker($x, $y, $values = false) - { - $this->_getFillStyle(); - $this->_getLineStyle(); - $this->_canvas->addVertex(array('x' => $x - $this->_size, 'y' => $y + $this->_size)); - $this->_canvas->addVertex(array('x' => $x, 'y' => $y - $this->_size)); - $this->_canvas->addVertex(array('x' => $x + $this->_size, 'y' => $y + $this->_size)); - $this->_canvas->polygon(array('connect' => true)); - parent::_drawMarker($x, $y, $values); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Triangle.php,v 1.6 2005/08/03 21:21:54 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * Data marker as a triangle. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Marker_Triangle extends Image_Graph_Marker +{ + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + $this->_getFillStyle(); + $this->_getLineStyle(); + $this->_canvas->addVertex(array('x' => $x - $this->_size, 'y' => $y + $this->_size)); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y - $this->_size)); + $this->_canvas->addVertex(array('x' => $x + $this->_size, 'y' => $y + $this->_size)); + $this->_canvas->polygon(array('connect' => true)); + parent::_drawMarker($x, $y, $values); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Marker/Value.php b/includes/pear/Image/Graph/Marker/Value.php index 9a6f7e12..ad044914 100644 --- a/includes/pear/Image/Graph/Marker/Value.php +++ b/includes/pear/Image/Graph/Marker/Value.php @@ -1,214 +1,214 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Value.php,v 1.9 2005/08/24 20:35:52 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Marker.php - */ -require_once 'Image/Graph/Marker.php'; - -/** - * A marker showing the data value. - * - * @category Images - * @package Image_Graph - * @subpackage Marker - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Marker_Value extends Image_Graph_Marker -{ - - /** - * Datapreproccesor to format the value - * @var DataPreprocessor - * @access private - */ - var $_dataPreprocessor = null; - - /** - * Which value to use from the data set, ie the X or Y value - * @var int - * @access private - */ - var $_useValue; - - /** - * Create a value marker, ie a box containing the value of the 'pointing - * data' - * - * @param int $useValue Defines which value to use from the dataset, i.e. the - * X or Y value - */ - function Image_Graph_Marker_Value($useValue = IMAGE_GRAPH_VALUE_X) - { - parent::Image_Graph_Marker(); - $this->_padding = 2; - $this->_useValue = $useValue; - $this->_fillStyle = 'white'; - $this->_borderStyle = 'black'; - } - - /** - * Sets the background fill style of the element - * - * @param Image_Graph_Fill $background The background - * @see Image_Graph_Fill - */ - function setBackground(& $background) - { - $this->setFillStyle($background); - } - - /** - * Sets the background color of the element - * - * @param mixed $color The color - */ - function setBackgroundColor($color) - { - $this->setFillColor($color); - } - - /** - * Sets a data preprocessor for formatting the values - * - * @param DataPreprocessor $dataPreprocessor The data preprocessor - * @return Image_Graph_DataPreprocessor The data preprocessor - */ - function &setDataPreprocessor(& $dataPreprocessor) - { - $this->_dataPreprocessor =& $dataPreprocessor; - return $dataPreprocessor; - } - - /** - * Get the value to display - * - * @param array $values The values representing the data the marker 'points' - * to - * @return string The display value, this is the pre-preprocessor value, to - * support for customized with multiple values. i.e show 'x = y' or '(x, y)' - * @access private - */ - function _getDisplayValue($values) - { - switch ($this->_useValue) { - case IMAGE_GRAPH_VALUE_X: - $value = $values['X']; - break; - - case IMAGE_GRAPH_PCT_X_MIN: - $value = $values['PCT_MIN_X']; - break; - - case IMAGE_GRAPH_PCT_X_MAX: - $value = $values['PCT_MAX_X']; - break; - - case IMAGE_GRAPH_PCT_Y_MIN: - $value = $values['PCT_MIN_Y']; - break; - - case IMAGE_GRAPH_PCT_Y_MAX: - $value = $values['PCT_MAX_Y']; - break; - - case IMAGE_GRAPH_PCT_Y_TOTAL: - if (isset($values['SUM_Y'])) { - $value = 100 * $values['Y'] / $values['SUM_Y']; - } - else { - $value = 0; - } - break; - - case IMAGE_GRAPH_POINT_ID: - $value = $values['ID']; - break; - - default: - $value = $values['Y']; - break; - } - return $value; - } - - /** - * Draw the marker on the canvas - * - * @param int $x The X (horizontal) position (in pixels) of the marker on - * the canvas - * @param int $y The Y (vertical) position (in pixels) of the marker on the - * canvas - * @param array $values The values representing the data the marker 'points' - * to - * @access private - */ - function _drawMarker($x, $y, $values = false) - { - parent::_drawMarker($x, $y, $values); - - $value = $this->_getDisplayValue($values); - - if ($this->_dataPreprocessor) { - $value = $this->_dataPreprocessor->_process($value); - } - - if ($this->_defaultFontOptions !== false) { - $this->_canvas->setFont($this->_defaultFontOptions); - } else { - $this->_canvas->setFont($this->_getFont()); - } - - $width = $this->_canvas->textWidth($value); - $height = $this->_canvas->textHeight($value); - $offsetX = $width/2 + $this->_padding; - $offsetY = $height/2 + $this->_padding; - - $this->_getFillStyle(); - $this->_getBorderStyle(); - $this->_canvas->rectangle( - array( - 'x0' => $x - $offsetX, - 'y0' => $y - $offsetY, - 'x1' => $x + $offsetX, - 'y1' => $y + $offsetY - ) - ); - - $this->write($x, $y, $value, IMAGE_GRAPH_ALIGN_CENTER); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Value.php,v 1.10 2006/02/28 22:48:07 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Marker.php + */ +require_once 'Image/Graph/Marker.php'; + +/** + * A marker showing the data value. + * + * @category Images + * @package Image_Graph + * @subpackage Marker + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Marker_Value extends Image_Graph_Marker +{ + + /** + * Datapreproccesor to format the value + * @var DataPreprocessor + * @access private + */ + var $_dataPreprocessor = null; + + /** + * Which value to use from the data set, ie the X or Y value + * @var int + * @access private + */ + var $_useValue; + + /** + * Create a value marker, ie a box containing the value of the 'pointing + * data' + * + * @param int $useValue Defines which value to use from the dataset, i.e. the + * X or Y value + */ + function Image_Graph_Marker_Value($useValue = IMAGE_GRAPH_VALUE_X) + { + parent::Image_Graph_Marker(); + $this->_padding = array('left' => 2, 'top' => 2, 'right' => 2, 'bottom' => 2); + $this->_useValue = $useValue; + $this->_fillStyle = 'white'; + $this->_borderStyle = 'black'; + } + + /** + * Sets the background fill style of the element + * + * @param Image_Graph_Fill $background The background + * @see Image_Graph_Fill + */ + function setBackground(& $background) + { + $this->setFillStyle($background); + } + + /** + * Sets the background color of the element + * + * @param mixed $color The color + */ + function setBackgroundColor($color) + { + $this->setFillColor($color); + } + + /** + * Sets a data preprocessor for formatting the values + * + * @param DataPreprocessor $dataPreprocessor The data preprocessor + * @return Image_Graph_DataPreprocessor The data preprocessor + */ + function &setDataPreprocessor(& $dataPreprocessor) + { + $this->_dataPreprocessor =& $dataPreprocessor; + return $dataPreprocessor; + } + + /** + * Get the value to display + * + * @param array $values The values representing the data the marker 'points' + * to + * @return string The display value, this is the pre-preprocessor value, to + * support for customized with multiple values. i.e show 'x = y' or '(x, y)' + * @access private + */ + function _getDisplayValue($values) + { + switch ($this->_useValue) { + case IMAGE_GRAPH_VALUE_X: + $value = $values['X']; + break; + + case IMAGE_GRAPH_PCT_X_MIN: + $value = $values['PCT_MIN_X']; + break; + + case IMAGE_GRAPH_PCT_X_MAX: + $value = $values['PCT_MAX_X']; + break; + + case IMAGE_GRAPH_PCT_Y_MIN: + $value = $values['PCT_MIN_Y']; + break; + + case IMAGE_GRAPH_PCT_Y_MAX: + $value = $values['PCT_MAX_Y']; + break; + + case IMAGE_GRAPH_PCT_Y_TOTAL: + if (isset($values['SUM_Y'])) { + $value = 100 * $values['Y'] / $values['SUM_Y']; + } + else { + $value = 0; + } + break; + + case IMAGE_GRAPH_POINT_ID: + $value = $values['ID']; + break; + + default: + $value = $values['Y']; + break; + } + return $value; + } + + /** + * Draw the marker on the canvas + * + * @param int $x The X (horizontal) position (in pixels) of the marker on + * the canvas + * @param int $y The Y (vertical) position (in pixels) of the marker on the + * canvas + * @param array $values The values representing the data the marker 'points' + * to + * @access private + */ + function _drawMarker($x, $y, $values = false) + { + parent::_drawMarker($x, $y, $values); + + $value = $this->_getDisplayValue($values); + + if ($this->_dataPreprocessor) { + $value = $this->_dataPreprocessor->_process($value); + } + + if ($this->_defaultFontOptions !== false) { + $this->_canvas->setFont($this->_defaultFontOptions); + } else { + $this->_canvas->setFont($this->_getFont()); + } + + $width = $this->_canvas->textWidth($value); + $height = $this->_canvas->textHeight($value); + $offsetX = $width/2 + $this->_padding['left']; + $offsetY = $height/2 + $this->_padding['top']; + + $this->_getFillStyle(); + $this->_getBorderStyle(); + $this->_canvas->rectangle( + array( + 'x0' => $x - $offsetX, + 'y0' => $y - $offsetY, + 'x1' => $x + $offsetX, + 'y1' => $y + $offsetY + ) + ); + + $this->write($x, $y, $value, IMAGE_GRAPH_ALIGN_CENTER); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Plot.php b/includes/pear/Image/Graph/Plot.php index 17dc2031..684ad057 100644 --- a/includes/pear/Image/Graph/Plot.php +++ b/includes/pear/Image/Graph/Plot.php @@ -1,818 +1,824 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Plot.php,v 1.18 2005/09/30 18:59:19 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Plotarea/Element.php - */ -require_once 'Image/Graph/Plotarea/Element.php'; - -/** - * Framework for a chart - * - * @category Images - * @package Image_Graph - * @subpackage Plot - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - * @abstract - */ -class Image_Graph_Plot extends Image_Graph_Plotarea_Element -{ - - /** - * The dataset to plot - * @var Dataset - * @access private - */ - var $_dataset; - - /** - * The marker to plot the data set as - * @var Marker - * @access private - */ - var $_marker = null; - - /** - * The dataselector to use for data marking - * @var DataSelector - * @access private - */ - var $_dataSelector = null; - - /** - * The Y axis to associate the plot with - * @var int - * @access private - */ - var $_axisY = IMAGE_GRAPH_AXIS_Y; - - /** - * The type of the plot if multiple datasets are used - * @var string - * @access private - */ - var $_multiType = 'normal'; - - /** - * The title of the plot, used for legending in case of simple plots - * @var string - * @access private - */ - var $_title = 'plot'; - - /** - * PlotType [Constructor] - * - * Valid values for multiType are: - * - * 'normal' Plot is normal, multiple datasets are displayes next to one - * another - * - * 'stacked' Datasets are stacked on top of each other - * - * 'stacked100pct' Datasets are stacked and displayed as percentages of the - * total sum - * - * I no title is specified a default is used, which is basically the plot - * type (fx. for a 'Image_Graph_Plot_Smoothed_Area' default title is - * 'Smoothed Area') - * - * @param Image_Graph_Dataset $dataset The data set (value containter) to - * plot or an array of datasets - * @param string $multiType The type of the plot - * @param string $title The title of the plot (used for legends, - * {@link Image_Graph_Legend}) - */ - function Image_Graph_Plot(& $dataset, $multiType = 'normal', $title = '') - { - if (!is_a($dataset, 'Image_Graph_Dataset')) { - if (is_array($dataset)) { - $keys = array_keys($dataset); - foreach ($keys as $key) { - if (!is_a($dataset[$key], 'Image_Graph_Dataset')) { - $this->_error('Invalid dataset passed to ' . get_class($this)); - } - } - unset($keys); - } else { - $this->_error('Invalid dataset passed to ' . get_class($this)); - } - } - - parent::Image_Graph_Common(); - if ($dataset) { - if (is_array($dataset)) { - $this->_dataset =& $dataset; - } else { - $this->_dataset = array(&$dataset); - } - } - if ($title) { - $this->_title = $title; - } else { - $this->_title = str_replace('_', ' ', substr(get_class($this), 17)); - } - - $multiType = strtolower($multiType); - if (($multiType == 'normal') || - ($multiType == 'stacked') || - ($multiType == 'stacked100pct')) - { - $this->_multiType = $multiType; - } else { - $this->_error( - 'Invalid multitype: ' . $multiType . - ' expected (normal|stacked|stacked100pct)' - ); - $this->_multiType = 'normal'; - } - } - - /** - * Sets the title of the plot, used for legend - * - * @param string $title The title of the plot - */ - function setTitle($title) - { - $this->_title = $title; - } - - /** - * Parses the URL mapping data in the point and adds it to the parameter array used by - * Image_Canvas - * - * @param array $point The data point (from the dataset) - * @param array $canvasData The The for the canvas method - * @return array The union of the canvas data points and the appropriate points for the dataset - * @access private - */ - function _mergeData($point, $canvasData) - { - if (isset($point['data'])) { - if (isset($point['data']['url'])) { - $canvasData['url'] = $point['data']['url']; - } - if (isset($point['data']['target'])) { - $canvasData['target'] = $point['data']['target']; - } - if (isset($point['data']['alt'])) { - $canvasData['alt'] = $point['data']['alt']; - } - if (isset($point['data']['htmltags'])) { - $canvasData['htmltags'] = $point['data']['htmltags']; - } - } - - return $canvasData; - } - - /** - * Sets the Y axis to plot the data - * - * @param int $axisY The Y axis (either IMAGE_GRAPH_AXIS_Y / 'y' or - * IMAGE_GRAPH_AXIS_Y_SECONDARY / 'ysec' (defaults to IMAGE_GRAPH_AXIS_Y)) - * @access private - */ - function _setAxisY($axisY) - { - if ($axisY == 'y') { - $this->_axisY = IMAGE_GRAPH_AXIS_Y; - } elseif ($axisY == 'ysec') { - $this->_axisY = IMAGE_GRAPH_AXIS_Y_SECONDARY; - } else { - $this->_axisY = $axisY; - } - } - - /** - * Sets the marker to 'display' data points on the graph - * - * @param Marker $marker The marker - */ - function &setMarker(& $marker) - { - $this->add($marker); - $this->_marker =& $marker; - return $marker; - } - - /** - * Sets the dataselector to specify which data should be displayed on the - * plot as markers and which are not - * - * @param DataSelector $dataSelector The dataselector - */ - function setDataSelector(& $dataSelector) - { - $this->_dataSelector =& $dataSelector; - } - - /** - * Calculate marker point data - * - * @param array Point The point to calculate data for - * @param array NextPoint The next point - * @param array PrevPoint The previous point - * @param array Totals The pre-calculated totals, if needed - * @return array An array containing marker point data - * @access private - */ - function _getMarkerData($point, $nextPoint, $prevPoint, & $totals) - { - if (is_array($this->_dataset)) { - if ($this->_multiType == 'stacked') { - if (!isset($totals['SUM_Y'])) { - $totals['SUM_Y'] = array(); - } - $x = $point['X']; - if (!isset($totals['SUM_Y'][$x])) { - $totals['SUM_Y'][$x] = 0; - } - } elseif ($this->_multiType == 'stacked100pct') { - $x = $point['X']; - if ($totals['TOTAL_Y'][$x] != 0) { - if (!isset($totals['SUM_Y'])) { - $totals['SUM_Y'] = array(); - } - if (!isset($totals['SUM_Y'][$x])) { - $totals['SUM_Y'][$x] = 0; - } - } - } - - if (isset($totals['ALL_SUM_Y'])) { - $point['SUM_Y'] = $totals['ALL_SUM_Y']; - } - - if (!$prevPoint) { - $point['AX'] = -5; - $point['AY'] = 5; - $point['PPX'] = 0; - $point['PPY'] = 0; - $point['NPX'] = $nextPoint['X']; - $point['NPY'] = $nextPoint['Y']; - } elseif (!$nextPoint) { - $point['AX'] = 5; - $point['AY'] = 5; - $point['PPX'] = $prevPoint['X']; - $point['PPY'] = $prevPoint['Y']; - $point['NPX'] = 0; - $point['NPY'] = 0; - } else { - $point['AX'] = $this->_pointY($prevPoint) - $this->_pointY($nextPoint); - $point['AY'] = $this->_pointX($nextPoint) - $this->_pointX($prevPoint); - $point['PPX'] = $prevPoint['X']; - $point['PPY'] = $prevPoint['Y']; - $point['NPX'] = $nextPoint['X']; - $point['NPY'] = $nextPoint['Y']; - } - - $point['APX'] = $point['X']; - $point['APY'] = $point['Y']; - - if ((isset($totals['MINIMUM_X'])) && ($totals['MINIMUM_X'] != 0)) { - $point['PCT_MIN_X'] = 100 * $point['X'] / $totals['MINIMUM_X']; - } - if ((isset($totals['MAXIMUM_X'])) && ($totals['MAXIMUM_X'] != 0)) { - $point['PCT_MAX_X'] = 100 * $point['X'] / $totals['MAXIMUM_X']; - } - - if ((isset($totals['MINIMUM_Y'])) && ($totals['MINIMUM_Y'] != 0)) { - $point['PCT_MIN_Y'] = 100 * $point['Y'] / $totals['MINIMUM_Y']; - } - if ((isset($totals['MAXIMUM_Y'])) && ($totals['MAXIMUM_Y'] != 0)) { - $point['PCT_MAX_Y'] = 100 * $point['Y'] / $totals['MAXIMUM_Y']; - } - - $point['LENGTH'] = sqrt($point['AX'] * $point['AX'] + - $point['AY'] * $point['AY']); - - if ((isset($point['LENGTH'])) && ($point['LENGTH'] != 0)) { - $point['ANGLE'] = asin($point['AY'] / $point['LENGTH']); - } - - if ((isset($point['AX'])) && ($point['AX'] > 0)) { - $point['ANGLE'] = pi() - $point['ANGLE']; - } - - if ($this->_parent->_horizontal) { - $point['MARKER_Y1'] = $this->_pointY($point) - - (isset($totals['WIDTH']) ? $totals['WIDTH'] : 0); - - $point['MARKER_Y2'] = $this->_pointY($point) + - (isset($totals['WIDTH']) ? $totals['WIDTH'] : 0); - - $point['COLUMN_WIDTH'] = abs($point['MARKER_Y2'] - - $point['MARKER_Y1']) / count($this->_dataset); - - $point['MARKER_Y'] = $point['MARKER_Y1'] + - ((isset($totals['NUMBER']) ? $totals['NUMBER'] : 0) + 0.5) * - $point['COLUMN_WIDTH']; - - $point['MARKER_X'] = $this->_pointX($point); - - if ($this->_multiType == 'stacked') { - $point['MARKER_Y'] = - ($point['MARKER_Y1'] + $point['MARKER_Y2']) / 2; - - $P1 = array('Y' => $totals['SUM_Y'][$x]); - $P2 = array('Y' => $totals['SUM_Y'][$x] + $point['Y']); - - $point['MARKER_X'] = - ($this->_pointX($P1) + $this->_pointX($P2)) / 2; - } elseif ($this->_multiType == 'stacked100pct') { - $x = $point['X']; - if ($totals['TOTAL_Y'][$x] != 0) { - $point['MARKER_Y'] = - ($point['MARKER_Y1'] + $point['MARKER_Y2']) / 2; - - $P1 = array( - 'Y' => 100 * $totals['SUM_Y'][$x] / $totals['TOTAL_Y'][$x] - ); - - $P2 = array( - 'Y' => 100 * ($totals['SUM_Y'][$x] + $point['Y']) / $totals['TOTAL_Y'][$x] - ); - - $point['MARKER_X'] = - ($this->_pointX($P1) + $this->_pointX($P2)) / 2; - } else { - $point = false; - } - } - } - else { - $point['MARKER_X1'] = $this->_pointX($point) - - (isset($totals['WIDTH']) ? $totals['WIDTH'] : 0); - - $point['MARKER_X2'] = $this->_pointX($point) + - (isset($totals['WIDTH']) ? $totals['WIDTH'] : 0); - - $point['COLUMN_WIDTH'] = abs($point['MARKER_X2'] - - $point['MARKER_X1']) / count($this->_dataset); - - $point['MARKER_X'] = $point['MARKER_X1'] + - ((isset($totals['NUMBER']) ? $totals['NUMBER'] : 0) + 0.5) * - $point['COLUMN_WIDTH']; - - $point['MARKER_Y'] = $this->_pointY($point); - - if ($this->_multiType == 'stacked') { - $point['MARKER_X'] = - ($point['MARKER_X1'] + $point['MARKER_X2']) / 2; - - $P1 = array('Y' => $totals['SUM_Y'][$x]); - $P2 = array('Y' => $totals['SUM_Y'][$x] + $point['Y']); - - $point['MARKER_Y'] = - ($this->_pointY($P1) + $this->_pointY($P2)) / 2; - } elseif ($this->_multiType == 'stacked100pct') { - $x = $point['X']; - if ($totals['TOTAL_Y'][$x] != 0) { - $point['MARKER_X'] = - ($point['MARKER_X1'] + $point['MARKER_X2']) / 2; - - $P1 = array( - 'Y' => 100 * $totals['SUM_Y'][$x] / $totals['TOTAL_Y'][$x] - ); - - $P2 = array( - 'Y' => 100 * ($totals['SUM_Y'][$x] + $point['Y']) / $totals['TOTAL_Y'][$x] - ); - - $point['MARKER_Y'] = - ($this->_pointY($P1) + $this->_pointY($P2)) / 2; - } else { - $point = false; - } - } - } - return $point; - } - } - - /** - * Draws markers on the canvas - * - * @access private - */ - function _drawMarker() - { - if (($this->_marker) && (is_array($this->_dataset))) { - $this->_canvas->startGroup(get_class($this) . '_marker'); - - $totals = $this->_getTotals(); - $totals['WIDTH'] = $this->width() / ($this->_maximumX() + 2) / 2; - - $number = 0; - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $dataset =& $this->_dataset[$key]; - $totals['MINIMUM_X'] = $dataset->minimumX(); - $totals['MAXIMUM_X'] = $dataset->maximumX(); - $totals['MINIMUM_Y'] = $dataset->minimumY(); - $totals['MAXIMUM_Y'] = $dataset->maximumY(); - $totals['NUMBER'] = $number ++; - $dataset->_reset(); - while ($point = $dataset->_next()) { - $prevPoint = $dataset->_nearby(-2); - $nextPoint = $dataset->_nearby(); - - $x = $point['X']; - $y = $point['Y']; - if (((!is_object($this->_dataSelector)) || - ($this->_dataSelector->_select($point))) && ($point['Y'] != null)) - { - - $point = $this->_getMarkerData( - $point, - $nextPoint, - $prevPoint, - $totals - ); - - if (is_array($point)) { - $this->_marker->_drawMarker( - $point['MARKER_X'], - $point['MARKER_Y'], - $point - ); - } - } - if (!isset($totals['SUM_Y'])) { - $totals['SUM_Y'] = array(); - } - if (isset($totals['SUM_Y'][$x])) { - $totals['SUM_Y'][$x] += $y; - } else { - $totals['SUM_Y'][$x] = $y; - } - } - } - unset($keys); - $this->_canvas->endGroup(); - } - } - - /** - * Get the minimum X value from the dataset - * - * @return double The minimum X value - * @access private - */ - function _minimumX() - { - if (!is_array($this->_dataset)) { - return 0; - } - - $min = false; - if (is_array($this->_dataset)) { - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - if ($min === false) { - $min = $this->_dataset[$key]->minimumX(); - } else { - $min = min($min, $this->_dataset[$key]->minimumX()); - } - } - unset($keys); - } - return $min; - } - - /** - * Get the maximum X value from the dataset - * - * @return double The maximum X value - * @access private - */ - function _maximumX() - { - if (!is_array($this->_dataset)) { - return 0; - } - - $max = 0; - if (is_array($this->_dataset)) { - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $max = max($max, $this->_dataset[$key]->maximumX()); - } - unset($keys); - } - return $max; - } - - /** - * Get the minimum Y value from the dataset - * - * @return double The minimum Y value - * @access private - */ - function _minimumY() - { - if (!is_array($this->_dataset)) { - return 0; - } - - $min = false; - if (is_array($this->_dataset)) { - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - if ($this->_multiType == 'normal') { - if ($min === false) { - $min = $this->_dataset[$key]->minimumY(); - } else { - $min = min($min, $this->_dataset[$key]->minimumY()); - } - } else { - if ($min === false) { - $min = 0; - } - $dataset =& $this->_dataset[$key]; - $dataset->_reset(); - while ($point = $dataset->_next()) { - if ($point['Y'] < 0) { - $x = $point['X']; - if ((!isset($total)) || (!isset($total[$x]))) { - $total[$x] = $point['Y']; - } else { - $total[$x] += $point['Y']; - } - if (isset($min)) { - $min = min($min, $total[$x]); - } else { - $min = $total[$x]; - } - } - } - } - } - unset($keys); - } - return $min; - } - - /** - * Get the maximum Y value from the dataset - * - * @return double The maximum Y value - * @access private - */ - function _maximumY() - { - if ($this->_multiType == 'stacked100pct') { - return 100; - } - - $maxY = 0; - if (is_array($this->_dataset)) { - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $dataset =& $this->_dataset[$key]; - - if ($this->_multiType == 'normal') { - if (isset($maxY)) { - $maxY = max($maxY, $dataset->maximumY()); - } else { - $maxY = $dataset->maximumY(); - } - } else { - $dataset->_reset(); - while ($point = $dataset->_next()) { - if ($point['Y'] > 0) { - $x = $point['X']; - if ((!isset($total)) || (!isset($total[$x]))) { - $total[$x] = $point['Y']; - } else { - $total[$x] += $point['Y']; - } - if (isset($maxY)) { - $maxY = max($maxY, $total[$x]); - } else { - $maxY = $total[$x]; - } - } - } - } - } - unset($keys); - } - return $maxY; - } - - /** - * Get the X pixel position represented by a value - * - * @param double $point The value to get the pixel-point for - * @return double The pixel position along the axis - * @access private - */ - function _pointX($point) - { - $point['AXIS_Y'] = $this->_axisY; - return parent::_pointX($point); - } - - /** - * Get the Y pixel position represented by a value - * - * @param double $point the value to get the pixel-point for - * @return double The pixel position along the axis - * @access private - */ - function _pointY($point) - { - $point['AXIS_Y'] = $this->_axisY; - return parent::_pointY($point); - } - - /** - * Update coordinates - * - * @access private - */ - function _updateCoords() - { - $this->_setCoords($this->_parent->_plotLeft, $this->_parent->_plotTop, $this->_parent->_plotRight, $this->_parent->_plotBottom); - parent::_updateCoords(); - } - - /** - * Get the dataset - * - * @return Image_Graph_Dataset The dataset(s) - */ - function &dataset() - { - return $this->_dataset; - } - - /** - * Calulate totals - * - * @return array An associated array with the totals - * @access private - */ - function _getTotals() - { - $total = array( - 'MINIMUM_X' => $this->_minimumX(), - 'MAXIMUM_X' => $this->_maximumX(), - 'MINIMUM_Y' => $this->_minimumY(), - 'MAXIMUM_Y' => $this->_maximumY() - ); - $total['ALL_SUM_Y'] = 0; - - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $dataset =& $this->_dataset[$key]; - - $dataset->_reset(); - while ($point = $dataset->_next()) { - $x = $point['X']; - $total['ALL_SUM_Y'] += $point['Y']; - if (isset($total['TOTAL_Y'][$x])) { - $total['TOTAL_Y'][$x] += $point['Y']; - } else { - $total['TOTAL_Y'][$x] = $point['Y']; - } - if (isset($total['TOTAL_X'][$x])) { - $total['TOTAL_X'][$x] += $point['X']; - } else { - $total['TOTAL_X'][$x] = $point['X']; - } - } - } - unset($keys); - return $total; - } - - /** - * Perform the actual drawing on the legend. - * - * @param int $x0 The top-left x-coordinate - * @param int $y0 The top-left y-coordinate - * @param int $x1 The bottom-right x-coordinate - * @param int $y1 The bottom-right y-coordinate - * @access private - */ - function _drawLegendSample($x0, $y0, $x1, $y1) - { - $this->_canvas->rectangle(array('x0' => $x0, 'y0' => $y0, 'x1' => $x1, 'y1' => $y1)); - } - - /** - * Draw a sample for use with legend - * - * @param array $param The parameters for the legend - * @access private - */ - function _legendSample(&$param) - { - if (!is_array($this->_dataset)) { - return false; - } - - if (is_a($this->_fillStyle, 'Image_Graph_Fill')) { - $this->_fillStyle->_reset(); - } - - $count = 0; - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $dataset =& $this->_dataset[$key]; - $count++; - - $caption = ($dataset->_name ? $dataset->_name : $this->_title); - - $this->_canvas->setFont($param['font']); - $width = 20 + $param['width'] + $this->_canvas->textWidth($caption); - $param['maxwidth'] = max($param['maxwidth'], $width); - $x2 = $param['x'] + $width; - $y2 = $param['y'] + $param['height'] + 5; - - if ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) && ($y2 > $param['bottom'])) { - $param['y'] = $param['top']; - $param['x'] = $x2; - $y2 = $param['y'] + $param['height']; - } elseif ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) == 0) && ($x2 > $param['right'])) { - $param['x'] = $param['left']; - $param['y'] = $y2; - $x2 = $param['x'] + 20 + $param['width'] + $this->_canvas->textWidth($caption); - } - - $x = $x0 = $param['x']; - $y = $param['y']; - $y0 = $param['y']; - $x1 = $param['x'] + $param['width']; - $y1 = $param['y'] + $param['height']; - - if (!isset($param['simulate'])) { - $this->_getFillStyle($key); - $this->_getLineStyle(); - $this->_drawLegendSample($x0, $y0, $x1, $y1); - - if (($this->_marker) && ($dataset) && ($param['show_marker'])) { - $dataset->_reset(); - $point = $dataset->_next(); - $prevPoint = $dataset->_nearby(-2); - $nextPoint = $dataset->_nearby(); - - $tmp = array(); - $point = $this->_getMarkerData($point, $nextPoint, $prevPoint, $tmp); - if (is_array($point)) { - $point['MARKER_X'] = $x+$param['width']/2; - $point['MARKER_Y'] = $y; - unset ($point['AVERAGE_Y']); - $this->_marker->_drawMarker($point['MARKER_X'], $point['MARKER_Y'], $point); - } - } - $this->write($x + $param['width'] + 10, $y + $param['height'] / 2, $caption, IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, $param['font']); - } - - if (($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) { - $param['y'] = $y2; - } else { - $param['x'] = $x2; - } - } - unset($keys); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Plot.php,v 1.20 2006/02/28 22:33:00 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plotarea/Element.php + */ +require_once 'Image/Graph/Plotarea/Element.php'; + +/** + * Framework for a chart + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + * @abstract + */ +class Image_Graph_Plot extends Image_Graph_Plotarea_Element +{ + + /** + * The dataset to plot + * @var Dataset + * @access private + */ + var $_dataset; + + /** + * The marker to plot the data set as + * @var Marker + * @access private + */ + var $_marker = null; + + /** + * The dataselector to use for data marking + * @var DataSelector + * @access private + */ + var $_dataSelector = null; + + /** + * The Y axis to associate the plot with + * @var int + * @access private + */ + var $_axisY = IMAGE_GRAPH_AXIS_Y; + + /** + * The type of the plot if multiple datasets are used + * @var string + * @access private + */ + var $_multiType = 'normal'; + + /** + * The title of the plot, used for legending in case of simple plots + * @var string + * @access private + */ + var $_title = 'plot'; + + /** + * PlotType [Constructor] + * + * Valid values for multiType are: + * + * 'normal' Plot is normal, multiple datasets are displayes next to one + * another + * + * 'stacked' Datasets are stacked on top of each other + * + * 'stacked100pct' Datasets are stacked and displayed as percentages of the + * total sum + * + * I no title is specified a default is used, which is basically the plot + * type (fx. for a 'Image_Graph_Plot_Smoothed_Area' default title is + * 'Smoothed Area') + * + * @param Image_Graph_Dataset $dataset The data set (value containter) to + * plot or an array of datasets + * @param string $multiType The type of the plot + * @param string $title The title of the plot (used for legends, + * {@link Image_Graph_Legend}) + */ + function Image_Graph_Plot(& $dataset, $multiType = 'normal', $title = '') + { + if (!is_a($dataset, 'Image_Graph_Dataset')) { + if (is_array($dataset)) { + $keys = array_keys($dataset); + foreach ($keys as $key) { + if (!is_a($dataset[$key], 'Image_Graph_Dataset')) { + $this->_error('Invalid dataset passed to ' . get_class($this)); + } + } + unset($keys); + } else { + $this->_error('Invalid dataset passed to ' . get_class($this)); + } + } + + parent::Image_Graph_Common(); + if ($dataset) { + if (is_array($dataset)) { + $this->_dataset =& $dataset; + } else { + $this->_dataset = array(&$dataset); + } + } + if ($title) { + $this->_title = $title; + } else { + $this->_title = str_replace('_', ' ', substr(get_class($this), 17)); + } + + $multiType = strtolower($multiType); + if (($multiType == 'normal') || + ($multiType == 'stacked') || + ($multiType == 'stacked100pct')) + { + $this->_multiType = $multiType; + } else { + $this->_error( + 'Invalid multitype: ' . $multiType . + ' expected (normal|stacked|stacked100pct)' + ); + $this->_multiType = 'normal'; + } + } + + /** + * Sets the title of the plot, used for legend + * + * @param string $title The title of the plot + */ + function setTitle($title) + { + $this->_title = $title; + } + + /** + * Parses the URL mapping data in the point and adds it to the parameter array used by + * Image_Canvas + * + * @param array $point The data point (from the dataset) + * @param array $canvasData The The for the canvas method + * @return array The union of the canvas data points and the appropriate points for the dataset + * @access private + */ + function _mergeData($point, $canvasData) + { + if (isset($point['data'])) { + if (isset($point['data']['url'])) { + $canvasData['url'] = $point['data']['url']; + } + if (isset($point['data']['target'])) { + $canvasData['target'] = $point['data']['target']; + } + if (isset($point['data']['alt'])) { + $canvasData['alt'] = $point['data']['alt']; + } + if (isset($point['data']['htmltags'])) { + $canvasData['htmltags'] = $point['data']['htmltags']; + } + } + + return $canvasData; + } + + /** + * Sets the Y axis to plot the data + * + * @param int $axisY The Y axis (either IMAGE_GRAPH_AXIS_Y / 'y' or + * IMAGE_GRAPH_AXIS_Y_SECONDARY / 'ysec' (defaults to IMAGE_GRAPH_AXIS_Y)) + * @access private + */ + function _setAxisY($axisY) + { + if ($axisY == 'y') { + $this->_axisY = IMAGE_GRAPH_AXIS_Y; + } elseif ($axisY == 'ysec') { + $this->_axisY = IMAGE_GRAPH_AXIS_Y_SECONDARY; + } else { + $this->_axisY = $axisY; + } + } + + /** + * Sets the marker to 'display' data points on the graph + * + * @param Marker $marker The marker + */ + function &setMarker(& $marker) + { + $this->add($marker); + $this->_marker =& $marker; + return $marker; + } + + /** + * Sets the dataselector to specify which data should be displayed on the + * plot as markers and which are not + * + * @param DataSelector $dataSelector The dataselector + */ + function setDataSelector(& $dataSelector) + { + $this->_dataSelector =& $dataSelector; + } + + /** + * Calculate marker point data + * + * @param array Point The point to calculate data for + * @param array NextPoint The next point + * @param array PrevPoint The previous point + * @param array Totals The pre-calculated totals, if needed + * @return array An array containing marker point data + * @access private + */ + function _getMarkerData($point, $nextPoint, $prevPoint, & $totals) + { + if (is_array($this->_dataset)) { + if ($this->_multiType == 'stacked') { + if (!isset($totals['SUM_Y'])) { + $totals['SUM_Y'] = array(); + } + $x = $point['X']; + if (!isset($totals['SUM_Y'][$x])) { + $totals['SUM_Y'][$x] = 0; + } + } elseif ($this->_multiType == 'stacked100pct') { + $x = $point['X']; + if ($totals['TOTAL_Y'][$x] != 0) { + if (!isset($totals['SUM_Y'])) { + $totals['SUM_Y'] = array(); + } + if (!isset($totals['SUM_Y'][$x])) { + $totals['SUM_Y'][$x] = 0; + } + } + } + + if (isset($totals['ALL_SUM_Y'])) { + $point['SUM_Y'] = $totals['ALL_SUM_Y']; + } + + if (!$prevPoint) { + $point['AX'] = -5; + $point['AY'] = 5; + $point['PPX'] = 0; + $point['PPY'] = 0; + $point['NPX'] = $nextPoint['X']; + $point['NPY'] = $nextPoint['Y']; + } elseif (!$nextPoint) { + $point['AX'] = 5; + $point['AY'] = 5; + $point['PPX'] = $prevPoint['X']; + $point['PPY'] = $prevPoint['Y']; + $point['NPX'] = 0; + $point['NPY'] = 0; + } else { + $point['AX'] = $this->_pointY($prevPoint) - $this->_pointY($nextPoint); + $point['AY'] = $this->_pointX($nextPoint) - $this->_pointX($prevPoint); + $point['PPX'] = $prevPoint['X']; + $point['PPY'] = $prevPoint['Y']; + $point['NPX'] = $nextPoint['X']; + $point['NPY'] = $nextPoint['Y']; + } + + $point['APX'] = $point['X']; + $point['APY'] = $point['Y']; + + if ((isset($totals['MINIMUM_X'])) && ($totals['MINIMUM_X'] != 0)) { + $point['PCT_MIN_X'] = 100 * $point['X'] / $totals['MINIMUM_X']; + } + if ((isset($totals['MAXIMUM_X'])) && ($totals['MAXIMUM_X'] != 0)) { + $point['PCT_MAX_X'] = 100 * $point['X'] / $totals['MAXIMUM_X']; + } + + if ((isset($totals['MINIMUM_Y'])) && ($totals['MINIMUM_Y'] != 0)) { + $point['PCT_MIN_Y'] = 100 * $point['Y'] / $totals['MINIMUM_Y']; + } + if ((isset($totals['MAXIMUM_Y'])) && ($totals['MAXIMUM_Y'] != 0)) { + $point['PCT_MAX_Y'] = 100 * $point['Y'] / $totals['MAXIMUM_Y']; + } + + $point['LENGTH'] = sqrt($point['AX'] * $point['AX'] + + $point['AY'] * $point['AY']); + + if ((isset($point['LENGTH'])) && ($point['LENGTH'] != 0)) { + $point['ANGLE'] = asin($point['AY'] / $point['LENGTH']); + } + + if ((isset($point['AX'])) && ($point['AX'] > 0)) { + $point['ANGLE'] = pi() - $point['ANGLE']; + } + + if ($this->_parent->_horizontal) { + $point['MARKER_Y1'] = $this->_pointY($point) - + (isset($totals['WIDTH']) ? $totals['WIDTH'] : 0); + + $point['MARKER_Y2'] = $this->_pointY($point) + + (isset($totals['WIDTH']) ? $totals['WIDTH'] : 0); + + $point['COLUMN_WIDTH'] = abs($point['MARKER_Y2'] - + $point['MARKER_Y1']) / count($this->_dataset); + + $point['MARKER_Y'] = $point['MARKER_Y1'] + + ((isset($totals['NUMBER']) ? $totals['NUMBER'] : 0) + 0.5) * + $point['COLUMN_WIDTH']; + + $point['MARKER_X'] = $this->_pointX($point); + + if ($this->_multiType == 'stacked') { + $point['MARKER_Y'] = + ($point['MARKER_Y1'] + $point['MARKER_Y2']) / 2; + + $P1 = array('Y' => $totals['SUM_Y'][$x]); + $P2 = array('Y' => $totals['SUM_Y'][$x] + $point['Y']); + + $point['MARKER_X'] = + ($this->_pointX($P1) + $this->_pointX($P2)) / 2; + } elseif ($this->_multiType == 'stacked100pct') { + $x = $point['X']; + if ($totals['TOTAL_Y'][$x] != 0) { + $point['MARKER_Y'] = + ($point['MARKER_Y1'] + $point['MARKER_Y2']) / 2; + + $P1 = array( + 'Y' => 100 * $totals['SUM_Y'][$x] / $totals['TOTAL_Y'][$x] + ); + + $P2 = array( + 'Y' => 100 * ($totals['SUM_Y'][$x] + $point['Y']) / $totals['TOTAL_Y'][$x] + ); + + $point['MARKER_X'] = + ($this->_pointX($P1) + $this->_pointX($P2)) / 2; + } else { + $point = false; + } + } + } + else { + $point['MARKER_X1'] = $this->_pointX($point) - + (isset($totals['WIDTH']) ? $totals['WIDTH'] : 0); + + $point['MARKER_X2'] = $this->_pointX($point) + + (isset($totals['WIDTH']) ? $totals['WIDTH'] : 0); + + $point['COLUMN_WIDTH'] = abs($point['MARKER_X2'] - + $point['MARKER_X1']) / count($this->_dataset); + + $point['MARKER_X'] = $point['MARKER_X1'] + + ((isset($totals['NUMBER']) ? $totals['NUMBER'] : 0) + 0.5) * + $point['COLUMN_WIDTH']; + + $point['MARKER_Y'] = $this->_pointY($point); + + if ($this->_multiType == 'stacked') { + $point['MARKER_X'] = + ($point['MARKER_X1'] + $point['MARKER_X2']) / 2; + + $P1 = array('Y' => $totals['SUM_Y'][$x]); + $P2 = array('Y' => $totals['SUM_Y'][$x] + $point['Y']); + + $point['MARKER_Y'] = + ($this->_pointY($P1) + $this->_pointY($P2)) / 2; + } elseif ($this->_multiType == 'stacked100pct') { + $x = $point['X']; + if ($totals['TOTAL_Y'][$x] != 0) { + $point['MARKER_X'] = + ($point['MARKER_X1'] + $point['MARKER_X2']) / 2; + + $P1 = array( + 'Y' => 100 * $totals['SUM_Y'][$x] / $totals['TOTAL_Y'][$x] + ); + + $P2 = array( + 'Y' => 100 * ($totals['SUM_Y'][$x] + $point['Y']) / $totals['TOTAL_Y'][$x] + ); + + $point['MARKER_Y'] = + ($this->_pointY($P1) + $this->_pointY($P2)) / 2; + } else { + $point = false; + } + } + } + return $point; + } + } + + /** + * Draws markers on the canvas + * + * @access private + */ + function _drawMarker() + { + if (($this->_marker) && (is_array($this->_dataset))) { + $this->_canvas->startGroup(get_class($this) . '_marker'); + + $totals = $this->_getTotals(); + $totals['WIDTH'] = $this->width() / ($this->_maximumX() + 2) / 2; + + $number = 0; + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $totals['MINIMUM_X'] = $dataset->minimumX(); + $totals['MAXIMUM_X'] = $dataset->maximumX(); + $totals['MINIMUM_Y'] = $dataset->minimumY(); + $totals['MAXIMUM_Y'] = $dataset->maximumY(); + $totals['NUMBER'] = $number ++; + $dataset->_reset(); + while ($point = $dataset->_next()) { + $prevPoint = $dataset->_nearby(-2); + $nextPoint = $dataset->_nearby(); + + $x = $point['X']; + $y = $point['Y']; + if (((!is_object($this->_dataSelector)) || + ($this->_dataSelector->_select($point))) && ($point['Y'] !== null)) + { + + $point = $this->_getMarkerData( + $point, + $nextPoint, + $prevPoint, + $totals + ); + + if (is_array($point)) { + $this->_marker->_drawMarker( + $point['MARKER_X'], + $point['MARKER_Y'], + $point + ); + } + } + if (!isset($totals['SUM_Y'])) { + $totals['SUM_Y'] = array(); + } + if (isset($totals['SUM_Y'][$x])) { + $totals['SUM_Y'][$x] += $y; + } else { + $totals['SUM_Y'][$x] = $y; + } + } + } + unset($keys); + $this->_canvas->endGroup(); + } + } + + /** + * Get the minimum X value from the dataset + * + * @return double The minimum X value + * @access private + */ + function _minimumX() + { + if (!is_array($this->_dataset)) { + return 0; + } + + $min = false; + if (is_array($this->_dataset)) { + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + if ($min === false) { + $min = $this->_dataset[$key]->minimumX(); + } else { + $min = min($min, $this->_dataset[$key]->minimumX()); + } + } + unset($keys); + } + return $min; + } + + /** + * Get the maximum X value from the dataset + * + * @return double The maximum X value + * @access private + */ + function _maximumX() + { + if (!is_array($this->_dataset)) { + return 0; + } + + $max = 0; + if (is_array($this->_dataset)) { + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $max = max($max, $this->_dataset[$key]->maximumX()); + } + unset($keys); + } + return $max; + } + + /** + * Get the minimum Y value from the dataset + * + * @return double The minimum Y value + * @access private + */ + function _minimumY() + { + if (!is_array($this->_dataset)) { + return 0; + } + + $min = false; + if (is_array($this->_dataset)) { + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + if ($this->_multiType == 'normal') { + if ($min === false) { + $min = $this->_dataset[$key]->minimumY(); + } else { + $min = min($min, $this->_dataset[$key]->minimumY()); + } + } else { + if ($min === false) { + $min = 0; + } + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + while ($point = $dataset->_next()) { + if ($point['Y'] < 0) { + $x = $point['X']; + if ((!isset($total)) || (!isset($total[$x]))) { + $total[$x] = $point['Y']; + } else { + $total[$x] += $point['Y']; + } + if (isset($min)) { + $min = min($min, $total[$x]); + } else { + $min = $total[$x]; + } + } + } + } + } + unset($keys); + } + return $min; + } + + /** + * Get the maximum Y value from the dataset + * + * @return double The maximum Y value + * @access private + */ + function _maximumY() + { + if ($this->_multiType == 'stacked100pct') { + return 100; + } + + $maxY = 0; + if (is_array($this->_dataset)) { + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + + if ($this->_multiType == 'normal') { + if (isset($maxY)) { + $maxY = max($maxY, $dataset->maximumY()); + } else { + $maxY = $dataset->maximumY(); + } + } else { + $dataset->_reset(); + while ($point = $dataset->_next()) { + if ($point['Y'] > 0) { + $x = $point['X']; + if ((!isset($total)) || (!isset($total[$x]))) { + $total[$x] = $point['Y']; + } else { + $total[$x] += $point['Y']; + } + if (isset($maxY)) { + $maxY = max($maxY, $total[$x]); + } else { + $maxY = $total[$x]; + } + } + } + } + } + unset($keys); + } + return $maxY; + } + + /** + * Get the X pixel position represented by a value + * + * @param double $point The value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointX($point) + { + $point['AXIS_Y'] = $this->_axisY; + return parent::_pointX($point); + } + + /** + * Get the Y pixel position represented by a value + * + * @param double $point the value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointY($point) + { + $point['AXIS_Y'] = $this->_axisY; + return parent::_pointY($point); + } + + /** + * Update coordinates + * + * @access private + */ + function _updateCoords() + { + $this->_setCoords($this->_parent->_plotLeft, $this->_parent->_plotTop, $this->_parent->_plotRight, $this->_parent->_plotBottom); + parent::_updateCoords(); + } + + /** + * Get the dataset + * + * @return Image_Graph_Dataset The dataset(s) + */ + function &dataset() + { + return $this->_dataset; + } + + /** + * Calulate totals + * + * @return array An associated array with the totals + * @access private + */ + function _getTotals() + { + $total = array( + 'MINIMUM_X' => $this->_minimumX(), + 'MAXIMUM_X' => $this->_maximumX(), + 'MINIMUM_Y' => $this->_minimumY(), + 'MAXIMUM_Y' => $this->_maximumY() + ); + $total['ALL_SUM_Y'] = 0; + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + + $dataset->_reset(); + while ($point = $dataset->_next()) { + $x = $point['X']; + + if (is_numeric($point['Y'])) { + $total['ALL_SUM_Y'] += $point['Y']; + if (isset($total['TOTAL_Y'][$x])) { + $total['TOTAL_Y'][$x] += $point['Y']; + } else { + $total['TOTAL_Y'][$x] = $point['Y']; + } + } + + if (is_numeric($point['X'])) { + if (isset($total['TOTAL_X'][$x])) { + $total['TOTAL_X'][$x] += $point['X']; + } else { + $total['TOTAL_X'][$x] = $point['X']; + } + } + } + } + unset($keys); + return $total; + } + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $this->_canvas->rectangle(array('x0' => $x0, 'y0' => $y0, 'x1' => $x1, 'y1' => $y1)); + } + + /** + * Draw a sample for use with legend + * + * @param array $param The parameters for the legend + * @access private + */ + function _legendSample(&$param) + { + if (!is_array($this->_dataset)) { + return false; + } + + if (is_a($this->_fillStyle, 'Image_Graph_Fill')) { + $this->_fillStyle->_reset(); + } + + $count = 0; + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $count++; + + $caption = ($dataset->_name ? $dataset->_name : $this->_title); + + $this->_canvas->setFont($param['font']); + $width = 20 + $param['width'] + $this->_canvas->textWidth($caption); + $param['maxwidth'] = max($param['maxwidth'], $width); + $x2 = $param['x'] + $width; + $y2 = $param['y'] + $param['height'] + 5; + + if ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) && ($y2 > $param['bottom'])) { + $param['y'] = $param['top']; + $param['x'] = $x2; + $y2 = $param['y'] + $param['height']; + } elseif ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) == 0) && ($x2 > $param['right'])) { + $param['x'] = $param['left']; + $param['y'] = $y2; + $x2 = $param['x'] + 20 + $param['width'] + $this->_canvas->textWidth($caption); + } + + $x = $x0 = $param['x']; + $y = $param['y']; + $y0 = $param['y']; + $x1 = $param['x'] + $param['width']; + $y1 = $param['y'] + $param['height']; + + if (!isset($param['simulate'])) { + $this->_getFillStyle($key); + $this->_getLineStyle(); + $this->_drawLegendSample($x0, $y0, $x1, $y1); + + if (($this->_marker) && ($dataset) && ($param['show_marker'])) { + $dataset->_reset(); + $point = $dataset->_next(); + $prevPoint = $dataset->_nearby(-2); + $nextPoint = $dataset->_nearby(); + + $tmp = array(); + $point = $this->_getMarkerData($point, $nextPoint, $prevPoint, $tmp); + if (is_array($point)) { + $point['MARKER_X'] = $x+$param['width']/2; + $point['MARKER_Y'] = $y; + unset ($point['AVERAGE_Y']); + $this->_marker->_drawMarker($point['MARKER_X'], $point['MARKER_Y'], $point); + } + } + $this->write($x + $param['width'] + 10, $y + $param['height'] / 2, $caption, IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, $param['font']); + } + + if (($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) { + $param['y'] = $y2; + } else { + $param['x'] = $x2; + } + } + unset($keys); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Plot/Area.php b/includes/pear/Image/Graph/Plot/Area.php index 45fb549a..d60b7c03 100644 --- a/includes/pear/Image/Graph/Plot/Area.php +++ b/includes/pear/Image/Graph/Plot/Area.php @@ -1,188 +1,194 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Area.php,v 1.12 2005/08/08 19:09:18 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Plot.php - */ -require_once 'Image/Graph/Plot.php'; - -/** - * Area Chart plot. - * - * An area chart plots all data points similar to a {@link - * Image_Graph_Plot_Line}, but the area beneath the line is filled and the whole - * area 'the-line', 'the right edge', 'the x-axis' and 'the left edge' is - * bounded. Smoothed charts are only supported with non-stacked types - * - * @category Images - * @package Image_Graph - * @subpackage Plot - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Plot_Area extends Image_Graph_Plot -{ - - /** - * Perform the actual drawing on the legend. - * - * @param int $x0 The top-left x-coordinate - * @param int $y0 The top-left y-coordinate - * @param int $x1 The bottom-right x-coordinate - * @param int $y1 The bottom-right y-coordinate - * @access private - */ - function _drawLegendSample($x0, $y0, $x1, $y1) - { - $dx = abs($x1 - $x0) / 3; - $dy = abs($y1 - $y0) / 3; - $this->_canvas->addVertex(array('x' => $x0, 'y' => $y1)); - $this->_canvas->addVertex(array('x' => $x0, 'y' => $y0 + $dy)); - $this->_canvas->addVertex(array('x' => $x0 + $dx, 'y' => $y0)); - $this->_canvas->addVertex(array('x' => $x0 + 2*$dx, 'y' => $y0 + 2*$dy)); - $this->_canvas->addVertex(array('x' => $x1, 'y' => $y0 + $dy)); - $this->_canvas->addVertex(array('x' => $x1, 'y' => $y1)); - $this->_canvas->polygon(array('connect' => true)); - } - - /** - * Output the plot - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (parent::_done() === false) { - return false; - } - - $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); - $base = array(); - if ($this->_multiType == 'stacked') { - reset($this->_dataset); - $key = key($this->_dataset); - $dataset =& $this->_dataset[$key]; - - $first = $dataset->first(); - $point = array ('X' => $first['X'], 'Y' => '#min_pos#'); - $base[] = array(); - $base[] = $this->_pointY($point); - $first = $this->_pointX($point); - $base[] = $first; - - $last = $dataset->last(); - $point = array ('X' => $last['X'], 'Y' => '#min_pos#'); - $base[] = array(); - $base[] = $this->_pointY($point); - $base[] = $this->_pointX($point); - - $current = array(); - } - - $minYaxis = $this->_parent->_getMinimum($this->_axisY); - $maxYaxis = $this->_parent->_getMaximum($this->_axisY); - - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $dataset =& $this->_dataset[$key]; - $dataset->_reset(); - if ($this->_multiType == 'stacked') { - $plotarea = array_reverse($base); - $base = array(); - while ($point = $dataset->_next()) { - $x = $point['X']; - $p = $point; - if (isset($current[$x])) { - $p['Y'] += $current[$x]; - } else { - $current[$x] = 0; - } - $x1 = $this->_pointX($p); - $y1 = $this->_pointY($p); - $plotarea[] = $x1; - $plotarea[] = $y1; - $plotarea[] = $point; - $base[] = array(); - $base[] = $y1; - $base[] = $x1; - $current[$x] += $point['Y']; - } - } else { - $first = true; - $plotarea = array(); - while ($point = $dataset->_next()) { - if ($first) { - $firstPoint = array ('X' => $point['X'], 'Y' => '#min_pos#'); - $plotarea[] = $this->_pointX($firstPoint); - $plotarea[] = $this->_pointY($firstPoint); - $plotarea[] = array(); - } - $plotarea[] = $this->_pointX($point); - $plotarea[] = $this->_pointY($point); - $plotarea[] = $point; - $lastPoint = $point; - $first = false; - } - $endPoint['X'] = $lastPoint['X']; - $endPoint['Y'] = '#min_pos#'; - $plotarea[] = $this->_pointX($endPoint); - $plotarea[] = $this->_pointY($endPoint); - $plotarea[] = array(); - } - - reset($plotarea); - while (list(, $x) = each($plotarea)) { - list(, $y) = each($plotarea); - list(, $data) = each($plotarea); - $this->_canvas->addVertex( - $this->_mergeData( - $data, - array('x' => $x, 'y' => $y) - ) - ); - } - - $this->_getFillStyle($key); - $this->_getLineStyle($key); - $this->_canvas->polygon(array('connect' => true, 'map_vertices' => true)); - } - unset($keys); - $this->_drawMarker(); - $this->_canvas->endGroup(); - return true; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Area.php,v 1.13 2005/11/27 22:21:17 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * Area Chart plot. + * + * An area chart plots all data points similar to a {@link + * Image_Graph_Plot_Line}, but the area beneath the line is filled and the whole + * area 'the-line', 'the right edge', 'the x-axis' and 'the left edge' is + * bounded. Smoothed charts are only supported with non-stacked types + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Plot_Area extends Image_Graph_Plot +{ + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $dx = abs($x1 - $x0) / 3; + $dy = abs($y1 - $y0) / 3; + $this->_canvas->addVertex(array('x' => $x0, 'y' => $y1)); + $this->_canvas->addVertex(array('x' => $x0, 'y' => $y0 + $dy)); + $this->_canvas->addVertex(array('x' => $x0 + $dx, 'y' => $y0)); + $this->_canvas->addVertex(array('x' => $x0 + 2*$dx, 'y' => $y0 + 2*$dy)); + $this->_canvas->addVertex(array('x' => $x1, 'y' => $y0 + $dy)); + $this->_canvas->addVertex(array('x' => $x1, 'y' => $y1)); + $this->_canvas->polygon(array('connect' => true)); + } + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + + $this->_clip(true); + + $base = array(); + if ($this->_multiType == 'stacked') { + reset($this->_dataset); + $key = key($this->_dataset); + $dataset =& $this->_dataset[$key]; + + $first = $dataset->first(); + $point = array ('X' => $first['X'], 'Y' => '#min_pos#'); + $base[] = array(); + $base[] = $this->_pointY($point); + $first = $this->_pointX($point); + $base[] = $first; + + $last = $dataset->last(); + $point = array ('X' => $last['X'], 'Y' => '#min_pos#'); + $base[] = array(); + $base[] = $this->_pointY($point); + $base[] = $this->_pointX($point); + + $current = array(); + } + + $minYaxis = $this->_parent->_getMinimum($this->_axisY); + $maxYaxis = $this->_parent->_getMaximum($this->_axisY); + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + if ($this->_multiType == 'stacked') { + $plotarea = array_reverse($base); + $base = array(); + while ($point = $dataset->_next()) { + $x = $point['X']; + $p = $point; + if (isset($current[$x])) { + $p['Y'] += $current[$x]; + } else { + $current[$x] = 0; + } + $x1 = $this->_pointX($p); + $y1 = $this->_pointY($p); + $plotarea[] = $x1; + $plotarea[] = $y1; + $plotarea[] = $point; + $base[] = array(); + $base[] = $y1; + $base[] = $x1; + $current[$x] += $point['Y']; + } + } else { + $first = true; + $plotarea = array(); + while ($point = $dataset->_next()) { + if ($first) { + $firstPoint = array ('X' => $point['X'], 'Y' => '#min_pos#'); + $plotarea[] = $this->_pointX($firstPoint); + $plotarea[] = $this->_pointY($firstPoint); + $plotarea[] = array(); + } + $plotarea[] = $this->_pointX($point); + $plotarea[] = $this->_pointY($point); + $plotarea[] = $point; + $lastPoint = $point; + $first = false; + } + $endPoint['X'] = $lastPoint['X']; + $endPoint['Y'] = '#min_pos#'; + $plotarea[] = $this->_pointX($endPoint); + $plotarea[] = $this->_pointY($endPoint); + $plotarea[] = array(); + } + + reset($plotarea); + while (list(, $x) = each($plotarea)) { + list(, $y) = each($plotarea); + list(, $data) = each($plotarea); + $this->_canvas->addVertex( + $this->_mergeData( + $data, + array('x' => $x, 'y' => $y) + ) + ); + } + + $this->_getFillStyle($key); + $this->_getLineStyle($key); + $this->_canvas->polygon(array('connect' => true, 'map_vertices' => true)); + } + unset($keys); + $this->_drawMarker(); + $this->_clip(false); + + $this->_canvas->endGroup(); + + return true; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Plot/Band.php b/includes/pear/Image/Graph/Plot/Band.php index 2a283384..7acaee9b 100644 --- a/includes/pear/Image/Graph/Plot/Band.php +++ b/includes/pear/Image/Graph/Plot/Band.php @@ -1,198 +1,205 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Band.php,v 1.11 2005/08/23 21:01:46 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - * @since File available since Release 0.3.0dev2 - */ - -/** - * Include file Image/Graph/Plot.php - */ -require_once 'Image/Graph/Plot.php'; - -/** - * "Band" (area chart with min AND max) chart. - * - * @category Images - * @package Image_Graph - * @subpackage Plot - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - * @since Class available since Release 0.3.0dev2 - */ -class Image_Graph_Plot_Band extends Image_Graph_Plot -{ - - /** - * Perform the actual drawing on the legend. - * - * @param int $x0 The top-left x-coordinate - * @param int $y0 The top-left y-coordinate - * @param int $x1 The bottom-right x-coordinate - * @param int $y1 The bottom-right y-coordinate - * @access private - */ - function _drawLegendSample($x0, $y0, $x1, $y1) - { - $h = abs($y1 - $y0) / 6; - $w = round(abs($x1 - $x0) / 5); - $y = ($y0 + $y1) / 2; - - $this->_canvas->addVertex(array('x' => $x0, 'y' => $y - $h * 3)); - $this->_canvas->addVertex(array('x' => $x0 + $w, 'y' => $y - 4 * $h)); - $this->_canvas->addVertex(array('x' => $x0 + 2 * $w, 'y' => $y - $h * 2)); - $this->_canvas->addVertex(array('x' => $x0 + 3 * $w, 'y' => $y - $h * 4)); - $this->_canvas->addVertex(array('x' => $x0 + 4 * $w, 'y' => $y - $h * 3)); - $this->_canvas->addVertex(array('x' => $x1, 'y' => $y - $h * 2)); - $this->_canvas->addVertex(array('x' => $x1, 'y' => $y + $h * 3)); - $this->_canvas->addVertex(array('x' => $x0 + 4 * $w, 'y' => $y + $h)); - $this->_canvas->addVertex(array('x' => $x0 + 3 * $w, 'y' => $y + 2 * $h)); - $this->_canvas->addVertex(array('x' => $x0 + 2 * $w, 'y' => $y + 1 * $h)); - $this->_canvas->addVertex(array('x' => $x0 + 1 * $w, 'y' => $y)); - $this->_canvas->addVertex(array('x' => $x0, 'y' => $y + $h)); - - $this->_getLineStyle(); - $this->_getFillStyle(); - $this->_canvas->polygon(array('connect' => true)); - } - - /** - * Output the plot - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (parent::_done() === false) { - return false; - } - - if (!is_array($this->_dataset)) { - return false; - } - - $current = array(); - - $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $dataset =& $this->_dataset[$key]; - $dataset->_reset(); - $upperBand = array(); - $lowerBand = array(); - while ($data = $dataset->_next()) { - if ($this->_parent->_horizontal) { - $point['X'] = $data['X']; - - $point['Y'] = $data['Y']['high']; - $y = $this->_pointY($point); - $x_high = $this->_pointX($point); - - $point['Y'] = $data['Y']['low']; - $x_low = $this->_pointX($point); - - $data = array('X' => $x_high, 'Y' => $y); - if (isset($point['data'])) { - $data['data'] = $point['data']; - } else { - $data['data'] = array(); - } - $upperBand[] = $data; - - $data = array('X' => $x_low, 'Y' => $y); - if (isset($point['data'])) { - $data['data'] = $point['data']; - } else { - $data['data'] = array(); - } - $lowerBand[] = $data; - } - else { - $point['X'] = $data['X']; - $y = $data['Y']; - - $point['Y'] = $data['Y']['high']; - $x = $this->_pointX($point); - $y_high = $this->_pointY($point); - - $point['Y'] = $data['Y']['low']; - $y_low = $this->_pointY($point); - - $data = array('X' => $x, 'Y' => $y_high); - if (isset($point['data'])) { - $data['data'] = $point['data']; - } else { - $data['data'] = array(); - } - $upperBand[] = $data; - - $data = array('X' => $x, 'Y' => $y_low); - if (isset($point['data'])) { - $data['data'] = $point['data']; - } else { - $data['data'] = array(); - } - $lowerBand[] = $data; - } - } - $lowerBand = array_reverse($lowerBand); - foreach ($lowerBand as $point) { - $this->_canvas->addVertex( - $this->_mergeData( - $point['data'], - array('x' => $point['X'], 'y' => $point['Y']) - ) - ); - } - foreach ($upperBand as $point) { - $this->_canvas->addVertex( - $this->_mergeData( - $point['data'], - array('x' => $point['X'], 'y' => $point['Y']) - ) - ); - } - unset($upperBand); - unset($lowerBand); - - $this->_getLineStyle($key); - $this->_getFillStyle($key); - $this->_canvas->polygon(array('connect' => true, 'map_vertices' => true)); - } - unset($keys); - $this->_drawMarker(); - $this->_canvas->endGroup(); - return true; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Band.php,v 1.12 2005/11/27 22:21:16 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + * @since File available since Release 0.3.0dev2 + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * "Band" (area chart with min AND max) chart. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + * @since Class available since Release 0.3.0dev2 + */ +class Image_Graph_Plot_Band extends Image_Graph_Plot +{ + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $h = abs($y1 - $y0) / 6; + $w = round(abs($x1 - $x0) / 5); + $y = ($y0 + $y1) / 2; + + $this->_canvas->addVertex(array('x' => $x0, 'y' => $y - $h * 3)); + $this->_canvas->addVertex(array('x' => $x0 + $w, 'y' => $y - 4 * $h)); + $this->_canvas->addVertex(array('x' => $x0 + 2 * $w, 'y' => $y - $h * 2)); + $this->_canvas->addVertex(array('x' => $x0 + 3 * $w, 'y' => $y - $h * 4)); + $this->_canvas->addVertex(array('x' => $x0 + 4 * $w, 'y' => $y - $h * 3)); + $this->_canvas->addVertex(array('x' => $x1, 'y' => $y - $h * 2)); + $this->_canvas->addVertex(array('x' => $x1, 'y' => $y + $h * 3)); + $this->_canvas->addVertex(array('x' => $x0 + 4 * $w, 'y' => $y + $h)); + $this->_canvas->addVertex(array('x' => $x0 + 3 * $w, 'y' => $y + 2 * $h)); + $this->_canvas->addVertex(array('x' => $x0 + 2 * $w, 'y' => $y + 1 * $h)); + $this->_canvas->addVertex(array('x' => $x0 + 1 * $w, 'y' => $y)); + $this->_canvas->addVertex(array('x' => $x0, 'y' => $y + $h)); + + $this->_getLineStyle(); + $this->_getFillStyle(); + $this->_canvas->polygon(array('connect' => true)); + } + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + if (!is_array($this->_dataset)) { + return false; + } + + $current = array(); + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + + $this->_clip(true); + + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + $upperBand = array(); + $lowerBand = array(); + while ($data = $dataset->_next()) { + if ($this->_parent->_horizontal) { + $point['X'] = $data['X']; + + $point['Y'] = $data['Y']['high']; + $y = $this->_pointY($point); + $x_high = $this->_pointX($point); + + $point['Y'] = $data['Y']['low']; + $x_low = $this->_pointX($point); + + $data = array('X' => $x_high, 'Y' => $y); + if (isset($point['data'])) { + $data['data'] = $point['data']; + } else { + $data['data'] = array(); + } + $upperBand[] = $data; + + $data = array('X' => $x_low, 'Y' => $y); + if (isset($point['data'])) { + $data['data'] = $point['data']; + } else { + $data['data'] = array(); + } + $lowerBand[] = $data; + } + else { + $point['X'] = $data['X']; + $y = $data['Y']; + + $point['Y'] = $data['Y']['high']; + $x = $this->_pointX($point); + $y_high = $this->_pointY($point); + + $point['Y'] = $data['Y']['low']; + $y_low = $this->_pointY($point); + + $data = array('X' => $x, 'Y' => $y_high); + if (isset($point['data'])) { + $data['data'] = $point['data']; + } else { + $data['data'] = array(); + } + $upperBand[] = $data; + + $data = array('X' => $x, 'Y' => $y_low); + if (isset($point['data'])) { + $data['data'] = $point['data']; + } else { + $data['data'] = array(); + } + $lowerBand[] = $data; + } + } + $lowerBand = array_reverse($lowerBand); + foreach ($lowerBand as $point) { + $this->_canvas->addVertex( + $this->_mergeData( + $point['data'], + array('x' => $point['X'], 'y' => $point['Y']) + ) + ); + } + foreach ($upperBand as $point) { + $this->_canvas->addVertex( + $this->_mergeData( + $point['data'], + array('x' => $point['X'], 'y' => $point['Y']) + ) + ); + } + unset($upperBand); + unset($lowerBand); + + $this->_getLineStyle($key); + $this->_getFillStyle($key); + $this->_canvas->polygon(array('connect' => true, 'map_vertices' => true)); + } + unset($keys); + $this->_drawMarker(); + $this->_clip(false); + + $this->_canvas->endGroup(); + + return true; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Plot/Bar.php b/includes/pear/Image/Graph/Plot/Bar.php index 17cc0624..c589d4b4 100644 --- a/includes/pear/Image/Graph/Plot/Bar.php +++ b/includes/pear/Image/Graph/Plot/Bar.php @@ -1,302 +1,307 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Bar.php,v 1.13 2005/08/24 16:02:49 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Plot.php - */ -require_once 'Image/Graph/Plot.php'; - -/** - * A bar chart. - * - * @category Images - * @package Image_Graph - * @subpackage Plot - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Plot_Bar extends Image_Graph_Plot -{ - - /** - * The space between 2 bars (should be a multipla of 2) - * @var int - * @access private - */ - var $_space = 4; - - /** - * The width of the bars - * @var array - * @access private - */ - var $_width = 'auto'; - - /** - * Perform the actual drawing on the legend. - * - * @param int $x0 The top-left x-coordinate - * @param int $y0 The top-left y-coordinate - * @param int $x1 The bottom-right x-coordinate - * @param int $y1 The bottom-right y-coordinate - * @access private - */ - function _drawLegendSample($x0, $y0, $x1, $y1) - { - $dx = abs($x1 - $x0) / 7; - $this->_canvas->rectangle(array('x0' => $x0 + $dx, 'y0' => $y0, 'x1' => $x1 - $dx, 'y1' => $y1)); - } - - /** - * Set the spacing between 2 neighbouring bars - * - * @param int $space The number of pixels between 2 bars, should be a - * multipla of 2 (ie an even number) - */ - function setSpacing($space) - { - $this->_space = (int) ($space / 2); - } - - /** - * Set the width of a bars. - * - * Specify 'auto' to auto calculate the width based on the positions on the - * x-axis. - * - * Supported units are: - * - * '%' The width is specified in percentage of the total plot width - * - * 'px' The width specified in pixels - * - * @param string $width The width of any bar - * @param string $unit The unit of the width - */ - function setBarWidth($width, $unit = false) - { - if ($width == 'auto') { - $this->_width = $width; - } else { - $this->_width = array( - 'width' => $width, - 'unit' => $unit - ); - } - } - - /** - * Output the plot - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (parent::_done() === false) { - return false; - } - - if (!is_array($this->_dataset)) { - return false; - } - - $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); - - if ($this->_width == 'auto') { - $width = $this->_parent->_labelDistance(IMAGE_GRAPH_AXIS_X) / 2; - } elseif ($this->_width['unit'] == '%') { - $width = $this->_width['width'] * $this->width() / 200; - } elseif ($this->_width['unit'] == 'px') { - $width = $this->_width['width'] / 2; - } - - if ($this->_multiType == 'stacked100pct') { - $total = $this->_getTotals(); - } - - $minYaxis = $this->_parent->_getMinimum($this->_axisY); - $maxYaxis = $this->_parent->_getMaximum($this->_axisY); - - $number = 0; - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $dataset =& $this->_dataset[$key]; - $dataset->_reset(); - while ($point = $dataset->_next()) { - - if ($this->_parent->_horizontal) { - $y1 = $this->_pointY($point) - $width; - $y2 = $this->_pointY($point) + $width; - - if ($y2 - $this->_space > $y1 + $this->_space) { - /* - * Take bar spacing into account _only_ if the space doesn't - * turn the bar "inside-out", i.e. if the actual bar width - * is smaller than the space between the bars - */ - $y2 -= $this->_space; - $y1 += $this->_space; - } - } - else { - $x1 = $this->_pointX($point) - $width; - $x2 = $this->_pointX($point) + $width; - - if ($x2 - $this->_space > $x1 + $this->_space) { - /* - * Take bar spacing into account _only_ if the space doesn't - * turn the bar "inside-out", i.e. if the actual bar width - * is smaller than the space between the bars - */ - $x2 -= $this->_space; - $x1 += $this->_space; - } - } - - - if (($this->_multiType == 'stacked') || - ($this->_multiType == 'stacked100pct')) - { - $x = $point['X']; - - if ($point['Y'] >= 0) { - if (!isset($current[$x])) { - $current[$x] = 0; - } - - if ($this->_multiType == 'stacked') { - $p0 = array( - 'X' => $point['X'], - 'Y' => $current[$x] - ); - $p1 = array( - 'X' => $point['X'], - 'Y' => $current[$x] + $point['Y'] - ); - } else { - $p0 = array( - 'X' => $point['X'], - 'Y' => 100 * $current[$x] / $total['TOTAL_Y'][$x] - ); - $p1 = array( - 'X' => $point['X'], - 'Y' => 100 * ($current[$x] + $point['Y']) / $total['TOTAL_Y'][$x] - ); - } - $current[$x] += $point['Y']; - } else { - if (!isset($currentNegative[$x])) { - $currentNegative[$x] = 0; - } - - $p0 = array( - 'X' => $point['X'], - 'Y' => $currentNegative[$x] - ); - $p1 = array( - 'X' => $point['X'], - 'Y' => $currentNegative[$x] + $point['Y'] - ); - $currentNegative[$x] += $point['Y']; - } - } else { - if (count($this->_dataset) > 1) { - $w = 2 * ($width - $this->_space) / count($this->_dataset); - if ($this->_parent->_horizontal) { - $y2 = ($y1 = ($y1 + $y2) / 2 - ($width - $this->_space) + $number * $w) + $w; - } - else { - $x2 = ($x1 = ($x1 + $x2) / 2 - ($width - $this->_space) + $number * $w) + $w; - } - } - $p0 = array('X' => $point['X'], 'Y' => 0); - $p1 = $point; - } - - if ((($minY = min($p0['Y'], $p1['Y'])) < $maxYaxis) && - (($maxY = max($p0['Y'], $p1['Y'])) > $minYaxis) - ) { - $p0['Y'] = $minY; - $p1['Y'] = $maxY; - - if ($p0['Y'] < $minYaxis) { - $p0['Y'] = '#min_pos#'; - } - if ($p1['Y'] > $maxYaxis) { - $p1['Y'] = '#max_neg#'; - } - - if ($this->_parent->_horizontal) { - $x1 = $this->_pointX($p0); - $x2 = $this->_pointX($p1); - } - else { - $y1 = $this->_pointY($p0); - $y2 = $this->_pointY($p1); - } - - $ID = $point['ID']; - if (($ID === false) && (count($this->_dataset) > 1)) { - $ID = $key; - } - $this->_getFillStyle($ID); - $this->_getLineStyle($ID); - - if (($y1 != $y2) && ($x1 != $x2)) { - $this->_canvas->rectangle( - $this->_mergeData( - $point, - array( - 'x0' => min($x1, $x2), - 'y0' => min($y1, $y2), - 'x1' => max($x1, $x2), - 'y1' => max($y1, $y2) - ) - ) - ); - } - } - } - $number ++; - } - unset($keys); - - $this->_drawMarker(); - - $this->_canvas->endGroup(); - return true; - } -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Bar.php,v 1.14 2005/11/27 22:21:16 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * A bar chart. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Plot_Bar extends Image_Graph_Plot +{ + + /** + * The space between 2 bars (should be a multipla of 2) + * @var int + * @access private + */ + var $_space = 4; + + /** + * The width of the bars + * @var array + * @access private + */ + var $_width = 'auto'; + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $dx = abs($x1 - $x0) / 7; + $this->_canvas->rectangle(array('x0' => $x0 + $dx, 'y0' => $y0, 'x1' => $x1 - $dx, 'y1' => $y1)); + } + + /** + * Set the spacing between 2 neighbouring bars + * + * @param int $space The number of pixels between 2 bars, should be a + * multipla of 2 (ie an even number) + */ + function setSpacing($space) + { + $this->_space = (int) ($space / 2); + } + + /** + * Set the width of a bars. + * + * Specify 'auto' to auto calculate the width based on the positions on the + * x-axis. + * + * Supported units are: + * + * '%' The width is specified in percentage of the total plot width + * + * 'px' The width specified in pixels + * + * @param string $width The width of any bar + * @param string $unit The unit of the width + */ + function setBarWidth($width, $unit = false) + { + if ($width == 'auto') { + $this->_width = $width; + } else { + $this->_width = array( + 'width' => $width, + 'unit' => $unit + ); + } + } + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + if (!is_array($this->_dataset)) { + return false; + } + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + + $this->_clip(true); + + if ($this->_width == 'auto') { + $width = $this->_parent->_labelDistance(IMAGE_GRAPH_AXIS_X) / 2; + } elseif ($this->_width['unit'] == '%') { + $width = $this->_width['width'] * $this->width() / 200; + } elseif ($this->_width['unit'] == 'px') { + $width = $this->_width['width'] / 2; + } + + if ($this->_multiType == 'stacked100pct') { + $total = $this->_getTotals(); + } + + $minYaxis = $this->_parent->_getMinimum($this->_axisY); + $maxYaxis = $this->_parent->_getMaximum($this->_axisY); + + $number = 0; + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + while ($point = $dataset->_next()) { + + if ($this->_parent->_horizontal) { + $y1 = $this->_pointY($point) - $width; + $y2 = $this->_pointY($point) + $width; + + if ($y2 - $this->_space > $y1 + $this->_space) { + /* + * Take bar spacing into account _only_ if the space doesn't + * turn the bar "inside-out", i.e. if the actual bar width + * is smaller than the space between the bars + */ + $y2 -= $this->_space; + $y1 += $this->_space; + } + } + else { + $x1 = $this->_pointX($point) - $width; + $x2 = $this->_pointX($point) + $width; + + if ($x2 - $this->_space > $x1 + $this->_space) { + /* + * Take bar spacing into account _only_ if the space doesn't + * turn the bar "inside-out", i.e. if the actual bar width + * is smaller than the space between the bars + */ + $x2 -= $this->_space; + $x1 += $this->_space; + } + } + + + if (($this->_multiType == 'stacked') || + ($this->_multiType == 'stacked100pct')) + { + $x = $point['X']; + + if ($point['Y'] >= 0) { + if (!isset($current[$x])) { + $current[$x] = 0; + } + + if ($this->_multiType == 'stacked') { + $p0 = array( + 'X' => $point['X'], + 'Y' => $current[$x] + ); + $p1 = array( + 'X' => $point['X'], + 'Y' => $current[$x] + $point['Y'] + ); + } else { + $p0 = array( + 'X' => $point['X'], + 'Y' => 100 * $current[$x] / $total['TOTAL_Y'][$x] + ); + $p1 = array( + 'X' => $point['X'], + 'Y' => 100 * ($current[$x] + $point['Y']) / $total['TOTAL_Y'][$x] + ); + } + $current[$x] += $point['Y']; + } else { + if (!isset($currentNegative[$x])) { + $currentNegative[$x] = 0; + } + + $p0 = array( + 'X' => $point['X'], + 'Y' => $currentNegative[$x] + ); + $p1 = array( + 'X' => $point['X'], + 'Y' => $currentNegative[$x] + $point['Y'] + ); + $currentNegative[$x] += $point['Y']; + } + } else { + if (count($this->_dataset) > 1) { + $w = 2 * ($width - $this->_space) / count($this->_dataset); + if ($this->_parent->_horizontal) { + $y2 = ($y1 = ($y1 + $y2) / 2 - ($width - $this->_space) + $number * $w) + $w; + } + else { + $x2 = ($x1 = ($x1 + $x2) / 2 - ($width - $this->_space) + $number * $w) + $w; + } + } + $p0 = array('X' => $point['X'], 'Y' => 0); + $p1 = $point; + } + + if ((($minY = min($p0['Y'], $p1['Y'])) < $maxYaxis) && + (($maxY = max($p0['Y'], $p1['Y'])) > $minYaxis) + ) { + $p0['Y'] = $minY; + $p1['Y'] = $maxY; + + if ($p0['Y'] < $minYaxis) { + $p0['Y'] = '#min_pos#'; + } + if ($p1['Y'] > $maxYaxis) { + $p1['Y'] = '#max_neg#'; + } + + if ($this->_parent->_horizontal) { + $x1 = $this->_pointX($p0); + $x2 = $this->_pointX($p1); + } + else { + $y1 = $this->_pointY($p0); + $y2 = $this->_pointY($p1); + } + + $ID = $point['ID']; + if (($ID === false) && (count($this->_dataset) > 1)) { + $ID = $key; + } + $this->_getFillStyle($ID); + $this->_getLineStyle($ID); + + if (($y1 != $y2) && ($x1 != $x2)) { + $this->_canvas->rectangle( + $this->_mergeData( + $point, + array( + 'x0' => min($x1, $x2), + 'y0' => min($y1, $y2), + 'x1' => max($x1, $x2), + 'y1' => max($y1, $y2) + ) + ) + ); + } + } + } + $number ++; + } + unset($keys); + + $this->_drawMarker(); + + $this->_clip(false); + + $this->_canvas->endGroup(); + + return true; + } +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Plot/BoxWhisker.php b/includes/pear/Image/Graph/Plot/BoxWhisker.php index d6b0d388..8acaa8d8 100644 --- a/includes/pear/Image/Graph/Plot/BoxWhisker.php +++ b/includes/pear/Image/Graph/Plot/BoxWhisker.php @@ -1,294 +1,298 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: BoxWhisker.php,v 1.13 2005/09/08 19:02:18 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - * @since File available since Release 0.3.0dev2 - */ - -/** - * Include file Image/Graph/Plot.php - */ -require_once 'Image/Graph/Plot.php'; - -/** - * Box & Whisker chart. - * - * @category Images - * @package Image_Graph - * @subpackage Plot - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - * @since Class available since Release 0.3.0dev2 - */ -class Image_Graph_Plot_BoxWhisker extends Image_Graph_Plot -{ - /** - * Whisker circle size - * @var int - * @access private - */ - var $_whiskerSize = false; - - /** - * Draws a box & whisker - * - * @param int $x The x position - * @param int $w The width of the box - * @param int $r The radius of the circle markers - * @param int $y_min The Y position of the minimum value - * @param int $y_q1 The Y position of the median of the first quartile - * @param int $y_med The Y position of the median - * @param int $y_q3 The Y position of the median of the third quartile - * @param int $y_max The Y position of the maximum value - * @param int $key The ID tag - * @access private - */ - function _drawBoxWhiskerV($x, $w, $r, $y_min, $y_q1, $y_med, $y_q3, $y_max, $key = false) - { - // draw circles - $this->_getLineStyle(); - $this->_getFillStyle('min'); - $this->_canvas->ellipse(array('x' => $x, 'y' => $y_min, 'rx' => $r, 'ry' => $r)); - - $this->_getLineStyle(); - $this->_getFillStyle('quartile1'); - $this->_canvas->ellipse(array('x' => $x, 'y' => $y_q1, 'rx' => $r, 'ry' => $r)); - - $this->_getLineStyle(); - $this->_getFillStyle('median'); - $this->_canvas->ellipse(array('x' => $x, 'y' => $y_med, 'rx' => $r, 'ry' => $r)); - - $this->_getLineStyle(); - $this->_getFillStyle('quartile3'); - $this->_canvas->ellipse(array('x' => $x, 'y' => $y_q3, $r, 'rx' => $r, 'ry' => $r)); - - $this->_getLineStyle(); - $this->_getFillStyle('max'); - $this->_canvas->ellipse(array('x' => $x, 'y' => $y_max, $r, 'rx' => $r, 'ry' => $r)); - - // draw box and lines - - $this->_getLineStyle(); - $this->_canvas->line(array('x0' => $x, 'y0' => $y_min, 'x1' => $x, 'y1' => $y_q1)); - $this->_getLineStyle(); - $this->_canvas->line(array('x0' => $x, 'y0' => $y_q3, 'x1' => $x, 'y1' => $y_max)); - - $this->_getLineStyle(); - $this->_getFillStyle('box'); - $this->_canvas->rectangle(array('x0' => $x - $w, 'y0' => $y_q1, 'x1' => $x + $w, 'y1' => $y_q3)); - - $this->_getLineStyle(); - $this->_canvas->line(array('x0' => $x - $w, 'y0' => $y_med, 'x1' => $x + $w, 'y1' => $y_med)); - } - - /** - * Draws a box & whisker - * - * @param int $y The x position - * @param int $h The width of the box - * @param int $r The radius of the circle markers - * @param int $x_min The Y position of the minimum value - * @param int $x_q1 The Y position of the median of the first quartile - * @param int $x_med The Y position of the median - * @param int $x_q3 The Y position of the median of the third quartile - * @param int $x_max The Y position of the maximum value - * @param int $key The ID tag - * @access private - */ - function _drawBoxWhiskerH($y, $h, $r, $x_min, $x_q1, $x_med, $x_q3, $x_max, $key = false) - { - // draw circles - $this->_getLineStyle(); - $this->_getFillStyle('min'); - $this->_canvas->ellipse(array('x' => $x_min, 'y' => $y, 'rx' => $r, 'ry' => $r)); - - $this->_getLineStyle(); - $this->_getFillStyle('quartile1'); - $this->_canvas->ellipse(array('x' => $x_q1, 'y' => $y, 'rx' => $r, 'ry' => $r)); - - $this->_getLineStyle(); - $this->_getFillStyle('median'); - $this->_canvas->ellipse(array('x' => $x_med, 'y' => $y, 'rx' => $r, 'ry' => $r)); - - $this->_getLineStyle(); - $this->_getFillStyle('quartile3'); - $this->_canvas->ellipse(array('x' => $x_q3, 'y' => $y, $r, 'rx' => $r, 'ry' => $r)); - - $this->_getLineStyle(); - $this->_getFillStyle('max'); - $this->_canvas->ellipse(array('x' => $x_max, 'y' => $y, $r, 'rx' => $r, 'ry' => $r)); - - // draw box and lines - - $this->_getLineStyle(); - $this->_canvas->line(array('x0' => $x_min, 'y0' => $y, 'x1' => $x_q1, 'y1' => $y)); - $this->_getLineStyle(); - $this->_canvas->line(array('x0' => $x_q3, 'y0' => $y, 'x1' => $x_max, 'y1' => $y)); - - $this->_getLineStyle(); - $this->_getFillStyle('box'); - $this->_canvas->rectangle(array('x0' => $x_q1, 'y0' => $y - $h, 'x1' => $x_q3, 'y1' => $y + $h)); - - $this->_getLineStyle(); - $this->_canvas->line(array('x0' => $x_med, 'y0' => $y - $h, 'x1' => $x_med, 'y1' => $y + $h)); - } - - /** - * Perform the actual drawing on the legend. - * - * @param int $x0 The top-left x-coordinate - * @param int $y0 The top-left y-coordinate - * @param int $x1 The bottom-right x-coordinate - * @param int $y1 The bottom-right y-coordinate - * @access private - */ - function _drawLegendSample($x0, $y0, $x1, $y1) - { - $x = round(($x0 + $x1) / 2); - $h = abs($y1 - $y0) / 9; - $w = round(abs($x1 - $x0) / 5); - $r = 2;//round(abs($x1 - $x0) / 13); - $this->_drawBoxWhiskerV($x, $w, $r, $y1, $y1 - 2 * $h, $y1 - 4 * $h, $y0 + 3 * $h, $y0); - } - - /** - * Sets the whisker circle size - * - * @param int $size Size (radius) of the whisker circle/dot - */ - function setWhiskerSize($size = false) - { - $this->_whiskerSize = $size; - } - - /** - * Output the plot - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (parent::_done() === false) { - return false; - } - - if (!is_array($this->_dataset)) { - return false; - } - - $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); - - if ($this->_multiType == 'stacked100pct') { - $total = $this->_getTotals(); - } - $current = array(); - $number = 0; - $width = floor(0.5 * $this->_parent->_labelDistance(IMAGE_GRAPH_AXIS_X) / 2); - - if ($this->_whiskerSize !== false) { - $r = $this->_whiskerSize; - } else { - $r = min(5, $width / 10); - } - - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $dataset =& $this->_dataset[$key]; - $dataset->_reset(); - while ($data = $dataset->_next()) { - if ($this->_parent->_horizontal) { - $point['X'] = $data['X']; - $y = $data['Y']; - - $min = min($y); - $max = max($y); - $q1 = $dataset->_median($y, 'first'); - $med = $dataset->_median($y, 'second'); - $q3 = $dataset->_median($y, 'third'); - - $point['Y'] = $min; - $y = $this->_pointY($point); - $x_min = $this->_pointX($point); - - $point['Y'] = $max; - $x_max = $this->_pointX($point); - - $point['Y'] = $q1; - $x_q1 = $this->_pointX($point); - - $point['Y'] = $med; - $x_med = $this->_pointX($point); - - $point['Y'] = $q3; - $x_q3 = $this->_pointX($point); - - $this->_drawBoxWhiskerH($y, $width, $r, $x_min, $x_q1, $x_med, $x_q3, $x_max, $key); - } - else { - $point['X'] = $data['X']; - $y = $data['Y']; - - $min = min($y); - $max = max($y); - $q1 = $dataset->_median($y, 'first'); - $med = $dataset->_median($y, 'second'); - $q3 = $dataset->_median($y, 'third'); - - $point['Y'] = $min; - $x = $this->_pointX($point); - $y_min = $this->_pointY($point); - - $point['Y'] = $max; - $y_max = $this->_pointY($point); - - $point['Y'] = $q1; - $y_q1 = $this->_pointY($point); - - $point['Y'] = $med; - $y_med = $this->_pointY($point); - - $point['Y'] = $q3; - $y_q3 = $this->_pointY($point); - - $this->_drawBoxWhiskerV($x, $width, $r, $y_min, $y_q1, $y_med, $y_q3, $y_max, $key); - } - } - } - unset($keys); - $this->_drawMarker(); - - $this->_canvas->endGroup(); - return true; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: BoxWhisker.php,v 1.14 2005/11/27 22:21:17 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + * @since File available since Release 0.3.0dev2 + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * Box & Whisker chart. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + * @since Class available since Release 0.3.0dev2 + */ +class Image_Graph_Plot_BoxWhisker extends Image_Graph_Plot +{ + /** + * Whisker circle size + * @var int + * @access private + */ + var $_whiskerSize = false; + + /** + * Draws a box & whisker + * + * @param int $x The x position + * @param int $w The width of the box + * @param int $r The radius of the circle markers + * @param int $y_min The Y position of the minimum value + * @param int $y_q1 The Y position of the median of the first quartile + * @param int $y_med The Y position of the median + * @param int $y_q3 The Y position of the median of the third quartile + * @param int $y_max The Y position of the maximum value + * @param int $key The ID tag + * @access private + */ + function _drawBoxWhiskerV($x, $w, $r, $y_min, $y_q1, $y_med, $y_q3, $y_max, $key = false) + { + // draw circles + $this->_getLineStyle(); + $this->_getFillStyle('min'); + $this->_canvas->ellipse(array('x' => $x, 'y' => $y_min, 'rx' => $r, 'ry' => $r)); + + $this->_getLineStyle(); + $this->_getFillStyle('quartile1'); + $this->_canvas->ellipse(array('x' => $x, 'y' => $y_q1, 'rx' => $r, 'ry' => $r)); + + $this->_getLineStyle(); + $this->_getFillStyle('median'); + $this->_canvas->ellipse(array('x' => $x, 'y' => $y_med, 'rx' => $r, 'ry' => $r)); + + $this->_getLineStyle(); + $this->_getFillStyle('quartile3'); + $this->_canvas->ellipse(array('x' => $x, 'y' => $y_q3, $r, 'rx' => $r, 'ry' => $r)); + + $this->_getLineStyle(); + $this->_getFillStyle('max'); + $this->_canvas->ellipse(array('x' => $x, 'y' => $y_max, $r, 'rx' => $r, 'ry' => $r)); + + // draw box and lines + + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x, 'y0' => $y_min, 'x1' => $x, 'y1' => $y_q1)); + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x, 'y0' => $y_q3, 'x1' => $x, 'y1' => $y_max)); + + $this->_getLineStyle(); + $this->_getFillStyle('box'); + $this->_canvas->rectangle(array('x0' => $x - $w, 'y0' => $y_q1, 'x1' => $x + $w, 'y1' => $y_q3)); + + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x - $w, 'y0' => $y_med, 'x1' => $x + $w, 'y1' => $y_med)); + } + + /** + * Draws a box & whisker + * + * @param int $y The x position + * @param int $h The width of the box + * @param int $r The radius of the circle markers + * @param int $x_min The Y position of the minimum value + * @param int $x_q1 The Y position of the median of the first quartile + * @param int $x_med The Y position of the median + * @param int $x_q3 The Y position of the median of the third quartile + * @param int $x_max The Y position of the maximum value + * @param int $key The ID tag + * @access private + */ + function _drawBoxWhiskerH($y, $h, $r, $x_min, $x_q1, $x_med, $x_q3, $x_max, $key = false) + { + // draw circles + $this->_getLineStyle(); + $this->_getFillStyle('min'); + $this->_canvas->ellipse(array('x' => $x_min, 'y' => $y, 'rx' => $r, 'ry' => $r)); + + $this->_getLineStyle(); + $this->_getFillStyle('quartile1'); + $this->_canvas->ellipse(array('x' => $x_q1, 'y' => $y, 'rx' => $r, 'ry' => $r)); + + $this->_getLineStyle(); + $this->_getFillStyle('median'); + $this->_canvas->ellipse(array('x' => $x_med, 'y' => $y, 'rx' => $r, 'ry' => $r)); + + $this->_getLineStyle(); + $this->_getFillStyle('quartile3'); + $this->_canvas->ellipse(array('x' => $x_q3, 'y' => $y, $r, 'rx' => $r, 'ry' => $r)); + + $this->_getLineStyle(); + $this->_getFillStyle('max'); + $this->_canvas->ellipse(array('x' => $x_max, 'y' => $y, $r, 'rx' => $r, 'ry' => $r)); + + // draw box and lines + + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x_min, 'y0' => $y, 'x1' => $x_q1, 'y1' => $y)); + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x_q3, 'y0' => $y, 'x1' => $x_max, 'y1' => $y)); + + $this->_getLineStyle(); + $this->_getFillStyle('box'); + $this->_canvas->rectangle(array('x0' => $x_q1, 'y0' => $y - $h, 'x1' => $x_q3, 'y1' => $y + $h)); + + $this->_getLineStyle(); + $this->_canvas->line(array('x0' => $x_med, 'y0' => $y - $h, 'x1' => $x_med, 'y1' => $y + $h)); + } + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $x = round(($x0 + $x1) / 2); + $h = abs($y1 - $y0) / 9; + $w = round(abs($x1 - $x0) / 5); + $r = 2;//round(abs($x1 - $x0) / 13); + $this->_drawBoxWhiskerV($x, $w, $r, $y1, $y1 - 2 * $h, $y1 - 4 * $h, $y0 + 3 * $h, $y0); + } + + /** + * Sets the whisker circle size + * + * @param int $size Size (radius) of the whisker circle/dot + */ + function setWhiskerSize($size = false) + { + $this->_whiskerSize = $size; + } + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + if (!is_array($this->_dataset)) { + return false; + } + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + + $this->_clip(true); + + if ($this->_multiType == 'stacked100pct') { + $total = $this->_getTotals(); + } + $current = array(); + $number = 0; + $width = floor(0.5 * $this->_parent->_labelDistance(IMAGE_GRAPH_AXIS_X) / 2); + + if ($this->_whiskerSize !== false) { + $r = $this->_whiskerSize; + } else { + $r = min(5, $width / 10); + } + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + while ($data = $dataset->_next()) { + if ($this->_parent->_horizontal) { + $point['X'] = $data['X']; + $y = $data['Y']; + + $min = min($y); + $max = max($y); + $q1 = $dataset->_median($y, 'first'); + $med = $dataset->_median($y, 'second'); + $q3 = $dataset->_median($y, 'third'); + + $point['Y'] = $min; + $y = $this->_pointY($point); + $x_min = $this->_pointX($point); + + $point['Y'] = $max; + $x_max = $this->_pointX($point); + + $point['Y'] = $q1; + $x_q1 = $this->_pointX($point); + + $point['Y'] = $med; + $x_med = $this->_pointX($point); + + $point['Y'] = $q3; + $x_q3 = $this->_pointX($point); + + $this->_drawBoxWhiskerH($y, $width, $r, $x_min, $x_q1, $x_med, $x_q3, $x_max, $key); + } + else { + $point['X'] = $data['X']; + $y = $data['Y']; + + $min = min($y); + $max = max($y); + $q1 = $dataset->_median($y, 'first'); + $med = $dataset->_median($y, 'second'); + $q3 = $dataset->_median($y, 'third'); + + $point['Y'] = $min; + $x = $this->_pointX($point); + $y_min = $this->_pointY($point); + + $point['Y'] = $max; + $y_max = $this->_pointY($point); + + $point['Y'] = $q1; + $y_q1 = $this->_pointY($point); + + $point['Y'] = $med; + $y_med = $this->_pointY($point); + + $point['Y'] = $q3; + $y_q3 = $this->_pointY($point); + + $this->_drawBoxWhiskerV($x, $width, $r, $y_min, $y_q1, $y_med, $y_q3, $y_max, $key); + } + } + } + unset($keys); + $this->_drawMarker(); + + $this->_clip(false); + + $this->_canvas->endGroup(); + return true; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Plot/CandleStick.php b/includes/pear/Image/Graph/Plot/CandleStick.php index 025d701f..5251e799 100644 --- a/includes/pear/Image/Graph/Plot/CandleStick.php +++ b/includes/pear/Image/Graph/Plot/CandleStick.php @@ -1,247 +1,251 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: CandleStick.php,v 1.11 2005/08/30 21:25:24 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - * @since File available since Release 0.3.0dev2 - */ - -/** - * Include file Image/Graph/Plot.php - */ -require_once 'Image/Graph/Plot.php'; - -/** - * Candlestick chart. - * - * @category Images - * @package Image_Graph - * @subpackage Plot - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - * @since Class available since Release 0.3.0dev2 - */ -class Image_Graph_Plot_CandleStick extends Image_Graph_Plot -{ - - /** - * (Add basic description here) - * - * @access private - */ - function _drawCandleStickH($y, $h, $x_min, $x_open, $x_close, $x_max, $ID) - { - $this->_getLineStyle($ID); - $this->_canvas->line( - array( - 'x0' => min($x_open, $x_close), - 'y0' => $y, - 'x1' => $x_min, - 'y1' => $y - ) - ); - $this->_getLineStyle($ID); - $this->_canvas->line( - array( - 'x0' => max($x_open, $x_close), - 'y0' => $y, - 'x1' => $x_max, - 'y1' => $y - ) - ); - - $this->_getLineStyle($ID); - $this->_getFillStyle($ID); - $this->_canvas->rectangle( - array( - 'x0' => min($x_open, $x_close), - 'y0' => $y - $h, - 'x1' => max($x_open, $x_close), - 'y1' => $y + $h - ) - ); - } - - /** - * (Add basic description here) - * - * @access private - */ - function _drawCandleStickV($x, $w, $y_min, $y_open, $y_close, $y_max, $ID) - { - $this->_getLineStyle($ID); - $this->_canvas->line( - array( - 'x0' => $x, - 'y0' => min($y_open, $y_close), - 'x1' => $x, - 'y1' => $y_max - ) - ); - $this->_getLineStyle($ID); - $this->_canvas->line( - array( - 'x0' => $x, - 'y0' => max($y_open, $y_close), - 'x1' => $x, - 'y1' => $y_min - ) - ); - - $this->_getLineStyle($ID); - $this->_getFillStyle($ID); - $this->_canvas->rectangle( - array( - 'x0' => $x - $w, - 'y0' => min($y_open, $y_close), - 'x1' => $x + $w, - 'y1' => max($y_open, $y_close) - ) - ); - } - - /** - * Perform the actual drawing on the legend. - * - * @param int $x0 The top-left x-coordinate - * @param int $y0 The top-left y-coordinate - * @param int $x1 The bottom-right x-coordinate - * @param int $y1 The bottom-right y-coordinate - * @access private - */ - function _drawLegendSample($x0, $y0, $x1, $y1) - { - $x = round(($x0 + $x1) / 2); - $h = abs($y1 - $y0) / 4; - $w = round(abs($x1 - $x0) / 5); - $this->_drawCandleStickV($x, $w, $y1, $y1 - $h, $y0 + $h, $y0, 'green'); - } - - /** - * Output the plot - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (parent::_done() === false) { - return false; - } - - if (!is_array($this->_dataset)) { - return false; - } - - $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); - - if ($this->_multiType == 'stacked100pct') { - $total = $this->_getTotals(); - } - $current = array(); - $number = 0; - $width = floor(0.8 * $this->_parent->_labelDistance(IMAGE_GRAPH_AXIS_X) / 2); - - $lastClosed = false; - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $dataset =& $this->_dataset[$key]; - $dataset->_reset(); - while ($data = $dataset->_next()) { - if ($this->_parent->_horizontal) { - $point['X'] = $data['X']; - //$y = $data['Y']; - - if (isset($data['Y']['open'])) { - $point['Y'] = $data['Y']['open']; - } else { - $point['Y'] = $lastClosed; - } - $y = $this->_pointY($point); - $x_open = $this->_pointX($point); - - $lastClosed = $point['Y'] = $data['Y']['close']; - $x_close = $this->_pointX($point); - - $point['Y'] = $data['Y']['min']; - $x_min = $this->_pointX($point); - - $point['Y'] = $data['Y']['max']; - $x_max = $this->_pointX($point); - - if ($data['Y']['close'] < $data['Y']['open']) { - $ID = 'red'; - } else { - $ID = 'green'; - } - - $this->_drawCandleStickH($y, $width, $x_min, $x_open, $x_close, $x_max, $ID); - } - else { - $point['X'] = $data['X']; - //$y = $data['Y']; - - if (isset($data['Y']['open'])) { - $point['Y'] = $data['Y']['open']; - } else { - $point['Y'] = $lastClosed; - } - $x = $this->_pointX($point); - $y_open = $this->_pointY($point); - - $lastClosed = $point['Y'] = $data['Y']['close']; - $y_close = $this->_pointY($point); - - $point['Y'] = $data['Y']['min']; - $y_min = $this->_pointY($point); - - $point['Y'] = $data['Y']['max']; - $y_max = $this->_pointY($point); - - if ($data['Y']['close'] < $data['Y']['open']) { - $ID = 'red'; - } else { - $ID = 'green'; - } - - $this->_drawCandleStickV($x, $width, $y_min, $y_open, $y_close, $y_max, $ID); - } - } - } - unset($keys); - $this->_drawMarker(); - - $this->_canvas->endGroup($this->_title); - - return true; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: CandleStick.php,v 1.12 2005/11/27 22:21:16 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + * @since File available since Release 0.3.0dev2 + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * Candlestick chart. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + * @since Class available since Release 0.3.0dev2 + */ +class Image_Graph_Plot_CandleStick extends Image_Graph_Plot +{ + + /** + * (Add basic description here) + * + * @access private + */ + function _drawCandleStickH($y, $h, $x_min, $x_open, $x_close, $x_max, $ID) + { + $this->_getLineStyle($ID); + $this->_canvas->line( + array( + 'x0' => min($x_open, $x_close), + 'y0' => $y, + 'x1' => $x_min, + 'y1' => $y + ) + ); + $this->_getLineStyle($ID); + $this->_canvas->line( + array( + 'x0' => max($x_open, $x_close), + 'y0' => $y, + 'x1' => $x_max, + 'y1' => $y + ) + ); + + $this->_getLineStyle($ID); + $this->_getFillStyle($ID); + $this->_canvas->rectangle( + array( + 'x0' => min($x_open, $x_close), + 'y0' => $y - $h, + 'x1' => max($x_open, $x_close), + 'y1' => $y + $h + ) + ); + } + + /** + * (Add basic description here) + * + * @access private + */ + function _drawCandleStickV($x, $w, $y_min, $y_open, $y_close, $y_max, $ID) + { + $this->_getLineStyle($ID); + $this->_canvas->line( + array( + 'x0' => $x, + 'y0' => min($y_open, $y_close), + 'x1' => $x, + 'y1' => $y_max + ) + ); + $this->_getLineStyle($ID); + $this->_canvas->line( + array( + 'x0' => $x, + 'y0' => max($y_open, $y_close), + 'x1' => $x, + 'y1' => $y_min + ) + ); + + $this->_getLineStyle($ID); + $this->_getFillStyle($ID); + $this->_canvas->rectangle( + array( + 'x0' => $x - $w, + 'y0' => min($y_open, $y_close), + 'x1' => $x + $w, + 'y1' => max($y_open, $y_close) + ) + ); + } + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $x = round(($x0 + $x1) / 2); + $h = abs($y1 - $y0) / 4; + $w = round(abs($x1 - $x0) / 5); + $this->_drawCandleStickV($x, $w, $y1, $y1 - $h, $y0 + $h, $y0, 'green'); + } + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + if (!is_array($this->_dataset)) { + return false; + } + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + + $this->_clip(true); + + if ($this->_multiType == 'stacked100pct') { + $total = $this->_getTotals(); + } + $current = array(); + $number = 0; + $width = floor(0.8 * $this->_parent->_labelDistance(IMAGE_GRAPH_AXIS_X) / 2); + + $lastClosed = false; + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + while ($data = $dataset->_next()) { + if ($this->_parent->_horizontal) { + $point['X'] = $data['X']; + //$y = $data['Y']; + + if (isset($data['Y']['open'])) { + $point['Y'] = $data['Y']['open']; + } else { + $point['Y'] = $lastClosed; + } + $y = $this->_pointY($point); + $x_open = $this->_pointX($point); + + $lastClosed = $point['Y'] = $data['Y']['close']; + $x_close = $this->_pointX($point); + + $point['Y'] = $data['Y']['min']; + $x_min = $this->_pointX($point); + + $point['Y'] = $data['Y']['max']; + $x_max = $this->_pointX($point); + + if ($data['Y']['close'] < $data['Y']['open']) { + $ID = 'red'; + } else { + $ID = 'green'; + } + + $this->_drawCandleStickH($y, $width, $x_min, $x_open, $x_close, $x_max, $ID); + } + else { + $point['X'] = $data['X']; + //$y = $data['Y']; + + if (isset($data['Y']['open'])) { + $point['Y'] = $data['Y']['open']; + } else { + $point['Y'] = $lastClosed; + } + $x = $this->_pointX($point); + $y_open = $this->_pointY($point); + + $lastClosed = $point['Y'] = $data['Y']['close']; + $y_close = $this->_pointY($point); + + $point['Y'] = $data['Y']['min']; + $y_min = $this->_pointY($point); + + $point['Y'] = $data['Y']['max']; + $y_max = $this->_pointY($point); + + if ($data['Y']['close'] < $data['Y']['open']) { + $ID = 'red'; + } else { + $ID = 'green'; + } + + $this->_drawCandleStickV($x, $width, $y_min, $y_open, $y_close, $y_max, $ID); + } + } + } + unset($keys); + $this->_drawMarker(); + + $this->_clip(false); + + $this->_canvas->endGroup($this->_title); + + return true; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Plot/Dot.php b/includes/pear/Image/Graph/Plot/Dot.php index 13bf16b8..2bde1908 100644 --- a/includes/pear/Image/Graph/Plot/Dot.php +++ b/includes/pear/Image/Graph/Plot/Dot.php @@ -1,95 +1,99 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Dot.php,v 1.10 2005/08/03 21:21:56 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Plot.php - */ -require_once 'Image/Graph/Plot.php'; - -/** - * Dot / scatter chart (only marker). - * - * This plot type only displays a {@link Image_Graph_Marker} for the datapoints. - * The marker must explicitly be defined using {@link Image_Graph_Plot:: - * setMarker()}. - * - * @category Images - * @package Image_Graph - * @subpackage Plot - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Plot_Dot extends Image_Graph_Plot -{ - - /** - * Perform the actual drawing on the legend. - * - * @param int $x0 The top-left x-coordinate - * @param int $y0 The top-left y-coordinate - * @param int $x1 The bottom-right x-coordinate - * @param int $y1 The bottom-right y-coordinate - * @access private - */ - function _drawLegendSample($x0, $y0, $x1, $y1) - { - if (isset($this->_marker)) { - $key = key($this->_dataset); - $samplePoint = $this->_dataset[$key]->_nearby(); - $this->_marker->_drawMarker(($x0 + $x1) / 2, ($y0 + $y1) / 2, $samplePoint); - } - } - - /** - * Output the plot - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (Image_Graph_Plot::_done() === false) { - return false; - } - - $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); - - $this->_drawMarker(); - - $this->_canvas->endGroup(); - - return true; - } -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Dot.php,v 1.11 2005/11/27 22:21:16 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * Dot / scatter chart (only marker). + * + * This plot type only displays a {@link Image_Graph_Marker} for the datapoints. + * The marker must explicitly be defined using {@link Image_Graph_Plot:: + * setMarker()}. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Plot_Dot extends Image_Graph_Plot +{ + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + if (isset($this->_marker)) { + $key = key($this->_dataset); + $samplePoint = $this->_dataset[$key]->_nearby(); + $this->_marker->_drawMarker(($x0 + $x1) / 2, ($y0 + $y1) / 2, $samplePoint); + } + } + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (Image_Graph_Plot::_done() === false) { + return false; + } + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + + $this->_clip(true); + + $this->_drawMarker(); + + $this->_clip(false); + + $this->_canvas->endGroup(); + + return true; + } +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Plot/Fit/Line.php b/includes/pear/Image/Graph/Plot/Fit/Line.php index c182a3c2..39455a6c 100644 --- a/includes/pear/Image/Graph/Plot/Fit/Line.php +++ b/includes/pear/Image/Graph/Plot/Fit/Line.php @@ -1,116 +1,118 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Line.php,v 1.1 2005/09/14 20:27:25 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Plot.php - */ -require_once 'Image/Graph/Plot.php'; - -/** - * Include file Image/Graph/Tool.php - */ -require_once 'Image/Graph/Tool.php'; - -/** - * Fit the graph (to a line using linear regression). - * - * @category Images - * @package Image_Graph - * @subpackage Plot - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Plot_Fit_Line extends Image_Graph_Plot -{ - - /** - * Perform the actual drawing on the legend. - * - * @param int $x0 The top-left x-coordinate - * @param int $y0 The top-left y-coordinate - * @param int $x1 The bottom-right x-coordinate - * @param int $y1 The bottom-right y-coordinate - * @access private - */ - function _drawLegendSample($x0, $y0, $x1, $y1) - { - $y = ($y0 + $y1) / 2; - $dy = abs($y1 - $y0) / 6; - $this->_canvas->addVertex(array('x' => $x0, 'y' => $y + $dy)); - $this->_canvas->addVertex(array('x' => $x1, 'y' => $y - $dy)); - $this->_canvas->polygon(array('connect' => false)); - } - - /** - * Output the plot - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (Image_Graph_Plot::_done() === false) { - return false; - } - - $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $dataset =& $this->_dataset[$key]; - $dataset->_reset(); - $data = array(); - while ($point = $dataset->_next()) { - $data[] = array( - 'X' => $this->_pointX($point), - 'Y' => $this->_pointY($point) - ); - } - - $regression = Image_Graph_Tool::calculateLinearRegression($data); - $this->_getLineStyle($key); - $this->_canvas->line( - array( - 'x0' => $this->_left, - 'y0' => $this->_left * $regression['slope'] + $regression['intersection'], - 'x1' => $this->_right, - 'y1' => $this->_right * $regression['slope'] + $regression['intersection'] - ) - ); - } - $this->_canvas->endGroup(); - - return true; - } -} - -?> + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Line.php,v 1.2 2005/11/27 22:21:18 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * Include file Image/Graph/Tool.php + */ +require_once 'Image/Graph/Tool.php'; + +/** + * Fit the graph (to a line using linear regression). + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Plot_Fit_Line extends Image_Graph_Plot +{ + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $y = ($y0 + $y1) / 2; + $dy = abs($y1 - $y0) / 6; + $this->_canvas->addVertex(array('x' => $x0, 'y' => $y + $dy)); + $this->_canvas->addVertex(array('x' => $x1, 'y' => $y - $dy)); + $this->_canvas->polygon(array('connect' => false)); + } + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (Image_Graph_Plot::_done() === false) { + return false; + } + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + $this->_clip(true); + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + $data = array(); + while ($point = $dataset->_next()) { + $data[] = array( + 'X' => $this->_pointX($point), + 'Y' => $this->_pointY($point) + ); + } + + $regression = Image_Graph_Tool::calculateLinearRegression($data); + $this->_getLineStyle($key); + $this->_canvas->line( + array( + 'x0' => $this->_left, + 'y0' => $this->_left * $regression['slope'] + $regression['intersection'], + 'x1' => $this->_right, + 'y1' => $this->_right * $regression['slope'] + $regression['intersection'] + ) + ); + } + $this->_clip(false); + $this->_canvas->endGroup(); + + return true; + } +} + +?> diff --git a/includes/pear/Image/Graph/Plot/Impulse.php b/includes/pear/Image/Graph/Plot/Impulse.php index 64a8207b..ed9e4ad3 100644 --- a/includes/pear/Image/Graph/Plot/Impulse.php +++ b/includes/pear/Image/Graph/Plot/Impulse.php @@ -1,203 +1,204 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Impulse.php,v 1.12 2005/08/08 19:09:18 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Plot.php - */ -require_once 'Image/Graph/Plot.php'; - -/** - * Impulse chart. - * - * @category Images - * @package Image_Graph - * @subpackage Plot - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Plot_Impulse extends Image_Graph_Plot -{ - - /** - * Perform the actual drawing on the legend. - * - * @param int $x0 The top-left x-coordinate - * @param int $y0 The top-left y-coordinate - * @param int $x1 The bottom-right x-coordinate - * @param int $y1 The bottom-right y-coordinate - * @access private - */ - function _drawLegendSample($x0, $y0, $x1, $y1) - { - $x = ($x0 + $x1) / 2; - $this->_canvas->line(array('x0' => $x, 'y0' => $y0, 'x1' => $x, 'y1' => $y1)); - } - - /** - * Output the plot - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (parent::_done() === false) { - return false; - } - - if (!is_array($this->_dataset)) { - return false; - } - - $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); - - - if ($this->_multiType == 'stacked100pct') { - $total = $this->_getTotals(); - } - $current = array(); - $number = 0; - - $minYaxis = $this->_parent->_getMinimum($this->_axisY); - $maxYaxis = $this->_parent->_getMaximum($this->_axisY); - - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $dataset =& $this->_dataset[$key]; - $dataset->_reset(); - while ($point = $dataset->_next()) { - $x0 = $this->_pointX($point); - if (($this->_multiType == 'stacked') || - ($this->_multiType == 'stacked100pct')) - { - $x = $point['X']; - - if ($point['Y'] >= 0) { - if (!isset($current[$x])) { - $current[$x] = 0; - } - - if ($this->_multiType == 'stacked') { - $p0 = array( - 'X' => $point['X'], - 'Y' => $current[$x] - ); - $p1 = array( - 'X' => $point['X'], - 'Y' => $current[$x] + $point['Y'] - ); - } else { - $p0 = array( - 'X' => $point['X'], - 'Y' => 100 * $current[$x] / $total['TOTAL_Y'][$x] - ); - $p1 = array( - 'X' => $point['X'], - 'Y' => 100 * ($current[$x] + $point['Y']) / $total['TOTAL_Y'][$x] - ); - } - $current[$x] += $point['Y']; - } else { - if (!isset($currentNegative[$x])) { - $currentNegative[$x] = 0; - } - - $p0 = array( - 'X' => $point['X'], - 'Y' => $currentNegative[$x] - ); - $p1 = array( - 'X' => $point['X'], - 'Y' => $currentNegative[$x] + $point['Y'] - ); - $currentNegative[$x] += $point['Y']; - } - } else { - $p0 = array('X' => $point['X'], 'Y' => 0); - $p1 = $point; - } - - if ((($minY = min($p0['Y'], $p1['Y'])) < $maxYaxis) && - (($maxY = max($p0['Y'], $p1['Y'])) > $minYaxis) - ) { - $p0['Y'] = $minY; - $p1['Y'] = $maxY; - - if ($p0['Y'] < $minYaxis) { - $p0['Y'] = '#min_pos#'; - } - if ($p1['Y'] > $maxYaxis) { - $p1['Y'] = '#max_neg#'; - } - - $x1 = $this->_pointX($p0); - $y1 = $this->_pointY($p0); - - $x2 = $this->_pointX($p1); - $y2 = $this->_pointY($p1); - - if ($this->_multiType == 'normal') { - $offset = 5*$number; - $x1 += $offset; - $x2 += $offset; - } - - $ID = $point['ID']; - if (($ID === false) && (count($this->_dataset) > 1)) { - $ID = $key; - } - $this->_getLineStyle($key); - $this->_canvas->line( - $this->_mergeData( - $point, - array( - 'x0' => $x1, - 'y0' => $y1, - 'x1' => $x2, - 'y1' => $y2 - ) - ) - ); - } - } - $number++; - } - unset($keys); - $this->_drawMarker(); - $this->_canvas->endGroup(); - return true; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Impulse.php,v 1.13 2005/11/27 22:21:17 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * Impulse chart. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Plot_Impulse extends Image_Graph_Plot +{ + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $x = ($x0 + $x1) / 2; + $this->_canvas->line(array('x0' => $x, 'y0' => $y0, 'x1' => $x, 'y1' => $y1)); + } + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + if (!is_array($this->_dataset)) { + return false; + } + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + $this->_clip(true); + + if ($this->_multiType == 'stacked100pct') { + $total = $this->_getTotals(); + } + $current = array(); + $number = 0; + + $minYaxis = $this->_parent->_getMinimum($this->_axisY); + $maxYaxis = $this->_parent->_getMaximum($this->_axisY); + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + while ($point = $dataset->_next()) { + $x0 = $this->_pointX($point); + if (($this->_multiType == 'stacked') || + ($this->_multiType == 'stacked100pct')) + { + $x = $point['X']; + + if ($point['Y'] >= 0) { + if (!isset($current[$x])) { + $current[$x] = 0; + } + + if ($this->_multiType == 'stacked') { + $p0 = array( + 'X' => $point['X'], + 'Y' => $current[$x] + ); + $p1 = array( + 'X' => $point['X'], + 'Y' => $current[$x] + $point['Y'] + ); + } else { + $p0 = array( + 'X' => $point['X'], + 'Y' => 100 * $current[$x] / $total['TOTAL_Y'][$x] + ); + $p1 = array( + 'X' => $point['X'], + 'Y' => 100 * ($current[$x] + $point['Y']) / $total['TOTAL_Y'][$x] + ); + } + $current[$x] += $point['Y']; + } else { + if (!isset($currentNegative[$x])) { + $currentNegative[$x] = 0; + } + + $p0 = array( + 'X' => $point['X'], + 'Y' => $currentNegative[$x] + ); + $p1 = array( + 'X' => $point['X'], + 'Y' => $currentNegative[$x] + $point['Y'] + ); + $currentNegative[$x] += $point['Y']; + } + } else { + $p0 = array('X' => $point['X'], 'Y' => 0); + $p1 = $point; + } + + if ((($minY = min($p0['Y'], $p1['Y'])) < $maxYaxis) && + (($maxY = max($p0['Y'], $p1['Y'])) > $minYaxis) + ) { + $p0['Y'] = $minY; + $p1['Y'] = $maxY; + + if ($p0['Y'] < $minYaxis) { + $p0['Y'] = '#min_pos#'; + } + if ($p1['Y'] > $maxYaxis) { + $p1['Y'] = '#max_neg#'; + } + + $x1 = $this->_pointX($p0); + $y1 = $this->_pointY($p0); + + $x2 = $this->_pointX($p1); + $y2 = $this->_pointY($p1); + + if ($this->_multiType == 'normal') { + $offset = 5*$number; + $x1 += $offset; + $x2 += $offset; + } + + $ID = $point['ID']; + if (($ID === false) && (count($this->_dataset) > 1)) { + $ID = $key; + } + $this->_getLineStyle($key); + $this->_canvas->line( + $this->_mergeData( + $point, + array( + 'x0' => $x1, + 'y0' => $y1, + 'x1' => $x2, + 'y1' => $y2 + ) + ) + ); + } + } + $number++; + } + unset($keys); + $this->_drawMarker(); + $this->_clip(false); + $this->_canvas->endGroup(); + return true; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Plot/Line.php b/includes/pear/Image/Graph/Plot/Line.php index f9b715a3..cfc89780 100644 --- a/includes/pear/Image/Graph/Plot/Line.php +++ b/includes/pear/Image/Graph/Plot/Line.php @@ -1,164 +1,171 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Line.php,v 1.12 2005/08/08 19:09:18 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Plot.php - */ -require_once 'Image/Graph/Plot.php'; - -/** - * Linechart. - * - * @category Images - * @package Image_Graph - * @subpackage Plot - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Plot_Line extends Image_Graph_Plot -{ - - /** - * Gets the fill style of the element - * - * @return int A GD filestyle representing the fill style - * @see Image_Graph_Fill - * @access private - */ - function _getFillStyle($ID = false) - { - return IMG_COLOR_TRANSPARENT; - } - - /** - * Perform the actual drawing on the legend. - * - * @param int $x0 The top-left x-coordinate - * @param int $y0 The top-left y-coordinate - * @param int $x1 The bottom-right x-coordinate - * @param int $y1 The bottom-right y-coordinate - * @access private - */ - function _drawLegendSample($x0, $y0, $x1, $y1) - { - $y = ($y0 + $y1) / 2; - $dx = abs($x1 - $x0) / 3; - $dy = abs($y1 - $y0) / 5; - $this->_canvas->addVertex(array('x' => $x0, 'y' => $y)); - $this->_canvas->addVertex(array('x' => $x0 + $dx, 'y' => $y - $dy * 2)); - $this->_canvas->addVertex(array('x' => $x1 - $dx, 'y' => $y + $dy)); - $this->_canvas->addVertex(array('x' => $x1, 'y' => $y - $dy)); - $this->_canvas->polygon(array('connect' => false)); - } - - /** - * Output the plot - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (parent::_done() === false) { - return false; - } - - if (!is_array($this->_dataset)) { - return false; - } - - $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); - - reset($this->_dataset); - - if ($this->_multiType == 'stacked100pct') { - $total = $this->_getTotals(); - } - - $p1 = false; - - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $dataset =& $this->_dataset[$key]; - $dataset->_reset(); - $numPoints = 0; - while ($point = $dataset->_next()) { - if (($this->_multiType == 'stacked') || - ($this->_multiType == 'stacked100pct')) - { - $x = $point['X']; - if (!isset($current[$x])) { - $current[$x] = 0; - } - if ($this->_multiType == 'stacked') { - $py = $current[$x] + $point['Y']; - } else { - $py = 100 * ($current[$x] + $point['Y']) / $total['TOTAL_Y'][$x]; - } - $current[$x] += $point['Y']; - $point['Y'] = $py; - } - - if ($point['Y'] === null) { - if ($numPoints > 1) { - $this->_getLineStyle($key); - $this->_canvas->polygon(array('connect' => false, 'map_vertices' => true)); - } - $numPoints = 0; - } else { - $p2['X'] = $this->_pointX($point); - $p2['Y'] = $this->_pointY($point); - - $this->_canvas->addVertex( - $this->_mergeData( - $point, - array('x' => $p2['X'], 'y' => $p2['Y']) - ) - ); - $numPoints++; - } - } - if ($numPoints > 1) { - $this->_getLineStyle($key); - $this->_canvas->polygon(array('connect' => false, 'map_vertices' => true)); - } - } - unset($keys); - $this->_drawMarker(); - $this->_canvas->endGroup(); - return true; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Line.php,v 1.15 2006/03/02 12:37:37 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * Linechart. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Plot_Line extends Image_Graph_Plot +{ + + /** + * Gets the fill style of the element + * + * @return int A GD filestyle representing the fill style + * @see Image_Graph_Fill + * @access private + */ + function _getFillStyle($ID = false) + { + return IMG_COLOR_TRANSPARENT; + } + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $y = ($y0 + $y1) / 2; + $dx = abs($x1 - $x0) / 3; + $dy = abs($y1 - $y0) / 5; + $this->_canvas->addVertex(array('x' => $x0, 'y' => $y)); + $this->_canvas->addVertex(array('x' => $x0 + $dx, 'y' => $y - $dy * 2)); + $this->_canvas->addVertex(array('x' => $x1 - $dx, 'y' => $y + $dy)); + $this->_canvas->addVertex(array('x' => $x1, 'y' => $y - $dy)); + $this->_canvas->polygon(array('connect' => false)); + } + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + if (!is_array($this->_dataset)) { + return false; + } + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + $this->_clip(true); + reset($this->_dataset); + + if ($this->_multiType == 'stacked100pct') { + $total = $this->_getTotals(); + } + + $p1 = false; + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + $numPoints = 0; + while ($point = $dataset->_next()) { + if (($this->_multiType == 'stacked') || + ($this->_multiType == 'stacked100pct')) + { + $x = $point['X']; + if (!isset($current[$x])) { + $current[$x] = 0; + } + if ($this->_multiType == 'stacked') { + $py = $current[$x] + $point['Y']; + } else { + $py = 100 * ($current[$x] + $point['Y']) / $total['TOTAL_Y'][$x]; + } + $current[$x] += $point['Y']; + $point['Y'] = $py; + } + + if ($point['Y'] === null) { + if ($numPoints > 1) { + $this->_getLineStyle($key); + $this->_canvas->polygon(array('connect' => false, 'map_vertices' => true)); + } + else { + $this->_canvas->reset(); + } + $numPoints = 0; + } else { + $p2['X'] = $this->_pointX($point); + $p2['Y'] = $this->_pointY($point); + + $this->_canvas->addVertex( + $this->_mergeData( + $point, + array('x' => $p2['X'], 'y' => $p2['Y']) + ) + ); + $numPoints++; + } + } + if ($numPoints > 1) { + $this->_getLineStyle($key); + $this->_canvas->polygon(array('connect' => false, 'map_vertices' => true)); + } + else { + $this->_canvas->reset(); + } + } + unset($keys); + $this->_drawMarker(); + $this->_clip(false); + $this->_canvas->endGroup(); + return true; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Plot/Odo.php b/includes/pear/Image/Graph/Plot/Odo.php index 4216b450..0a567a36 100644 --- a/includes/pear/Image/Graph/Plot/Odo.php +++ b/includes/pear/Image/Graph/Plot/Odo.php @@ -1,717 +1,719 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Odo.php,v 1.2 2005/09/30 18:59:19 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Plot.php - */ -require_once 'Image/Graph/Plot.php'; - -/** - * Include file Image/Graph/Tool.php - */ -require_once 'Image/Graph/Tool.php'; - -/** - * 2D Odochart. - * - * @category Images - * @package Image_Graph - * @subpackage Plot - * @author Maxime Delorme - * @copyright Copyright (C) 2005 Maxime Delorme - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Plot_Odo extends Image_Graph_Plot -{ - /** - * the percent of the radius of the chart that will be use as the width of the range - * @access private - * @var int - */ - var $_radiusPercent = 50; - - /** - * the minimun value of the chart or the start value - * @access private - * @var int - */ - var $_value_min = 0; - - /** - * the maximum value of the chart or the end value - * @access private - * @var int - */ - var $_value_max = 100; - - /** - * the start angle - * @access private - * @var int - */ - var $_deg_offset = 135; - - /** - * the angle of the chart , the length of the chart - * 180 min a half circle - * @access private - * @var int - */ - var $_deg_width = 270; - - /** - * the length of the big ticks - * the small ones will be half ot it, the values 160% of it - * 180 min a half circle - * @access private - * @var int - */ - var $_tickLength = 14; - - /** - * how many small ticks a big tick appears - * the small ticks appear every 6° - * so with the default value of 5, every 30° there is a value and a big tick - * 180 min a half circle - * @access private - * @var int - */ - var $_axisTicks = 5; - - /** - * Arrow marker - * @access private - * @var Image_Graph_Marker - */ - var $_arrowMarker; - - /** - * Range marker fill style - * @access private - * @var Image_Graph_Fill - */ - var $_rangeFillStyle = null; - - /** - * The width of the arrow - * @access private - * @var int - */ - var $_arrowWidth = 5; - - /** - * The length of the arrow - * @access private - * @var int - */ - var $_arrowLength = 80; - - /** - * The radius of the plot - * @access private - * @var int - */ - var $_radius = false; - - /** - * The total Y - * @access private - * @var int - */ - var $_totalY = false; - - /** - * Center X of odometer "circle" - * @access private - * @var int - */ - var $_centerX = false; - - /** - * Center y of odometer "circle" - * @access private - * @var int - */ - var $_centerY = false; - - /** - * Plot_Odo [Constructor] - * - * dataset with one data per arrow - * @param Image_Graph_Dataset $dataset The data set (value containter) to - * plot or an array of datasets - * {@link Image_Graph_Legend} - */ - function Image_Graph_Plot_Odo(&$dataset) - { - parent::Image_Graph_Plot($dataset); - - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $dataset =& $this->_dataset[$key]; - if (isset($min)) { - $min = min($dataset->minimumY(), $min); - } - else { - $min = $dataset->minimumY(); - } - if (isset($max)) { - $max = max($dataset->maximumY(), $max); - } - else { - $max = $dataset->maximumY(); - } - } - $this->_value_min = $min; - $this->_value_max = $max; - } - - /** - * Set the center of the odometer - * - * @param int $centerX The center x point - * @param int $centerY The center y point - */ - function setCenter($centerX, $centerY) - { - $this->_centerX = $centerX; - $this->_centerY = $centerY; - } - - /** - * Convert a value to the angle position onto the odometer - * - * @access private - * @param int $value the value to convert - * @return int the angle'position onto the odometer - */ - function _value2angle($value) - { - return $this->_deg_width * (($value - $this->_value_min) / $this->_totalY) + $this->_deg_offset; - } - - /** - * set some internal var - * - * @access private - */ - function _initialize() - { - $v1 = $this->_deg_offset; - $v2 = $this->_deg_offset + $this->_deg_width; - - $dimensions = Image_Graph_Tool::calculateArcDimensionAndCenter($v1, $v2); - - $radiusX = ($this->width() / 2) / $dimensions['rx']; - $radiusY = ($this->height() / 2) / $dimensions['ry']; - - $this->_radius = min($radiusX, $radiusY); - - if ($this->_marker) { - $this->_radius = $this->_radius * 0.85; - } - - //the center of the plot - if ($this->_centerX === false) { - $this->_centerX = (int) (($this->_left + $this->_right) / 2) + - $this->_radius * ($dimensions['cx'] - 0.5); - } - - if ($this->_centerY === false) { - $this->_centerY = (int) (($this->_top + $this->_bottom) / 2) + - $this->_radius * ($dimensions['cy'] - 0.5); - } - - //the max range - $this->_totalY = abs($this->_value_max - $this->_value_min); - } - - /** - * set min and max value of the range - * - * @access public - * @param integer $value_min the minimun value of the chart or the start value - * @param integer $value_max the maximum value of the chart or the end value - */ - function setRange($value_min, $value_max) - { - $this->_value_min = $value_min; - $this->_value_max = $value_max; - } - - /** - * Set start's angle and amplitude of the chart - * - * @access public - * @param integer $deg_offset the start angle - * @param integer $deg_width the angle of the chart (the length) - */ - function setAngles($deg_offset, $deg_width) - { - $this->_deg_offset = min(360, abs($deg_offset)); - $this->_deg_width = min(360, abs($deg_width)); - } - - /** - * set the width of the chart - * - * @access public - * @param string $radius_percent a value between 0 and 100 - */ - function setRadiusWidth($radius_percent) - { - $this->_radiusPercent = $radius_percent; - } - - /** - * set the width and length of the arrow (in percent of the total plot "radius") - * - * @param int length The length in percent - * @param int width The width in percent - */ - function setArrowSize($length, $width) - { - $this->_arrowWidth = max(0, min(100, $width)); - $this->_arrowLength = max(0, min(100, $length)); - } - - /** - * Set the arrow marker - * @param Image_Graph_Marker $marker The marker to set for arrow marker - */ - function setArrowMarker(&$marker) - { - $this->_arrowMarker =& $marker; - } - - - /** - * Output the plot - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (parent::_done() === false) { - return false; - } - $this->_initialize(); - $this->_drawRange(); - $this->_drawAxis(); - $this->_drawArrow(); - $this->_drawMarker(); - return true; - } - - /** - * set the length of the ticks - * - * @access public - * @param string $radius_percent a value between 0 and 100 - */ - function setTickLength($radius) - { - $this->_tickLength = $radius; - } - - /** - * set the length of the ticks - * - * @access public - * @param string $radius_percent a value between 0 and 100 - */ - function setAxisTicks($int) - { - $this->_axisTicks = $int; - } - - /** - * Draw the outline and the axis - * - * @access private - */ - function _drawAxis() - { - //draw outline - $this->_getLineStyle(); - $this->_canvas->pieslice( - array( - 'x' => $this->_centerX, - 'y' => $this->_centerY, - 'rx' => $this->_radius, - 'ry' => $this->_radius, - 'v1' => $this->_deg_offset, - 'v2' => $this->_deg_offset+$this->_deg_width, - 'srx' => $this->_radius * (1 - $this->_radiusPercent / 100), - 'sry' => $this->_radius * (1 - $this->_radiusPercent / 100) - ) - ); - - //step for every 6° - $step = (int) ($this->_totalY / $this->_deg_width * 6); - $value = $this->_value_min; - $i = 0; - while ($value <= $this->_value_max) { - $angle = $this->_value2angle($value); - - $cos = cos(deg2rad($angle)); - $sin = sin(deg2rad($angle)); - $point = array('Y' => $value); - $point['AX'] = $cos; - $point['AY'] = $sin; - $point['LENGTH'] = 1; - $x = $this->_centerX + $this->_radius * $cos; - $y = $this->_centerY + $this->_radius * $sin; - $deltaX = - $cos * $this->_tickLength ; - $deltaY = - $sin * $this->_tickLength ; - $this->_getLineStyle(); - if(($i % $this->_axisTicks) == 0){ - $this->_canvas->line(array('x0' => $x, 'y0' => $y, 'x1' => $x + $deltaX, 'y1' => $y + $deltaY)); - if ($this->_arrowMarker) { - $this->_arrowMarker->_drawMarker($x + $deltaX * 1.6, $y + $deltaY *1.6, $point); - } - } else { - $this->_canvas->line(array('x0' => $x, 'y0' => $y, 'x1' => $x + $deltaX * 0.5, 'y1' => $y + $deltaY * 0.5)); - } - $i++; - $value += $step; - } - - } - - /** - * Set the line style of the arrows - * - * @param Image_Graph_Line $lineStyle The line style of the Arrow - * @see Image_Graph_Line - * @access public - */ - function setArrowLineStyle($lineStyle) - { - $this->_arrowLineStyle = &$lineStyle; - } - - /** - * Set the fillstyle of the arrows - * - * @param Image_Graph_Fill $fillStyle The fill style of the arrows - * @see Image_Graph_Fill - * @access public - */ - function setArrowFillStyle($fillStyle) - { - $this->_arrowFillStyle = &$fillStyle; - } - - /** - * Draw the arrows - * - * @access private - */ - function _drawArrow() - { - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $dataset =& $this->_dataset[$key]; - $dataset->_reset(); - $this->setLineStyle($this->_arrowLineStyle); - $this->setFillStyle($this->_arrowFillStyle); - while ($point = $dataset->_next()) { - $ID = $point['ID']; - $this->_getFillStyle($ID); - $this->_getLineStyle($ID); - $deg = $this->_value2angle($point['Y']); - list($xr,$yr) = Image_Graph_Tool::rotate($this->_centerX + $this->_arrowLength * $this->_radius / 100, $this->_centerY, $this->_centerX, $this->_centerY, $deg); - $this->_canvas->addVertex(array('x' => $xr, 'y' => $yr)); - list($xr,$yr) = Image_Graph_Tool::rotate($this->_centerX, $this->_centerY - $this->_arrowWidth * $this->_radius/100, $this->_centerX, $this->_centerY, $deg); - $this->_canvas->addVertex(array('x' => $xr, 'y' => $yr)); - list($xr,$yr) = Image_Graph_Tool::rotate($this->_centerX - $this->_arrowWidth * $this->_radius / 100, $this->_centerY, $this->_centerX, $this->_centerY, $deg); - $this->_canvas->addVertex(array('x' => $xr, 'y' => $yr)); - list($xr,$yr) = Image_Graph_Tool::rotate($this->_centerX,$this->_centerY + $this->_arrowWidth * $this->_radius / 100, $this->_centerX, $this->_centerY, $deg); - $this->_canvas->addVertex(array('x' => $xr, 'y' => $yr)); - $this->_canvas->polygon(array('connect' => true)); - } - } - } - - /** - * Calculate marker point data - * - * @param array $point The point to calculate data for - * @param array $nextPoint The next point - * @param array $prevPoint The previous point - * @param array $totals The pre-calculated totals, if needed - * @return array An array containing marker point data - * @access private - */ - function _getMarkerData($point, $nextPoint, $prevPoint, &$totals) - { - $point = parent::_getMarkerData($point, $nextPoint, $prevPoint, $totals); - - $point['ANGLE'] = $this->_value2angle($point['Y']); - - $point['ANG_X'] = cos(deg2rad($point['ANGLE'])); - $point['ANG_Y'] = sin(deg2rad($point['ANGLE'])); - - $point['AX'] = -$point['ANG_X']; - $point['AY'] = -$point['ANG_Y']; - - $point['LENGTH'] = 2.5; //$radius; - - $point['MARKER_X'] = $totals['CENTER_X'] + - $totals['ODO_RADIUS'] * $point['ANG_X']; - $point['MARKER_Y'] = $totals['CENTER_Y'] + - $totals['ODO_RADIUS'] * $point['ANG_Y']; - - return $point; - } - - /** - * Draws markers of the arrows on the canvas - * - * @access private - */ - function _drawMarker() - { - - if ($this->_marker) { - $this->_marker->_radius += $this->_radius / 2; - $totals = $this->_getTotals(); - - $totals['CENTER_X'] = $this->_centerX; - $totals['CENTER_Y'] = $this->_centerY; - - - /* $keys = array_keys($this->_dataset); - foreach ($keys as $key) { */ - $dataset =& $this->_dataset[0]; - - $totals['RADIUS0'] = false; - $totals['ODO_RADIUS'] = 1.1 * $this->_radius * $this->_arrowLength / 100; - $totals['ALL_SUM_Y'] = $this->_totalY; - - $dataset->_reset(); - while ($point = $dataset->_next()) { - if ((!is_object($this->_dataSelector)) || - ($this->_dataSelector->select($point)) - ) { - $point = $this->_getMarkerData( - $point, - false, - false, - $totals - ); - if (is_array($point)) { - $this->_marker->_drawMarker( - $point['MARKER_X'], - $point['MARKER_Y'], - $point - ); - } - } - } - /* } - unset($keys); */ - } - } - - /** - * Set range - * - * dataset with two data start and end value of the range - * @param Image_Graph_Dataset $dataset The data set (value containter) to - * plot or an array of datasets - * - */ - function addRangeMarker($min, $max, $id = false) - { - $this->_range[] = - array( - 'min' => max($this->_value_min, min($min, $max)), - 'max' => min($this->_value_max, max($min, $max)), - 'id' => $id - ); - } - - /** - * Set the fillstyle of the ranges - * - * @param Image_Graph_Fill $fillStyle The fill style of the range - * @see Image_Graph_Fill - * @access public - */ - function &setRangeMarkerFillStyle(&$rangeMarkerFillStyle) - { - $this->_rangeFillStyle = $rangeMarkerFillStyle; - } - - /** - * Draw the ranges - * - * @access private - */ - function _drawRange() - { - if($this->_range){ - $radius0 = $this->_radius * (1 - $this->_radiusPercent/100); - foreach ($this->_range as $range) { - $angle1 = $this->_value2angle($range['min']); - $angle2 = $this->_value2angle($range['max']); - - if (is_object($this->_rangeFillStyle)) { - $this->_canvas->setFill($this->_rangeFillStyle->_getFillStyle($range['id'])); - } elseif ($this->_rangeFillStyle != null) { - $this->_canvas->setFill($this->_rangeFillStyle); - } - $this->_getLineStyle(); - $this->_canvas->Pieslice( - array( - 'x' => $this->_centerX, - 'y' => $this->_centerY, - 'rx' => $this->_radius, - 'ry' => $this->_radius, - 'v1' => $angle1, - 'v2' => $angle2, - 'srx' => $radius0, - 'sry' => $radius0 - ) - ); - } - } - } - - /** - * Perform the actual drawing on the legend. - * - * @param int $x0 The top-left x-coordinate - * @param int $y0 The top-left y-coordinate - * @param int $x1 The bottom-right x-coordinate - * @param int $y1 The bottom-right y-coordinate - * @access private - */ - function _drawLegendSample($x0, $y0, $x1, $y1) - { - $dx = abs($x1 - $x0) / 4; - $this->_canvas->addVertex(array('x' => $x0 + $dx , 'y' => $y1)); - $this->_canvas->addVertex(array('x' => ($x0 + $x1) / 2, 'y' => $y0 )); - $this->_canvas->addVertex(array('x' => $x1 - $dx , 'y' => $y1)); - $this->_canvas->polygon(array('connect' => true)); - } - - /** - * Draw a sample for use with legend - * - * @param array $param The parameters for the legend - * @access private - */ - function _legendSample(&$param) - { - if (is_array($this->_dataset)) { - - $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); - - $totals = $this->_getTotals(); - $totals['CENTER_X'] = (int) (($this->_left + $this->_right) / 2); - $totals['CENTER_Y'] = (int) (($this->_top + $this->_bottom) / 2); - $totals['RADIUS'] = min($this->height(), $this->width()) * 0.75 * 0.5; - $totals['CURRENT_Y'] = 0; - - if (is_a($this->_fillStyle, "Image_Graph_Fill")) { - $this->_fillStyle->_reset(); - } - - $count = 0; - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $dataset =& $this->_dataset[$key]; - $count++; - - $dataset->_reset(); - while ($point = $dataset->_next()) { - $caption = $point['X']; - - $this->_canvas->setFont($param['font']); - $width = 20 + $param['width'] + $this->_canvas->textWidth($caption); - $param['maxwidth'] = max($param['maxwidth'], $width); - $x2 = $param['x'] + $width; - $y2 = $param['y'] + $param['height'] + 5; - - if ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) && ($y2 > $param['bottom'])) { - $param['y'] = $param['top']; - $param['x'] = $x2; - $y2 = $param['y'] + $param['height']; - } elseif ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) == 0) && ($x2 > $param['right'])) { - $param['x'] = $param['left']; - $param['y'] = $y2; - $x2 = $param['x'] + 20 + $param['width'] + $this->_canvas->textWidth($caption); - } - - $x = $x0 = $param['x']; - $y = $param['y']; - $y0 = $param['y'] - $param['height'] / 2; - $x1 = $param['x'] + $param['width']; - $y1 = $param['y'] + $param['height'] / 2; - - if (!isset($param['simulate'])) { - $this->_getFillStyle($point['ID']); - $this->_getLineStyle($point['ID']); - $this->_drawLegendSample($x0, $y0, $x1, $y1); - - if (($this->_marker) && ($dataset) && ($param['show_marker'])) { - $prevPoint = $dataset->_nearby(-2); - $nextPoint = $dataset->_nearby(); - - $p = $this->_getMarkerData($point, $nextPoint, $prevPoint, $totals); - if (is_array($point)) { - $p['MARKER_X'] = $x+$param['width'] / 2; - $p['MARKER_Y'] = $y; - unset ($p['AVERAGE_Y']); - $this->_marker->_drawMarker($p['MARKER_X'], $p['MARKER_Y'], $p); - } - } - $this->write($x + $param['width'] + 10, $y, $caption, IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, $param['font']); - } - - if (($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) { - $param['y'] = $y2; - } else { - $param['x'] = $x2; - } - } - } - unset($keys); - $this->_canvas->endGroup(); - } - } -} + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Odo.php,v 1.3 2005/11/27 22:21:16 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * Include file Image/Graph/Tool.php + */ +require_once 'Image/Graph/Tool.php'; + +/** + * 2D Odochart. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @author Maxime Delorme + * @copyright Copyright (C) 2005 Maxime Delorme + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Plot_Odo extends Image_Graph_Plot +{ + /** + * the percent of the radius of the chart that will be use as the width of the range + * @access private + * @var int + */ + var $_radiusPercent = 50; + + /** + * the minimun value of the chart or the start value + * @access private + * @var int + */ + var $_value_min = 0; + + /** + * the maximum value of the chart or the end value + * @access private + * @var int + */ + var $_value_max = 100; + + /** + * the start angle + * @access private + * @var int + */ + var $_deg_offset = 135; + + /** + * the angle of the chart , the length of the chart + * 180 min a half circle + * @access private + * @var int + */ + var $_deg_width = 270; + + /** + * the length of the big ticks + * the small ones will be half ot it, the values 160% of it + * 180 min a half circle + * @access private + * @var int + */ + var $_tickLength = 14; + + /** + * how many small ticks a big tick appears + * the small ticks appear every 6° + * so with the default value of 5, every 30° there is a value and a big tick + * 180 min a half circle + * @access private + * @var int + */ + var $_axisTicks = 5; + + /** + * Arrow marker + * @access private + * @var Image_Graph_Marker + */ + var $_arrowMarker; + + /** + * Range marker fill style + * @access private + * @var Image_Graph_Fill + */ + var $_rangeFillStyle = null; + + /** + * The width of the arrow + * @access private + * @var int + */ + var $_arrowWidth = 5; + + /** + * The length of the arrow + * @access private + * @var int + */ + var $_arrowLength = 80; + + /** + * The radius of the plot + * @access private + * @var int + */ + var $_radius = false; + + /** + * The total Y + * @access private + * @var int + */ + var $_totalY = false; + + /** + * Center X of odometer "circle" + * @access private + * @var int + */ + var $_centerX = false; + + /** + * Center y of odometer "circle" + * @access private + * @var int + */ + var $_centerY = false; + + /** + * Plot_Odo [Constructor] + * + * dataset with one data per arrow + * @param Image_Graph_Dataset $dataset The data set (value containter) to + * plot or an array of datasets + * {@link Image_Graph_Legend} + */ + function Image_Graph_Plot_Odo(&$dataset) + { + parent::Image_Graph_Plot($dataset); + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + if (isset($min)) { + $min = min($dataset->minimumY(), $min); + } + else { + $min = $dataset->minimumY(); + } + if (isset($max)) { + $max = max($dataset->maximumY(), $max); + } + else { + $max = $dataset->maximumY(); + } + } + $this->_value_min = $min; + $this->_value_max = $max; + } + + /** + * Set the center of the odometer + * + * @param int $centerX The center x point + * @param int $centerY The center y point + */ + function setCenter($centerX, $centerY) + { + $this->_centerX = $centerX; + $this->_centerY = $centerY; + } + + /** + * Convert a value to the angle position onto the odometer + * + * @access private + * @param int $value the value to convert + * @return int the angle'position onto the odometer + */ + function _value2angle($value) + { + return $this->_deg_width * (($value - $this->_value_min) / $this->_totalY) + $this->_deg_offset; + } + + /** + * set some internal var + * + * @access private + */ + function _initialize() + { + $v1 = $this->_deg_offset; + $v2 = $this->_deg_offset + $this->_deg_width; + + $dimensions = Image_Graph_Tool::calculateArcDimensionAndCenter($v1, $v2); + + $radiusX = ($this->width() / 2) / $dimensions['rx']; + $radiusY = ($this->height() / 2) / $dimensions['ry']; + + $this->_radius = min($radiusX, $radiusY); + + if ($this->_marker) { + $this->_radius = $this->_radius * 0.85; + } + + //the center of the plot + if ($this->_centerX === false) { + $this->_centerX = (int) (($this->_left + $this->_right) / 2) + + $this->_radius * ($dimensions['cx'] - 0.5); + } + + if ($this->_centerY === false) { + $this->_centerY = (int) (($this->_top + $this->_bottom) / 2) + + $this->_radius * ($dimensions['cy'] - 0.5); + } + + //the max range + $this->_totalY = abs($this->_value_max - $this->_value_min); + } + + /** + * set min and max value of the range + * + * @access public + * @param integer $value_min the minimun value of the chart or the start value + * @param integer $value_max the maximum value of the chart or the end value + */ + function setRange($value_min, $value_max) + { + $this->_value_min = $value_min; + $this->_value_max = $value_max; + } + + /** + * Set start's angle and amplitude of the chart + * + * @access public + * @param integer $deg_offset the start angle + * @param integer $deg_width the angle of the chart (the length) + */ + function setAngles($deg_offset, $deg_width) + { + $this->_deg_offset = min(360, abs($deg_offset)); + $this->_deg_width = min(360, abs($deg_width)); + } + + /** + * set the width of the chart + * + * @access public + * @param string $radius_percent a value between 0 and 100 + */ + function setRadiusWidth($radius_percent) + { + $this->_radiusPercent = $radius_percent; + } + + /** + * set the width and length of the arrow (in percent of the total plot "radius") + * + * @param int length The length in percent + * @param int width The width in percent + */ + function setArrowSize($length, $width) + { + $this->_arrowWidth = max(0, min(100, $width)); + $this->_arrowLength = max(0, min(100, $length)); + } + + /** + * Set the arrow marker + * @param Image_Graph_Marker $marker The marker to set for arrow marker + */ + function setArrowMarker(&$marker) + { + $this->_arrowMarker =& $marker; + } + + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + $this->_initialize(); + $this->_drawRange(); + $this->_drawAxis(); + $this->_drawArrow(); + $this->_drawMarker(); + return true; + } + + /** + * set the length of the ticks + * + * @access public + * @param string $radius_percent a value between 0 and 100 + */ + function setTickLength($radius) + { + $this->_tickLength = $radius; + } + + /** + * set the length of the ticks + * + * @access public + * @param string $radius_percent a value between 0 and 100 + */ + function setAxisTicks($int) + { + $this->_axisTicks = $int; + } + + /** + * Draw the outline and the axis + * + * @access private + */ + function _drawAxis() + { + //draw outline + $this->_getLineStyle(); + $this->_canvas->pieslice( + array( + 'x' => $this->_centerX, + 'y' => $this->_centerY, + 'rx' => $this->_radius, + 'ry' => $this->_radius, + 'v1' => $this->_deg_offset, + 'v2' => $this->_deg_offset+$this->_deg_width, + 'srx' => $this->_radius * (1 - $this->_radiusPercent / 100), + 'sry' => $this->_radius * (1 - $this->_radiusPercent / 100) + ) + ); + + //step for every 6° + $step = (int) ($this->_totalY / $this->_deg_width * 6); + $value = $this->_value_min; + $i = 0; + while ($value <= $this->_value_max) { + $angle = $this->_value2angle($value); + + $cos = cos(deg2rad($angle)); + $sin = sin(deg2rad($angle)); + $point = array('Y' => $value); + $point['AX'] = $cos; + $point['AY'] = $sin; + $point['LENGTH'] = 1; + $x = $this->_centerX + $this->_radius * $cos; + $y = $this->_centerY + $this->_radius * $sin; + $deltaX = - $cos * $this->_tickLength ; + $deltaY = - $sin * $this->_tickLength ; + $this->_getLineStyle(); + if(($i % $this->_axisTicks) == 0){ + $this->_canvas->line(array('x0' => $x, 'y0' => $y, 'x1' => $x + $deltaX, 'y1' => $y + $deltaY)); + if ($this->_arrowMarker) { + $this->_arrowMarker->_drawMarker($x + $deltaX * 1.6, $y + $deltaY *1.6, $point); + } + } else { + $this->_canvas->line(array('x0' => $x, 'y0' => $y, 'x1' => $x + $deltaX * 0.5, 'y1' => $y + $deltaY * 0.5)); + } + $i++; + $value += $step; + } + + } + + /** + * Set the line style of the arrows + * + * @param Image_Graph_Line $lineStyle The line style of the Arrow + * @see Image_Graph_Line + * @access public + */ + function setArrowLineStyle($lineStyle) + { + $this->_arrowLineStyle = &$lineStyle; + } + + /** + * Set the fillstyle of the arrows + * + * @param Image_Graph_Fill $fillStyle The fill style of the arrows + * @see Image_Graph_Fill + * @access public + */ + function setArrowFillStyle($fillStyle) + { + $this->_arrowFillStyle = &$fillStyle; + } + + /** + * Draw the arrows + * + * @access private + */ + function _drawArrow() + { + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + $this->setLineStyle($this->_arrowLineStyle); + $this->setFillStyle($this->_arrowFillStyle); + while ($point = $dataset->_next()) { + $ID = $point['ID']; + $this->_getFillStyle($ID); + $this->_getLineStyle($ID); + $deg = $this->_value2angle($point['Y']); + list($xr,$yr) = Image_Graph_Tool::rotate($this->_centerX + $this->_arrowLength * $this->_radius / 100, $this->_centerY, $this->_centerX, $this->_centerY, $deg); + $this->_canvas->addVertex(array('x' => $xr, 'y' => $yr)); + list($xr,$yr) = Image_Graph_Tool::rotate($this->_centerX, $this->_centerY - $this->_arrowWidth * $this->_radius/100, $this->_centerX, $this->_centerY, $deg); + $this->_canvas->addVertex(array('x' => $xr, 'y' => $yr)); + list($xr,$yr) = Image_Graph_Tool::rotate($this->_centerX - $this->_arrowWidth * $this->_radius / 100, $this->_centerY, $this->_centerX, $this->_centerY, $deg); + $this->_canvas->addVertex(array('x' => $xr, 'y' => $yr)); + list($xr,$yr) = Image_Graph_Tool::rotate($this->_centerX,$this->_centerY + $this->_arrowWidth * $this->_radius / 100, $this->_centerX, $this->_centerY, $deg); + $this->_canvas->addVertex(array('x' => $xr, 'y' => $yr)); + $this->_canvas->polygon(array('connect' => true)); + } + } + } + + /** + * Calculate marker point data + * + * @param array $point The point to calculate data for + * @param array $nextPoint The next point + * @param array $prevPoint The previous point + * @param array $totals The pre-calculated totals, if needed + * @return array An array containing marker point data + * @access private + */ + function _getMarkerData($point, $nextPoint, $prevPoint, &$totals) + { + $point = parent::_getMarkerData($point, $nextPoint, $prevPoint, $totals); + + $point['ANGLE'] = $this->_value2angle($point['Y']); + + $point['ANG_X'] = cos(deg2rad($point['ANGLE'])); + $point['ANG_Y'] = sin(deg2rad($point['ANGLE'])); + + $point['AX'] = -$point['ANG_X']; + $point['AY'] = -$point['ANG_Y']; + + $point['LENGTH'] = 2.5; //$radius; + + $point['MARKER_X'] = $totals['CENTER_X'] + + $totals['ODO_RADIUS'] * $point['ANG_X']; + $point['MARKER_Y'] = $totals['CENTER_Y'] + + $totals['ODO_RADIUS'] * $point['ANG_Y']; + + return $point; + } + + /** + * Draws markers of the arrows on the canvas + * + * @access private + */ + function _drawMarker() + { + + if ($this->_marker) { + $this->_marker->_radius += $this->_radius / 2; + $totals = $this->_getTotals(); + + $totals['CENTER_X'] = $this->_centerX; + $totals['CENTER_Y'] = $this->_centerY; + + + /* $keys = array_keys($this->_dataset); + foreach ($keys as $key) { */ + $dataset =& $this->_dataset[0]; + + $totals['RADIUS0'] = false; + $totals['ODO_RADIUS'] = 1.1 * $this->_radius * $this->_arrowLength / 100; + $totals['ALL_SUM_Y'] = $this->_totalY; + + $dataset->_reset(); + while ($point = $dataset->_next()) { + if ((!is_object($this->_dataSelector)) || + ($this->_dataSelector->select($point)) + ) { + $point = $this->_getMarkerData( + $point, + false, + false, + $totals + ); + if (is_array($point)) { + $this->_marker->_drawMarker( + $point['MARKER_X'], + $point['MARKER_Y'], + $point + ); + } + } + } + /* } + unset($keys); */ + } + } + + /** + * Set range + * + * dataset with two data start and end value of the range + * @param Image_Graph_Dataset $dataset The data set (value containter) to + * plot or an array of datasets + * + */ + function addRangeMarker($min, $max, $id = false) + { + $this->_range[] = + array( + 'min' => max($this->_value_min, min($min, $max)), + 'max' => min($this->_value_max, max($min, $max)), + 'id' => $id + ); + } + + /** + * Set the fillstyle of the ranges + * + * @param Image_Graph_Fill $fillStyle The fill style of the range + * @see Image_Graph_Fill + * @access public + */ + function &setRangeMarkerFillStyle(&$rangeMarkerFillStyle) + { + $this->_rangeFillStyle = $rangeMarkerFillStyle; + } + + /** + * Draw the ranges + * + * @access private + */ + function _drawRange() + { + if($this->_range){ + $radius0 = $this->_radius * (1 - $this->_radiusPercent/100); + foreach ($this->_range as $range) { + $angle1 = $this->_value2angle($range['min']); + $angle2 = $this->_value2angle($range['max']); + + if (is_object($this->_rangeFillStyle)) { + $this->_canvas->setFill($this->_rangeFillStyle->_getFillStyle($range['id'])); + } elseif ($this->_rangeFillStyle != null) { + $this->_canvas->setFill($this->_rangeFillStyle); + } + $this->_getLineStyle(); + $this->_canvas->Pieslice( + array( + 'x' => $this->_centerX, + 'y' => $this->_centerY, + 'rx' => $this->_radius, + 'ry' => $this->_radius, + 'v1' => $angle1, + 'v2' => $angle2, + 'srx' => $radius0, + 'sry' => $radius0 + ) + ); + } + } + } + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $dx = abs($x1 - $x0) / 4; + $this->_canvas->addVertex(array('x' => $x0 + $dx , 'y' => $y1)); + $this->_canvas->addVertex(array('x' => ($x0 + $x1) / 2, 'y' => $y0 )); + $this->_canvas->addVertex(array('x' => $x1 - $dx , 'y' => $y1)); + $this->_canvas->polygon(array('connect' => true)); + } + + /** + * Draw a sample for use with legend + * + * @param array $param The parameters for the legend + * @access private + */ + function _legendSample(&$param) + { + if (is_array($this->_dataset)) { + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + $this->_clip(true); + + $totals = $this->_getTotals(); + $totals['CENTER_X'] = (int) (($this->_left + $this->_right) / 2); + $totals['CENTER_Y'] = (int) (($this->_top + $this->_bottom) / 2); + $totals['RADIUS'] = min($this->height(), $this->width()) * 0.75 * 0.5; + $totals['CURRENT_Y'] = 0; + + if (is_a($this->_fillStyle, "Image_Graph_Fill")) { + $this->_fillStyle->_reset(); + } + + $count = 0; + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $count++; + + $dataset->_reset(); + while ($point = $dataset->_next()) { + $caption = $point['X']; + + $this->_canvas->setFont($param['font']); + $width = 20 + $param['width'] + $this->_canvas->textWidth($caption); + $param['maxwidth'] = max($param['maxwidth'], $width); + $x2 = $param['x'] + $width; + $y2 = $param['y'] + $param['height'] + 5; + + if ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) && ($y2 > $param['bottom'])) { + $param['y'] = $param['top']; + $param['x'] = $x2; + $y2 = $param['y'] + $param['height']; + } elseif ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) == 0) && ($x2 > $param['right'])) { + $param['x'] = $param['left']; + $param['y'] = $y2; + $x2 = $param['x'] + 20 + $param['width'] + $this->_canvas->textWidth($caption); + } + + $x = $x0 = $param['x']; + $y = $param['y']; + $y0 = $param['y'] - $param['height'] / 2; + $x1 = $param['x'] + $param['width']; + $y1 = $param['y'] + $param['height'] / 2; + + if (!isset($param['simulate'])) { + $this->_getFillStyle($point['ID']); + $this->_getLineStyle($point['ID']); + $this->_drawLegendSample($x0, $y0, $x1, $y1); + + if (($this->_marker) && ($dataset) && ($param['show_marker'])) { + $prevPoint = $dataset->_nearby(-2); + $nextPoint = $dataset->_nearby(); + + $p = $this->_getMarkerData($point, $nextPoint, $prevPoint, $totals); + if (is_array($point)) { + $p['MARKER_X'] = $x+$param['width'] / 2; + $p['MARKER_Y'] = $y; + unset ($p['AVERAGE_Y']); + $this->_marker->_drawMarker($p['MARKER_X'], $p['MARKER_Y'], $p); + } + } + $this->write($x + $param['width'] + 10, $y, $caption, IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, $param['font']); + } + + if (($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) { + $param['y'] = $y2; + } else { + $param['x'] = $x2; + } + } + } + unset($keys); + $this->_clip(false); + $this->_canvas->endGroup(); + } + } +} ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Plot/Pie.php b/includes/pear/Image/Graph/Plot/Pie.php index 0456c96d..e232993d 100644 --- a/includes/pear/Image/Graph/Plot/Pie.php +++ b/includes/pear/Image/Graph/Plot/Pie.php @@ -1,481 +1,623 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Pie.php,v 1.17 2005/09/29 18:21:24 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Plot.php - */ -require_once 'Image/Graph/Plot.php'; - -/** - * 2D Piechart. - * - * @category Images - * @package Image_Graph - * @subpackage Plot - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Plot_Pie extends Image_Graph_Plot -{ - - /** - * The radius of the 'pie' spacing - * @access private - * @var int - */ - var $_radius = 3; - - /** - * Explode pie slices. - * @access private - * @var mixed - */ - var $_explode = false; - - /** - * The starting angle of the plot - * @access private - * @var int - */ - var $_startingAngle = 0; - - /** - * The angle direction (1 = CCW, -1 = CW) - * @access private - * @var int - */ - var $_angleDirection = 1; - - /** - * The diameter of the pie plot - * @access private - * @var int - */ - var $_diameter = false; - - /** - * Perform the actual drawing on the legend. - * - * @param int $x0 The top-left x-coordinate - * @param int $y0 The top-left y-coordinate - * @param int $x1 The bottom-right x-coordinate - * @param int $y1 The bottom-right y-coordinate - * @access private - */ - function _drawLegendSample($x0, $y0, $x1, $y1) - { - $y = ($y0 + $y1) / 2; - $this->_canvas->pieslice( - array( - 'x' => $x1, - 'y' => $y, - 'rx' => abs($x1 - $x0) / 2, - 'ry' => abs($y1 - $y0) / 2, - 'v1' => 45, - 'v2' => 315 - ) - ); - } - - /** - * Calculate marker point data - * - * @param array $point The point to calculate data for - * @param array $nextPoint The next point - * @param array $prevPoint The previous point - * @param array $totals The pre-calculated totals, if needed - * @return array An array containing marker point data - * @access private - */ - function _getMarkerData($point, $nextPoint, $prevPoint, &$totals) - { - $point = parent::_getMarkerData($point, $nextPoint, $prevPoint, $totals); - - $y = $totals['CURRENT_Y']; - - if ($this->_angleDirection < 0) { - $y = $totals['ALL_SUM_Y'] - $y; - } - - $point['ANGLE'] = 360 * (($y + ($point['Y'] / 2)) / $totals['ALL_SUM_Y']) + $this->_startingAngle; - $totals['CURRENT_Y'] += $point['Y']; - - $point['ANG_X'] = cos(deg2rad($point['ANGLE'])); - $point['ANG_Y'] = sin(deg2rad($point['ANGLE'])); - - $point['AX'] = -10 * $point['ANG_X']; - $point['AY'] = -10 * $point['ANG_Y']; - - if ((isset($totals['ALL_SUM_Y'])) && ($totals['ALL_SUM_Y'] != 0)) { - $point['PCT_MIN_Y'] = $point['PCT_MAX_Y'] = (100 * $point['Y'] / $totals['ALL_SUM_Y']); - } - - $point['LENGTH'] = 10; //$radius; - - $x = $point['X']; - $explodeRadius = 0; - if ((is_array($this->_explode)) && (isset($this->_explode[$x]))) { - $explodeRadius = $this->_explode[$x]; - } elseif (is_numeric($this->_explode)) { - $explodeRadius = $this->_explode; - } - - $point['MARKER_X'] = $totals['CENTER_X'] + - ($totals['RADIUS'] + $explodeRadius) * $point['ANG_X']; - $point['MARKER_Y'] = $totals['CENTER_Y'] + - ($totals['RADIUS'] + $explodeRadius) * $point['ANG_Y']; - - return $point; - } - - /** - * Draws markers on the canvas - * - * @access private - */ - function _drawMarker() - { - - if ($this->_marker) { - $totals = $this->_getTotals(); - - $totals['CENTER_X'] = (int) (($this->_left + $this->_right) / 2); - $totals['CENTER_Y'] = (int) (($this->_top + $this->_bottom) / 2); - - $totals['CURRENT_Y'] = 0; - $number = 0; - - $diameter = $this->_getDiameter(); - - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $dataset =& $this->_dataset[$key]; - - if (count($this->_dataset) == 1) { - $totals['RADIUS0'] = false; - $totals['RADIUS'] = $diameter / 2; - } else { - $dr = $diameter / (2 * count($this->_dataset)); - - $totals['RADIUS0'] = $number * $dr + ($number > 0 ? $this->_radius : 0); - $totals['RADIUS'] = ($number + 1) * $dr; - } - - $totals['ALL_SUM_Y'] = 0; - $totals['CURRENT_Y'] = 0; - $dataset->_reset(); - while ($point = $dataset->_next()) { - $totals['ALL_SUM_Y'] += $point['Y']; - } - - $dataset->_reset(); - $currentY = 0; - while ($point = $dataset->_next()) { - if ((!is_object($this->_dataSelector)) || - ($this->_dataSelector->select($point)) - ) { - $point = $this->_getMarkerData( - $point, - false, - false, - $totals - ); - if (is_array($point)) { - $this->_marker->_drawMarker( - $point['MARKER_X'], - $point['MARKER_Y'], - $point - ); - } - } - } - $number++; - } - unset($keys); - } - } - - /** - * Explodes a piece of this pie chart - * - * @param int $explode Radius to explode with (or an array) - * @param string $x The 'x' value to explode or omitted - */ - function explode($explode, $x = false) - { - if ($x === false) { - $this->_explode = $explode; - } else { - $this->_explode[$x] = $explode; - } - } - - /** - * Set the starting angle of the plot - * - * East is 0 degrees - * South is 90 degrees - * West is 180 degrees - * North is 270 degrees - * - * It is also possible to specify the direction of the plot angles (i.e. clockwise 'cw' or - * counterclockwise 'ccw') - */ - function setStartingAngle($angle = 0, $direction = 'ccw') - { - $this->_startingAngle = ($angle % 360); - $this->_angleDirection = ($direction == 'ccw' ? 1 : -1); - } - - /** - * Set the diameter of the pie plot (i.e. the number of pixels the - * pie plot should be across) - * - * Use 'max' for the maximum possible diameter - * - * Use negative values for the maximum possible - minus this value (fx -2 - * to leave 1 pixel at each side) - * - * @param mixed @diameter The number of pixels - */ - function setDiameter($diameter) - { - $this->_diameter = $diameter; - } - - /** - * Get the diameter of the plot - * @return int The number of pixels the diameter is - * @access private - */ - function _getDiameter() - { - $diameter = 0; - if ($this->_diameter === false) { - $diameter = min($this->height(), $this->width()) * 0.75; - } - else { - if ($this->_diameter === 'max') { - $diameter = min($this->height(), $this->width()); - } - elseif ($this->_diameter < 0) { - $diameter = min($this->height(), $this->width()) + $this->_diameter; - } else { - $diameter = $this->_diameter; - } - } - return $diameter; - } - - - /** - * Output the plot - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (parent::_done() === false) { - return false; - } - - $number = 0; - - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $dataset =& $this->_dataset[$key]; - - $totalY = 0; - $dataset->_reset(); - while ($point = $dataset->_next()) { - $totalY += $point['Y']; - } - - $centerX = (int) (($this->_left + $this->_right) / 2); - $centerY = (int) (($this->_top + $this->_bottom) / 2); - $diameter = $this->_getDiameter(); - if ($this->_angleDirection < 0) { - $currentY = $totalY; - } else { - $currentY = 0; //rand(0, 100)*$totalY/100; - } - $dataset->_reset(); - - if (count($this->_dataset) == 1) { - $radius0 = false; - $radius1 = $diameter / 2; - } else { - $dr = $diameter / (2 * count($this->_dataset)); - - $radius0 = $number * $dr + ($number > 0 ? $this->_radius : 0); - $radius1 = ($number + 1) * $dr; - } - - while ($point = $dataset->_next()) { - $angle1 = 360 * ($currentY / $totalY) + $this->_startingAngle; - $currentY += $this->_angleDirection * $point['Y']; - $angle2 = 360 * ($currentY / $totalY) + $this->_startingAngle; - - $x = $point['X']; - $id = $point['ID']; - - $dX = 0; - $dY = 0; - $explodeRadius = 0; - if ((is_array($this->_explode)) && (isset($this->_explode[$x]))) { - $explodeRadius = $this->_explode[$x]; - } elseif (is_numeric($this->_explode)) { - $explodeRadius = $this->_explode; - } - - if ($explodeRadius > 0) { - $dX = $explodeRadius * cos(deg2rad(($angle1 + $angle2) / 2)); - $dY = $explodeRadius * sin(deg2rad(($angle1 + $angle2) / 2)); - } - - $ID = $point['ID']; - $this->_getFillStyle($ID); - $this->_getLineStyle($ID); - $this->_canvas->pieslice( - $this->_mergeData( - $point, - array( - 'x' => $centerX + $dX, - 'y' => $centerY + $dY, - 'rx' => $radius1, - 'ry' => $radius1, - 'v1' => $angle1, - 'v2' => $angle2, - 'srx' => $radius0, - 'sry' => $radius0 - ) - ) - ); - } - $number++; - } - unset($keys); - $this->_drawMarker(); - return true; - } - - /** - * Draw a sample for use with legend - * - * @param array $param The parameters for the legend - * @access private - */ - function _legendSample(&$param) - { - if (is_array($this->_dataset)) { - - $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); - - $totals = $this->_getTotals(); - $totals['CENTER_X'] = (int) (($this->_left + $this->_right) / 2); - $totals['CENTER_Y'] = (int) (($this->_top + $this->_bottom) / 2); - $totals['RADIUS'] = min($this->height(), $this->width()) * 0.75 * 0.5; - $totals['CURRENT_Y'] = 0; - - if (is_a($this->_fillStyle, "Image_Graph_Fill")) { - $this->_fillStyle->_reset(); - } - - $count = 0; - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $dataset =& $this->_dataset[$key]; - $count++; - - $dataset->_reset(); - while ($point = $dataset->_next()) { - $caption = $point['X']; - - $this->_canvas->setFont($param['font']); - $width = 20 + $param['width'] + $this->_canvas->textWidth($caption); - $param['maxwidth'] = max($param['maxwidth'], $width); - $x2 = $param['x'] + $width; - $y2 = $param['y'] + $param['height']+5; - - if ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) && ($y2 > $param['bottom'])) { - $param['y'] = $param['top']; - $param['x'] = $x2; - $y2 = $param['y'] + $param['height']; - } elseif ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) == 0) && ($x2 > $param['right'])) { - $param['x'] = $param['left']; - $param['y'] = $y2; - $x2 = $param['x'] + 20 + $param['width'] + $this->_canvas->textWidth($caption); - } - - $x = $x0 = $param['x']; - $y = $param['y']; - $y0 = $param['y'] - $param['height']/2; - $x1 = $param['x'] + $param['width']; - $y1 = $param['y'] + $param['height']/2; - - if (!isset($param['simulate'])) { - $this->_getFillStyle($point['ID']); - $this->_getLineStyle($point['ID']); - $this->_drawLegendSample($x0, $y0, $x1, $y1); - - if (($this->_marker) && ($dataset) && ($param['show_marker'])) { - $prevPoint = $dataset->_nearby(-2); - $nextPoint = $dataset->_nearby(); - - $p = $this->_getMarkerData($point, $nextPoint, $prevPoint, $totals); - if (is_array($point)) { - $p['MARKER_X'] = $x+$param['width']/2; - $p['MARKER_Y'] = $y; - unset ($p['AVERAGE_Y']); - $this->_marker->_drawMarker($p['MARKER_X'], $p['MARKER_Y'], $p); - } - } - $this->write($x + $param['width'] +10, $y, $caption, IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, $param['font']); - } - - if (($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) { - $param['y'] = $y2; - } else { - $param['x'] = $x2; - } - } - } - unset($keys); - $this->_canvas->endGroup(); - } - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Pie.php,v 1.19 2005/11/27 22:21:16 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * 2D Piechart. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Plot_Pie extends Image_Graph_Plot +{ + + /** + * The radius of the 'pie' spacing + * @access private + * @var int + */ + var $_radius = 3; + + /** + * Explode pie slices. + * @access private + * @var mixed + */ + var $_explode = false; + + /** + * The starting angle of the plot + * @access private + * @var int + */ + var $_startingAngle = 0; + + /** + * The angle direction (1 = CCW, -1 = CW) + * @access private + * @var int + */ + var $_angleDirection = 1; + + /** + * The diameter of the pie plot + * @access private + * @var int + */ + var $_diameter = false; + + /** + * Group items below this limit together as "the rest" + * @access private + * @var double + */ + var $_restGroupLimit = false; + + /** + * Rest group title + * @access private + * @var string + */ + var $_restGroupTitle = 'The rest'; + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $y = ($y0 + $y1) / 2; + $this->_canvas->pieslice( + array( + 'x' => $x1, + 'y' => $y, + 'rx' => abs($x1 - $x0) / 2, + 'ry' => abs($y1 - $y0) / 2, + 'v1' => 45, + 'v2' => 315 + ) + ); + } + + /** + * Calculate marker point data + * + * @param array $point The point to calculate data for + * @param array $nextPoint The next point + * @param array $prevPoint The previous point + * @param array $totals The pre-calculated totals, if needed + * @return array An array containing marker point data + * @access private + */ + function _getMarkerData($point, $nextPoint, $prevPoint, &$totals) + { + $point = parent::_getMarkerData($point, $nextPoint, $prevPoint, $totals); + + $y = $totals['CURRENT_Y']; + + if ($this->_angleDirection < 0) { + $y = $totals['ALL_SUM_Y'] - $y; + } + + $point['ANGLE'] = 360 * (($y + ($point['Y'] / 2)) / $totals['ALL_SUM_Y']) + $this->_startingAngle; + $totals['CURRENT_Y'] += $point['Y']; + + $point['ANG_X'] = cos(deg2rad($point['ANGLE'])); + $point['ANG_Y'] = sin(deg2rad($point['ANGLE'])); + + $point['AX'] = -10 * $point['ANG_X']; + $point['AY'] = -10 * $point['ANG_Y']; + + if ((isset($totals['ALL_SUM_Y'])) && ($totals['ALL_SUM_Y'] != 0)) { + $point['PCT_MIN_Y'] = $point['PCT_MAX_Y'] = (100 * $point['Y'] / $totals['ALL_SUM_Y']); + } + + $point['LENGTH'] = 10; //$radius; + + $x = $point['X']; + $explodeRadius = 0; + if ((is_array($this->_explode)) && (isset($this->_explode[$x]))) { + $explodeRadius = $this->_explode[$x]; + } elseif (is_numeric($this->_explode)) { + $explodeRadius = $this->_explode; + } + + $point['MARKER_X'] = $totals['CENTER_X'] + + ($totals['RADIUS'] + $explodeRadius) * $point['ANG_X']; + $point['MARKER_Y'] = $totals['CENTER_Y'] + + ($totals['RADIUS'] + $explodeRadius) * $point['ANG_Y']; + + return $point; + } + + /** + * Draws markers on the canvas + * + * @access private + */ + function _drawMarker() + { + + if ($this->_marker) { + $totals = $this->_getTotals(); + + $totals['CENTER_X'] = (int) (($this->_left + $this->_right) / 2); + $totals['CENTER_Y'] = (int) (($this->_top + $this->_bottom) / 2); + + $totals['CURRENT_Y'] = 0; + $number = 0; + + $diameter = $this->_getDiameter(); + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + + if (count($this->_dataset) == 1) { + $totals['RADIUS0'] = false; + $totals['RADIUS'] = $diameter / 2; + } else { + $dr = $diameter / (2 * count($this->_dataset)); + + $totals['RADIUS0'] = $number * $dr + ($number > 0 ? $this->_radius : 0); + $totals['RADIUS'] = ($number + 1) * $dr; + } + + $totals['ALL_SUM_Y'] = 0; + $totals['CURRENT_Y'] = 0; + $dataset->_reset(); + while ($point = $dataset->_next()) { + $totals['ALL_SUM_Y'] += $point['Y']; + } + + $dataset->_reset(); + $currentY = 0; + $the_rest = 0; + while ($point = $dataset->_next()) { + if (($this->_restGroupLimit !== false) && ($point['Y'] <= $this->_restGroupLimit)) { + $the_rest += $point['Y']; + } + else { + if ((!is_object($this->_dataSelector)) || + ($this->_dataSelector->select($point)) + ) { + $point = $this->_getMarkerData( + $point, + false, + false, + $totals + ); + if (is_array($point)) { + $this->_marker->_drawMarker( + $point['MARKER_X'], + $point['MARKER_Y'], + $point + ); + } + } + } + } + if ($the_rest > 0) { + $point = array('X' => $this->_restGroupTitle, 'Y' => $the_rest); + $point = $this->_getMarkerData( + $point, + false, + false, + $totals + ); + if (is_array($point)) { + $this->_marker->_drawMarker( + $point['MARKER_X'], + $point['MARKER_Y'], + $point + ); + } + } + $number++; + } + unset($keys); + } + } + + /** + * Explodes a piece of this pie chart + * + * @param int $explode Radius to explode with (or an array) + * @param string $x The 'x' value to explode or omitted + */ + function explode($explode, $x = false) + { + if ($x === false) { + $this->_explode = $explode; + } else { + $this->_explode[$x] = $explode; + } + } + + /** + * Set the starting angle of the plot + * + * East is 0 degrees + * South is 90 degrees + * West is 180 degrees + * North is 270 degrees + * + * It is also possible to specify the direction of the plot angles (i.e. clockwise 'cw' or + * counterclockwise 'ccw') + */ + function setStartingAngle($angle = 0, $direction = 'ccw') + { + $this->_startingAngle = ($angle % 360); + $this->_angleDirection = ($direction == 'ccw' ? 1 : -1); + } + + /** + * Set the diameter of the pie plot (i.e. the number of pixels the + * pie plot should be across) + * + * Use 'max' for the maximum possible diameter + * + * Use negative values for the maximum possible - minus this value (fx -2 + * to leave 1 pixel at each side) + * + * @param mixed @diameter The number of pixels + */ + function setDiameter($diameter) + { + $this->_diameter = $diameter; + } + + /** + * Set the limit for the y-value, where values below are grouped together + * as "the rest" + * + * @param double $limit The limit + * @param string $title The title to display in the legends (default 'The + * rest') + */ + function setRestGroup($limit, $title = 'The rest') + { + $this->_restGroupLimit = $limit; + $this->_restGroupTitle = $title; + } + + /** + * Get the diameter of the plot + * @return int The number of pixels the diameter is + * @access private + */ + function _getDiameter() + { + $diameter = 0; + if ($this->_diameter === false) { + $diameter = min($this->height(), $this->width()) * 0.75; + } + else { + if ($this->_diameter === 'max') { + $diameter = min($this->height(), $this->width()); + } + elseif ($this->_diameter < 0) { + $diameter = min($this->height(), $this->width()) + $this->_diameter; + } else { + $diameter = $this->_diameter; + } + } + return $diameter; + } + + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + $number = 0; + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + + $totalY = 0; + $dataset->_reset(); + while ($point = $dataset->_next()) { + $totalY += $point['Y']; + } + + $centerX = (int) (($this->_left + $this->_right) / 2); + $centerY = (int) (($this->_top + $this->_bottom) / 2); + $diameter = $this->_getDiameter(); + if ($this->_angleDirection < 0) { + $currentY = $totalY; + } else { + $currentY = 0; //rand(0, 100)*$totalY/100; + } + $dataset->_reset(); + + if (count($this->_dataset) == 1) { + $radius0 = false; + $radius1 = $diameter / 2; + } else { + $dr = $diameter / (2 * count($this->_dataset)); + + $radius0 = $number * $dr + ($number > 0 ? $this->_radius : 0); + $radius1 = ($number + 1) * $dr; + } + + $the_rest = 0; + while ($point = $dataset->_next()) { + if (($this->_restGroupLimit !== false) && ($point['Y'] <= $this->_restGroupLimit)) { + $the_rest += $point['Y']; + } + else { + $angle1 = 360 * ($currentY / $totalY) + $this->_startingAngle; + $currentY += $this->_angleDirection * $point['Y']; + $angle2 = 360 * ($currentY / $totalY) + $this->_startingAngle; + + $x = $point['X']; + $id = $point['ID']; + + $dX = 0; + $dY = 0; + $explodeRadius = 0; + if ((is_array($this->_explode)) && (isset($this->_explode[$x]))) { + $explodeRadius = $this->_explode[$x]; + } elseif (is_numeric($this->_explode)) { + $explodeRadius = $this->_explode; + } + + if ($explodeRadius > 0) { + $dX = $explodeRadius * cos(deg2rad(($angle1 + $angle2) / 2)); + $dY = $explodeRadius * sin(deg2rad(($angle1 + $angle2) / 2)); + } + + $ID = $point['ID']; + $this->_getFillStyle($ID); + $this->_getLineStyle($ID); + $this->_canvas->pieslice( + $this->_mergeData( + $point, + array( + 'x' => $centerX + $dX, + 'y' => $centerY + $dY, + 'rx' => $radius1, + 'ry' => $radius1, + 'v1' => $angle1, + 'v2' => $angle2, + 'srx' => $radius0, + 'sry' => $radius0 + ) + ) + ); + } + } + + if ($the_rest > 0) { + $angle1 = 360 * ($currentY / $totalY) + $this->_startingAngle; + $currentY += $this->_angleDirection * $the_rest; + $angle2 = 360 * ($currentY / $totalY) + $this->_startingAngle; + + $x = 'rest'; + $id = 'rest'; + + $dX = 0; + $dY = 0; + $explodeRadius = 0; + if ((is_array($this->_explode)) && (isset($this->_explode[$x]))) { + $explodeRadius = $this->_explode[$x]; + } elseif (is_numeric($this->_explode)) { + $explodeRadius = $this->_explode; + } + + if ($explodeRadius > 0) { + $dX = $explodeRadius * cos(deg2rad(($angle1 + $angle2) / 2)); + $dY = $explodeRadius * sin(deg2rad(($angle1 + $angle2) / 2)); + } + + $ID = $id; + $this->_getFillStyle($ID); + $this->_getLineStyle($ID); + $this->_canvas->pieslice( + $this->_mergeData( + $point, + array( + 'x' => $centerX + $dX, + 'y' => $centerY + $dY, + 'rx' => $radius1, + 'ry' => $radius1, + 'v1' => $angle1, + 'v2' => $angle2, + 'srx' => $radius0, + 'sry' => $radius0 + ) + ) + ); + } + $number++; + } + unset($keys); + $this->_drawMarker(); + return true; + } + + /** + * Draw a sample for use with legend + * + * @param array $param The parameters for the legend + * @access private + */ + function _legendSample(&$param) + { + if (is_array($this->_dataset)) { + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + $this->_clip(true); + + $totals = $this->_getTotals(); + $totals['CENTER_X'] = (int) (($this->_left + $this->_right) / 2); + $totals['CENTER_Y'] = (int) (($this->_top + $this->_bottom) / 2); + $totals['RADIUS'] = min($this->height(), $this->width()) * 0.75 * 0.5; + $totals['CURRENT_Y'] = 0; + + if (is_a($this->_fillStyle, "Image_Graph_Fill")) { + $this->_fillStyle->_reset(); + } + + $count = 0; + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $count++; + + $dataset->_reset(); + $the_rest = 0; + while ($point = $dataset->_next()) { + $caption = $point['X']; + if (($this->_restGroupLimit !== false) && ($point['Y'] <= $this->_restGroupLimit)) { + $the_rest += $point['Y']; + } + else { + $this->_canvas->setFont($param['font']); + $width = 20 + $param['width'] + $this->_canvas->textWidth($caption); + $param['maxwidth'] = max($param['maxwidth'], $width); + $x2 = $param['x'] + $width; + $y2 = $param['y'] + $param['height']+5; + + if ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) && ($y2 > $param['bottom'])) { + $param['y'] = $param['top']; + $param['x'] = $x2; + $y2 = $param['y'] + $param['height']; + } elseif ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) == 0) && ($x2 > $param['right'])) { + $param['x'] = $param['left']; + $param['y'] = $y2; + $x2 = $param['x'] + 20 + $param['width'] + $this->_canvas->textWidth($caption); + } + + $x = $x0 = $param['x']; + $y = $param['y']; + $y0 = $param['y'] - $param['height']/2; + $x1 = $param['x'] + $param['width']; + $y1 = $param['y'] + $param['height']/2; + + if (!isset($param['simulate'])) { + $this->_getFillStyle($point['ID']); + $this->_getLineStyle($point['ID']); + $this->_drawLegendSample($x0, $y0, $x1, $y1); + + if (($this->_marker) && ($dataset) && ($param['show_marker'])) { + $prevPoint = $dataset->_nearby(-2); + $nextPoint = $dataset->_nearby(); + + $p = $this->_getMarkerData($point, $nextPoint, $prevPoint, $totals); + if (is_array($point)) { + $p['MARKER_X'] = $x+$param['width']/2; + $p['MARKER_Y'] = $y; + unset ($p['AVERAGE_Y']); + $this->_marker->_drawMarker($p['MARKER_X'], $p['MARKER_Y'], $p); + } + } + $this->write($x + $param['width'] +10, $y, $caption, IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, $param['font']); + } + + if (($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) { + $param['y'] = $y2; + } else { + $param['x'] = $x2; + } + } + } + if ($the_rest > 0) { + $this->_canvas->setFont($param['font']); + $width = 20 + $param['width'] + $this->_canvas->textWidth($this->_restGroupTitle); + $param['maxwidth'] = max($param['maxwidth'], $width); + $x2 = $param['x'] + $width; + $y2 = $param['y'] + $param['height']+5; + + if ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) && ($y2 > $param['bottom'])) { + $param['y'] = $param['top']; + $param['x'] = $x2; + $y2 = $param['y'] + $param['height']; + } elseif ((($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) == 0) && ($x2 > $param['right'])) { + $param['x'] = $param['left']; + $param['y'] = $y2; + $x2 = $param['x'] + 20 + $param['width'] + $this->_canvas->textWidth($this->_restGroupTitle); + } + + $x = $x0 = $param['x']; + $y = $param['y']; + $y0 = $param['y'] - $param['height']/2; + $x1 = $param['x'] + $param['width']; + $y1 = $param['y'] + $param['height']/2; + + if (!isset($param['simulate'])) { + $this->_getFillStyle('rest'); + $this->_getLineStyle('rest'); + $this->_drawLegendSample($x0, $y0, $x1, $y1); + + $this->write($x + $param['width'] + 10, $y, $this->_restGroupTitle, IMAGE_GRAPH_ALIGN_CENTER_Y | IMAGE_GRAPH_ALIGN_LEFT, $param['font']); + } + + if (($param['align'] & IMAGE_GRAPH_ALIGN_VERTICAL) != 0) { + $param['y'] = $y2; + } else { + $param['x'] = $x2; + } + } + } + unset($keys); + $this->_clip(false); + $this->_canvas->endGroup(); + } + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Plot/Radar.php b/includes/pear/Image/Graph/Plot/Radar.php index cf73df0c..11577e66 100644 --- a/includes/pear/Image/Graph/Plot/Radar.php +++ b/includes/pear/Image/Graph/Plot/Radar.php @@ -1,116 +1,118 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Radar.php,v 1.10 2005/08/03 21:21:55 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Plot.php - */ -require_once 'Image/Graph/Plot.php'; - -/** - * Radar chart. - * - * @category Images - * @package Image_Graph - * @subpackage Plot - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Plot_Radar extends Image_Graph_Plot -{ - - /** - * Perform the actual drawing on the legend. - * - * @param int $x0 The top-left x-coordinate - * @param int $y0 The top-left y-coordinate - * @param int $x1 The bottom-right x-coordinate - * @param int $y1 The bottom-right y-coordinate - * @access private - */ - function _drawLegendSample($x0, $y0, $x1, $y1) - { - $p = 10; - $rx = abs($x1 - $x0) / 2; - $ry = abs($x1 - $x0) / 2; - $r = min($rx, $ry); - $cx = ($x0 + $x1) / 2; - $cy = ($y0 + $y1) / 2; - $max = 5; - for ($i = 0; $i < $p; $i++) { - $v = 2 * pi() * $i / $p; - $t = $r * rand(3, $max) / $max; - $x = $cx + $t * cos($v); - $y = $cy + $t * sin($v); - $this->_canvas->addVertex(array('x' => $x, 'y' => $y)); - } - $this->_canvas->polygon(array('connect' => true)); - } - - /** - * Output the plot - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); - if (is_a($this->_parent, 'Image_Graph_Plotarea_Radar')) { - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $dataset =& $this->_dataset[$key]; - $maxY = $dataset->maximumY(); - $count = $dataset->count(); - - $dataset->_reset(); - while ($point = $dataset->_next()) { - $this->_canvas->addVertex(array('x' => - $this->_pointX($point), 'y' => - $this->_pointY($point) - )); - } - $this->_getFillStyle($key); - $this->_getLineStyle($key); - $this->_canvas->polygon(array('connect' => true)); - } - unset($keys); - } - $this->_drawMarker(); - - $this->_canvas->endGroup(); - return parent::_done(); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Radar.php,v 1.11 2005/11/27 22:21:16 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * Radar chart. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Plot_Radar extends Image_Graph_Plot +{ + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $p = 10; + $rx = abs($x1 - $x0) / 2; + $ry = abs($x1 - $x0) / 2; + $r = min($rx, $ry); + $cx = ($x0 + $x1) / 2; + $cy = ($y0 + $y1) / 2; + $max = 5; + for ($i = 0; $i < $p; $i++) { + $v = 2 * pi() * $i / $p; + $t = $r * rand(3, $max) / $max; + $x = $cx + $t * cos($v); + $y = $cy + $t * sin($v); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y)); + } + $this->_canvas->polygon(array('connect' => true)); + } + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + $this->_clip(true); + if (is_a($this->_parent, 'Image_Graph_Plotarea_Radar')) { + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $maxY = $dataset->maximumY(); + $count = $dataset->count(); + + $dataset->_reset(); + while ($point = $dataset->_next()) { + $this->_canvas->addVertex(array('x' => + $this->_pointX($point), 'y' => + $this->_pointY($point) + )); + } + $this->_getFillStyle($key); + $this->_getLineStyle($key); + $this->_canvas->polygon(array('connect' => true)); + } + unset($keys); + } + $this->_drawMarker(); + + $this->_clip(false); + $this->_canvas->endGroup(); + return parent::_done(); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Plot/Smoothed/Area.php b/includes/pear/Image/Graph/Plot/Smoothed/Area.php index 8cabc310..914e3b26 100644 --- a/includes/pear/Image/Graph/Plot/Smoothed/Area.php +++ b/includes/pear/Image/Graph/Plot/Smoothed/Area.php @@ -1,142 +1,145 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Area.php,v 1.10 2005/08/03 21:21:52 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Plot/Smoothed/Bezier.php - */ -require_once 'Image/Graph/Plot/Smoothed/Bezier.php'; - -/** - * Bezier smoothed area chart - * - * Similar to an {@link Image_Graph_Plot_Area}, but the interconnecting lines - * between two datapoints are smoothed using a Bezier curve, which enables the - * chart to appear as a nice curved plot instead of the sharp edges of a - * conventional {@link Image_Graph_Plot_Area}. Smoothed charts are only supported - * with non-stacked types - * - * @category Images - * @package Image_Graph - * @subpackage Plot - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Plot_Smoothed_Area extends Image_Graph_Plot_Smoothed_Bezier -{ - - /** - * Perform the actual drawing on the legend. - * - * @param int $x0 The top-left x-coordinate - * @param int $y0 The top-left y-coordinate - * @param int $x1 The bottom-right x-coordinate - * @param int $y1 The bottom-right y-coordinate - * @access private - */ - function _drawLegendSample($x0, $y0, $x1, $y1) - { - - $this->_canvas->addVertex(array('x' => $x0, 'y' => $y1)); - $this->_addSamplePoints($x0, $y0, $x1, $y1); - $this->_canvas->addVertex(array('x' => $x1, 'y' => $y1)); - $this->_canvas->polygon(array('connect' => true)); - } - - /** - * Output the Bezier smoothed plot as an Area Chart - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (parent::_done() === false) { - return false; - } - - $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $dataset =& $this->_dataset[$key]; - $dataset->_reset(); - $first = true; - while ($p1 = $dataset->_next()) { - $p0 = $dataset->_nearby(-2); - $p2 = $dataset->_nearby(0); - $p3 = $dataset->_nearby(1); - if ($first) { - $p = $p1; - $p['Y'] = '#min_pos#'; - $x = $this->_pointX($p); - $y = $this->_pointY($p); - $this->_canvas->addVertex(array('x' => $x, 'y' => $y)); - } - - if ($p2) { - $cp = $this->_getControlPoints($p1, $p0, $p2, $p3); - $this->_canvas->addSpline( - array( - 'x' => $cp['X'], - 'y' => $cp['Y'], - 'p1x' => $cp['P1X'], - 'p1y' => $cp['P1Y'], - 'p2x' => $cp['P2X'], - 'p2y' => $cp['P2Y'] - ) - ); - } else { - $x = $this->_pointX($p1); - $y = $this->_pointY($p1); - $this->_canvas->addVertex(array('x' => $x, 'y' => $y)); - } - $lastPoint = $p1; - $first = false; - } - $lastPoint['Y'] = '#min_pos#'; - $x = $this->_pointX($lastPoint); - $y = $this->_pointY($lastPoint); - $this->_canvas->addVertex(array('x' => $x, 'y' => $y)); - - $this->_getFillStyle($key); - $this->_getLineStyle($key); - $this->_canvas->polygon(array('connect' => true)); - } - unset($keys); - $this->_drawMarker(); - $this->_canvas->endGroup(); - return true; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Area.php,v 1.11 2005/11/27 22:21:17 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot/Smoothed/Bezier.php + */ +require_once 'Image/Graph/Plot/Smoothed/Bezier.php'; + +/** + * Bezier smoothed area chart + * + * Similar to an {@link Image_Graph_Plot_Area}, but the interconnecting lines + * between two datapoints are smoothed using a Bezier curve, which enables the + * chart to appear as a nice curved plot instead of the sharp edges of a + * conventional {@link Image_Graph_Plot_Area}. Smoothed charts are only supported + * with non-stacked types + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Plot_Smoothed_Area extends Image_Graph_Plot_Smoothed_Bezier +{ + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + + $this->_canvas->addVertex(array('x' => $x0, 'y' => $y1)); + $this->_addSamplePoints($x0, $y0, $x1, $y1); + $this->_canvas->addVertex(array('x' => $x1, 'y' => $y1)); + $this->_canvas->polygon(array('connect' => true)); + } + + /** + * Output the Bezier smoothed plot as an Area Chart + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + $this->_clip(true); + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + $first = true; + while ($p1 = $dataset->_next()) { + $p0 = $dataset->_nearby(-2); + $p2 = $dataset->_nearby(0); + $p3 = $dataset->_nearby(1); + if ($first) { + $p = $p1; + $p['Y'] = '#min_pos#'; + $x = $this->_pointX($p); + $y = $this->_pointY($p); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y)); + } + + if ($p2) { + $cp = $this->_getControlPoints($p1, $p0, $p2, $p3); + $this->_canvas->addSpline( + array( + 'x' => $cp['X'], + 'y' => $cp['Y'], + 'p1x' => $cp['P1X'], + 'p1y' => $cp['P1Y'], + 'p2x' => $cp['P2X'], + 'p2y' => $cp['P2Y'] + ) + ); + } else { + $x = $this->_pointX($p1); + $y = $this->_pointY($p1); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y)); + } + $lastPoint = $p1; + $first = false; + } + $lastPoint['Y'] = '#min_pos#'; + $x = $this->_pointX($lastPoint); + $y = $this->_pointY($lastPoint); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y)); + + $this->_getFillStyle($key); + $this->_getLineStyle($key); + $this->_canvas->polygon(array('connect' => true)); + } + unset($keys); + $this->_drawMarker(); + $this->_clip(false); + $this->_canvas->endGroup(); + return true; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Plot/Smoothed/Bezier.php b/includes/pear/Image/Graph/Plot/Smoothed/Bezier.php index 0b9f5366..2350c7f0 100644 --- a/includes/pear/Image/Graph/Plot/Smoothed/Bezier.php +++ b/includes/pear/Image/Graph/Plot/Smoothed/Bezier.php @@ -1,173 +1,173 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Bezier.php,v 1.8 2005/08/24 20:36:02 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Plot.php - */ -require_once 'Image/Graph/Plot.php'; - -/** - * Include file Image/Graph/Tool.php - */ -require_once 'Image/Graph/Tool.php'; - -/** - * Bezier smoothed plottype. - * - * The framework for calculating the Bezier smoothed curve from the dataset. - * Used in {@link Image_Graph_Plot_Smoothed_Line} and {@link - * Image_Graph_Plot_Smoothed_Area}. Smoothed charts are only supported with non- - * stacked types - * @link http://homepages.borland.com/efg2lab/Graphics/Jean- - * YvesQueinecBezierCurves.htm efg computer lab - description of bezier curves - * - * @category Images - * @package Image_Graph - * @subpackage Plot - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - * @abstract - */ -class Image_Graph_Plot_Smoothed_Bezier extends Image_Graph_Plot -{ - - /** - * Image_Graph_Plot_Smoothed_Bezier [Constructor] - * - * Only 'normal' multitype supported - * - * @param Dataset $dataset The data set (value containter) to plot - * @param string $title The title of the plot (used for legends, {@link - * Image_Graph_Legend}) - */ - function Image_Graph_Plot_Smoothed_Bezier(& $dataset, $title = '') - { - parent::Image_Graph_Plot($dataset, 'normal', $title); - } - - /** - * Return the minimum Y point - * - * @return double The minumum Y point - * @access private - */ - function _minimumY() - { - return 1.05 * parent::_minimumY(); - } - - /** - * Return the maximum Y point - * - * @return double The maximum Y point - * @access private - */ - function _maximumY() - { - return 1.05 * parent::_maximumY(); - } - - /** - * Calculates all Bezier points, for the curve - * - * @param array $p1 The actual point to calculate control points for - * @param array $p0 The point "just before" $p1 - * @param array $p2 The point "just after" $p1 - * @param array $p3 The point "just after" $p2 - * @return array Array of Bezier points - * @access private - */ - function _getControlPoints($p1, $p0, $p2, $p3) - { - $p1 = $this->_pointXY($p1); - if ($p2) { - $p2 = $this->_pointXY($p2); - } - if (!$p0) { - $p0['X'] = $p1['X'] - abs($p2['X'] - $p1['X']); - $p0['Y'] = $p1['Y']; //-($p2['Y']-$p1['Y']); - } else { - $p0 = $this->_pointXY($p0); - } - if (!$p3) { - $p3['X'] = $p1['X'] + 2*abs($p1['X'] - $p0['X']); - $p3['Y'] = $p1['Y']; - } else { - $p3 = $this->_pointXY($p3); - } - - if (!$p2) { - $p2['X'] = $p1['X'] + abs($p1['X'] - $p0['X']); - $p2['Y'] = $p1['Y']; - } - - $pC1['X'] = Image_Graph_Tool::controlPoint($p0['X'], $p1['X'], $p2['X']); - $pC1['Y'] = Image_Graph_Tool::controlPoint($p0['Y'], $p1['Y'], $p2['Y']); - $pC2['X'] = Image_Graph_Tool::controlPoint($p3['X'], $p2['X'], $p1['X']); - $pC2['Y'] = Image_Graph_Tool::controlPoint($p3['Y'], $p2['Y'], $p1['Y']); - - return array( - 'X' => $p1['X'], - 'Y' => $p1['Y'], - 'P1X' => $pC1['X'], - 'P1Y' => $pC1['Y'], - 'P2X' => $pC2['X'], - 'P2Y' => $pC2['Y'] - ); - } - - /** - * Create legend sample data for the canvas. - * - * Common for all smoothed plots - * - * @access private - */ - function _addSamplePoints($x0, $y0, $x1, $y1) - { - $p = abs($x1 - $x0); - $cy = ($y0 + $y1) / 2; - $h = abs($y1 - $y0); - $dy = $h / 4; - $dw = abs($x1 - $x0) / $p; - for ($i = 0; $i < $p; $i++) { - $v = 2 * pi() * $i / $p; - $x = $x0 + $i * $dw; - $y = $cy + 2 * $v * sin($v); - $this->_canvas->addVertex(array('x' => $x, 'y' => $y)); - } - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Bezier.php,v 1.8 2005/08/24 20:36:02 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot.php + */ +require_once 'Image/Graph/Plot.php'; + +/** + * Include file Image/Graph/Tool.php + */ +require_once 'Image/Graph/Tool.php'; + +/** + * Bezier smoothed plottype. + * + * The framework for calculating the Bezier smoothed curve from the dataset. + * Used in {@link Image_Graph_Plot_Smoothed_Line} and {@link + * Image_Graph_Plot_Smoothed_Area}. Smoothed charts are only supported with non- + * stacked types + * @link http://homepages.borland.com/efg2lab/Graphics/Jean- + * YvesQueinecBezierCurves.htm efg computer lab - description of bezier curves + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + * @abstract + */ +class Image_Graph_Plot_Smoothed_Bezier extends Image_Graph_Plot +{ + + /** + * Image_Graph_Plot_Smoothed_Bezier [Constructor] + * + * Only 'normal' multitype supported + * + * @param Dataset $dataset The data set (value containter) to plot + * @param string $title The title of the plot (used for legends, {@link + * Image_Graph_Legend}) + */ + function Image_Graph_Plot_Smoothed_Bezier(& $dataset, $title = '') + { + parent::Image_Graph_Plot($dataset, 'normal', $title); + } + + /** + * Return the minimum Y point + * + * @return double The minumum Y point + * @access private + */ + function _minimumY() + { + return 1.05 * parent::_minimumY(); + } + + /** + * Return the maximum Y point + * + * @return double The maximum Y point + * @access private + */ + function _maximumY() + { + return 1.05 * parent::_maximumY(); + } + + /** + * Calculates all Bezier points, for the curve + * + * @param array $p1 The actual point to calculate control points for + * @param array $p0 The point "just before" $p1 + * @param array $p2 The point "just after" $p1 + * @param array $p3 The point "just after" $p2 + * @return array Array of Bezier points + * @access private + */ + function _getControlPoints($p1, $p0, $p2, $p3) + { + $p1 = $this->_pointXY($p1); + if ($p2) { + $p2 = $this->_pointXY($p2); + } + if (!$p0) { + $p0['X'] = $p1['X'] - abs($p2['X'] - $p1['X']); + $p0['Y'] = $p1['Y']; //-($p2['Y']-$p1['Y']); + } else { + $p0 = $this->_pointXY($p0); + } + if (!$p3) { + $p3['X'] = $p1['X'] + 2*abs($p1['X'] - $p0['X']); + $p3['Y'] = $p1['Y']; + } else { + $p3 = $this->_pointXY($p3); + } + + if (!$p2) { + $p2['X'] = $p1['X'] + abs($p1['X'] - $p0['X']); + $p2['Y'] = $p1['Y']; + } + + $pC1['X'] = Image_Graph_Tool::controlPoint($p0['X'], $p1['X'], $p2['X']); + $pC1['Y'] = Image_Graph_Tool::controlPoint($p0['Y'], $p1['Y'], $p2['Y']); + $pC2['X'] = Image_Graph_Tool::controlPoint($p3['X'], $p2['X'], $p1['X']); + $pC2['Y'] = Image_Graph_Tool::controlPoint($p3['Y'], $p2['Y'], $p1['Y']); + + return array( + 'X' => $p1['X'], + 'Y' => $p1['Y'], + 'P1X' => $pC1['X'], + 'P1Y' => $pC1['Y'], + 'P2X' => $pC2['X'], + 'P2Y' => $pC2['Y'] + ); + } + + /** + * Create legend sample data for the canvas. + * + * Common for all smoothed plots + * + * @access private + */ + function _addSamplePoints($x0, $y0, $x1, $y1) + { + $p = abs($x1 - $x0); + $cy = ($y0 + $y1) / 2; + $h = abs($y1 - $y0); + $dy = $h / 4; + $dw = abs($x1 - $x0) / $p; + for ($i = 0; $i < $p; $i++) { + $v = 2 * pi() * $i / $p; + $x = $x0 + $i * $dw; + $y = $cy + 2 * $v * sin($v); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y)); + } + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Plot/Smoothed/Line.php b/includes/pear/Image/Graph/Plot/Smoothed/Line.php index d99769bd..d768aac8 100644 --- a/includes/pear/Image/Graph/Plot/Smoothed/Line.php +++ b/includes/pear/Image/Graph/Plot/Smoothed/Line.php @@ -1,164 +1,172 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Line.php,v 1.11 2005/08/08 19:09:19 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Plot/Smoothed/Bezier.php - */ -require_once 'Image/Graph/Plot/Smoothed/Bezier.php'; - -/** - * Bezier smoothed line chart. - * - * Similar to a {@link Image_Graph_Plot_Line}, but the interconnecting lines - * between two datapoints are smoothed using a Bezier curve, which enables the - * chart to appear as a nice curved plot instead of the sharp edges of a - * conventional {@link Image_Graph_Plot_Line}. Smoothed charts are only supported - * with non-stacked types - * - * @category Images - * @package Image_Graph - * @subpackage Plot - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Plot_Smoothed_Line extends Image_Graph_Plot_Smoothed_Bezier -{ - - /** - * Gets the fill style of the element - * - * @return int A GD filestyle representing the fill style - * @see Image_Graph_Fill - * @access private - */ - function _getFillStyle($ID = false) - { - return IMG_COLOR_TRANSPARENT; - } - - /** - * Perform the actual drawing on the legend. - * - * @param int $x0 The top-left x-coordinate - * @param int $y0 The top-left y-coordinate - * @param int $x1 The bottom-right x-coordinate - * @param int $y1 The bottom-right y-coordinate - * @access private - */ - function _drawLegendSample($x0, $y0, $x1, $y1) - { - $this->_addSamplePoints($x0, $y0, $x1, $y1); - $this->_canvas->polygon(array('connect' => false)); - } - - /** - * Output the Bezier smoothed plot as an Line Chart - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (parent::_done() === false) { - return false; - } - - $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $dataset =& $this->_dataset[$key]; - $dataset->_reset(); - $numPoints = 0; - while ($p1 = $dataset->_next()) { - if ($p1['Y'] === null) { - if ($numPoints > 1) { - $this->_getLineStyle($key); - $this->_canvas->polygon(array('connect' => false, 'map_vertices' => true)); - } - $numPoints = 0; - } else { - $p0 = $dataset->_nearby(-2); - $p2 = $dataset->_nearby(0); - $p3 = $dataset->_nearby(1); - - if (($p0) && ($p0['Y'] === null)) { - $p0 = false; - } - if (($p2) && ($p2['Y'] === null)) { - $p2 = false; - } - if (($p3) && ($p3['Y'] === null)) { - $p3 = false; - } - - if ($p2) { - $cp = $this->_getControlPoints($p1, $p0, $p2, $p3); - $this->_canvas->addSpline( - $this->_mergeData( - $p1, - array( - 'x' => $cp['X'], - 'y' => $cp['Y'], - 'p1x' => $cp['P1X'], - 'p1y' => $cp['P1Y'], - 'p2x' => $cp['P2X'], - 'p2y' => $cp['P2Y'] - ) - ) - ); - } else { - $x = $this->_pointX($p1); - $y = $this->_pointY($p1); - $this->_canvas->addVertex( - $this->_mergeData( - $p1, - array('x' => $x, 'y' => $y) - ) - ); - } - $numPoints++; - } - } - if ($numPoints > 1) { - $this->_getLineStyle(); - $this->_canvas->polygon(array('connect' => false, 'map_vertices' => true)); - } - } - unset($keys); - $this->_drawMarker(); - $this->_canvas->endGroup(); - return true; - } - -} + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Line.php,v 1.14 2006/03/02 12:37:37 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot/Smoothed/Bezier.php + */ +require_once 'Image/Graph/Plot/Smoothed/Bezier.php'; + +/** + * Bezier smoothed line chart. + * + * Similar to a {@link Image_Graph_Plot_Line}, but the interconnecting lines + * between two datapoints are smoothed using a Bezier curve, which enables the + * chart to appear as a nice curved plot instead of the sharp edges of a + * conventional {@link Image_Graph_Plot_Line}. Smoothed charts are only supported + * with non-stacked types + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Plot_Smoothed_Line extends Image_Graph_Plot_Smoothed_Bezier +{ + + /** + * Gets the fill style of the element + * + * @return int A GD filestyle representing the fill style + * @see Image_Graph_Fill + * @access private + */ + function _getFillStyle($ID = false) + { + return IMG_COLOR_TRANSPARENT; + } + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $this->_addSamplePoints($x0, $y0, $x1, $y1); + $this->_canvas->polygon(array('connect' => false)); + } + + /** + * Output the Bezier smoothed plot as an Line Chart + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (parent::_done() === false) { + return false; + } + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + $this->_clip(true); + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + $numPoints = 0; + while ($p1 = $dataset->_next()) { + if ($p1['Y'] === null) { + if ($numPoints > 1) { + $this->_getLineStyle($key); + $this->_canvas->polygon(array('connect' => false, 'map_vertices' => true)); + } + else { + $this->_canvas->reset(); + } + $numPoints = 0; + } else { + $p0 = $dataset->_nearby(-2); + $p2 = $dataset->_nearby(0); + $p3 = $dataset->_nearby(1); + + if (($p0) && ($p0['Y'] === null)) { + $p0 = false; + } + if (($p2) && ($p2['Y'] === null)) { + $p2 = false; + } + if (($p3) && ($p3['Y'] === null)) { + $p3 = false; + } + + if ($p2) { + $cp = $this->_getControlPoints($p1, $p0, $p2, $p3); + $this->_canvas->addSpline( + $this->_mergeData( + $p1, + array( + 'x' => $cp['X'], + 'y' => $cp['Y'], + 'p1x' => $cp['P1X'], + 'p1y' => $cp['P1Y'], + 'p2x' => $cp['P2X'], + 'p2y' => $cp['P2Y'] + ) + ) + ); + } else { + $x = $this->_pointX($p1); + $y = $this->_pointY($p1); + $this->_canvas->addVertex( + $this->_mergeData( + $p1, + array('x' => $x, 'y' => $y) + ) + ); + } + $numPoints++; + } + } + if ($numPoints > 1) { + $this->_getLineStyle(); + $this->_canvas->polygon(array('connect' => false, 'map_vertices' => true)); + } + else { + $this->_canvas->reset(); + } + } + unset($keys); + $this->_drawMarker(); + $this->_clip(false); + $this->_canvas->endGroup(); + return true; + } + +} ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Plot/Smoothed/Radar.php b/includes/pear/Image/Graph/Plot/Smoothed/Radar.php index 49e989f2..15922962 100644 --- a/includes/pear/Image/Graph/Plot/Smoothed/Radar.php +++ b/includes/pear/Image/Graph/Plot/Smoothed/Radar.php @@ -1,140 +1,142 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Radar.php,v 1.9 2005/08/03 21:21:52 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - * @since File available since Release 0.3.0dev2 - */ - -/** - * Include file Image/Graph/Plot/Smoothed/Bezier.php - */ -require_once 'Image/Graph/Plot/Smoothed/Bezier.php'; - -/** - * Smoothed radar chart. - * - * @category Images - * @package Image_Graph - * @subpackage Plot - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - * @since Class available since Release 0.3.0dev2 - */ -class Image_Graph_Plot_Smoothed_Radar extends Image_Graph_Plot_Smoothed_Bezier -{ - - /** - * Output the plot - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); - if (is_a($this->_parent, 'Image_Graph_Plotarea_Radar')) { - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $dataset =& $this->_dataset[$key]; - if ($dataset->count() >= 3) { - $dataset->_reset(); - $p1_ = $dataset->_next(); - $p2_ = $dataset->_next(); - $p3_ = $dataset->_next(); - $plast_ = false; - if ($p3_) { - while ($p = $dataset->_next()) { - $plast_ = $p; - } - } - - if ($plast_ === false) { - $plast_ = $p3_; - } - $dataset->_reset(); - while ($p1 = $dataset->_next()) { - $p0 = $dataset->_nearby(-2); - $p2 = $dataset->_nearby(0); - $p3 = $dataset->_nearby(1); - - if ($p0 === false) { - $p0 = $plast_; - } - - if ($p2 === false) { - $p2 = $p1_; - $p3 = $p2_; - } elseif ($p3 === false) { - $p3 = $p1_; - } - - - $cp = $this->_getControlPoints($p1, $p0, $p2, $p3); - $this->_canvas->addSpline( - array( - 'x' => $cp['X'], - 'y' => $cp['Y'], - 'p1x' => $cp['P1X'], - 'p1y' => $cp['P1Y'], - 'p2x' => $cp['P2X'], - 'p2y' => $cp['P2Y'] - ) - ); - - $next2last = $p0; - $last = $p1; - } - - $cp = $this->_getControlPoints($p1_, $plast_, $p2_, $p3_); - $this->_canvas->addSpline( - array( - 'x' => $cp['X'], - 'y' => $cp['Y'], - 'p1x' => $cp['P1X'], - 'p1y' => $cp['P1Y'], - 'p2x' => $cp['P2X'], - 'p2y' => $cp['P2Y'] - ) - ); - $this->_getFillStyle($key); - $this->_getLineStyle($key); - $this->_canvas->polygon(array('connect' => true)); - } - } - unset($keys); - } - $this->_drawMarker(); - $this->_canvas->endGroup($this->_title); - return parent::_done(); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Radar.php,v 1.10 2005/11/27 22:21:17 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + * @since File available since Release 0.3.0dev2 + */ + +/** + * Include file Image/Graph/Plot/Smoothed/Bezier.php + */ +require_once 'Image/Graph/Plot/Smoothed/Bezier.php'; + +/** + * Smoothed radar chart. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + * @since Class available since Release 0.3.0dev2 + */ +class Image_Graph_Plot_Smoothed_Radar extends Image_Graph_Plot_Smoothed_Bezier +{ + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + $this->_clip(true); + if (is_a($this->_parent, 'Image_Graph_Plotarea_Radar')) { + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + if ($dataset->count() >= 3) { + $dataset->_reset(); + $p1_ = $dataset->_next(); + $p2_ = $dataset->_next(); + $p3_ = $dataset->_next(); + $plast_ = false; + if ($p3_) { + while ($p = $dataset->_next()) { + $plast_ = $p; + } + } + + if ($plast_ === false) { + $plast_ = $p3_; + } + $dataset->_reset(); + while ($p1 = $dataset->_next()) { + $p0 = $dataset->_nearby(-2); + $p2 = $dataset->_nearby(0); + $p3 = $dataset->_nearby(1); + + if ($p0 === false) { + $p0 = $plast_; + } + + if ($p2 === false) { + $p2 = $p1_; + $p3 = $p2_; + } elseif ($p3 === false) { + $p3 = $p1_; + } + + + $cp = $this->_getControlPoints($p1, $p0, $p2, $p3); + $this->_canvas->addSpline( + array( + 'x' => $cp['X'], + 'y' => $cp['Y'], + 'p1x' => $cp['P1X'], + 'p1y' => $cp['P1Y'], + 'p2x' => $cp['P2X'], + 'p2y' => $cp['P2Y'] + ) + ); + + $next2last = $p0; + $last = $p1; + } + + $cp = $this->_getControlPoints($p1_, $plast_, $p2_, $p3_); + $this->_canvas->addSpline( + array( + 'x' => $cp['X'], + 'y' => $cp['Y'], + 'p1x' => $cp['P1X'], + 'p1y' => $cp['P1Y'], + 'p2x' => $cp['P2X'], + 'p2y' => $cp['P2Y'] + ) + ); + $this->_getFillStyle($key); + $this->_getLineStyle($key); + $this->_canvas->polygon(array('connect' => true)); + } + } + unset($keys); + } + $this->_drawMarker(); + $this->_clip(false); + $this->_canvas->endGroup($this->_title); + return parent::_done(); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Plot/Step.php b/includes/pear/Image/Graph/Plot/Step.php index c5ccf4cd..27dc04bd 100644 --- a/includes/pear/Image/Graph/Plot/Step.php +++ b/includes/pear/Image/Graph/Plot/Step.php @@ -1,198 +1,200 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Step.php,v 1.14 2005/10/05 20:51:21 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Plot/Bar.php - */ -require_once 'Image/Graph/Plot/Bar.php'; - -/** - * Step chart. - * - * @category Images - * @package Image_Graph - * @subpackage Plot - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Plot_Step extends Image_Graph_Plot -{ - - /** - * Perform the actual drawing on the legend. - * - * @param int $x0 The top-left x-coordinate - * @param int $y0 The top-left y-coordinate - * @param int $x1 The bottom-right x-coordinate - * @param int $y1 The bottom-right y-coordinate - * @access private - */ - function _drawLegendSample($x0, $y0, $x1, $y1) - { - $dx = abs($x1 - $x0) / 3; - $dy = abs($y1 - $y0) / 3; - $this->_canvas->addVertex(array('x' => $x0, 'y' => $y1)); - $this->_canvas->addVertex(array('x' => $x0, 'y' => $y0 + $dy)); - - $this->_canvas->addVertex(array('x' => $x0 + $dx, 'y' => $y0 + $dy)); - $this->_canvas->addVertex(array('x' => $x0 + $dx, 'y' => $y0)); - - $this->_canvas->addVertex(array('x' => $x0 + 2*$dx, 'y' => $y0)); - $this->_canvas->addVertex(array('x' => $x0 + 2*$dx, 'y' => $y0 + 2*$dy)); - - $this->_canvas->addVertex(array('x' => $x1, 'y' => $y0 + 2*$dy)); - $this->_canvas->addVertex(array('x' => $x1, 'y' => $y1)); - $this->_canvas->polygon(array('connect' => true)); - } - - /** - * PlotType [Constructor] - * - * A 'normal' step chart is 'stacked' - * - * @param Dataset $dataset The data set (value containter) to plot - * @param string $multiType The type of the plot - * @param string $title The title of the plot (used for legends, - * {@link Image_Graph_Legend}) - */ - function Image_Graph_Plot_Step(& $dataset, $multiType = 'stacked', $title = '') - { - $multiType = strtolower($multiType); - if (($multiType != 'stacked') && ($multiType != 'stacked100pct')) { - $multiType = 'stacked'; - } - parent::Image_Graph_Plot($dataset, $multiType, $title); - } - - /** - * Output the plot - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if (Image_Graph_Plot::_done() === false) { - return false; - } - - $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); - - if ($this->_multiType == 'stacked100pct') { - $total = $this->_getTotals(); - } - - if ($this->_parent->_horizontal) { - $width = $this->height() / ($this->_maximumX() + 2) / 2; - } - else { - $width = $this->width() / ($this->_maximumX() + 2) / 2; - } - - reset($this->_dataset); - $key = key($this->_dataset); - $dataset =& $this->_dataset[$key]; - - $first = $dataset->first(); - $last = $dataset->last(); - - $point = array ('X' => $first['X'], 'Y' => '#min_pos#'); - $firstY = $this->_pointY($point) + ($this->_parent->_horizontal ? $width : 0); - $base[] = $firstY; - $firstX = $this->_pointX($point) - ($this->_parent->_horizontal ? 0 : $width); - $base[] = $firstX; - - $point = array ('X' => $last['X'], 'Y' => '#min_pos#'); - $base[] = $this->_pointY($point) - ($this->_parent->_horizontal ? $width : 0); - $base[] = $this->_pointX($point) + ($this->_parent->_horizontal ? 0 : $width); - - $first = ($this->_parent->_horizontal ? $firstY : $firstX); - - $keys = array_keys($this->_dataset); - foreach ($keys as $key) { - $dataset =& $this->_dataset[$key]; - $dataset->_reset(); - $polygon = array_reverse($base); - unset ($base); - $last = $first; - while ($point = $dataset->_next()) { - $x = $point['X']; - $p = $point; - - if (!isset($current[$x])) { - $current[$x] = 0; - } - - if ($this->_multiType == 'stacked100pct') { - $p['Y'] = 100 * ($current[$x] + $point['Y']) / $total['TOTAL_Y'][$x]; - } else { - $p['Y'] += $current[$x]; - } - $current[$x] += $point['Y']; - $point = $p; - - if ($this->_parent->_horizontal) { - $x0 = $this->_pointX($point); - $y0 = $last; - $x1 = $this->_pointX($point); - $last = $y1 = $this->_pointY($point) - $width; - } - else { - $x0 = $last; - $y0 = $this->_pointY($point); - $last = $x1 = $this->_pointX($point) + $width; - $y1 = $this->_pointY($point); - } - $polygon[] = $x0; $base[] = $y0; - $polygon[] = $y0; $base[] = $x0; - $polygon[] = $x1; $base[] = $y1; - $polygon[] = $y1; $base[] = $x1; - } - - while (list(, $x) = each($polygon)) { - list(, $y) = each($polygon); - $this->_canvas->addVertex(array('x' => $x, 'y' => $y)); - } - - $this->_getFillStyle($key); - $this->_getLineStyle($key); - $this->_canvas->polygon(array('connect' => true)); - } - unset($keys); - $this->_drawMarker(); - $this->_canvas->endGroup(); - return true; - } -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Step.php,v 1.15 2005/11/27 22:21:16 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plot/Bar.php + */ +require_once 'Image/Graph/Plot/Bar.php'; + +/** + * Step chart. + * + * @category Images + * @package Image_Graph + * @subpackage Plot + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Plot_Step extends Image_Graph_Plot +{ + + /** + * Perform the actual drawing on the legend. + * + * @param int $x0 The top-left x-coordinate + * @param int $y0 The top-left y-coordinate + * @param int $x1 The bottom-right x-coordinate + * @param int $y1 The bottom-right y-coordinate + * @access private + */ + function _drawLegendSample($x0, $y0, $x1, $y1) + { + $dx = abs($x1 - $x0) / 3; + $dy = abs($y1 - $y0) / 3; + $this->_canvas->addVertex(array('x' => $x0, 'y' => $y1)); + $this->_canvas->addVertex(array('x' => $x0, 'y' => $y0 + $dy)); + + $this->_canvas->addVertex(array('x' => $x0 + $dx, 'y' => $y0 + $dy)); + $this->_canvas->addVertex(array('x' => $x0 + $dx, 'y' => $y0)); + + $this->_canvas->addVertex(array('x' => $x0 + 2*$dx, 'y' => $y0)); + $this->_canvas->addVertex(array('x' => $x0 + 2*$dx, 'y' => $y0 + 2*$dy)); + + $this->_canvas->addVertex(array('x' => $x1, 'y' => $y0 + 2*$dy)); + $this->_canvas->addVertex(array('x' => $x1, 'y' => $y1)); + $this->_canvas->polygon(array('connect' => true)); + } + + /** + * PlotType [Constructor] + * + * A 'normal' step chart is 'stacked' + * + * @param Dataset $dataset The data set (value containter) to plot + * @param string $multiType The type of the plot + * @param string $title The title of the plot (used for legends, + * {@link Image_Graph_Legend}) + */ + function Image_Graph_Plot_Step(& $dataset, $multiType = 'stacked', $title = '') + { + $multiType = strtolower($multiType); + if (($multiType != 'stacked') && ($multiType != 'stacked100pct')) { + $multiType = 'stacked'; + } + parent::Image_Graph_Plot($dataset, $multiType, $title); + } + + /** + * Output the plot + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if (Image_Graph_Plot::_done() === false) { + return false; + } + + $this->_canvas->startGroup(get_class($this) . '_' . $this->_title); + $this->_clip(true); + + if ($this->_multiType == 'stacked100pct') { + $total = $this->_getTotals(); + } + + if ($this->_parent->_horizontal) { + $width = $this->height() / ($this->_maximumX() + 2) / 2; + } + else { + $width = $this->width() / ($this->_maximumX() + 2) / 2; + } + + reset($this->_dataset); + $key = key($this->_dataset); + $dataset =& $this->_dataset[$key]; + + $first = $dataset->first(); + $last = $dataset->last(); + + $point = array ('X' => $first['X'], 'Y' => '#min_pos#'); + $firstY = $this->_pointY($point) + ($this->_parent->_horizontal ? $width : 0); + $base[] = $firstY; + $firstX = $this->_pointX($point) - ($this->_parent->_horizontal ? 0 : $width); + $base[] = $firstX; + + $point = array ('X' => $last['X'], 'Y' => '#min_pos#'); + $base[] = $this->_pointY($point) - ($this->_parent->_horizontal ? $width : 0); + $base[] = $this->_pointX($point) + ($this->_parent->_horizontal ? 0 : $width); + + $first = ($this->_parent->_horizontal ? $firstY : $firstX); + + $keys = array_keys($this->_dataset); + foreach ($keys as $key) { + $dataset =& $this->_dataset[$key]; + $dataset->_reset(); + $polygon = array_reverse($base); + unset ($base); + $last = $first; + while ($point = $dataset->_next()) { + $x = $point['X']; + $p = $point; + + if (!isset($current[$x])) { + $current[$x] = 0; + } + + if ($this->_multiType == 'stacked100pct') { + $p['Y'] = 100 * ($current[$x] + $point['Y']) / $total['TOTAL_Y'][$x]; + } else { + $p['Y'] += $current[$x]; + } + $current[$x] += $point['Y']; + $point = $p; + + if ($this->_parent->_horizontal) { + $x0 = $this->_pointX($point); + $y0 = $last; + $x1 = $this->_pointX($point); + $last = $y1 = $this->_pointY($point) - $width; + } + else { + $x0 = $last; + $y0 = $this->_pointY($point); + $last = $x1 = $this->_pointX($point) + $width; + $y1 = $this->_pointY($point); + } + $polygon[] = $x0; $base[] = $y0; + $polygon[] = $y0; $base[] = $x0; + $polygon[] = $x1; $base[] = $y1; + $polygon[] = $y1; $base[] = $x1; + } + + while (list(, $x) = each($polygon)) { + list(, $y) = each($polygon); + $this->_canvas->addVertex(array('x' => $x, 'y' => $y)); + } + + $this->_getFillStyle($key); + $this->_getLineStyle($key); + $this->_canvas->polygon(array('connect' => true)); + } + unset($keys); + $this->_drawMarker(); + $this->_clip(false); + $this->_canvas->endGroup(); + return true; + } +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Plotarea.php b/includes/pear/Image/Graph/Plotarea.php index b8b53af8..d7a70f40 100644 --- a/includes/pear/Image/Graph/Plotarea.php +++ b/includes/pear/Image/Graph/Plotarea.php @@ -1,1143 +1,1145 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Plotarea.php,v 1.21 2005/10/05 20:51:21 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Layout.php - */ -require_once 'Image/Graph/Layout.php'; - -/** - * Plot area used for drawing plots. - * - * The plotarea consists of an x-axis and an y-axis, the plotarea can plot multiple - * charts within one plotares, by simply adding them (the axis' will scale to the - * plots automatically). A graph can consist of more plotareas - * - * @category Images - * @package Image_Graph - * @subpackage Plotarea - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Plotarea extends Image_Graph_Layout -{ - - /** - * The left most pixel of the 'real' plot area on the canvas - * @var int - * @access private - */ - var $_plotLeft = 0; - - /** - * The top most pixel of the 'real' plot area on the canvas - * @var int - * @access private - */ - var $_plotTop = 0; - - /** - * The right most pixel of the 'real' plot area on the canvas - * @var int - * @access private - */ - var $_plotRight = 0; - - /** - * The bottom most pixel of the 'real' plot area on the canvas - * @var int - * @access private - */ - var $_plotBottom = 0; - - /** - * The X axis - * @var Axis - * @access private - */ - var $_axisX = null; - - /** - * The Y axis - * @var Axis - * @access private - */ - var $_axisY = null; - - /** - * The secondary Y axis - * @var Axis - * @access private - */ - var $_axisYSecondary = null; - - /** - * The border style of the 'real' plot area - * @var LineStyle - * @access private - */ - var $_plotBorderStyle = null; - - /** - * Does any plot have any data? - * @var bool - * @access private - */ - var $_hasData = false; - - /** - * Is the plotarea horizontal? - * @var bool - * @access private - */ - var $_horizontal = false; - - /** - * Image_Graph_Plotarea [Constructor] - * - * @param string $axisX The class of the X axis (if omitted a std. axis is created) - * @param string $axisY The class of the Y axis (if omitted a std. axis is created) - * @param string $direction The direction of the plotarea - 'horizontal' or 'vertical' (default) - */ - function Image_Graph_Plotarea($axisX = 'Image_Graph_Axis_Category', $axisY = 'Image_Graph_Axis', $direction = 'vertical') - { - parent::Image_Graph_Layout(); - - $this->_padding = 5; - - include_once 'Image/Graph.php'; - - $this->_axisX =& Image_Graph::factory($axisX, IMAGE_GRAPH_AXIS_X); - $this->_axisX->_setParent($this); - - $this->_axisY =& Image_Graph::factory($axisY, IMAGE_GRAPH_AXIS_Y); - $this->_axisY->_setParent($this); - $this->_axisY->_setMinimum(0); - - $this->_fillStyle = false; - - if ($direction == 'horizontal') { - $this->_horizontal = true; - $this->_axisX->_transpose = true; - $this->_axisY->_transpose = true; - } - } - - /** - * Sets the parent. The parent chain should ultimately be a GraPHP object - * - * @see Image_Graph_Common - * @param Image_Graph_Common $parent The parent - * @access private - */ - function _setParent(& $parent) - { - parent::_setParent($parent); - if ($this->_axisX !== null) { - $this->_axisX->_setParent($this); - } - if ($this->_axisY !== null) { - $this->_axisY->_setParent($this); - } - if ($this->_axisYSecondary !== null) { - $this->_axisYSecondary->_setParent($this); - } - } - - /** - * Sets the plot border line style of the element. - * - * @param Image_Graph_Line $lineStyle The line style of the border - * @deprecated 0.3.0dev2 - 2004-12-16 - */ - function setPlotBorderStyle(& $plotBorderStyle) - { - } - - /** - * Adds an element to the plotarea - * - * @param Image_Graph_Element $element The element to add - * @param int $axis The axis to associate the element with, either - * IMAGE_GRAPH_AXIS_X, IMAGE_GRAPH_AXIS_Y, IMAGE_GRAPH_AXIS_Y_SECONDARY - * or the shorter string notations 'x', 'y' or 'ysec' (defaults to - * IMAGE_GRAPH_AXIS_Y) - * @return Image_Graph_Element The added element - * @see Image_Graph_Common::add() - */ - function &add(& $element, $axis = IMAGE_GRAPH_AXIS_Y) - { - if ($axis == 'x') { - $axis = IMAGE_GRAPH_AXIS_X; - } - if ($axis == 'y') { - $axis = IMAGE_GRAPH_AXIS_Y; - } - if ($axis == 'ysec') { - $axis = IMAGE_GRAPH_AXIS_Y_SECONDARY; - } - if (($axis == IMAGE_GRAPH_AXIS_Y_SECONDARY) && - ($this->_axisYSecondary == null)) - { - $this->_axisYSecondary =& Image_Graph::factory('axis', IMAGE_GRAPH_AXIS_Y_SECONDARY); - $this->_axisYSecondary->_setMinimum(0); - if ($this->_horizontal) { - $this->_axisYSecondary->_transpose = true; - } - } - - parent::add($element); - - if (is_a($element, 'Image_Graph_Plot')) { - $element->_setAxisY($axis); - // postpone extrema calculation until we calculate coordinates - //$this->_setExtrema($element); - } elseif (is_a($element, 'Image_Graph_Grid')) { - switch ($axis) { - case IMAGE_GRAPH_AXIS_X: - if ($this->_axisX != null) { - $element->_setPrimaryAxis($this->_axisX); - if ($this->_axisY != null) { - $element->_setSecondaryAxis($this->_axisY); - } - } - break; - case IMAGE_GRAPH_AXIS_Y: - if ($this->_axisY != null) { - $element->_setPrimaryAxis($this->_axisY); - if ($this->_axisX != null) { - $element->_setSecondaryAxis($this->_axisX); - } - } - break; - case IMAGE_GRAPH_AXIS_Y_SECONDARY: - if ($this->_axisYSecondary != null) { - $element->_setPrimaryAxis($this->_axisYSecondary); - if ($this->_axisX != null) { - $element->_setSecondaryAxis($this->_axisX); - } - } - break; - } - } elseif (is_a($element, 'Image_Graph_Axis')) { - switch ($element->_type) { - case IMAGE_GRAPH_AXIS_X: - $this->_axisX =& $element; - break; - - case IMAGE_GRAPH_AXIS_Y: - $this->_axisY =& $element; - break; - - case IMAGE_GRAPH_AXIS_Y_SECONDARY: - $this->_axisYSecondary =& $element; - break; - - } - if ($element->_getMinimum() == $element->_getMaximum()) { - $element->_setMinimum(0); - $element->_setMaximum(1); - } - } - return $element; - } - - /** - * Get the width of the 'real' plotarea - * - * @return int The width of the 'real' plotarea, ie not including space occupied by padding and axis - * @access private - */ - function _plotWidth() - { - return abs($this->_plotRight - $this->_plotLeft); - } - - /** - * Get the height of the 'real' plotarea - * - * @return int The height of the 'real' plotarea, ie not including space - * occupied by padding and axis - * @access private - */ - function _plotHeight() - { - return abs($this->_plotBottom - $this->_plotTop); - } - - /** - * Set the extrema of the axis - * - * @param Image_Graph_Plot $plot The plot that 'hold' the values - * @access private - */ - function _setExtrema(& $plot) - { - if (($this->_axisX != null) && ($this->_axisX->_isNumeric())) { - $this->_axisX->_setMinimum($plot->_minimumX()); - $this->_axisX->_setMaximum($plot->_maximumX()); - } - - if (($plot->_axisY == IMAGE_GRAPH_AXIS_Y_SECONDARY) && - ($this->_axisYSecondary !== null) && - ($this->_axisYSecondary->_isNumeric())) - { - $this->_axisYSecondary->_setMinimum($plot->_minimumY()); - $this->_axisYSecondary->_setMaximum($plot->_maximumY()); - } elseif (($this->_axisY != null) && ($this->_axisY->_isNumeric())) { - $this->_axisY->_setMinimum($plot->_minimumY()); - $this->_axisY->_setMaximum($plot->_maximumY()); - } - - $datasets =& $plot->dataset(); - if (!is_array($datasets)) { - $datasets = array($datasets); - } - - $keys = array_keys($datasets); - foreach ($keys as $key) { - $dataset =& $datasets[$key]; - if ($dataset->count() > 0) { - $this->_hasData = true; - } - - if (is_a($dataset, 'Image_Graph_Dataset')) { - if (($this->_axisX != null) && (!$this->_axisX->_isNumeric())) { - $this->_axisX->_applyDataset($dataset); - } - - if (($plot->_axisY == IMAGE_GRAPH_AXIS_Y_SECONDARY) && - ($this->_axisYSecondary !== null) && - (!$this->_axisYSecondary->_isNumeric())) - { - $this->_axisYSecondary->_applyDataset($dataset); - } elseif (($this->_axisY != null) && (!$this->_axisY->_isNumeric())) { - $this->_axisY->_applyDataset($dataset); - } - } - } - unset($keys); - } - - /** - * Left boundary of the background fill area - * - * @return int Leftmost position on the canvas - * @access private - */ - function _fillLeft() - { - return $this->_plotLeft; - } - - /** - * Top boundary of the background fill area - * - * @return int Topmost position on the canvas - * @access private - */ - function _fillTop() - { - return $this->_plotTop; - } - - /** - * Right boundary of the background fill area - * - * @return int Rightmost position on the canvas - * @access private - */ - function _fillRight() - { - return $this->_plotRight; - } - - /** - * Bottom boundary of the background fill area - * - * @return int Bottommost position on the canvas - * @access private - */ - function _fillBottom() - { - return $this->_plotBottom; - } - - /** - * Get the point from the x-axis - * @param array $value The value array - * @param int $min The minimum pixel position possible - * @param int $max The maximum pixel position possible - * @return int The pixel position from the axis - * @access private - */ - function _axisPointX($value, $min, $max) - { - if (($this->_axisX == null) || (!isset($value['X']))) { - return false; - } - - if ($value['X'] === '#min#') { - return $min; - } - if ($value['X'] === '#max#') { - return $max; - } - - return $this->_axisX->_point($value['X']); - } - - /** - * Get the point from the x-axis - * @param array $value The value array - * @param int $min The minimum pixel position possible - * @param int $max The maximum pixel position possible - * @return int The pixel position from the axis - * @access private - */ - function _axisPointY($value, $min, $max) - { - if (!isset($value['Y'])) { - return false; - } - - if (($value['Y'] === '#min_pos#') || ($value['Y'] === '#max_nex#')) { - // return the minimum (bottom) position or if negative then zero - // or the maxmum (top) position or if positive then zero - if ((isset($value['AXIS_Y'])) && - ($value['AXIS_Y'] == IMAGE_GRAPH_AXIS_Y_SECONDARY) && - ($this->_axisYSecondary !== null) - ) { - $axisY =& $this->_axisYSecondary; - } else { - $axisY =& $this->_axisY; - } - if ($value['Y'] === '#min_pos#') { - return $axisY->_point(max(0, $axisY->_getMinimum())); - } else { - return $axisY->_point(min(0, $axisY->_getMaximum())); - } - } - - if ($value['Y'] === '#min#') { - return $min; - } - if ($value['Y'] === '#max#') { - return $max; - } - - if ((isset($value['AXIS_Y'])) && - ($value['AXIS_Y'] == IMAGE_GRAPH_AXIS_Y_SECONDARY) - ) { - if ($this->_axisYSecondary !== null) { - return $this->_axisYSecondary->_point($value['Y']); - } - } else { - if ($this->_axisY !== null) { - return $this->_axisY->_point($value['Y']); - } - } - return false; - } - - /** - * Get the X pixel position represented by a value - * - * @param double Value the value to get the pixel-point for - * @return double The pixel position along the axis - * @access private - */ - function _pointX($value) - { - if ($this->_horizontal) { - return $this->_axisPointY($value, $this->_plotLeft, $this->_plotRight); - } - else { - return $this->_axisPointX($value, $this->_plotLeft, $this->_plotRight); - } - } - - /** - * Get the Y pixel position represented by a value - * - * @param double Value the value to get the pixel-point for - * @return double The pixel position along the axis - * @access private - */ - function _pointY($value) - { - if ($this->_horizontal) { - return $this->_axisPointX($value, $this->_plotBottom, $this->_plotTop); - } - else { - return $this->_axisPointY($value, $this->_plotBottom, $this->_plotTop); - } - } - - /** - * Return the minimum value of the specified axis - * - * @param int $axis The axis to return the minimum value of (see {$link - * Image_Graph_Plotarea::getAxis()}) - * @return double The minimum value of the axis - * @access private - */ - function _getMinimum($axis = IMAGE_GRAPH_AXIS_Y) - { - $axis =& $this->getAxis($axis); - if ($axis !== null) { - return $axis->_getMinimum(); - } else { - return 0; - } - } - - /** - * Return the maximum value of the specified axis - * - * @param int $axis The axis to return the maximum value of(see {$link - * Image_Graph_Plotarea::getAxis()}) - * @return double The maximum value of the axis - * @access private - */ - function _getMaximum($axis = IMAGE_GRAPH_AXIS_Y) - { - $axis =& $this->getAxis($axis); - if ($axis !== null) { - return $axis->_getMaximum(); - } else { - return 0; - } - } - - /** - * Return the label distance for the specified axis. - * - * @param int $axis The axis to return the label distance for - * @return int The distance between 2 adjacent labels - * @access private - */ - function _labelDistance($axis) - { - $axis =& $this->getAxis($axis); - if ($axis !== null) { - return $axis->_labelDistance(); - } - - return false; - } - - /** - * Hides the axis - */ - function hideAxis($axis = false) - { - if (((!$axis) || ($axis === $this->_axisX) || ($axis === 'x')) && ($this->_axisX != null)) { - $this->_axisX->hide(); - } - if (((!$axis) || ($axis === $this->_axisY) || ($axis === 'y')) && ($this->_axisY != null)) { - $this->_axisY->hide(); - } - if (((!$axis) || ($axis === $this->_axisYSecondary) || ($axis === 'y_sec')) && ($this->_axisYSecondary != null)) { - $this->_axisYSecondary->hide(); - } - } - - /** - * Clears/removes the axis - */ - function clearAxis() - { - $this->_axisX = $this->_axisY = $this->_axisYSecondary = null; - } - - /** - * Get axis. - * - * Possible values are IMAGE_GRAPH_AXIS_X, IMAGE_GRAPH_AXIS_Y, - * IMAGE_GRAPH_AXIS_Y_SECONDARY or a short hand notation using - * string identifiers: 'x', 'y', 'ysec' - * - * @param int $axis The axis to return - * @return Image_Graph_Axis The axis - */ - function &getAxis($axis = IMAGE_GRAPH_AXIS_X) - { - switch ($axis) { - case IMAGE_GRAPH_AXIS_X: - case 'x': - return $this->_axisX; - - case IMAGE_GRAPH_AXIS_Y: - case 'y': - return $this->_axisY; - - case IMAGE_GRAPH_AXIS_Y_SECONDARY: - case 'ysec': - return $this->_axisYSecondary; - - } - return null; - } - - /** - * Update coordinates - * - * @access private - */ - function _updateCoords() - { - if (is_array($this->_elements)) { - $keys = array_keys($this->_elements); - foreach ($keys as $key) { - $element =& $this->_elements[$key]; - if (is_a($element, 'Image_Graph_Plot')) { - if (((is_a($element, 'Image_Graph_Plot_Bar')) || - (is_a($element, 'Image_Graph_Plot_Step')) || - (is_a($element, 'Image_Graph_Plot_Dot')) || - (is_a($element, 'Image_Graph_Plot_CandleStick')) || - (is_a($element, 'Image_Graph_Plot_BoxWhisker')) || - (is_a($element, 'Image_Graph_Plot_Impulse'))) && - ($this->_axisX != null)) - { - $this->_axisX->_pushValues(); - } - $this->_setExtrema($element); - } - } - unset($keys); - } - - $this->_calcEdges(); - - $pctWidth = (int) ($this->width() * 0.05); - $pctHeight = (int) ($this->height() * 0.05); - - $left = $this->_left + $this->_padding; - $top = $this->_top + $this->_padding; - $right = $this->_right - $this->_padding; - $bottom = $this->_bottom - $this->_padding; - - // temporary place holder for axis point calculations - $axisPoints['x'] = array($left, $top, $right, $bottom); - $axisPoints['y'] = $axisPoints['x']; - $axisPoints['y2'] = $axisPoints['x']; - - if ($this->_axisX !== null) { - $intersectX = $this->_axisX->_getAxisIntersection(); - $sizeX = $this->_axisX->_size(); - $this->_axisX->_setCoords($left, $top, $right, $bottom); - $this->_axisX->_updateCoords(); - } - - if ($this->_axisY !== null) { - $intersectY = $this->_axisY->_getAxisIntersection(); - $sizeY = $this->_axisY->_size(); - $this->_axisY->_setCoords($left, $top, $right, $bottom); - $this->_axisY->_updateCoords(); - } - - if ($this->_axisYSecondary !== null) { - $intersectYsec = $this->_axisYSecondary->_getAxisIntersection(); - $sizeYsec = $this->_axisYSecondary->_size(); - $this->_axisYSecondary->_setCoords($left, $top, $right, $bottom); - $this->_axisYSecondary->_updateCoords(); - } - - $axisCoordAdd = array('left' => 0, 'right' => 0, 'top' => 0, 'bottom' => 0); - - if ($this->_axisY != null) { - if ($this->_axisX != null) { - $pos = $this->_axisX->_intersectPoint($intersectY['value']); - } else { - $pos = ($this->_horizontal ? $bottom : $left); - } - - if ($this->_horizontal) { - if (($pos + $sizeY) > $bottom) { - $axisCoordAdd['bottom'] = ($pos + $sizeY) - $bottom; - // the y-axis position needs to be recalculated! - } else { - // top & bottom may need to be adjusted when the x-axis has been - // calculated! - $this->_axisY->_setCoords( - $left, - $pos, - $right, - $pos + $sizeY - ); - $this->_axisY->_updateCoords(); - } - } - else { - if (($pos - $sizeY) < $left) { - $axisCoordAdd['left'] = $left - ($pos - $sizeY); - // the y-axis position needs to be recalculated! - } else { - // top & bottom may need to be adjusted when the x-axis has been - // calculated! - $this->_axisY->_setCoords( - $pos - $sizeY, - $top, - $pos, - $bottom - ); - $this->_axisY->_updateCoords(); - } - } - } - - if ($this->_axisYSecondary != null) { - if ($this->_axisX != null) { - $pos = $this->_axisX->_intersectPoint($intersectYsec['value']); - } else { - $pos = ($this->_horizontal ? $top : $right); - } - - if ($this->_horizontal) { - if (($pos - $sizeYsec) < $top) { - $axisCoordAdd['top'] = $top - ($pos - $sizeYsec); - // the secondary y-axis position need to be recalculated - } else { - // top & bottom may need to be adjusted when the x-axis has been - // calculated! - $this->_axisYSecondary->_setCoords( - $left, - $pos - $sizeY, - $right, - $pos - ); - $this->_axisYSecondary->_updateCoords(); - } - } - else { - if (($pos + $sizeYsec) > $right) { - $axisCoordAdd['right'] = ($pos + $sizeYsec) - $right; - // the secondary y-axis position need to be recalculated - } else { - // top & bottom may need to be adjusted when the x-axis has been - // calculated! - $this->_axisYSecondary->_setCoords( - $pos, - $top, - $pos + $sizeY, - $bottom - ); - $this->_axisYSecondary->_updateCoords(); - } - } - } - - if ($this->_axisX != null) { - if (($intersectX['axis'] == IMAGE_GRAPH_AXIS_Y_SECONDARY) && - ($this->_axisYSecondary !== null) - ) { - $axis =& $this->_axisYSecondary; - } elseif ($this->_axisY !== null) { - $axis =& $this->_axisY; - } else { - $axis = false; - } - - if ($axis !== false) { - $pos = $axis->_intersectPoint($intersectX['value']); - } else { - $pos = ($this->_horizontal ? $left : $bottom); - } - - if ($this->_horizontal) { - if (($pos - $sizeX) < $left) { - $axisCoordAdd['left'] = $left - ($pos - $sizeX); - $pos = $left + $sizeX; - } - - $this->_axisX->_setCoords( - $pos - $sizeX, - $top + $axisCoordAdd['top'], - $pos, - $bottom - $axisCoordAdd['bottom'] - ); - $this->_axisX->_updateCoords(); - } - else { - if (($pos + $sizeX) > $bottom) { - $axisCoordAdd['bottom'] = ($pos + $sizeX) - $bottom; - $pos = $bottom - $sizeX; - } - - $this->_axisX->_setCoords( - $left + $axisCoordAdd['left'], - $pos, - $right - $axisCoordAdd['right'], - $pos + $sizeX - ); - $this->_axisX->_updateCoords(); - } - } - - if ($this->_horizontal) { - if (($this->_axisX !== null) && - (($axisCoordAdd['top'] != 0) || - ($axisCoordAdd['bottom'] != 0)) - ) { - // readjust y-axis for better estimate of position - if ($this->_axisY !== null) { - $pos = $this->_axisX->_intersectPoint($intersectY['value']); - $this->_axisY->_setCoords( - false, - $pos, - false, - $pos + $sizeY - ); - $this->_axisY->_updateCoords(); - } - - if ($this->_axisYSecondary !== null) { - $pos = $this->_axisX->_intersectPoint($intersectYsec['value']); - $this->_axisYSecondary->_setCoords( - false, - $pos - $sizeYsec, - false, - $pos - ); - $this->_axisYSecondary->_updateCoords(); - } - } - - // adjust top and bottom of y-axis - if ($this->_axisY !== null) { - $this->_axisY->_setCoords( - $left + $axisCoordAdd['left'], - false, - $right - $axisCoordAdd['right'], - false - ); - $this->_axisY->_updateCoords(); - } - - // adjust top and bottom of y-axis - if ($this->_axisYSecondary !== null) { - $this->_axisYSecondary->_setCoords( - $left + $axisCoordAdd['left'], - false, - $right - $axisCoordAdd['right'], - false - ); - $this->_axisYSecondary->_updateCoords(); - } - - if ($this->_axisX !== null) { - $this->_plotTop = $this->_axisX->_top; - $this->_plotBottom = $this->_axisX->_bottom; - } else { - $this->_plotTop = $top; - $this->_plotBottom = $bottom; - } - - if ($this->_axisY !== null) { - $this->_plotLeft = $this->_axisY->_left; - $this->_plotRight = $this->_axisY->_right; - } elseif ($this->_axisYSecondary !== null) { - $this->_plotLeft = $this->_axisYSecondary->_left; - $this->_plotRight = $this->_axisYSecondary->_right; - } else { - $this->_plotLeft = $this->_left; - $this->_plotRight = $this->_right; - } - } - else { - if (($this->_axisX !== null) && - (($axisCoordAdd['left'] != 0) || - ($axisCoordAdd['right'] != 0)) - ) { - // readjust y-axis for better estimate of position - if ($this->_axisY !== null) { - $pos = $this->_axisX->_intersectPoint($intersectY['value']); - $this->_axisY->_setCoords( - $pos - $sizeY, - false, - $pos, - false - ); - $this->_axisY->_updateCoords(); - } - - if ($this->_axisYSecondary !== null) { - $pos = $this->_axisX->_intersectPoint($intersectYsec['value']); - $this->_axisYSecondary->_setCoords( - $pos, - false, - $pos + $sizeYsec, - false - ); - $this->_axisYSecondary->_updateCoords(); - } - } - - // adjust top and bottom of y-axis - if ($this->_axisY !== null) { - $this->_axisY->_setCoords( - false, - $top + $axisCoordAdd['top'], - false, - $bottom - $axisCoordAdd['bottom'] - ); - $this->_axisY->_updateCoords(); - } - - // adjust top and bottom of y-axis - if ($this->_axisYSecondary !== null) { - $this->_axisYSecondary->_setCoords( - false, - $top + $axisCoordAdd['top'], - false, - $bottom - $axisCoordAdd['bottom'] - ); - $this->_axisYSecondary->_updateCoords(); - } - - if ($this->_axisX !== null) { - $this->_plotLeft = $this->_axisX->_left; - $this->_plotRight = $this->_axisX->_right; - } else { - $this->_plotLeft = $left; - $this->_plotRight = $right; - } - - if ($this->_axisY !== null) { - $this->_plotTop = $this->_axisY->_top; - $this->_plotBottom = $this->_axisY->_bottom; - } elseif ($this->_axisYSecondary !== null) { - $this->_plotTop = $this->_axisYSecondary->_top; - $this->_plotBottom = $this->_axisYSecondary->_bottom; - } else { - $this->_plotTop = $this->_top; - $this->_plotBottom = $this->_bottom; - } - } - - Image_Graph_Element::_updateCoords(); -/* - if ($this->_axisX != null) { - $this->_axisX->_updateCoords(); - } - if ($this->_axisY != null) { - $this->_axisY->_updateCoords(); - } - if ($this->_axisYSecondary != null) { - $this->_axisYSecondary->_updateCoords(); - }*/ - } - - /** - * Set the axis padding for a specified position. - * - * The axis padding is padding "inside" the plotarea (i.e. to put some space - * between the axis line and the actual plot). - * - * This can be specified in a number of ways: - * - * 1) Specify an associated array with 'left', 'top', 'right' and 'bottom' - * indices with values for the paddings. Leave out 2nd parameter. - * - * 2) Specify an overall padding as the first parameter - * - * 3) Specify the padding and position with position values as mentioned - * above - * - * Normally you'd only consider applying axis padding to a category x-axis. - * - * @param mixed $value The value/padding - * @param mixed $position The "position" of the padding - */ - function setAxisPadding($value, $position = false) - { - if ($position === false) { - if (is_array($value)) { - if ($this->_horizontal) { - if ((isset($value['top'])) && ($this->_axisX !== null)) { - $this->_axisX->_setAxisPadding('low', $value['top']); - } - if ((isset($value['bottom'])) && ($this->_axisX !== null)) { - $this->_axisX->_setAxisPadding('high', $value['bottom']); - } - if ((isset($value['left'])) && ($this->_axisY !== null)) { - $this->_axisY->_setAxisPadding('low', $value['left']); - } - if ((isset($value['right'])) && ($this->_axisY !== null)) { - $this->_axisY->_setAxisPadding('high', $value['right']); - } - if ((isset($value['left'])) && ($this->_axisYSecondary !== null)) { - $this->_axisYSecondary->_setAxisPadding('low', $value['left']); - } - if ((isset($value['right'])) && ($this->_axisYSecondary !== null)) { - $this->_axisYSecondary->_setAxisPadding('high', $value['right']); - } - } - else { - if ((isset($value['left'])) && ($this->_axisX !== null)) { - $this->_axisX->_setAxisPadding('low', $value['left']); - } - if ((isset($value['right'])) && ($this->_axisX !== null)) { - $this->_axisX->_setAxisPadding('high', $value['right']); - } - if ((isset($value['bottom'])) && ($this->_axisY !== null)) { - $this->_axisY->_setAxisPadding('low', $value['bottom']); - } - if ((isset($value['top'])) && ($this->_axisY !== null)) { - $this->_axisY->_setAxisPadding('high', $value['top']); - } - if ((isset($value['bottom'])) && ($this->_axisYSecondary !== null)) { - $this->_axisYSecondary->_setAxisPadding('low', $value['bottom']); - } - if ((isset($value['top'])) && ($this->_axisYSecondary !== null)) { - $this->_axisYSecondary->_setAxisPadding('high', $value['top']); - } - } - } else { - if ($this->_axisX !== null) { - $this->_axisX->_setAxisPadding('low', $value); - $this->_axisX->_setAxisPadding('high', $value); - } - if ($this->_axisY !== null) { - $this->_axisY->_setAxisPadding('low', $value); - $this->_axisY->_setAxisPadding('high', $value); - } - if ($this->_axisYSecondary !== null) { - $this->_axisYSecondary->_setAxisPadding('low', $value); - $this->_axisYSecondary->_setAxisPadding('high', $value); - } - } - } else { - switch ($position) { - case 'left': - if ($this->_horizontal) { - if ($this->_axisY !== null) { - $this->_axisY->_setAxisPadding('low', $value); - } - if ($this->_axisYSecondary !== null) { - $this->_axisYSecondary->_setAxisPadding('low', $value); - } - } - else if ($this->_axisX !== null) { - $this->_axisX->_setAxisPadding('low', $value); - } - break; - - case 'right': - if ($this->_horizontal) { - if ($this->_axisY !== null) { - $this->_axisY->_setAxisPadding('high', $value); - } - if ($this->_axisYSecondary !== null) { - $this->_axisYSecondary->_setAxisPadding('high', $value); - } - } - else if ($this->_axisX !== null) { - $this->_axisX->_setAxisPadding('high', $value); - } - break; - - case 'top': - if (!$this->_horizontal) { - if ($this->_axisY !== null) { - $this->_axisY->_setAxisPadding('high', $value); - } - if ($this->_axisYSecondary !== null) { - $this->_axisYSecondary->_setAxisPadding('high', $value); - } - } - else if ($this->_axisX !== null) { - $this->_axisX->_setAxisPadding('high', $value); - } - break; - - case 'bottom': - if (!$this->_horizontal) { - if ($this->_axisY !== null) { - $this->_axisY->_setAxisPadding('low', $value); - } - if ($this->_axisYSecondary !== null) { - $this->_axisYSecondary->_setAxisPadding('low', $value); - } - } - else if ($this->_axisX !== null) { - $this->_axisX->_setAxisPadding('low', $value); - } - break; - } - } - } - - /** - * Output the plotarea to the canvas - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if ($this->_hasData) { - $this->_canvas->startGroup(get_class($this)); - - if ($this->_axisX != null) { - $this->add($this->_axisX); - } - if ($this->_axisY != null) { - $this->add($this->_axisY); - } - if ($this->_axisYSecondary != null) { - $this->add($this->_axisYSecondary); - } - - $this->_getFillStyle(); - $this->_canvas->rectangle( - array( - 'x0' => $this->_plotLeft, - 'y0' => $this->_plotTop, - 'x1' => $this->_plotRight, - 'y1' => $this->_plotBottom - ) - ); - $result = parent::_done(); - $this->_canvas->endGroup(); - return $result; - } else { - // no data -> do nothing at all! - return true; - } - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Plotarea.php,v 1.23 2006/02/28 22:48:07 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Layout.php + */ +require_once 'Image/Graph/Layout.php'; + +/** + * Plot area used for drawing plots. + * + * The plotarea consists of an x-axis and an y-axis, the plotarea can plot multiple + * charts within one plotares, by simply adding them (the axis' will scale to the + * plots automatically). A graph can consist of more plotareas + * + * @category Images + * @package Image_Graph + * @subpackage Plotarea + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Plotarea extends Image_Graph_Layout +{ + + /** + * The left most pixel of the 'real' plot area on the canvas + * @var int + * @access private + */ + var $_plotLeft = 0; + + /** + * The top most pixel of the 'real' plot area on the canvas + * @var int + * @access private + */ + var $_plotTop = 0; + + /** + * The right most pixel of the 'real' plot area on the canvas + * @var int + * @access private + */ + var $_plotRight = 0; + + /** + * The bottom most pixel of the 'real' plot area on the canvas + * @var int + * @access private + */ + var $_plotBottom = 0; + + /** + * The X axis + * @var Axis + * @access private + */ + var $_axisX = null; + + /** + * The Y axis + * @var Axis + * @access private + */ + var $_axisY = null; + + /** + * The secondary Y axis + * @var Axis + * @access private + */ + var $_axisYSecondary = null; + + /** + * The border style of the 'real' plot area + * @var LineStyle + * @access private + */ + var $_plotBorderStyle = null; + + /** + * Does any plot have any data? + * @var bool + * @access private + */ + var $_hasData = false; + + /** + * Is the plotarea horizontal? + * @var bool + * @access private + */ + var $_horizontal = false; + + /** + * Image_Graph_Plotarea [Constructor] + * + * @param string $axisX The class of the X axis (if omitted a std. axis is created) + * @param string $axisY The class of the Y axis (if omitted a std. axis is created) + * @param string $direction The direction of the plotarea - 'horizontal' or 'vertical' (default) + */ + function Image_Graph_Plotarea($axisX = 'Image_Graph_Axis_Category', $axisY = 'Image_Graph_Axis', $direction = 'vertical') + { + parent::Image_Graph_Layout(); + + $this->_padding = array('left' => 5, 'top' => 5, 'right' => 5, 'bottom' => 5);; + + include_once 'Image/Graph.php'; + + $this->_axisX =& Image_Graph::factory($axisX, IMAGE_GRAPH_AXIS_X); + $this->_axisX->_setParent($this); + + $this->_axisY =& Image_Graph::factory($axisY, IMAGE_GRAPH_AXIS_Y); + $this->_axisY->_setParent($this); + $this->_axisY->_setMinimum(0); + + $this->_fillStyle = false; + + if ($direction == 'horizontal') { + $this->_horizontal = true; + $this->_axisX->_transpose = true; + $this->_axisY->_transpose = true; + } + } + + /** + * Sets the parent. The parent chain should ultimately be a GraPHP object + * + * @see Image_Graph_Common + * @param Image_Graph_Common $parent The parent + * @access private + */ + function _setParent(& $parent) + { + parent::_setParent($parent); + if ($this->_axisX !== null) { + $this->_axisX->_setParent($this); + } + if ($this->_axisY !== null) { + $this->_axisY->_setParent($this); + } + if ($this->_axisYSecondary !== null) { + $this->_axisYSecondary->_setParent($this); + } + } + + /** + * Sets the plot border line style of the element. + * + * @param Image_Graph_Line $lineStyle The line style of the border + * @deprecated 0.3.0dev2 - 2004-12-16 + */ + function setPlotBorderStyle(& $plotBorderStyle) + { + } + + /** + * Adds an element to the plotarea + * + * @param Image_Graph_Element $element The element to add + * @param int $axis The axis to associate the element with, either + * IMAGE_GRAPH_AXIS_X, IMAGE_GRAPH_AXIS_Y, IMAGE_GRAPH_AXIS_Y_SECONDARY + * or the shorter string notations 'x', 'y' or 'ysec' (defaults to + * IMAGE_GRAPH_AXIS_Y) + * @return Image_Graph_Element The added element + * @see Image_Graph_Common::add() + */ + function &add(& $element, $axis = IMAGE_GRAPH_AXIS_Y) + { + if ($axis == 'x') { + $axis = IMAGE_GRAPH_AXIS_X; + } + if ($axis == 'y') { + $axis = IMAGE_GRAPH_AXIS_Y; + } + if ($axis == 'ysec') { + $axis = IMAGE_GRAPH_AXIS_Y_SECONDARY; + } + if (($axis == IMAGE_GRAPH_AXIS_Y_SECONDARY) && + ($this->_axisYSecondary == null)) + { + $this->_axisYSecondary =& Image_Graph::factory('axis', IMAGE_GRAPH_AXIS_Y_SECONDARY); + $this->_axisYSecondary->_setMinimum(0); + if ($this->_horizontal) { + $this->_axisYSecondary->_transpose = true; + } + } + + parent::add($element); + + if (is_a($element, 'Image_Graph_Plot')) { + $element->_setAxisY($axis); + // postpone extrema calculation until we calculate coordinates + //$this->_setExtrema($element); + } elseif (is_a($element, 'Image_Graph_Grid')) { + switch ($axis) { + case IMAGE_GRAPH_AXIS_X: + if ($this->_axisX != null) { + $element->_setPrimaryAxis($this->_axisX); + if ($this->_axisY != null) { + $element->_setSecondaryAxis($this->_axisY); + } + } + break; + case IMAGE_GRAPH_AXIS_Y: + if ($this->_axisY != null) { + $element->_setPrimaryAxis($this->_axisY); + if ($this->_axisX != null) { + $element->_setSecondaryAxis($this->_axisX); + } + } + break; + case IMAGE_GRAPH_AXIS_Y_SECONDARY: + if ($this->_axisYSecondary != null) { + $element->_setPrimaryAxis($this->_axisYSecondary); + if ($this->_axisX != null) { + $element->_setSecondaryAxis($this->_axisX); + } + } + break; + } + } elseif (is_a($element, 'Image_Graph_Axis')) { + switch ($element->_type) { + case IMAGE_GRAPH_AXIS_X: + $this->_axisX =& $element; + break; + + case IMAGE_GRAPH_AXIS_Y: + $this->_axisY =& $element; + break; + + case IMAGE_GRAPH_AXIS_Y_SECONDARY: + $this->_axisYSecondary =& $element; + break; + + } + if ($element->_getMinimum() == $element->_getMaximum()) { + $element->_setMinimum(0); + $element->_setMaximum(1); + } + } + return $element; + } + + /** + * Get the width of the 'real' plotarea + * + * @return int The width of the 'real' plotarea, ie not including space occupied by padding and axis + * @access private + */ + function _plotWidth() + { + return abs($this->_plotRight - $this->_plotLeft); + } + + /** + * Get the height of the 'real' plotarea + * + * @return int The height of the 'real' plotarea, ie not including space + * occupied by padding and axis + * @access private + */ + function _plotHeight() + { + return abs($this->_plotBottom - $this->_plotTop); + } + + /** + * Set the extrema of the axis + * + * @param Image_Graph_Plot $plot The plot that 'hold' the values + * @access private + */ + function _setExtrema(& $plot) + { + if (($this->_axisX != null) && ($this->_axisX->_isNumeric())) { + $this->_axisX->_setMinimum($plot->_minimumX()); + $this->_axisX->_setMaximum($plot->_maximumX()); + } + + if (($plot->_axisY == IMAGE_GRAPH_AXIS_Y_SECONDARY) && + ($this->_axisYSecondary !== null) && + ($this->_axisYSecondary->_isNumeric())) + { + $this->_axisYSecondary->_setMinimum($plot->_minimumY()); + $this->_axisYSecondary->_setMaximum($plot->_maximumY()); + } elseif (($this->_axisY != null) && ($this->_axisY->_isNumeric())) { + $this->_axisY->_setMinimum($plot->_minimumY()); + $this->_axisY->_setMaximum($plot->_maximumY()); + } + + $datasets =& $plot->dataset(); + if (!is_array($datasets)) { + $datasets = array($datasets); + } + + $keys = array_keys($datasets); + foreach ($keys as $key) { + $dataset =& $datasets[$key]; + if ($dataset->count() > 0) { + $this->_hasData = true; + } + + if (is_a($dataset, 'Image_Graph_Dataset')) { + if (($this->_axisX != null) && (!$this->_axisX->_isNumeric())) { + $this->_axisX->_applyDataset($dataset); + } + + if (($plot->_axisY == IMAGE_GRAPH_AXIS_Y_SECONDARY) && + ($this->_axisYSecondary !== null) && + (!$this->_axisYSecondary->_isNumeric())) + { + $this->_axisYSecondary->_applyDataset($dataset); + } elseif (($this->_axisY != null) && (!$this->_axisY->_isNumeric())) { + $this->_axisY->_applyDataset($dataset); + } + } + } + unset($keys); + } + + /** + * Left boundary of the background fill area + * + * @return int Leftmost position on the canvas + * @access private + */ + function _fillLeft() + { + return $this->_plotLeft; + } + + /** + * Top boundary of the background fill area + * + * @return int Topmost position on the canvas + * @access private + */ + function _fillTop() + { + return $this->_plotTop; + } + + /** + * Right boundary of the background fill area + * + * @return int Rightmost position on the canvas + * @access private + */ + function _fillRight() + { + return $this->_plotRight; + } + + /** + * Bottom boundary of the background fill area + * + * @return int Bottommost position on the canvas + * @access private + */ + function _fillBottom() + { + return $this->_plotBottom; + } + + /** + * Get the point from the x-axis + * @param array $value The value array + * @param int $min The minimum pixel position possible + * @param int $max The maximum pixel position possible + * @return int The pixel position from the axis + * @access private + */ + function _axisPointX($value, $min, $max) + { + if (($this->_axisX == null) || (!isset($value['X']))) { + return false; + } + + if ($value['X'] === '#min#') { + return $min; + } + if ($value['X'] === '#max#') { + return $max; + } + + return $this->_axisX->_point($value['X']); + } + + /** + * Get the point from the x-axis + * @param array $value The value array + * @param int $min The minimum pixel position possible + * @param int $max The maximum pixel position possible + * @return int The pixel position from the axis + * @access private + */ + function _axisPointY($value, $min, $max) + { + if (!isset($value['Y'])) { + return false; + } + + if (($value['Y'] === '#min_pos#') || ($value['Y'] === '#max_nex#')) { + // return the minimum (bottom) position or if negative then zero + // or the maxmum (top) position or if positive then zero + if ((isset($value['AXIS_Y'])) && + ($value['AXIS_Y'] == IMAGE_GRAPH_AXIS_Y_SECONDARY) && + ($this->_axisYSecondary !== null) + ) { + $axisY =& $this->_axisYSecondary; + } else { + $axisY =& $this->_axisY; + } + if ($value['Y'] === '#min_pos#') { + return $axisY->_point(max(0, $axisY->_getMinimum())); + } else { + return $axisY->_point(min(0, $axisY->_getMaximum())); + } + } + + if ($value['Y'] === '#min#') { + return $min; + } + if ($value['Y'] === '#max#') { + return $max; + } + + if ((isset($value['AXIS_Y'])) && + ($value['AXIS_Y'] == IMAGE_GRAPH_AXIS_Y_SECONDARY) + ) { + if ($this->_axisYSecondary !== null) { + return $this->_axisYSecondary->_point($value['Y']); + } + } else { + if ($this->_axisY !== null) { + return $this->_axisY->_point($value['Y']); + } + } + return false; + } + + /** + * Get the X pixel position represented by a value + * + * @param double Value the value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointX($value) + { + if ($this->_horizontal) { + return $this->_axisPointY($value, $this->_plotLeft, $this->_plotRight); + } + else { + return $this->_axisPointX($value, $this->_plotLeft, $this->_plotRight); + } + } + + /** + * Get the Y pixel position represented by a value + * + * @param double Value the value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointY($value) + { + if ($this->_horizontal) { + return $this->_axisPointX($value, $this->_plotBottom, $this->_plotTop); + } + else { + return $this->_axisPointY($value, $this->_plotBottom, $this->_plotTop); + } + } + + /** + * Return the minimum value of the specified axis + * + * @param int $axis The axis to return the minimum value of (see {$link + * Image_Graph_Plotarea::getAxis()}) + * @return double The minimum value of the axis + * @access private + */ + function _getMinimum($axis = IMAGE_GRAPH_AXIS_Y) + { + $axis =& $this->getAxis($axis); + if ($axis !== null) { + return $axis->_getMinimum(); + } else { + return 0; + } + } + + /** + * Return the maximum value of the specified axis + * + * @param int $axis The axis to return the maximum value of(see {$link + * Image_Graph_Plotarea::getAxis()}) + * @return double The maximum value of the axis + * @access private + */ + function _getMaximum($axis = IMAGE_GRAPH_AXIS_Y) + { + $axis =& $this->getAxis($axis); + if ($axis !== null) { + return $axis->_getMaximum(); + } else { + return 0; + } + } + + /** + * Return the label distance for the specified axis. + * + * @param int $axis The axis to return the label distance for + * @return int The distance between 2 adjacent labels + * @access private + */ + function _labelDistance($axis) + { + $axis =& $this->getAxis($axis); + if ($axis !== null) { + return $axis->_labelDistance(); + } + + return false; + } + + /** + * Hides the axis + */ + function hideAxis($axis = false) + { + if (((!$axis) || ($axis === $this->_axisX) || ($axis === 'x')) && ($this->_axisX != null)) { + $this->_axisX->hide(); + } + if (((!$axis) || ($axis === $this->_axisY) || ($axis === 'y')) && ($this->_axisY != null)) { + $this->_axisY->hide(); + } + if (((!$axis) || ($axis === $this->_axisYSecondary) || ($axis === 'y_sec')) && ($this->_axisYSecondary != null)) { + $this->_axisYSecondary->hide(); + } + } + + /** + * Clears/removes the axis + */ + function clearAxis() + { + $this->_axisX = $this->_axisY = $this->_axisYSecondary = null; + } + + /** + * Get axis. + * + * Possible values are IMAGE_GRAPH_AXIS_X, IMAGE_GRAPH_AXIS_Y, + * IMAGE_GRAPH_AXIS_Y_SECONDARY or a short hand notation using + * string identifiers: 'x', 'y', 'ysec' + * + * @param int $axis The axis to return + * @return Image_Graph_Axis The axis + */ + function &getAxis($axis = IMAGE_GRAPH_AXIS_X) + { + switch ($axis) { + case IMAGE_GRAPH_AXIS_X: + case 'x': + return $this->_axisX; + + case IMAGE_GRAPH_AXIS_Y: + case 'y': + return $this->_axisY; + + case IMAGE_GRAPH_AXIS_Y_SECONDARY: + case 'ysec': + return $this->_axisYSecondary; + + } + return null; + } + + /** + * Update coordinates + * + * @access private + */ + function _updateCoords() + { + if (is_array($this->_elements)) { + $keys = array_keys($this->_elements); + foreach ($keys as $key) { + $element =& $this->_elements[$key]; + if (is_a($element, 'Image_Graph_Plot')) { + if (((is_a($element, 'Image_Graph_Plot_Bar')) || + (is_a($element, 'Image_Graph_Plot_Step')) || + (is_a($element, 'Image_Graph_Plot_Dot')) || + (is_a($element, 'Image_Graph_Plot_CandleStick')) || + (is_a($element, 'Image_Graph_Plot_BoxWhisker')) || + (is_a($element, 'Image_Graph_Plot_Impulse'))) && + ($this->_axisX != null) && + (strtolower(get_class($this->_axisX)) != 'image_graph_axis') // do not push plot if x-axis is linear + ) + { + $this->_axisX->_pushValues(); + } + $this->_setExtrema($element); + } + } + unset($keys); + } + + $this->_calcEdges(); + + $pctWidth = (int) ($this->width() * 0.05); + $pctHeight = (int) ($this->height() * 0.05); + + $left = $this->_left + $this->_padding['left']; + $top = $this->_top + $this->_padding['top']; + $right = $this->_right - $this->_padding['right']; + $bottom = $this->_bottom - $this->_padding['bottom']; + + // temporary place holder for axis point calculations + $axisPoints['x'] = array($left, $top, $right, $bottom); + $axisPoints['y'] = $axisPoints['x']; + $axisPoints['y2'] = $axisPoints['x']; + + if ($this->_axisX !== null) { + $intersectX = $this->_axisX->_getAxisIntersection(); + $sizeX = $this->_axisX->_size(); + $this->_axisX->_setCoords($left, $top, $right, $bottom); + $this->_axisX->_updateCoords(); + } + + if ($this->_axisY !== null) { + $intersectY = $this->_axisY->_getAxisIntersection(); + $sizeY = $this->_axisY->_size(); + $this->_axisY->_setCoords($left, $top, $right, $bottom); + $this->_axisY->_updateCoords(); + } + + if ($this->_axisYSecondary !== null) { + $intersectYsec = $this->_axisYSecondary->_getAxisIntersection(); + $sizeYsec = $this->_axisYSecondary->_size(); + $this->_axisYSecondary->_setCoords($left, $top, $right, $bottom); + $this->_axisYSecondary->_updateCoords(); + } + + $axisCoordAdd = array('left' => 0, 'right' => 0, 'top' => 0, 'bottom' => 0); + + if ($this->_axisY != null) { + if ($this->_axisX != null) { + $pos = $this->_axisX->_intersectPoint($intersectY['value']); + } else { + $pos = ($this->_horizontal ? $bottom : $left); + } + + if ($this->_horizontal) { + if (($pos + $sizeY) > $bottom) { + $axisCoordAdd['bottom'] = ($pos + $sizeY) - $bottom; + // the y-axis position needs to be recalculated! + } else { + // top & bottom may need to be adjusted when the x-axis has been + // calculated! + $this->_axisY->_setCoords( + $left, + $pos, + $right, + $pos + $sizeY + ); + $this->_axisY->_updateCoords(); + } + } + else { + if (($pos - $sizeY) < $left) { + $axisCoordAdd['left'] = $left - ($pos - $sizeY); + // the y-axis position needs to be recalculated! + } else { + // top & bottom may need to be adjusted when the x-axis has been + // calculated! + $this->_axisY->_setCoords( + $pos - $sizeY, + $top, + $pos, + $bottom + ); + $this->_axisY->_updateCoords(); + } + } + } + + if ($this->_axisYSecondary != null) { + if ($this->_axisX != null) { + $pos = $this->_axisX->_intersectPoint($intersectYsec['value']); + } else { + $pos = ($this->_horizontal ? $top : $right); + } + + if ($this->_horizontal) { + if (($pos - $sizeYsec) < $top) { + $axisCoordAdd['top'] = $top - ($pos - $sizeYsec); + // the secondary y-axis position need to be recalculated + } else { + // top & bottom may need to be adjusted when the x-axis has been + // calculated! + $this->_axisYSecondary->_setCoords( + $left, + $pos - $sizeY, + $right, + $pos + ); + $this->_axisYSecondary->_updateCoords(); + } + } + else { + if (($pos + $sizeYsec) > $right) { + $axisCoordAdd['right'] = ($pos + $sizeYsec) - $right; + // the secondary y-axis position need to be recalculated + } else { + // top & bottom may need to be adjusted when the x-axis has been + // calculated! + $this->_axisYSecondary->_setCoords( + $pos, + $top, + $pos + $sizeY, + $bottom + ); + $this->_axisYSecondary->_updateCoords(); + } + } + } + + if ($this->_axisX != null) { + if (($intersectX['axis'] == IMAGE_GRAPH_AXIS_Y_SECONDARY) && + ($this->_axisYSecondary !== null) + ) { + $axis =& $this->_axisYSecondary; + } elseif ($this->_axisY !== null) { + $axis =& $this->_axisY; + } else { + $axis = false; + } + + if ($axis !== false) { + $pos = $axis->_intersectPoint($intersectX['value']); + } else { + $pos = ($this->_horizontal ? $left : $bottom); + } + + if ($this->_horizontal) { + if (($pos - $sizeX) < $left) { + $axisCoordAdd['left'] = $left - ($pos - $sizeX); + $pos = $left + $sizeX; + } + + $this->_axisX->_setCoords( + $pos - $sizeX, + $top + $axisCoordAdd['top'], + $pos, + $bottom - $axisCoordAdd['bottom'] + ); + $this->_axisX->_updateCoords(); + } + else { + if (($pos + $sizeX) > $bottom) { + $axisCoordAdd['bottom'] = ($pos + $sizeX) - $bottom; + $pos = $bottom - $sizeX; + } + + $this->_axisX->_setCoords( + $left + $axisCoordAdd['left'], + $pos, + $right - $axisCoordAdd['right'], + $pos + $sizeX + ); + $this->_axisX->_updateCoords(); + } + } + + if ($this->_horizontal) { + if (($this->_axisX !== null) && + (($axisCoordAdd['top'] != 0) || + ($axisCoordAdd['bottom'] != 0)) + ) { + // readjust y-axis for better estimate of position + if ($this->_axisY !== null) { + $pos = $this->_axisX->_intersectPoint($intersectY['value']); + $this->_axisY->_setCoords( + false, + $pos, + false, + $pos + $sizeY + ); + $this->_axisY->_updateCoords(); + } + + if ($this->_axisYSecondary !== null) { + $pos = $this->_axisX->_intersectPoint($intersectYsec['value']); + $this->_axisYSecondary->_setCoords( + false, + $pos - $sizeYsec, + false, + $pos + ); + $this->_axisYSecondary->_updateCoords(); + } + } + + // adjust top and bottom of y-axis + if ($this->_axisY !== null) { + $this->_axisY->_setCoords( + $left + $axisCoordAdd['left'], + false, + $right - $axisCoordAdd['right'], + false + ); + $this->_axisY->_updateCoords(); + } + + // adjust top and bottom of y-axis + if ($this->_axisYSecondary !== null) { + $this->_axisYSecondary->_setCoords( + $left + $axisCoordAdd['left'], + false, + $right - $axisCoordAdd['right'], + false + ); + $this->_axisYSecondary->_updateCoords(); + } + + if ($this->_axisX !== null) { + $this->_plotTop = $this->_axisX->_top; + $this->_plotBottom = $this->_axisX->_bottom; + } else { + $this->_plotTop = $top; + $this->_plotBottom = $bottom; + } + + if ($this->_axisY !== null) { + $this->_plotLeft = $this->_axisY->_left; + $this->_plotRight = $this->_axisY->_right; + } elseif ($this->_axisYSecondary !== null) { + $this->_plotLeft = $this->_axisYSecondary->_left; + $this->_plotRight = $this->_axisYSecondary->_right; + } else { + $this->_plotLeft = $this->_left; + $this->_plotRight = $this->_right; + } + } + else { + if (($this->_axisX !== null) && + (($axisCoordAdd['left'] != 0) || + ($axisCoordAdd['right'] != 0)) + ) { + // readjust y-axis for better estimate of position + if ($this->_axisY !== null) { + $pos = $this->_axisX->_intersectPoint($intersectY['value']); + $this->_axisY->_setCoords( + $pos - $sizeY, + false, + $pos, + false + ); + $this->_axisY->_updateCoords(); + } + + if ($this->_axisYSecondary !== null) { + $pos = $this->_axisX->_intersectPoint($intersectYsec['value']); + $this->_axisYSecondary->_setCoords( + $pos, + false, + $pos + $sizeYsec, + false + ); + $this->_axisYSecondary->_updateCoords(); + } + } + + // adjust top and bottom of y-axis + if ($this->_axisY !== null) { + $this->_axisY->_setCoords( + false, + $top + $axisCoordAdd['top'], + false, + $bottom - $axisCoordAdd['bottom'] + ); + $this->_axisY->_updateCoords(); + } + + // adjust top and bottom of y-axis + if ($this->_axisYSecondary !== null) { + $this->_axisYSecondary->_setCoords( + false, + $top + $axisCoordAdd['top'], + false, + $bottom - $axisCoordAdd['bottom'] + ); + $this->_axisYSecondary->_updateCoords(); + } + + if ($this->_axisX !== null) { + $this->_plotLeft = $this->_axisX->_left; + $this->_plotRight = $this->_axisX->_right; + } else { + $this->_plotLeft = $left; + $this->_plotRight = $right; + } + + if ($this->_axisY !== null) { + $this->_plotTop = $this->_axisY->_top; + $this->_plotBottom = $this->_axisY->_bottom; + } elseif ($this->_axisYSecondary !== null) { + $this->_plotTop = $this->_axisYSecondary->_top; + $this->_plotBottom = $this->_axisYSecondary->_bottom; + } else { + $this->_plotTop = $this->_top; + $this->_plotBottom = $this->_bottom; + } + } + + Image_Graph_Element::_updateCoords(); +/* + if ($this->_axisX != null) { + $this->_axisX->_updateCoords(); + } + if ($this->_axisY != null) { + $this->_axisY->_updateCoords(); + } + if ($this->_axisYSecondary != null) { + $this->_axisYSecondary->_updateCoords(); + }*/ + } + + /** + * Set the axis padding for a specified position. + * + * The axis padding is padding "inside" the plotarea (i.e. to put some space + * between the axis line and the actual plot). + * + * This can be specified in a number of ways: + * + * 1) Specify an associated array with 'left', 'top', 'right' and 'bottom' + * indices with values for the paddings. Leave out 2nd parameter. + * + * 2) Specify an overall padding as the first parameter + * + * 3) Specify the padding and position with position values as mentioned + * above + * + * Normally you'd only consider applying axis padding to a category x-axis. + * + * @param mixed $value The value/padding + * @param mixed $position The "position" of the padding + */ + function setAxisPadding($value, $position = false) + { + if ($position === false) { + if (is_array($value)) { + if ($this->_horizontal) { + if ((isset($value['top'])) && ($this->_axisX !== null)) { + $this->_axisX->_setAxisPadding('low', $value['top']); + } + if ((isset($value['bottom'])) && ($this->_axisX !== null)) { + $this->_axisX->_setAxisPadding('high', $value['bottom']); + } + if ((isset($value['left'])) && ($this->_axisY !== null)) { + $this->_axisY->_setAxisPadding('low', $value['left']); + } + if ((isset($value['right'])) && ($this->_axisY !== null)) { + $this->_axisY->_setAxisPadding('high', $value['right']); + } + if ((isset($value['left'])) && ($this->_axisYSecondary !== null)) { + $this->_axisYSecondary->_setAxisPadding('low', $value['left']); + } + if ((isset($value['right'])) && ($this->_axisYSecondary !== null)) { + $this->_axisYSecondary->_setAxisPadding('high', $value['right']); + } + } + else { + if ((isset($value['left'])) && ($this->_axisX !== null)) { + $this->_axisX->_setAxisPadding('low', $value['left']); + } + if ((isset($value['right'])) && ($this->_axisX !== null)) { + $this->_axisX->_setAxisPadding('high', $value['right']); + } + if ((isset($value['bottom'])) && ($this->_axisY !== null)) { + $this->_axisY->_setAxisPadding('low', $value['bottom']); + } + if ((isset($value['top'])) && ($this->_axisY !== null)) { + $this->_axisY->_setAxisPadding('high', $value['top']); + } + if ((isset($value['bottom'])) && ($this->_axisYSecondary !== null)) { + $this->_axisYSecondary->_setAxisPadding('low', $value['bottom']); + } + if ((isset($value['top'])) && ($this->_axisYSecondary !== null)) { + $this->_axisYSecondary->_setAxisPadding('high', $value['top']); + } + } + } else { + if ($this->_axisX !== null) { + $this->_axisX->_setAxisPadding('low', $value); + $this->_axisX->_setAxisPadding('high', $value); + } + if ($this->_axisY !== null) { + $this->_axisY->_setAxisPadding('low', $value); + $this->_axisY->_setAxisPadding('high', $value); + } + if ($this->_axisYSecondary !== null) { + $this->_axisYSecondary->_setAxisPadding('low', $value); + $this->_axisYSecondary->_setAxisPadding('high', $value); + } + } + } else { + switch ($position) { + case 'left': + if ($this->_horizontal) { + if ($this->_axisY !== null) { + $this->_axisY->_setAxisPadding('low', $value); + } + if ($this->_axisYSecondary !== null) { + $this->_axisYSecondary->_setAxisPadding('low', $value); + } + } + else if ($this->_axisX !== null) { + $this->_axisX->_setAxisPadding('low', $value); + } + break; + + case 'right': + if ($this->_horizontal) { + if ($this->_axisY !== null) { + $this->_axisY->_setAxisPadding('high', $value); + } + if ($this->_axisYSecondary !== null) { + $this->_axisYSecondary->_setAxisPadding('high', $value); + } + } + else if ($this->_axisX !== null) { + $this->_axisX->_setAxisPadding('high', $value); + } + break; + + case 'top': + if (!$this->_horizontal) { + if ($this->_axisY !== null) { + $this->_axisY->_setAxisPadding('high', $value); + } + if ($this->_axisYSecondary !== null) { + $this->_axisYSecondary->_setAxisPadding('high', $value); + } + } + else if ($this->_axisX !== null) { + $this->_axisX->_setAxisPadding('high', $value); + } + break; + + case 'bottom': + if (!$this->_horizontal) { + if ($this->_axisY !== null) { + $this->_axisY->_setAxisPadding('low', $value); + } + if ($this->_axisYSecondary !== null) { + $this->_axisYSecondary->_setAxisPadding('low', $value); + } + } + else if ($this->_axisX !== null) { + $this->_axisX->_setAxisPadding('low', $value); + } + break; + } + } + } + + /** + * Output the plotarea to the canvas + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if ($this->_hasData) { + $this->_canvas->startGroup(get_class($this)); + + if ($this->_axisX != null) { + $this->add($this->_axisX); + } + if ($this->_axisY != null) { + $this->add($this->_axisY); + } + if ($this->_axisYSecondary != null) { + $this->add($this->_axisYSecondary); + } + + $this->_getFillStyle(); + $this->_canvas->rectangle( + array( + 'x0' => $this->_plotLeft, + 'y0' => $this->_plotTop, + 'x1' => $this->_plotRight, + 'y1' => $this->_plotBottom + ) + ); + $result = parent::_done(); + $this->_canvas->endGroup(); + return $result; + } else { + // no data -> do nothing at all! + return true; + } + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Plotarea/Element.php b/includes/pear/Image/Graph/Plotarea/Element.php index 4c528c69..c70d708b 100644 --- a/includes/pear/Image/Graph/Plotarea/Element.php +++ b/includes/pear/Image/Graph/Plotarea/Element.php @@ -1,87 +1,87 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Element.php,v 1.5 2005/02/21 20:50:01 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Element.php - */ -require_once 'Image/Graph/Element.php'; - -/** - * Representation of a element on a plotarea. - * - * @category Images - * @package Image_Graph - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - * @abstract - */ -class Image_Graph_Plotarea_Element extends Image_Graph_Element -{ - - /** - * Get the X pixel position represented by a value - * - * @param double $point the value to get the pixel-point for - * @return double The pixel position along the axis - * @access private - */ - function _pointX($point) - { - return $this->_parent->_pointX($point); - } - - /** - * Get the Y pixel position represented by a value - * - * @param double $point the value to get the pixel-point for - * @return double The pixel position along the axis - * @access private - */ - function _pointY($point) - { - return $this->_parent->_pointY($point); - } - - /** - * Get the X and Y pixel position represented by a value - * - * @param array $point the values to get the pixel-point for - * @return array The (x, y) pixel position along the axis - * @access private - */ - function _pointXY($point) - { - return array ('X' => $this->_pointX($point), 'Y' => $this->_pointY($point)); - } - -} + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Element.php,v 1.5 2005/02/21 20:50:01 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Element.php + */ +require_once 'Image/Graph/Element.php'; + +/** + * Representation of a element on a plotarea. + * + * @category Images + * @package Image_Graph + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + * @abstract + */ +class Image_Graph_Plotarea_Element extends Image_Graph_Element +{ + + /** + * Get the X pixel position represented by a value + * + * @param double $point the value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointX($point) + { + return $this->_parent->_pointX($point); + } + + /** + * Get the Y pixel position represented by a value + * + * @param double $point the value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointY($point) + { + return $this->_parent->_pointY($point); + } + + /** + * Get the X and Y pixel position represented by a value + * + * @param array $point the values to get the pixel-point for + * @return array The (x, y) pixel position along the axis + * @access private + */ + function _pointXY($point) + { + return array ('X' => $this->_pointX($point), 'Y' => $this->_pointY($point)); + } + +} ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Plotarea/Map.php b/includes/pear/Image/Graph/Plotarea/Map.php index eb456cf6..54e5124f 100644 --- a/includes/pear/Image/Graph/Plotarea/Map.php +++ b/includes/pear/Image/Graph/Plotarea/Map.php @@ -1,304 +1,304 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Map.php,v 1.9 2005/08/24 20:36:01 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Plotarea.php - */ -require_once 'Image/Graph/Plotarea.php'; - -/** - * Plot area used for map plots. - * - * A map plot is a chart that displays a map (fx. a world map) in the form of . - * png file. The maps must be located in the /Images/Maps folder and a - * corresponding .txt files mush also exist in this location where named - * locations are mapped to an (x, y) coordinate of the map picture (this text - * file is tab separated with 'Name' 'X' 'Y' values, fx 'Denmark 378 223'). The - * x-values in the dataset are then the named locations (fx 'Denmark') and the - * y-values are then the data to plot. Currently the best (if not only) use is - * to combine a map plot area with a {@link Image_Graph_Plot_Dot} using {@link - * Image_Graph_Marker_PercentageCircle} as marker. - * - * @category Images - * @package Image_Graph - * @subpackage Plotarea - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Plotarea_Map extends Image_Graph_Plotarea -{ - - /** - * The GD image for the map - * @var string - * @access private - */ - var $_imageMap; - - /** - * The value for scaling the width and height to fit into the layout boundaries - * @var int - * @access private - */ - var $_scale; - - /** - * The (x,y)-points for the named point - * @var array - * @access private - */ - var $_mapPoints; - - /** - * The original size of the image map - * @var array - * @access private - */ - var $_mapSize; - - /** - * PlotareaMap [Constructor] - * - * @param string $map The name of the map, i.e. the [name].png and [name]. - * txt files located in the Images/maps folder - */ - function Image_Graph_Plotarea_Map($map) - { - parent::Image_Graph_Plotarea(); - - $this->_imageMap = dirname(__FILE__)."/../Images/Maps/$map.png"; - $points = file(dirname(__FILE__)."/../Images/Maps/$map.txt"); - list($width, $height) = getimagesize($this->_imageMap); - $this->_mapSize['X'] = $width; - $this->_mapSize['Y'] = $height; - - if (is_array($points)) { - unset($this->_mapPoints); - foreach ($points as $line) { - list($country, $x, $y) = explode("\t", $line); - $this->_mapPoints[$country] = array('X' => $x, 'Y' => $y); - } - } - } - - /** - * Left boundary of the background fill area - * - * @return int Leftmost position on the canvas - * @access private - */ - function _fillLeft() - { - return $this->_left + $this->_padding; - } - - /** - * Top boundary of the background fill area - * - * @return int Topmost position on the canvas - * @access private - */ - function _fillTop() - { - return $this->_top + $this->_padding; - } - - /** - * Right boundary of the background fill area - * - * @return int Rightmost position on the canvas - * @access private - */ - function _fillRight() - { - return $this->_right - $this->_padding; - } - - /** - * Bottom boundary of the background fill area - * - * @return int Bottommost position on the canvas - * @access private - */ - function _fillBottom() - { - return $this->_bottom - $this->_padding; - } - - /** - * Set the extrema of the axis - * - * @param Image_Graph_Plot $plot The plot that 'hold' the values - * @access private - */ - function _setExtrema(& $plot) - { - } - - /** - * Get the X pixel position represented by a value - * - * @param double $value The value to get the pixel-point for - * @return double The pixel position along the axis - * @access private - */ - function _pointX($value) - { - $country = $value['X']; - return $this->_plotLeft+$this->_mapPoints[$country]['X']*$this->_scale; - } - - /** - * Get the Y pixel position represented by a value - * - * @param double $value The value to get the pixel-point for - * @return double The pixel position along the axis - * @access private - */ - function _pointY($value) - { - $country = $value['X']; - return $this->_plotTop+$this->_mapPoints[$country]['Y']*$this->_scale; - } - - /** - * Hides the axis - */ - function hideAxis() - { - } - - /** - * Add a point to the maps - * - * @param int $latitude The latitude of the point - * @param int $longiude The longitude of the point - * @param string $name The name of the plot - */ - function addMappoint($latitude, $longitude, $name) - { - $x = (($longitude + 180) * ($this->_mapSize['X'] / 360)); - $y = ((($latitude * -1) + 90) * ($this->_mapSize['Y'] / 180)); - $this->_mapPoints[$name] = array('X' => $x, 'Y' => $y); - } - - /** - * Add a point to the maps - * - * @param int $x The latitude of the point - * @param int $y The longitude of the point - * @param string $name The name of the plot - */ - function addPoint($x, $y, $name) - { - $this->_mapPoints[$name] = array('X' => $x, 'Y' => $y); - } - - /** - * Update coordinates - * - * @access private - */ - function _updateCoords() - { - parent::_updateCoords(); - - $mapAspectRatio = $this->_mapSize['X']/$this->_mapSize['Y']; - $plotAspectRatio = ($width = $this->_fillWidth())/($height = $this->_fillHeight()); - - $scaleFactorX = ($mapAspectRatio > $plotAspectRatio); - - if ((($this->_mapSize['X'] <= $width) && ($this->_mapSize['Y'] <= $height)) || - (($this->_mapSize['X'] >= $width) && ($this->_mapSize['Y'] >= $height))) - { - if ($scaleFactorX) { - $this->_scale = $width / $this->_mapSize['X']; - } else { - $this->_scale = $height / $this->_mapSize['Y']; - } - } elseif ($this->_mapSize['X'] < $width) { - $this->_scale = $height / $this->_mapSize['Y']; - } elseif ($this->_mapSize['Y'] < $height) { - $this->_scale = $width / $this->_mapSize['X']; - } - - $this->_plotLeft = ($this->_fillLeft() + $this->_fillRight() - - $this->_mapSize['X']*$this->_scale)/2; - - $this->_plotTop = ($this->_fillTop() + $this->_fillBottom() - - $this->_mapSize['Y']*$this->_scale)/2; - - $this->_plotRight = ($this->_fillLeft() + $this->_fillRight() + - $this->_mapSize['X']*$this->_scale)/2; - - $this->_plotBottom = ($this->_fillTop() + $this->_fillBottom() + - $this->_mapSize['Y']*$this->_scale)/2; - } - - /** - * Output the plotarea to the canvas - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - $this->_getFillStyle(); - $this->_canvas->rectangle( - array( - 'x0' => $this->_fillLeft(), - 'y0' => $this->_fillTop(), - 'x1' => $this->_fillRight(), - 'y1' => $this->_fillBottom() - ) - ); - - $scaledWidth = $this->_mapSize['X']*$this->_scale; - $scaledHeight = $this->_mapSize['Y']*$this->_scale; - - $this->_canvas->image( - array( - 'x' => $this->_plotLeft, - 'y' => $this->_plotTop, - 'filename' => $this->_imageMap, - 'width' => $scaledWidth, - 'height' => $scaledHeight - ) - ); - - return Image_Graph_Layout::_done(); - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Map.php,v 1.10 2006/02/28 22:48:07 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plotarea.php + */ +require_once 'Image/Graph/Plotarea.php'; + +/** + * Plot area used for map plots. + * + * A map plot is a chart that displays a map (fx. a world map) in the form of . + * png file. The maps must be located in the /Images/Maps folder and a + * corresponding .txt files mush also exist in this location where named + * locations are mapped to an (x, y) coordinate of the map picture (this text + * file is tab separated with 'Name' 'X' 'Y' values, fx 'Denmark 378 223'). The + * x-values in the dataset are then the named locations (fx 'Denmark') and the + * y-values are then the data to plot. Currently the best (if not only) use is + * to combine a map plot area with a {@link Image_Graph_Plot_Dot} using {@link + * Image_Graph_Marker_PercentageCircle} as marker. + * + * @category Images + * @package Image_Graph + * @subpackage Plotarea + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Plotarea_Map extends Image_Graph_Plotarea +{ + + /** + * The GD image for the map + * @var string + * @access private + */ + var $_imageMap; + + /** + * The value for scaling the width and height to fit into the layout boundaries + * @var int + * @access private + */ + var $_scale; + + /** + * The (x,y)-points for the named point + * @var array + * @access private + */ + var $_mapPoints; + + /** + * The original size of the image map + * @var array + * @access private + */ + var $_mapSize; + + /** + * PlotareaMap [Constructor] + * + * @param string $map The name of the map, i.e. the [name].png and [name]. + * txt files located in the Images/maps folder + */ + function Image_Graph_Plotarea_Map($map) + { + parent::Image_Graph_Plotarea(); + + $this->_imageMap = dirname(__FILE__)."/../Images/Maps/$map.png"; + $points = file(dirname(__FILE__)."/../Images/Maps/$map.txt"); + list($width, $height) = getimagesize($this->_imageMap); + $this->_mapSize['X'] = $width; + $this->_mapSize['Y'] = $height; + + if (is_array($points)) { + unset($this->_mapPoints); + foreach ($points as $line) { + list($country, $x, $y) = explode("\t", $line); + $this->_mapPoints[$country] = array('X' => $x, 'Y' => $y); + } + } + } + + /** + * Left boundary of the background fill area + * + * @return int Leftmost position on the canvas + * @access private + */ + function _fillLeft() + { + return $this->_left + $this->_padding['left']; + } + + /** + * Top boundary of the background fill area + * + * @return int Topmost position on the canvas + * @access private + */ + function _fillTop() + { + return $this->_top + $this->_padding['top']; + } + + /** + * Right boundary of the background fill area + * + * @return int Rightmost position on the canvas + * @access private + */ + function _fillRight() + { + return $this->_right - $this->_padding['right']; + } + + /** + * Bottom boundary of the background fill area + * + * @return int Bottommost position on the canvas + * @access private + */ + function _fillBottom() + { + return $this->_bottom - $this->_padding['bottom']; + } + + /** + * Set the extrema of the axis + * + * @param Image_Graph_Plot $plot The plot that 'hold' the values + * @access private + */ + function _setExtrema(& $plot) + { + } + + /** + * Get the X pixel position represented by a value + * + * @param double $value The value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointX($value) + { + $country = $value['X']; + return $this->_plotLeft+$this->_mapPoints[$country]['X']*$this->_scale; + } + + /** + * Get the Y pixel position represented by a value + * + * @param double $value The value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointY($value) + { + $country = $value['X']; + return $this->_plotTop+$this->_mapPoints[$country]['Y']*$this->_scale; + } + + /** + * Hides the axis + */ + function hideAxis() + { + } + + /** + * Add a point to the maps + * + * @param int $latitude The latitude of the point + * @param int $longiude The longitude of the point + * @param string $name The name of the plot + */ + function addMappoint($latitude, $longitude, $name) + { + $x = (($longitude + 180) * ($this->_mapSize['X'] / 360)); + $y = ((($latitude * -1) + 90) * ($this->_mapSize['Y'] / 180)); + $this->_mapPoints[$name] = array('X' => $x, 'Y' => $y); + } + + /** + * Add a point to the maps + * + * @param int $x The latitude of the point + * @param int $y The longitude of the point + * @param string $name The name of the plot + */ + function addPoint($x, $y, $name) + { + $this->_mapPoints[$name] = array('X' => $x, 'Y' => $y); + } + + /** + * Update coordinates + * + * @access private + */ + function _updateCoords() + { + parent::_updateCoords(); + + $mapAspectRatio = $this->_mapSize['X']/$this->_mapSize['Y']; + $plotAspectRatio = ($width = $this->_fillWidth())/($height = $this->_fillHeight()); + + $scaleFactorX = ($mapAspectRatio > $plotAspectRatio); + + if ((($this->_mapSize['X'] <= $width) && ($this->_mapSize['Y'] <= $height)) || + (($this->_mapSize['X'] >= $width) && ($this->_mapSize['Y'] >= $height))) + { + if ($scaleFactorX) { + $this->_scale = $width / $this->_mapSize['X']; + } else { + $this->_scale = $height / $this->_mapSize['Y']; + } + } elseif ($this->_mapSize['X'] < $width) { + $this->_scale = $height / $this->_mapSize['Y']; + } elseif ($this->_mapSize['Y'] < $height) { + $this->_scale = $width / $this->_mapSize['X']; + } + + $this->_plotLeft = ($this->_fillLeft() + $this->_fillRight() - + $this->_mapSize['X']*$this->_scale)/2; + + $this->_plotTop = ($this->_fillTop() + $this->_fillBottom() - + $this->_mapSize['Y']*$this->_scale)/2; + + $this->_plotRight = ($this->_fillLeft() + $this->_fillRight() + + $this->_mapSize['X']*$this->_scale)/2; + + $this->_plotBottom = ($this->_fillTop() + $this->_fillBottom() + + $this->_mapSize['Y']*$this->_scale)/2; + } + + /** + * Output the plotarea to the canvas + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + $this->_getFillStyle(); + $this->_canvas->rectangle( + array( + 'x0' => $this->_fillLeft(), + 'y0' => $this->_fillTop(), + 'x1' => $this->_fillRight(), + 'y1' => $this->_fillBottom() + ) + ); + + $scaledWidth = $this->_mapSize['X']*$this->_scale; + $scaledHeight = $this->_mapSize['Y']*$this->_scale; + + $this->_canvas->image( + array( + 'x' => $this->_plotLeft, + 'y' => $this->_plotTop, + 'filename' => $this->_imageMap, + 'width' => $scaledWidth, + 'height' => $scaledHeight + ) + ); + + return Image_Graph_Layout::_done(); + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Plotarea/Radar.php b/includes/pear/Image/Graph/Plotarea/Radar.php index 8ceab265..296f5e6d 100644 --- a/includes/pear/Image/Graph/Plotarea/Radar.php +++ b/includes/pear/Image/Graph/Plotarea/Radar.php @@ -1,243 +1,243 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Radar.php,v 1.7 2005/08/24 20:36:02 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Plotarea.php - */ -require_once 'Image/Graph/Plotarea.php'; - -/** - * Plot area used for radar plots. - * - * @category Images - * @package Image_Graph - * @subpackage Plotarea - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Plotarea_Radar extends Image_Graph_Plotarea -{ - - /** - * Create the plotarea, implicitely creates 2 normal axis - */ - function Image_Graph_Plotarea_Radar() - { - parent::Image_Graph_Element(); - $this->_padding = 10; - $this->_axisX =& Image_Graph::factory('Image_Graph_Axis_Radar'); - $this->_axisX->_setParent($this); - $this->_axisY =& Image_Graph::factory('Image_Graph_Axis', IMAGE_GRAPH_AXIS_Y); - $this->_axisY->_setParent($this); - $this->_axisY->_setMinimum(0); - } - - /** - * Get the width of the 'real' plotarea - * - * @return int The width of the 'real' plotarea, ie not including space occupied by padding and axis - * @access private - */ - function _plotWidth() - { - return (min($this->height(), $this->width())) * 0.80; - } - - /** - * Get the height of the 'real' plotarea - * - * @return int The height of the 'real' plotarea, ie not including space occupied by padding and axis - * @access private - */ - function _plotHeight() - { - return (min($this->height(), $this->width())) * 0.80; - } - - /** - * Left boundary of the background fill area - * - * @return int Leftmost position on the canvas - * @access private - */ - function _fillLeft() - { - return (int) (($this->_left + $this->_right - $this->_plotWidth()) / 2); - } - - /** - * Top boundary of the background fill area - * - * @return int Topmost position on the canvas - * @access private - */ - function _fillTop() - { - return (int) (($this->_top + $this->_bottom - $this->_plotHeight()) / 2); - } - - /** - * Right boundary of the background fill area - * - * @return int Rightmost position on the canvas - * @access private - */ - function _fillRight() - { - return (int) (($this->_left + $this->_right + $this->_plotWidth()) / 2); - } - - /** - * Bottom boundary of the background fill area - * - * @return int Bottommost position on the canvas - * @access private - */ - function _fillBottom() - { - return (int) (($this->_top + $this->_bottom + $this->_plotHeight()) / 2); - } - - /** - * Get the X pixel position represented by a value - * - * @param double $value The value to get the pixel-point for - * @return double The pixel position along the axis - * @access private - */ - function _pointX($value) - { - if (is_array($value)) { - if ($value['Y'] == '#min#') { - $radius = 0; - } elseif (($value['Y'] == '#max#') || ($value['Y'] === false)) { - $radius = 1; - } else { - $radius = ($value['Y'] - $this->_axisY->_getMinimum()) / - ($this->_axisY->_getMaximum() - $this->_axisY->_getMinimum()); - } - $x = ($this->_left + $this->_right) / 2 - - $radius * ($this->_plotWidth() / 2) * - cos(deg2rad($this->_axisX->_point($value['X']))); - } - return max($this->_plotLeft, min($this->_plotRight, $x)); - } - - /** - * Get the Y pixel position represented by a value - * - * @param double $value The value to get the pixel-point for - * @return double The pixel position along the axis - * @access private - */ - function _pointY($value) - { - if (is_array($value)) { - if ($value['Y'] == '#min#') { - $radius = 0; - } elseif (($value['Y'] == '#max#') || ($value['Y'] === false)) { - $radius = 1; - } else { - $radius = ($value['Y'] - $this->_axisY->_getMinimum()) / - ($this->_axisY->_getMaximum() - $this->_axisY->_getMinimum()); - } - - $y = ($this->_top + $this->_bottom) / 2 - - $radius * ($this->_plotHeight() / 2) * - sin(deg2rad($this->_axisX->_point($value['X']))); - } - return max($this->_plotTop, min($this->_plotBottom, $y)); - } - - /** - * Update coordinates - * - * @access private - */ - function _updateCoords() - { - if (is_array($this->_elements)) { - $keys = array_keys($this->_elements); - foreach ($keys as $key) { - $element =& $this->_elements[$key]; - if (is_a($element, 'Image_Graph_Plot')) { - $this->_setExtrema($element); - } - } - unset($keys); - } - - $this->_calcEdges(); - - $centerX = (int) (($this->_left + $this->_right) / 2); - $centerY = (int) (($this->_top + $this->_bottom) / 2); - $radius = min($this->_plotHeight(), $this->_plotWidth()) / 2; - - if (is_object($this->_axisX)) { - $this->_axisX->_setCoords( - $centerX - $radius, - $centerY - $radius, - $centerX + $radius, - $centerY + $radius - ); - } - - if (is_object($this->_axisY)) { - $this->_axisY->_setCoords( - $centerX, - $centerY, - $centerX - $radius, - $centerY - $radius - ); - } - - $this->_plotLeft = $this->_fillLeft(); - $this->_plotTop = $this->_fillTop(); - $this->_plotRight = $this->_fillRight(); - $this->_plotBottom = $this->_fillBottom(); - - Image_Graph_Element::_updateCoords(); - - if (is_object($this->_axisX)) { - $this->_axisX->_updateCoords(); - } - - if (is_object($this->_axisY)) { - $this->_axisY->_updateCoords(); - } - - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Radar.php,v 1.8 2006/02/28 22:48:07 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Plotarea.php + */ +require_once 'Image/Graph/Plotarea.php'; + +/** + * Plot area used for radar plots. + * + * @category Images + * @package Image_Graph + * @subpackage Plotarea + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Plotarea_Radar extends Image_Graph_Plotarea +{ + + /** + * Create the plotarea, implicitely creates 2 normal axis + */ + function Image_Graph_Plotarea_Radar() + { + parent::Image_Graph_Element(); + $this->_padding = array('left' => 10, 'top' => 10, 'right' => 10, 'bottom' => 10); + $this->_axisX =& Image_Graph::factory('Image_Graph_Axis_Radar'); + $this->_axisX->_setParent($this); + $this->_axisY =& Image_Graph::factory('Image_Graph_Axis', IMAGE_GRAPH_AXIS_Y); + $this->_axisY->_setParent($this); + $this->_axisY->_setMinimum(0); + } + + /** + * Get the width of the 'real' plotarea + * + * @return int The width of the 'real' plotarea, ie not including space occupied by padding and axis + * @access private + */ + function _plotWidth() + { + return (min($this->height(), $this->width())) * 0.80; + } + + /** + * Get the height of the 'real' plotarea + * + * @return int The height of the 'real' plotarea, ie not including space occupied by padding and axis + * @access private + */ + function _plotHeight() + { + return (min($this->height(), $this->width())) * 0.80; + } + + /** + * Left boundary of the background fill area + * + * @return int Leftmost position on the canvas + * @access private + */ + function _fillLeft() + { + return (int) (($this->_left + $this->_right - $this->_plotWidth()) / 2); + } + + /** + * Top boundary of the background fill area + * + * @return int Topmost position on the canvas + * @access private + */ + function _fillTop() + { + return (int) (($this->_top + $this->_bottom - $this->_plotHeight()) / 2); + } + + /** + * Right boundary of the background fill area + * + * @return int Rightmost position on the canvas + * @access private + */ + function _fillRight() + { + return (int) (($this->_left + $this->_right + $this->_plotWidth()) / 2); + } + + /** + * Bottom boundary of the background fill area + * + * @return int Bottommost position on the canvas + * @access private + */ + function _fillBottom() + { + return (int) (($this->_top + $this->_bottom + $this->_plotHeight()) / 2); + } + + /** + * Get the X pixel position represented by a value + * + * @param double $value The value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointX($value) + { + if (is_array($value)) { + if ($value['Y'] == '#min#') { + $radius = 0; + } elseif (($value['Y'] == '#max#') || ($value['Y'] === false)) { + $radius = 1; + } else { + $radius = ($value['Y'] - $this->_axisY->_getMinimum()) / + ($this->_axisY->_getMaximum() - $this->_axisY->_getMinimum()); + } + $x = ($this->_left + $this->_right) / 2 - + $radius * ($this->_plotWidth() / 2) * + cos(deg2rad($this->_axisX->_point($value['X']))); + } + return max($this->_plotLeft, min($this->_plotRight, $x)); + } + + /** + * Get the Y pixel position represented by a value + * + * @param double $value The value to get the pixel-point for + * @return double The pixel position along the axis + * @access private + */ + function _pointY($value) + { + if (is_array($value)) { + if ($value['Y'] == '#min#') { + $radius = 0; + } elseif (($value['Y'] == '#max#') || ($value['Y'] === false)) { + $radius = 1; + } else { + $radius = ($value['Y'] - $this->_axisY->_getMinimum()) / + ($this->_axisY->_getMaximum() - $this->_axisY->_getMinimum()); + } + + $y = ($this->_top + $this->_bottom) / 2 - + $radius * ($this->_plotHeight() / 2) * + sin(deg2rad($this->_axisX->_point($value['X']))); + } + return max($this->_plotTop, min($this->_plotBottom, $y)); + } + + /** + * Update coordinates + * + * @access private + */ + function _updateCoords() + { + if (is_array($this->_elements)) { + $keys = array_keys($this->_elements); + foreach ($keys as $key) { + $element =& $this->_elements[$key]; + if (is_a($element, 'Image_Graph_Plot')) { + $this->_setExtrema($element); + } + } + unset($keys); + } + + $this->_calcEdges(); + + $centerX = (int) (($this->_left + $this->_right) / 2); + $centerY = (int) (($this->_top + $this->_bottom) / 2); + $radius = min($this->_plotHeight(), $this->_plotWidth()) / 2; + + if (is_object($this->_axisX)) { + $this->_axisX->_setCoords( + $centerX - $radius, + $centerY - $radius, + $centerX + $radius, + $centerY + $radius + ); + } + + if (is_object($this->_axisY)) { + $this->_axisY->_setCoords( + $centerX, + $centerY, + $centerX - $radius, + $centerY - $radius + ); + } + + $this->_plotLeft = $this->_fillLeft(); + $this->_plotTop = $this->_fillTop(); + $this->_plotRight = $this->_fillRight(); + $this->_plotBottom = $this->_fillBottom(); + + Image_Graph_Element::_updateCoords(); + + if (is_object($this->_axisX)) { + $this->_axisX->_updateCoords(); + } + + if (is_object($this->_axisY)) { + $this->_axisY->_updateCoords(); + } + + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Simple.php b/includes/pear/Image/Graph/Simple.php index c359f3c5..b83ec30f 100644 --- a/includes/pear/Image/Graph/Simple.php +++ b/includes/pear/Image/Graph/Simple.php @@ -1,121 +1,121 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Simple.php,v 1.8 2005/08/24 20:35:54 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph.php - */ -require_once 'Image/Graph.php'; - -/** - * Class for simple creation of graphs - * - * @category Images - * @package Image_Graph - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Simple extends Image_Graph -{ - - /** - * Image_Graph_Simple [Constructor] - * - * @param int $width The width of the graph in pixels - * @param int $height The height of the graph in pixels - */ - function Image_Graph_Simple($width, $height, $plotType, $data, $title, $lineColor = 'black', $fillColor = 'white', $font = false) - { - parent::Image_Graph($width, $height); - - $plotarea =& Image_Graph::factory('plotarea'); - - $dataset =& Image_Graph::factory('dataset', array($data)); - - if ($font === false) { - $font =& Image_Graph::factory('Image_Graph_Font'); - } elseif (is_string($font)) { - $font =& Image_Graph::factory('ttf_font', $font); - $font->setSize(8); - } - - $this->setFont($font); - - $this->add( - Image_Graph::vertical( - Image_Graph::factory('title', - array( - $title, - array('size_rel' => 2) - ) - ), - $plotarea, - 10 - ) - ); - - $plotarea->addNew('line_grid', array(), IMAGE_GRAPH_AXIS_Y); - - $plot =& $plotarea->addNew($plotType, array(&$dataset)); - $plot->setLineColor($lineColor); - $plot->setFillColor($fillColor); - - $axisX =& $plotarea->getAxis(IMAGE_GRAPH_AXIS_X); - $axisX->showLabel( - IMAGE_GRAPH_LABEL_MINIMUM + - IMAGE_GRAPH_LABEL_ZERO + - IMAGE_GRAPH_LABEL_MAXIMUM - ); - - } - - /** - * Factory method to create the Image_Simple_Graph object. - */ - function &factory($width, $height, $plotType, $data, $title, $lineColor = 'black', $fillColor = 'white', $font = false) - { - $obj =& Image_Graph::factory('Image_Graph_Simple', - array( - $width, - $height, - $plotType, - $data, - $title, - $lineColor, - $fillColor, - $font - ) - ); - return $obj; - } - -} + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Simple.php,v 1.8 2005/08/24 20:35:54 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph.php + */ +require_once 'Image/Graph.php'; + +/** + * Class for simple creation of graphs + * + * @category Images + * @package Image_Graph + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Simple extends Image_Graph +{ + + /** + * Image_Graph_Simple [Constructor] + * + * @param int $width The width of the graph in pixels + * @param int $height The height of the graph in pixels + */ + function Image_Graph_Simple($width, $height, $plotType, $data, $title, $lineColor = 'black', $fillColor = 'white', $font = false) + { + parent::Image_Graph($width, $height); + + $plotarea =& Image_Graph::factory('plotarea'); + + $dataset =& Image_Graph::factory('dataset', array($data)); + + if ($font === false) { + $font =& Image_Graph::factory('Image_Graph_Font'); + } elseif (is_string($font)) { + $font =& Image_Graph::factory('ttf_font', $font); + $font->setSize(8); + } + + $this->setFont($font); + + $this->add( + Image_Graph::vertical( + Image_Graph::factory('title', + array( + $title, + array('size_rel' => 2) + ) + ), + $plotarea, + 10 + ) + ); + + $plotarea->addNew('line_grid', array(), IMAGE_GRAPH_AXIS_Y); + + $plot =& $plotarea->addNew($plotType, array(&$dataset)); + $plot->setLineColor($lineColor); + $plot->setFillColor($fillColor); + + $axisX =& $plotarea->getAxis(IMAGE_GRAPH_AXIS_X); + $axisX->showLabel( + IMAGE_GRAPH_LABEL_MINIMUM + + IMAGE_GRAPH_LABEL_ZERO + + IMAGE_GRAPH_LABEL_MAXIMUM + ); + + } + + /** + * Factory method to create the Image_Simple_Graph object. + */ + function &factory($width, $height, $plotType, $data, $title, $lineColor = 'black', $fillColor = 'white', $font = false) + { + $obj =& Image_Graph::factory('Image_Graph_Simple', + array( + $width, + $height, + $plotType, + $data, + $title, + $lineColor, + $fillColor, + $font + ) + ); + return $obj; + } + +} ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Title.php b/includes/pear/Image/Graph/Title.php index 10907b57..619dab45 100644 --- a/includes/pear/Image/Graph/Title.php +++ b/includes/pear/Image/Graph/Title.php @@ -1,194 +1,194 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Title.php,v 1.12 2005/08/24 20:35:56 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * Include file Image/Graph/Layout.php - */ -require_once 'Image/Graph/Layout.php'; - -/** - * Title - * - * @category Images - * @package Image_Graph - * @subpackage Text - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Title extends Image_Graph_Layout -{ - - /** - * The text to print - * @var string - * @access private - */ - var $_text; - - /** - * The font to use - * @var Font - * @access private - */ - var $_font; - - /** - * The alignment of the title - * @var int - * @access private - */ - var $_alignment = IMAGE_GRAPH_ALIGN_CENTER_X; - - /** - * Create the title. - * - * Pass a Image_Graph_Font object - preferably by-ref (&) as second - * parameter, the font size in pixels or an associated array with some or - * all of the followin keys: - * - * 'size' The size of the title - * - * 'angle' The angle at which to write the title (in degrees or 'vertical') - * - * 'color' The font-face color - * - * @param sting $text The text to represent the title - * @param mixed $fontOptions The font to use in the title - */ - function Image_Graph_Title($text, $fontOptions = false) - { - parent::Image_Graph_Layout(); - if (is_object($fontOptions)) { - $this->_font =& $fontOptions; - } else { - if (is_array($fontOptions)) { - $this->_fontOptions = $fontOptions; - } else { - $this->_fontOptions['size'] = $fontOptions; - } - } - $this->setText($text); - } - - /** - * Set the text - * - * @param string $text The text to display - */ - function setText($text) - { - $this->_text = $text; - } - - /** - * Returns the calculated "auto" size - * - * @return int The calculated auto size - * @access private - */ - function _getAutoSize() - { - if ($this->_defaultFontOptions !== false) { - $this->_canvas->setFont($this->_defaultFontOptions); - } else { - $this->_canvas->setFont($this->_getFont()); - } - - return $this->_canvas->textHeight($this->_text); - } - - /** - * Set the alignment of the legend - * - * @param int $alignment The alignment - */ - function setAlignment($alignment) - { - $this->_alignment = $alignment & 0x7; - } - - /** - * Output the text - * - * @return bool Was the output 'good' (true) or 'bad' (false). - * @access private - */ - function _done() - { - if ($this->_defaultFontOptions !== false) { - $this->_canvas->setFont($this->_defaultFontOptions); - } else { - $this->_canvas->setFont($this->_getFont()); - } - - if (is_a($this->_parent, 'Image_Graph_Plotarea')) { - $this->_setCoords( - $this->_parent->_left, - $this->_parent->_top, - $this->_parent->_right, - $this->_parent->_top + $this->_canvas->textHeight($this->_text) - ); - } elseif (!is_a($this->_parent, 'Image_Graph_Layout')) { - $this->_setCoords( - $this->_parent->_fillLeft(), - $this->_parent->_fillTop(), - $this->_parent->_fillRight(), - $this->_parent->_fillTop() + $this->_canvas->textHeight($this->_text) - ); - } - - if (parent::_done() === false) { - return false; - } - - if ($this->_alignment == IMAGE_GRAPH_ALIGN_CENTER_X) { - $x = ($this->_left + $this->_right) / 2; - } elseif ($this->_alignment == IMAGE_GRAPH_ALIGN_LEFT) { - $x = $this->_left; - } else { - $x = $this->_right; - } - $y = ($this->_top + $this->_bottom) / 2; - - $this->write( - $x, - $y, - $this->_text, - $this->_alignment + IMAGE_GRAPH_ALIGN_CENTER_Y - ); - return true; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Title.php,v 1.12 2005/08/24 20:35:56 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * Include file Image/Graph/Layout.php + */ +require_once 'Image/Graph/Layout.php'; + +/** + * Title + * + * @category Images + * @package Image_Graph + * @subpackage Text + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Title extends Image_Graph_Layout +{ + + /** + * The text to print + * @var string + * @access private + */ + var $_text; + + /** + * The font to use + * @var Font + * @access private + */ + var $_font; + + /** + * The alignment of the title + * @var int + * @access private + */ + var $_alignment = IMAGE_GRAPH_ALIGN_CENTER_X; + + /** + * Create the title. + * + * Pass a Image_Graph_Font object - preferably by-ref (&) as second + * parameter, the font size in pixels or an associated array with some or + * all of the followin keys: + * + * 'size' The size of the title + * + * 'angle' The angle at which to write the title (in degrees or 'vertical') + * + * 'color' The font-face color + * + * @param sting $text The text to represent the title + * @param mixed $fontOptions The font to use in the title + */ + function Image_Graph_Title($text, $fontOptions = false) + { + parent::Image_Graph_Layout(); + if (is_object($fontOptions)) { + $this->_font =& $fontOptions; + } else { + if (is_array($fontOptions)) { + $this->_fontOptions = $fontOptions; + } else { + $this->_fontOptions['size'] = $fontOptions; + } + } + $this->setText($text); + } + + /** + * Set the text + * + * @param string $text The text to display + */ + function setText($text) + { + $this->_text = $text; + } + + /** + * Returns the calculated "auto" size + * + * @return int The calculated auto size + * @access private + */ + function _getAutoSize() + { + if ($this->_defaultFontOptions !== false) { + $this->_canvas->setFont($this->_defaultFontOptions); + } else { + $this->_canvas->setFont($this->_getFont()); + } + + return $this->_canvas->textHeight($this->_text); + } + + /** + * Set the alignment of the legend + * + * @param int $alignment The alignment + */ + function setAlignment($alignment) + { + $this->_alignment = $alignment & 0x7; + } + + /** + * Output the text + * + * @return bool Was the output 'good' (true) or 'bad' (false). + * @access private + */ + function _done() + { + if ($this->_defaultFontOptions !== false) { + $this->_canvas->setFont($this->_defaultFontOptions); + } else { + $this->_canvas->setFont($this->_getFont()); + } + + if (is_a($this->_parent, 'Image_Graph_Plotarea')) { + $this->_setCoords( + $this->_parent->_left, + $this->_parent->_top, + $this->_parent->_right, + $this->_parent->_top + $this->_canvas->textHeight($this->_text) + ); + } elseif (!is_a($this->_parent, 'Image_Graph_Layout')) { + $this->_setCoords( + $this->_parent->_fillLeft(), + $this->_parent->_fillTop(), + $this->_parent->_fillRight(), + $this->_parent->_fillTop() + $this->_canvas->textHeight($this->_text) + ); + } + + if (parent::_done() === false) { + return false; + } + + if ($this->_alignment == IMAGE_GRAPH_ALIGN_CENTER_X) { + $x = ($this->_left + $this->_right) / 2; + } elseif ($this->_alignment == IMAGE_GRAPH_ALIGN_LEFT) { + $x = $this->_left; + } else { + $x = $this->_right; + } + $y = ($this->_top + $this->_bottom) / 2; + + $this->write( + $x, + $y, + $this->_text, + $this->_alignment + IMAGE_GRAPH_ALIGN_CENTER_Y + ); + return true; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/Graph/Tool.php b/includes/pear/Image/Graph/Tool.php index fa296b3a..e9fd424a 100644 --- a/includes/pear/Image/Graph/Tool.php +++ b/includes/pear/Image/Graph/Tool.php @@ -1,291 +1,291 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: Tool.php,v 1.4 2005/09/14 20:27:24 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -/** - * This class contains a set of tool-functions. - * - * These functions are all to be called statically - * - * @category Images - * @package Image_Graph - * @author Jesper Veggerby - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version Release: @package_version@ - * @link http://pear.php.net/package/Image_Graph - */ -class Image_Graph_Tool -{ - - /** - * Return the average of 2 points - * - * @param double P1 1st point - * @param double P2 2nd point - * @return double The average of P1 and P2 - * @static - */ - function mid($p1, $p2) - { - return ($p1 + $p2) / 2; - } - - /** - * Mirrors P1 in P2 by a amount of Factor - * - * @param double $p1 1st point, point to mirror - * @param double $o2 2nd point, mirror point - * @param double $factor Mirror factor, 0 returns $p2, 1 returns a pure - * mirror, ie $p1 on the exact other side of $p2 - * @return double $p1 mirrored in $p2 by Factor - * @static - */ - function mirror($p1, $p2, $factor = 1) - { - return $p2 + $factor * ($p2 - $p1); - } - - /** - * Calculates a Bezier control point, this function must be called for BOTH - * X and Y coordinates (will it work for 3D coordinates!?) - * - * @param double $p1 1st point - * @param double $p2 Point to - * @param double $factor Mirror factor, 0 returns P2, 1 returns a pure - * mirror, i.e. P1 on the exact other side of P2 - * @return double P1 mirrored in P2 by Factor - * @static - */ - function controlPoint($p1, $p2, $factor, $smoothFactor = 0.75) - { - $sa = Image_Graph_Tool::mirror($p1, $p2, $smoothFactor); - $sb = Image_Graph_Tool::mid($p2, $sa); - - $m = Image_Graph_Tool::mid($p2, $factor); - - $pC = Image_Graph_Tool::mid($sb, $m); - - return $pC; - } - - /** - * Calculates a Bezier point, this function must be called for BOTH X and Y - * coordinates (will it work for 3D coordinates!?) - * - * @param double $t A position between $p2 and $p3, value between 0 and 1 - * @param double $p1 Point to use for calculating control points - * @param double $p2 Point 1 to calculate bezier curve between - * @param double $p3 Point 2 to calculate bezier curve between - * @param double $p4 Point to use for calculating control points - * @return double The bezier value of the point t between $p2 and $p3 using - * $p1 and $p4 to calculate control points - * @static - */ - function bezier($t, $p1, $p2, $p3, $p4) - { - // (1-t)^3*p1 + 3*(1-t)^2*t*p2 + 3*(1-t)*t^2*p3 + t^3*p4 - return pow(1 - $t, 3) * $p1 + - 3 * pow(1 - $t, 2) * $t * $p2 + - 3 * (1 - $t) * pow($t, 2) * $p3 + - pow($t, 3) * $p4; - } - - /** - * For a given point (x,y) return a point rotated by a given angle aroung the center (xy,yc) - * - * @param int $x x coordinate of the point to rotate - * @param int $y y coordinate of the point to rotate - * @param int $xc x coordinate of the center of the rotation - * @param int $yc y coordinate of the center of the rotation - * @param int $angle angle of the rotation - * @return array the coordinate of the new point - * @static - */ - function rotate($x, $y, $xc, $yc, $angle) - { - $cos = cos(deg2rad($angle)); - $sin = sin(deg2rad($angle)); - $xr= $x - $xc; - $yr= $y - $yc; - $x1= $xc + $cos * $xr - $sin * $yr; - $y1= $yc + $sin * $xr + $cos * $yr; - return array((int) $x1,(int) $y1); - } - - /** - * If a number is close 0 zero (i.e. 0 within $decimal decimals) it is rounded down to zero - * - * @param double $value The value to round - * @param int $decimal The number of decimals - * @return double The value or zero if "close enough" to zero - * @static - */ - function close2zero($value, $decimal) - { - if (abs($value) < pow(10, -$decimal)) { - return 0; - } - else { - return $value; - } - } - - /** - * Calculate the dimensions and center point (of gravity) for an arc - * - * @param int $v1 The angle at which the arc starts - * @param int $v2 The angle at which the arc ends - * @return array An array with the dimensions in a fraction of a circle width radius 1 'rx', 'ry' and the - * center point of gravity ('cx', 'cy') - * @static - */ - function calculateArcDimensionAndCenter($v1, $v2) - { - // $v2 always larger than $v1 - $r1x = Image_Graph_Tool::close2zero(cos(deg2rad($v1)), 3); - $r2x = Image_Graph_Tool::close2zero(cos(deg2rad($v2)), 3); - - $r1y = Image_Graph_Tool::close2zero(sin(deg2rad($v1)), 3); - $r2y = Image_Graph_Tool::close2zero(sin(deg2rad($v2)), 3); - - // $rx = how many percent of the x-diameter of the entire ellipse does the arc x-diameter occupy: 1 entire width, 0 no width - // $cx = at what percentage of the diameter does the center lie - - // if the arc passes through 0/360 degrees the "highest" of r1x and r2x is replaced by 1! - if ((($v1 <= 0) && ($v2 >= 0)) || (($v1 <= 360) && ($v2 >= 360))) { - $r1x = min($r1x, $r2x); - $r2x = 1; - } - - // if the arc passes through 180 degrees the "lowest" of r1x and r2x is replaced by -1! - if ((($v1 <= 180) && ($v2 >= 180)) || (($v1 <= 540) && ($v2 >= 540))) { - $r1x = max($r1x, $r2x); - $r2x = -1; - } - - if ($r1x >= 0) { // start between [270; 360] or [0; 90] - if ($r2x >= 0) { - $rx = max($r1x, $r2x) / 2; - $cx = 0; // center lies 0 percent along this "vector" - } - else { - $rx = abs($r1x - $r2x) / 2; - $cx = abs($r2x / 2) / $rx; - } - } - else { // start between ]90; 270[ - if ($r2x < 0) { - $rx = max(abs($r1x), abs($r2x)) / 2; - $cx = $rx; - } - else { - $rx = abs($r1x - $r2x) / 2; - $cx = abs($r1x / 2) / $rx; - } - } - - // $ry = how many percent of the y-diameter of the entire ellipse does the arc y-diameter occupy: 1 entire, 0 none - // $cy = at what percentage of the y-diameter does the center lie - - // if the arc passes through 90 degrees the "lowest" of r1x and r2x is replaced by -1! - if ((($v1 <= 90) && ($v2 >= 90)) || (($v1 <= 450) && ($v2 >= 450))) { - $r1y = min($r1y, $r2y); - $r2y = 1; - } - - // if the arc passes through 270 degrees the "highest" of r1y and r2y is replaced by -1! - if ((($v1 <= 270) && ($v2 >= 270)) || (($v1 <= 630) && ($v2 >= 630))) { - $r1y = max($r1y, $r2y); - $r2y = -1; - } - - if ($r1y >= 0) { // start between [0; 180] - if ($r2y >= 0) { - $ry = max($r1y, $r2y) / 2; - $cy = 0; // center lies 0 percent along this "vector" - } - else { - $ry = abs($r1y - $r2y) / 2; - $cy = abs($r2y / 2) / $ry; - } - } - else { // start between ]180; 360[ - if ($r2y < 0) { - $ry = max(abs($r1y), abs($r2y)) / 2; - $cy = $ry; - } - else { - $ry = abs($r1y - $r2y) / 2; - $cy = abs($r1y / 2) / $ry; - } - } - - return array( - 'rx' => $rx, - 'cx' => $cx, - 'ry' => $ry, - 'cy' => $cy - ); - } - - /** - * Calculate linear regression on a dataset - * @param array $data The data to calculate regression upon - * @return array The slope and intersection of the "best-fit" line - * @static - */ - function calculateLinearRegression(&$data) - { - $sumX = 0; - $sumY = 0; - foreach ($data as $point) { - $sumX += $point['X']; - $sumY += $point['Y']; - } - $meanX = $sumX / count($data); - $meanY = $sumY / count($data); - - $sumXX = 0; - $sumYY = 0; - $sumXY = 0; - foreach ($data as $point) { - $sumXX += ($point['X'] - $meanX) * ($point['X'] - $meanX); - $sumYY += ($point['Y'] - $meanY) * ($point['Y'] - $meanY); - $sumXY += ($point['X'] - $meanX) * ($point['Y'] - $meanY); - } - - $result = array(); - $result['slope'] = ($sumXY / $sumXX); - $result['intersection'] = $meanY - ($result['slope'] * $meanX); - return $result; - } - -} - + + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Tool.php,v 1.4 2005/09/14 20:27:24 nosey Exp $ + * @link http://pear.php.net/package/Image_Graph + */ + +/** + * This class contains a set of tool-functions. + * + * These functions are all to be called statically + * + * @category Images + * @package Image_Graph + * @author Jesper Veggerby + * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version Release: @package_version@ + * @link http://pear.php.net/package/Image_Graph + */ +class Image_Graph_Tool +{ + + /** + * Return the average of 2 points + * + * @param double P1 1st point + * @param double P2 2nd point + * @return double The average of P1 and P2 + * @static + */ + function mid($p1, $p2) + { + return ($p1 + $p2) / 2; + } + + /** + * Mirrors P1 in P2 by a amount of Factor + * + * @param double $p1 1st point, point to mirror + * @param double $o2 2nd point, mirror point + * @param double $factor Mirror factor, 0 returns $p2, 1 returns a pure + * mirror, ie $p1 on the exact other side of $p2 + * @return double $p1 mirrored in $p2 by Factor + * @static + */ + function mirror($p1, $p2, $factor = 1) + { + return $p2 + $factor * ($p2 - $p1); + } + + /** + * Calculates a Bezier control point, this function must be called for BOTH + * X and Y coordinates (will it work for 3D coordinates!?) + * + * @param double $p1 1st point + * @param double $p2 Point to + * @param double $factor Mirror factor, 0 returns P2, 1 returns a pure + * mirror, i.e. P1 on the exact other side of P2 + * @return double P1 mirrored in P2 by Factor + * @static + */ + function controlPoint($p1, $p2, $factor, $smoothFactor = 0.75) + { + $sa = Image_Graph_Tool::mirror($p1, $p2, $smoothFactor); + $sb = Image_Graph_Tool::mid($p2, $sa); + + $m = Image_Graph_Tool::mid($p2, $factor); + + $pC = Image_Graph_Tool::mid($sb, $m); + + return $pC; + } + + /** + * Calculates a Bezier point, this function must be called for BOTH X and Y + * coordinates (will it work for 3D coordinates!?) + * + * @param double $t A position between $p2 and $p3, value between 0 and 1 + * @param double $p1 Point to use for calculating control points + * @param double $p2 Point 1 to calculate bezier curve between + * @param double $p3 Point 2 to calculate bezier curve between + * @param double $p4 Point to use for calculating control points + * @return double The bezier value of the point t between $p2 and $p3 using + * $p1 and $p4 to calculate control points + * @static + */ + function bezier($t, $p1, $p2, $p3, $p4) + { + // (1-t)^3*p1 + 3*(1-t)^2*t*p2 + 3*(1-t)*t^2*p3 + t^3*p4 + return pow(1 - $t, 3) * $p1 + + 3 * pow(1 - $t, 2) * $t * $p2 + + 3 * (1 - $t) * pow($t, 2) * $p3 + + pow($t, 3) * $p4; + } + + /** + * For a given point (x,y) return a point rotated by a given angle aroung the center (xy,yc) + * + * @param int $x x coordinate of the point to rotate + * @param int $y y coordinate of the point to rotate + * @param int $xc x coordinate of the center of the rotation + * @param int $yc y coordinate of the center of the rotation + * @param int $angle angle of the rotation + * @return array the coordinate of the new point + * @static + */ + function rotate($x, $y, $xc, $yc, $angle) + { + $cos = cos(deg2rad($angle)); + $sin = sin(deg2rad($angle)); + $xr= $x - $xc; + $yr= $y - $yc; + $x1= $xc + $cos * $xr - $sin * $yr; + $y1= $yc + $sin * $xr + $cos * $yr; + return array((int) $x1,(int) $y1); + } + + /** + * If a number is close 0 zero (i.e. 0 within $decimal decimals) it is rounded down to zero + * + * @param double $value The value to round + * @param int $decimal The number of decimals + * @return double The value or zero if "close enough" to zero + * @static + */ + function close2zero($value, $decimal) + { + if (abs($value) < pow(10, -$decimal)) { + return 0; + } + else { + return $value; + } + } + + /** + * Calculate the dimensions and center point (of gravity) for an arc + * + * @param int $v1 The angle at which the arc starts + * @param int $v2 The angle at which the arc ends + * @return array An array with the dimensions in a fraction of a circle width radius 1 'rx', 'ry' and the + * center point of gravity ('cx', 'cy') + * @static + */ + function calculateArcDimensionAndCenter($v1, $v2) + { + // $v2 always larger than $v1 + $r1x = Image_Graph_Tool::close2zero(cos(deg2rad($v1)), 3); + $r2x = Image_Graph_Tool::close2zero(cos(deg2rad($v2)), 3); + + $r1y = Image_Graph_Tool::close2zero(sin(deg2rad($v1)), 3); + $r2y = Image_Graph_Tool::close2zero(sin(deg2rad($v2)), 3); + + // $rx = how many percent of the x-diameter of the entire ellipse does the arc x-diameter occupy: 1 entire width, 0 no width + // $cx = at what percentage of the diameter does the center lie + + // if the arc passes through 0/360 degrees the "highest" of r1x and r2x is replaced by 1! + if ((($v1 <= 0) && ($v2 >= 0)) || (($v1 <= 360) && ($v2 >= 360))) { + $r1x = min($r1x, $r2x); + $r2x = 1; + } + + // if the arc passes through 180 degrees the "lowest" of r1x and r2x is replaced by -1! + if ((($v1 <= 180) && ($v2 >= 180)) || (($v1 <= 540) && ($v2 >= 540))) { + $r1x = max($r1x, $r2x); + $r2x = -1; + } + + if ($r1x >= 0) { // start between [270; 360] or [0; 90] + if ($r2x >= 0) { + $rx = max($r1x, $r2x) / 2; + $cx = 0; // center lies 0 percent along this "vector" + } + else { + $rx = abs($r1x - $r2x) / 2; + $cx = abs($r2x / 2) / $rx; + } + } + else { // start between ]90; 270[ + if ($r2x < 0) { + $rx = max(abs($r1x), abs($r2x)) / 2; + $cx = $rx; + } + else { + $rx = abs($r1x - $r2x) / 2; + $cx = abs($r1x / 2) / $rx; + } + } + + // $ry = how many percent of the y-diameter of the entire ellipse does the arc y-diameter occupy: 1 entire, 0 none + // $cy = at what percentage of the y-diameter does the center lie + + // if the arc passes through 90 degrees the "lowest" of r1x and r2x is replaced by -1! + if ((($v1 <= 90) && ($v2 >= 90)) || (($v1 <= 450) && ($v2 >= 450))) { + $r1y = min($r1y, $r2y); + $r2y = 1; + } + + // if the arc passes through 270 degrees the "highest" of r1y and r2y is replaced by -1! + if ((($v1 <= 270) && ($v2 >= 270)) || (($v1 <= 630) && ($v2 >= 630))) { + $r1y = max($r1y, $r2y); + $r2y = -1; + } + + if ($r1y >= 0) { // start between [0; 180] + if ($r2y >= 0) { + $ry = max($r1y, $r2y) / 2; + $cy = 0; // center lies 0 percent along this "vector" + } + else { + $ry = abs($r1y - $r2y) / 2; + $cy = abs($r2y / 2) / $ry; + } + } + else { // start between ]180; 360[ + if ($r2y < 0) { + $ry = max(abs($r1y), abs($r2y)) / 2; + $cy = $ry; + } + else { + $ry = abs($r1y - $r2y) / 2; + $cy = abs($r1y / 2) / $ry; + } + } + + return array( + 'rx' => $rx, + 'cx' => $cx, + 'ry' => $ry, + 'cy' => $cy + ); + } + + /** + * Calculate linear regression on a dataset + * @param array $data The data to calculate regression upon + * @return array The slope and intersection of the "best-fit" line + * @static + */ + function calculateLinearRegression(&$data) + { + $sumX = 0; + $sumY = 0; + foreach ($data as $point) { + $sumX += $point['X']; + $sumY += $point['Y']; + } + $meanX = $sumX / count($data); + $meanY = $sumY / count($data); + + $sumXX = 0; + $sumYY = 0; + $sumXY = 0; + foreach ($data as $point) { + $sumXX += ($point['X'] - $meanX) * ($point['X'] - $meanX); + $sumYY += ($point['Y'] - $meanY) * ($point['Y'] - $meanY); + $sumXY += ($point['X'] - $meanX) * ($point['Y'] - $meanY); + } + + $result = array(); + $result['slope'] = ($sumXY / $sumXX); + $result['intersection'] = $meanY - ($result['slope'] * $meanX); + return $result; + } + +} + ?> \ No newline at end of file diff --git a/includes/pear/Image/docs/ChangeLog b/includes/pear/Image/docs/ChangeLog deleted file mode 100644 index 061a8061..00000000 --- a/includes/pear/Image/docs/ChangeLog +++ /dev/null @@ -1,48 +0,0 @@ -************************** - Image_Canvas - Changelog -************************** -Version 0.2.4 [2005-Nov-08] - Jesper Veggerby - * Fixed a bug causing in Image_Canvas_SVG causing grouping to give a "Missing argument..." error (this rendered Image_Graph using SVG broken) - * Fixed a bug causing rectangles not being displayed, if points were given in the wrong order - -Version 0.2.3 [2005-Oct-28] - Jesper Veggerby - * Fixed Bug #5786 "Error in producing SVG" - * Fixed Bug #5805 "Canvas\Fonts\fontmap.txt is missing" - -Version 0.2.2 [2005-Sep-30] - Jesper Veggerby - * Added 'border' and 'cssclass' option to Image_Canvas_GD::toHtml() - * Added image support when using SVG (using embedded base64 encoding) - * Added link ("imagemap") support with SVG - * Made image loading in GD canvas use getimagesize() to determine type instead of relying on extension - * Fixed bug where 'htmltags' were not transferred to image mapping of polygon vertices - * Fixed bug in SVG where pie slices with some specific angles curled the wrong way - * Fixed bug in Image_Canvas_ImageMap::show() and Image_Canvas_ImageMap::save() calling non-existing method _toHtml() - * Fixed bug in Image_Canvas_SVG::polygon() not showing polygon if last point was a spline - addSpline() - * Fixed bug causing line ends not to show if color not exlicitly defined - * Fixed Bug #5066 "Reference Notices" (from Image_Graph) - * Fixed bug #5175 "Unable to define IMAGE_GRAPH_SYSTEM_FONT_PATH outside of Config.php" - * Fixed Bug #5325 "Image/Color.php compatibility with old PHP versions" - -Version 0.2.1 [2005-Aug-08] - Jesper Veggerby - * Added Request #4997 "HTML attributes and JS actions in imagemaps" - using 'htmltags' entry - * Fixed bug with fonts, now it's not required for the font to have a name - * Changed examples to use require_once instead of include/require - -Version 0.2.0 [2005-Aug-01] - Jesper Veggerby - * First released package in PEAR - * Added support for image maps - a separate canvas (Image_Canvas_ImageMap) has been created to accomplish this - * Added support for antialiasing images when using GD (both using native GD method and Image_Graph own implementation) - * Added support for multi line texts - * Added a toHtml() method for to easy facilitate including canvas in HTML (this includes the associated image map, if any) - * Added line ends - only supported in GD canvases currently and not on polygons (yet!) - -Version 0.1.2 [2005-Jul-21] - Jesper Veggerby - * Changed write() to addText() - * Split done() into show() and save() - * Changed all methods with more than 1 parameter to use hashed array as parameters - -Version 0.1.1 [2005-Mar-21] - Jesper Veggerby - * Renamed package to Image_Canvas - -Version 0.1.0 [2005-Feb-14] - Jesper Veggerby - * First "stand-alone" release ("outside" Image_Graph) \ No newline at end of file diff --git a/includes/pear/Image/docs/LICENSE b/includes/pear/Image/docs/LICENSE deleted file mode 100644 index a825d02b..00000000 --- a/includes/pear/Image/docs/LICENSE +++ /dev/null @@ -1,344 +0,0 @@ - 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 \ No newline at end of file diff --git a/includes/pear/Image/docs/README b/includes/pear/Image/docs/README deleted file mode 100644 index d26d35ca..00000000 --- a/includes/pear/Image/docs/README +++ /dev/null @@ -1,41 +0,0 @@ - ******************************* - Image_Canvas - ******************************* - version 0.2.4 - - ------ CopyRight (C) Jesper Veggerby Hansen, 2003-2005 ------ - http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - -_________________________________________________________________ - - 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. -_________________________________________________________________ - -Image_Canvas - -Requirements ------------- -The only system requirement is PHP4/PHP5 support. -For GD output GD support is required with GD 2 for optimal performance. For PDF -support, PDFlib is required (planned File_PDF support when released in working -version). - -Documentation -------------- -See http://pear.veggerby.dk/Image_Canvas/docs/ for documentation - -History -------- -Release history of Image_Canvas -0.2.4 08-Nov-2005 -0.2.3 28-Oct-2005 -0.2.2 30-Sep-2005 -0.2.1 08-Aug-2005 First version used by Image_Graph -0.2.0 01-Aug-2005 First PEAR release -0.1.2 21-Jul-2005 -0.1.1 21-Mar-2005 -0.1.0 14-Feb-2005 \ No newline at end of file diff --git a/includes/pear/Image/docs/colors.txt b/includes/pear/Image/docs/colors.txt deleted file mode 100644 index e92d7cb0..00000000 --- a/includes/pear/Image/docs/colors.txt +++ /dev/null @@ -1,142 +0,0 @@ -List of supported named colors (extract from Image/Color.php) - -aliceblue -antiquewhite -aqua -aquamarine -azure -beige -bisque -black -blanchedalmond -blue -blueviolet -brown -burlywood -cadetblue -chartreuse -chocolate -coral -cornflowerblue -cornsilk -crimson -cyan -darkblue -darkcyan -darkgoldenrod -darkgray -darkgreen -darkkhaki -darkmagenta -darkolivegreen -darkorange -darkorchid -darkred -darksalmon -darkseagreen -darkslateblue -darkslategray -darkturquoise -darkviolet -deeppink -deepskyblue -dimgray -dodgerblue -firebrick -floralwhite -forestgreen -fuchsia -gainsboro -ghostwhite -gold -goldenrod -gray -green -greenyellow -honeydew -hotpink -indianred -indigo -ivory -khaki -lavender -lavenderblush -lawngreen -lemonchiffon -lightblue -lightcoral -lightcyan -lightgoldenrodyellow -lightgreen -lightgrey -lightpink -lightsalmon -lightseagreen -lightskyblue -lightslategray -lightsteelblue -lightyellow -lime -limegreen -linen -magenta -maroon -mediumaquamarine -mediumblue -mediumorchid -mediumpurple -mediumseagreen -mediumslateblue -mediumspringgreen -mediumturquoise -mediumvioletred -midnightblue -mintcream -mistyrose -moccasin -navajowhite -navy -oldlace -olive -olivedrab -orange -orangered -orchid -palegoldenrod -palegreen -paleturquoise -palevioletred -papayawhip -peachpuff -peru -pink -plum -powderblue -purple -red -rosybrown -royalblue -saddlebrown -salmon -sandybrown -seagreen -seashell -sienna -silver -skyblue -slateblue -slategray -snow -springgreen -steelblue -tan -teal -thistle -tomato -turquoise -violet -wheat -white -whitesmoke -yellow -yellowgreen \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/antialias.php b/includes/pear/Image/docs/examples/antialias.php deleted file mode 100644 index 1025d77e..00000000 --- a/includes/pear/Image/docs/examples/antialias.php +++ /dev/null @@ -1,104 +0,0 @@ - - */ - -// include libraries -require_once 'Image/Graph.php'; -require_once 'Image/Canvas.php'; - -// create a PNG canvas and enable antialiasing (canvas implementation) -$Canvas =& Image_Canvas::factory('png', array('width' => 600, 'height' => 300, 'antialias' => 'native')); - -// create the graph -$Graph =& Image_Graph::factory('graph', $Canvas); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 8 pixels -$Font->setSize(8); - -// set the font -$Graph->setFont($Font); - -// create the layout -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Antialiased Sample Chart', 12)), - Image_Graph::vertical( - Image_Graph::horizontal( - $Plotarea1 = Image_Graph::factory('plotarea'), - $Plotarea2 = Image_Graph::factory('plotarea') - ), - $Legend = Image_Graph::factory('legend'), - 80 - ), - 5 - ) -); - -// add grids -$Grid =& $Plotarea1->addNew('line_grid', IMAGE_GRAPH_AXIS_Y); -$Grid->setLineColor('silver'); -$Grid =& $Plotarea2->addNew('line_grid', IMAGE_GRAPH_AXIS_Y); -$Grid->setLineColor('silver'); - -// setup legend -$Legend->setPlotarea($Plotarea1); -$Legend->setPlotarea($Plotarea2); - -// create the dataset -$Datasets = - array( - Image_Graph::factory('random', array(10, 2, 15, true)), - Image_Graph::factory('random', array(10, 2, 15, true)), - Image_Graph::factory('random', array(10, 2, 15, true)) - ); - -// create the plot as stacked area chart using the datasets -$Plot =& $Plotarea1->addNew('Image_Graph_Plot_Area', array($Datasets, 'stacked')); - -// set names for datasets (for legend) -$Datasets[0]->setName('Jylland'); -$Datasets[1]->setName('Fyn'); -$Datasets[2]->setName('Sjælland'); - -// set line color for plot -$Plot->setLineColor('gray'); - -// create and populate the fillarray -$FillArray =& Image_Graph::factory('Image_Graph_Fill_Array'); -$FillArray->addColor('blue@0.2'); -$FillArray->addColor('yellow@0.2'); -$FillArray->addColor('green@0.2'); - -// set a fill style -$Plot->setFillStyle($FillArray); - -// add other plots -$Plot =& $Plotarea2->addNew('line', $Datasets[0]); -$Plot->setLineColor('blue@0.2'); -$Plot =& $Plotarea2->addNew('line', $Datasets[1]); -$Plot->setLineColor('yellow@0.2'); -$Plot =& $Plotarea2->addNew('line', $Datasets[2]); -$Plot->setLineColor('green@0.2'); - -// set color -$Plotarea1->setFillColor('silver@0.3'); -$Plotarea2->setFillColor('silver@0.3'); - -// output the Graph -$Graph->done(); - -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/axis_direction.php b/includes/pear/Image/docs/examples/axis_direction.php deleted file mode 100644 index e9c55a64..00000000 --- a/includes/pear/Image/docs/examples/axis_direction.php +++ /dev/null @@ -1,54 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(600, 300)); - -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(10); - -$Graph->setFont($Font); - -// setup the plotarea, legend and their layout -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Changing Axis Direction', 12)), - Image_Graph::horizontal( - $Plotarea1 = Image_Graph::factory('plotarea'), - $Plotarea2 = Image_Graph::factory('plotarea'), - 50 - ), - 5 - ) -); - -$Dataset =& Image_Graph::factory('random', array(10, 2, 15, true)); -$Plot1 =& $Plotarea1->addNew('line', array(&$Dataset)); -$Plot1->setLineColor('red'); - -$Plot2 =& $Plotarea2->addNew('line', array(&$Dataset)); -$Plot2->setLineColor('red'); - -$AxisY =& $Plotarea2->getAxis('y'); -$AxisY->setInverted(true); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/canvas.php b/includes/pear/Image/docs/examples/canvas.php deleted file mode 100644 index a5270016..00000000 --- a/includes/pear/Image/docs/examples/canvas.php +++ /dev/null @@ -1,61 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: canvas.php,v 1.1 2005/08/03 21:11:22 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -include_once 'Image/Canvas.php'; - -$Canvas =& Image_Canvas::factory((isset($_GET['canvas']) ? $_GET['canvas'] : 'png'), array('width' => 400, 'height' => 300)); - -$Canvas->setLineColor('black'); -$Canvas->rectangle(array('x0' => 0, 'y0' => 0, 'x1' => 399, 'y1' => 299)); - -$Canvas->setGradientFill(array('direction' => 'horizontal', 'start' => 'red', 'end' => 'blue')); -$Canvas->setLineColor('black'); -$Canvas->ellipse(array('x' => 199, 'y' => 149, 'rx' => 50, 'ry' => 50)); - -$Canvas->setFont(array('name' => 'Arial', 'size' => 12)); -$Canvas->addText(array('x' => 0, 'y' => 0, 'text' => 'Demonstration of what Image_Canvas do!')); - -$Canvas->setFont(array('name' => 'Times New Roman', 'size' => 12)); -$Canvas->addText(array('x' => 399, 'y' => 20, 'text' => 'This does not demonstrate what is does!', 'alignment' => array('horizontal' => 'right'))); - -$Canvas->setFont(array('name' => 'Courier New', 'size' => 7, 'angle' => 270)); -$Canvas->addText(array('x' => 350, 'y' => 50, 'text' => 'True, but it\'s all independent of the format!', 'alignment' => array('horizontal' => 'right'))); - -$Canvas->setFont(array('name' => 'Garamond', 'size' => 10)); -$Canvas->addText(array('x' => 199, 'y' => 295, 'text' => '[Changing format is done by changing 3 letters in the source]', 'alignment' => array('horizontal' => 'center', 'vertical' => 'bottom'))); - -$Canvas->addVertex(array('x' => 50, 'y' => 200)); -$Canvas->addVertex(array('x' => 100, 'y' => 200)); -$Canvas->addVertex(array('x' => 100, 'y' => 250)); -$Canvas->setFillColor('red@0.2'); -$Canvas->polygon(array('connect' => true)); - -$Canvas->image(array('x' => 398, 'y' => 298, 'filename' => './pear-icon.png', 'alignment' => array('horizontal' => 'right', 'vertical' => 'bottom'))); - -$Canvas->show(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/category_axis_explanation.php b/includes/pear/Image/docs/examples/category_axis_explanation.php deleted file mode 100644 index ef9fa327..00000000 --- a/includes/pear/Image/docs/examples/category_axis_explanation.php +++ /dev/null @@ -1,84 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; -require_once 'Image/Canvas.php'; - -$Canvas =& Image_Canvas::factory('png', array('width' => 500, 'height' => 200, 'antialias' => true)); - -// create the graph -$Graph =& Image_Graph::factory('graph', $Canvas); - -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(9); - -$Graph->setFont($Font); - -$Plotarea =& $Graph->addNew('plotarea'); - -$Datasets[0] =& Image_Graph::factory('dataset'); -$Datasets[1] =& Image_Graph::factory('dataset'); -$Datasets[2] =& Image_Graph::factory('dataset'); - -$Datasets[0]->addPoint('this', 1); -$Datasets[0]->addPoint('can', 3); -$Datasets[0]->addPoint('make', 2); -$Datasets[0]->addPoint('correctly', 1); - -$Datasets[1]->addPoint('sentence', 1); -$Datasets[1]->addPoint('can', 1); -$Datasets[1]->addPoint('sense', 2); -$Datasets[1]->addPoint('written', 2); -$Datasets[1]->addPoint('correctly', 2); - -$Datasets[2]->addPoint('actually', 3); -$Datasets[2]->addPoint('make', 2); -$Datasets[2]->addPoint('if', 3); -$Datasets[2]->addPoint('written', 1); - - -// expecting the following X-axis order -// 'this sentence can actually make sense if written correctly' -// making points be placed in the following order: -// -// |this|sentence|can|actually|make|sense|if|written|correctly| -// 1 |_1__|________|_2_|________|_3__|_____|__|_______|____4____| -// 2 |____|___1____|_2_|________|____|__3__|__|___4___|____5____| -// 3 |____|________|___|___1____|_2__|_____|3_|___4___|_________| -// -// if an append-algorithm were to be (wrongly) used it would yield -// 'this can make correctly sentence sense written actually if' -// making points be placed in the following order: -// -// |this|can|make|correctly|sentence|sense|written|actually|if| -// 1 |_1__|_2_|_3__|____4____|________|_____|_______|________|__| -// 2 |____|_2_|____|____5____|___1____|__3__|___4___|________|__| -// 3 |____|___|_2__|_________|________|_____|___4___|___1____|3_| - - -$Plot1 =& $Plotarea->addNew('line', array(&$Datasets[0])); -$Plot2 =& $Plotarea->addNew('line', array(&$Datasets[1])); -$Plot3 =& $Plotarea->addNew('line', array(&$Datasets[2])); - -$Plot1->setLineColor('red'); -$Plot2->setLineColor('blue'); -$Plot3->setLineColor('green'); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/color_chart.php b/includes/pear/Image/docs/examples/color_chart.php deleted file mode 100644 index e935ded7..00000000 --- a/includes/pear/Image/docs/examples/color_chart.php +++ /dev/null @@ -1,51 +0,0 @@ - - */ - -$file = file('./data/colors.txt'); - -require_once 'Image/Canvas.php'; -require_once 'Image/Graph/Color.php'; -require_once 'Image/Graph/Constants.php'; - -$Canvas =& Image_Canvas::factory('gd', array('width' => 600, 'height' => 1200)); - -$i = 0; -$cols = 10; -$Width = ($Canvas->getWidth() / $cols); -$rows = count($file) / $cols; -$rows = floor($rows) + ($rows > floor($rows) ? 1 : 0); -$Height = ($Canvas->getHeight() / $rows); -while (list($id, $color) = each($file)) { - $color = trim($color); - $x = ($i % $cols) * $Width + $Width / 2; - $y = floor($i / $cols) * $Height; - $Canvas->setLineColor('black'); - $Canvas->setFillColor($color); - $Canvas->rectangle($x - $Width / 4, $y, $x + $Width / 4, $y + $Height / 3); - $Canvas->write($x, $y + $Height / 3 + 3, $color, IMAGE_GRAPH_ALIGN_CENTER_X + IMAGE_GRAPH_ALIGN_TOP); - - $rgbColor = Image_Graph_Color::color2RGB($color); - $rgbs = 'RGB: '; - unset($rgbColor[3]); - while (list($id, $rgb) = each($rgbColor)) { - $rgbs .= ($rgb < 0x10 ? '0' : '') . dechex($rgb); - } - $Canvas->write($x, $y + $Height / 3 + 13, $rgbs, IMAGE_GRAPH_ALIGN_CENTER_X + IMAGE_GRAPH_ALIGN_TOP); - $i++; -} - -$Canvas->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/customize.php b/includes/pear/Image/docs/examples/customize.php deleted file mode 100644 index 4c765b0a..00000000 --- a/includes/pear/Image/docs/examples/customize.php +++ /dev/null @@ -1,116 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(450, 300)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Stacked Bar Chart with defined axis properties', 12)), - $Plotarea = Image_Graph::factory('plotarea'), - 5 - ) -); - -$MarkerX =& $Plotarea->addNew('Image_Graph_Axis_Marker_Area', null, IMAGE_GRAPH_AXIS_X); -$MarkerX->setFillColor('blue@0.3'); -$MarkerX->setLineColor('blue@0.3'); -$MarkerX->setLowerBound(7); -$MarkerX->setUpperBound(8); - -$MarkerY =& $Plotarea->addNew('Image_Graph_Axis_Marker_Area', null, IMAGE_GRAPH_AXIS_Y); -$MarkerY->setFillColor('green@0.3'); -$MarkerY->setLineColor('green@0.3'); -$MarkerY->setLowerBound(5.2); -$MarkerY->setUpperBound(9.3); - -$MarkerY =& $Plotarea->addNew('Image_Graph_Axis_Marker_Line', null, IMAGE_GRAPH_AXIS_Y); -$MarkerY->setLineColor('red'); -$MarkerY->setValue(14.4); - -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot1 =& $Plotarea->add( - Image_Graph::factory('bar', - array( - $Dataset = array( - Image_Graph::factory('random', array(8, 1, 10, false)), - Image_Graph::factory('random', array(8, 1, 10, false)), - Image_Graph::factory('random', array(8, 1, 10, false)) - ), - 'stacked' - ) - ) -); - -$Dataset[0]->setName('Dataset one'); -$Dataset[1]->setName('Numero duo'); -$Dataset[2]->setName('En-to-tre'); - -$FillArray =& Image_Graph::factory('Image_Graph_Fill_Array'); -$FillArray->addColor('blue@0.1', 0); -$FillArray->addColor('red@0.1', 1); -$FillArray->addColor('yellow@0.1', 2); -$Plot1->setFillStyle($FillArray); - -// Show arrow heads on the axis -$AxisX =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X); -$AxisY =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y); - -$AxisY->addMark(5); -$AxisY->addMark(7); - -$AxisY->setFontSize(7); - -$AxisY->addMark(10.8, 17.5); -$AxisY->setFillColor('red@0.7'); -$AxisY->setLabelInterval(array(1, 5, 9, 12, 13, 14, 19, 21)); -$AxisY->setTickOptions(-3, 2); -$AxisY->setLabelInterval('auto', 2); -$AxisY->setTickOptions(-1, 1, 2); - -$AxisY->setLabelOptions( - array( - 'showtext' => true, - 'font' => array( - 'size' => 3, - 'color' => 'red' - ) - ), 2 -); -$AxisY->setLabelOption('showoffset', true, 1); - -$AxisX->showArrow(); - -$Legend =& $Plotarea->addNew('legend'); -$Legend->setFillColor('white@0.7'); -$Legend->setFontSize(8); -$Legend->showShadow(); - -$Plot1->setLineColor('black@0.1'); - - -// output the Graph -$Graph->done(); -?> diff --git a/includes/pear/Image/docs/examples/data/colors.txt b/includes/pear/Image/docs/examples/data/colors.txt deleted file mode 100644 index c472f0ac..00000000 --- a/includes/pear/Image/docs/examples/data/colors.txt +++ /dev/null @@ -1,140 +0,0 @@ -aliceblue -antiquewhite -aqua -aquamarine -azure -beige -bisque -black -blanchedalmond -blue -blueviolet -brown -burlywood -cadetblue -chartreuse -chocolate -coral -cornflowerblue -cornsilk -crimson -cyan -darkblue -darkcyan -darkgoldenrod -darkgray -darkgreen -darkkhaki -darkmagenta -darkolivegreen -darkorange -darkorchid -darkred -darksalmon -darkseagreen -darkslateblue -darkslategray -darkturquoise -darkviolet -deeppink -deepskyblue -dimgray -dodgerblue -firebrick -floralwhite -forestgreen -fuchsia -gainsboro -ghostwhite -gold -goldenrod -gray -green -greenyellow -honeydew -hotpink -indianred -indigo -ivory -khaki -lavender -lavenderblush -lawngreen -lemonchiffon -lightblue -lightcoral -lightcyan -lightgoldenrodyellow -lightgreen -lightgrey -lightpink -lightsalmon -lightseagreen -lightskyblue -lightslategray -lightsteelblue -lightyellow -lime -limegreen -linen -magenta -maroon -mediumaquamarine -mediumblue -mediumorchid -mediumpurple -mediumseagreen -mediumslateblue -mediumspringgreen -mediumturquoise -mediumvioletred -midnightblue -mintcream -mistyrose -moccasin -navajowhite -navy -oldlace -olive -olivedrab -orange -orangered -orchid -palegoldenrod -palegreen -paleturquoise -palevioletred -papayawhip -peachpuff -peru -pink -plum -powderblue -purple -red -rosybrown -royalblue -saddlebrown -salmon -sandybrown -seagreen -seashell -sienna -silver -skyblue -slateblue -slategray -snow -springgreen -steelblue -tan -teal -thistle -tomato -turquoise -violet -wheat -white -whitesmoke -yellow -yellowgreen \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/datapreprocessor.php b/includes/pear/Image/docs/examples/datapreprocessor.php deleted file mode 100644 index 2ab78749..00000000 --- a/includes/pear/Image/docs/examples/datapreprocessor.php +++ /dev/null @@ -1,99 +0,0 @@ - - */ - -error_reporting(E_ALL); -include('Image/Graph.php'); - -function foo($value) { - return '-' . chr($value+63) . '-'; -} - -// create the graph -$Graph =& Image_Graph::factory('Image_Graph', array(600, 400)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(7); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('Image_Graph_Title', array('DataPreprocessor Example', 11)), - $Matrix = Image_Graph::factory('Image_Graph_Layout_Matrix', array(2, 2)), - 5 - ) -); - -$Charts = array('bar', 'line', 'Image_Graph_Plot_Smoothed_Line', 'Image_Graph_Plot_Area'); - -for ($i = 0; $i < 2; $i++) { - for ($j = 0; $j < 2; $j++) { - $Plotarea =& $Matrix->getEntry($i, $j); - - $Chart = $Charts[($i*2+$j)]; - - $GridY =& $Plotarea->addNew('bar_grid', IMAGE_GRAPH_AXIS_Y); - $GridY->setFillStyle(Image_Graph::factory('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'lightgrey'))); - - $Var = "Plot$i$j"; - $Dataset =& Image_Graph::factory('Image_Graph_Dataset_Random', array(8, 10, 100, $Chart == 'Image_Graph_Plot_Area')); - $$Var =& $Plotarea->addNew($Chart, array(&$Dataset)); - } -} -$Plotarea =& $Matrix->getEntry(0, 0); - -$AxisX =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X); -$AxisX->setDataPreprocessor(Image_Graph::factory('Image_Graph_DataPreprocessor_RomanNumerals')); -$AxisY =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y); -$AxisY->setDataPreprocessor(Image_Graph::factory('Image_Graph_DataPreprocessor_NumberText')); - -$Plotarea =& $Matrix->getEntry(0, 1); -$AxisX =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X); -$AxisX->setDataPreprocessor( - Image_Graph::factory('Image_Graph_DataPreprocessor_Array', - array( - array( - 1 => '30 Jul', - 2 => '31 Jul', - 3 => '1 Aug', - 4 => '2 Aug', - 5 => '3 Aug', - 6 => '4 Aug', - 7 => '5 Aug', - 8 => '6 Aug' - ) - ) - ) -); -$AxisY =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y); -$AxisY->setDataPreprocessor(Image_Graph::factory('Image_Graph_DataPreprocessor_Formatted', '+ %0.1f%%')); - -$Plotarea =& $Matrix->getEntry(1, 0); -$AxisX =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X); -$AxisX->setDataPreprocessor(Image_Graph::factory('Image_Graph_DataPreprocessor_Function', 'foo')); -$AxisY =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y); -$AxisY->setDataPreprocessor(Image_Graph::factory('Image_Graph_DataPreprocessor_Currency', 'US$')); - -// just for looks -$Plot00->setFillColor('red@0.2'); - -$Plot11->setFillColor('blue@0.2'); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/double_category_axis.php b/includes/pear/Image/docs/examples/double_category_axis.php deleted file mode 100644 index ed5e3631..00000000 --- a/includes/pear/Image/docs/examples/double_category_axis.php +++ /dev/null @@ -1,100 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); -// add a TrueType font -$Font =& $Graph->addNew('ttf_font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(7); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Testing Category Axis', 10)), - $Plotarea = Image_Graph::factory('plotarea', array('Image_Graph_Axis_Category', 'Image_Graph_Axis_Category')), - 5 - ) -); - -//$DS =& Image_Graph::factory('dataset'); -//$DS->addPoint('Apache', 'Open Source'); -//$DS->addPoint('BSD', 'Open Source'); -//$DS->addPoint('Linux', 'Open Source'); -//$DS->addPoint('Microsoft', 'Proprietary'); -//$DS->addPoint('Micro', 'Proprietary'); -//$DS->addPoint('Minisoft', 'Proprie'); -//$DS->addPoint('Millisoft', 'Prop'); -// -//$DS2 =& Image_Graph::factory('dataset'); -//$DS->addPoint('Apache', 'Open Source'); -//$DS->addPoint('BSD', 'Open Source'); -//$DS->addPoint('Linux', 'Open Source'); -//$DS->addPoint('Microsoft', 'Proprietary'); -//$DS->addPoint('Micro', 'Proprietary'); -//$DS->addPoint('Minisoft', 'Proprie'); -//$DS->addPoint('Miniority', 'Proprias'); -// -//$Plot =& $Plotarea->addNew('scatter', $DS); -//$Marker =& Image_Graph::factory('Image_Graph_Marker_Plus'); -//$Marker->setFillColor('red'); -//$Marker->setLineColor('black'); -//$Plot->setMarker($Marker); -// -//$Plot2 =& $Plotarea->addNew('scatter', $DS2); -//$Marker =& Image_Graph::factory('Image_Graph_Marker_Cross'); -//$Marker->setFillColor('blue'); -//$Marker->setLineColor('black'); -//$Plot2->setMarker($Marker); -// -//$Graph->done(); - -$DS =& Image_Graph::factory('dataset'); -$DS->addPoint('Germany', 'England'); -$DS->addPoint('Denmark', 'France'); -$DS->addPoint('Sweden', 'Denmark'); -$DS->addPoint('England', 'France'); -$DS->addPoint('Norway', 'Finland'); -$DS->addPoint('Denmark', 'Finland'); -$DS->addPoint('Iceland', 'Germany'); -$DS->addPoint('Norway', 'France'); - -$DS2 =& Image_Graph::factory('dataset'); -$DS2->addPoint('Sweden', 'France'); -$DS2->addPoint('Austria', 'Germany'); -$DS2->addPoint('Norway', 'Holland'); -$DS2->addPoint('Denmark', 'Germany'); -$DS2->addPoint('Sweden', 'Holland'); -$DS2->addPoint('Iceland', 'Denmark'); - -$Plot =& $Plotarea->addNew('scatter', $DS); -$Marker =& Image_Graph::factory('Image_Graph_Marker_Cross'); -$Marker->setFillColor('blue'); -$Marker->setLineColor('black'); -$Plot->setMarker($Marker); - -$Plot2 =& $Plotarea->addNew('scatter', $DS2); -$Marker2 =& Image_Graph::factory('Image_Graph_Marker_Plus'); -$Marker2->setFillColor('yellow'); -$Marker2->setLineColor('black'); -$Plot2->setMarker($Marker2); - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/driver_filepdf.php b/includes/pear/Image/docs/examples/driver_filepdf.php deleted file mode 100644 index f302fd69..00000000 --- a/includes/pear/Image/docs/examples/driver_filepdf.php +++ /dev/null @@ -1,53 +0,0 @@ - - */ - -error_reporting(E_ALL); - -require_once 'Image/Graph.php'; -require_once 'Image/Canvas.php'; - -$Canvas =& Image_Canvas::factory('File_PDF', array('page' => 'A4')); - -// create the graph -$Graph =& Image_Graph::factory('graph', $Canvas); - -// // setup the plotarea, legend and their layout -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Simple Line Chart Sample', 12)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 88 - ), - 5 - ) -); - -// link the legend with the plotares -$Legend->setPlotarea($Plotarea); - -// create a random dataset for sake of simplicity -$Dataset =& Image_Graph::factory('random', array(10, 2, 15, true)); -// create the plot as line chart using the dataset -$Plot =& $Plotarea->addNew('line', array(&$Dataset)); - -// set a line color -$Plot->setLineColor('red'); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/driver_pdf.php b/includes/pear/Image/docs/examples/driver_pdf.php deleted file mode 100644 index 7f99b418..00000000 --- a/includes/pear/Image/docs/examples/driver_pdf.php +++ /dev/null @@ -1,198 +0,0 @@ - - */ - -error_reporting(E_ALL); - -require_once 'Image/Graph.php'; -require_once 'Image/Canvas.php'; - -$Canvas =& Image_Canvas::factory('pdflib', array('page' => 'A3', 'align' => 'center', 'width' => 600, 'height' => 400)); - - -// create the graph -$Graph =& Image_Graph::factory('graph', $Canvas); - -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 15 pixels -$Font->setSize(15); -// add a title using the created font - -$Dataset_SmoothedLine =& Image_Graph::factory('dataset'); -$Dataset_SmoothedLine->addPoint('DK', 6); -$Dataset_SmoothedLine->addPoint('UK', 8); -$Dataset_SmoothedLine->addPoint('PO', 2); -$Dataset_SmoothedLine->addPoint('NL', 4); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Layout and Legend Sample', &$Font)), - Image_Graph::horizontal( - Image_Graph::vertical( - Image_Graph::horizontal( - Image_Graph::factory('title', array('This is the Y Axis', &$_Image_Graph_verticalFont)), - Image_Graph::vertical( - $Plotarea_BarAndLine = Image_Graph::factory('plotarea'), - Image_Graph::factory('title', array('This is the X Axis', &$_Image_Graph_font)), - 95 - ), - 5 - ), - $Legend_BarAndLine = Image_Graph::factory('legend'), - 95 - ), - Image_Graph::vertical( - Image_Graph::horizontal( - $Plotarea_SmoothedLine = Image_Graph::factory('plotarea'), - $Legend_SmoothedLine = Image_Graph::factory('legend'), - 80 - ), - $Plotarea_Radar = Image_Graph::factory('Image_Graph_Plotarea_Radar') - ), - 65 - ), - 9 - ) -); - -$Legend_BarAndLine->setPlotarea($Plotarea_BarAndLine); -$Legend_SmoothedLine->setPlotarea($Plotarea_SmoothedLine); - -// create a Y grid -$Grid_Radar =& $Plotarea_Radar->addNew('line_grid', IMAGE_GRAPH_AXIS_Y); -$Grid_Radar->setLineColor('lightgrey'); - -// create a Y grid -$Grid_BarAndLine =& $Plotarea_BarAndLine->addNew('bar_grid', IMAGE_GRAPH_AXIS_Y); -// that is light gray in color -$Grid_BarAndLine->setFillStyle(Image_Graph::factory('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'lightgrey'))); - -// create a Y grid -$Grid_SmoothedLine =& $Plotarea_SmoothedLine->addNew('line_grid', IMAGE_GRAPH_AXIS_Y); -$Grid_SmoothedLine->setLineColor('lightgrey'); - -// create the 1st dataset -//$Dataset_SmoothedLine =& new Image_RandomDataset(4, 2, 15, true); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot_SmoothedLine =& $Plotarea_SmoothedLine->addNew('Image_Graph_Plot_Smoothed_Line', $Dataset_SmoothedLine); -$Plot_SmoothedLine->setLineColor('orange'); - -// create a 3rd dataset -$Dataset_BarChart =& Image_Graph::factory('random', array(8, 10, 120, false)); -// create the 3rd plot as line chart using the 2nd dataset -$Plot_BarChart =& $Plotarea_BarAndLine->addNew('bar', $Dataset_BarChart); -// set the fill style of the barchart to the almost transparent BlueAlpha -$FillArray =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Plot_BarChart->setFillStyle($FillArray); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'red')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'blue')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'yellow')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'green')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'purple')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'orange')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'black')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'brown')); - -// create the 2nd dataset -$Dataset_LineMarker =& Image_Graph::factory('random', array(8, 20, 100, false)); -// create the 2nd plot as line chart using the 2nd dataset -$Plot_LineMarker =& $Plotarea_BarAndLine->addNew('line', $Dataset_LineMarker); - -$Marker =& Image_Graph::factory('Image_Graph_Marker_Array'); -$CrossMarker =& Image_Graph::factory('Image_Graph_Marker_Cross'); -$CircleMarker =& Image_Graph::factory('Image_Graph_Marker_Circle'); -$Marker->add($CrossMarker); -$Marker->add($CircleMarker); -$Plot_LineMarker->setMarker($Marker); -// Create a red line -$CrossMarker->setLineColor('red'); -// Create a blue line -$CircleMarker->setLineColor('blue'); - -// Show arrow heads on the axis -$AxisX =& $Plotarea_BarAndLine->getAxis(IMAGE_GRAPH_AXIS_X); -$AxisY =& $Plotarea_BarAndLine->getAxis(IMAGE_GRAPH_AXIS_Y); -$AxisX->showArrow(); -$AxisY->showArrow(); - -// create an data label array for formatting label data based on an array -$ArrayData =& Image_Graph::factory('Image_Graph_DataPreprocessor_Array', - array( - array( - 1=>'A Point', - 2=>'Another', - 6=>'Yet another' - ) - ) -); - -// use the data label array on the X axis -$AxisX->setDataPreprocessor($ArrayData); -$AxisFontX =& $Graph->addNew('Image_Graph_Font_Vertical'); -$AxisX->setFont($AxisFontX); - -$Legend_BarAndLine->setFillColor('white'); -$Legend_SmoothedLine->setFillColor('white'); - -$Font2 =& $Graph->addNew('font', 'Verdana'); -$Font2->setSize(8); -$Legend_BarAndLine->setFont($Font2); -$Legend_SmoothedLine->setFont($Font2); - -$Plot_SmoothedLine->setTitle('Oil'); -$Plot_LineMarker->setTitle('Data Set 1'); -$Plot_BarChart->setTitle('Data Set 2'); - -// create the dataset -$Dataset_Radar1 =& Image_Graph::factory('random', array(8, 1, 5)); -$Dataset_Radar2 =& Image_Graph::factory('random', array(8, 1, 5)); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot_Radar1 =& $Plotarea_Radar->addNew('Image_Graph_Plot_Radar', $Dataset_Radar1); -$Plot_Radar2 =& $Plotarea_Radar->addNew('Image_Graph_Plot_Radar', $Dataset_Radar2); - -//$Dataset_Radar1->setMaximumY(7); - -$DataPreprocessor =& Image_Graph::factory('Image_Graph_DataPreprocessor_Array', - array( - array( - 'Irrelevance', - 'Partly', - 'Regular', - 'Relevance', - 'Something', - 'Everything', - 'Nothing', - 'Irregular' - ) - ) -); - -$AxisX =& $Plotarea_Radar->getAxis(IMAGE_GRAPH_AXIS_X); -$AxisX->setDataPreprocessor($DataPreprocessor); - -$AverageMarker =& Image_Graph::factory('Image_Graph_Marker_Average'); -$Plot_SmoothedLine->setMarker($AverageMarker); -$AverageMarker->setLineColor('purple'); - -// set a standard fill style -$Plot_Radar1->setFillColor('yellow@0.2'); -$Plot_Radar2->setFillColor('green@0.2'); -// output the Graph - - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/driver_png_svg.php b/includes/pear/Image/docs/examples/driver_png_svg.php deleted file mode 100644 index e7b758e7..00000000 --- a/includes/pear/Image/docs/examples/driver_png_svg.php +++ /dev/null @@ -1,72 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; -require_once 'Image/Canvas.php'; - -// create a new GD canvas -$Canvas =& Image_Canvas::factory('gd', - array( - 'filename' => './images/modify.jpg', - 'left' => 400, - 'top' => 100, - 'width' => 500, - 'height' => 500, - 'transparent' => true - ) - ); - - // create the graph using the GD canvas -$Graph =& Image_Graph::factory('graph', $Canvas); - -// create a simple graph -$Graph->add( - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 90 - ) -); -$Legend->setPlotarea($Plotarea); -$Dataset =& Image_Graph::factory('random', array(10, 2, 15, true)); -$Plot =& $Plotarea->addNew('area', $Dataset); -$Plot->setLineColor('gray'); -$Plot->setFillColor('blue@0.2'); - -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); -$Graph->addNew('title', array('Simple Area Chart Sample', 12)); - -// output the graph using the GD canvas -$Graph->done(array('filename' => './canvassample.png')); - -// create a new SVG canvas -$Canvas =& Image_Canvas::factory('svg', - array( - 'width' => 600, - 'height' => 400 - ) -); -// make the graph use this now instead -$Graph->setCanvas($Canvas); - -// 're'-output the graph, but not using the SVG canvas -$Graph->done(array('filename' => './canvassample.svg')); -?> diff --git a/includes/pear/Image/docs/examples/driver_swf01.php b/includes/pear/Image/docs/examples/driver_swf01.php deleted file mode 100644 index f4053f10..00000000 --- a/includes/pear/Image/docs/examples/driver_swf01.php +++ /dev/null @@ -1,57 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; -require_once 'Image/Canvas.php'; - -$Canvas =& Image_Canvas::factory('swf', array('width' => 600, 'height' => 400)); - - -// create the graph -$Graph =& Image_Graph::factory('graph', $Canvas); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(11); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Simple Area Chart Sample', &$Font)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 5 - ) -); -$Legend->setPlotarea($Plotarea); - -// create the dataset -$Dataset =& Image_Graph::factory('random', array(10, 2, 15, true)); -// create the 1st plot as smoothed area chart using the 1st dataset - -$Plot =& $Plotarea->addNew('area', $Dataset); - -// set a line color -$Plot->setLineColor('gray'); - -// set a standard fill style -$Plot->setFillColor('blue@0.2'); - -// output the Graph -$Graph->done(); -?> diff --git a/includes/pear/Image/docs/examples/driver_swf02.php b/includes/pear/Image/docs/examples/driver_swf02.php deleted file mode 100644 index aa4799c6..00000000 --- a/includes/pear/Image/docs/examples/driver_swf02.php +++ /dev/null @@ -1,197 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; -require_once 'Image/Canvas.php'; - -$Canvas =& Image_Canvas::factory('swf', array('width' => 600, 'height' => 400)); - - -// create the graph -$Graph =& Image_Graph::factory('graph', $Canvas); - -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 15 pixels -$Font->setSize(15); -// add a title using the created font - -$Dataset_SmoothedLine =& Image_Graph::factory('dataset'); -$Dataset_SmoothedLine->addPoint('DK', 6); -$Dataset_SmoothedLine->addPoint('UK', 8); -$Dataset_SmoothedLine->addPoint('PO', 2); -$Dataset_SmoothedLine->addPoint('NL', 4); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Layout and Legend Sample', &$Font)), - Image_Graph::horizontal( - Image_Graph::vertical( - Image_Graph::horizontal( - Image_Graph::factory('title', array('This is the Y Axis', &$_Image_Graph_verticalFont)), - Image_Graph::vertical( - $Plotarea_BarAndLine = Image_Graph::factory('plotarea'), - Image_Graph::factory('title', array('This is the X Axis', &$_Image_Graph_font)), - 95 - ), - 5 - ), - $Legend_BarAndLine = Image_Graph::factory('legend'), - 95 - ), - Image_Graph::vertical( - Image_Graph::horizontal( - $Plotarea_SmoothedLine = Image_Graph::factory('plotarea'), - $Legend_SmoothedLine = Image_Graph::factory('legend'), - 80 - ), - $Plotarea_Radar = Image_Graph::factory('Image_Graph_Plotarea_Radar') - ), - 65 - ), - 9 - ) -); - -$Legend_BarAndLine->setPlotarea($Plotarea_BarAndLine); -$Legend_SmoothedLine->setPlotarea($Plotarea_SmoothedLine); - -// create a Y grid -$Grid_Radar =& $Plotarea_Radar->addNew('line_grid', IMAGE_GRAPH_AXIS_Y); -$Grid_Radar->setLineColor('lightgrey'); - -// create a Y grid -$Grid_BarAndLine =& $Plotarea_BarAndLine->addNew('bar_grid', IMAGE_GRAPH_AXIS_Y); -// that is light gray in color -$Grid_BarAndLine->setFillStyle(Image_Graph::factory('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'lightgrey'))); - -// create a Y grid -$Grid_SmoothedLine =& $Plotarea_SmoothedLine->addNew('line_grid', IMAGE_GRAPH_AXIS_Y); -$Grid_SmoothedLine->setLineColor('lightgrey'); - -// create the 1st dataset -//$Dataset_SmoothedLine =& new Image_RandomDataset(4, 2, 15, true); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot_SmoothedLine =& $Plotarea_SmoothedLine->addNew('Image_Graph_Plot_Smoothed_Line', $Dataset_SmoothedLine); -$Plot_SmoothedLine->setLineColor('orange'); - -// create a 3rd dataset -$Dataset_BarChart =& Image_Graph::factory('random', array(8, 10, 120, false)); -// create the 3rd plot as line chart using the 2nd dataset -$Plot_BarChart =& $Plotarea_BarAndLine->addNew('bar', $Dataset_BarChart); -// set the fill style of the barchart to the almost transparent BlueAlpha -$FillArray =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Plot_BarChart->setFillStyle($FillArray); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_HORIZONTAL, 'white', 'red')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'blue')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'yellow')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_HORIZONTAL, 'white', 'green')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'purple')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'orange')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'black')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'brown')); - -// create the 2nd dataset -$Dataset_LineMarker =& Image_Graph::factory('random', array(8, 20, 100, false)); -// create the 2nd plot as line chart using the 2nd dataset -$Plot_LineMarker =& $Plotarea_BarAndLine->addNew('line', $Dataset_LineMarker); - -$Marker =& Image_Graph::factory('Image_Graph_Marker_Array'); -$CrossMarker =& Image_Graph::factory('Image_Graph_Marker_Cross'); -$CircleMarker =& Image_Graph::factory('Image_Graph_Marker_Circle'); -$Marker->add($CrossMarker); -$Marker->add($CircleMarker); -$Plot_LineMarker->setMarker($Marker); -// Create a red line -$CrossMarker->setLineColor('red'); -// Create a blue line -$CircleMarker->setLineColor('blue'); - -// Show arrow heads on the axis -$AxisX =& $Plotarea_BarAndLine->getAxis(IMAGE_GRAPH_AXIS_X); -$AxisY =& $Plotarea_BarAndLine->getAxis(IMAGE_GRAPH_AXIS_Y); -$AxisX->showArrow(); -$AxisY->showArrow(); - -// create an data label array for formatting label data based on an array -$ArrayData =& Image_Graph::factory('Image_Graph_DataPreprocessor_Array', - array( - array( - 1=>'A Point', - 2=>'Another', - 6=>'Yet another' - ) - ) -); - -// use the data label array on the X axis -$AxisX->setDataPreprocessor($ArrayData); -$AxisFontX =& $Graph->addNew('Image_Graph_Font_Vertical'); -$AxisX->setFont($AxisFontX); - -$Legend_BarAndLine->setFillColor('white'); -$Legend_SmoothedLine->setFillColor('white'); - -$Font2 =& $Graph->addNew('font', 'Verdana'); -$Font2->setSize(8); -$Legend_BarAndLine->setFont($Font2); -$Legend_SmoothedLine->setFont($Font2); - -$Plot_SmoothedLine->setTitle('Oil'); -$Plot_LineMarker->setTitle('Data Set 1'); -$Plot_BarChart->setTitle('Data Set 2'); - -// create the dataset -$Dataset_Radar1 =& Image_Graph::factory('random', array(8, 1, 5)); -$Dataset_Radar2 =& Image_Graph::factory('random', array(8, 1, 5)); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot_Radar1 =& $Plotarea_Radar->addNew('Image_Graph_Plot_Radar', $Dataset_Radar1); -$Plot_Radar2 =& $Plotarea_Radar->addNew('Image_Graph_Plot_Radar', $Dataset_Radar2); - -//$Dataset_Radar1->setMaximumY(7); - -$DataPreprocessor =& Image_Graph::factory('Image_Graph_DataPreprocessor_Array', - array( - array( - 'Irrelevance', - 'Partly', - 'Regular', - 'Relevance', - 'Something', - 'Everything', - 'Nothing', - 'Irregular' - ) - ) -); - -$AxisX =& $Plotarea_Radar->getAxis(IMAGE_GRAPH_AXIS_X); -$AxisX->setDataPreprocessor($DataPreprocessor); - -//$Plot_Radar1->setMarker(new Image_CrossMarker(), 'Marker'); -//$Plot_Radar1->setLineStyle($YELLOW); - -$AverageMarker =& Image_Graph::factory('Image_Graph_Marker_Average'); -$Plot_SmoothedLine->setMarker($AverageMarker); -$AverageMarker->setLineColor('purple'); - -// set a standard fill style -$Plot_Radar1->setFillColor('yellow@0.2'); -$Plot_Radar2->setFillColor('green@0.2'); -// output the Graph - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/driver_swf03.php b/includes/pear/Image/docs/examples/driver_swf03.php deleted file mode 100644 index 6e3b052e..00000000 --- a/includes/pear/Image/docs/examples/driver_swf03.php +++ /dev/null @@ -1,53 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; -require_once 'Image/Canvas.php'; - -$Canvas =& Image_Canvas::factory('swf', array('width' => 600, 'height' => 400)); - - -// create the graph -$Graph =& Image_Graph::factory('graph', $Canvas); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(11); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Simple Line Chart Sample', &$Font)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 5 - ) -); -$Legend->setPlotarea($Plotarea); - -// create the dataset -$Dataset =& Image_Graph::factory('random', array(10, 2, 15, true)); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot =& $Plotarea->addNew('line', $Dataset); - -// set a line color -$Plot->setLineColor('red'); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/frontpage_sample.php b/includes/pear/Image/docs/examples/frontpage_sample.php deleted file mode 100644 index fa85ddea..00000000 --- a/includes/pear/Image/docs/examples/frontpage_sample.php +++ /dev/null @@ -1,313 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; -require_once 'Image/Canvas.php'; - -// create a new GD canvas -$Canvas =& Image_Canvas::factory('gd', - array( - 'width' => 600, - 'height' => 400 - ) -); - -// create the graph -$Graph =& Image_Graph::factory('graph', $Canvas); - -$Font =& $Graph->addNew('font', 'Verdana'); -$Font->setSize(7); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Image_Graph Demonstration', 12)), - Image_Graph::vertical( - Image_Graph::vertical( - $Plotarea_Weather = Image_Graph::factory('plotarea'), - $Legend_Weather = Image_Graph::factory('legend'), - 85 - ), - Image_Graph::horizontal( - Image_Graph::vertical( - Image_Graph::vertical( - Image_Graph::factory( - 'title', - array('Demonstration of Mathematical Functions', 10) - ), - $Plotarea_SinCos = Image_Graph::factory('plotarea', 'axis'), - 5 - ), - $Legend_SinCos = Image_Graph::factory('legend'), - 90 - ), - $Plotarea_Car = Image_Graph::factory('plotarea'), - 50 - ), - 60 - ), - 5) -); -$Legend_Weather->setPlotarea($Plotarea_Weather); -$Legend_Weather->setFontSize(7); - -$Legend_SinCos->setPlotarea($Plotarea_SinCos); -$Legend_SinCos->setFontSize(8); - -$GridY_Weather =& $Plotarea_Weather->addNew( - 'line_grid', - null, - IMAGE_GRAPH_AXIS_Y -); -$GridY_Weather->setLineColor('gray@0.1'); - -$Marker_AverageSpan =& - $Plotarea_Weather->addNew( - 'Image_Graph_Axis_Marker_Area', - IMAGE_GRAPH_AXIS_Y - ); -$Marker_AverageSpan->setFillColor('green@0.2'); -$Marker_AverageSpan->setLowerBound(3.8); -$Marker_AverageSpan->setUpperBound(11.4); - -$Marker_Average =& - $Plotarea_Weather->addNew( - 'Image_Graph_Axis_Marker_Line', - IMAGE_GRAPH_AXIS_Y - ); -$Marker_Average->setLineColor('blue@0.4'); -$Marker_Average->setValue(7.7); - -$Dataset_Rainfall =& Image_Graph::factory('dataset'); -$Dataset_Rainfall->addPoint('Jan', 60); -$Dataset_Rainfall->addPoint('Feb', 41); -$Dataset_Rainfall->addPoint('Mar', 48); -$Dataset_Rainfall->addPoint('Apr', 42); -$Dataset_Rainfall->addPoint('May', 50); -$Dataset_Rainfall->addPoint('Jun', 55); -$Dataset_Rainfall->addPoint('Jul', 67); -$Dataset_Rainfall->addPoint('Aug', 65); -$Dataset_Rainfall->addPoint('Sep', 72); -$Dataset_Rainfall->addPoint('Oct', 77); -$Dataset_Rainfall->addPoint('Nov', 80); -$Dataset_Rainfall->addPoint('Dec', 68); -$Plot_Rainfall =& - $Plotarea_Weather->addNew( - 'bar', - array(&$Dataset_Rainfall), - IMAGE_GRAPH_AXIS_Y_SECONDARY - ); -$Plot_Rainfall->setLineColor('gray'); -$Plot_Rainfall->setFillColor('yellow@0.1'); -$Plot_Rainfall->setTitle('Average rainfall'); - -$Dataset_TempAvg =& Image_Graph::factory('dataset'); -$Dataset_TempAvg->addPoint('Jan', 0.2); -$Dataset_TempAvg->addPoint('Feb', 0.1); -$Dataset_TempAvg->addPoint('Mar', 2.3); -$Dataset_TempAvg->addPoint('Apr', 5.8); -$Dataset_TempAvg->addPoint('May', 10.8); -$Dataset_TempAvg->addPoint('Jun', 14.1); -$Dataset_TempAvg->addPoint('Jul', 16.2); -$Dataset_TempAvg->addPoint('Aug', 15.9); -$Dataset_TempAvg->addPoint('Sep', 12.1); -$Dataset_TempAvg->addPoint('Oct', 8.7); -$Dataset_TempAvg->addPoint('Nov', 4.4); -$Dataset_TempAvg->addPoint('Dec', 1.8); -$Plot_TempAvg =& - $Plotarea_Weather->addNew( - 'Image_Graph_Plot_Smoothed_Line', - array(&$Dataset_TempAvg) - ); -$Plot_TempAvg->setLineColor('blue'); -$Plot_TempAvg->setTitle('Average temperature'); - -$Dataset_TempMin =& Image_Graph::factory('dataset'); -$Dataset_TempMin->addPoint('Jan', -2.7); -$Dataset_TempMin->addPoint('Feb', -2.8); -$Dataset_TempMin->addPoint('Mar', -0.9); -$Dataset_TempMin->addPoint('Apr', 1.2); -$Dataset_TempMin->addPoint('May', 5.5); -$Dataset_TempMin->addPoint('Jun', 9.2); -$Dataset_TempMin->addPoint('Jul', 11.3); -$Dataset_TempMin->addPoint('Aug', 11.1); -$Dataset_TempMin->addPoint('Sep', 7.8); -$Dataset_TempMin->addPoint('Oct', 5.0); -$Dataset_TempMin->addPoint('Nov', 1.5); -$Dataset_TempMin->addPoint('Dec', -0.9); -$Plot_TempMin =& - $Plotarea_Weather->addNew( - 'Image_Graph_Plot_Smoothed_Line', - array(&$Dataset_TempMin) - ); -$Plot_TempMin->setLineColor('teal'); -$Plot_TempMin->setTitle('Minimum temperature'); - -$Dataset_TempMax =& Image_Graph::factory('dataset'); -$Dataset_TempMax->addPoint('Jan', 2.4); -$Dataset_TempMax->addPoint('Feb', 2.5); -$Dataset_TempMax->addPoint('Mar', 5.4); -$Dataset_TempMax->addPoint('Apr', 10.5); -$Dataset_TempMax->addPoint('May', 15.8); -$Dataset_TempMax->addPoint('Jun', 18.9); -$Dataset_TempMax->addPoint('Jul', 21.2); -$Dataset_TempMax->addPoint('Aug', 20.8); -$Dataset_TempMax->addPoint('Sep', 16.3); -$Dataset_TempMax->addPoint('Oct', 11.8); -$Dataset_TempMax->addPoint('Nov', 6.9); -$Dataset_TempMax->addPoint('Dec', 4.1); -$Plot_TempMax =& - $Plotarea_Weather->addNew( - 'Image_Graph_Plot_Smoothed_Line', - array(&$Dataset_TempMax) - ); -$Plot_TempMax->setLineColor('red'); -$Plot_TempMax->setTitle('Maximum temperature'); - -$DataPreprocessor_MM =& - Image_Graph::factory('Image_Graph_DataPreprocessor_Formatted', '%d mm'); -$DataPreprocessor_DegC =& - Image_Graph::factory('Image_Graph_DataPreprocessor_Formatted', '%d C'); - -$Marker_Rainfall =& - $Plot_Rainfall->addNew('Image_Graph_Marker_Value', IMAGE_GRAPH_VALUE_Y); -$Marker_Rainfall->setDataPreprocessor($DataPreprocessor_MM); -$Marker_Rainfall->setFontSize(7); -$PointingMarker_Rainfall =& - $Plot_Rainfall->addNew( - 'Image_Graph_Marker_Pointing_Angular', - array(20, &$Marker_Rainfall) - ); -$Plot_Rainfall->setMarker($PointingMarker_Rainfall); - -$AxisY_Weather =& $Plotarea_Weather->getAxis(IMAGE_GRAPH_AXIS_Y); -$AxisY_Weather->showLabel(IMAGE_GRAPH_LABEL_ZERO); -$AxisY_Weather->setDataPreprocessor($DataPreprocessor_DegC); -$AxisY_Weather->setTitle( - 'Temperature', - array('vertical' => true, 'angle' => 90) -); - -$AxisYsecondary_Weather =& - $Plotarea_Weather->getAxis(IMAGE_GRAPH_AXIS_Y_SECONDARY); -$AxisYsecondary_Weather->setDataPreprocessor($DataPreprocessor_MM); -$AxisYsecondary_Weather->setTitle( - 'Rainfall', - array('vertical' => true, 'angle' => 270) -); - -$GridX_SinCos =& - $Plotarea_SinCos->addNew('line_grid', null, IMAGE_GRAPH_AXIS_X); -$GridY_SinCos =& - $Plotarea_SinCos->addNew('line_grid', null, IMAGE_GRAPH_AXIS_Y); -$Dataset_Sin =& - Image_Graph::factory( - 'Image_Graph_Dataset_Function', - array(-2*pi(), 2*pi(), 'sin', 50) - ); -$Dataset_Cos =& - Image_Graph::factory( - 'Image_Graph_Dataset_Function', - array(-2*pi(), 2*pi(), 'cos', 50) - ); -$Plot_Sin =& $Plotarea_SinCos->addNew('line', $Dataset_Sin); -$Plot_Cos =& $Plotarea_SinCos->addNew('line', $Dataset_Cos); -$Plot_Sin->setLineColor('red'); -$Plot_Cos->setLineColor('blue'); -$Plot_Sin->setTitle('sin(x)'); -$Plot_Cos->setTitle('cos(x)'); -$AxisX_SinCos =& $Plotarea_SinCos->getAxis(IMAGE_GRAPH_AXIS_X); -$AxisX_SinCos->setLabelInterval(array(-6, -4, -2, 2, 4, 6)); -$AxisY_SinCos =& $Plotarea_SinCos->getAxis(IMAGE_GRAPH_AXIS_Y); -$AxisY_SinCos->forceMinimum(-1.1); -$AxisY_SinCos->forceMaximum(1.1); -$AxisY_SinCos->setLabelInterval(array(-1, -0.5, 0.5, 1)); - -function carLabel($value) { - return 2000+$value; -} - -$DataPreprocessor_Car =& - Image_Graph::factory('Image_Graph_DataPreprocessor_Function', 'carLabel'); - -$GridX_Car =& $Plotarea_Car->addNew('line_grid', null, IMAGE_GRAPH_AXIS_X); -$GridY_Car =& $Plotarea_Car->addNew('line_grid', null, IMAGE_GRAPH_AXIS_Y); -$GridX_Car->setLineColor('gray@0.2'); -$GridY_Car->setLineColor('gray@0.2'); -$Dataset_Car =& Image_Graph::factory('random', array(10, 10, 100, true)); -$Fill_Car =& - Image_Graph::factory('Image_Graph_Fill_Image', './images/audi-tt-coupe.jpg'); -$Plotarea_Car->setFillStyle($Fill_Car); -$Plot_Car =& - $Plotarea_Car->addNew('Image_Graph_Plot_Smoothed_Area', $Dataset_Car); -$Plot_Car->setLineColor('gray'); -$Plot_Car->setFillColor('white@0.7'); - -$AxisX_Car =& $Plotarea_Car->getAxis(IMAGE_GRAPH_AXIS_X); -$AxisX_Car->setDataPreprocessor($DataPreprocessor_Car); -$AxisX_Car->setFontSize(6); -$AxisY_Car =& $Plotarea_Car->getAxis(IMAGE_GRAPH_AXIS_Y); -$AxisY_Car->forceMaximum(100); - -// output the graph using the GD canvas -$Graph->done(array('filename' => './output/frontpage_sample.png')); - -// create a new SVG canvas -$Canvas =& Image_Canvas::factory('svg', - array( - 'width' => 600, - 'height' => 400 - ) -); -// make the graph use this now instead -$Graph->setCanvas($Canvas); - -// 're'-output the graph, but not using the SVG canvas -$Graph->done(array('filename' => './output/frontpage_sample.svg')); - -/* -// create a new PDF canvas -$Canvas =& Image_Canvas::factory('pdflib', - array( - 'page' => 'A4', - 'align' => 'center', - 'orientation' => 'landscape', - 'width' => 600, - 'height' => 400 - ) -); -// make the graph use this now instead -$Graph->setCanvas($Canvas); - -// 're'-output the graph, but not using the PDF canvas -$Graph->done(array('filename' => './output/frontpage_sample.pdf')); - -// create a new SWF canvas -$Canvas =& Image_Canvas::factory('swf', - array( - 'width' => 600, - 'height' => 400 - ) -); -// make the graph use this now instead -$Graph->setCanvas($Canvas); - -// 're'-output the graph, but not using the SWF canvas -$Graph->done(array('filename' => './output/frontpage_sample.swf')); -*/ -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/gradient_fill_area.php b/includes/pear/Image/docs/examples/gradient_fill_area.php deleted file mode 100644 index 4b4f13f3..00000000 --- a/includes/pear/Image/docs/examples/gradient_fill_area.php +++ /dev/null @@ -1,80 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Gradient filled smoothed area chart', 12)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 85 - ), - 8 - ) -); - -$Legend->setPlotarea($Plotarea); - -// create the 1st dataset -$Dataset =& Image_Graph::factory('random', array(10, 40, 100, true)); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot =& $Plotarea->addNew('smooth_area', array(&$Dataset)); -// create a vertical gradient fill using red and yellow, ie bottom of graph -// will be yellow and the 'higher' the value the more red it will be, ie a 'fire' effect -$Plot->setFillStyle(Image_Graph::factory('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'green', 'lightyellow'))); -$Plot->setTitle('Inside scope'); - -// create the 2nd dataset -$Dataset2 =& Image_Graph::factory('random', array(10, 50, 70, true)); -// create the 2nd plot as smoothed area chart using the 2nd dataset -$Plot2 =& $Plotarea->addNew('smooth_area', array(&$Dataset2)); -// create a vertical gradient fill using red and yellow, ie bottom of graph -// will be yellow and the 'higher' the value the more red it will be, ie a 'fire' effect -$Plot2->setFillColor('white@0.4'); -$Plot2->setTitle('Outside scope'); - -$Graph->setBackground(Image_Graph::factory('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL_MIRRORED, 'steelblue', 'lightcyan'))); -$Graph->setBorderColor('black'); - - -// create a Y data value marker -$Marker =& $Plot->addNew('Image_Graph_Marker_Value', IMAGE_GRAPH_PCT_Y_MAX); -// create a pin-point marker type -$PointingMarker =& $Plot->addNew('Image_Graph_Marker_Pointing_Angular', array(20, &$Marker)); -// and use the marker on the 1st plot -$Plot->setMarker($PointingMarker); -// format value marker labels as percentage values -$Marker->setDataPreProcessor(Image_Graph::factory('Image_Graph_DataPreprocessor_Formatted', '%0.1f%%')); -$Marker->setFontSize(7); - -$AxisY =& $Plotarea->getAxis('y'); -$AxisY->forceMinimum(30); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/gradient_pie.php b/includes/pear/Image/docs/examples/gradient_pie.php deleted file mode 100644 index 694542b2..00000000 --- a/includes/pear/Image/docs/examples/gradient_pie.php +++ /dev/null @@ -1,106 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph = & Image_Graph::factory('graph', array(400, 300)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Gradient Filled Donut/Pie Chart', 12)), - Image_Graph::horizontal( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 60 - ), - 5 - ) -); - -$Legend->setPlotarea($Plotarea); -$Legend->setAlignment(IMAGE_GRAPH_ALIGN_VERTICAL); - -// create the dataset -$Dataset = & Image_Graph::factory('dataset'); -$Dataset->addPoint('Beef', rand(1, 10), 'beef'); -$Dataset->addPoint('Pork', rand(1, 10), 'pork'); -$Dataset->addPoint('Poultry', rand(1, 10), 'poultry'); -$Dataset->addPoint('Camels', rand(1, 10), 'camels'); -$Dataset->addPoint('Other', rand(1, 10), 'other'); - -// create the dataset -$Dataset2 = & Image_Graph::factory('dataset'); -$Dataset2->addPoint('Beer', rand(1, 10), 'beer'); -$Dataset2->addPoint('Wine', rand(1, 10), 'wine'); -$Dataset2->addPoint('Alcohol', rand(1, 10), 'alcohol'); -$Dataset2->addPoint('Coffee', rand(1, 10), 'coffee'); -$Dataset2->addPoint('Milk', rand(1, 10), 'milk'); -$Dataset2->addPoint('Water', rand(1, 10), 'water'); - -// create the plot as pie chart using the dataset -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Pie', array(array(&$Dataset, &$Dataset2))); -$Plotarea->hideAxis(); - -// create a Y data value marker -$Marker =& $Plot->addNew('Image_Graph_Marker_Value', IMAGE_GRAPH_PCT_Y_TOTAL); -// fill it with white -$Marker->setFillColor('white'); -// and use black border -$Marker->setBorderColor('black'); -// and format it using a data preprocessor -$Marker->setDataPreprocessor(Image_Graph::factory('Image_Graph_DataPreprocessor_Formatted', '%0.1f%%')); -$Marker->setFontSize(7); - -// create a pin-point marker type -$PointingMarker =& $Plot->addNew('Image_Graph_Marker_Pointing_Angular', array(20, &$Marker)); -// and use the marker on the plot -$Plot->setMarker($PointingMarker); -// format value marker labels as percentage values -$Plot->Radius = 2; - -// create a fillstyle for the plot -$FillArray = & Image_Graph::factory('Image_Graph_Fill_Array'); -$Plot->setFillStyle($FillArray); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'green'), 'beef'); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'blue'), 'pork'); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'yellow'), 'poultry'); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'red'), 'camels'); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'orange'), 'other'); - - -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'dimgray', 'white'), 'beer'); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'sandybrown', 'white'), 'wine'); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'sienna', 'white'), 'alcohol'); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'powderblue', 'white'), 'coffee'); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'purple', 'white'), 'milk'); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'thistle', 'white'), 'water'); - -$Plot->explode(20, 'Beer'); - -$Plot->setLineColor('lightgrey'); - -// output the Graph -$Graph->done(); -?> diff --git a/includes/pear/Image/docs/examples/gradient_step.php b/includes/pear/Image/docs/examples/gradient_step.php deleted file mode 100644 index b4284431..00000000 --- a/includes/pear/Image/docs/examples/gradient_step.php +++ /dev/null @@ -1,77 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; -require_once 'Image/Canvas.php'; - -$Canvas =& Image_Canvas::factory('png', - array( - 'width' => 400, - 'height' => 200 - ) -); - - -// create the graph -$Graph =& Image_Graph::factory('graph', $Canvas); - -$Font =& $Graph->addNew('font', 'Verdana'); -$Font->setSize(8); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Gradient Filled Step Chart', 11)), - Image_Graph::horizontal( - $Plotarea = Image_Graph::factory('plotarea'), - Image_Graph::factory('title', array('Anybody recognize?', array('size' => 7, 'color' => 'gray@0.6', 'angle' => 270))), - 98 - ), - 5) -); - -$Grid =& $Plotarea->addNew('line_grid', array(), IMAGE_GRAPH_AXIS_Y); -$Grid->setLineColor('white@0.4'); - -$Dataset =& Image_Graph::factory('dataset'); -$Dataset->addPoint(1, 20); -$Dataset->addPoint(2, 10); -$Dataset->addPoint(3, 35); -$Dataset->addPoint(4, 5); -$Dataset->addPoint(5, 18); -$Dataset->addPoint(6, 33); -$Plot =& $Plotarea->addNew('step', array(&$Dataset)); - -$Fill =& Image_Graph::factory('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'darkgreen', 'white')); -$Plot->setFillStyle($Fill); - -$Fill =& Image_Graph::factory('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'yellow', 'darkred')); -$Plotarea->setFillStyle($Fill); - -$AxisY =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y); -$AxisY->forceMaximum(40); -$AxisY->setLabelInterval(10); - -$Graph->setBackgroundColor('green@0.2'); -$Graph->setBorderColor('black'); -$Graph->setPadding(10); - -$Plot->setBorderColor('black'); - -// output the graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/horizontal.php b/includes/pear/Image/docs/examples/horizontal.php deleted file mode 100644 index cf5812eb..00000000 --- a/includes/pear/Image/docs/examples/horizontal.php +++ /dev/null @@ -1,127 +0,0 @@ - - */ - -error_reporting(E_ALL); - -include_once 'Image/Graph.php'; -include_once 'Image/Canvas.php'; - - -$Dataset =& Image_Graph::factory('dataset', - array( - array( - 'A' => 10, - 'B' => 9, - 'C' => 4, - 'D' => 6, - 'E' => 5, - 'F' => 9, - 'G' => 11, - 'H' => 8 - ) - ) -); - -$Dataset2 =& Image_Graph::factory('dataset', - array( - array( - 'A' => 121, - 'B' => 134, - 'C' => 192, - 'D' => 213, - 'E' => 123, - 'F' => 167, - 'G' => 153, - 'H' => 149 - ) - ) -); - -$Canvas =& Image_Canvas::factory('png', array('width' => 800, 'height' => 400)); - -// create the graph -$Graph =& Image_Graph::factory('graph', &$Canvas); - -$Graph->setFont(Image_Graph::factory('font', array('Courier New'))); -$Graph->setFontSize(8); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Vertical & Horizontal Plots', 11)), - Image_Graph::vertical( - Image_Graph::horizontal( - $Plotarea = Image_Graph::factory('plotarea'), - $Plotarea2 = Image_Graph::factory('plotarea', array('category', 'axis', 'horizontal')) - ), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 7 - ) -); -$Legend->setPlotarea($Plotarea); - -$GridY =& $Plotarea->addNew('line_grid', null, IMAGE_GRAPH_AXIS_Y); - -$Plot =& $Plotarea->addNew('step', &$Dataset); -$Plot->setFillColor('blue@0.2'); -$Marker =& Image_Graph::factory('value_marker', IMAGE_GRAPH_VALUE_Y); -$Marker->setFontSize(7); -$Plot->setMarker($Marker); - -$Plot12 =& $Plotarea->addNew('line', &$Dataset2, IMAGE_GRAPH_AXIS_Y_SECONDARY); -$Plot12->setLineColor('red'); - -$Plot->setTitle('Primary axis'); -$Plot12->setTitle('Secondary axis'); - -$AxisX =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X); -$AxisX->setTitle('X Data', array('size' => 10)); - -$AxisY =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y); -$AxisY->setTitle('Y Data', array('size' => 10)); - -$AxisY2 =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y_SECONDARY); -$AxisY2->setTitle('Y2 Data', array('size' => 10)); - -$Plotarea->setFillColor('gray@0.2'); - -$GridY =& $Plotarea2->addNew('line_grid', null, IMAGE_GRAPH_AXIS_Y); - -$Plot2 =& $Plotarea2->addNew('step', &$Dataset); -$Plot2->setFillColor('blue@0.2'); -$Marker2 =& Image_Graph::factory('value_marker', IMAGE_GRAPH_VALUE_Y); -$Marker2->setFontSize(7); -$Plot2->setMarker($Marker2); - -$Plot22 =& $Plotarea2->addNew('line', &$Dataset2, IMAGE_GRAPH_AXIS_Y_SECONDARY); -$Plot22->setLineColor('red'); - -$Plot2->setTitle('Primary axis'); -$Plot22->setTitle('Secondary axis'); - -$AxisX =& $Plotarea2->getAxis(IMAGE_GRAPH_AXIS_X); -$AxisX->setTitle('X Data', array('size' => 10)); - -$AxisY =& $Plotarea2->getAxis(IMAGE_GRAPH_AXIS_Y); -$AxisY->setTitle('Y Data', array('size' => 10)); - -$AxisY2 =& $Plotarea2->getAxis(IMAGE_GRAPH_AXIS_Y_SECONDARY); -$AxisY2->setTitle('Y2 Data', array('size' => 10)); -$Plotarea2->setFillColor('gray@0.2'); - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/html_image_map.php b/includes/pear/Image/docs/examples/html_image_map.php deleted file mode 100644 index dd60fb69..00000000 --- a/includes/pear/Image/docs/examples/html_image_map.php +++ /dev/null @@ -1,108 +0,0 @@ - - */ - - -require_once 'Image/Graph.php'; -require_once 'Image/Canvas.php'; - -$Canvas =& Image_Canvas::factory('png', array('width' => 400, 'height' => 300, 'usemap' => true)); - -// This is how you get the ImageMap object, fx. to save map to file (using toHtml()) -$Imagemap = $Canvas->getImageMap(); - -// create the graph -$Graph =& Image_Graph::factory('graph', $Canvas); - // add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 90 - ) -); -$Legend->setPlotarea($Plotarea); - -$Dataset =& Image_Graph::factory('dataset'); -$Dataset2 =& Image_Graph::factory('dataset'); -$Dataset3 =& Image_Graph::factory('dataset'); - -$months = array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'); - -foreach($months as $month) { - - $Dataset->addPoint( - $month, - rand(0, 10), - array( - 'url' => 'http://pear.php.net/?month=' . $month, - 'alt' => $month, - 'target' => '_blank' - ) - ); - - $Dataset2->addPoint( - $month, - rand(11, 16), - array( - 'url' => 'http://pear.veggerby.dk/' . $month . '/', - 'alt' => 'Downloads for ' . $month, - 'target' => '_blank' - ) - ); - - $Dataset3->addPoint( - $month, - rand(-1, -10), - array( - 'url' => 'http://pear.veggerby.dk/' . $month . '/', - 'alt' => $month . ' 2005', - 'target' => '_blank', - 'htmltags' => array( - 'onMouseOver' => 'alert("Hello, World!");' - ) - ) - ); -} - -$Plot =& $Plotarea->addNew('bar', array(&$Dataset)); -$Plot->setFillColor('blue@0.2'); - -$Plot2 =& $Plotarea->addNew('line', array(&$Dataset2)); -$Plot2->setLineColor('red'); - -$Plot3 =& $Plotarea->addNew('area', array(&$Dataset3)); -$Plot3->setFillColor('yellow@0.2'); - -// output the Graph -$output = $Graph->done( - array( - 'tohtml' => true, - 'border' => 0, - 'filename' => 'imagemap.png', - 'filepath' => './', - 'urlpath' => '' - ) -); - -print $output . '

' . htmlspecialchars($output) . '
'; -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/image_fill.php b/includes/pear/Image/docs/examples/image_fill.php deleted file mode 100644 index a378e98c..00000000 --- a/includes/pear/Image/docs/examples/image_fill.php +++ /dev/null @@ -1,85 +0,0 @@ - - */ - - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); - -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 8 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Image Filling / Data Preprocessing', 11)), - $Plotarea = Image_Graph::factory('plotarea'), - 8 - ) -); - -// create a Y grid -$GridY =& $Plotarea->addNew('bar_grid', IMAGE_GRAPH_AXIS_Y); -// that is light gray in color -$GridY->setFillColor('lightgrey'); - -// create the 1st dataset -$Dataset1 =& Image_Graph::factory('random', array(8, 70, 100, false)); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot1 =& $Plotarea->addNew('Image_Graph_Plot_Smoothed_Area', array(&$Dataset1)); -// create a vertical gradient fill using red and yellow, ie bottom of graph -// will be yellow and the "higher" the value the more red it will be, ie a "fire" effect -$Plot1->setFillStyle(Image_Graph::factory('Image_Graph_Fill_Image', './images/mountain.jpg')); - -// create a Y data value marker -$Marker =& $Plot1->addNew('Image_Graph_Marker_Value', IMAGE_GRAPH_PCT_Y_MAX); -// fill it with white -$Marker->setFillColor('white'); -// and use black border -$Marker->setBorderColor('black'); -// create a pin-point marker type -$PointingMarker =& $Plot1->addNew('Image_Graph_Marker_Pointing_Angular', array(20, &$Marker)); -// and use the marker on the 1st plot -$Plot1->setMarker($PointingMarker); -// format value marker labels as percentage values -$Marker->setDataPreProcessor(Image_Graph::factory('Image_Graph_DataPreprocessor_Formatted', '%0.1f%%')); - -// create the 2nd dataset -$Dataset2 =& Image_Graph::factory('random', array(8, 30, 80, false)); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot2 =& $Plotarea->addNew('bar', array(&$Dataset2)); -// create a vertical gradient fill using red and yellow, ie bottom of graph -// will be yellow and the 'higher' the value the more red it will be, ie a 'fire' effect -$Plot2->setFillColor('orange@0.6'); - -// Show arrow heads on the axis -$AxisX =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X); -$AxisY =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y); -$AxisX->showArrow(); -$AxisY->showArrow(); - -$AxisX->setDataPreProcessor(Image_Graph::factory('Image_Graph_DataPreprocessor_RomanNumerals')); -$AxisY->setDataPreProcessor(Image_Graph::factory('Image_Graph_DataPreprocessor_NumberText')); -$AxisY->forceMinimum(10); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/imagemap.png b/includes/pear/Image/docs/examples/imagemap.png deleted file mode 100644 index 7b72d3e265615c8f469f3dcccedf0d7f773d6ae9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8737 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 I6aw}CKX&cD>i_@% diff --git a/includes/pear/Image/docs/examples/images/audi-tt-coupe.jpg b/includes/pear/Image/docs/examples/images/audi-tt-coupe.jpg deleted file mode 100644 index 8a7d920a396dc7a24a989b9ce71de2fe6541b0aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 93601 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 z�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 diff --git a/includes/pear/Image/docs/examples/images/bmw.png b/includes/pear/Image/docs/examples/images/bmw.png deleted file mode 100644 index c9587638127e541b6dcb4791a465d1c503219881..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1684 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 diff --git a/includes/pear/Image/docs/examples/images/modify.jpg b/includes/pear/Image/docs/examples/images/modify.jpg deleted file mode 100644 index d5494d29dc766d1e2248f88124ddff9500210478..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 87978 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 I{&)U=0l9P$FaQ7m diff --git a/includes/pear/Image/docs/examples/images/mountain.jpg b/includes/pear/Image/docs/examples/images/mountain.jpg deleted file mode 100644 index 754acd4b637e7cf7e0a2be7b7ff14f9026ab3352..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22009 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 diff --git a/includes/pear/Image/docs/examples/index.html b/includes/pear/Image/docs/examples/index.html deleted file mode 100644 index d5f72538..00000000 --- a/includes/pear/Image/docs/examples/index.html +++ /dev/null @@ -1 +0,0 @@ -Image_Graph Examplesantialias.php
antialias.php
axis_direction.php
axis_direction.php
category_axis_explanation.php
category_axis_explanation.php
color_chart.php
color_chart.php
customize.php
customize.php
datapreprocessor.php
datapreprocessor.php
double_category_axis.php
double_category_axis.php
driver_pdf.php
driver_pdf.php
driver_png_svg.php
driver_png_svg.php
driver_swf01.php
driver_swf01.php
driver_swf02.php
driver_swf02.php
driver_swf03.php
driver_swf03.php
frontpage_sample.php
frontpage_sample.php
gradient_fill_area.php
gradient_fill_area.php
gradient_pie.php
gradient_pie.php
gradient_step.php
gradient_step.php
html_image_map.php
html_image_map.php
image_fill.php
image_fill.php
layout_matrix.php
layout_matrix.php
line_break.php
line_break.php
logo_graph.php
logo_graph.php
log_axis.php
log_axis.php
log_axis_intersect.php
log_axis_intersect.php
manual_labels.php
manual_labels.php
misc01.php
misc01.php
misc02.php
misc02.php
misc03.php
misc03.php
misc04.php
misc04.php
misc05.php
misc05.php
misc06.php
misc06.php
multiple_plots.php
multiple_plots.php
negative_values.php
negative_values.php
plot_all.php
plot_all.php
plot_all_horizontal.php
plot_all_horizontal.php
plot_all_horizontal_invert.php
plot_all_horizontal_invert.php
plot_area.php
plot_area.php
plot_area_smooth.php
plot_area_smooth.php
plot_area_stack.php
plot_area_stack.php
plot_band.php
plot_band.php
plot_bar.php
plot_bar.php
plot_bar_horizontal.php
plot_bar_horizontal.php
plot_bar_multiple.php
plot_bar_multiple.php
plot_bar_stacked.php
plot_bar_stacked.php
plot_bar_stacked100pct.php
plot_bar_stacked100pct.php
plot_bar_stacked_horizontal.php
plot_bar_stacked_horizontal.php
plot_bar_stacked_negative.php
plot_bar_stacked_negative.php
plot_boxwhisker.php
plot_boxwhisker.php
plot_candlestick.php
plot_candlestick.php
plot_impulse.php
plot_impulse.php
plot_impulse_stacked.php
plot_impulse_stacked.php
plot_line.php
plot_line.php
plot_line_smooth.php
plot_line_smooth.php
plot_map.php
plot_map.php
plot_odo.php
plot_odo.php
plot_pie.php
plot_pie.php
plot_pie_rotate.php
plot_pie_rotate.php
plot_radar.php
plot_radar.php
plot_radar_smooth.php
plot_radar_smooth.php
plot_scatter.php
plot_scatter.php
plot_scatter_linefit.php
plot_scatter_linefit.php
plot_step.php
plot_step.php
secondary_axis.php
secondary_axis.php
simple.php
simple.php
simple_graph.php
simple_graph.php
small_pie_plot.php
small_pie_plot.php
vector_function.php
vector_function.php
\ No newline at end of file diff --git a/includes/pear/Image/docs/examples/layout_matrix.php b/includes/pear/Image/docs/examples/layout_matrix.php deleted file mode 100644 index 848b4bc0..00000000 --- a/includes/pear/Image/docs/examples/layout_matrix.php +++ /dev/null @@ -1,49 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(600, 400)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(7); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Matrix Layout', 10)), - $Matrix = Image_Graph::factory('Image_Graph_Layout_Matrix', array(3, 3)), - 5 - ) -); - -for ($i = 0; $i < 9; $i++) { - $Dataset =& Image_Graph::factory('random', array(5, 2, 15, false)); - $Plotarea =& $Matrix->getEntry($i % 3, floor($i / 3)); - $Plotarea->addNew('line_grid', false, IMAGE_GRAPH_AXIS_X); - $Plotarea->addNew('line_grid', false, IMAGE_GRAPH_AXIS_Y); - - $Plot =& $Plotarea->addNew('line', $Dataset); - $Plot->setLineColor('red'); - $Plot->setTitle("x^2"); -} - -$Graph->done(); -?> diff --git a/includes/pear/Image/docs/examples/line_break.php b/includes/pear/Image/docs/examples/line_break.php deleted file mode 100644 index 742bb60d..00000000 --- a/includes/pear/Image/docs/examples/line_break.php +++ /dev/null @@ -1,78 +0,0 @@ - - */ - - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); - -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(10); - -$Graph->setFont($Font); - -// setup the plotarea, legend and their layout -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Data \'Break\' Sample', 12)), - Image_Graph::vertical( - Image_Graph::vertical( - $Plotarea1 = Image_Graph::factory('plotarea'), - $Plotarea2 = Image_Graph::factory('plotarea'), - 50 - ), - $Legend = Image_Graph::factory('legend'), - 88 - ), - 5 - ) -); - -// link the legend with the plotares -$Legend->setPlotarea($Plotarea1); -$Legend->setPlotarea($Plotarea2); - -// create the dataset -$Dataset =& Image_Graph::factory('dataset'); -$Dataset->addPoint('Jan', 10); -$Dataset->addPoint('Feb', 12); -$Dataset->addPoint('Mar', 3); -$Dataset->addPoint('Apr', null); -$Dataset->addPoint('May', 4); -$Dataset->addPoint('Jun', 10); -$Dataset->addPoint('Jul', null); -$Dataset->addPoint('Aug', null); -$Dataset->addPoint('Sep', 9); -$Dataset->addPoint('Oct', 10); -$Dataset->addPoint('Nov', 4); -$Dataset->addPoint('Dec', 14); - -// create the line plot -$Plot1 =& $Plotarea1->addNew('line', array(&$Dataset)); -// set line color -$Plot1->setLineColor('red'); - -// create the line plot -$Plot2 =& $Plotarea2->addNew('smooth_line', array(&$Dataset)); -// set line color -$Plot2->setLineColor('blue'); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/log_axis.php b/includes/pear/Image/docs/examples/log_axis.php deleted file mode 100644 index 6df4ef66..00000000 --- a/includes/pear/Image/docs/examples/log_axis.php +++ /dev/null @@ -1,104 +0,0 @@ - - */ - - -require_once 'Image/Graph.php'; -require_once 'Image/Canvas.php'; - -$Canvas =& Image_Canvas::factory('png', array('width' => 600, 'height' => 400, 'antialias' => true)); - -// create the graph -$Graph =& Image_Graph::factory('graph', $Canvas); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 15 pixels -$Font->setSize(8); -// add a title using the created font - -for ($i = 0; $i < 2; $i++) { - for ($j = 0; $j < 2; $j++) { - $Axis['X'][($i*2+$j)] = 'axis' . ($i % 2 == 0 ? '' : '_log'); - $Axis['Y'][($i*2+$j)] = 'axis' . ($j % 2 == 0 ? '' : '_log'); - } -} - -for ($i = 0; $i < 4; $i++) { - $Plotarea[$i] =& Image_Graph::factory('plotarea', array($Axis['X'][$i], $Axis['Y'][$i])); -} - -$Graph->setFont($Font); -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Logarithmic Axis', 11)), - Image_Graph::vertical( - Image_Graph::horizontal( - Image_Graph::vertical( - Image_Graph::factory('title', array('Normal Y-Axis', array('size' => 10, 'angle' => 90))), - Image_Graph::factory('title', array('Logarithmic Y-Axis', array('size' => 10, 'angle' => 90))) - ), - Image_Graph::horizontal( - Image_Graph::vertical( - Image_Graph::factory('title', array('Normal X-Axis', 10)), - Image_Graph::vertical( - $Plotarea[0], - $Plotarea[1] - ), - 7 - ), - Image_Graph::vertical( - Image_Graph::factory('Image_Graph_Title', array('Logarithmic X-Axis', 10)), - Image_Graph::vertical( - $Plotarea[2], - $Plotarea[3] - ), - 7 - ) - ), - 4 - ), - $Legend = Image_Graph::factory('Image_Graph_Legend'), - 92 - ), - 5 - ) -); -$Legend->setPlotarea($Plotarea[0]); - -$Dataset = Image_Graph::factory('dataset'); -$i = 1; -while ($i <= 10) { - $Dataset->addPoint($i, $i*$i); - $i++; -} - -for ($i = 0; $i < 4; $i++) { - $Plotarea[$i]->addNew('line_grid', false, IMAGE_GRAPH_AXIS_X); - $Plotarea[$i]->addNew('line_grid', false, IMAGE_GRAPH_AXIS_Y); - - if ($i % 2 == 1) { - $Axis =& $Plotarea[$i]->getAxis(IMAGE_GRAPH_AXIS_Y); - $Axis->setLabelInterval(array(1, 2, 3, 5, 10, 20, 30, 50, 100)); - } - - - $Plot =& $Plotarea[$i]->addNew('line', array(&$Dataset)); - $Plot->setLineColor('red'); - $Plot->setTitle("x^2"); -} - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/log_axis_intersect.php b/includes/pear/Image/docs/examples/log_axis_intersect.php deleted file mode 100644 index b0b30740..00000000 --- a/includes/pear/Image/docs/examples/log_axis_intersect.php +++ /dev/null @@ -1,106 +0,0 @@ - - */ - - -require_once 'Image/Graph.php'; -require_once 'Image/Canvas.php'; - -$Canvas =& Image_Canvas::factory('png', array('width' => 600, 'height' => 400, 'antialias' => true)); - -// create the graph -$Graph =& Image_Graph::factory('graph', $Canvas); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 15 pixels -$Font->setSize(8); -// add a title using the created font - -for ($i = 0; $i < 2; $i++) { - for ($j = 0; $j < 2; $j++) { - $Axis['X'][($i*2+$j)] = 'axis' . ($i % 2 == 0 ? '' : '_log'); - $Axis['Y'][($i*2+$j)] = 'axis' . ($j % 2 == 0 ? '' : '_log'); - } -} - -for ($i = 0; $i < 4; $i++) { - $Plotarea[$i] =& Image_Graph::factory('plotarea', array($Axis['X'][$i], $Axis['Y'][$i])); -} - -$Graph->setFont($Font); -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Logarithmic Axis', 11)), - Image_Graph::vertical( - Image_Graph::horizontal( - Image_Graph::vertical( - Image_Graph::factory('title', array('Normal Y-Axis', array('size' => 10, 'angle' => 90))), - Image_Graph::factory('title', array('Logarithmic Y-Axis', array('size' => 10, 'angle' => 90))) - ), - Image_Graph::horizontal( - Image_Graph::vertical( - Image_Graph::factory('title', array('Normal X-Axis', 10)), - Image_Graph::vertical( - $Plotarea[0], - $Plotarea[1] - ), - 7 - ), - Image_Graph::vertical( - Image_Graph::factory('Image_Graph_Title', array('Logarithmic X-Axis', 10)), - Image_Graph::vertical( - $Plotarea[2], - $Plotarea[3] - ), - 7 - ) - ), - 4 - ), - $Legend = Image_Graph::factory('Image_Graph_Legend'), - 92 - ), - 5 - ) -); -$Legend->setPlotarea($Plotarea[0]); - -$Dataset = Image_Graph::factory('dataset'); -$i = 1; -while ($i <= 10) { - $Dataset->addPoint($i, $i*$i); - $i++; -} - -for ($i = 0; $i < 4; $i++) { - $Plotarea[$i]->addNew('line_grid', false, IMAGE_GRAPH_AXIS_X); - $Plotarea[$i]->addNew('line_grid', false, IMAGE_GRAPH_AXIS_Y); - - if ($i % 2 == 1) { - $Axis =& $Plotarea[$i]->getAxis(IMAGE_GRAPH_AXIS_Y); - $Axis->setLabelInterval(array(1, 2, 3, 5, 10, 20, 30, 50, 100)); - } - - $AxisX =& $Plotarea[$i]->getAxis(IMAGE_GRAPH_AXIS_X); - $AxisX->setAxisIntersection('max'); - - $Plot =& $Plotarea[$i]->addNew('line', array(&$Dataset)); - $Plot->setLineColor('red'); - $Plot->setTitle("x^2"); -} - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/logo_graph.php b/includes/pear/Image/docs/examples/logo_graph.php deleted file mode 100644 index e6f97df2..00000000 --- a/includes/pear/Image/docs/examples/logo_graph.php +++ /dev/null @@ -1,194 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -require_once 'Image/Canvas.php'; - -// create a new GD canvas -$Canvas =& Image_Canvas::factory('png', - array( - 'width' => 600, - 'height' => 400 - ) -); - -// create the graph -$Graph =& Image_Graph::factory('graph', $Canvas); - -$Font =& $Graph->addNew('font', 'Verdana'); -$Font->setSize(8); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Weather Conditions', 12)), - Image_Graph::vertical( - $Plotarea_Weather = Image_Graph::factory('plotarea'), - $Legend_Weather = Image_Graph::factory('legend'), - 85 - ), - 7) -); -$Legend_Weather->setPlotarea($Plotarea_Weather); -$Legend_Weather->setFontSize(7); - -/* $GridY_Weather =& $Plotarea_Weather->addNew( - 'line_grid', - null, - IMAGE_GRAPH_AXIS_Y - ); - $GridY_Weather->setLineColor('gray@0.1'); - - $Marker_AverageSpan =& - $Plotarea_Weather->addNew( - 'Image_Graph_Axis_Marker_Area', - IMAGE_GRAPH_AXIS_Y - ); - $Marker_AverageSpan->setFillColor('green@0.2'); - $Marker_AverageSpan->setLowerBound(3.8); - $Marker_AverageSpan->setUpperBound(11.4); - - $Marker_Average =& - $Plotarea_Weather->addNew( - 'Image_Graph_Axis_Marker_Line', - IMAGE_GRAPH_AXIS_Y - ); - $Marker_Average->setLineColor('blue@0.4'); - $Marker_Average->setValue(7.7);*/ - -$Dataset_Rainfall =& Image_Graph::factory('dataset'); -$Dataset_Rainfall->addPoint('Jan', 60); -$Dataset_Rainfall->addPoint('Feb', 41); -$Dataset_Rainfall->addPoint('Mar', 48); -$Dataset_Rainfall->addPoint('Apr', 42); -$Dataset_Rainfall->addPoint('May', 50); -$Dataset_Rainfall->addPoint('Jun', 55); -$Dataset_Rainfall->addPoint('Jul', 67); -$Dataset_Rainfall->addPoint('Aug', 65); -$Dataset_Rainfall->addPoint('Sep', 72); -$Dataset_Rainfall->addPoint('Oct', 77); -$Dataset_Rainfall->addPoint('Nov', 80); -$Dataset_Rainfall->addPoint('Dec', 68); -$Plot_Rainfall =& - $Plotarea_Weather->addNew( - 'bar', - array(&$Dataset_Rainfall), - IMAGE_GRAPH_AXIS_Y_SECONDARY - ); -$Plot_Rainfall->setLineColor('gray'); -$Plot_Rainfall->setFillStyle(Image_Graph::factory('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', '#7AB025'))); -$Plot_Rainfall->setTitle('Average rainfall'); - -$Dataset_TempAvg =& Image_Graph::factory('dataset'); -$Dataset_TempAvg->addPoint('Jan', 0.2); -$Dataset_TempAvg->addPoint('Feb', 0.1); -$Dataset_TempAvg->addPoint('Mar', 2.3); -$Dataset_TempAvg->addPoint('Apr', 5.8); -$Dataset_TempAvg->addPoint('May', 10.8); -$Dataset_TempAvg->addPoint('Jun', 14.1); -$Dataset_TempAvg->addPoint('Jul', 16.2); -$Dataset_TempAvg->addPoint('Aug', 15.9); -$Dataset_TempAvg->addPoint('Sep', 12.1); -$Dataset_TempAvg->addPoint('Oct', 8.7); -$Dataset_TempAvg->addPoint('Nov', 4.4); -$Dataset_TempAvg->addPoint('Dec', 1.8); -$Plot_TempAvg =& - $Plotarea_Weather->addNew( - 'Image_Graph_Plot_Smoothed_Line', - array(&$Dataset_TempAvg) - ); -$Plot_TempAvg->setLineColor('#7AB025'); -$Plot_TempAvg->setTitle('Average temperature'); - -$Dataset_TempMin =& Image_Graph::factory('dataset'); -$Dataset_TempMin->addPoint('Jan', -2.7); -$Dataset_TempMin->addPoint('Feb', -2.8); -$Dataset_TempMin->addPoint('Mar', -0.9); -$Dataset_TempMin->addPoint('Apr', 1.2); -$Dataset_TempMin->addPoint('May', 5.5); -$Dataset_TempMin->addPoint('Jun', 9.2); -$Dataset_TempMin->addPoint('Jul', 11.3); -$Dataset_TempMin->addPoint('Aug', 11.1); -$Dataset_TempMin->addPoint('Sep', 7.8); -$Dataset_TempMin->addPoint('Oct', 5.0); -$Dataset_TempMin->addPoint('Nov', 1.5); -$Dataset_TempMin->addPoint('Dec', -0.9); -$Plot_TempMin =& - $Plotarea_Weather->addNew( - 'Image_Graph_Plot_Smoothed_Line', - array(&$Dataset_TempMin) - ); -$Plot_TempMin->setLineColor('gray'); -$Plot_TempMin->setTitle('Minimum temperature'); - -$Dataset_TempMax =& Image_Graph::factory('dataset'); -$Dataset_TempMax->addPoint('Jan', 2.4); -$Dataset_TempMax->addPoint('Feb', 2.5); -$Dataset_TempMax->addPoint('Mar', 5.4); -$Dataset_TempMax->addPoint('Apr', 10.5); -$Dataset_TempMax->addPoint('May', 15.8); -$Dataset_TempMax->addPoint('Jun', 18.9); -$Dataset_TempMax->addPoint('Jul', 21.2); -$Dataset_TempMax->addPoint('Aug', 20.8); -$Dataset_TempMax->addPoint('Sep', 16.3); -$Dataset_TempMax->addPoint('Oct', 11.8); -$Dataset_TempMax->addPoint('Nov', 6.9); -$Dataset_TempMax->addPoint('Dec', 4.1); -$Plot_TempMax =& - $Plotarea_Weather->addNew( - 'Image_Graph_Plot_Smoothed_Line', - array(&$Dataset_TempMax) - ); -$Plot_TempMax->setLineColor('black'); -$Plot_TempMax->setTitle('Maximum temperature'); - -$DataPreprocessor_MM =& - Image_Graph::factory('Image_Graph_DataPreprocessor_Formatted', '%d mm'); -$DataPreprocessor_DegC =& - Image_Graph::factory('Image_Graph_DataPreprocessor_Formatted', '%d C'); - -$Marker_Rainfall =& - $Plot_Rainfall->addNew('Image_Graph_Marker_Value', IMAGE_GRAPH_VALUE_Y); -$Marker_Rainfall->setDataPreprocessor($DataPreprocessor_MM); -$Marker_Rainfall->setFontSize(7); -$PointingMarker_Rainfall =& - $Plot_Rainfall->addNew( - 'Image_Graph_Marker_Pointing_Angular', - array(20, &$Marker_Rainfall) - ); -$Plot_Rainfall->setMarker($PointingMarker_Rainfall); - -$AxisY_Weather =& $Plotarea_Weather->getAxis(IMAGE_GRAPH_AXIS_Y); -$AxisY_Weather->showLabel(IMAGE_GRAPH_LABEL_ZERO); -$AxisY_Weather->setDataPreprocessor($DataPreprocessor_DegC); -$AxisY_Weather->setTitle('Temperature', array('angle' => 90, 'size' => 10)); -$AxisY_Weather->forceMinimum(-4); - -$AxisYsecondary_Weather =& - $Plotarea_Weather->getAxis(IMAGE_GRAPH_AXIS_Y_SECONDARY); -$AxisYsecondary_Weather->setDataPreprocessor($DataPreprocessor_MM); -$AxisYsecondary_Weather->setTitle('Rainfall', array('angle' => 270, 'size' => 10)); - -$AxisX_Weather =& - $Plotarea_Weather->getAxis(IMAGE_GRAPH_AXIS_X); -$AxisX_Weather->setAxisIntersection('min'); - -//$Graph->setBackgroundColor('#F7F9F9'); -// output the graph using the GD canvas -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/manual_labels.php b/includes/pear/Image/docs/examples/manual_labels.php deleted file mode 100644 index a1dbfc61..00000000 --- a/includes/pear/Image/docs/examples/manual_labels.php +++ /dev/null @@ -1,42 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(500, 200)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -$Plotarea =& $Graph->addNew('plotarea'); - -$Dataset =& Image_Graph::factory('random', array(8, 1, 10)); -$Plot =& $Plotarea->addNew('line', array(&$Dataset)); - -$LineStyle =& Image_Graph::factory('Image_Graph_Line_Dashed', array('red', 'transparent')); -//$Plot->setLineColor('red'); -$Plot->setLineStyle($LineStyle); - -$AxisY =& $Plotarea->getAxis('y'); -$AxisY->setLabelInterval(array(2, 4, 9)); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/misc01.php b/includes/pear/Image/docs/examples/misc01.php deleted file mode 100644 index 1cac6138..00000000 --- a/includes/pear/Image/docs/examples/misc01.php +++ /dev/null @@ -1,197 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('Image_Graph', array(600, 400)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -$Dataset_SmoothedLine =& Image_Graph::factory('dataset'); -$Dataset_SmoothedLine->addPoint('DK', 6); -$Dataset_SmoothedLine->addPoint('UK', 8); -$Dataset_SmoothedLine->addPoint('PO', 2); -$Dataset_SmoothedLine->addPoint('NL', 4); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('A Sample Demonstrating Many-a-thing', 15)), - Image_Graph::vertical( - Image_Graph::horizontal( - $Plotarea_BarAndLine = Image_Graph::factory('plotarea'), - Image_Graph::vertical( - $Plotarea_SmoothedLine = Image_Graph::factory('plotarea'), - $Plotarea_Radar = Image_Graph::factory('Image_Graph_Plotarea_Radar') - ), - 65 - ), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 9 - ) -); - -$Legend->setPlotarea($Plotarea_BarAndLine); -$Legend->setPlotarea($Plotarea_SmoothedLine); -$Legend->setPlotarea($Plotarea_Radar); - -// $Plotarea_SmoothedLine->setFillStyle(Image_Graph::factory('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'lightred', 'brown'))); -$Plotarea_SmoothedLine->setBorderColor('black'); -$Plotarea_SmoothedLine->showShadow(); -$Plotarea_SmoothedLine->setPadding(15); -$Plotarea_SmoothedLine->setBackground(Image_Graph::factory('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'brown'))); - -// create a Y grid -$Grid_Radar =& $Plotarea_Radar->addNew('line_grid', IMAGE_GRAPH_AXIS_Y); -$Grid_Radar->setLineColor('lightgrey'); - -// create a Y grid -$Grid_BarAndLine =& $Plotarea_BarAndLine->addNew('bar_grid', IMAGE_GRAPH_AXIS_Y); -// that is light gray in color -$Grid_BarAndLine->setFillColor('blue@0.3'); - -// create a Y grid -$Grid_SmoothedLine =& $Plotarea_SmoothedLine->addNew('line_grid', false, IMAGE_GRAPH_AXIS_Y); -$Grid_SmoothedLine->setLineColor('gray'); -$Grid_SmoothedLine =& $Plotarea_SmoothedLine->addNew('line_grid', false, IMAGE_GRAPH_AXIS_X); -$Grid_SmoothedLine->setLineColor('gray'); - -// create the 1st dataset -//$Dataset_SmoothedLine =& new Image_RandomDataset(4, 2, 15, true); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot_SmoothedLine =& $Plotarea_SmoothedLine->addNew('Image_Graph_Plot_Smoothed_Line', $Dataset_SmoothedLine); -$Plot_SmoothedLine->setLineColor('orange'); - -// create a 3rd dataset -$Dataset_BarChart =& Image_Graph::factory('random', array(7, 10, 120, false)); -// create the 3rd plot as line chart using the 2nd dataset -$Plot_BarChart =& $Plotarea_BarAndLine->addNew('bar', array(&$Dataset_BarChart)); -// set the fill style of the barchart to the almost transparent BlueAlpha -$FillArray =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Plot_BarChart->setFillStyle($FillArray); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'red')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_HORIZONTAL, 'white', 'blue')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_HORIZONTAL_MIRRORED, 'orange', 'white')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL_MIRRORED, 'green', 'white')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'purple')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_DIAGONALLY_TL_BR, 'white', 'brown')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_DIAGONALLY_BL_TR, 'white', 'black')); - -// create the 2nd dataset -$Dataset_LineMarker =& Image_Graph::factory('random', array(7, 20, 100, false)); -// create the 2nd plot as line chart using the 2nd dataset -$Plot_LineMarker =& $Plotarea_BarAndLine->addNew('line', array(&$Dataset_LineMarker)); - -$LineStyle =& Image_Graph::factory('Image_Graph_Line_Dotted', array('black', 'transparent')); -$Plot_LineMarker->setLineStyle($LineStyle); - -$Marker =& Image_Graph::factory('Image_Graph_Marker_Array'); -$CrossMarker =& Image_Graph::factory('Image_Graph_Marker_Cross'); -$PlusMarker =& Image_Graph::factory('Image_Graph_Marker_Plus'); -$StarMarker =& Image_Graph::factory('Image_Graph_Marker_Star'); -$Marker->add($CrossMarker); -$Marker->add($PlusMarker); -$Marker->add($StarMarker); -$Plot_LineMarker->setMarker($Marker); - -$CrossMarker->setLineColor('black'); -$CrossMarker->setFillColor('green'); -$PlusMarker->setLineColor('black'); -$PlusMarker->setFillColor('red'); -$StarMarker->setLineColor('black@0.4'); -$StarMarker->setFillColor('yellow'); - -// Show arrow heads on the axis -$AxisX =& $Plotarea_BarAndLine->getAxis(IMAGE_GRAPH_AXIS_X); -$AxisY =& $Plotarea_BarAndLine->getAxis(IMAGE_GRAPH_AXIS_Y); - -$AxisY->setLabelInterval(5, 2); -$AxisY->setTickOptions(-1, 1, 2); - -// create an data label array for formatting label data based on an array -$ArrayData =& Image_Graph::factory('Image_Graph_DataPreprocessor_Array', - array( - array( - 1=>'A Point', - 2=>'Another', - 6=>'Yet another' - ) - ) -); - -// use the data label array on the X axis -$AxisX->setDataPreprocessor($ArrayData); -$AxisX->setFontAngle('vertical'); -$AxisX->setTitle('Very obvious', array('angle' => 0, 'size' => 10)); - -$Plotarea_BarAndLine->setAxisPadding(array('left' => 20, 'right' => 20)); - -$Plot_SmoothedLine->setTitle('Oil'); -$Plot_LineMarker->setTitle('Clearly not a good day'); -$Plot_BarChart->setTitle('Buy or Sell'); - -// create the dataset -$Dataset_Radar1 =& Image_Graph::factory('random', array(8, 1, 5)); -$Dataset_Radar2 =& Image_Graph::factory('random', array(8, 1, 5)); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot_Radar1 =& $Plotarea_Radar->addNew('Image_Graph_Plot_Radar', array(&$Dataset_Radar1)); -$Plot_Radar1->setTitle('Obscurity'); -$Plot_Radar2 =& $Plotarea_Radar->addNew('Image_Graph_Plot_Radar', array(&$Dataset_Radar2)); -$Plot_Radar2->setTitle('Clarity'); - -//$Dataset_Radar1->setMaximumY(7); - -$DataPreprocessor =& Image_Graph::factory('Image_Graph_DataPreprocessor_Array', - array( - array( - 1 => 'Irrelevance', - 2 => 'Regular', - 3 => 'Partly', - 4 => 'Relevance', - 5 => 'Something', - 6 => 'Everything', - 7 => 'Nothing', - 8 => 'Irregular' - ) - ) -); - -$AxisX =& $Plotarea_Radar->getAxis(IMAGE_GRAPH_AXIS_X); -$AxisX->setDataPreprocessor($DataPreprocessor); - -//$Plot_Radar1->setMarker(new Image_CrossMarker(), 'Marker'); -//$Plot_Radar1->setLineStyle($YELLOW); - -$AverageMarker =& Image_Graph::factory('Image_Graph_Marker_Average'); -$Plot_SmoothedLine->setMarker($AverageMarker); -$AverageMarker->setLineColor('purple'); - -// set a standard fill style -$Plot_Radar1->setFillColor('yellow@0.2'); -$Plot_Radar2->setFillColor('green@0.2'); -// output the Graph - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/misc02.php b/includes/pear/Image/docs/examples/misc02.php deleted file mode 100644 index 972ca5e9..00000000 --- a/includes/pear/Image/docs/examples/misc02.php +++ /dev/null @@ -1,117 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -function XtoYear($Value) -{ - return floor($Value+2000); -} - -function salaries($Value) -{ - // I wish! - return exp($Value)+1000; -} - -// create the graph as a 500 x 300 image -$Graph =& Image_Graph::factory('graph', array(600, 300)); -$Graph->setBackground(Image_Graph::factory('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'lightsteelblue', 'papayawhip'))); - -// create a random dataset to use for demonstrational purposes -$DataSet =& Image_Graph::factory('function', array(1, 9, 'salaries', 8)); - -$DataSet2 =& Image_Graph::factory('dataset'); -$DataSet2->addPoint('CEO', 10); -$DataSet2->addPoint('TAP', 32); -$DataSet2->addPoint('TBF', 13); -$DataSet2->addPoint('ABC', 19); -$DataSet2->addPoint('QED', 26); - -// create and set the plot font -$Font =& $Graph->addNew('font', 'Verdana'); -$Font->setSize(7); -$Graph->setFont($Font); - -// add a plot area in a vertical layout to display a title on top -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Annual income', 11)), - Image_Graph::horizontal( - $Plotarea = Image_Graph::factory('plotarea'), - Image_Graph::vertical( - $Plotarea2 = Image_Graph::factory('plotarea'), - $Legend2 = Image_Graph::factory('legend'), - 90 - ) - ), - 5 - ), - 5 -); - -$Legend2->setPlotarea($Plotarea2); - -// create a bar grid and fill it with a gradient fill white->lightgray -$Grid =& $Plotarea->addNew('bar_grid', null, IMAGE_GRAPH_AXIS_Y); -$Grid->setFillColor('gray@0.2'); - -$Plotarea->setFillColor('gray@0.2'); - -// add a line plot to the plotarea based on the function dataset -$Plot =& $Plotarea->addNew('line', array(&$DataSet)); - -// add coins-icon as marker -$Plot->setMarker(Image_Graph::factory('Image_Graph_Marker_Icon', './images/coins.png')); - -$AxisX =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X); -$AxisY =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y); - -// make x-axis start at 0 -$AxisX->forceMinimum(0); - -// make x-axis end at 9 -$AxisX->forceMaximum(9); - -// show axis arrows -$AxisY->showArrow(); - -// make y-axis have a maximum at 9.500 -$AxisY->forceMaximum(9500); - -// create a datapreprocessor to map X-values to years -$AxisX->setDataPreprocessor(Image_Graph::factory('Image_Graph_DataPreprocessor_Function', 'XtoYear')); -$AxisY->setDataPreprocessor(Image_Graph::factory('Image_Graph_DataPreprocessor_Currency', "US$")); - -$Plot2 =& $Plotarea2->addNew('pie', array(&$DataSet2)); -$Plotarea2->hideAxis(); -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'red')); -$Fill->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'blue')); -$Fill->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'yellow')); -$Fill->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'green')); -$Fill->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'orange')); -$Plot2->setFillStyle($Fill); - -$Marker2 =& $Graph->addNew('value_marker', IMAGE_GRAPH_VALUE_Y); -$Plot2->setMarker($Marker2); -$Marker2->setDataPreprocessor(Image_Graph::factory('Image_Graph_DataPreprocessor_Formatted', '%0.0f%%')); - -$Plot2->explode(20, 'TBF'); - -// output the graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/misc03.php b/includes/pear/Image/docs/examples/misc03.php deleted file mode 100644 index 530f6019..00000000 --- a/includes/pear/Image/docs/examples/misc03.php +++ /dev/null @@ -1,78 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); - -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 7 pixels -$Font->setSize(7); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Meat Export', 12)), - Image_Graph::horizontal( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 70 - ), - 5 - ) -); - -$Legend->setPlotarea($Plotarea); - -// create the 1st dataset -$Dataset1 =& Image_Graph::factory('dataset'); -$Dataset1->addPoint('Beef', rand(1, 10)); -$Dataset1->addPoint('Pork', rand(1, 10)); -$Dataset1->addPoint('Poultry', rand(1, 10)); -$Dataset1->addPoint('Camels', rand(1, 10)); -$Dataset1->addPoint('Other', rand(1, 10)); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot =& $Plotarea->addNew('pie', array(&$Dataset1)); -$Plotarea->hideAxis(); - -// create a Y data value marker -$Marker =& $Plot->addNew('Image_Graph_Marker_Value', IMAGE_GRAPH_PCT_Y_TOTAL); -// create a pin-point marker type -$PointingMarker =& $Plot->addNew('Image_Graph_Marker_Pointing_Angular', array(20, &$Marker)); -// and use the marker on the 1st plot -$Plot->setMarker($PointingMarker); -// format value marker labels as percentage values -$Marker->setDataPreprocessor(Image_Graph::factory('Image_Graph_DataPreprocessor_Formatted', '%0.1f%%')); - -$Plot->Radius = 2; - -$FillArray =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Plot->setFillStyle($FillArray); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'green')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'blue')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'yellow')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'red')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'orange')); - -$Plot->explode(5); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/misc04.php b/includes/pear/Image/docs/examples/misc04.php deleted file mode 100644 index a05a26ec..00000000 --- a/includes/pear/Image/docs/examples/misc04.php +++ /dev/null @@ -1,35 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(500, 300)); - -$Plotarea =& $Graph->addNew('plotarea'); - -$Dataset =& Image_Graph::factory('Image_Graph_Dataset_Random', array(20, 10, 100, true)); - -$Fill =& Image_Graph::factory('Image_Graph_Fill_Image', './images/audi-tt-coupe.jpg'); -$Plotarea->setFillStyle($Fill); - -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Smoothed_Area', $Dataset); - -$Plot->setFillColor('white@0.4'); - -// output the Graph -$Graph->done(); -?> diff --git a/includes/pear/Image/docs/examples/misc05.php b/includes/pear/Image/docs/examples/misc05.php deleted file mode 100644 index 3da000e4..00000000 --- a/includes/pear/Image/docs/examples/misc05.php +++ /dev/null @@ -1,146 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(600, 400)); - -$Font =& $Graph->addNew('font', 'Verdana'); -$Font->setSize(9); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::vertical( - Image_Graph::factory('title', array('Weather Conditions by Month', 12)), - Image_Graph::factory('title', array('Location: Århus, Denmark', 8)), - 80 - ), - Image_Graph::vertical( - $Plotarea_Weather = Image_Graph::factory('plotarea'), - $Legend_Weather = Image_Graph::factory('legend'), - 85 - ), - 9) -); -$Legend_Weather->setPlotarea($Plotarea_Weather); - -$GridY_Weather =& $Plotarea_Weather->addNew('line_grid', null, IMAGE_GRAPH_AXIS_Y); -$GridY_Weather->setLineColor('gray@0.1'); - -$Dataset_TempAvg =& Image_Graph::factory('dataset'); -$Dataset_TempAvg->addPoint('Jan', 0.2); -$Dataset_TempAvg->addPoint('Feb', 0.1); -$Dataset_TempAvg->addPoint('Mar', 2.3); -$Dataset_TempAvg->addPoint('Apr', 5.8); -$Dataset_TempAvg->addPoint('May', 10.8); -$Dataset_TempAvg->addPoint('Jun', 14.1); -$Dataset_TempAvg->addPoint('Jul', 16.2); -$Dataset_TempAvg->addPoint('Aug', 15.9); -$Dataset_TempAvg->addPoint('Sep', 12.1); -$Dataset_TempAvg->addPoint('Oct', 8.7); -$Dataset_TempAvg->addPoint('Nov', 4.4); -$Dataset_TempAvg->addPoint('Dec', 1.8); -$Plot_TempAvg =& $Plotarea_Weather->addNew('smooth_line', array(&$Dataset_TempAvg)); -$Plot_TempAvg->setLineColor('blue'); -$Plot_TempAvg->setTitle('Average temperature'); - -$Dataset_TempMin =& Image_Graph::factory('dataset'); -$Dataset_TempMin->addPoint('Jan', -2.7); -$Dataset_TempMin->addPoint('Feb', -2.8); -$Dataset_TempMin->addPoint('Mar', -0.9); -$Dataset_TempMin->addPoint('Apr', 1.2); -$Dataset_TempMin->addPoint('May', 5.5); -$Dataset_TempMin->addPoint('Jun', 9.2); -$Dataset_TempMin->addPoint('Jul', 11.3); -$Dataset_TempMin->addPoint('Aug', 11.1); -$Dataset_TempMin->addPoint('Sep', 7.8); -$Dataset_TempMin->addPoint('Oct', 5.0); -$Dataset_TempMin->addPoint('Nov', 1.5); -$Dataset_TempMin->addPoint('Dec', -0.9); -$Plot_TempMin =& $Plotarea_Weather->addNew('smooth_line', array(&$Dataset_TempMin)); -$Plot_TempMin->setLineColor('teal'); -$Plot_TempMin->setTitle('Minimum temperature'); - -$Dataset_TempMax =& Image_Graph::factory('dataset'); -$Dataset_TempMax->addPoint('Jan', 2.4); -$Dataset_TempMax->addPoint('Feb', 2.5); -$Dataset_TempMax->addPoint('Mar', 5.4); -$Dataset_TempMax->addPoint('Apr', 10.5); -$Dataset_TempMax->addPoint('May', 15.8); -$Dataset_TempMax->addPoint('Jun', 18.9); -$Dataset_TempMax->addPoint('Jul', 21.2); -$Dataset_TempMax->addPoint('Aug', 20.8); -$Dataset_TempMax->addPoint('Sep', 16.3); -$Dataset_TempMax->addPoint('Oct', 11.8); -$Dataset_TempMax->addPoint('Nov', 6.9); -$Dataset_TempMax->addPoint('Dec', 4.1); -$Plot_TempMax =& $Plotarea_Weather->addNew('smooth_line', array(&$Dataset_TempMax)); -$Plot_TempMax->setLineColor('red'); -$Plot_TempMax->setTitle('Maximum temperature'); - -$Marker_AverageSpan =& $Plotarea_Weather->addNew('Image_Graph_Axis_Marker_Area', IMAGE_GRAPH_AXIS_Y); -$Marker_AverageSpan->setFillColor('green@0.2'); -$Marker_AverageSpan->setLowerBound(3.8); -$Marker_AverageSpan->setUpperBound(11.4); - -$Marker_Average =& $Plotarea_Weather->addNew('Image_Graph_Axis_Marker_Line', IMAGE_GRAPH_AXIS_Y); -$Marker_Average->setLineColor('blue@0.4'); -$Marker_Average->setValue(7.7); - -$Dataset_Rainfall =& Image_Graph::factory('dataset'); -$Dataset_Rainfall->addPoint('Jan', 60); -$Dataset_Rainfall->addPoint('Feb', 41); -$Dataset_Rainfall->addPoint('Mar', 48); -$Dataset_Rainfall->addPoint('Apr', 42); -$Dataset_Rainfall->addPoint('May', 50); -$Dataset_Rainfall->addPoint('Jun', 55); -$Dataset_Rainfall->addPoint('Jul', 67); -$Dataset_Rainfall->addPoint('Aug', 65); -$Dataset_Rainfall->addPoint('Sep', 72); -$Dataset_Rainfall->addPoint('Oct', 77); -$Dataset_Rainfall->addPoint('Nov', 80); -$Dataset_Rainfall->addPoint('Dec', 68); -$Plot_Rainfall =& $Plotarea_Weather->addNew('bar', array(&$Dataset_Rainfall), IMAGE_GRAPH_AXIS_Y_SECONDARY); -$Plot_Rainfall->setLineColor('gray'); -$Plot_Rainfall->setFillColor('blue@0.1'); -$Plot_Rainfall->setTitle('Average rainfall'); - -$DataPreprocessor_MM =& Image_Graph::factory('Image_Graph_DataPreprocessor_Formatted', '%d mm'); -$DataPreprocessor_DegC =& Image_Graph::factory('Image_Graph_DataPreprocessor_Formatted', '%d C'); - -$Marker_Rainfall =& $Plot_Rainfall->addNew('Image_Graph_Marker_Value', IMAGE_GRAPH_VALUE_Y); -$Marker_Rainfall->setDataPreprocessor($DataPreprocessor_MM); -$PointingMarker_Rainfall =& $Plot_Rainfall->addNew('Image_Graph_Marker_Pointing_Angular', array(20, &$Marker_Rainfall)); -$Plot_Rainfall->setMarker($PointingMarker_Rainfall); - -$AxisX_Weather =& $Plotarea_Weather->getAxis(IMAGE_GRAPH_AXIS_X); -$AxisX_Weather->setAxisIntersection('min'); - -$AxisY_Weather =& $Plotarea_Weather->getAxis(IMAGE_GRAPH_AXIS_Y); -$AxisY_Weather->showLabel(IMAGE_GRAPH_LABEL_ZERO); -$AxisY_Weather->setDataPreprocessor($DataPreprocessor_DegC); -$AxisY_Weather->setTitle('Temperature', 'vertical'); - -$AxisYsecondary_Weather =& $Plotarea_Weather->getAxis(IMAGE_GRAPH_AXIS_Y_SECONDARY); -$AxisYsecondary_Weather->setDataPreprocessor($DataPreprocessor_MM); -$AxisYsecondary_Weather->setTitle('Rainfall', 'vertical2'); - -// output the graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/misc06.php b/includes/pear/Image/docs/examples/misc06.php deleted file mode 100644 index 2250db19..00000000 --- a/includes/pear/Image/docs/examples/misc06.php +++ /dev/null @@ -1,132 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); - -// add a TrueType font -$Arial =& $Graph->addNew('font', 'Verdana'); -// set the font size to 8 pixels -$Arial->setSize(8); -// set default font color to white -$Arial->setColor('white'); - -// make the entire graph use this font -$Graph->setFont($Arial); - -// create the graph layout -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('German Car Popularity', 11)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 7 - ) -); - -// associate the legend with the plotarea -$Legend->setPlotarea($Plotarea); - -// make the graph have a gradient filled background -$Graph->setBackground(Image_Graph::factory('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'green', 'lightblue'))); -// and a black border -$Graph->setBorderColor('black'); - -// create and populate the dataset for 'popularity' -$Dataset =& Image_Graph::factory('dataset'); -$Dataset->addPoint('Audi', 100); -$Dataset->addPoint('Mercedes', 41); -$Dataset->addPoint('Porsche', 78); -$Dataset->addPoint('BMW', 12); - -// create and populate the dataset for 'defects / 1000 units' -$Dataset2 =& Image_Graph::factory('dataset'); -$Dataset2->addPoint('Audi', 10); -$Dataset2->addPoint('Mercedes', 17); -$Dataset2->addPoint('Porsche', 12); -$Dataset2->addPoint('BMW', 21); - -// add a line grid -$GridY =& $Plotarea->addNew('line_grid', null, IMAGE_GRAPH_AXIS_Y); -// make it have a slightly transparent white color -$GridY->setLineColor('white@0.8'); - -// create the plot as bar chart using the 'popularity' dataset -$Plot =& $Plotarea->addNew('bar', array(&$Dataset)); -// set the plot title (for legends) -$Plot->setTitle('Popularity'); - -// create a fill array to make the bars have individual fill's -$FillArray =& Image_Graph::factory('Image_Graph_Fill_Array'); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'orange')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'blue')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'yellow')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'red')); - -// make the 'popularity' plot use this fillarray -$Plot->setFillStyle($FillArray); - -// create a marker array and populate it with icon markers -$Marker =& $Graph->addNew('Image_Graph_Marker_Array'); -$Marker->addNew('icon_marker', './images/audi.png'); -$Marker->addNew('icon_marker', './images/mercedes.png'); -$Marker->addNew('icon_marker', './images/porsche.png'); -$Marker->addNew('icon_marker', './images/bmw.png'); - -// make the plot use the marker array -$Plot->setMarker($Marker); - -// create the 2nd plot ('defects / 1000 units') as a line plot and associate -// it with the secondary y-axis (implicitly this creates a y-axis of the class -// Image_Graph_Axis) -$Plot2 =& $Plotarea->addNew('line', array(&$Dataset2), IMAGE_GRAPH_AXIS_Y_SECONDARY); -// set the plot title -$Plot2->setTitle('Defects'); -// and line style -$Plot2->setLineColor('gray@0.8'); - -// create a value marker to display the actual y-values -$Marker =& $Graph->addNew('value_marker', IMAGE_GRAPH_VALUE_Y); -// and make the line plot use this -$Plot2->setMarker($Marker); -// make the marker print using font-size 7 -$Marker->setFontSize(7); -// ... in blue -$Marker->setFontColor('blue'); - -// get the y-axis -$AxisY =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y); -// and create a datapreprocessor to make the labels print out as percentage valuexs -$AxisY->setDataPreprocessor(Image_Graph::factory('Image_Graph_DataPreprocessor_Formatted', '%0.0f%%')); -// force a maximum on the y-axis to 105 -$AxisY->forceMaximum(105); -// set the axis title and make it display vertically ('vertical' = down->up) -$AxisY->setTitle('Popularity', 'vertical'); - -// get the secondary y-axis -$AxisYsec =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y_SECONDARY); -// set the axis title and make it display vertically ('vertical2' = up->down) -$AxisYsec->setTitle('Defects / 1000 units', 'vertical2'); - -// output the Graph -$Graph->done(); - -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/multiple_plots.php b/includes/pear/Image/docs/examples/multiple_plots.php deleted file mode 100644 index 95016652..00000000 --- a/includes/pear/Image/docs/examples/multiple_plots.php +++ /dev/null @@ -1,82 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(600, 400)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::vertical( - $Title = Image_Graph::factory('title', array('Multiple Plots', 11)), - $SubTitle = Image_Graph::factory('title', array('This is a demonstration of title alignment', 7)), - 90 - ), - $Plotarea = Image_Graph::factory('plotarea'), - 8 - ) -); -$Title->setAlignment(IMAGE_GRAPH_ALIGN_LEFT); -$SubTitle->setAlignment(IMAGE_GRAPH_ALIGN_LEFT); - -$Grid =& $Plotarea->addNew('bar_grid', IMAGE_GRAPH_AXIS_Y); -$Grid->setFillStyle(Image_Graph::factory('gradient', array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'lightgrey'))); - -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Smoothed_Area', Image_Graph::factory('random', array(10, 20, 100, true))); -$Plot->setFillColor('red@0.2'); - -$Plot =& $Plotarea->addNew('line', Image_Graph::factory('random', array(10, 20, 100, true))); -$Plot->setLineColor('blue@0.2'); -$CircleMarker =& Image_Graph::factory('Image_Graph_Marker_Circle'); -$Plot->setMarker($CircleMarker); -$CircleMarker->setFillColor('white@0.4'); - -$Plot =& $Plotarea->addNew('bar', Image_Graph::factory('random', array(10, 2, 40, true))); -$Plot->setFillColor('green@0.2'); -$Marker =& Image_Graph::factory('Image_Graph_Marker_Value', IMAGE_GRAPH_VALUE_Y); -$Plot->setMarker($Marker); -$Marker->setFillColor('white'); -$Marker->setBorderColor('black'); - -$AxisY = $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y); -$AxisY->showArrow(); - -$Array = array( - "Jan-Feb\n2004", - "Mar-Apr\n2004", - "May-Jun\n2004", - "Jul-Aug\n2004", - "Sep-Oct\n2004", - "Nov-Dev\n2004", - "Jan-Feb\n2005", - "Mar-Apr\n2005", - "May-Jun\n2005", - "Jul-Aug\n2005" -); -$AxisX = $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X); -$AxisX->setDataPreprocessor(Image_Graph::factory('Image_Graph_DataPreprocessor_Array', array($Array))); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/negative_values.php b/includes/pear/Image/docs/examples/negative_values.php deleted file mode 100644 index 779aa724..00000000 --- a/includes/pear/Image/docs/examples/negative_values.php +++ /dev/null @@ -1,72 +0,0 @@ - - */ - - -require_once 'Image/Graph.php'; -require_once 'Image/Canvas.php'; - -$Canvas =& Image_Canvas::factory('png', array('width' => 400, 'height' => 300, 'antialias' => true)); - -// create the graph -$Graph =& Image_Graph::factory('graph', $Canvas); - // add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 90 - ) -); -$Legend->setPlotarea($Plotarea); - -$Dataset =& Image_Graph::factory('dataset'); -$Dataset->addPoint('Jan', 1); -$Dataset->addPoint('Feb', 2); -$Dataset->addPoint('Mar', -2); -$Dataset->addPoint('Apr', 4); -$Dataset->addPoint('May', 3); -$Dataset->addPoint('Jun', 6); -$Dataset->addPoint('Jul', -1); -$Dataset->addPoint('Aug', -3); -$Dataset->addPoint('Sep', 2); -$Dataset->addPoint('Oct', 3); -$Dataset->addPoint('Nov', 1); -$Dataset->addPoint('Dec', 4); - -$Dataset2 =& Image_Graph::factory('dataset'); -$Dataset2->addPoint('Jan', 3); -$Dataset2->addPoint('Feb', 4); -$Dataset2->addPoint('Mar', 1); -$Dataset2->addPoint('Apr', -2); -$Dataset2->addPoint('May', 3); -$Dataset2->addPoint('Jul', 1); - -$Plot =& $Plotarea->addNew('area', array(&$Dataset)); -$Plot->setFillColor('red@0.2'); - -$Plot2 =& $Plotarea->addNew('bar', array(&$Dataset2)); -$Plot2->setFillColor('blue@0.2'); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/pear-icon.png b/includes/pear/Image/docs/examples/pear-icon.png deleted file mode 100644 index 26118f113cee46860251f693ae8693432583aa9d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 927 zcmV;Q17Q4#P)}wZaU8($-`UPCXXfUndD(2{nwplHW?~nWoOmfJ zih?o~ipmFjkfeM0P;a6T6i85n^pH>(m_~({u8`s^$kJtPWx6drE_de6wzIRX2k9l} z{IA+ezsLXo{J)>`aQJfoLOd7%tiK+ry0!*5p=$q{e*?(FS2h&hyi(Q~5};VMuWj$U z9C=ZP?$*LxJlGtcE69--t&80fA&i`He4nAsb$Lx+W=CrumROxLe+#IjX=k>yWXBb_ zJT$}70$jxBiU8p8r#pV@!2!vUnODlX2%fOlaAU&y!3$mt!<6Fmf`qCA>2*Wq=kKQm z{v6<7+`7DGAAc$|L-RA!vWRcJbN zO#(b@_v*7;4i5ligj_Aloqu3WbZ)Lf^K!f^I6#0C*|7y0)!yyN)wJ8{WU0-{iuwA& zSsj%f1b_inrmi@Ybv99&=5SLOfQTpAlX?MPqz(WgUiiXA|9}7|&gWm>mQ-b)8|&0H zo9&-9iAPk@^*D#WSRDXJ+Jp+6-h8b*sj`2v{jKStQj$@uIuzL(riMlp1A}eruetHb|Mo8__K-{u~>dccm^3@3WVn=elLY#_Hw=>j@ zq04@^e!q*hChmz4M!hjV%8V^VtOLNLO>d+ONWjJwrAFH*?Ve3rUWix+02vWO@WPM) zwJhCe`xq{W67!?b0jY4gQj&}W5O|n_wGntYh6Qnxb2+$JAVmULuN&v^STBQK2LK=V zoGgt5j9bSd2_@y4c6t0C@H=*fnxOPZz@V{DDOuz3vEQuk(1B5MXxcuB1oRo&agI8PmaKo69_;+sy4bFtPvvU=8N(0V z_M|$>MYauJBT`^>@zrtKZ3_aRT$YBuDvQIiE9I0@vNphBJ40Q1c6fNIKfoJs z0YJXv_tjY^*{#1TBVvkIRm+Gtzb6MKd(QRj*P5ONsGB;M`gK&x(#zEcv*PmO#cCl= zuwJ)$?%VKGf4Bbbpt0BM^9HB`fVSp8_%{vt`~)fJKZgDv!iN9=002ovPDHLkV1gAM B!&m?S diff --git a/includes/pear/Image/docs/examples/plot_all.php b/includes/pear/Image/docs/examples/plot_all.php deleted file mode 100644 index 761f889f..00000000 --- a/includes/pear/Image/docs/examples/plot_all.php +++ /dev/null @@ -1,231 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -$Graph =& Image_Graph::factory('graph', array(800, 800)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Arial'); -// set the font size to 11 pixels -$Font->setSize(6); - -$Graph->setFont($Font); - -$Matrix =& $Graph->addNew('Image_Graph_Layout_Matrix', array(5, 4)); - -$Dataset =& Image_Graph::factory('random', array(10, 2, 15, false)); -$Dataset2 =& Image_Graph::factory('random', array(10, 2, 15, false)); -$Dataset3 =& Image_Graph::factory('random', array(10, 2, 15, false)); - -$Plotarea =& $Matrix->getEntry(0, 0); -$Plot =& $Plotarea->addNew('line', array(&$Dataset)); -$Plot->setLineColor('red'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Line', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(0, 1); -$Plot =& $Plotarea->addNew('area', array(&$Dataset)); -$Plot->setLineColor('gray'); -$Plot->setFillColor('blue@0.2'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Area', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(0, 2); -$Plot =& $Plotarea->addNew('bar', array(&$Dataset)); -$Plot->setLineColor('gray'); -$Plot->setFillColor('green@0.2'); -$Plot->setSpacing(2); -$Plotarea->setAxisPadding(1, 'left'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Bar', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(0, 3); -$Plot =& $Plotarea->addNew('smooth_line', array(&$Dataset)); -$Plot->setLineColor('orange'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Smoothed_Line', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(1, 0); -$Plot =& $Plotarea->addNew('smooth_area', array(&$Dataset)); -$Plot->setLineColor('purple@0.4'); -$Plot->setFillColor('purple@0.2'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Smoothed_Area', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(1, 1); -$Plot =& $Plotarea->addNew('pie', array(&$Dataset)); -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('red@0.2'); -$Fill->addColor('blue@0.2'); -$Fill->addColor('green@0.2'); -$Fill->addColor('yellow@0.2'); -$Fill->addColor('orange@0.2'); -$Fill->addColor('purple@0.2'); -$Plot->setFillStyle($Fill); -$Plot->setLineColor('gray'); -$Plotarea->hideAxis(); -$Plot->explode(10, 1); -$Plotarea->addNew('title', array('Image_Graph_Plot_Pie', array('size' => 7))); - -$Plotarea =& $Matrix->getEntry(1, 2); -$Plot =& $Plotarea->addNew('step', array(&$Dataset)); -$Plot->setLineColor('yellow@0.5'); -$Plot->setFillColor('yellow@0.3'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Step', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(1, 3); -$Plot =& $Plotarea->addNew('impulse', array(&$Dataset)); -$Plot->setLineColor('blue'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Impulse', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - - $Plotarea =& $Matrix->getEntry(2, 0); - $Plot =& $Plotarea->addNew('scatter', array(&$Dataset)); -$Marker =& $Plot->addNew('Image_Graph_Marker_Circle'); -$Marker->setSize(4); -$Marker->setLineColor('green@0.4'); -$Marker->setFillColor('green@0.2'); -$Plot->setMarker($Marker); -$Plotarea->addNew('title', array('Image_Graph_Plot_Dot', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Graph->addNew('Image_Graph_Plotarea_Radar'); -$Matrix->setEntry(2, 1, $Plotarea); -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Radar', array(&$Dataset)); -$Plot->setLineColor('orange@0.4'); -$Plot->setFillColor('orange@0.2'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Radar', array('size' => 7))); - -$Dataset1 =& Image_Graph::factory('dataset'); -$base = mktime(0, 0, 0, 11, 1, 2004); -$open = rand(20, 100); -//for ($i = 0; $i < 61; $i++) { -for ($i = 0; $i < 10; $i++) { - $span = rand(-25, 25); - $close = ($open + $span < 0 ? $open - $span : $open + $span); - $min = max(1, min($close, $open) - rand(1, 20)); - $max = max($close, $open) + rand(1, 20); - $date = $base + $i * 86400; - $Dataset1->addPoint(date('d-M', $date), array('min' => $min, 'open' => $open, 'close' => $close, 'max' => $max)); - $open = $close; -} -$Plotarea =& $Matrix->getEntry(2, 2); -$Plot =& $Plotarea->addNew('Image_Graph_Plot_CandleStick', array(&$Dataset1)); -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('red@0.4', 'red'); -$Fill->addColor('green@0.4', 'green'); -$Plot->setFillStyle($Fill); -$Axis =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X); -$Axis->setLabelInterval(3); -$Plotarea->addNew('title', array('Image_Graph_Plot_CandleStick', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(2, 3); -$Dataset1 =& Image_Graph::factory('dataset'); -for ($i = 0; $i < 40; $i++) { - $v1 = rand(5, 15); - $v2 = $v1 + rand(10, 20); - $Dataset1->addPoint($i, array('low' => $v1, 'high' => $v2)); -} -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Band', array($Dataset1)); -// set a line color -$Plot->setLineColor('gray'); -$Plot->setFillColor('teal@0.2'); -$Axis =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X); -$Axis->setLabelInterval(5); -$Plotarea->addNew('title', array('Image_Graph_Plot_Band', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(3, 0); -$Dataset1 =& Image_Graph::factory('dataset'); -for ($i = 0; $i < 4; $i++) { - $data = array(); - $min = rand(1, 10); - $max = rand(15, 30); - for ($j = 0; $j < 20; $j++) { - $data[] = rand($min, $max); - } - $Dataset1->addPoint($i, $data); -} -$Plot =& $Plotarea->addNew('Image_Graph_Plot_BoxWhisker', array($Dataset1)); -$Plot->setWhiskerSize(3); -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('red', 'min'); -$Fill->addColor('green', 'max'); -$Fill->addColor('orange@0.2', 'quartile1'); -$Fill->addColor('blue@0.2', 'median'); -$Fill->addColor('orange@0.2', 'quartile3'); -$Fill->addColor('yellow@0.1', 'box'); -$Plot->setFillStyle($Fill); -$Line =& Image_Graph::factory('Image_Graph_Line_Solid', 'black@0.6'); -$Line->setThickness(1); -$Plot->setLineStyle($Line); -$Plotarea->addNew('title', array('Image_Graph_Plot_BoxWhisker', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Graph->addNew('Image_Graph_Plotarea_Radar'); -$Matrix->setEntry(3, 1, $Plotarea); -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Smoothed_Radar', array(&$Dataset)); -$Plot->setLineColor('red@0.4'); -$Plot->setFillColor('red@0.2'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Smoothed_Radar', array('size' => 7))); - -$Plotarea =& $Matrix->getEntry(4, 0); -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Bar', array(array(&$Dataset, &$Dataset2))); -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('red@0.2'); -$Fill->addColor('blue@0.2'); -$Plot->setFillStyle($Fill); -$Plot->setSpacing(2); -$Plotarea->setAxisPadding(2, 'left'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Bar (normal)', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(4, 1); -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Area', array(array(&$Dataset, &$Dataset2, &$Dataset3), 'stacked')); -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('khaki@0.2'); -$Fill->addColor('indianred@0.2'); -$Fill->addColor('gold@0.2'); -$Plot->setFillStyle($Fill); -$Plotarea->addNew('title', array('Image_Graph_Plot_Area (stacked)', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - - $Plotarea =& $Matrix->getEntry(4, 2); - $Plot =& $Plotarea->addNew('Image_Graph_Plot_Bar', array(array(&$Dataset, &$Dataset2), 'stacked')); -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('maroon@0.5'); -$Fill->addColor('peru@0.5'); -$Plot->setFillStyle($Fill); -$Plot->setSpacing(2); -$Plotarea->setAxisPadding(1, 'left'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Bar (stacked)', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(4, 3); -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Step', array(array(&$Dataset, &$Dataset2, &$Dataset3), 'stacked100pct')); -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('orange@0.2'); -$Fill->addColor('yellow@0.2'); -$Fill->addColor('lightgrey@0.2'); -$Plot->setFillStyle($Fill); -$Plotarea->setAxisPadding(-1, 'left'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Step (stacked 100%)', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/plot_all_horizontal.php b/includes/pear/Image/docs/examples/plot_all_horizontal.php deleted file mode 100644 index 3ac05318..00000000 --- a/includes/pear/Image/docs/examples/plot_all_horizontal.php +++ /dev/null @@ -1,247 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -$Graph =& Image_Graph::factory('graph', array(800, 800)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Arial'); -// set the font size to 11 pixels -$Font->setSize(6); - -$Graph->setFont($Font); - -$Matrix =& $Graph->addNew('Image_Graph_Layout_Matrix', array(5, 4, false)); - -for ($i = 0; $i < 5; $i++) { - for ($j = 0; $j < 4; $j++) { - $Matrix->setEntry( - $i, $j, - Image_Graph::factory( - 'plotarea', - array( - 'Image_Graph_Axis_Category', - 'Image_Graph_Axis', - 'horizontal' - ) - ) - ); - } -} - -$Dataset =& Image_Graph::factory('random', array(10, 2, 15, false)); -$Dataset2 =& Image_Graph::factory('random', array(10, 2, 15, false)); -$Dataset3 =& Image_Graph::factory('random', array(10, 2, 15, false)); - -$Plotarea =& $Matrix->getEntry(0, 0); -$Plot =& $Plotarea->addNew('line', array(&$Dataset)); -$Plot->setLineColor('red'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Line', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(0, 1); -$Plot =& $Plotarea->addNew('area', array(&$Dataset)); -$Plot->setLineColor('gray'); -$Plot->setFillColor('blue@0.2'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Area', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(0, 2); -$Plot =& $Plotarea->addNew('bar', array(&$Dataset)); -$Plot->setLineColor('gray'); -$Plot->setFillColor('green@0.2'); -$Plot->setSpacing(2); -$Plotarea->setAxisPadding(1, 'left'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Bar', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(0, 3); -$Plot =& $Plotarea->addNew('smooth_line', array(&$Dataset)); -$Plot->setLineColor('orange'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Smoothed_Line', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(1, 0); -$Plot =& $Plotarea->addNew('smooth_area', array(&$Dataset)); -$Plot->setLineColor('purple@0.4'); -$Plot->setFillColor('purple@0.2'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Smoothed_Area', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(1, 1); -$Plot =& $Plotarea->addNew('pie', array(&$Dataset)); -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('red@0.2'); -$Fill->addColor('blue@0.2'); -$Fill->addColor('green@0.2'); -$Fill->addColor('yellow@0.2'); -$Fill->addColor('orange@0.2'); -$Fill->addColor('purple@0.2'); -$Plot->setFillStyle($Fill); -$Plot->setLineColor('gray'); -$Plotarea->hideAxis(); -$Plot->explode(10, 1); -$Plotarea->addNew('title', array('Image_Graph_Plot_Pie', array('size' => 7))); - -$Plotarea =& $Matrix->getEntry(1, 2); -$Plot =& $Plotarea->addNew('step', array(&$Dataset)); -$Plot->setLineColor('yellow@0.5'); -$Plot->setFillColor('yellow@0.3'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Step', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(1, 3); -$Plot =& $Plotarea->addNew('impulse', array(&$Dataset)); -$Plot->setLineColor('blue'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Impulse', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - - $Plotarea =& $Matrix->getEntry(2, 0); - $Plot =& $Plotarea->addNew('scatter', array(&$Dataset)); -$Marker =& $Plot->addNew('Image_Graph_Marker_Circle'); -$Marker->setSize(4); -$Marker->setLineColor('green@0.4'); -$Marker->setFillColor('green@0.2'); -$Plot->setMarker($Marker); -$Plotarea->addNew('title', array('Image_Graph_Plot_Dot', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Graph->addNew('Image_Graph_Plotarea_Radar'); -$Matrix->setEntry(2, 1, $Plotarea); -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Radar', array(&$Dataset)); -$Plot->setLineColor('orange@0.4'); -$Plot->setFillColor('orange@0.2'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Radar', array('size' => 7))); - -$Dataset1 =& Image_Graph::factory('dataset'); -$base = mktime(0, 0, 0, 11, 1, 2004); -$open = rand(20, 100); -//for ($i = 0; $i < 61; $i++) { -for ($i = 0; $i < 10; $i++) { - $span = rand(-25, 25); - $close = ($open + $span < 0 ? $open - $span : $open + $span); - $min = max(1, min($close, $open) - rand(1, 20)); - $max = max($close, $open) + rand(1, 20); - $date = $base + $i * 86400; - $Dataset1->addPoint(date('d-M', $date), array('min' => $min, 'open' => $open, 'close' => $close, 'max' => $max)); - $open = $close; -} -$Plotarea =& $Matrix->getEntry(2, 2); -$Plot =& $Plotarea->addNew('Image_Graph_Plot_CandleStick', array(&$Dataset1)); -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('red@0.4', 'red'); -$Fill->addColor('green@0.4', 'green'); -$Plot->setFillStyle($Fill); -$Axis =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X); -$Axis->setLabelInterval(3); -$Plotarea->addNew('title', array('Image_Graph_Plot_CandleStick', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(2, 3); -$Dataset1 =& Image_Graph::factory('dataset'); -for ($i = 0; $i < 40; $i++) { - $v1 = rand(5, 15); - $v2 = $v1 + rand(10, 20); - $Dataset1->addPoint($i, array('low' => $v1, 'high' => $v2)); -} -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Band', array($Dataset1)); -// set a line color -$Plot->setLineColor('gray'); -$Plot->setFillColor('teal@0.2'); -$Axis =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X); -$Axis->setLabelInterval(5); -$Plotarea->addNew('title', array('Image_Graph_Plot_Band', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(3, 0); -$Dataset1 =& Image_Graph::factory('dataset'); -for ($i = 0; $i < 4; $i++) { - $data = array(); - $min = rand(1, 10); - $max = rand(15, 30); - for ($j = 0; $j < 20; $j++) { - $data[] = rand($min, $max); - } - $Dataset1->addPoint($i, $data); -} -$Plot =& $Plotarea->addNew('Image_Graph_Plot_BoxWhisker', array($Dataset1)); -$Plot->setWhiskerSize(3); -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('red', 'min'); -$Fill->addColor('green', 'max'); -$Fill->addColor('orange@0.2', 'quartile1'); -$Fill->addColor('blue@0.2', 'median'); -$Fill->addColor('orange@0.2', 'quartile3'); -$Fill->addColor('yellow@0.1', 'box'); -$Plot->setFillStyle($Fill); -$Line =& Image_Graph::factory('Image_Graph_Line_Solid', 'black@0.6'); -$Line->setThickness(1); -$Plot->setLineStyle($Line); -$Plotarea->addNew('title', array('Image_Graph_Plot_BoxWhisker', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Graph->addNew('Image_Graph_Plotarea_Radar'); -$Matrix->setEntry(3, 1, $Plotarea); -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Smoothed_Radar', array(&$Dataset)); -$Plot->setLineColor('red@0.4'); -$Plot->setFillColor('red@0.2'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Smoothed_Radar', array('size' => 7))); - -$Plotarea =& $Matrix->getEntry(4, 0); -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Bar', array(array(&$Dataset, &$Dataset2))); -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('red@0.2'); -$Fill->addColor('blue@0.2'); -$Plot->setFillStyle($Fill); -$Plot->setSpacing(2); -$Plotarea->setAxisPadding(2, 'left'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Bar (normal)', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(4, 1); -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Area', array(array(&$Dataset, &$Dataset2, &$Dataset3), 'stacked')); -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('khaki@0.2'); -$Fill->addColor('indianred@0.2'); -$Fill->addColor('gold@0.2'); -$Plot->setFillStyle($Fill); -$Plotarea->addNew('title', array('Image_Graph_Plot_Area (stacked)', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - - $Plotarea =& $Matrix->getEntry(4, 2); - $Plot =& $Plotarea->addNew('Image_Graph_Plot_Bar', array(array(&$Dataset, &$Dataset2), 'stacked')); -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('maroon@0.5'); -$Fill->addColor('peru@0.5'); -$Plot->setFillStyle($Fill); -$Plot->setSpacing(2); -$Plotarea->setAxisPadding(1, 'left'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Bar (stacked)', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(4, 3); -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Step', array(array(&$Dataset, &$Dataset2, &$Dataset3), 'stacked100pct')); -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('orange@0.2'); -$Fill->addColor('yellow@0.2'); -$Fill->addColor('lightgrey@0.2'); -$Plot->setFillStyle($Fill); -$Plotarea->setAxisPadding(-1, 'left'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Step (stacked 100%)', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/plot_all_horizontal_invert.php b/includes/pear/Image/docs/examples/plot_all_horizontal_invert.php deleted file mode 100644 index 89646e65..00000000 --- a/includes/pear/Image/docs/examples/plot_all_horizontal_invert.php +++ /dev/null @@ -1,250 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -$Graph =& Image_Graph::factory('graph', array(800, 800)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Arial'); -// set the font size to 11 pixels -$Font->setSize(6); - -$Graph->setFont($Font); - -$Matrix =& $Graph->addNew('Image_Graph_Layout_Matrix', array(5, 4, false)); - -for ($i = 0; $i < 5; $i++) { - for ($j = 0; $j < 4; $j++) { - $Plotarea =& Image_Graph::factory( - 'plotarea', - array( - 'Image_Graph_Axis_Category', - 'Image_Graph_Axis', - 'horizontal' - ) - ); - $AxisX =& $Plotarea->getAxis('x'); - $AxisX->setInverted(true); - $AxisY =& $Plotarea->getAxis('y'); - $AxisY->setInverted(true); - - $Matrix->setEntry($i, $j, $Plotarea); - } -} - -$Dataset =& Image_Graph::factory('random', array(10, 2, 15, false)); -$Dataset2 =& Image_Graph::factory('random', array(10, 2, 15, false)); -$Dataset3 =& Image_Graph::factory('random', array(10, 2, 15, false)); - -$Plotarea =& $Matrix->getEntry(0, 0); -$Plot =& $Plotarea->addNew('line', array(&$Dataset)); -$Plot->setLineColor('red'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Line', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(0, 1); -$Plot =& $Plotarea->addNew('area', array(&$Dataset)); -$Plot->setLineColor('gray'); -$Plot->setFillColor('blue@0.2'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Area', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(0, 2); -$Plot =& $Plotarea->addNew('bar', array(&$Dataset)); -$Plot->setLineColor('gray'); -$Plot->setFillColor('green@0.2'); -$Plot->setSpacing(2); -$Plotarea->setAxisPadding(1, 'left'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Bar', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(0, 3); -$Plot =& $Plotarea->addNew('smooth_line', array(&$Dataset)); -$Plot->setLineColor('orange'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Smoothed_Line', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(1, 0); -$Plot =& $Plotarea->addNew('smooth_area', array(&$Dataset)); -$Plot->setLineColor('purple@0.4'); -$Plot->setFillColor('purple@0.2'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Smoothed_Area', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(1, 1); -$Plot =& $Plotarea->addNew('pie', array(&$Dataset)); -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('red@0.2'); -$Fill->addColor('blue@0.2'); -$Fill->addColor('green@0.2'); -$Fill->addColor('yellow@0.2'); -$Fill->addColor('orange@0.2'); -$Fill->addColor('purple@0.2'); -$Plot->setFillStyle($Fill); -$Plot->setLineColor('gray'); -$Plotarea->hideAxis(); -$Plot->explode(10, 1); -$Plotarea->addNew('title', array('Image_Graph_Plot_Pie', array('size' => 7))); - -$Plotarea =& $Matrix->getEntry(1, 2); -$Plot =& $Plotarea->addNew('step', array(&$Dataset)); -$Plot->setLineColor('yellow@0.5'); -$Plot->setFillColor('yellow@0.3'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Step', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(1, 3); -$Plot =& $Plotarea->addNew('impulse', array(&$Dataset)); -$Plot->setLineColor('blue'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Impulse', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - - $Plotarea =& $Matrix->getEntry(2, 0); - $Plot =& $Plotarea->addNew('scatter', array(&$Dataset)); -$Marker =& $Plot->addNew('Image_Graph_Marker_Circle'); -$Marker->setSize(4); -$Marker->setLineColor('green@0.4'); -$Marker->setFillColor('green@0.2'); -$Plot->setMarker($Marker); -$Plotarea->addNew('title', array('Image_Graph_Plot_Dot', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Graph->addNew('Image_Graph_Plotarea_Radar'); -$Matrix->setEntry(2, 1, $Plotarea); -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Radar', array(&$Dataset)); -$Plot->setLineColor('orange@0.4'); -$Plot->setFillColor('orange@0.2'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Radar', array('size' => 7))); - -$Dataset1 =& Image_Graph::factory('dataset'); -$base = mktime(0, 0, 0, 11, 1, 2004); -$open = rand(20, 100); -//for ($i = 0; $i < 61; $i++) { -for ($i = 0; $i < 10; $i++) { - $span = rand(-25, 25); - $close = ($open + $span < 0 ? $open - $span : $open + $span); - $min = max(1, min($close, $open) - rand(1, 20)); - $max = max($close, $open) + rand(1, 20); - $date = $base + $i * 86400; - $Dataset1->addPoint(date('d-M', $date), array('min' => $min, 'open' => $open, 'close' => $close, 'max' => $max)); - $open = $close; -} -$Plotarea =& $Matrix->getEntry(2, 2); -$Plot =& $Plotarea->addNew('Image_Graph_Plot_CandleStick', array(&$Dataset1)); -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('red@0.4', 'red'); -$Fill->addColor('green@0.4', 'green'); -$Plot->setFillStyle($Fill); -$Axis =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X); -$Axis->setLabelInterval(3); -$Plotarea->addNew('title', array('Image_Graph_Plot_CandleStick', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(2, 3); -$Dataset1 =& Image_Graph::factory('dataset'); -for ($i = 0; $i < 40; $i++) { - $v1 = rand(5, 15); - $v2 = $v1 + rand(10, 20); - $Dataset1->addPoint($i, array('low' => $v1, 'high' => $v2)); -} -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Band', array($Dataset1)); -// set a line color -$Plot->setLineColor('gray'); -$Plot->setFillColor('teal@0.2'); -$Axis =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X); -$Axis->setLabelInterval(5); -$Plotarea->addNew('title', array('Image_Graph_Plot_Band', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(3, 0); -$Dataset1 =& Image_Graph::factory('dataset'); -for ($i = 0; $i < 4; $i++) { - $data = array(); - $min = rand(1, 10); - $max = rand(15, 30); - for ($j = 0; $j < 20; $j++) { - $data[] = rand($min, $max); - } - $Dataset1->addPoint($i, $data); -} -$Plot =& $Plotarea->addNew('Image_Graph_Plot_BoxWhisker', array($Dataset1)); -$Plot->setWhiskerSize(3); -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('red', 'min'); -$Fill->addColor('green', 'max'); -$Fill->addColor('orange@0.2', 'quartile1'); -$Fill->addColor('blue@0.2', 'median'); -$Fill->addColor('orange@0.2', 'quartile3'); -$Fill->addColor('yellow@0.1', 'box'); -$Plot->setFillStyle($Fill); -$Line =& Image_Graph::factory('Image_Graph_Line_Solid', 'black@0.6'); -$Line->setThickness(1); -$Plot->setLineStyle($Line); -$Plotarea->addNew('title', array('Image_Graph_Plot_BoxWhisker', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Graph->addNew('Image_Graph_Plotarea_Radar'); -$Matrix->setEntry(3, 1, $Plotarea); -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Smoothed_Radar', array(&$Dataset)); -$Plot->setLineColor('red@0.4'); -$Plot->setFillColor('red@0.2'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Smoothed_Radar', array('size' => 7))); - -$Plotarea =& $Matrix->getEntry(4, 0); -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Bar', array(array(&$Dataset, &$Dataset2))); -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('red@0.2'); -$Fill->addColor('blue@0.2'); -$Plot->setFillStyle($Fill); -$Plot->setSpacing(2); -$Plotarea->setAxisPadding(2, 'left'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Bar (normal)', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(4, 1); -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Area', array(array(&$Dataset, &$Dataset2, &$Dataset3), 'stacked')); -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('khaki@0.2'); -$Fill->addColor('indianred@0.2'); -$Fill->addColor('gold@0.2'); -$Plot->setFillStyle($Fill); -$Plotarea->addNew('title', array('Image_Graph_Plot_Area (stacked)', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - - $Plotarea =& $Matrix->getEntry(4, 2); - $Plot =& $Plotarea->addNew('Image_Graph_Plot_Bar', array(array(&$Dataset, &$Dataset2), 'stacked')); -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('maroon@0.5'); -$Fill->addColor('peru@0.5'); -$Plot->setFillStyle($Fill); -$Plot->setSpacing(2); -$Plotarea->setAxisPadding(1, 'left'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Bar (stacked)', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Plotarea =& $Matrix->getEntry(4, 3); -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Step', array(array(&$Dataset, &$Dataset2, &$Dataset3), 'stacked100pct')); -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('orange@0.2'); -$Fill->addColor('yellow@0.2'); -$Fill->addColor('lightgrey@0.2'); -$Plot->setFillStyle($Fill); -$Plotarea->setAxisPadding(-1, 'left'); -$Plotarea->addNew('title', array('Image_Graph_Plot_Step (stacked 100%)', array('size' => 7))); -$Plotarea->setAxisPadding(10, 'top'); - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/plot_area.php b/includes/pear/Image/docs/examples/plot_area.php deleted file mode 100644 index e8899b05..00000000 --- a/includes/pear/Image/docs/examples/plot_area.php +++ /dev/null @@ -1,57 +0,0 @@ - - */ - - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); - -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Simple Area Chart Sample', 12)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 5 - ) -); -$Legend->setPlotarea($Plotarea); - -// create the dataset -$Dataset =& Image_Graph::factory('random', array(10, 2, 15, true)); -// create the 1st plot as smoothed area chart using the 1st dataset - -$Plot =& $Plotarea->addNew('area', array(&$Dataset)); - -// set a line color -$Plot->setLineColor('gray'); - -// set a standard fill style -$Plot->setFillColor('blue@0.2'); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/plot_area_smooth.php b/includes/pear/Image/docs/examples/plot_area_smooth.php deleted file mode 100644 index d6fcc680..00000000 --- a/includes/pear/Image/docs/examples/plot_area_smooth.php +++ /dev/null @@ -1,55 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Smoothed Area Chart Sample', 12)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 5 - ) -); - -$Legend->setPlotarea($Plotarea); - -// create the dataset -$Dataset =& Image_Graph::factory('random', array(10, 2, 15, true)); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Smoothed_Area', array(&$Dataset)); - -// set a line color -$Plot->setLineColor('gray'); - -// set a standard fill style -$Plot->setFillColor('blue@0.2'); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/plot_area_stack.php b/includes/pear/Image/docs/examples/plot_area_stack.php deleted file mode 100644 index dafb1ce2..00000000 --- a/includes/pear/Image/docs/examples/plot_area_stack.php +++ /dev/null @@ -1,64 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Stacked Area Chart Sample', 12)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 5 - ) -); -$Legend->setPlotarea($Plotarea); - -// create the dataset -$Datasets = - array( - Image_Graph::factory('random', array(10, 2, 15, true)), - Image_Graph::factory('random', array(10, 2, 15, true)), - Image_Graph::factory('random', array(10, 2, 15, true)) - ); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Area', array($Datasets, 'stacked')); - -// set a line color -$Plot->setLineColor('gray'); - -$FillArray =& Image_Graph::factory('Image_Graph_Fill_Array'); -$FillArray->addColor('blue@0.2'); -$FillArray->addColor('yellow@0.2'); -$FillArray->addColor('green@0.2'); - -// set a standard fill style -$Plot->setFillStyle($FillArray); - -// output the Graph -$Graph->done(); -?> diff --git a/includes/pear/Image/docs/examples/plot_band.php b/includes/pear/Image/docs/examples/plot_band.php deleted file mode 100644 index 3a283bb6..00000000 --- a/includes/pear/Image/docs/examples/plot_band.php +++ /dev/null @@ -1,62 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Band Chart Sample', 12)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 5 - ) -); - -$Legend->setPlotarea($Plotarea); - -// create the dataset -$Dataset =& Image_Graph::factory('dataset'); -for ($i = 0; $i < 40; $i++) { - $v1 = rand(5, 15); - $v2 = $v1 + rand(10, 20); - $Dataset->addPoint($i, array('low' => $v1, 'high' => $v2)); -} - -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Band', $Dataset); - -// set a line color -$Plot->setLineColor('gray'); -$Plot->setFillColor('blue@0.2'); - -$Axis =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X); -$Axis->setLabelInterval(5); - -// output the Graph -$Graph->done(); -?> diff --git a/includes/pear/Image/docs/examples/plot_bar.php b/includes/pear/Image/docs/examples/plot_bar.php deleted file mode 100644 index 92f92e8e..00000000 --- a/includes/pear/Image/docs/examples/plot_bar.php +++ /dev/null @@ -1,55 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Bar Chart Sample', 12)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 5 - ) -); - -$Legend->setPlotarea($Plotarea); - -// create the dataset -$Dataset =& Image_Graph::factory('random', array(10, 2, 15, false)); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot =& $Plotarea->addNew('bar', array(&$Dataset)); - -// set a line color -$Plot->setLineColor('gray'); - -// set a standard fill style -$Plot->setFillColor('blue@0.2'); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/plot_bar_horizontal.php b/includes/pear/Image/docs/examples/plot_bar_horizontal.php deleted file mode 100644 index 9e32a8cb..00000000 --- a/includes/pear/Image/docs/examples/plot_bar_horizontal.php +++ /dev/null @@ -1,80 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(600, 300)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Vertical and Horizontal Bar Chart', 12)), - Image_Graph::horizontal( - $Plotarea1 = Image_Graph::factory('plotarea'), - $Plotarea2 = Image_Graph::factory('plotarea', array('category', 'axis', 'horizontal')), - 50 - ), - 5 - ) -); - -$Dataset[0] =& Image_Graph::factory('dataset'); -$Dataset[1] =& Image_Graph::factory('dataset'); -$Dataset[2] =& Image_Graph::factory('dataset'); - -$Dataset[0]->addPoint('A', 1); -$Dataset[0]->addPoint('B', 4); -$Dataset[0]->addPoint('C', -1); -$Dataset[0]->addPoint('D', 2); -$Dataset[0]->addPoint('E', 1); -$Dataset[0]->addPoint('F', 2); -$Dataset[0]->addPoint('G', 3); - -$Dataset[1]->addPoint('A', 2); -$Dataset[1]->addPoint('B', -3); -$Dataset[1]->addPoint('C', -2); -$Dataset[1]->addPoint('D', 3); -$Dataset[1]->addPoint('E', 3); -$Dataset[1]->addPoint('F', 2); -$Dataset[1]->addPoint('G', -1); - -$Dataset[2]->addPoint('A', -1); -$Dataset[2]->addPoint('B', 2); -$Dataset[2]->addPoint('C', 1); -$Dataset[2]->addPoint('D', 3); -$Dataset[2]->addPoint('E', -1); -$Dataset[2]->addPoint('F', 2); -$Dataset[2]->addPoint('G', 3); - -$Plot1 =& $Plotarea1->addNew('bar', array(&$Dataset, 'stacked')); -$Plot2 =& $Plotarea2->addNew('bar', array(&$Dataset, 'stacked')); - -$FillArray =& Image_Graph::factory('Image_Graph_Fill_Array'); -$FillArray->addColor('blue@0.2'); -$FillArray->addColor('yellow@0.2'); -$FillArray->addColor('green@0.2'); -$Plot1->setFillStyle($FillArray); -$Plot2->setFillStyle($FillArray); - -$Graph->done(); -?> diff --git a/includes/pear/Image/docs/examples/plot_bar_multiple.php b/includes/pear/Image/docs/examples/plot_bar_multiple.php deleted file mode 100644 index 9e2df1b0..00000000 --- a/includes/pear/Image/docs/examples/plot_bar_multiple.php +++ /dev/null @@ -1,72 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Multiple Bar Chart Sample', 12)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 5 - ) -); -$Legend->setPlotarea($Plotarea); - -// create the dataset - $Datasets = - array( - Image_Graph::factory('random', array(5, 2, 15, false)), - Image_Graph::factory('random', array(5, 2, 15, false)), - Image_Graph::factory('random', array(5, 2, 15, false)) -); - -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot =& $Plotarea->addNew('bar', array($Datasets)); - -// set a line color -$Plot->setLineColor('gray'); - -$FillArray =& Image_Graph::factory('Image_Graph_Fill_Array'); -$FillArray->addColor('blue@0.2'); -$FillArray->addColor('yellow@0.2'); -$FillArray->addColor('green@0.2'); - -// set a standard fill style -$Plot->setFillStyle($FillArray); - -// create a Y data value marker -$Marker =& $Plot->addNew('Image_Graph_Marker_Value', IMAGE_GRAPH_VALUE_Y); -// create a pin-point marker type -$PointingMarker =& $Plot->addNew('Image_Graph_Marker_Pointing_Angular', array(20, &$Marker)); -// and use the marker on the 1st plot -$Plot->setMarker($PointingMarker); - -// output the Graph -$Graph->done(); -?> diff --git a/includes/pear/Image/docs/examples/plot_bar_stacked.php b/includes/pear/Image/docs/examples/plot_bar_stacked.php deleted file mode 100644 index ec5ea4dd..00000000 --- a/includes/pear/Image/docs/examples/plot_bar_stacked.php +++ /dev/null @@ -1,73 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Stacked Bar Chart Sample', 12)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 5 - ) -); - -$Legend->setPlotarea($Plotarea); - -// create the dataset -$Datasets[] =& Image_Graph::factory('random', array(10, 0, 4, false)); -$Datasets[] =& Image_Graph::factory('random', array(10, 0, 4, false)); -$Datasets[] =& Image_Graph::factory('random', array(10, 0, 4, false)); - - -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot =& $Plotarea->addNew('bar', array($Datasets, 'stacked')); - -// set a line color -$Plot->setLineColor('gray'); - -// create a fill array -$FillArray =& Image_Graph::factory('Image_Graph_Fill_Array'); -$FillArray->addColor('blue@0.2'); -$FillArray->addColor('yellow@0.2'); -$FillArray->addColor('green@0.2'); - -// set a standard fill style -$Plot->setFillStyle($FillArray); - -// create a Y data value marker -$Marker =& $Plot->addNew('Image_Graph_Marker_Value', IMAGE_GRAPH_VALUE_Y); -// and use the marker on the 1st plot -$Plot->setMarker($Marker); - -$Plot->setDataSelector(Image_Graph::factory('Image_Graph_DataSelector_NoZeros')); - -// output the Graph -$Graph->done(); -?> diff --git a/includes/pear/Image/docs/examples/plot_bar_stacked100pct.php b/includes/pear/Image/docs/examples/plot_bar_stacked100pct.php deleted file mode 100644 index dc35faaa..00000000 --- a/includes/pear/Image/docs/examples/plot_bar_stacked100pct.php +++ /dev/null @@ -1,83 +0,0 @@ - - */ - - -include_once('Image/Graph.php'); -include_once('Image/Graph/Marker/Value.php'); - -class myValueMarker extends Image_Graph_Marker_Value { - - function getDisplayValue($Values) { - return "\{$Values[Y]}"; - } - -} - - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Stacked Bar 100% Chart Sample', 12)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 5 - ) -); -$Legend->setPlotarea($Plotarea); - -for ($j = 0; $j<4; $j++) { - $DX =& Image_Graph::factory('dataset'); - $Datasets[$j] =& $DX; - for ($i = 0; $i<10; $i++) - $DX->addPoint($i, rand(2, 15), $j); -} - -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot =& $Plotarea->addNew('bar', array($Datasets, 'stacked100pct')); - -// set a line color -$Plot->setLineColor('gray'); - -// create a fill array -$FillArray =& Image_Graph::factory('Image_Graph_Fill_Array'); -$FillArray->addColor('blue@0.2'); -$FillArray->addColor('yellow@0.2'); -$FillArray->addColor('green@0.2'); -$FillArray->addColor('red@0.2'); -$FillArray->addColor('gray@0.2'); - -// set a standard fill style -$Plot->setFillStyle($FillArray); - -// create a Y data value marker -$Marker =& $Plot->add(new myValueMarker(IMAGE_GRAPH_VALUE_Y)); -// and use the marker on the 1st plot -$Plot->setMarker($Marker); - -// output the Graph -$Graph->done(); -?> diff --git a/includes/pear/Image/docs/examples/plot_bar_stacked_horizontal.php b/includes/pear/Image/docs/examples/plot_bar_stacked_horizontal.php deleted file mode 100644 index 23cfc24c..00000000 --- a/includes/pear/Image/docs/examples/plot_bar_stacked_horizontal.php +++ /dev/null @@ -1,79 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Stacked Bar Chart Sample', 12)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea', - array( - 'category', - 'axis', - 'horizontal' - ) - ), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 5 - ) -); - -$Legend->setPlotarea($Plotarea); - -// create the dataset -$Datasets[] =& Image_Graph::factory('random', array(10, 0, 4, false)); -$Datasets[] =& Image_Graph::factory('random', array(10, 0, 4, false)); -$Datasets[] =& Image_Graph::factory('random', array(10, 0, 4, false)); - - -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot =& $Plotarea->addNew('bar', array($Datasets, 'stacked')); - -// set a line color -$Plot->setLineColor('gray'); - -// create a fill array -$FillArray =& Image_Graph::factory('Image_Graph_Fill_Array'); -$FillArray->addColor('blue@0.2'); -$FillArray->addColor('yellow@0.2'); -$FillArray->addColor('green@0.2'); - -// set a standard fill style -$Plot->setFillStyle($FillArray); - -// create a Y data value marker -$Marker =& $Plot->addNew('Image_Graph_Marker_Value', IMAGE_GRAPH_VALUE_Y); -// and use the marker on the 1st plot -$Plot->setMarker($Marker); - -$Plot->setDataSelector(Image_Graph::factory('Image_Graph_DataSelector_NoZeros')); - -// output the Graph -$Graph->done(); -?> diff --git a/includes/pear/Image/docs/examples/plot_bar_stacked_negative.php b/includes/pear/Image/docs/examples/plot_bar_stacked_negative.php deleted file mode 100644 index 8e0a5319..00000000 --- a/includes/pear/Image/docs/examples/plot_bar_stacked_negative.php +++ /dev/null @@ -1,74 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Negative Stacked Bar Chart', 10)), - $Plotarea = Image_Graph::factory('plotarea'), - 5 - ) -); - -$Dataset[0] =& Image_Graph::factory('dataset'); -$Dataset[1] =& Image_Graph::factory('dataset'); -$Dataset[2] =& Image_Graph::factory('dataset'); - -$Dataset[0]->addPoint('A', 1); -$Dataset[0]->addPoint('B', 4); -$Dataset[0]->addPoint('C', -1); -$Dataset[0]->addPoint('D', 2); -$Dataset[0]->addPoint('E', 1); -$Dataset[0]->addPoint('F', 2); -$Dataset[0]->addPoint('G', 3); - -$Dataset[1]->addPoint('A', 2); -$Dataset[1]->addPoint('B', -3); -$Dataset[1]->addPoint('C', -2); -$Dataset[1]->addPoint('D', 3); -$Dataset[1]->addPoint('E', 3); -$Dataset[1]->addPoint('F', 2); -$Dataset[1]->addPoint('G', -1); - -$Dataset[2]->addPoint('A', -1); -$Dataset[2]->addPoint('B', 2); -$Dataset[2]->addPoint('C', 1); -$Dataset[2]->addPoint('D', 3); -$Dataset[2]->addPoint('E', -1); -$Dataset[2]->addPoint('F', 2); -$Dataset[2]->addPoint('G', 3); - -$Plot =& $Plotarea->addNew('bar', array(&$Dataset, 'stacked')); - -$FillArray =& Image_Graph::factory('Image_Graph_Fill_Array'); -$FillArray->addColor('blue@0.2'); -$FillArray->addColor('yellow@0.2'); -$FillArray->addColor('green@0.2'); -$Plot->setFillStyle($FillArray); - -$Graph->done(); -?> diff --git a/includes/pear/Image/docs/examples/plot_boxwhisker.php b/includes/pear/Image/docs/examples/plot_boxwhisker.php deleted file mode 100644 index f3ed76d7..00000000 --- a/includes/pear/Image/docs/examples/plot_boxwhisker.php +++ /dev/null @@ -1,64 +0,0 @@ - - */ - - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Box & Whisker Chart', 12)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 5 - ) -); -$Legend->setPlotarea($Plotarea); - -$Plotarea->addNew('line_grid', array(), IMAGE_GRAPH_AXIS_Y); - -$Dataset =& Image_Graph::factory('dataset'); -$Dataset->addPoint('Security', array(10, 21, 12, 18, 12, 17, 14, 13)); -$Dataset->addPoint('Internal', array(3, 6, 1, 9, 12, 4, 3, 5, 6)); -$Dataset->addPoint('External', array(9, 10, 12, 15, 13, 12, 11, 17)); -$Plot =& $Plotarea->addNew('Image_Graph_Plot_BoxWhisker', array(&$Dataset)); - -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('red', 'min'); -$Fill->addColor('green', 'max'); -$Fill->addColor('orange@0.2', 'quartile1'); -$Fill->addColor('blue@0.2', 'median'); -$Fill->addColor('orange@0.2', 'quartile3'); -$Fill->addColor('yellow@0.1', 'box'); -$Plot->setFillStyle($Fill); -$Line =& Image_Graph::factory('Image_Graph_Line_Solid', 'black@0.6'); -$Line->setThickness(1); -$Plot->setLineStyle($Line); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/plot_candlestick.php b/includes/pear/Image/docs/examples/plot_candlestick.php deleted file mode 100644 index 53f0b785..00000000 --- a/includes/pear/Image/docs/examples/plot_candlestick.php +++ /dev/null @@ -1,84 +0,0 @@ - - */ - - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(600, 400)); - -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - - -// create the plotareas -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Candlestick Diagram', 12)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 5 - ) -); -$Legend->setPlotarea($Plotarea); - -// create the dataset -$Dataset =& Image_Graph::factory('dataset'); - -$base = mktime(0, 0, 0, 11, 1, 2004); -$open = rand(20, 100); -//for ($i = 0; $i < 61; $i++) { -for ($i = 0; $i < 60; $i++) { - $span = rand(-25, 25); - $close = ($open + $span < 0 ? $open - $span : $open + $span); - $min = max(1, min($close, $open) - rand(1, 20)); - $max = max($close, $open) + rand(1, 20); - $date = $base + $i * 86400; - $Dataset->addPoint(date('d-M-y', $date), array('min' => $min, 'open' => $open, 'close' => $close, 'max' => $max)); - $open = $close; -} - -$Grid =& $Plotarea->addNew('line_grid', null, IMAGE_GRAPH_AXIS_X); -$Grid->setLineColor('lightgray@0.1'); -$Grid =& $Plotarea->addNew('line_grid', null, IMAGE_GRAPH_AXIS_Y); -$Grid->setLineColor('lightgray@0.1'); - -$Plot =& $Plotarea->addNew('Image_Graph_Plot_CandleStick', array(&$Dataset)); -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('red@0.4', 'red'); -$Fill->addColor('green@0.4', 'green'); -$Plot->setFillStyle($Fill); -$Plot->setTitle('Image_Graph Daily'); - -$AxisX =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X); -$AxisX->setFontAngle('vertical'); -$AxisX->setLabelInterval(5); -$AxisY =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y); -$AxisY->setLabelInterval(20); -$AxisY->setTitle('Stock Price', array('size' => 10, 'angle' => 90)); - -$Legend->setFontSize(10); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/plot_impulse.php b/includes/pear/Image/docs/examples/plot_impulse.php deleted file mode 100644 index 2f96d6f5..00000000 --- a/includes/pear/Image/docs/examples/plot_impulse.php +++ /dev/null @@ -1,51 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Impulse Chart Sample', 12)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 5 - ) -); -$Legend->setPlotarea($Plotarea); - -// create the dataset -$Dataset =& Image_Graph::factory('random', array(10, 2, 15, false)); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot =& $Plotarea->addNew('Plot_Impulse', array(&$Dataset)); - -// set a line color -$Plot->setLineColor('red'); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/plot_impulse_stacked.php b/includes/pear/Image/docs/examples/plot_impulse_stacked.php deleted file mode 100644 index 800f0ba9..00000000 --- a/includes/pear/Image/docs/examples/plot_impulse_stacked.php +++ /dev/null @@ -1,66 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Stacked Impulse Chart Sample', 12)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 5 - ) -); - -$Legend->setPlotarea($Plotarea); - -// create the dataset -$Datasets[] =& Image_Graph::factory('random', array(10, 2, 15, false)); -$Datasets[] =& Image_Graph::factory('random', array(10, 2, 15, false)); -$Datasets[] =& Image_Graph::factory('random', array(10, 2, 15, false)); - - -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot =& $Plotarea->addNew('impulse', array($Datasets, 'stacked')); - -// set a line color -$Plot->setLineColor('gray'); - -// create a line array -$LineArray =& Image_Graph::factory('Image_Graph_Line_Array'); -$LineArray->addColor('blue'); -$LineArray->addColor('orange'); -$LineArray->addColor('green'); - -// set a standard fill style -$Plot->setLineStyle($LineArray); - -$Plotarea->setFillColor('gray@0.2'); -// output the Graph -$Graph->done(); -?> diff --git a/includes/pear/Image/docs/examples/plot_line.php b/includes/pear/Image/docs/examples/plot_line.php deleted file mode 100644 index 8f5d5243..00000000 --- a/includes/pear/Image/docs/examples/plot_line.php +++ /dev/null @@ -1,55 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); - -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(10); - -$Graph->setFont($Font); - -// setup the plotarea, legend and their layout -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Simple Line Chart Sample', 12)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 88 - ), - 5 - ) -); - -// link the legend with the plotares -$Legend->setPlotarea($Plotarea); - -// create a random dataset for sake of simplicity -$Dataset =& Image_Graph::factory('random', array(10, 2, 15, true)); -// create the plot as line chart using the dataset -$Plot =& $Plotarea->addNew('line', array(&$Dataset)); - -// set a line color -$Plot->setLineColor('red'); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/plot_line_smooth.php b/includes/pear/Image/docs/examples/plot_line_smooth.php deleted file mode 100644 index 6fc50510..00000000 --- a/includes/pear/Image/docs/examples/plot_line_smooth.php +++ /dev/null @@ -1,51 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Smoothed Line Chart Sample', 12)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 5 - ) -); -$Legend->setPlotarea($Plotarea); - -// create the dataset -$Dataset =& Image_Graph::factory('random', array(10, 2, 15, true)); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Smoothed_Line', array(&$Dataset)); - -// set a line color -$Plot->setLineColor('red'); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/plot_map.php b/includes/pear/Image/docs/examples/plot_map.php deleted file mode 100644 index efd34f58..00000000 --- a/includes/pear/Image/docs/examples/plot_map.php +++ /dev/null @@ -1,75 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(600, 400)); - -// create the plotareas -$Plotarea =& $Graph->addNew('Image_Graph_Plotarea_Map', 'europe'); - -// create the dataset -$Dataset =& Image_Graph::factory('dataset'); -$Dataset->addPoint('Denmark', 10); -$Dataset->addPoint('Sweden', 5); -$Dataset->addPoint('Iceland', 7); -$Dataset->addPoint('Portugal', 2); -$Dataset->addPoint('Sicily', 5); - -$Dataset2 =& Image_Graph::factory('dataset'); -$Dataset2->addPoint('Finland', 0); -$Dataset2->addPoint('Ukraine', 0); -$Dataset2->addPoint('Cyprus', 0); - -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Dot', array(&$Dataset)); -$Marker =& $Plot->setMarker(Image_Graph::factory('Image_Graph_Marker_Bubble')); - -// set a line color -$Plot->setLineColor('gray'); - -// set a standard fill style -$FillArray =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Marker->setFillStyle($FillArray); -$FillArray->addColor('green@0.2'); -$FillArray->addColor('blue@0.2'); -$FillArray->addColor('yellow@0.2'); -$FillArray->addColor('red@0.2'); -$FillArray->addColor('orange@0.2'); - -$Plot2 =& $Plotarea->addNew('line', array(&$Dataset2)); -$Plot2->setLineColor('red'); -$Marker2 =& $Plot2->setMarker(Image_Graph::factory('Image_Graph_Marker_Circle')); -$Marker2->setLineColor('blue'); -$Marker2->setFillColor('white'); -$Marker2->Size = 5; -$ValueMarker =& Image_Graph::factory('Image_Graph_Marker_Value', IMAGE_GRAPH_VALUE_X); -$Marker2->setSecondaryMarker(Image_Graph::factory('Image_Graph_Marker_Pointing_Angular', array(40, &$ValueMarker))); - -$ValueMarker->setFillColor('white'); - -$Font =& $Graph->addNew('font', 'Verdana'); -$Font->setSize(8); -$Graph->setFont($Font); -$Graph->addNew('title', array('Map Chart Sample', 12)); - -$Graph->setBorderColor('black'); -$Graph->showShadow(); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/plot_odo.php b/includes/pear/Image/docs/examples/plot_odo.php deleted file mode 100644 index c9c6522a..00000000 --- a/includes/pear/Image/docs/examples/plot_odo.php +++ /dev/null @@ -1,121 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; -// create the graph -$driver=& Image_Canvas::factory('png',array('width'=>400,'height'=>300,'antialias' => 'native')); -$Graph = & Image_Graph::factory('graph', $driver); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Odo Chart', 12)), - Image_Graph::horizontal( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 80 - ), - 5 - ) -); - -$Legend->setPlotarea($Plotarea); -$Legend->setAlignment(IMAGE_GRAPH_ALIGN_HORIZONTAL); -/***************************Arrows************************/ -$Arrows = & Image_Graph::factory('dataset'); -$Arrows->addPoint('ok', 200, 'OK'); -$Arrows->addPoint('std', 120, 'Std'); -$Arrows->addPoint('bad', 250, 'Bad'); - - -/**************************PARAMATERS for PLOT*******************/ - -// create the plot as odo chart using the dataset -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Odo',$Arrows); -$Plot->setRange(100, 300); -$Plot->setAngles(135, 270); -$Plot->setRadiusWidth(75); -$Plot->setLineColor('gray');//for range and outline - -$Marker =& $Plot->addNew('Image_Graph_Marker_Value', IMAGE_GRAPH_VALUE_Y); -$Plot->setArrowMarker($Marker); - -$Plotarea->hideAxis(); -/***************************Axis************************/ -// create a Y data value marker - -$Marker->setFillColor('transparent'); -$Marker->setBorderColor('transparent'); -$Marker->setFontSize(7); -$Marker->setFontColor('black'); - -// create a pin-point marker type -$Plot->setTickLength(14); -$Plot->setAxisTicks(5); -/********************************color of arrows*************/ -$FillArray = & Image_Graph::factory('Image_Graph_Fill_Array'); -$FillArray->addColor('blue@0.6', 'OK'); -$FillArray->addColor('orange@0.6', 'Std'); -$FillArray->addColor('green@0.6', 'Bad'); - -// create a line array -$LineArray =& Image_Graph::factory('Image_Graph_Line_Array'); -$LineArray->addColor('blue', 'OK'); -$LineArray->addColor('orange', 'Std'); -$LineArray->addColor('green', 'Bad'); -$Plot->setArrowLineStyle($LineArray); -$Plot->setArrowFillStyle($FillArray); - -/***************************MARKER OR ARROW************************/ -// create a Y data value marker -$Marker =& $Plot->addNew('Image_Graph_Marker_Value', IMAGE_GRAPH_VALUE_Y); -$Marker->setFillColor('black'); -$Marker->setBorderColor('blue'); -$Marker->setFontSize(7); -$Marker->setFontColor('white'); -// create a pin-point marker type -$PointingMarker =& $Plot->addNew('Image_Graph_Marker_Pointing_Angular', array(20, &$Marker)); -// and use the marker on the plot -$Plot->setMarker($PointingMarker); -/**************************RANGE*******************/ -// create the dataset -/*$Range[] = & Image_Graph::factory('dataset',array(array(100,140))); -$Range[] = & Image_Graph::factory('dataset',array(array(150,260))); -$Range[] = & Image_Graph::factory('dataset',array(array(270,290)));*/ -//print_r($Range);die(); -$Plot->addRangeMarker(100, 140); -$Plot->addRangeMarker(150, 260); -$Plot->addRangeMarker(270, 290); -// create a fillstyle for the ranges -$FillRangeArray = & Image_Graph::factory('Image_Graph_Fill_Array'); -$FillRangeArray->addColor('green@0.7'); -$FillRangeArray->addColor('yellow@0.7'); -$FillRangeArray->addColor('blue@0.7'); -/* $FillRangeArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'green')); -$FillRangeArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'orange')); -$FillRangeArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'red')); */ -$Plot->setRangeMarkerFillStyle($FillRangeArray); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/plot_pie.php b/includes/pear/Image/docs/examples/plot_pie.php deleted file mode 100644 index d0ade349..00000000 --- a/includes/pear/Image/docs/examples/plot_pie.php +++ /dev/null @@ -1,58 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); -// create the plotareas -$Plotarea =& $Graph->addNew('plotarea'); - -$Plotarea->hideAxis(); - -// create the dataset -$Dataset =& Image_Graph::factory('random', array(10, 10, 20, true)); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Pie', $Dataset); - -$Plot->Radius = 2; - -// set a line color -$Plot->setLineColor('gray'); - -// set a standard fill style -$FillArray =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Plot->setFillStyle($FillArray); -$FillArray->addColor('green@0.2'); -$FillArray->addColor('blue@0.2'); -$FillArray->addColor('yellow@0.2'); -$FillArray->addColor('red@0.2'); -$FillArray->addColor('orange@0.2'); - -// add a title using the created font -$Graph->addNew('title', array('Pie Chart Sample', 11)); - -$Plot->explode(10); - -// output the Graph -$Graph->done(); -?> diff --git a/includes/pear/Image/docs/examples/plot_pie_rotate.php b/includes/pear/Image/docs/examples/plot_pie_rotate.php deleted file mode 100644 index ad962d6e..00000000 --- a/includes/pear/Image/docs/examples/plot_pie_rotate.php +++ /dev/null @@ -1,80 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); - -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 7 pixels -$Font->setSize(7); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Meat Export', 12)), - Image_Graph::horizontal( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 70 - ), - 5 - ) -); - -$Legend->setPlotarea($Plotarea); - -// create the 1st dataset -$Dataset1 =& Image_Graph::factory('dataset'); -$Dataset1->addPoint('Beef', rand(1, 10)); -$Dataset1->addPoint('Pork', rand(1, 10)); -$Dataset1->addPoint('Poultry', rand(1, 10)); -$Dataset1->addPoint('Camels', rand(1, 10)); -$Dataset1->addPoint('Other', rand(1, 10)); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot =& $Plotarea->addNew('pie', array(&$Dataset1)); -$Plotarea->hideAxis(); - -// create a Y data value marker -$Marker =& $Plot->addNew('Image_Graph_Marker_Value', IMAGE_GRAPH_PCT_Y_TOTAL); -// create a pin-point marker type -$PointingMarker =& $Plot->addNew('Image_Graph_Marker_Pointing_Angular', array(20, &$Marker)); -// and use the marker on the 1st plot -$Plot->setMarker($PointingMarker); -// format value marker labels as percentage values -$Marker->setDataPreprocessor(Image_Graph::factory('Image_Graph_DataPreprocessor_Formatted', '%0.1f%%')); - -$Plot->Radius = 2; - -$FillArray =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Plot->setFillStyle($FillArray); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'green')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'blue')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'yellow')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'red')); -$FillArray->addNew('gradient', array(IMAGE_GRAPH_GRAD_RADIAL, 'white', 'orange')); - -$Plot->explode(5); - -$Plot->setStartingAngle(90); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/plot_radar.php b/includes/pear/Image/docs/examples/plot_radar.php deleted file mode 100644 index 14a9d881..00000000 --- a/includes/pear/Image/docs/examples/plot_radar.php +++ /dev/null @@ -1,82 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; -require_once 'Image/Canvas.php'; - -$Canvas =& Image_Canvas::factory('png', - array( - 'width' => 400, - 'height' => 300, - 'antialias' => 'native' - ) -); - -// create the graph -$Graph =& Image_Graph::factory('graph', $Canvas); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Spider/Radar Chart Sample', 12)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('Image_Graph_Plotarea_Radar'), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 5 - ) -); -$Legend->setPlotarea($Plotarea); - -$Plotarea->addNew('Image_Graph_Grid_Polar', IMAGE_GRAPH_AXIS_Y); - -// create the dataset -$DS1 =& Image_Graph::factory('dataset'); -$DS1->addPoint('Life', rand(1, 6)); -$DS1->addPoint('Universe', rand(1, 6)); -$DS1->addPoint('Everything', rand(1, 6)); -$DS1->addPoint('Something', rand(1, 6)); -$DS1->addPoint('Nothing', rand(1, 6)); -$DS1->addPoint('Irrelevevant', rand(1, 6)); - -$DS2 =& Image_Graph::factory('dataset'); -$DS2->addPoint('Life', rand(1, 6)); -$DS2->addPoint('Universe', rand(1, 6)); -$DS2->addPoint('Everything', rand(1, 6)); -$DS2->addPoint('Something', rand(1, 6)); -$DS2->addPoint('Nothing', rand(1, 6)); -$DS2->addPoint('Irrelevevant', rand(1, 6)); - -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Radar', $DS1); -$Plot2 =& $Plotarea->addNew('Image_Graph_Plot_Radar', $DS2); - - -// set a standard fill style -$Plot->setLineColor('blue@0.4'); -$Plot->setFillColor('blue@0.2'); - -$Plot2->setLineColor('red@0.4'); -$Plot2->setFillColor('red@0.2'); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/plot_radar_smooth.php b/includes/pear/Image/docs/examples/plot_radar_smooth.php deleted file mode 100644 index 27bdec8d..00000000 --- a/includes/pear/Image/docs/examples/plot_radar_smooth.php +++ /dev/null @@ -1,78 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Smoothed Radar Chart Sample', 11)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('Image_Graph_Plotarea_Radar'), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 5 - ) -); -$Legend->setPlotarea($Plotarea); - -$Plotarea->addNew('Image_Graph_Grid_Polar', IMAGE_GRAPH_AXIS_Y); - -// create the dataset -$DS1 =& Image_Graph::factory('dataset'); -$DS2 =& Image_Graph::factory('dataset'); -for ($i = 0; $i < 360; $i += 10) { - $DS1->addPoint($i, rand(3, 6)); - if ($i % 30 == 0) { - $DS2->addPoint($i, rand(2, 4)); - } -} - -$Plot1 =& $Plotarea->addNew('Image_Graph_Plot_Smoothed_Radar', $DS1); -$Plot2 =& $Plotarea->addNew('Image_Graph_Plot_Smoothed_Radar', $DS2); - -// set a standard fill style -$Plot1->setLineColor('blue@0.4'); -$Plot1->setFillColor('blue@0.2'); -// set a standard fill style -$Plot2->setLineColor('green@0.4'); -$Plot2->setFillColor('green@0.2'); - -$AxisX =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X); -$AxisX->setLabelInterval(3); -$AxisX->setLineColor('lightgrey'); -$AxisY =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y); -$AxisY->setLineColor('lightgrey'); - -// create a Y data value marker -$Marker =& $Plot2->addNew('Image_Graph_Marker_Circle'); -$Marker->setSize(5); -$Marker->setFillColor('gray@0.2'); -$Plot2->setMarker($Marker); - - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/plot_scatter.php b/includes/pear/Image/docs/examples/plot_scatter.php deleted file mode 100644 index 69a1ece2..00000000 --- a/includes/pear/Image/docs/examples/plot_scatter.php +++ /dev/null @@ -1,65 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Dot Chart Sample', 12)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 5 - ) -); -$Legend->setPlotarea($Plotarea); - -// create the dataset -$Dataset1 =& Image_Graph::factory('random', array(10, 2, 9, false)); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot1 =& $Plotarea->addNew('Image_Graph_Plot_Dot', array(&$Dataset1)); -$Marker1 =& Image_Graph::factory('Image_Graph_Marker_Cross'); -$Marker1->setFillColor('blue'); -$Marker1->setLineColor('black'); -// set a line color -$Plot1->setMarker($Marker1); -$Plot1->setTitle('Introvert'); - -// create the dataset -$Dataset2 =& Image_Graph::factory('random', array(10, 10, 15, false)); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot2 =& $Plotarea->addNew('Image_Graph_Plot_Dot', array(&$Dataset2)); -$Marker2 =& Image_Graph::factory('Image_Graph_Marker_Plus'); -$Marker2->setFillColor('green'); -$Marker2->setLineColor('black'); -// set a line color -$Plot2->setMarker($Marker2); -$Plot2->setTitle('Extrovert'); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/plot_scatter_linefit.php b/includes/pear/Image/docs/examples/plot_scatter_linefit.php deleted file mode 100644 index 4c58e5c6..00000000 --- a/includes/pear/Image/docs/examples/plot_scatter_linefit.php +++ /dev/null @@ -1,60 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Dot Chart Sample', 12)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 5 - ) -); -$Legend->setPlotarea($Plotarea); - -// create the dataset -$Dataset1 =& Image_Graph::factory('random', array(10, 10, 50, false)); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot1 =& $Plotarea->addNew('Image_Graph_Plot_Dot', array(&$Dataset1)); -$Marker1 =& Image_Graph::factory('Image_Graph_Marker_Cross'); -$Marker1->setFillColor('blue'); -$Marker1->setLineColor('black'); -// set a line color -$Plot1->setMarker($Marker1); -$Plot1->setTitle('Introvert'); - -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot2 =& $Plotarea->addNew('Image_Graph_Plot_Fit_Line', array(&$Dataset1)); -// set a line color -$Plot2->setLineColor('blue'); -$Plot2->setTitle('Extrovert'); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/plot_step.php b/includes/pear/Image/docs/examples/plot_step.php deleted file mode 100644 index efa4462e..00000000 --- a/includes/pear/Image/docs/examples/plot_step.php +++ /dev/null @@ -1,60 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Step Chart Sample', 12)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 5 - ) -); -$Legend->setPlotarea($Plotarea); - -// create the dataset -$Dataset[] =& Image_Graph::factory('random', array(10, 2, 5, false)); -$Dataset[] =& Image_Graph::factory('random', array(10, 2, 5, false)); -$Dataset[] =& Image_Graph::factory('random', array(10, 2, 5, false)); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Step', array($Dataset, 'stacked')); - -// set a line color -$Plot->setLineColor('gray'); - -$Fill =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Fill->addColor('red@0.2'); -$Fill->addColor('blue@0.2'); -$Fill->addColor('green@0.2'); -$Plot->setFillStyle($Fill); - -// output the Graph -$Graph->done(); -?> diff --git a/includes/pear/Image/docs/examples/secondary_axis.php b/includes/pear/Image/docs/examples/secondary_axis.php deleted file mode 100644 index d7cbfc67..00000000 --- a/includes/pear/Image/docs/examples/secondary_axis.php +++ /dev/null @@ -1,85 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; -require_once 'Image/Canvas.php'; - -$Canvas =& Image_Canvas::factory('png', array('width' => 400, 'height' => 300, 'antialias' => 'native')); - -// create the graph -$Graph =& Image_Graph::factory('graph', $Canvas); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - -// create the plotarea layout -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Primary & Secondary Axis', 11)), - Image_Graph::vertical( - $Plotarea = Image_Graph::factory('plotarea'), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 5 - ) -); - -// make the legend use the plotarea (or implicitly it's plots) -$Legend->setPlotarea($Plotarea); - -// create a grid and assign it to the secondary Y axis -$GridY2 =& $Plotarea->addNew('bar_grid', IMAGE_GRAPH_AXIS_Y_SECONDARY); -$GridY2->setFillStyle( - Image_Graph::factory( - 'gradient', - array(IMAGE_GRAPH_GRAD_VERTICAL, 'white', 'lightgrey') - ) -); - -// create a line plot using a random dataset -$Dataset1 =& Image_Graph::factory('random', array(8, 10, 100, true)); -$Plot1 =& $Plotarea->addNew('line', array(&$Dataset1)); -$Plot1->setLineColor('red'); - -// create an area plot using a random dataset -$Dataset2 =& Image_Graph::factory('random', array(8, 1, 10, true)); -$Plot2 =& $Plotarea->addNew( - 'Image_Graph_Plot_Area', - $Dataset2, - IMAGE_GRAPH_AXIS_Y_SECONDARY -); - -$Plot2->setLineColor('gray'); -$Plot2->setFillColor('blue@0.2'); - - // set the titles for the plots -$Plot1->setTitle('Primary Axis'); -$Plot2->setTitle('Secondary Axis'); - -$AxisX =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X); -$AxisX->setTitle('Oranges'); -$AxisY =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y); -$AxisY->setTitle('Apples', 'vertical'); -$AxisYsecondary =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y_SECONDARY); -$AxisYsecondary->setTitle('Pears', 'vertical2'); - -// output the Graph -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/simple.php b/includes/pear/Image/docs/examples/simple.php deleted file mode 100644 index c33d25fa..00000000 --- a/includes/pear/Image/docs/examples/simple.php +++ /dev/null @@ -1,28 +0,0 @@ - - */ - -error_reporting(E_ALL); -include 'Image/Graph.php'; -$Graph =& Image_Graph::factory('graph', array(400, 300)); -$Plotarea =& $Graph->addNew('plotarea'); -$Dataset =& Image_Graph::factory('dataset'); -$Dataset->addPoint('Denmark', 10); -$Dataset->addPoint('Norway', 3); -$Dataset->addPoint('Sweden', 8); -$Dataset->addPoint('Finland', 5); -$Plot =& $Plotarea->addNew('bar', &$Dataset); -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/docs/examples/simple_graph.php b/includes/pear/Image/docs/examples/simple_graph.php deleted file mode 100644 index b48be524..00000000 --- a/includes/pear/Image/docs/examples/simple_graph.php +++ /dev/null @@ -1,40 +0,0 @@ - - */ - -include('Image/Graph/Simple.php'); - -$Data = array( - 'Dogs' => 3, - 'Cats' => 1, - 'Parrots' => 4, - 'Mice' => 5 -); - -// create the graph -$Graph =& Image_Graph_Simple::factory( - 400, - 300, - 'Image_Graph_Plot_Smoothed_Area', - $Data, - 'Simple Graph Example', - 'gray', - 'blue@0.2', - 'Verdana' -); - -// output the Graph -$Graph->done(); -?> diff --git a/includes/pear/Image/docs/examples/small_pie_plot.php b/includes/pear/Image/docs/examples/small_pie_plot.php deleted file mode 100644 index e3fc30b5..00000000 --- a/includes/pear/Image/docs/examples/small_pie_plot.php +++ /dev/null @@ -1,53 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(80, 80)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); -// create the plotareas -$Plotarea =& $Graph->addNew('plotarea'); - -$Plotarea->hideAxis(); - -// create the dataset -$Dataset =& Image_Graph::factory('random', array(10, 10, 20, true)); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot =& $Plotarea->addNew('Image_Graph_Plot_Pie', $Dataset); - -$Plot->setDiameter(-1); -$Plotarea->setPadding(0); - -// set a line color -$Plot->setLineColor('gray'); - -// set a standard fill style -$FillArray =& Image_Graph::factory('Image_Graph_Fill_Array'); -$Plot->setFillStyle($FillArray); -$FillArray->addColor('green@0.2'); -$FillArray->addColor('blue@0.2'); -$FillArray->addColor('yellow@0.2'); -$FillArray->addColor('red@0.2'); -$FillArray->addColor('orange@0.2'); - -$Graph->done(); -?> diff --git a/includes/pear/Image/docs/examples/vector_function.php b/includes/pear/Image/docs/examples/vector_function.php deleted file mode 100644 index f2e152d4..00000000 --- a/includes/pear/Image/docs/examples/vector_function.php +++ /dev/null @@ -1,62 +0,0 @@ - - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); -// add a TrueType font -$Font =& $Graph->addNew('font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(8); - -$Graph->setFont($Font); - - -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Vector Function Chart Sample', 12)), - Image_Graph::vertical( - // create the plotarea with a normal linear axis as x-axis! - $Plotarea = Image_Graph::factory('plotarea', 'axis'), - $Legend = Image_Graph::factory('legend'), - 90 - ), - 5 - ) -); -$Legend->setPlotarea($Plotarea); - -function tcost($t) { return $t*cos($t); } -function tsint($t) { return $t*sin($t); } - -$GridX =& $Plotarea->addNew('line_grid', null, IMAGE_GRAPH_AXIS_X); -$GridY =& $Plotarea->addNew('line_grid', null, IMAGE_GRAPH_AXIS_Y); -$LineStyle =& Image_Graph::factory('Image_Graph_Line_Dashed', array('lightgrey', 'transparent')); -$GridX->setLineStyle($LineStyle); -$GridY->setLineStyle($LineStyle); - -$Dataset =& Image_Graph::factory('vector', array(0, 20, 'tcost', 'tsint', 200)); -// create the 1st plot as smoothed area chart using the 1st dataset -$Plot =& $Plotarea->addNew('line', array(&$Dataset)); -$Plot->setLineColor('red'); -$Plot->setTitle('f(t) = { t*cos(t), t*sin(t) }'); - -$AxisY =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y); -$AxisY->setAxisIntersection(0); - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/README b/includes/pear/Image/tests/README deleted file mode 100644 index 5f6b7dc0..00000000 --- a/includes/pear/Image/tests/README +++ /dev/null @@ -1,12 +0,0 @@ -------------------------------------------------------------------------------- - These tests are not unit or regression tests. -------------------------------------------------------------------------------- - -This is because it is not possible to compare output from Image_Driver with an -expected "value" (i.e. is this graph equal to this graph). The problem is similar -to testing user interfaces. - -The provided test "cases" are visual test suites that renders Image_Driver output, -the output should then be viewed and checked for inconsistencies on a visual base, -fx. this line chart does not show as _expected_, this gradient fill does not fill -to the edges of the area, the text does not align properly, etc. \ No newline at end of file diff --git a/includes/pear/Image/tests/axis/category.php b/includes/pear/Image/tests/axis/category.php deleted file mode 100644 index 71085125..00000000 --- a/includes/pear/Image/tests/axis/category.php +++ /dev/null @@ -1,87 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: category.php,v 1.4 2005/08/03 21:21:58 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(400, 300)); -// add a TrueType font -$Font =& $Graph->addNew('ttf_font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(7); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Testing Category Axis', 10)), - $Plotarea = Image_Graph::factory('plotarea', array('Image_Graph_Axis_Category', 'Image_Graph_Axis_Category')), - 5 - ) -); - -$DS =& Image_Graph::factory('dataset'); -$DS->addPoint('Germany', 'England'); -$DS->addPoint('Denmark', 'France'); -$DS->addPoint('Sweden', 'Denmark'); -$DS->addPoint('England', 'France'); -$DS->addPoint('Norway', 'Finland'); -$DS->addPoint('Denmark', 'Finland'); -$DS->addPoint('Iceland', 'Germany'); -$DS->addPoint('Norway', 'France'); - -$DS2 =& Image_Graph::factory('dataset'); -$DS2->addPoint('Sweden', 'France'); -$DS2->addPoint('Austria', 'Germany'); -$DS2->addPoint('Norway', 'Holland'); -$DS2->addPoint('Denmark', 'Germany'); -$DS2->addPoint('Sweden', 'Holland'); -$DS2->addPoint('Iceland', 'Denmark'); - -/* Expect x-axis to be ordered: - * Germany, Denmark, Sweden, England, Austria, Norway, Iceland - * - * Expect y-axis to be ordered: - * England, France, Denmark, Finland, Holland, Germany - * - * Special points are X = Austria and Y = Holland, which are expected to be - * "placed" before Norway and Germany respective (since that is the point at - * which they exist "before" in the dataset on their first occurence) - */ - -$Plot =& $Plotarea->addNew('line', $DS); -$Plot->setLineColor('red'); - -$Plot2 =& $Plotarea->addNew('line', $DS2); -$Plot2->setLineColor('blue'); - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/axis/intersection.php b/includes/pear/Image/tests/axis/intersection.php deleted file mode 100644 index dad11805..00000000 --- a/includes/pear/Image/tests/axis/intersection.php +++ /dev/null @@ -1,82 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: intersection.php,v 1.5 2005/08/03 21:21:58 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(600, 400)); -// add a TrueType font -$Font =& $Graph->addNew('ttf_font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(7); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Testing Axis Intersection', 10)), - $Matrix = Image_Graph::factory('Image_Graph_Layout_Matrix', array(3, 3)), - 5 - ) -); - -$DS[0] =& Image_Graph::factory('dataset', array(array('0' => 1, '1' => 2, '2' => 0))); -$DS[1] =& Image_Graph::factory('dataset', array(array('0' => -1, '1' => 2, '2' => 2))); -$DS[2] =& Image_Graph::factory('dataset', array(array('0' => 1, '1' => 3, '2' => 2))); - -for ($row = 0; $row < 3; $row++) { - for ($col = 0; $col < 3; $col++) { - if (isset($DS[$col])) { - $Plotarea =& $Matrix->getEntry($row, $col); - $AxisY =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y); - $AxisX =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X); - if ($row >= 1) { - $AxisY->setAxisIntersection(1); - $AxisY->setTitle("Intersect\n at x = 1"); - } else { - $AxisY->setTitle("Intersect\nat x = min"); - } - if ($row >= 2) { - $AxisX->setAxisIntersection(1); - $AxisX->setTitle('Intersect at y = 1'); - } else { - $AxisX->setTitle('Intersect at y = 0'); - } - $Plot =& $Plotarea->addNew('line', $DS[$col]); - $Plot->setLineColor('red'); - $Plotarea->setBackgroundColor('blue@0.2'); - } - } -} - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/axis/intersection_secondary_axis.php b/includes/pear/Image/tests/axis/intersection_secondary_axis.php deleted file mode 100644 index da6df6ca..00000000 --- a/includes/pear/Image/tests/axis/intersection_secondary_axis.php +++ /dev/null @@ -1,89 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: intersection_secondary_axis.php,v 1.5 2005/08/03 21:21:58 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(800, 600)); -// add a TrueType font -$Font =& $Graph->addNew('ttf_font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(7); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Testing Secondary Axis Intersection', 10)), - $Matrix = Image_Graph::factory('Image_Graph_Layout_Matrix', array(3, 3)), - 5 - ) -); - -$DS[0] =& Image_Graph::factory('dataset', array(array('0' => 1, '1' => 2, '2' => 0))); -$DS[1] =& Image_Graph::factory('dataset', array(array('0' => -1, '1' => 2, '2' => 1))); -$DS[2] =& Image_Graph::factory('dataset', array(array('0' => 1, '1' => 3, '2' => 2))); -$DS2[0] =& Image_Graph::factory('dataset', array(array('0' => -1, '1' => 2, '2' => 1))); -$DS2[1] =& Image_Graph::factory('dataset', array(array('0' => 1, '1' => 3, '2' => 2))); -$DS2[2] =& Image_Graph::factory('dataset', array(array('0' => 1, '1' => 2, '2' => 1))); - -for ($row = 0; $row < 3; $row++) { - for ($col = 0; $col < 3; $col++) { - if (isset($DS[$col])) { - $Plotarea =& $Matrix->getEntry($row, $col); - $AxisY =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y); - $AxisY->setLineColor('silver'); - - $AxisX =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X); - $AxisX->setAxisIntersection(($row < 1 ? 0 : 1), IMAGE_GRAPH_AXIS_Y_SECONDARY); - $AxisX->setTitle("Intersect at\ny2=" . ($row < 1 ? '0' : '1')); - - $Plot =& $Plotarea->addNew('line', $DS2[$col]); - $Plot->setLineColor('red@0.1'); - $Plot2 =& $Plotarea->addNew('line', $DS[$col], IMAGE_GRAPH_AXIS_Y_SECONDARY); - $Plot2->setLineColor('green'); - $Plotarea->setBackgroundColor('blue@0.2'); - - $AxisYsec =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y_SECONDARY); - if ($row > 1) { - $AxisYsec->setAxisIntersection(1); - $AxisYsec->setTitle("Intersect\nat x=1"); - } else { - $AxisYsec->setTitle("Intersect\nat x=max"); - } - } - } -} - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/axis/inversion.php b/includes/pear/Image/tests/axis/inversion.php deleted file mode 100644 index a3d01e6a..00000000 --- a/includes/pear/Image/tests/axis/inversion.php +++ /dev/null @@ -1,89 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: inversion.php,v 1.4 2005/08/03 21:21:58 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(600, 600)); -// add a TrueType font -$Font =& $Graph->addNew('ttf_font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(7); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Testing Axis Inversion', 10)), - $Matrix = Image_Graph::factory('Image_Graph_Layout_Matrix', array(4, 3)), - 5 - ) -); - -$DS[0] =& Image_Graph::factory('dataset', array(array('0' => 1, '1' => 2, '2' => 0))); -$DS[1] =& Image_Graph::factory('dataset', array(array('0' => -1, '1' => 2, '2' => 2))); -$DS[2] =& Image_Graph::factory('dataset', array(array('0' => 1, '1' => 3, '2' => 2))); - -for ($row = 0; $row < 4; $row++) { - for ($col = 0; $col < 3; $col++) { - if (isset($DS[$col])) { - $Plotarea =& $Matrix->getEntry($row, $col); - $AxisY =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y); - $AxisX =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X); - - if ($row >= 1) { - $AxisY->setInverted(true); - $AxisY->setTitle('Inverted Y', 'vertical'); - } else { - $AxisY->setTitle('Normal Y', 'vertical'); - } - - if ($row >= 2) { - $AxisX->setInverted(true); - $AxisX->setTitle('Inverted X'); - } else { - $AxisX->setTitle('Normal X'); - } - - if ($row >= 3) { - $AxisX->setAxisIntersection('max'); - $AxisX->setTitle('Inverted X at Bottom (set X intersection)'); - } - - $Plot =& $Plotarea->addNew('line', $DS[$col]); - $Plot->setLineColor('red'); - $Plotarea->setBackgroundColor('blue@0.2'); - } - } -} - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/axis/labelinterval.php b/includes/pear/Image/tests/axis/labelinterval.php deleted file mode 100644 index 542ba6b6..00000000 --- a/includes/pear/Image/tests/axis/labelinterval.php +++ /dev/null @@ -1,99 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: labelinterval.php,v 1.4 2005/08/03 21:21:58 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(800, 600)); -// add a TrueType font -$Font =& $Graph->addNew('ttf_font', 'Verdana'); -// set the font size to 7 pixels -$Font->setSize(7); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Testing Changing Axis Label Intervals (Bar Charts also test label distance)', 10)), - $Matrix = Image_Graph::factory('Image_Graph_Layout_Matrix', array(4, 4)), - 5 - ) -); - -$DS[0] =& Image_Graph::factory('dataset', array(array(0 => 1, 1 => 2, 2 => 0, 3 => 1, 4 => 4))); -$DS[1] =& Image_Graph::factory('dataset', array(array('A' => 1, 'B' => 2, 'C' => 0, 'D' => 1, 'E' => 4))); - -$DS[2] =& Image_Graph::factory('dataset', array(array(0 => 1, 1 => 2, 2 => -2, 3 => 1, 4 => 4))); -$DS[3] =& Image_Graph::factory('dataset', array(array('A' => 1, 'B' => 2, 'C' => -2, 'D' => 1, 'E' => 4))); - -for ($row = 0; $row < 4; $row++) { - for ($col = 0; $col < 4; $col++) { - if (isset($DS[$col])) { - $Plotarea =& $Matrix->getEntry($row, $col); - $AxisY =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y); - $AxisX =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X); - - if ($row > 2) { - $AxisX->setLabelInterval(3); - $AxisX->setTitle('"Odd" interval'); - } elseif ($row > 0) { - $AxisX->setLabelInterval(2); - $AxisX->setTitle('Changed interval'); - } else { - $AxisX->setTitle('Default interval'); - } - - if ($row > 2) { - $AxisY->setLabelInterval(0.25); - $AxisY->setTitle('Small interval', 'vertical'); - } elseif ($row > 1) { - $AxisY->setLabelInterval(2); - $AxisY->setTitle('Changed interval', 'vertical'); - } else { - $AxisY->setTitle('Default interval', 'vertical'); - } - - if ($col > 1) { - $Plot =& $Plotarea->addNew('bar', $DS[$col]); - $Plot->setLineColor('gray'); - $Plot->setFillColor('blue@0.2'); - } else { - $Plot =& $Plotarea->addNew('line', $DS[$col]); - $Plot->setLineColor('red'); - } - - $Plotarea->setBackgroundColor('blue@0.2'); - } - } -} - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/axis/logarithmic.php b/includes/pear/Image/tests/axis/logarithmic.php deleted file mode 100644 index fe66c64c..00000000 --- a/includes/pear/Image/tests/axis/logarithmic.php +++ /dev/null @@ -1,84 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: logarithmic.php,v 1.4 2005/08/03 21:21:58 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(600, 400)); -// add a TrueType font -$Font =& $Graph->addNew('ttf_font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(7); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Testing Logarihtmic Axis', 10)), - $Matrix = Image_Graph::factory('Image_Graph_Layout_Matrix', array(2, 2, false)), - 5 - ) -); - -$Matrix->setEntry(0, 0, Image_Graph::factory('plotarea', array('axis', 'axis'))); -$Matrix->setEntry(0, 1, Image_Graph::factory('plotarea', array('axis', 'axis_log'))); -$Matrix->setEntry(1, 0, Image_Graph::factory('plotarea', array('axis_log', 'axis'))); -$Matrix->setEntry(1, 1, Image_Graph::factory('plotarea', array('axis_log', 'axis_log'))); - -function sqr($x) { return $x * $x; } - -$DS =& Image_Graph::factory('function', array(1, 10, 'sqr', 9)); - -for ($row = 0; $row < 2; $row++) { - for ($col = 0; $col < 2; $col++) { - $Plotarea =& $Matrix->getEntry($row, $col); - - $AxisX =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_X); - if (is_a($AxisX, 'Image_Graph_Axis_Logarithmic')) { - $AxisX->setTitle('Logarithmic'); - } else { - $AxisX->setTitle('Normal'); - } - - $AxisY =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y); - if (is_a($AxisY, 'Image_Graph_Axis_Logarithmic')) { - $AxisY->setTitle('Logarithmic', 'vertical'); - } else { - $AxisY->setTitle('Normal', 'vertical'); - } - - $Plot =& $Plotarea->addNew('line', $DS); - $Plot->setLineColor('red'); - } -} - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/canvas_body.php b/includes/pear/Image/tests/canvas_body.php deleted file mode 100644 index 6371a56c..00000000 --- a/includes/pear/Image/tests/canvas_body.php +++ /dev/null @@ -1,326 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: canvas_body.php,v 1.4 2005/08/16 21:27:58 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -$canvas->addText(array('x' => 5, 'y' => 5, 'text' => 'Line')); - -$canvas->setLineColor('black'); -$canvas->line(array('x0' => 100, 'x1' => 195, 'y0' => 5, 'y1' => 5)); -$canvas->setLineColor('red'); -$canvas->line(array('x0' => 200, 'x1' => 295, 'y0' => 5, 'y1' => 5)); -$canvas->setLineColor('green'); -$canvas->line(array('x0' => 300, 'x1' => 395, 'y0' => 5, 'y1' => 5)); -$canvas->setLineColor('blue'); -$canvas->line(array('x0' => 400, 'x1' => 495, 'y0' => 5, 'y1' => 5)); - -$canvas->setLineColor(array('blue', 'red')); -$canvas->line(array('x0' => 100, 'x1' => 195, 'y0' => 10, 'y1' => 10)); - -$canvas->setLineColor(array('blue', 'blue', 'transparent')); -$canvas->line(array('x0' => 200, 'x1' => 295, 'y0' => 10, 'y1' => 10)); - -$canvas->setLineColor('yellow'); -$canvas->setLineThickness(2); -$canvas->line(array('x0' => 300, 'x1' => 395, 'y0' => 10, 'y1' => 10)); - -$canvas->setLineColor('red'); -$canvas->setLineThickness(4); -$canvas->line(array('x0' => 400, 'x1' => 495, 'y0' => 10, 'y1' => 10)); - -$canvas->setLineColor('black@0.4'); -$canvas->setLineThickness(4); -$canvas->line(array('x0' => 100, 'x1' => 220, 'y0' => 15, 'y1' => 15)); -$canvas->setLineColor('red@0.4'); -$canvas->setLineThickness(4); -$canvas->line(array('x0' => 200, 'x1' => 320, 'y0' => 15, 'y1' => 15)); -$canvas->setLineColor('green@0.4'); -$canvas->setLineThickness(4); -$canvas->line(array('x0' => 300, 'x1' => 420, 'y0' => 15, 'y1' => 15)); -$canvas->setLineColor('blue@0.4'); -$canvas->setLineThickness(4); -$canvas->line(array('x0' => 400, 'x1' => 495, 'y0' => 15, 'y1' => 15)); - -$canvas->addText(array('x' => 5, 'y' => 30, 'text' => 'Rectangle')); - -$canvas->setLineColor('black'); -$canvas->rectangle(array('x0' => 100, 'x1' => 150, 'y0' => 30, 'y1' => 80)); -$canvas->setLineColor('red'); -$canvas->rectangle(array('x0' => 155, 'x1' => 205, 'y0' => 30, 'y1' => 80)); -$canvas->setLineColor('green'); -$canvas->rectangle(array('x0' => 210, 'x1' => 260, 'y0' => 30, 'y1' => 80)); -$canvas->setLineColor('blue'); -$canvas->rectangle(array('x0' => 265, 'x1' => 315, 'y0' => 30, 'y1' => 80)); - -$canvas->setFillColor('black'); -$canvas->rectangle(array('x0' => 100, 'x1' => 150, 'y0' => 85, 'y1' => 135)); -$canvas->setLineColor('black'); -$canvas->setFillColor('red'); -$canvas->rectangle(array('x0' => 155, 'x1' => 205, 'y0' => 85, 'y1' => 135)); -$canvas->setLineColor('black'); -$canvas->setFillColor('green'); -$canvas->rectangle(array('x0' => 210, 'x1' => 260, 'y0' => 85, 'y1' => 135)); -$canvas->setLineColor('black'); -$canvas->setFillColor('blue'); -$canvas->rectangle(array('x0' => 265, 'x1' => 315, 'y0' => 85, 'y1' => 135)); - -$canvas->setLineColor('red'); -$canvas->setFillColor('red@0.3'); -$canvas->rectangle(array('x0' => 340, 'x1' => 400, 'y0' => 30, 'y1' => 90)); -$canvas->setLineColor('green'); -$canvas->setFillColor('green@0.3'); -$canvas->rectangle(array('x0' => 380, 'x1' => 440, 'y0' => 50, 'y1' => 110)); -$canvas->setLineColor('blue'); -$canvas->setFillColor('blue@0.3'); -$canvas->rectangle(array('x0' => 360, 'x1' => 420, 'y0' => 70, 'y1' => 130)); - -$canvas->addText(array('x' => 90, 'y' => 140, 'text' => "Circle / Ellipse", 'alignment' => array('horizontal' => 'right'))); - -$canvas->setLineColor('black'); -$canvas->ellipse(array('x' => 130, 'y' => 170, 'rx' => 30, 'ry' => 30)); -$canvas->setLineColor('red'); -$canvas->ellipse(array('x' => 195, 'y' => 170, 'rx' => 30, 'ry' => 30)); -$canvas->setLineColor('blue'); -$canvas->ellipse(array('x' => 250, 'y' => 170, 'rx' => 30, 'ry' => 30)); -$canvas->setLineColor('green'); -$canvas->ellipse(array('x' => 305, 'y' => 170, 'rx' => 30, 'ry' => 30)); - -$canvas->setFillColor('black'); -$canvas->ellipse(array('x' => 130, 'y' => 235, 'rx' => 30, 'ry' => 30)); -$canvas->setLineColor('black'); -$canvas->setFillColor('red'); -$canvas->ellipse(array('x' => 195, 'y' => 235, 'rx' => 30, 'ry' => 30)); -$canvas->setLineColor('black'); -$canvas->setFillColor('blue'); -$canvas->ellipse(array('x' => 250, 'y' => 235, 'rx' => 30, 'ry' => 30)); -$canvas->setLineColor('black'); -$canvas->setFillColor('green'); -$canvas->ellipse(array('x' => 305, 'y' => 235, 'rx' => 30, 'ry' => 30)); - -$canvas->setLineColor('brown'); -$canvas->setFillColor('brown@0.3'); -$canvas->ellipse(array('x' => 400, 'y' => 200, 'rx' => 40, 'ry' => 40)); -$canvas->setLineColor('orange'); -$canvas->setFillColor('orange@0.3'); -$canvas->ellipse(array('x' => 430, 'y' => 220, 'rx' => 30, 'ry' => 40)); -$canvas->setLineColor('purple'); -$canvas->setFillColor('purple@0.3'); -$canvas->ellipse(array('x' => 390, 'y' => 230, 'rx' => 40, 'ry' => 20)); - -$canvas->addText(array('x' => 5, 'y' => 270, 'text' => 'Pie slices')); - -$c = 0; -for ($i = 360; $i >= 45; $i -= 30) { - $canvas->setLineColor('black'); - $canvas->setFillColor('blue@' . sprintf('%0.1f', ((360 - $i) / 360))); - $canvas->pieslice( - array( - 'x' => 130 + $c * 55, - 'y' => 295, - 'rx' => 25, - 'ry' => 25, - 'v1' => 0, - 'v2' => $i - ) - ); - $c++; -} - -$canvas->addText(array('x' => 5, 'y' => 325, 'text' => 'Polygon')); - -$canvas->setLineColor('green'); -for ($i = 0; $i < 8; $i++) { - $canvas->addVertex(array('x' => 115 + $i * 50, 'y' => 330)); - $canvas->addVertex(array('x' => 100 + $i * 50, 'y' => 325)); - $canvas->addVertex(array('x' => 125 + $i * 50, 'y' => 350)); -} -$canvas->polygon(array('connect' => false)); - -$canvas->setLineColor('purple'); -$canvas->setFillColor('purple@0.3'); -for ($i = 0; $i < 8; $i++) { - $canvas->addVertex(array('x' => 100 + $i * 50, 'y' => 355)); - $canvas->addVertex(array('x' => 125 + $i * 50, 'y' => 380 + 2 * $i)); -} -$canvas->addVertex(array('x' => 550, 'y' => 355)); -for ($i = 4; $i >= 0; $i--) { - $canvas->addVertex(array('x' => 120 + $i * 100, 'y' => 430 + $i * 5)); - $canvas->addVertex(array('x' => 110 + $i * 100, 'y' => 405 - $i * 5)); -} -$canvas->polygon(array('connect' => true)); - -$canvas->addText(array('x' => 5, 'y' => 455, 'text' => 'Splines')); - -$points = array(); -$points[] = array( - 'x' => 100, 'y' => 470, - 'p1x' => 120, 'p1y' => 455, - 'p2x' => 150, 'p2y' => 460 -); - -$points[] = array( - 'x' => 170, 'y' => 490, - 'p1x' => 190, 'p1y' => 500, - 'p2x' => 200, 'p2y' => 510 -); - -$points[] = array( - 'x' => 210, 'y' => 540, - 'p1x' => 200, 'p1y' => 550, - 'p2x' => 160, 'p2y' => 560 -); - -$points[] = array( - 'x' => 120, 'y' => 480 -); - -// draw control points! not directly a canvas test! -foreach ($points as $point) { - if (isset($last)) { - $canvas->setLineColor('gray@0.2'); - $canvas->line(array('x0' => $last['p2x'], 'y0' => $last['p2y'], 'x1' => $point['x'], 'y1' => $point['y'])); - } - - $canvas->setLineColor('red'); - $canvas->ellipse(array('x' => $point['x'], 'y' => $point['y'], 'rx' => 3, 'ry' => 3)); - - if (isset($point['p1x'])) { - $canvas->setLineColor('green'); - $canvas->ellipse(array('x' => $point['p1x'], 'y' => $point['p1y'], 'rx' => 2, 'ry' => 2)); - $canvas->setLineColor('green'); - $canvas->ellipse(array('x' => $point['p2x'], 'y' => $point['p2y'], 'rx' => 2, 'ry' => 2)); - - $canvas->setLineColor('gray@0.2'); - $canvas->line(array('x0' => $point['x'], 'y0' => $point['y'], 'x1' => $point['p1x'], 'y1' => $point['p1y'])); - $canvas->setLineColor('gray@0.2'); - $canvas->line(array('x0' => $point['p1x'], 'y0' => $point['p1y'], 'x1' => $point['p2x'], 'y1' => $point['p2y'])); - - $last = $point; - } -} - -foreach ($points as $point) { - if (isset($point['p1x'])) { - $canvas->addSpline($point); - } else { - $canvas->addVertex($point); - } -} - -$canvas->setLineColor('black'); -$canvas->polygon(array('connect' => false)); - -$points = array(); -$points[] = array( - 'x' => 220, 'y' => 470, - 'p1x' => 240, 'p1y' => 455, - 'p2x' => 270, 'p2y' => 460 -); - -$points[] = array( - 'x' => 240, 'y' => 490, - 'p1x' => 310, 'p1y' => 460, - 'p2x' => 320, 'p2y' => 470 -); - -$points[] = array( - 'x' => 330, 'y' => 500, - 'p1x' => 320, 'p1y' => 550, - 'p2x' => 280, 'p2y' => 560 -); - -$points[] = array( - 'x' => 240, 'y' => 520, - 'p1x' => 230, 'p1y' => 490, - 'p2x' => 225, 'p2y' => 490 -); - -$points[] = array( - 'x' => 220, 'y' => 470 -); - -unset($last); -// draw control points! not directly a canvas test! -foreach ($points as $point) { - if (isset($last)) { - $canvas->setLineColor('gray@0.2'); - $canvas->line(array('x0' => $last['p2x'], 'y0' => $last['p2y'], 'x1' => $point['x'], 'y1' => $point['y'])); - } - - $canvas->setLineColor('red'); - $canvas->ellipse(array('x' => $point['x'], 'y' => $point['y'], 'rx' => 3, 'ry' => 3)); - - if (isset($point['p1x'])) { - $canvas->setLineColor('green'); - $canvas->ellipse(array('x' => $point['p1x'], 'y' => $point['p1y'], 'rx' => 2, 'ry' => 2)); - $canvas->setLineColor('green'); - $canvas->ellipse(array('x' => $point['p2x'], 'y' => $point['p2y'], 'rx' => 2, 'ry' => 2)); - - $canvas->setLineColor('gray@0.2'); - $canvas->line(array('x0' => $point['x'], 'y0' => $point['y'], 'x1' => $point['p1x'], 'y1' => $point['p1y'])); - $canvas->setLineColor('gray@0.2'); - $canvas->line(array('x0' => $point['p1x'], 'y0' => $point['p1y'], 'x1' => $point['p2x'], 'y1' => $point['p2y'])); - - $last = $point; - } -} - -foreach ($points as $point) { - if (isset($point['p1x'])) { - $canvas->addSpline($point); - } else { - $canvas->addVertex($point); - } -} - -$canvas->setLineColor('black'); -$canvas->setFillColor('red@0.2'); -$canvas->polygon(array('connect' => true)); - -$canvas->addText(array('x' => 375, 'y' => 455, 'text' => 'Image')); - -$canvas->image(array('x' => 445, 'y' => 455, 'filename' => './pear-icon.png', 'url' => 'http://pear.veggerby.dk/', 'target' => '_blank')); - -$canvas->image(array('x' => 445, 'y' => 495, 'filename' => './pear-icon.png', 'width' => 20, 'height' => 20)); - -$canvas->image(array('x' => 445, 'y' => 523, 'filename' => './pear-icon.png', 'width' => 40, 'height' => 40)); - -//$canvas->show(); -$type = basename($_SERVER['SCRIPT_NAME'], '.php'); -$canvas->toHtml( - array( - 'filename' => 'test' . $type . '.' . $type, - 'urlpath' => '', - 'filepath' => './', - 'width' => '100%', - 'height' => '100%' - ) -); - -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/freetype.php b/includes/pear/Image/tests/freetype.php deleted file mode 100644 index 5e8718a8..00000000 --- a/includes/pear/Image/tests/freetype.php +++ /dev/null @@ -1,70 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: freetype.php,v 1.2 2005/02/21 20:49:58 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -// SPECIFY HERE WHERE A TRUETYPE FONT CAN BE FOUND -$testFont = 'c:/windows/fonts/Arial.ttf'; - -if (!file_exists($testFont)) { - die('The font specified cannot be found (' . $testFont .')! Please specify an existing font'); -} - -// create a true color image (requires GD2) -$image = ImageCreateTrueColor(600, 200); -ImageAlphaBlending($image, true); - -// allocate some colors -$black = ImageColorAllocate($image, 0, 0, 0); -$red = ImageColorAllocate($image, 0xff, 0, 0); -$green = ImageColorAllocate($image, 0, 0xff, 0); -$blue = ImageColorAllocate($image, 0, 0, 0xff); -$white = ImageColorAllocate($image, 0xff, 0xff, 0xff); - -// create a frame -ImageFilledRectangle($image, 0, 0, 599, 199, $white); -ImageRectangle($image, 0, 0, 599, 199, $black); - -// output some text using the specified font -$y = 20; -$text = 'Your Freetype installation with GD works'; -for ($i = 12; $i <= 20; $i++) { - $box = ImageTTFBbox($i, 0, $testFont, $text); - $x = 300 - (max($box[0], $box[2], $box[4], $box[6]) - min($box[0], $box[2], $box[4], $box[6])) / 2; - ImageTTFText($image, $i, 0, $x, $y, $black, $testFont, $text); - $y += max($box[1], $box[3], $box[5], $box[7]) - min($box[1], $box[3], $box[5], $box[7]); -} - -// output the test image -header('Content-Type: image/png'); -ImagePNG($image); - -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/gd.php b/includes/pear/Image/tests/gd.php deleted file mode 100644 index f673f74c..00000000 --- a/includes/pear/Image/tests/gd.php +++ /dev/null @@ -1,75 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: gd.php,v 1.2 2005/02/21 20:49:58 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -// create a true color image (requires GD2) -$image = ImageCreateTrueColor(400, 300); -ImageAlphaBlending($image, true); - -// allocate some colors -$black = ImageColorAllocate($image, 0, 0, 0); -$red = ImageColorAllocate($image, 0xff, 0, 0); -$green = ImageColorAllocate($image, 0, 0xff, 0); -$blue = ImageColorAllocate($image, 0, 0, 0xff); -$white = ImageColorAllocate($image, 0xff, 0xff, 0xff); - -// create a frame -ImageFilledRectangle($image, 0, 0, 399, 299, $white); -ImageRectangle($image, 0, 0, 399, 299, $black); - -// draw some lines -ImageLine($image, 200, 50, 350, 150, $red); -ImageLine($image, 200, 60, 350, 160, $green); -ImageLine($image, 200, 70, 350, 170, $blue); - -// draw some overlapping alpha blended boxes -$redAlpha = ImageColorAllocateAlpha($image, 0xff, 0, 0, 75); -$blueAlpha = ImageColorAllocateAlpha($image, 0, 0xff, 0, 75); -$greenAlpha = ImageColorAllocateAlpha($image, 0, 0, 0xff, 75); - -ImageFilledRectangle($image, 50, 50, 90, 90, $redAlpha); -ImageFilledRectangle($image, 60, 80, 100, 120, $greenAlpha); -ImageFilledRectangle($image, 80, 60, 120, 100, $blueAlpha); - -// write some _default_ text -for ($font = 1; $font <= 5; $font++) { - ImageString($image, $font, 50, 150 + $font * 20, 'Testing GD output', $black); -} - -ImageString($image, 3, 51, 21, 'Congratulations! The GD2 installation works', $black); -ImageString($image, 3, 50, 20, 'Congratulations! The GD2 installation works', $red); - -// output the test image -header('Content-Type: image/png'); -ImagePNG($image); - -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/gradients.php b/includes/pear/Image/tests/gradients.php deleted file mode 100644 index a3187cc1..00000000 --- a/includes/pear/Image/tests/gradients.php +++ /dev/null @@ -1,87 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: gradients.php,v 1.2 2005/08/03 21:17:48 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -require_once 'Image/Canvas.php'; - -$canvas =& Image_Canvas::factory( - 'png', - array('width' => 605, 'height' => 350) -); - -$gradient = array( - 'type' => 'gradient', - 'start' => 'yellow', - 'end' => 'maroon' -); - -$directions = array('horizontal', 'vertical', 'horizontal_mirror', 'vertical_mirror', 'diagonal_tl_br', 'diagonal_bl_tr', 'radial'); - -$space = 10; -$size = 75; - -$canvas->setLineColor('black'); -$canvas->rectangle(array('x0' => 0, 'y0' => 0, 'x1' => $canvas->getWidth() - 1, 'y1' => $canvas->getHeight() - 1)); - -$i = 0; -foreach ($directions as $direction) { - $gradient['direction'] = $direction; - - $x = $space + ($i * ($size + $space)); - - $y = $space; - $canvas->setGradientFill($gradient); - $canvas->rectangle(array('x0' => $x, 'y0' => $y, 'x1' => $x + $size, 'y1' => $y + $size)); - - $y += $size + $space; - $canvas->setGradientFill($gradient); - $canvas->ellipse(array('x' => $x + $size / 2, 'y' => $y + $size / 2, 'rx' => $size / 2, 'ry' => $size / 2)); - - $y += $size + $space; - $canvas->setGradientFill($gradient); - $canvas->pieslice(array('x' => $x + $size / 2, 'y' => $y + $size / 2, 'rx' => $size / 2, 'ry' => $size / 2, 'v1' => 45, 'v2' => 270)); - - $y += $size + $space; - $points = array(); - $points[] = array('x' => $x + $size / 3, 'y' => $y); - $points[] = array('x' => $x + $size, 'y' => $y + $size / 2); - $points[] = array('x' => $x + $size / 3, 'y' => $y + 3 * $size / 4); - $points[] = array('x' => $x + $size / 5, 'y' => $y + $size); - $points[] = array('x' => $x, 'y' => $y + $size / 3); - $y += $size + $space; - $canvas->setGradientFill($gradient); - foreach ($points as $point) { - $canvas->addVertex($point); - } - $canvas->polygon(array('connect' => true)); - $i++; -} - -$canvas->show(); - -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/imagemap.php b/includes/pear/Image/tests/imagemap.php deleted file mode 100644 index 31d81f77..00000000 --- a/includes/pear/Image/tests/imagemap.php +++ /dev/null @@ -1,180 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: imagemap.php,v 1.4 2005/08/10 20:01:05 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -require_once 'Image/Canvas.php'; - -$canvas =& Image_Canvas::factory( - 'png', - array('width' => 800, 'height' => 500, 'usemap' => true, 'antialias' => 'native') -); - -$canvas->setLineColor('black'); -$canvas->rectangle(array('x0' => 0, 'y0' => 0, 'x1' => $canvas->getWidth() - 1, 'y1' => $canvas->getHeight() - 1)); - - -$canvas->setLineColor('gray'); -$canvas->line( - array( - 'x0' => 450, - 'y0' => 50, - 'x1' => 550, - 'y1' => 100, - 'url' => 'http://pear.veggerby.dk/', - 'target' => '_blank', - 'alt' => 'Line', - 'mapsize' => 5 - ) -); - -$canvas->setLineColor('gray'); -$canvas->line( - array( - 'x0' => 600, - 'y0' => 125, - 'x1' => 700, - 'y1' => 50, - 'url' => 'http://pear.veggerby.dk/', - 'target' => '_blank', - 'alt' => 'Line', - 'mapsize' => 5 - ) -); - -$canvas->setLineColor('blue'); -$canvas->rectangle( - array( - 'x0' => 50, - 'y0' => 50, - 'x1' => 350, - 'y1' => 100, - 'url' => 'http://pear.veggerby.dk/', - 'target' => '_blank', - 'alt' => 'Rectangle' - ) -); - -$canvas->setLineColor('red'); -$canvas->ellipse( - array( - 'x' => 200, - 'y' => 200, - 'rx' => 75, - 'ry' => 75, - 'url' => 'http://pear.php.net/Image_Graph/', - 'alt' => 'Circle' - ) -); - -$canvas->setLineColor('brown'); -$canvas->ellipse( - array( - 'x' => 500, - 'y' => 200, - 'rx' => 100, - 'ry' => 75, - 'url' => 'http://pear.php.net/Image_Graph/', - 'alt' => 'Ellipse' - ) -); - -$canvas->setLineColor('green'); -for ($i = 0; $i < 8; $i++) { - $canvas->addVertex(array('x' => 115 + $i * 50, 'y' => 330, 'alt' => 'Vertex #' . $i * 3, 'url' => 'test?id=' . $i * 3)); - $canvas->addVertex(array('x' => 100 + $i * 50, 'y' => 325, 'alt' => 'Vertex #' . ($i * 3 + 1), 'url' => 'test?id=' . ($i * 3 + 1))); - $canvas->addVertex(array('x' => 125 + $i * 50, 'y' => 350, 'alt' => 'Vertex #' . ($i * 3 + 2), 'url' => 'test?id=' . ($i * 3 + 2))); -} -$canvas->polygon( - array( - 'connect' => false, - 'url' => 'http://php.net/', - 'alt' => 'Open polygon', - 'map_vertices' => true - ) -); - -$canvas->setLineColor('purple'); -for ($i = 0; $i < 8; $i++) { - $canvas->addVertex(array('x' => 100 + $i * 50, 'y' => 355)); - $canvas->addVertex(array('x' => 125 + $i * 50, 'y' => 380 + 2 * $i)); -} -$canvas->addVertex(array('x' => 550, 'y' => 355)); -for ($i = 4; $i >= 0; $i--) { - $canvas->addVertex(array('x' => 120 + $i * 100, 'y' => 430 + $i * 5)); - $canvas->addVertex(array('x' => 110 + $i * 100, 'y' => 405 - $i * 5)); -} -$canvas->polygon( - array( - 'connect' => true, - 'url' => 'http://pear.php.net/', - 'alt' => 'Closed polygon' - ) -); - -$canvas->setLineColor('orange'); -$canvas->pieslice( - array( - 'x' => 600, - 'y' => 400, - 'rx' => 50, - 'ry' => 50, - 'v1' => 10, - 'v2' => 350, - 'url' => 'http://www.dr.dk/', - 'alt' => 'Pieslice' - ) -); - -$canvas->setLineColor('silver'); -$canvas->pieslice( - array( - 'x' => 700, - 'y' => 300, - 'rx' => 100, - 'ry' => 50, - 'v1' => 45, - 'v2' => 275, - 'srx' => 25, - 'sry' => 10, - 'url' => 'http://www.dr.dk/', - 'alt' => 'Donut slice', - 'htmltags' => array( - 'onMouseOver' => 'alert("Hello, World!");' - ) - ) -); - -print $canvas->toHtml( - array( - 'filename' => 'imagemap.png', - 'filepath' => './', - 'urlpath' => '' - ) -); - -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/jpg.php b/includes/pear/Image/tests/jpg.php deleted file mode 100644 index 05994d11..00000000 --- a/includes/pear/Image/tests/jpg.php +++ /dev/null @@ -1,39 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: jpg.php,v 1.2 2005/08/03 21:17:48 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -// SPECIFY HERE WHERE A TRUETYPE FONT CAN BE FOUND -$testFont = 'c:/windows/fonts/Arial.ttf'; - -require_once 'Image/Canvas.php'; - -$canvas =& Image_Canvas::factory('jpg', array('width' => 600, 'height' => 600, 'quality' => 90)); - -require_once './canvas_body.php'; - -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/lineends.php b/includes/pear/Image/tests/lineends.php deleted file mode 100644 index d21ff797..00000000 --- a/includes/pear/Image/tests/lineends.php +++ /dev/null @@ -1,85 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: lineends.php,v 1.3 2005/08/04 19:24:39 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -require_once 'Image/Canvas.php'; - -$font = array('name' => 'Verdana', 'size' => 10); - -$canvas =& Image_Canvas::factory( - 'png', - array('width' => 300, 'height' => 300) -); - -$shapes = array('arrow', 'box', 'diamond', 'arrow2', 'lollipop', 'line'); - -$j = 0; -for ($i = 0; $i < 360; $i += 30) { - $x0 = 150; - $y0 = 150; - if ($j >= count($shapes)) { - $j = 0; - } - $shape1 = $shapes[$j]; $j++; - - if ($j >= count($shapes)) { - $j = 0; - } - $shape2 = $shapes[$j]; $j++; - - $canvas->setLineColor('black'); - $canvas->line( - array( - 'x0' => $x0 + cos(deg2rad($i)) * 50, - 'y0' => $y0 - sin(deg2rad($i)) * 50, - 'x1' => $x0 + cos(deg2rad($i)) * 100, - 'y1' => $y0 - sin(deg2rad($i)) * 100, - 'end0' => $shape1, - 'size0' => 8, - 'color0' => 'red', - 'end1' => $shape2, - 'color1' => 'green', - 'size1' => 8 - ) - ); - $canvas->setFont($font); - $canvas->addText( - array( - 'x' => $x0 + cos(deg2rad($i)) * 125, - 'y' => $y0 - sin(deg2rad($i)) * 125, - 'text' => $i, - 'alignment' => array( - 'horizontal' => ((($i > 90) && ($i < 270)) ? 'right' : ((($i == 90) || ($i == 270)) ? 'center' : 'left')), - 'vertical' => (($i < 180) ? 'bottom' : ((($i == 0) || ($i == 180)) ? 'center' : 'top')), - ) - ) - ); -} -$canvas->show(); - -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/pdf.php b/includes/pear/Image/tests/pdf.php deleted file mode 100644 index efc503e3..00000000 --- a/includes/pear/Image/tests/pdf.php +++ /dev/null @@ -1,39 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: pdf.php,v 1.2 2005/08/03 21:17:48 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -// SPECIFY HERE WHERE A TRUETYPE FONT CAN BE FOUND -$testFont = 'c:/windows/fonts/Arial.ttf'; - -require_once 'Image/Canvas.php'; - -$canvas =& Image_Canvas::factory('pdf', array('page' => 'A4', 'align' => 'center', 'width' => 600, 'height' => 600)); - -require_once './canvas_body.php'; - -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/pear-icon.png b/includes/pear/Image/tests/pear-icon.png deleted file mode 100644 index 26118f113cee46860251f693ae8693432583aa9d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 927 zcmV;Q17Q4#P)}wZaU8($-`UPCXXfUndD(2{nwplHW?~nWoOmfJ zih?o~ipmFjkfeM0P;a6T6i85n^pH>(m_~({u8`s^$kJtPWx6drE_de6wzIRX2k9l} z{IA+ezsLXo{J)>`aQJfoLOd7%tiK+ry0!*5p=$q{e*?(FS2h&hyi(Q~5};VMuWj$U z9C=ZP?$*LxJlGtcE69--t&80fA&i`He4nAsb$Lx+W=CrumROxLe+#IjX=k>yWXBb_ zJT$}70$jxBiU8p8r#pV@!2!vUnODlX2%fOlaAU&y!3$mt!<6Fmf`qCA>2*Wq=kKQm z{v6<7+`7DGAAc$|L-RA!vWRcJbN zO#(b@_v*7;4i5ligj_Aloqu3WbZ)Lf^K!f^I6#0C*|7y0)!yyN)wJ8{WU0-{iuwA& zSsj%f1b_inrmi@Ybv99&=5SLOfQTpAlX?MPqz(WgUiiXA|9}7|&gWm>mQ-b)8|&0H zo9&-9iAPk@^*D#WSRDXJ+Jp+6-h8b*sj`2v{jKStQj$@uIuzL(riMlp1A}eruetHb|Mo8__K-{u~>dccm^3@3WVn=elLY#_Hw=>j@ zq04@^e!q*hChmz4M!hjV%8V^VtOLNLO>d+ONWjJwrAFH*?Ve3rUWix+02vWO@WPM) zwJhCe`xq{W67!?b0jY4gQj&}W5O|n_wGntYh6Qnxb2+$JAVmULuN&v^STBQK2LK=V zoGgt5j9bSd2_@y4c6t0C@H=*fnxOPZz@V{DDOuz3vEQuk(1B5MXxcuB1oRo&agI8PmaKo69_;+sy4bFtPvvU=8N(0V z_M|$>MYauJBT`^>@zrtKZ3_aRT$YBuDvQIiE9I0@vNphBJ40Q1c6fNIKfoJs z0YJXv_tjY^*{#1TBVvkIRm+Gtzb6MKd(QRj*P5ONsGB;M`gK&x(#zEcv*PmO#cCl= zuwJ)$?%VKGf4Bbbpt0BM^9HB`fVSp8_%{vt`~)fJKZgDv!iN9=002ovPDHLkV1gAM B!&m?S diff --git a/includes/pear/Image/tests/plot/area.php b/includes/pear/Image/tests/plot/area.php deleted file mode 100644 index b7669f52..00000000 --- a/includes/pear/Image/tests/plot/area.php +++ /dev/null @@ -1,79 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: area.php,v 1.5 2005/08/03 21:21:58 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(600, 400)); -// add a TrueType font -$Font =& $Graph->addNew('ttf_font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(7); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Testing Area Plots', 10)), - $Matrix = Image_Graph::factory('Image_Graph_Layout_Matrix', array(2, 2)), - 5 - ) -); - -$DS[0][0] =& Image_Graph::factory('dataset', array(array('A' => 1, 'B' => 2, 'C' => 0, 'D' => 4, 'E' => 3))); -$DS[0][1] =& Image_Graph::factory('dataset', array(array('A' => 1, 'B' => -2, 'C' => 1, 'D' => 3, 'E' => -1))); -$DS[1][0] =& Image_Graph::factory('dataset', array(array('A' => 2, 'B' => 3, 'C' => 1, 'D' => 4, 'E' => 2))); -$DS[1][1] =& Image_Graph::factory('dataset', array(array('A' => -1, 'B' => -3, 'C' => -2, 'D' => -4, 'E' => -1))); - -for ($row = 0; $row < 2; $row++) { - for ($col = 0; $col < 2; $col++) { - if (isset($DS[$row][$col])) { - $Plotarea =& $Matrix->getEntry($row, $col); - - $Plot =& $Plotarea->addNew('area', $DS[$row][$col]); - $Plot->setLineColor('gray'); - $Plot->setFillColor('blue@0.2'); - } - } -} - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/plot/bar.php b/includes/pear/Image/tests/plot/bar.php deleted file mode 100644 index 7cec368c..00000000 --- a/includes/pear/Image/tests/plot/bar.php +++ /dev/null @@ -1,79 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: bar.php,v 1.5 2005/08/03 21:21:58 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(600, 400)); -// add a TrueType font -$Font =& $Graph->addNew('ttf_font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(7); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Testing Area Plots', 10)), - $Matrix = Image_Graph::factory('Image_Graph_Layout_Matrix', array(2, 2)), - 5 - ) -); - -$DS[0][0] =& Image_Graph::factory('dataset', array(array('A' => 1, 'B' => 2, 'C' => 0, 'D' => 4, 'E' => 3))); -$DS[0][1] =& Image_Graph::factory('dataset', array(array('A' => 1, 'B' => -2, 'C' => 1, 'D' => 3, 'E' => -1))); -$DS[1][0] =& Image_Graph::factory('dataset', array(array('A' => 2, 'B' => 3, 'C' => 1, 'D' => 4, 'E' => 2))); -$DS[1][1] =& Image_Graph::factory('dataset', array(array('A' => -1, 'B' => -3, 'C' => -2, 'D' => -4, 'E' => -1))); - -for ($row = 0; $row < 2; $row++) { - for ($col = 0; $col < 2; $col++) { - if (isset($DS[$row][$col])) { - $Plotarea =& $Matrix->getEntry($row, $col); - - $Plot =& $Plotarea->addNew('bar', $DS[$row][$col]); - $Plot->setLineColor('gray'); - $Plot->setFillColor('blue@0.2'); - } - } -} - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/plot/horizontal/area.php b/includes/pear/Image/tests/plot/horizontal/area.php deleted file mode 100644 index c68d37a9..00000000 --- a/includes/pear/Image/tests/plot/horizontal/area.php +++ /dev/null @@ -1,92 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: area.php,v 1.1 2005/08/27 17:27:32 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(600, 400)); -// add a TrueType font -$Font =& $Graph->addNew('ttf_font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(7); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Testing Area Plots', 10)), - $Matrix = Image_Graph::factory('Image_Graph_Layout_Matrix', array(2, 2, false)), - 5 - ) -); - -for ($i = 0; $i < 2; $i++) { - for ($j = 0; $j < 2; $j++) { - $Matrix->setEntry( - $i, - $j, - Image_Graph::factory( - 'plotarea', - array('Image_Graph_Axis_Category', 'axis', 'horizontal') - ) - ); - } -} - -$DS[0][0] =& Image_Graph::factory('dataset', array(array('A' => 1, 'B' => 2, 'C' => 0, 'D' => 4, 'E' => 3))); -$DS[0][1] =& Image_Graph::factory('dataset', array(array('A' => 1, 'B' => -2, 'C' => 1, 'D' => 3, 'E' => -1))); -$DS[1][0] =& Image_Graph::factory('dataset', array(array('A' => 2, 'B' => 3, 'C' => 1, 'D' => 4, 'E' => 2))); -$DS[1][1] =& Image_Graph::factory('dataset', array(array('A' => -1, 'B' => -3, 'C' => -2, 'D' => -4, 'E' => -1))); - -for ($row = 0; $row < 2; $row++) { - for ($col = 0; $col < 2; $col++) { - if (isset($DS[$row][$col])) { - $Plotarea =& $Matrix->getEntry($row, $col); - - $Plot =& $Plotarea->addNew('area', $DS[$row][$col]); - $Plot->setLineColor('gray'); - $Plot->setFillColor('blue@0.2'); - } - } -} - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/plot/horizontal/bar.php b/includes/pear/Image/tests/plot/horizontal/bar.php deleted file mode 100644 index 83e12583..00000000 --- a/includes/pear/Image/tests/plot/horizontal/bar.php +++ /dev/null @@ -1,92 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: bar.php,v 1.1 2005/08/27 17:27:32 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(600, 400)); -// add a TrueType font -$Font =& $Graph->addNew('ttf_font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(7); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Testing Area Plots', 10)), - $Matrix = Image_Graph::factory('Image_Graph_Layout_Matrix', array(2, 2, false)), - 5 - ) -); - -for ($i = 0; $i < 2; $i++) { - for ($j = 0; $j < 2; $j++) { - $Matrix->setEntry( - $i, - $j, - Image_Graph::factory( - 'plotarea', - array('Image_Graph_Axis_Category', 'axis', 'horizontal') - ) - ); - } -} - -$DS[0][0] =& Image_Graph::factory('dataset', array(array('A' => 1, 'B' => 2, 'C' => 0, 'D' => 4, 'E' => 3))); -$DS[0][1] =& Image_Graph::factory('dataset', array(array('A' => 1, 'B' => -2, 'C' => 1, 'D' => 3, 'E' => -1))); -$DS[1][0] =& Image_Graph::factory('dataset', array(array('A' => 2, 'B' => 3, 'C' => 1, 'D' => 4, 'E' => 2))); -$DS[1][1] =& Image_Graph::factory('dataset', array(array('A' => -1, 'B' => -3, 'C' => -2, 'D' => -4, 'E' => -1))); - -for ($row = 0; $row < 2; $row++) { - for ($col = 0; $col < 2; $col++) { - if (isset($DS[$row][$col])) { - $Plotarea =& $Matrix->getEntry($row, $col); - - $Plot =& $Plotarea->addNew('bar', $DS[$row][$col]); - $Plot->setLineColor('gray'); - $Plot->setFillColor('blue@0.2'); - } - } -} - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/plot/horizontal/impulse.php b/includes/pear/Image/tests/plot/horizontal/impulse.php deleted file mode 100644 index e8d8331c..00000000 --- a/includes/pear/Image/tests/plot/horizontal/impulse.php +++ /dev/null @@ -1,91 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: impulse.php,v 1.1 2005/08/27 17:27:32 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(600, 400)); -// add a TrueType font -$Font =& $Graph->addNew('ttf_font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(7); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Testing Area Plots', 10)), - $Matrix = Image_Graph::factory('Image_Graph_Layout_Matrix', array(2, 2, false)), - 5 - ) -); - -for ($i = 0; $i < 2; $i++) { - for ($j = 0; $j < 2; $j++) { - $Matrix->setEntry( - $i, - $j, - Image_Graph::factory( - 'plotarea', - array('Image_Graph_Axis_Category', 'axis', 'horizontal') - ) - ); - } -} - -$DS[0][0] =& Image_Graph::factory('dataset', array(array('A' => 1, 'B' => 2, 'C' => 0, 'D' => 4, 'E' => 3))); -$DS[0][1] =& Image_Graph::factory('dataset', array(array('A' => 1, 'B' => -2, 'C' => 1, 'D' => 3, 'E' => -1))); -$DS[1][0] =& Image_Graph::factory('dataset', array(array('A' => 2, 'B' => 3, 'C' => 1, 'D' => 4, 'E' => 2))); -$DS[1][1] =& Image_Graph::factory('dataset', array(array('A' => -1, 'B' => -3, 'C' => -2, 'D' => -4, 'E' => -1))); - -for ($row = 0; $row < 2; $row++) { - for ($col = 0; $col < 2; $col++) { - if (isset($DS[$row][$col])) { - $Plotarea =& $Matrix->getEntry($row, $col); - - $Plot =& $Plotarea->addNew('impulse', $DS[$row][$col]); - $Plot->setLineColor('red'); - } - } -} - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/plot/horizontal/line.php b/includes/pear/Image/tests/plot/horizontal/line.php deleted file mode 100644 index 84e5a3cf..00000000 --- a/includes/pear/Image/tests/plot/horizontal/line.php +++ /dev/null @@ -1,91 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: line.php,v 1.1 2005/08/27 17:27:32 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(600, 400)); -// add a TrueType font -$Font =& $Graph->addNew('ttf_font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(7); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Testing Line Plots', 10)), - $Matrix = Image_Graph::factory('Image_Graph_Layout_Matrix', array(2, 2, false)), - 5 - ) -); - -for ($i = 0; $i < 2; $i++) { - for ($j = 0; $j < 2; $j++) { - $Matrix->setEntry( - $i, - $j, - Image_Graph::factory( - 'plotarea', - array('Image_Graph_Axis_Category', 'axis', 'horizontal') - ) - ); - } -} - -$DS[0][0] =& Image_Graph::factory('dataset', array(array('A' => 1, 'B' => 2, 'C' => 0, 'D' => 4, 'E' => 3))); -$DS[0][1] =& Image_Graph::factory('dataset', array(array('A' => 1, 'B' => -2, 'C' => 1, 'D' => 3, 'E' => -1))); -$DS[1][0] =& Image_Graph::factory('dataset', array(array('A' => 2, 'B' => 3, 'C' => 1, 'D' => 4, 'E' => 2))); -$DS[1][1] =& Image_Graph::factory('dataset', array(array('A' => -1, 'B' => -3, 'C' => -2, 'D' => -4, 'E' => -1))); - -for ($row = 0; $row < 2; $row++) { - for ($col = 0; $col < 2; $col++) { - if (isset($DS[$row][$col])) { - $Plotarea =& $Matrix->getEntry($row, $col); - - $Plot =& $Plotarea->addNew('line', $DS[$row][$col]); - $Plot->setLineColor('red'); - } - } -} - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/plot/horizontal/step.php b/includes/pear/Image/tests/plot/horizontal/step.php deleted file mode 100644 index 8c817ce9..00000000 --- a/includes/pear/Image/tests/plot/horizontal/step.php +++ /dev/null @@ -1,92 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: step.php,v 1.1 2005/08/27 17:27:32 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(600, 400)); -// add a TrueType font -$Font =& $Graph->addNew('ttf_font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(7); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Testing Area Plots', 10)), - $Matrix = Image_Graph::factory('Image_Graph_Layout_Matrix', array(2, 2, false)), - 5 - ) -); - -for ($i = 0; $i < 2; $i++) { - for ($j = 0; $j < 2; $j++) { - $Matrix->setEntry( - $i, - $j, - Image_Graph::factory( - 'plotarea', - array('Image_Graph_Axis_Category', 'axis', 'horizontal') - ) - ); - } -} - -$DS[0][0] =& Image_Graph::factory('dataset', array(array('A' => 1, 'B' => 2, 'C' => 0, 'D' => 4, 'E' => 3))); -$DS[0][1] =& Image_Graph::factory('dataset', array(array('A' => 1, 'B' => -2, 'C' => 1, 'D' => 3, 'E' => -1))); -$DS[1][0] =& Image_Graph::factory('dataset', array(array('A' => 2, 'B' => 3, 'C' => 1, 'D' => 4, 'E' => 2))); -$DS[1][1] =& Image_Graph::factory('dataset', array(array('A' => -1, 'B' => -3, 'C' => -2, 'D' => -4, 'E' => -1))); - -for ($row = 0; $row < 2; $row++) { - for ($col = 0; $col < 2; $col++) { - if (isset($DS[$row][$col])) { - $Plotarea =& $Matrix->getEntry($row, $col); - - $Plot =& $Plotarea->addNew('step', $DS[$row][$col]); - $Plot->setLineColor('gray'); - $Plot->setFillColor('blue@0.2'); - } - } -} - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/plot/impulse.php b/includes/pear/Image/tests/plot/impulse.php deleted file mode 100644 index f456ba71..00000000 --- a/includes/pear/Image/tests/plot/impulse.php +++ /dev/null @@ -1,78 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: impulse.php,v 1.5 2005/08/03 21:21:58 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(600, 400)); -// add a TrueType font -$Font =& $Graph->addNew('ttf_font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(7); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Testing Area Plots', 10)), - $Matrix = Image_Graph::factory('Image_Graph_Layout_Matrix', array(2, 2)), - 5 - ) -); - -$DS[0][0] =& Image_Graph::factory('dataset', array(array('A' => 1, 'B' => 2, 'C' => 0, 'D' => 4, 'E' => 3))); -$DS[0][1] =& Image_Graph::factory('dataset', array(array('A' => 1, 'B' => -2, 'C' => 1, 'D' => 3, 'E' => -1))); -$DS[1][0] =& Image_Graph::factory('dataset', array(array('A' => 2, 'B' => 3, 'C' => 1, 'D' => 4, 'E' => 2))); -$DS[1][1] =& Image_Graph::factory('dataset', array(array('A' => -1, 'B' => -3, 'C' => -2, 'D' => -4, 'E' => -1))); - -for ($row = 0; $row < 2; $row++) { - for ($col = 0; $col < 2; $col++) { - if (isset($DS[$row][$col])) { - $Plotarea =& $Matrix->getEntry($row, $col); - - $Plot =& $Plotarea->addNew('impulse', $DS[$row][$col]); - $Plot->setLineColor('red'); - } - } -} - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/plot/line.php b/includes/pear/Image/tests/plot/line.php deleted file mode 100644 index 0a857f24..00000000 --- a/includes/pear/Image/tests/plot/line.php +++ /dev/null @@ -1,78 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: line.php,v 1.5 2005/08/03 21:21:58 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(600, 400)); -// add a TrueType font -$Font =& $Graph->addNew('ttf_font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(7); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Testing Line Plots', 10)), - $Matrix = Image_Graph::factory('Image_Graph_Layout_Matrix', array(2, 2)), - 5 - ) -); - -$DS[0][0] =& Image_Graph::factory('dataset', array(array('A' => 1, 'B' => 2, 'C' => 0, 'D' => 4, 'E' => 3))); -$DS[0][1] =& Image_Graph::factory('dataset', array(array('A' => 1, 'B' => -2, 'C' => 1, 'D' => 3, 'E' => -1))); -$DS[1][0] =& Image_Graph::factory('dataset', array(array('A' => 2, 'B' => 3, 'C' => 1, 'D' => 4, 'E' => 2))); -$DS[1][1] =& Image_Graph::factory('dataset', array(array('A' => -1, 'B' => -3, 'C' => -2, 'D' => -4, 'E' => -1))); - -for ($row = 0; $row < 2; $row++) { - for ($col = 0; $col < 2; $col++) { - if (isset($DS[$row][$col])) { - $Plotarea =& $Matrix->getEntry($row, $col); - - $Plot =& $Plotarea->addNew('line', $DS[$row][$col]); - $Plot->setLineColor('red'); - } - } -} - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/plot/step.php b/includes/pear/Image/tests/plot/step.php deleted file mode 100644 index fa9c21a3..00000000 --- a/includes/pear/Image/tests/plot/step.php +++ /dev/null @@ -1,79 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: step.php,v 1.5 2005/08/03 21:21:58 nosey Exp $ - * @link http://pear.php.net/package/Image_Graph - */ - -require_once 'Image/Graph.php'; - -// create the graph -$Graph =& Image_Graph::factory('graph', array(600, 400)); -// add a TrueType font -$Font =& $Graph->addNew('ttf_font', 'Verdana'); -// set the font size to 11 pixels -$Font->setSize(7); - -$Graph->setFont($Font); - -// create the plotarea -$Graph->add( - Image_Graph::vertical( - Image_Graph::factory('title', array('Testing Area Plots', 10)), - $Matrix = Image_Graph::factory('Image_Graph_Layout_Matrix', array(2, 2)), - 5 - ) -); - -$DS[0][0] =& Image_Graph::factory('dataset', array(array('A' => 1, 'B' => 2, 'C' => 0, 'D' => 4, 'E' => 3))); -$DS[0][1] =& Image_Graph::factory('dataset', array(array('A' => 1, 'B' => -2, 'C' => 1, 'D' => 3, 'E' => -1))); -$DS[1][0] =& Image_Graph::factory('dataset', array(array('A' => 2, 'B' => 3, 'C' => 1, 'D' => 4, 'E' => 2))); -$DS[1][1] =& Image_Graph::factory('dataset', array(array('A' => -1, 'B' => -3, 'C' => -2, 'D' => -4, 'E' => -1))); - -for ($row = 0; $row < 2; $row++) { - for ($col = 0; $col < 2; $col++) { - if (isset($DS[$row][$col])) { - $Plotarea =& $Matrix->getEntry($row, $col); - - $Plot =& $Plotarea->addNew('step', $DS[$row][$col]); - $Plot->setLineColor('gray'); - $Plot->setFillColor('blue@0.2'); - } - } -} - -$Graph->done(); -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/png.php b/includes/pear/Image/tests/png.php deleted file mode 100644 index 899a7125..00000000 --- a/includes/pear/Image/tests/png.php +++ /dev/null @@ -1,39 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: png.php,v 1.2 2005/08/03 21:17:48 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -// SPECIFY HERE WHERE A TRUETYPE FONT CAN BE FOUND -$testFont = 'c:/windows/fonts/Arial.ttf'; - -require_once 'Image/Canvas.php'; - -$canvas =& Image_Canvas::factory('png', array('width' => 600, 'height' => 600)); - -require_once './canvas_body.php'; - -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/svg.php b/includes/pear/Image/tests/svg.php deleted file mode 100644 index cc8a4b0e..00000000 --- a/includes/pear/Image/tests/svg.php +++ /dev/null @@ -1,39 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: svg.php,v 1.2 2005/08/03 21:17:48 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -// SPECIFY HERE WHERE A TRUETYPE FONT CAN BE FOUND -$testFont = 'c:/windows/fonts/Arial.ttf'; - -require_once 'Image/Canvas.php'; - -$canvas =& Image_Canvas::factory('svg', array('width' => 600, 'height' => 600)); - -require_once './canvas_body.php'; - -?> \ No newline at end of file diff --git a/includes/pear/Image/tests/text.php b/includes/pear/Image/tests/text.php deleted file mode 100644 index b43f6707..00000000 --- a/includes/pear/Image/tests/text.php +++ /dev/null @@ -1,109 +0,0 @@ - - * @copyright Copyright (C) 2003, 2004 Jesper Veggerby Hansen - * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 - * @version CVS: $Id: text.php,v 1.2 2005/08/03 21:17:48 nosey Exp $ - * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=212 - */ - -require_once 'Image/Canvas.php'; - -$canvas =& Image_Canvas::factory( - 'png', - array('width' => 300, 'height' => 200) -); - -$canvas->setLineColor('black'); -$canvas->rectangle(array('x0' => 0, 'y0' => 0, 'x1' => $canvas->getWidth() - 1, 'y1' => $canvas->getHeight() - 1)); - -$canvas->setLineColor('lightgrey@0.3'); -$canvas->rectangle(array('x0' => 10, 'y0' => 10, 'x1' => 290, 'y1' => 190)); -$canvas->setLineColor('lightgrey@0.3'); -$canvas->line(array('x0' => 10, 'y0' => 100, 'x1' => 290, 'y1' => 100)); -$canvas->setLineColor('lightgrey@0.3'); -$canvas->rectangle(array('x0' => 150, 'y0' => 10, 'x1' => 150, 'y1' => 190)); - -$font = array('name' => 'Verdana', 'size' => 10); - -$align = array( - array( - array('horizontal' => 'left', 'vertical' => 'top'), - array('horizontal' => 'center', 'vertical' => 'top'), - array('horizontal' => 'right', 'vertical' => 'top') - ), - array( - array('horizontal' => 'left', 'vertical' => 'center'), - array('horizontal' => 'center', 'vertical' => 'center'), - array('horizontal' => 'right', 'vertical' => 'center') - ), - array( - array('horizontal' => 'left', 'vertical' => 'bottom'), - array('horizontal' => 'center', 'vertical' => 'bottom'), - array('horizontal' => 'right', 'vertical' => 'bottom') - ) -); - -for ($row = 0; $row < 3; $row++) { - for ($col = 0; $col < 3; $col++) { - $x = 10 + $col * 140; - $y = 10 + $row * 90; - - switch ($row) { - case 0: - $text = 'Top'; - break; - case 1: - $text = 'Center'; - break; - case 2: - $text = 'Bottom'; - break; - } - switch ($col) { - case 0: - $text .= "\n" . 'Left'; - break; - case 1: - if ($row !== 1) { - $text .= "\n" . 'Center'; - } - break; - case 2: - $text .= "\n" . 'Right'; - break; - } - - $canvas->setLineColor('red'); - $canvas->line(array('x0' => $x - 5, 'y0' => $y, 'x1' => $x + 5, 'y1' => $y)); - $canvas->setLineColor('red'); - $canvas->line(array('x0' => $x, 'y0' => $y - 5, 'x1' => $x, 'y1' => $y + 5)); - - $canvas->setFont($font); - $canvas->addText(array('x' => $x, 'y' => $y, 'text' => $text, 'alignment' => $align[$row][$col])); - } -} - -$canvas->show(); - -?> \ No newline at end of file diff --git a/includes/pear/OS/Guess.php b/includes/pear/OS/Guess.php index 47411406..d266e701 100644 --- a/includes/pear/OS/Guess.php +++ b/includes/pear/OS/Guess.php @@ -14,9 +14,9 @@ * @package PEAR * @author Stig Bakken * @author Gregory Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Guess.php,v 1.20 2005/10/26 19:33:03 cellog Exp $ + * @version CVS: $Id: Guess.php,v 1.26 2008/01/03 20:26:34 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since PEAR 0.1 */ @@ -91,9 +91,9 @@ * @package PEAR * @author Stig Bakken * @author Gregory Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ @@ -201,11 +201,14 @@ class OS_Guess if ($glibc !== false) { return $glibc; // no need to run this multiple times } + $major = $minor = 0; include_once "System.php"; - if (!file_exists('/usr/bin/cpp') || !is_executable('/usr/bin/cpp')) { - // Use glibc's header file to - // get major and minor version number: - if ($features_file = @fopen('/usr/include/features.h', 'rb') ) { + // Use glibc's header file to + // get major and minor version number: + if (@file_exists('/usr/include/features.h') && + @is_readable('/usr/include/features.h')) { + if (!@file_exists('/usr/bin/cpp') || !@is_executable('/usr/bin/cpp')) { + $features_file = fopen('/usr/include/features.h', 'rb'); while (!feof($features_file)) { $line = fgets($features_file, 8192); if (!$line || (strpos($line, '#define') === false)) { @@ -236,29 +239,27 @@ class OS_Guess return $glibc = ''; } return $glibc = 'glibc' . trim($glibc_major) . "." . trim($glibc_minor) ; + } // no cpp + $tmpfile = System::mktemp("glibctest"); + $fp = fopen($tmpfile, "w"); + fwrite($fp, "#include \n__GLIBC__ __GLIBC_MINOR__\n"); + fclose($fp); + $cpp = popen("/usr/bin/cpp $tmpfile", "r"); + while ($line = fgets($cpp, 1024)) { + if ($line{0} == '#' || trim($line) == '') { + continue; + } + if (list($major, $minor) = explode(' ', trim($line))) { + break; + } } - return $glibc = ''; - } - $tmpfile = System::mktemp("glibctest"); - $fp = fopen($tmpfile, "w"); - fwrite($fp, "#include \n__GLIBC__ __GLIBC_MINOR__\n"); - fclose($fp); - $cpp = popen("/usr/bin/cpp $tmpfile", "r"); - $major = $minor = 0; - while ($line = fgets($cpp, 1024)) { - if ($line{0} == '#' || trim($line) == '') { - continue; - } - if (list($major, $minor) = explode(' ', trim($line))) { - break; - } - } - pclose($cpp); - unlink($tmpfile); - if (!($major && $minor) && is_link('/lib/libc.so.6')) { + pclose($cpp); + unlink($tmpfile); + } // features.h + if (!($major && $minor) && @is_link('/lib/libc.so.6')) { // Let's try reading the libc.so.6 symlink - if (ereg('^libc-([.*])\.so$', basename(readlink('/lib/libc.so.6')), $matches)) { - list($major, $minor) = explode('.', $matches); + if (ereg('^libc-(.*)\.so$', basename(readlink('/lib/libc.so.6')), $matches)) { + list($major, $minor) = explode('.', $matches[1]); } } if (!($major && $minor)) { diff --git a/includes/pear/PEAR.php b/includes/pear/PEAR.php index ed7c8c55..4c24c600 100644 --- a/includes/pear/PEAR.php +++ b/includes/pear/PEAR.php @@ -18,9 +18,9 @@ * @author Stig Bakken * @author Tomas V.V.Cox * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: PEAR.php,v 1.96 2005/09/21 00:12:35 cellog Exp $ + * @version CVS: $Id: PEAR.php,v 1.104 2008/01/03 20:26:34 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ @@ -91,9 +91,9 @@ $GLOBALS['_PEAR_error_handler_stack'] = array(); * @author Stig Bakken * @author Tomas V.V. Cox * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2006 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @see PEAR_Error * @since Class available since PHP 4.0.2 @@ -230,6 +230,12 @@ class PEAR function &getStaticProperty($class, $var) { static $properties; + if (!isset($properties[$class])) { + $properties[$class] = array(); + } + if (!array_key_exists($var, $properties[$class])) { + $properties[$class][$var] = null; + } return $properties[$class][$var]; } @@ -247,6 +253,12 @@ class PEAR */ function registerShutdownFunc($func, $args = array()) { + // if we are called statically, there is a potential + // that no shutdown func is registered. Bug #6445 + if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) { + register_shutdown_function("_PEAR_call_destructors"); + $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true; + } $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args); } @@ -553,13 +565,17 @@ class PEAR } else { $ec = 'PEAR_Error'; } - if ($skipmsg) { - $a = &new $ec($code, $mode, $options, $userinfo); - return $a; - } else { - $a = &new $ec($message, $code, $mode, $options, $userinfo); + if (intval(PHP_VERSION) < 5) { + // little non-eval hack to fix bug #12147 + include 'PEAR/FixPHP5PEARWarnings.php'; return $a; } + if ($skipmsg) { + $a = new $ec($code, $mode, $options, $userinfo); + } else { + $a = new $ec($message, $code, $mode, $options, $userinfo); + } + return $a; } // }}} @@ -761,7 +777,7 @@ function _PEAR_call_destructors() sizeof($_PEAR_destructor_object_list)) { reset($_PEAR_destructor_object_list); - if (@PEAR::getStaticProperty('PEAR', 'destructlifo')) { + if (PEAR::getStaticProperty('PEAR', 'destructlifo')) { $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list); } while (list($k, $objref) = each($_PEAR_destructor_object_list)) { @@ -800,9 +816,9 @@ function _PEAR_call_destructors() * @author Stig Bakken * @author Tomas V.V. Cox * @author Gregory Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2006 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/manual/en/core.pear.pear-error.php * @see PEAR::raiseError(), PEAR::throwError() * @since Class available since PHP 4.0.2 @@ -852,9 +868,10 @@ class PEAR_Error $this->code = $code; $this->mode = $mode; $this->userinfo = $userinfo; - if (function_exists("debug_backtrace")) { - if (@!PEAR::getStaticProperty('PEAR_Error', 'skiptrace')) { - $this->backtrace = debug_backtrace(); + if (!PEAR::getStaticProperty('PEAR_Error', 'skiptrace')) { + $this->backtrace = debug_backtrace(); + if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) { + unset($this->backtrace[0]['object']); } } if ($mode & PEAR_ERROR_CALLBACK) { @@ -1033,6 +1050,12 @@ class PEAR_Error } } + // }}} + // {{{ toString() + function __toString() + { + return $this->getMessage(); + } // }}} // {{{ toString() diff --git a/includes/pear/PEAR/Autoloader.php b/includes/pear/PEAR/Autoloader.php index d79545d3..07c4de10 100644 --- a/includes/pear/PEAR/Autoloader.php +++ b/includes/pear/PEAR/Autoloader.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Stig Bakken - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Autoloader.php,v 1.12 2005/03/21 00:51:26 cellog Exp $ + * @version CVS: $Id: Autoloader.php,v 1.14 2008/01/03 20:26:34 cellog Exp $ * @link http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader * @since File available since Release 0.1 * @deprecated File deprecated in Release 1.4.0a1 @@ -48,9 +48,9 @@ require_once "PEAR.php"; * @category pear * @package PEAR * @author Stig Bakken - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader * @since File available since Release 0.1 * @deprecated File deprecated in Release 1.4.0a1 diff --git a/includes/pear/PEAR/Builder.php b/includes/pear/PEAR/Builder.php index dda183f5..f7986c00 100644 --- a/includes/pear/PEAR/Builder.php +++ b/includes/pear/PEAR/Builder.php @@ -14,11 +14,14 @@ * @package PEAR * @author Stig Bakken * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Builder.php,v 1.26 2005/09/27 03:34:01 cellog Exp $ + * @version CVS: $Id: Builder.php,v 1.34 2008/05/12 23:43:21 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 + * + * TODO: log output parameters in PECL command line + * TODO: msdev path in configuration */ /** @@ -33,9 +36,9 @@ require_once 'PEAR/PackageFile.php'; * @package PEAR * @author Stig Bakken * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since PHP 4.0.2 * @see http://pear.php.net/manual/en/core.ppm.pear-builder.php @@ -50,6 +53,10 @@ class PEAR_Builder extends PEAR_Common var $extensions_built = array(); + /** + * @var string Used for reporting when it is not possible to pass function + * via extra parameter, e.g. log, msdevCallback + */ var $current_callback = null; // used for msdev builds @@ -83,6 +90,7 @@ class PEAR_Builder extends PEAR_Common { if (is_object($descfile)) { $pkg = $descfile; + $descfile = $pkg->getPackageFile(); } else { $pf = &new PEAR_PackageFile($this->config, $this->debug); $pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL); @@ -90,22 +98,31 @@ class PEAR_Builder extends PEAR_Common return $pkg; } } - $dir = dirname($pkg->getArchiveFile()); + $dir = dirname($descfile); $old_cwd = getcwd(); - if (!@chdir($dir)) { + if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) { return $this->raiseError("could not chdir to $dir"); } + // packages that were in a .tar have the packagefile in this directory + $vdir = $pkg->getPackage() . '-' . $pkg->getVersion(); + if (file_exists($dir) && is_dir($vdir)) { + if (chdir($vdir)) { + $dir = getcwd(); + } else { + return $this->raiseError("could not chdir to " . realpath($vdir)); + } + } + $this->log(2, "building in $dir"); $dsp = $pkg->getPackage().'.dsp'; - if (!@is_file("$dir/$dsp")) { + if (!file_exists("$dir/$dsp")) { return $this->raiseError("The DSP $dsp does not exist."); } // XXX TODO: make release build type configurable - $command = 'msdev '.$dsp.' /MAKE "'.$info['package']. ' - Release"'; + $command = 'msdev '.$dsp.' /MAKE "'.$pkg->getPackage(). ' - Release"'; - $this->current_callback = $callback; $err = $this->_runCommand($command, array(&$this, 'msdevCallback')); if (PEAR::isError($err)) { return $err; @@ -147,7 +164,8 @@ class PEAR_Builder extends PEAR_Common } else { return $this->raiseError("Could not retrieve output information from $dsp."); } - if (@copy($outfile, "$dir/$out")) { + // realpath returns false if the file doesn't exist + if ($outfile && copy($outfile, "$dir/$out")) { $outfile = "$dir/$out"; } @@ -168,6 +186,7 @@ class PEAR_Builder extends PEAR_Common if (!$this->_firstline) $this->_firstline = $data; $this->_lastline = $data; + call_user_func($this->current_callback, $what, $data); } // }}} @@ -241,6 +260,7 @@ class PEAR_Builder extends PEAR_Common */ function build($descfile, $callback = null) { + $this->current_callback = $callback; if (PEAR_OS == "Windows") { return $this->_build_win32($descfile,$callback); } @@ -250,16 +270,23 @@ class PEAR_Builder extends PEAR_Common if (is_object($descfile)) { $pkg = $descfile; $descfile = $pkg->getPackageFile(); + if (is_a($pkg, 'PEAR_PackageFile_v1')) { + $dir = dirname($descfile); + } else { + $dir = $pkg->_config->get('temp_dir') . '/' . $pkg->getName(); + // automatically delete at session end + $this->addTempFile($dir); + } } else { $pf = &new PEAR_PackageFile($this->config); $pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL); if (PEAR::isError($pkg)) { return $pkg; } + $dir = dirname($descfile); } - $dir = dirname($descfile); $old_cwd = getcwd(); - if (!@chdir($dir)) { + if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) { return $this->raiseError("could not chdir to $dir"); } $vdir = $pkg->getPackage() . '-' . $pkg->getVersion(); @@ -268,7 +295,6 @@ class PEAR_Builder extends PEAR_Common } $dir = getcwd(); $this->log(2, "building in $dir"); - $this->current_callback = $callback; putenv('PATH=' . $this->config->get('bin_dir') . ':' . getenv('PATH')); $err = $this->_runCommand("phpize", array(&$this, 'phpizeCallback')); if (PEAR::isError($err)) { @@ -283,10 +309,11 @@ class PEAR_Builder extends PEAR_Common $configure_options = $pkg->getConfigureOptions(); if ($configure_options) { foreach ($configure_options as $o) { + $default = array_key_exists('default', $o) ? $o['default'] : null; list($r) = $this->ui->userDialog('build', array($o['prompt']), array('text'), - array(@$o['default'])); + array($default)); if (substr($o['name'], 0, 5) == 'with-' && ($r == 'yes' || $r == 'autodetect')) { $configure_command .= " --$o[name]"; @@ -326,12 +353,12 @@ class PEAR_Builder extends PEAR_Common $configure_command, $make_command, "$make_command INSTALL_ROOT=\"$inst_dir\" install", - "find \"$inst_dir\" -ls" + "find \"$inst_dir\" | xargs ls -dils" ); - if (!@chdir($build_dir)) { + if (!file_exists($build_dir) || !is_dir($build_dir) || !chdir($build_dir)) { return $this->raiseError("could not chdir to $build_dir"); } - putenv('PHP_PEAR_VERSION=1.4.5'); + putenv('PHP_PEAR_VERSION=1.7.2'); foreach ($to_run as $cmd) { $err = $this->_runCommand($cmd, $callback); if (PEAR::isError($err)) { @@ -412,7 +439,7 @@ class PEAR_Builder extends PEAR_Common function _runCommand($command, $callback = null) { $this->log(1, "running: $command"); - $pp = @popen("$command 2>&1", "r"); + $pp = popen("$command 2>&1", "r"); if (!$pp) { return $this->raiseError("failed to run `$command'"); } @@ -431,7 +458,11 @@ class PEAR_Builder extends PEAR_Common if ($callback && isset($olddbg)) { $callback[0]->debug = $olddbg; } - $exitcode = @pclose($pp); + if (is_resource($pp)) { + $exitcode = pclose($pp); + } else { + $exitcode = -1; + } return ($exitcode == 0); } diff --git a/includes/pear/PEAR/ChannelFile.php b/includes/pear/PEAR/ChannelFile.php index 86bcc3d4..46dd691b 100644 --- a/includes/pear/PEAR/ChannelFile.php +++ b/includes/pear/PEAR/ChannelFile.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: ChannelFile.php,v 1.73 2005/08/21 05:01:37 cellog Exp $ + * @version CVS: $Id: ChannelFile.php,v 1.80 2008/01/03 20:26:34 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -150,9 +150,9 @@ $GLOBALS['_PEAR_CHANNELS_MIRROR_TYPES'] = array('server'); * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -284,7 +284,7 @@ class PEAR_ChannelFile { if ($result !== true) { if ($result->getCode() == 1) { $this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_XML_EXT, 'error', - array('error' => $error)); + array('error' => $result->getMessage())); } else { $this->_stack->push(PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER, 'error'); } @@ -324,6 +324,20 @@ class PEAR_ChannelFile { } return $a; } + + /** + * Unlike {@link fromArray()} this does not do any validation + * @param array + * @static + * @return PEAR_ChannelFile + */ + function &fromArrayWithErrors($data, $compatibility = false, + $stackClass = 'PEAR_ErrorStack') + { + $a = new PEAR_ChannelFile($compatibility, $stackClass); + $a->_fromArray($data); + return $a; + } /** * @param array @@ -377,21 +391,16 @@ class PEAR_ChannelFile { */ function fromXmlFile($descfile) { - if (!@is_file($descfile) || !is_readable($descfile) || - (!$fp = @fopen($descfile, 'r'))) { + if (!file_exists($descfile) || !is_file($descfile) || !is_readable($descfile) || + (!$fp = fopen($descfile, 'r'))) { require_once 'PEAR.php'; return PEAR::raiseError("Unable to open $descfile"); } // read the whole thing so we only get one cdata callback // for each block of cdata - if (function_exists('file_get_contents')) { - fclose($fp); - $data = file_get_contents($descfile); - } else { - $data = fread($fp, filesize($descfile)); - fclose($fp); - } + fclose($fp); + $data = file_get_contents($descfile); return $this->fromXmlString($data); } @@ -664,8 +673,11 @@ class PEAR_ChannelFile { $this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME); } if (!isset($info['validatepackage']['attribs']['version'])) { + $content = isset($info['validatepackage']['_content']) ? + $info['validatepackage']['_content'] : + null; $this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION, - array('package' => @$info['validatepackage']['_content'])); + array('package' => $content)); } } if (isset($info['servers']['primary']['attribs']['port']) && @@ -699,7 +711,6 @@ class PEAR_ChannelFile { if (!isset($info['servers']['mirror'][0])) { $info['servers']['mirror'] = array($info['servers']['mirror']); } - $i = 0; foreach ($info['servers']['mirror'] as $mirror) { if (!isset($mirror['attribs']['host'])) { $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_HOST, @@ -1002,10 +1013,8 @@ class PEAR_ChannelFile { } else { return false; } - $server = $mirror; } else { $rest = $this->_channelInfo['servers']['primary']['rest']; - $server = $this->getServer(); } if (!isset($rest['baseurl'][0])) { $rest['baseurl'] = array($rest['baseurl']); @@ -1143,7 +1152,6 @@ class PEAR_ChannelFile { array('mirror' => $mirror)); return false; } - $setmirror = false; if (isset($this->_channelInfo['servers']['mirror'][0])) { foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { if ($mirror == $mir['attribs']['host']) { @@ -1176,7 +1184,6 @@ class PEAR_ChannelFile { array('mirror' => $mirror)); return false; } - $setmirror = false; if (isset($this->_channelInfo['servers']['mirror'][0])) { foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { if ($mirror == $mir['attribs']['host']) { @@ -1231,7 +1238,6 @@ class PEAR_ChannelFile { array('mirror' => $mirror)); return false; } - $setmirror = false; if (isset($this->_channelInfo['servers']['mirror'][0])) { foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { if ($mirror == $mir['attribs']['host']) { @@ -1343,6 +1349,7 @@ class PEAR_ChannelFile { if (isset($this->_channelInfo['name'])) { return $this->_channelInfo['name']; } + return ''; } /** @@ -1376,6 +1383,12 @@ class PEAR_ChannelFile { } $set = array('attribs' => array('version' => $version), '_content' => $name); if (!isset($this->_channelInfo['servers']['primary'][$type]['function'])) { + if (!isset($this->_channelInfo['servers'])) { + $this->_channelInfo['servers'] = array('primary' => + array($type => array())); + } elseif (!isset($this->_channelInfo['servers']['primary'])) { + $this->_channelInfo['servers']['primary'] = array($type => array()); + } $this->_channelInfo['servers']['primary'][$type]['function'] = $set; $this->_isValid = false; return true; @@ -1395,7 +1408,6 @@ class PEAR_ChannelFile { */ function addMirrorFunction($mirror, $type, $version, $name = '') { - $found = false; if (!isset($this->_channelInfo['servers']['mirror'])) { $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, array('mirror' => $mirror)); @@ -1440,7 +1452,6 @@ class PEAR_ChannelFile { function setBaseURL($resourceType, $url, $mirror = false) { if ($mirror) { - $found = false; if (!isset($this->_channelInfo['servers']['mirror'])) { $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, array('mirror' => $mirror)); @@ -1463,6 +1474,9 @@ class PEAR_ChannelFile { $setmirror = &$this->_channelInfo['servers']['primary']; } $set = array('attribs' => array('type' => $resourceType), '_content' => $url); + if (!isset($setmirror['rest'])) { + $setmirror['rest'] = array(); + } if (!isset($setmirror['rest']['baseurl'])) { $setmirror['rest']['baseurl'] = $set; $this->_isValid = false; diff --git a/includes/pear/PEAR/ChannelFile/Parser.php b/includes/pear/PEAR/ChannelFile/Parser.php index ed6f9802..88402439 100644 --- a/includes/pear/PEAR/ChannelFile/Parser.php +++ b/includes/pear/PEAR/ChannelFile/Parser.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Parser.php,v 1.3 2005/03/21 01:43:00 cellog Exp $ + * @version CVS: $Id: Parser.php,v 1.5 2008/01/03 20:26:36 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -30,9 +30,9 @@ require_once 'PEAR/ChannelFile.php'; * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ diff --git a/includes/pear/PEAR/Command.php b/includes/pear/PEAR/Command.php index 89cb4f82..38fe69c9 100644 --- a/includes/pear/PEAR/Command.php +++ b/includes/pear/PEAR/Command.php @@ -14,9 +14,9 @@ * @package PEAR * @author Stig Bakken * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Command.php,v 1.35 2005/11/01 05:39:23 cellog Exp $ + * @version CVS: $Id: Command.php,v 1.39 2008/01/03 20:26:34 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ @@ -34,6 +34,12 @@ require_once 'PEAR/XMLParser.php'; */ $GLOBALS['_PEAR_Command_commandlist'] = array(); +/** + * List of commands and their descriptions + * @var array command => description + */ +$GLOBALS['_PEAR_Command_commanddesc'] = array(); + /** * List of shortcuts to common commands. * @var array shortcut => command @@ -92,9 +98,9 @@ $GLOBALS['_PEAR_Command_objects'] = array(); * @package PEAR * @author Stig Bakken * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ @@ -231,6 +237,9 @@ class PEAR_Command if ($dir === null) { $dir = dirname(__FILE__) . '/Command'; } + if (!is_dir($dir)) { + return PEAR::raiseError("registerCommands: opendir($dir) '$dir' does not exist or is not a directory"); + } $dp = @opendir($dir); if (empty($dp)) { return PEAR::raiseError("registerCommands: opendir($dir) failed"); diff --git a/includes/pear/PEAR/Command/Auth.php b/includes/pear/PEAR/Command/Auth.php index ea169131..005235b6 100644 --- a/includes/pear/PEAR/Command/Auth.php +++ b/includes/pear/PEAR/Command/Auth.php @@ -14,9 +14,9 @@ * @package PEAR * @author Stig Bakken * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Auth.php,v 1.21 2005/04/13 04:29:15 cellog Exp $ + * @version CVS: $Id: Auth.php,v 1.31 2008/01/03 20:26:36 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ @@ -34,9 +34,9 @@ require_once 'PEAR/Config.php'; * @package PEAR * @author Stig Bakken * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ @@ -50,8 +50,9 @@ class PEAR_Command_Auth extends PEAR_Command_Common 'shortcut' => 'li', 'function' => 'doLogin', 'options' => array(), - 'doc' => ' -Log in to the remote server. To use remote functions in the installer + 'doc' => ' +Log in to a remote channel server. If is not supplied, +the default channel is used. To use remote functions in the installer that require any kind of privileges, you need to log in first. The username and password you enter here will be stored in your per-user PEAR configuration (~/.pearrc on Unix-like systems). After logging @@ -106,13 +107,23 @@ password from your user configuration.', function doLogin($command, $options, $params) { $reg = &$this->config->getRegistry(); - $channel = $this->config->get('default_channel'); + + // If a parameter is supplied, use that as the channel to log in to + if (isset($params[0])) { + $channel = $params[0]; + } else { + $channel = $this->config->get('default_channel'); + } + $chan = $reg->getChannel($channel); - $server = $this->config->get('preferred_mirror'); + if (PEAR::isError($chan)) { + return $this->raiseError($chan); + } + $server = $this->config->get('preferred_mirror', null, $channel); $remote = &$this->config->getRemote(); - $username = $this->config->get('username'); + $username = $this->config->get('username', null, $channel); if (empty($username)) { - $username = @$_ENV['USER']; + $username = isset($_ENV['USER']) ? $_ENV['USER'] : null; } $this->ui->outputData("Logging in to $server.", $command); @@ -124,9 +135,14 @@ password from your user configuration.', ); $username = trim($username); $password = trim($password); - - $this->config->set('username', $username); - $this->config->set('password', $password); + + $ourfile = $this->config->getConfFile('user'); + if (!$ourfile) { + $ourfile = $this->config->getConfFile('system'); + } + + $this->config->set('username', $username, 'user', $channel); + $this->config->set('password', $password, 'user', $channel); if ($chan->supportsREST()) { $ok = true; @@ -137,7 +153,11 @@ password from your user configuration.', } if ($ok === true) { $this->ui->outputData("Logged in.", $command); - $this->config->store(); + // avoid changing any temporary settings changed with -d + $ourconfig = new PEAR_Config($ourfile, $ourfile); + $ourconfig->set('username', $username, 'user', $channel); + $ourconfig->set('password', $password, 'user', $channel); + $ourconfig->store(); } else { return $this->raiseError("Login failed!"); } @@ -166,6 +186,9 @@ password from your user configuration.', $reg = &$this->config->getRegistry(); $channel = $this->config->get('default_channel'); $chan = $reg->getChannel($channel); + if (PEAR::isError($chan)) { + return $this->raiseError($chan); + } $server = $this->config->get('preferred_mirror'); $this->ui->outputData("Logging out from $server.", $command); $this->config->remove('username'); diff --git a/includes/pear/PEAR/Command/Auth.xml b/includes/pear/PEAR/Command/Auth.xml index bfc28da3..17e3b34c 100644 --- a/includes/pear/PEAR/Command/Auth.xml +++ b/includes/pear/PEAR/Command/Auth.xml @@ -4,8 +4,9 @@ li doLogin - -Log in to the remote server. To use remote functions in the installer + <channel name> +Log in to a remote channel server. <channel name> is not supplied, +the default channel is used. To use remote functions in the installer that require any kind of privileges, you need to log in first. The username and password you enter here will be stored in your per-user PEAR configuration (~/.pearrc on Unix-like systems). After logging diff --git a/includes/pear/PEAR/Command/Build.php b/includes/pear/PEAR/Command/Build.php index 8f0f3702..d6773100 100644 --- a/includes/pear/PEAR/Command/Build.php +++ b/includes/pear/PEAR/Command/Build.php @@ -15,9 +15,9 @@ * @author Stig Bakken * @author Tomas V.V.Cox * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Build.php,v 1.12 2005/04/13 04:29:36 cellog Exp $ + * @version CVS: $Id: Build.php,v 1.14 2008/01/03 20:26:36 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ @@ -35,9 +35,9 @@ require_once 'PEAR/Command/Common.php'; * @author Stig Bakken * @author Tomas V.V.Cox * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ diff --git a/includes/pear/PEAR/Command/Channels.php b/includes/pear/PEAR/Command/Channels.php index 3eebcead..5de0d39b 100644 --- a/includes/pear/PEAR/Command/Channels.php +++ b/includes/pear/PEAR/Command/Channels.php @@ -16,9 +16,9 @@ * @package PEAR * @author Stig Bakken * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Channels.php,v 1.42 2005/05/11 19:44:16 cellog Exp $ + * @version CVS: $Id: Channels.php,v 1.57 2008/01/03 20:26:36 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -34,9 +34,9 @@ require_once 'PEAR/Command/Common.php'; * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -132,8 +132,13 @@ alias. 'function' => 'doDiscover', 'shortcut' => 'di', 'options' => array(), - 'doc' => ' -List the files in an installed package. + 'doc' => '[|] +Initialize a channel from its server and create a local channel.xml. +If is in the format ":@" then + and will be set as the login username/password for +. Use caution when passing the username/password in this way, as +it may allow other users on your computer to briefly view your username/ +password via the system\'s process list. ' ), ); @@ -185,133 +190,24 @@ List the files in an installed package. function doUpdateAll($command, $options, $params) { $reg = &$this->config->getRegistry(); - $savechannel = $this->config->get('default_channel'); - if (isset($options['channel'])) { - if (!$reg->channelExists($options['channel'])) { - return $this->raiseError('Unknown channel "' . $options['channel'] . '"'); - } - $this->config->set('default_channel', $options['channel']); - } else { - $this->config->set('default_channel', 'pear.php.net'); - } - $remote = &$this->config->getRemote(); - $channels = $remote->call('channel.listAll'); - if (PEAR::isError($channels)) { - $this->config->set('default_channel', $savechannel); - return $channels; - } - if (!is_array($channels) || isset($channels['faultCode'])) { - $this->config->set('default_channel', $savechannel); - return $this->raiseError("Incorrect channel listing returned from channel '$chan'"); - } - if (!count($channels)) { - $data = 'no updates available'; - } - $dl = &$this->getDownloader(); - if (!class_exists('System')) { - require_once 'System.php'; - } - $tmpdir = System::mktemp(array('-d')); + $channels = $reg->getChannels(); + + $success = true; foreach ($channels as $channel) { - $channel = $channel[0]; - $save = $channel; - if ($reg->channelExists($channel, true)) { - $this->ui->outputData("Updating channel \"$channel\"", $command); - $test = $reg->getChannel($channel, true); - if (!$test) { - $this->ui->outputData("Channel '$channel' is corrupt in registry!", $command); - $lastmodified = false; + if ($channel->getName() != '__uri') { + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $err = $this->doUpdate('channel-update', + $options, + array($channel->getName())); + if (PEAR::isError($err)) { + $this->ui->outputData($err->getMessage(), $command); + $success = false; } else { - $lastmodified = $test->lastModified(); - + $success &= $err; } - PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); - $contents = $dl->downloadHttp('http://' . $test->getName() . '/channel.xml', - $this->ui, $tmpdir, null, $lastmodified); - PEAR::staticPopErrorHandling(); - if (PEAR::isError($contents)) { - $this->ui->outputData('ERROR: Cannot retrieve channel.xml for channel "' . - $test->getName() . '"', $command); - continue; - } - if (!$contents) { - $this->ui->outputData("Channel \"$channel\" is up-to-date", $command); - continue; - } - list($contents, $lastmodified) = $contents; - $info = implode('', file($contents)); - if (!$info) { - $this->ui->outputData("Channel \"$channel\" is up-to-date", $command); - continue; - } - if (!class_exists('PEAR_ChannelFile')) { - require_once 'PEAR/ChannelFile.php'; - } - $channelinfo = new PEAR_ChannelFile; - $channelinfo->fromXmlString($info); - if ($channelinfo->getErrors()) { - $this->ui->outputData("Downloaded channel data from channel \"$channel\" " . - 'is corrupt, skipping', $command); - continue; - } - $channel = $channelinfo; - if ($channel->getName() != $save) { - $this->ui->outputData('ERROR: Security risk - downloaded channel ' . - 'definition file for channel "' - . $channel->getName() . ' from channel "' . $save . - '". To use anyway, use channel-update', $command); - continue; - } - $reg->updateChannel($channel, $lastmodified); - } else { - if ($reg->isAlias($channel)) { - $temp = &$reg->getChannel($channel); - $temp->setAlias($temp->getName(), true); // set the alias to the channel name - if ($reg->channelExists($temp->getName())) { - $this->ui->outputData('ERROR: existing channel "' . $temp->getName() . - '" is aliased to "' . $channel . '" already and cannot be ' . - 're-aliased to "' . $temp->getName() . '" because a channel with ' . - 'that name or alias already exists! Please re-alias and try ' . - 'again.', $command); - continue; - } - } - $this->ui->outputData("Adding new channel \"$channel\"", $command); - PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); - $contents = $dl->downloadHttp('http://' . $channel . '/channel.xml', - $this->ui, $tmpdir, null, false); - PEAR::staticPopErrorHandling(); - if (PEAR::isError($contents)) { - $this->ui->outputData('ERROR: Cannot retrieve channel.xml for channel "' . - $channel . '"', $command); - continue; - } - list($contents, $lastmodified) = $contents; - $info = implode('', file($contents)); - if (!class_exists('PEAR_ChannelFile')) { - require_once 'PEAR/ChannelFile.php'; - } - $channelinfo = new PEAR_Channelfile; - $channelinfo->fromXmlString($info); - if ($channelinfo->getErrors()) { - $this->ui->outputData("Downloaded channel data from channel \"$channel\"" . - ' is corrupt, skipping', $command); - continue; - } - $channel = $channelinfo; - if ($channel->getName() != $save) { - $this->ui->outputData('ERROR: Security risk - downloaded channel ' . - 'definition file for channel "' - . $channel->getName() . '" from channel "' . $save . - '". To use anyway, use channel-update', $command); - continue; - } - $reg->addChannel($channel, $lastmodified); } } - $this->config->set('default_channel', $savechannel); - $this->ui->outputData('update-channels complete', $command); - return true; + return $success; } function doInfo($command, $options, $params) @@ -323,29 +219,30 @@ List the files in an installed package. $channel = strtolower($params[0]); if ($reg->channelExists($channel)) { $chan = $reg->getChannel($channel); + if (PEAR::isError($chan)) { + return $this->raiseError($chan); + } } else { if (strpos($channel, '://')) { $downloader = &$this->getDownloader(); - if (!class_exists('System')) { - require_once 'System.php'; - } - $tmpdir = System::mktemp(array('-d')); + $tmpdir = $this->config->get('temp_dir'); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $loc = $downloader->downloadHttp($channel, $this->ui, $tmpdir); PEAR::staticPopErrorHandling(); if (PEAR::isError($loc)) { - return $this->raiseError('Cannot open "' . $channel . '"'); + return $this->raiseError('Cannot open "' . $channel . + '" (' . $loc->getMessage() . ')'); } else { $contents = implode('', file($loc)); } } else { - $fp = @fopen($params[0], 'r'); - if (!$fp) { - if (@file_exists($params[0])) { + if (file_exists($params[0])) { + $fp = fopen($params[0], 'r'); + if (!$fp) { return $this->raiseError('Cannot open "' . $params[0] . '"'); - } else { - return $this->raiseError('Unknown channel "' . $channel . '"'); } + } else { + return $this->raiseError('Unknown channel "' . $channel . '"'); } $contents = ''; while (!feof($fp)) { @@ -431,7 +328,7 @@ List the files in an installed package. $data['data'][] = array($mirror['attribs']['host']); $d['mirrors'] = $data; } - foreach ($mirrors as $mirror) { + foreach ($mirrors as $i => $mirror) { $data['data'] = array(); $data['caption'] = 'Mirror ' . $mirror['attribs']['host'] . ' Capabilities'; $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base'); @@ -469,7 +366,7 @@ List the files in an installed package. } else { $data['data'][] = array('No supported protocols'); } - $d['mirrorprotocols'] = $data; + $d['mirrorprotocols' . $i] = $data; } } $this->ui->outputData($d, 'channel-info'); @@ -522,22 +419,38 @@ List the files in an installed package. } if (strpos($params[0], '://')) { $downloader = &$this->getDownloader(); - if (!class_exists('System')) { + $tmpdir = $this->config->get('temp_dir'); + if (!file_exists($tmpdir)) { require_once 'System.php'; + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $err = System::mkdir(array('-p', $tmpdir)); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($err)) { + return $this->raiseError('channel-add: temp_dir does not exist: "' . + $tmpdir . + '" - You can change this location with "pear config-set temp_dir"'); + } + } + if (!is_writable($tmpdir)) { + return $this->raiseError('channel-add: temp_dir is not writable: "' . + $tmpdir . + '" - You can change this location with "pear config-set temp_dir"'); } - $tmpdir = System::mktemp(array('-d')); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $loc = $downloader->downloadHttp($params[0], $this->ui, $tmpdir, null, false); PEAR::staticPopErrorHandling(); if (PEAR::isError($loc)) { - return $this->raiseError('channel-add: Cannot open "' . $params[0] . '"'); + return $this->raiseError('channel-add: Cannot open "' . $params[0] . + '" (' . $loc->getMessage() . ')'); } else { list($loc, $lastmodified) = $loc; $contents = implode('', file($loc)); } } else { - $lastmodified = false; - $fp = @fopen($params[0], 'r'); + $lastmodified = $fp = false; + if (file_exists($params[0])) { + $fp = fopen($params[0], 'r'); + } if (!$fp) { return $this->raiseError('channel-add: cannot open "' . $params[0] . '"'); } @@ -588,10 +501,23 @@ List the files in an installed package. function doUpdate($command, $options, $params) { - if (!class_exists('System')) { + $tmpdir = $this->config->get('temp_dir'); + if (!file_exists($tmpdir)) { require_once 'System.php'; + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $err = System::mkdir(array('-p', $tmpdir)); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($err)) { + return $this->raiseError('channel-add: temp_dir does not exist: "' . + $tmpdir . + '" - You can change this location with "pear config-set temp_dir"'); + } + } + if (!is_writable($tmpdir)) { + return $this->raiseError('channel-add: temp_dir is not writable: "' . + $tmpdir . + '" - You can change this location with "pear config-set temp_dir"'); } - $tmpdir = System::mktemp(array('-d')); $reg = &$this->config->getRegistry(); if (sizeof($params) != 1) { return $this->raiseError("No channel file specified"); @@ -600,7 +526,10 @@ List the files in an installed package. if ((!file_exists($params[0]) || is_dir($params[0])) && $reg->channelExists(strtolower($params[0]))) { $c = $reg->getChannel(strtolower($params[0])); - $this->ui->outputData('Retrieving channel.xml from remote server'); + if (PEAR::isError($c)) { + return $this->raiseError($c); + } + $this->ui->outputData("Updating channel \"$params[0]\"", $command); $dl = &$this->getDownloader(array()); // if force is specified, use a timestamp of "1" to force retrieval $lastmodified = isset($options['force']) ? false : $c->lastModified(); @@ -610,11 +539,11 @@ List the files in an installed package. PEAR::staticPopErrorHandling(); if (PEAR::isError($contents)) { return $this->raiseError('Cannot retrieve channel.xml for channel "' . - $c->getName() . '"'); + $c->getName() . '" (' . $contents->getMessage() . ')'); } list($contents, $lastmodified) = $contents; if (!$contents) { - $this->ui->outputData("Channel $params[0] channel.xml is up to date"); + $this->ui->outputData("Channel \"$params[0]\" is up to date"); return; } $contents = implode('', file($contents)); @@ -645,13 +574,17 @@ List the files in an installed package. $this->ui, $tmpdir, null, $lastmodified); PEAR::staticPopErrorHandling(); if (PEAR::isError($loc)) { - return $this->raiseError("Cannot open " . $params[0]); + return $this->raiseError("Cannot open " . $params[0] . + ' (' . $loc->getMessage() . ')'); } else { list($loc, $lastmodified) = $loc; $contents = implode('', file($loc)); } } else { - $fp = @fopen($params[0], 'r'); + $fp = false; + if (file_exists($params[0])) { + $fp = fopen($params[0], 'r'); + } if (!$fp) { return $this->raiseError("Cannot open " . $params[0]); } @@ -729,9 +662,9 @@ List the files in an installed package. 'already aliased to "' . strtolower($params[1]) . '", cannot re-alias'); } $chan = &$reg->getChannel($params[0]); - if (!$chan) { + if (PEAR::isError($chan)) { return $this->raiseError('Corrupt registry? Error retrieving channel "' . $params[0] . - '" information'); + '" information (' . $chan->getMessage() . ')'); } // make it a local alias if (!$chan->setAlias(strtolower($params[1]), true)) { @@ -743,28 +676,62 @@ List the files in an installed package. strtolower($params[1]) . '"'); } + /** + * The channel-discover command + * + * @param string $command command name + * @param array $options option_name => value + * @param array $params list of additional parameters. + * $params[0] should contain a string with either: + * - or + * - :@ + * @return null|PEAR_Error + */ function doDiscover($command, $options, $params) { $reg = &$this->config->getRegistry(); if (sizeof($params) != 1) { return $this->raiseError("No channel server specified"); } - if ($reg->channelExists($params[0])) { - if ($reg->isAlias($params[0])) { - return $this->raiseError("A channel alias named \"$params[0]\" " . - 'already exists, aliasing channel "' . $reg->channelName($params[0]) + + // Look for the possible input format ":@" + if (preg_match('/^(.+):(.+)@(.+)\\z/', $params[0], $matches)) { + $username = $matches[1]; + $password = $matches[2]; + $channel = $matches[3]; + } else { + $channel = $params[0]; + } + + if ($reg->channelExists($channel)) { + if ($reg->isAlias($channel)) { + return $this->raiseError("A channel alias named \"$channel\" " . + 'already exists, aliasing channel "' . $reg->channelName($channel) . '"'); } else { - return $this->raiseError("Channel \"$params[0]\" is already initialized"); + return $this->raiseError("Channel \"$channel\" is already initialized"); } } $this->pushErrorHandling(PEAR_ERROR_RETURN); - $err = $this->doAdd($command, $options, array('http://' . $params[0] . '/channel.xml')); + $err = $this->doAdd($command, $options, array('http://' . $channel . '/channel.xml')); $this->popErrorHandling(); if (PEAR::isError($err)) { - return $this->raiseError("Discovery of channel \"$params[0]\" failed"); + return $this->raiseError("Discovery of channel \"$channel\" failed (" . + $err->getMessage() . ')'); } - $this->ui->outputData("Discovery of channel \"$params[0]\" succeeded", $command); + + // Store username/password if they were given + // Arguably we should do a logintest on the channel here, but since + // that's awkward on a REST-based channel (even "pear login" doesn't + // do it for those), and XML-RPC is deprecated, it's fairly pointless. + if (isset($username)) { + $this->config->set('username', $username, 'user', $channel); + $this->config->set('password', $password, 'user', $channel); + $this->config->store(); + $this->ui->outputData("Stored login for channel \"$channel\" using username \"$username\"", $command); + } + + $this->ui->outputData("Discovery of channel \"$channel\" succeeded", $command); } } ?> diff --git a/includes/pear/PEAR/Command/Channels.xml b/includes/pear/PEAR/Command/Channels.xml index fc3739b3..e7c7b7fe 100644 --- a/includes/pear/PEAR/Command/Channels.xml +++ b/includes/pear/PEAR/Command/Channels.xml @@ -86,8 +86,13 @@ alias. doDiscover di - <package> -List the files in an installed package. + [<channel.xml>|<channel name>] +Initialize a channel from its server and create a local channel.xml. +If <channel name> is in the format "<username>:<password>@<channel>" then +<username> and <password> will be set as the login username/password for +<channel>. Use caution when passing the username/password in this way, as +it may allow other users on your computer to briefly view your username/ +password via the system's process list. - \ No newline at end of file + diff --git a/includes/pear/PEAR/Command/Common.php b/includes/pear/PEAR/Command/Common.php index 91c3b4dc..41595403 100644 --- a/includes/pear/PEAR/Command/Common.php +++ b/includes/pear/PEAR/Command/Common.php @@ -14,9 +14,9 @@ * @package PEAR * @author Stig Bakken * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Common.php,v 1.29 2005/04/13 04:29:58 cellog Exp $ + * @version CVS: $Id: Common.php,v 1.36 2008/01/03 20:26:36 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ @@ -33,9 +33,9 @@ require_once 'PEAR.php'; * @package PEAR * @author Stig Bakken * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ @@ -74,7 +74,7 @@ class PEAR_Command_Common extends PEAR var $_deps_type_trans = array( 'pkg' => 'package', - 'extension' => 'extension', + 'ext' => 'extension', 'php' => 'PHP', 'prog' => 'external program', 'ldlib' => 'external library for linking', @@ -145,7 +145,12 @@ class PEAR_Command_Common extends PEAR if (isset($shortcuts[$command])) { $command = $shortcuts[$command]; } - return @$this->commands[$command]['options']; + if (isset($this->commands[$command]) && + isset($this->commands[$command]['options'])) { + return $this->commands[$command]['options']; + } else { + return null; + } } // }}} @@ -192,12 +197,19 @@ class PEAR_Command_Common extends PEAR function getHelp($command) { $config = &PEAR_Config::singleton(); - $help = @$this->commands[$command]['doc']; + if (!isset($this->commands[$command])) { + return "No such command \"$command\""; + } + $help = null; + if (isset($this->commands[$command]['doc'])) { + $help = $this->commands[$command]['doc']; + } if (empty($help)) { // XXX (cox) Fallback to summary if there is no doc (show both?) - if (!$help = @$this->commands[$command]['summary']) { + if (!isset($this->commands[$command]['summary'])) { return "No help for command \"$command\""; } + $help = $this->commands[$command]['summary']; } if (preg_match_all('/{config\s+([^\}]+)}/e', $help, $matches)) { foreach($matches[0] as $k => $v) { @@ -223,7 +235,7 @@ class PEAR_Command_Common extends PEAR $help = "Options:\n"; foreach ($this->commands[$command]['options'] as $k => $v) { if (isset($v['arg'])) { - if ($v['arg']{0} == '(') { + if ($v['arg'][0] == '(') { $arg = substr($v['arg'], 1, -1); $sapp = " [$arg]"; $lapp = "[=$arg]"; @@ -236,9 +248,9 @@ class PEAR_Command_Common extends PEAR } if (isset($v['shortopt'])) { $s = $v['shortopt']; - @$help .= " -$s$sapp, --$k$lapp\n"; + $help .= " -$s$sapp, --$k$lapp\n"; } else { - @$help .= " --$k$lapp\n"; + $help .= " --$k$lapp\n"; } $p = " "; $doc = rtrim(str_replace("\n", "\n$p", $v['doc'])); @@ -254,19 +266,21 @@ class PEAR_Command_Common extends PEAR function run($command, $options, $params) { - $func = @$this->commands[$command]['function']; - if (empty($func)) { + if (empty($this->commands[$command]['function'])) { // look for shortcuts foreach (array_keys($this->commands) as $cmd) { - if (@$this->commands[$cmd]['shortcut'] == $command) { - $command = $cmd; - $func = @$this->commands[$command]['function']; - if (empty($func)) { + if (isset($this->commands[$cmd]['shortcut']) && $this->commands[$cmd]['shortcut'] == $command) { + if (empty($this->commands[$cmd]['function'])) { return $this->raiseError("unknown command `$command'"); + } else { + $func = $this->commands[$cmd]['function']; } + $command = $cmd; break; } } + } else { + $func = $this->commands[$command]['function']; } return $this->$func($command, $options, $params); } @@ -274,4 +288,4 @@ class PEAR_Command_Common extends PEAR // }}} } -?> \ No newline at end of file +?> diff --git a/includes/pear/PEAR/Command/Config.php b/includes/pear/PEAR/Command/Config.php index 45fa8dc4..d8179d3a 100644 --- a/includes/pear/PEAR/Command/Config.php +++ b/includes/pear/PEAR/Command/Config.php @@ -14,9 +14,9 @@ * @package PEAR * @author Stig Bakken * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Config.php,v 1.48 2005/09/24 04:25:33 cellog Exp $ + * @version CVS: $Id: Config.php,v 1.56 2008/01/03 20:26:36 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ @@ -33,9 +33,9 @@ require_once 'PEAR/Command/Common.php'; * @package PEAR * @author Stig Bakken * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ @@ -155,8 +155,14 @@ and uninstall). function doConfigShow($command, $options, $params) { + if (is_array($params)) { + $layer = isset($params[0]) ? $params[0] : NULL; + } else { + $layer = NULL; + } + // $params[0] -> the layer - if ($error = $this->_checkLayer(@$params[0])) { + if ($error = $this->_checkLayer($layer)) { return $this->raiseError("config-show:$error"); } $keys = $this->config->getKeys(); @@ -170,7 +176,7 @@ and uninstall). $data = array('caption' => 'Configuration (channel ' . $channel . '):'); foreach ($keys as $key) { $type = $this->config->getType($key); - $value = $this->config->get($key, @$params[0], $channel); + $value = $this->config->get($key, $layer, $channel); if ($type == 'password' && $value) { $value = '********'; } @@ -184,7 +190,7 @@ and uninstall). foreach ($this->config->getLayers() as $layer) { $data['data']['Config Files'][] = array(ucfirst($layer) . ' Configuration File', 'Filename' , $this->config->getConfFile($layer)); } - + $this->ui->outputData($data, $command); return true; } @@ -194,27 +200,38 @@ and uninstall). function doConfigGet($command, $options, $params) { - // $params[0] -> the parameter - // $params[1] -> the layer - if ($error = $this->_checkLayer(@$params[1])) { - return $this->raiseError("config-get:$error"); + if (!is_array($params)) { + $args_cnt = 0; + } else { + $args_cnt = count($params); } - $channel = isset($options['channel']) ? $options['channel'] : - $this->config->get('default_channel'); + + switch ($args_cnt) { + case 1: + $config_key = $params[0]; + $layer = NULL; + break; + case 2: + $config_key = $params[0]; + $layer = $params[1]; + if ($error = $this->_checkLayer($layer)) { + return $this->raiseError("config-get:$error"); + } + break; + case 0: + default: + return $this->raiseError("config-get expects 1 or 2 parameters"); + } + + $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel'); $reg = &$this->config->getRegistry(); + if (!$reg->channelExists($channel)) { return $this->raiseError('Channel "' . $channel . '" does not exist'); } - if (sizeof($params) < 1 || sizeof($params) > 2) { - return $this->raiseError("config-get expects 1 or 2 parameters"); - } else { - if (count($params) == 1) { - $layer = null; - } else { - $layer = $params[1]; - } - $this->ui->outputData($this->config->get($params[0], $layer, $channel), $command); - } + + $this->ui->outputData($this->config->get($config_key, $layer, $channel), $command); + return true; } @@ -231,7 +248,7 @@ and uninstall). $failmsg .= "config-set expects 2 or 3 parameters"; return PEAR::raiseError($failmsg); } - if ($error = $this->_checkLayer(@$params[2])) { + if (isset($params[2]) && ($error = $this->_checkLayer($params[2]))) { $failmsg .= $error; return PEAR::raiseError("config-set:$failmsg"); } @@ -333,10 +350,14 @@ and uninstall). $config->noRegistry(); $config->set('php_dir', $windows ? "$root\\pear\\php" : "$root/pear/php", 'user'); $config->set('data_dir', $windows ? "$root\\pear\\data" : "$root/pear/data"); + $config->set('www_dir', $windows ? "$root\\pear\\www" : "$root/pear/www"); + $config->set('cfg_dir', $windows ? "$root\\pear\\cfg" : "$root/pear/cfg"); $config->set('ext_dir', $windows ? "$root\\pear\\ext" : "$root/pear/ext"); $config->set('doc_dir', $windows ? "$root\\pear\\docs" : "$root/pear/docs"); $config->set('test_dir', $windows ? "$root\\pear\\tests" : "$root/pear/tests"); $config->set('cache_dir', $windows ? "$root\\pear\\cache" : "$root/pear/cache"); + $config->set('download_dir', $windows ? "$root\\pear\\download" : "$root/pear/download"); + $config->set('temp_dir', $windows ? "$root\\pear\\temp" : "$root/pear/temp"); $config->set('bin_dir', $windows ? "$root\\pear" : "$root/pear"); $config->writeConfigFile(); $this->_showConfig($config); @@ -372,7 +393,7 @@ and uninstall). array(ucfirst($layer) . ' Configuration File', 'Filename' , $config->getConfFile($layer)); } - + $this->ui->outputData($data, 'config-show'); return true; } diff --git a/includes/pear/PEAR/Command/Install.php b/includes/pear/PEAR/Command/Install.php index dd43ef32..fba43820 100644 --- a/includes/pear/PEAR/Command/Install.php +++ b/includes/pear/PEAR/Command/Install.php @@ -14,9 +14,9 @@ * @package PEAR * @author Stig Bakken * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Install.php,v 1.109 2005/10/26 19:37:14 cellog Exp $ + * @version CVS: $Id: Install.php,v 1.141 2008/05/13 18:32:29 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ @@ -34,9 +34,9 @@ require_once 'PEAR/Command/Common.php'; * @package PEAR * @author Stig Bakken * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ @@ -81,7 +81,12 @@ class PEAR_Command_Install extends PEAR_Command_Common 'installroot' => array( 'shortopt' => 'R', 'arg' => 'DIR', - 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)', + 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM', + ), + 'packagingroot' => array( + 'shortopt' => 'P', + 'arg' => 'DIR', + 'doc' => 'root directory used when packaging files, like RPM packaging', ), 'ignore-errors' => array( 'doc' => 'force install even if there were errors', @@ -196,7 +201,7 @@ More than one package may be specified at once. '), 'upgrade-all' => array( 'summary' => 'Upgrade All Packages', - 'function' => 'doInstall', + 'function' => 'doUpgradeAll', 'shortcut' => 'ua', 'options' => array( 'nodeps' => array( @@ -218,7 +223,7 @@ More than one package may be specified at once. 'installroot' => array( 'shortopt' => 'R', 'arg' => 'DIR', - 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)', + 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM', ), 'ignore-errors' => array( 'doc' => 'force install even if there were errors', @@ -333,77 +338,302 @@ Run post-installation scripts in package , if any exist. return $a; } + function enableExtension($binaries, $type) + { + if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) { + return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location'); + } + $ini = $this->_parseIni($phpini); + if (PEAR::isError($ini)) { + return $ini; + } + $line = 0; + if ($type == 'extsrc' || $type == 'extbin') { + $search = 'extensions'; + $enable = 'extension'; + } else { + $search = 'zend_extensions'; + ob_start(); + phpinfo(INFO_GENERAL); + $info = ob_get_contents(); + ob_end_clean(); + $debug = function_exists('leak') ? '_debug' : ''; + $ts = preg_match('Thread Safety.+enabled', $info) ? '_ts' : ''; + $enable = 'zend_extension' . $debug . $ts; + } + foreach ($ini[$search] as $line => $extension) { + if (in_array($extension, $binaries, true) || in_array( + $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) { + // already enabled - assume if one is, all are + return true; + } + } + if ($line) { + $newini = array_slice($ini['all'], 0, $line); + } else { + $newini = array(); + } + foreach ($binaries as $binary) { + if ($ini['extension_dir']) { + $binary = basename($binary); + } + $newini[] = $enable . '="' . $binary . '"' . (OS_UNIX ? "\n" : "\r\n"); + } + $newini = array_merge($newini, array_slice($ini['all'], $line)); + $fp = @fopen($phpini, 'wb'); + if (!$fp) { + return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing'); + } + foreach ($newini as $line) { + fwrite($fp, $line); + } + fclose($fp); + return true; + } + + function disableExtension($binaries, $type) + { + if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) { + return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location'); + } + $ini = $this->_parseIni($phpini); + if (PEAR::isError($ini)) { + return $ini; + } + $line = 0; + if ($type == 'extsrc' || $type == 'extbin') { + $search = 'extensions'; + $enable = 'extension'; + } else { + $search = 'zend_extensions'; + ob_start(); + phpinfo(INFO_GENERAL); + $info = ob_get_contents(); + ob_end_clean(); + $debug = function_exists('leak') ? '_debug' : ''; + $ts = preg_match('Thread Safety.+enabled', $info) ? '_ts' : ''; + $enable = 'zend_extension' . $debug . $ts; + } + $found = false; + foreach ($ini[$search] as $line => $extension) { + if (in_array($extension, $binaries, true) || in_array( + $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) { + $found = true; + break; + } + } + if (!$found) { + // not enabled + return true; + } + $fp = @fopen($phpini, 'wb'); + if (!$fp) { + return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing'); + } + if ($line) { + $newini = array_slice($ini['all'], 0, $line); + // delete the enable line + $newini = array_merge($newini, array_slice($ini['all'], $line + 1)); + } else { + $newini = array_slice($ini['all'], 1); + } + foreach ($newini as $line) { + fwrite($fp, $line); + } + fclose($fp); + return true; + } + + function _parseIni($filename) + { + if (file_exists($filename)) { + if (filesize($filename) > 300000) { + return PEAR::raiseError('php.ini "' . $filename . '" is too large, aborting'); + } + ob_start(); + phpinfo(INFO_GENERAL); + $info = ob_get_contents(); + ob_end_clean(); + $debug = function_exists('leak') ? '_debug' : ''; + $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : ''; + $zend_extension_line = 'zend_extension' . $debug . $ts; + $all = @file($filename); + if (!$all) { + return PEAR::raiseError('php.ini "' . $filename .'" could not be read'); + } + $zend_extensions = $extensions = array(); + // assume this is right, but pull from the php.ini if it is found + $extension_dir = ini_get('extension_dir'); + foreach ($all as $linenum => $line) { + $line = trim($line); + if (!$line) { + continue; + } + if ($line[0] == ';') { + continue; + } + if (strtolower(substr($line, 0, 13)) == 'extension_dir') { + $line = trim(substr($line, 13)); + if ($line[0] == '=') { + $x = trim(substr($line, 1)); + $x = explode(';', $x); + $extension_dir = str_replace('"', '', array_shift($x)); + continue; + } + } + if (strtolower(substr($line, 0, 9)) == 'extension') { + $line = trim(substr($line, 9)); + if ($line[0] == '=') { + $x = trim(substr($line, 1)); + $x = explode(';', $x); + $extensions[$linenum] = str_replace('"', '', array_shift($x)); + continue; + } + } + if (strtolower(substr($line, 0, strlen($zend_extension_line))) == + $zend_extension_line) { + $line = trim(substr($line, strlen($zend_extension_line))); + if ($line[0] == '=') { + $x = trim(substr($line, 1)); + $x = explode(';', $x); + $zend_extensions[$linenum] = str_replace('"', '', array_shift($x)); + continue; + } + } + } + return array( + 'extensions' => $extensions, + 'zend_extensions' => $zend_extensions, + 'extension_dir' => $extension_dir, + 'all' => $all, + ); + } else { + return PEAR::raiseError('php.ini "' . $filename . '" does not exist'); + } + } + // {{{ doInstall() function doInstall($command, $options, $params) { + if (!class_exists('PEAR_PackageFile')) { + require_once 'PEAR/PackageFile.php'; + } if (empty($this->installer)) { $this->installer = &$this->getInstaller($this->ui); } - if ($command == 'upgrade') { + if ($command == 'upgrade' || $command == 'upgrade-all') { $options['upgrade'] = true; + } else { + $packages = $params; + } + if (isset($options['installroot']) && isset($options['packagingroot'])) { + return $this->raiseError('ERROR: cannot use both --installroot and --packagingroot'); } $reg = &$this->config->getRegistry(); - if ($command == 'upgrade-all') { - $options['upgrade'] = true; - $reg = &$this->config->getRegistry(); - $savechannel = $this->config->get('default_channel'); - $params = array(); - foreach ($reg->listChannels() as $channel) { - if ($channel == '__uri') { + $instreg = &$reg; // instreg used to check if package is installed + if (isset($options['packagingroot']) && !isset($options['upgrade'])) { + $packrootphp_dir = $this->installer->_prependPath( + $this->config->get('php_dir', null, 'pear.php.net'), + $options['packagingroot']); + $instreg = new PEAR_Registry($packrootphp_dir); // other instreg! + + if ($this->config->get('verbose') > 2) { + $this->ui->outputData('using package root: ' . $options['packagingroot']); + } + } + $abstractpackages = array(); + $otherpackages = array(); + // parse params + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + foreach($params as $param) { + if (strpos($param, 'http://') === 0) { + $otherpackages[] = $param; + continue; + } + if (strpos($param, 'channel://') === false && @file_exists($param)) { + if (isset($options['force'])) { + $otherpackages[] = $param; continue; } - $this->config->set('default_channel', $channel); - $chan = &$reg->getChannel($channel); - if ($chan->supportsREST($this->config->get('preferred_mirror')) && - $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { - $dorest = true; - unset($remote); - } else { - $dorest = false; - $remote = &$this->config->getRemote($this->config); - } - $state = $this->config->get('preferred_state'); - $installed = array_flip($reg->listPackages($channel)); - PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); - if ($dorest) { - $rest = &$this->config->getREST('1.0', array()); - $latest = $rest->listLatestUpgrades($base, $state, $installed, $channel, $reg); - } else { - if (empty($state) || $state == 'any') { - $latest = $remote->call("package.listLatestReleases"); - } else { - $latest = $remote->call("package.listLatestReleases", $state); - } - } - PEAR::staticPopErrorHandling(); - if (PEAR::isError($latest) || !is_array($latest)) { + $pkg = new PEAR_PackageFile($this->config); + $pf = $pkg->fromAnyFile($param, PEAR_VALIDATE_DOWNLOADING); + if (PEAR::isError($pf)) { + $otherpackages[] = $param; continue; } - foreach ($latest as $package => $info) { - $package = strtolower($package); - if (!isset($installed[$package])) { - // skip packages we don't have installed + if ($reg->packageExists($pf->getPackage(), $pf->getChannel()) && + version_compare($pf->getVersion(), + $reg->packageInfo($pf->getPackage(), 'version', $pf->getChannel()), + '<=')) { + if ($this->config->get('verbose')) { + $this->ui->outputData('Ignoring installed package ' . + $reg->parsedPackageNameToString( + array('package' => $pf->getPackage(), + 'channel' => $pf->getChannel()), true)); + } + continue; + } + $otherpackages[] = $param; + continue; + } + $e = $reg->parsePackageName($param, $this->config->get('default_channel')); + if (PEAR::isError($e)) { + $otherpackages[] = $param; + } else { + $abstractpackages[] = $e; + } + } + PEAR::staticPopErrorHandling(); + + // if there are any local package .tgz or remote static url, we can't + // filter. The filter only works for abstract packages + if (count($abstractpackages) && !isset($options['force'])) { + // when not being forced, only do necessary upgrades/installs + if (isset($options['upgrade'])) { + $abstractpackages = $this->_filterUptodatePackages($abstractpackages, + $command); + } else { + foreach ($abstractpackages as $i => $package) { + if (isset($package['group'])) { + // do not filter out install groups continue; } - $inst_version = $reg->packageInfo($package, 'version', $channel); - if (version_compare("$info[version]", "$inst_version", "le")) { - // installed version is up-to-date - continue; + if ($instreg->packageExists($package['package'], $package['channel'])) { + if ($this->config->get('verbose')) { + $this->ui->outputData('Ignoring installed package ' . + $reg->parsedPackageNameToString($package, true)); + } + unset($abstractpackages[$i]); } - $params[] = $reg->parsedPackageNameToString(array('package' => $package, - 'channel' => $channel)); - $this->ui->outputData(array('data' => "Will upgrade $package"), $command); } } - $this->config->set('default_channel', $savechannel); + $abstractpackages = + array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages); + } elseif (count($abstractpackages)) { + $abstractpackages = + array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages); } + + + $packages = array_merge($abstractpackages, $otherpackages); + if (!count($packages)) { + $this->ui->outputData('Nothing to ' . $command); + return true; + } + $this->downloader = &$this->getDownloader($this->ui, $options, $this->config); $errors = array(); + $binaries = array(); $downloaded = array(); - $downloaded = &$this->downloader->download($params); + $downloaded = &$this->downloader->download($packages); + if (PEAR::isError($downloaded)) { + return $this->raiseError($downloaded); + } $errors = $this->downloader->getErrorMsgs(); if (count($errors)) { + $err = array(); + $err['data'] = array(); foreach ($errors as $error) { $err['data'][] = array($error); } @@ -430,6 +660,7 @@ Run post-installation scripts in package , if any exist. return true; } $extrainfo = array(); + $binaries = array(); foreach ($downloaded as $param) { PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $info = $this->installer->install($param, $options); @@ -450,13 +681,16 @@ Run post-installation scripts in package , if any exist. } if (is_array($info)) { if ($param->getPackageType() == 'extsrc' || - $param->getPackageType() == 'extbin') { + $param->getPackageType() == 'extbin' || + $param->getPackageType() == 'zendextsrc' || + $param->getPackageType() == 'zendextbin') { $pkg = &$param->getPackageFile(); if ($instbin = $pkg->getInstalledBinary()) { - $instpkg = &$reg->getPackage($instbin, $pkg->getChannel()); + $instpkg = &$instreg->getPackage($instbin, $pkg->getChannel()); } else { - $instpkg = &$reg->getPackage($pkg->getPackage(), $pkg->getChannel()); + $instpkg = &$instreg->getPackage($pkg->getPackage(), $pkg->getChannel()); } + foreach ($instpkg->getFilelist() as $name => $atts) { $pinfo = pathinfo($atts['installed_as']); if (!isset($pinfo['extension']) || @@ -469,11 +703,37 @@ Run post-installation scripts in package , if any exist. $pinfo['extension'] == 'so' || // hp-ux $pinfo['extension'] == 'sl') { - $extrainfo[] = 'You should add "extension=' . $pinfo['basename'] - . '" to php.ini'; + $binaries[] = array($atts['installed_as'], $pinfo); break; } } + if (count($binaries)) { + foreach ($binaries as $pinfo) { + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $ret = $this->enableExtension(array($pinfo[0]), $param->getPackageType()); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($ret)) { + $extrainfo[] = $ret->getMessage(); + if ($param->getPackageType() == 'extsrc' || + $param->getPackageType() == 'extbin') { + $exttype = 'extension'; + } else { + ob_start(); + phpinfo(INFO_GENERAL); + $info = ob_get_contents(); + ob_end_clean(); + $debug = function_exists('leak') ? '_debug' : ''; + $ts = preg_match('Thread Safety.+enabled', $info) ? '_ts' : ''; + $exttype = 'zend_extension' . $debug . $ts; + } + $extrainfo[] = 'You should add "' . $exttype . '=' . + $pinfo[1]['basename'] . '" to php.ini'; + } else { + $extrainfo[] = 'Extension ' . $instpkg->getProvidesExtension() . + ' enabled in php.ini'; + } + } + } } if ($this->config->get('verbose') > 0) { $channel = $param->getChannel(); @@ -515,28 +775,33 @@ Run post-installation scripts in package , if any exist. // explicitly chooses to install another group continue; } - $this->ui->outputData($param->getPackage() . ': Optional feature ' . + $extrainfo[] = $param->getPackage() . ': Optional feature ' . $group['attribs']['name'] . ' available (' . - $group['attribs']['hint'] . ')'); + $group['attribs']['hint'] . ')'; } - $extrainfo[] = 'To install use "pear install ' . - $param->getPackage() . '#featurename"'; + $extrainfo[] = $param->getPackage() . + ': To install optional features use "pear install ' . + $reg->parsedPackageNameToString( + array('package' => $param->getPackage(), + 'channel' => $param->getChannel()), true) . + '#featurename"'; } } - if (isset($options['installroot'])) { - $reg = &$this->config->getRegistry(); - } - $pkg = &$reg->getPackage($param->getPackage(), $param->getChannel()); - $pkg->setConfig($this->config); - if ($list = $pkg->listPostinstallScripts()) { - $pn = $reg->parsedPackageNameToString(array('channel' => - $param->getChannel(), 'package' => $param->getPackage()), true); - $extrainfo[] = $pn . ' has post-install scripts:'; - foreach ($list as $file) { - $extrainfo[] = $file; + $pkg = &$instreg->getPackage($param->getPackage(), $param->getChannel()); + // $pkg may be NULL if install is a 'fake' install via --packagingroot + if (is_object($pkg)) { + $pkg->setConfig($this->config); + if ($list = $pkg->listPostinstallScripts()) { + $pn = $reg->parsedPackageNameToString(array('channel' => + $param->getChannel(), 'package' => $param->getPackage()), true); + $extrainfo[] = $pn . ' has post-install scripts:'; + foreach ($list as $file) { + $extrainfo[] = $file; + } + $extrainfo[] = $param->getPackage() . + ': Use "pear run-scripts ' . $pn . '" to finish setup.'; + $extrainfo[] = 'DO NOT RUN SCRIPTS FROM UNTRUSTED SOURCES'; } - $extrainfo[] = 'Use "pear run-scripts ' . $pn . '" to run'; - $extrainfo[] = 'DO NOT RUN SCRIPTS FROM UNTRUSTED SOURCES'; } } else { return $this->raiseError("$command failed"); @@ -550,6 +815,33 @@ Run post-installation scripts in package , if any exist. return true; } + // }}} + // {{{ doUpgradeAll() + + function doUpgradeAll($command, $options, $params) + { + $reg = &$this->config->getRegistry(); + $toUpgrade = array(); + foreach ($reg->listChannels() as $channel) { + if ($channel == '__uri') { + continue; + } + + // parse name with channel + foreach ($reg->listPackages($channel) as $name) { + $toUpgrade[] = $reg->parsedPackageNameToString(array( + 'channel' => $channel, + 'package' => $name + )); + } + } + + $err = $this->doInstall('upgrade-all', $options, $toUpgrade); + if (PEAR::isError($err)) { + $this->ui->outputData($err->getMessage(), $command); + } + } + // }}} // {{{ doUninstall() @@ -569,6 +861,7 @@ Run post-installation scripts in package , if any exist. } $reg = &$this->config->getRegistry(); $newparams = array(); + $binaries = array(); $badparams = array(); foreach ($params as $pkg) { $channel = $this->config->get('default_channel'); @@ -607,7 +900,7 @@ Run post-installation scripts in package , if any exist. if (isset($parsed['group'])) { $group = $info->getDependencyGroup($parsed['group']); if ($group) { - $installed = &$reg->getInstalledGroup($group); + $installed = $reg->getInstalledGroup($group); if ($installed) { foreach ($installed as $i => $p) { $newparams[] = &$installed[$i]; @@ -627,6 +920,7 @@ Run post-installation scripts in package , if any exist. // for circular dependencies like subpackages $this->installer->setUninstallPackages($newparams); $params = array_merge($params, $badparams); + $binaries = array(); foreach ($params as $pkg) { $this->installer->pushErrorHandling(PEAR_ERROR_RETURN); if ($err = $this->installer->uninstall($pkg, $options)) { @@ -635,6 +929,58 @@ Run post-installation scripts in package , if any exist. $this->ui->outputData($err->getMessage(), $command); continue; } + if ($pkg->getPackageType() == 'extsrc' || + $pkg->getPackageType() == 'extbin' || + $pkg->getPackageType() == 'zendextsrc' || + $pkg->getPackageType() == 'zendextbin') { + if ($instbin = $pkg->getInstalledBinary()) { + continue; // this will be uninstalled later + } + + foreach ($pkg->getFilelist() as $name => $atts) { + $pinfo = pathinfo($atts['installed_as']); + if (!isset($pinfo['extension']) || + in_array($pinfo['extension'], array('c', 'h'))) { + continue; // make sure we don't match php_blah.h + } + if ((strpos($pinfo['basename'], 'php_') === 0 && + $pinfo['extension'] == 'dll') || + // most unices + $pinfo['extension'] == 'so' || + // hp-ux + $pinfo['extension'] == 'sl') { + $binaries[] = array($atts['installed_as'], $pinfo); + break; + } + } + if (count($binaries)) { + foreach ($binaries as $pinfo) { + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $ret = $this->disableExtension(array($pinfo[0]), $pkg->getPackageType()); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($ret)) { + $extrainfo[] = $ret->getMessage(); + if ($pkg->getPackageType() == 'extsrc' || + $pkg->getPackageType() == 'extbin') { + $exttype = 'extension'; + } else { + ob_start(); + phpinfo(INFO_GENERAL); + $info = ob_get_contents(); + ob_end_clean(); + $debug = function_exists('leak') ? '_debug' : ''; + $ts = preg_match('Thread Safety.+enabled', $info) ? '_ts' : ''; + $exttype = 'zend_extension' . $debug . $ts; + } + $this->ui->outputData('Unable to remove "' . $exttype . '=' . + $pinfo[1]['basename'] . '" from php.ini', $command); + } else { + $this->ui->outputData('Extension ' . $pkg->getProvidesExtension() . + ' disabled in php.ini', $command); + } + } + } + } $savepkg = $pkg; if ($this->config->get('verbose') > 0) { if (is_object($pkg)) { @@ -680,7 +1026,7 @@ Run post-installation scripts in package , if any exist. function doBundle($command, $options, $params) { $downloader = &$this->getDownloader($this->ui, array('force' => true, 'nodeps' => true, - 'soft' => true), $this->config); + 'soft' => true, 'downloadonly' => true), $this->config); $reg = &$this->config->getRegistry(); if (sizeof($params) < 1) { return $this->raiseError("Please supply the package you want to bundle"); @@ -699,11 +1045,20 @@ Run post-installation scripts in package , if any exist. $dest = $pwd; } } - $downloader->setDownloadDir($dest); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $err = $downloader->setDownloadDir($dest); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($err)) { + return PEAR::raiseError('download directory "' . $dest . + '" is not writeable.'); + } $result = &$downloader->download(array($params[0])); if (PEAR::isError($result)) { return $result; } + if (!isset($result[0])) { + return $this->raiseError('unable to unpack ' . $params[0]); + } $pkgfile = &$result[0]->getPackageFile(); $pkgname = $pkgfile->getName(); $pkgversion = $pkgfile->getVersion(); @@ -713,7 +1068,7 @@ Run post-installation scripts in package , if any exist. $orig = $pkgname . '-' . $pkgversion; $tar = &new Archive_Tar($pkgfile->getArchiveFile()); - if (!@$tar->extractModify($dest, $orig)) { + if (!$tar->extractModify($dest, $orig)) { return $this->raiseError('unable to unpack ' . $pkgfile->getArchiveFile()); } $this->ui->outputData("Package ready at '$dest'"); @@ -744,5 +1099,90 @@ Run post-installation scripts in package , if any exist. $this->ui->outputData('Install scripts complete', $command); return true; } + + /** + * Given a list of packages, filter out those ones that are already up to date + * + * @param $packages: packages, in parsed array format ! + * @return list of packages that can be upgraded + */ + function _filterUptodatePackages($packages, $command) + { + $reg = &$this->config->getRegistry(); + $latestReleases = array(); + + $ret = array(); + foreach($packages as $package) { + if (isset($package['group'])) { + $ret[] = $package; + continue; + } + $channel = $package['channel']; + $name = $package['package']; + + if (!$reg->packageExists($name, $channel)) { + $ret[] = $package; + continue; + } + if (!isset($latestReleases[$channel])) { + // fill in cache for this channel + $chan = &$reg->getChannel($channel); + if (PEAR::isError($chan)) { + return $this->raiseError($chan); + } + if ($chan->supportsREST($this->config->get('preferred_mirror', + null, $channel)) && + $base = $chan->getBaseURL('REST1.0', + $this->config->get('preferred_mirror', + null, $channel))) + { + $dorest = true; + } else { + $dorest = false; + $remote = &$this->config->getRemote($this->config); + } + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + if ($dorest) { + $rest = &$this->config->getREST('1.0', array()); + $installed = array_flip($reg->listPackages($channel)); + $latest = $rest->listLatestUpgrades($base, + $this->config->get('preferred_state', null, $channel), $installed, + $channel, $reg); + } else { + $latest = $remote->call("package.listLatestReleases", + $this->config->get('preferred_state', null, $channel)); + unset($remote); + } + PEAR::staticPopErrorHandling(); + if (PEAR::isError($latest)) { + $this->ui->outputData('Error getting channel info from ' . $channel . + ': ' . $latest->getMessage()); + continue; + } + + $latestReleases[$channel] = array_change_key_case($latest); + } + + // check package for latest release + if (isset($latestReleases[$channel][strtolower($name)])) { + // if not set, up to date + $inst_version = $reg->packageInfo($name, 'version', $channel); + $channel_version = $latestReleases[$channel][strtolower($name)]['version']; + if (version_compare($channel_version, $inst_version, "le")) { + // installed version is up-to-date + continue; + } + // maintain BC + if ($command == 'upgrade-all') { + $this->ui->outputData(array('data' => 'Will upgrade ' . + $reg->parsedPackageNameToString($package)), $command); + } + $ret[] = $package; + } + } + + return $ret; + } + } ?> diff --git a/includes/pear/PEAR/Command/Install.xml b/includes/pear/PEAR/Command/Install.xml index ccb9ecf6..94044c26 100644 --- a/includes/pear/PEAR/Command/Install.xml +++ b/includes/pear/PEAR/Command/Install.xml @@ -35,8 +35,13 @@ R DIR - root directory used when installing files (ala PHP's INSTALL_ROOT) + root directory used when installing files (ala PHP's INSTALL_ROOT), use packagingroot for RPM + + P + DIR + root directory used when packaging files, like RPM packaging + force install even if there were errors diff --git a/includes/pear/PEAR/Command/Mirror.php b/includes/pear/PEAR/Command/Mirror.php index 2cb35dd7..f1256e0a 100644 --- a/includes/pear/PEAR/Command/Mirror.php +++ b/includes/pear/PEAR/Command/Mirror.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Alexander Merz - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Mirror.php,v 1.15 2005/05/04 04:39:04 cellog Exp $ + * @version CVS: $Id: Mirror.php,v 1.20 2008/04/11 01:16:40 dufuz Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.2.0 */ @@ -31,9 +31,9 @@ require_once 'PEAR/Command/Common.php'; * @category pear * @package PEAR * @author Alexander Merz - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.2.0 */ @@ -98,7 +98,7 @@ packages within preferred_state ({config preferred_state}) will be downloaded' * @param array $options the command options before the command * @param array $params the stuff after the command name * @return bool true if succesful - * @throw PEAR_Error + * @throw PEAR_Error */ function doDownloadAll($command, $options, $params) { @@ -113,10 +113,13 @@ packages within preferred_state ({config preferred_state}) will be downloaded' $this->config->set('default_channel', $channel); $this->ui->outputData('Using Channel ' . $this->config->get('default_channel')); $chan = $reg->getChannel($channel); + if (PEAR::isError($chan)) { + return $this->raiseError($chan); + } if ($chan->supportsREST($this->config->get('preferred_mirror')) && $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { $rest = &$this->config->getREST('1.0', array()); - $remoteInfo = array_flip($rest->listPackages($base)); + $remoteInfo = array_flip($rest->listPackages($base, $channel)); } else { $remote = &$this->config->getRemote(); $stable = ($this->config->get('preferred_state') == 'stable'); @@ -129,8 +132,11 @@ packages within preferred_state ({config preferred_state}) will be downloaded' if (PEAR::isError($cmd)) { return $cmd; } + $this->ui->outputData('Using Preferred State of ' . + $this->config->get('preferred_state')); + $this->ui->outputData('Gathering release information, please wait...'); /** - * Error handling not necessary, because already done by + * Error handling not necessary, because already done by * the download command */ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); diff --git a/includes/pear/PEAR/Command/Package.php b/includes/pear/PEAR/Command/Package.php index 10eeb6a5..8eb16df7 100644 --- a/includes/pear/PEAR/Command/Package.php +++ b/includes/pear/PEAR/Command/Package.php @@ -16,9 +16,9 @@ * @author Stig Bakken * @author Martin Jansen * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Package.php,v 1.114 2005/10/26 19:14:14 cellog Exp $ + * @version CVS: $Id: Package.php,v 1.128 2008/03/29 21:06:58 dufuz Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ @@ -36,7 +36,7 @@ require_once 'PEAR/Command/Common.php'; * @author Stig Bakken * @author Martin Jansen * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 * @version Release: @package_version@ * @link http://pear.php.net/package/PEAR @@ -185,13 +185,18 @@ release), pass them as additional parameters. 'shortcut' => 'pd', 'options' => array(), 'doc' => ' -List all depencies the package has.' +List all dependencies the package has.' ), 'sign' => array( 'summary' => 'Sign a package distribution file', 'function' => 'doSign', 'shortcut' => 'si', - 'options' => array(), + 'options' => array( + 'verbose' => array( + 'shortopt' => 'v', + 'doc' => 'Display GnuPG output', + ), + ), 'doc' => ' Signs a package distribution (.tar or .tgz) file with GnuPG.', ), @@ -296,7 +301,7 @@ used for automated conversion or learning the format. if (!class_exists('PEAR_Common')) { require_once 'PEAR/Common.php'; } - if (!class_exists('PEAR/PackageFile.php')) { + if (!class_exists('PEAR_PackageFile')) { require_once 'PEAR/PackageFile.php'; } $a = &new PEAR_PackageFile($config, $debug, $tmpdir); @@ -369,10 +374,9 @@ used for automated conversion or learning the format. } else { $valid = $info->validate(PEAR_VALIDATE_PACKAGING); } - $err = array(); - $warn = array(); - if (!$valid) { - foreach ($info->getValidationWarnings() as $error) { + $err = $warn = array(); + if ($errors = $info->getValidationWarnings()) { + foreach ($errors as $error) { if ($error['level'] == 'warning') { $warn[] = $error['message']; } else { @@ -511,8 +515,11 @@ used for automated conversion or learning the format. $cmd .= ' diff'; // the rest of the options are passed right on to "cvs diff" foreach ($options as $option => $optarg) { - $arg = @$this->commands[$command]['options'][$option]['arg']; - $short = @$this->commands[$command]['options'][$option]['shortopt']; + $arg = $short = false; + if (isset($this->commands[$command]['options'][$option])) { + $arg = $this->commands[$command]['options'][$option]['arg']; + $short = $this->commands[$command]['options'][$option]['shortopt']; + } $cmd .= $short ? " -$short" : " --$option"; if ($arg && $optarg) { $cmd .= ($short ? '' : '=') . escapeshellarg($optarg); @@ -689,10 +696,8 @@ used for automated conversion or learning the format. } $tar = new Archive_Tar($params[0]); $tmpdir = System::mktemp('-d pearsign'); - if (!$tar->extractList('package2.xml package.sig', $tmpdir)) { - if (!$tar->extractList('package.xml package.sig', $tmpdir)) { - return $this->raiseError("failed to extract tar file"); - } + if (!$tar->extractList('package2.xml package.xml package.sig', $tmpdir)) { + return $this->raiseError("failed to extract tar file"); } if (file_exists("$tmpdir/package.sig")) { return $this->raiseError("package already signed"); @@ -701,11 +706,22 @@ used for automated conversion or learning the format. if (file_exists("$tmpdir/package2.xml")) { $packagexml = 'package2.xml'; } - @unlink("$tmpdir/package.sig"); + if (file_exists("$tmpdir/package.sig")) { + unlink("$tmpdir/package.sig"); + } + if (!file_exists("$tmpdir/$packagexml")) { + return $this->raiseError("Extracted file $tmpdir/$packagexml not found."); + } $input = $this->ui->userDialog($command, array('GnuPG Passphrase'), array('password')); - $gpg = popen("gpg --batch --passphrase-fd 0 --armor --detach-sign --output $tmpdir/package.sig $tmpdir/$packagexml 2>/dev/null", "w"); + if (!isset($input[0])) { + //use empty passphrase + $input[0] = ''; + } + + $devnull = (isset($options['verbose'])) ? '' : ' 2>/dev/null'; + $gpg = popen("gpg --batch --passphrase-fd 0 --armor --detach-sign --output $tmpdir/package.sig $tmpdir/$packagexml" . $devnull, "w"); if (!$gpg) { return $this->raiseError("gpg command failed"); } @@ -713,7 +729,11 @@ used for automated conversion or learning the format. if (pclose($gpg) || !file_exists("$tmpdir/package.sig")) { return $this->raiseError("gpg sign failed"); } - $tar->addModify("$tmpdir/package.sig", '', $tmpdir); + if (!$tar->addModify("$tmpdir/package.sig", '', $tmpdir)) { + return $this->raiseError('failed adding signature to file'); + } + + $this->ui->outputData("Package signed.", $command); return true; } @@ -731,355 +751,45 @@ used for automated conversion or learning the format. return $a; } + /** + * For unit testing purposes + */ + function &getCommandPackaging(&$ui, &$config) + { + if (!class_exists('PEAR_Command_Packaging')) { + if ($fp = @fopen('PEAR/Command/Packaging.php', 'r', true)) { + fclose($fp); + include_once 'PEAR/Command/Packaging.php'; + } + } + + if (class_exists('PEAR_Command_Packaging')) { + $a = &new PEAR_Command_Packaging($ui, $config); + } else { + $a = null; + } + return $a; + } + // {{{ doMakeRPM() - /* - - (cox) - - TODO: - - Fill the rpm dependencies in the template file. - - IDEAS: - - Instead of mapping the role to rpm vars, perhaps it's better - to use directly the pear cmd to install the files by itself - in %postrun so: - pear -d php_dir=%{_libdir}/php/pear -d test_dir=.. - */ - function doMakeRPM($command, $options, $params) { - require_once 'System.php'; - require_once 'Archive/Tar.php'; - if (sizeof($params) != 1) { - return $this->raiseError("bad parameter(s), try \"help $command\""); - } - if (!file_exists($params[0])) { - return $this->raiseError("file does not exist: $params[0]"); - } - $reg = &$this->config->getRegistry(); - $pkg = &$this->getPackageFile($this->config, $this->_debug); - $pf = &$pkg->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL); - if (PEAR::isError($pf)) { - $u = $pf->getUserinfo(); - if (is_array($u)) { - foreach ($u as $err) { - if (is_array($err)) { - $err = $err['message']; - } - $this->ui->outputData($err); - } - } - return $this->raiseError("$params[0] is not a valid package"); - } - $tmpdir = System::mktemp(array('-d', 'pear2rpm')); - $instroot = System::mktemp(array('-d', 'pear2rpm')); - $tmp = $this->config->get('verbose'); - $this->config->set('verbose', 0); - $installer = $this->getInstaller($this->ui); - require_once 'PEAR/Downloader/Package.php'; - $pack = new PEAR_Downloader_Package($installer); - $pack->setPackageFile($pf); - $params[0] = &$pack; - $installer->setOptions(array('installroot' => $instroot, - 'nodeps' => true, 'soft' => true)); - $installer->setDownloadedPackages($params); - $info = $installer->install($params[0], - array('installroot' => $instroot, - 'nodeps' => true, 'soft' => true)); - $pkgdir = $pf->getPackage() . '-' . $pf->getVersion(); - $info['rpm_xml_dir'] = '/var/lib/pear'; - $this->config->set('verbose', $tmp); - if (isset($options['spec-template'])) { - $spec_template = $options['spec-template']; - } else { - $spec_template = '@DATA-DIR@/PEAR/template.spec'; - } - $info['possible_channel'] = ''; - $info['extra_config'] = ''; - if (isset($options['rpm-pkgname'])) { - $rpm_pkgname_format = $options['rpm-pkgname']; - } else { - if ($pf->getChannel() == 'pear.php.net' || $pf->getChannel() == 'pecl.php.net') { - $alias = 'PEAR'; - } else { - $chan = &$reg->getChannel($pf->getChannel()); - $alias = $chan->getAlias(); - $alias = strtoupper($alias); - $info['possible_channel'] = $pf->getChannel() . '/'; - } - $rpm_pkgname_format = $alias . '::%s'; - } - $info['extra_headers'] = ''; - $info['doc_files'] = ''; - $info['files'] = ''; - $info['package2xml'] = ''; - $info['rpm_package'] = sprintf($rpm_pkgname_format, $pf->getPackage()); - $srcfiles = 0; - foreach ($info['filelist'] as $name => $attr) { - if (!isset($attr['role'])) { - continue; - } - $name = preg_replace('![/:\\\\]!', '/', $name); - if ($attr['role'] == 'doc') { - $info['doc_files'] .= " $name"; - // Map role to the rpm vars - } else { - $c_prefix = '%{_libdir}/php/pear'; - switch ($attr['role']) { - case 'php': - $prefix = $c_prefix; - break; - case 'ext': - $prefix = '%{_libdir}/php'; - break; // XXX good place? - case 'src': - $srcfiles++; - $prefix = '%{_includedir}/php'; - break; // XXX good place? - case 'test': - $prefix = "$c_prefix/tests/" . $pf->getPackage(); - break; - case 'data': - $prefix = "$c_prefix/data/" . $pf->getPackage(); - break; - case 'script': - $prefix = '%{_bindir}'; - break; - default: // non-standard roles - $prefix = "$c_prefix/$attr[role]/" . $pf->getPackage(); - $info['extra_config'] .= - "\n -d {$attr[role]}_dir=$c_prefix/{$attr[role]} \\"; - $this->ui->outputData('WARNING: role "' . $attr['role'] . '" used, ' . - 'and will be installed in "' . $c_prefix . '/' . $attr['role'] . - '/' . $pf->getPackage() . - ' - hand-edit the final .spec if this is wrong', $command); - break; - } - $name = str_replace('\\', '/', $name); - $info['files'] .= "$prefix/$name\n"; - } - } - if ($srcfiles > 0) { - require_once 'OS/Guess.php'; - $os = new OS_Guess; - $arch = $os->getCpu(); + // Check to see if PEAR_Command_Packaging is installed, and + // transparently switch to use the "make-rpm-spec" command from it + // instead, if it does. Otherwise, continue to use the old version + // of "makerpm" supplied with this package (PEAR). + $packaging_cmd = $this->getCommandPackaging($this->ui, $this->config); + if ($packaging_cmd !== null) { + $this->ui->outputData('PEAR_Command_Packaging is installed; using '. + 'newer "make-rpm-spec" command instead'); + return $packaging_cmd->run('make-rpm-spec', $options, $params); } else { - $arch = 'noarch'; + $this->ui->outputData('WARNING: "pear makerpm" is no longer available; an '. + 'improved version is available via "pear make-rpm-spec", which '. + 'is available by installing PEAR_Command_Packaging'); } - $cfg = array('master_server', 'php_dir', 'ext_dir', 'doc_dir', - 'bin_dir', 'data_dir', 'test_dir'); - foreach ($cfg as $k) { - if ($k == 'master_server') { - $chan = $reg->getChannel($pf->getChannel()); - $info[$k] = $chan->getServer(); - continue; - } - $info[$k] = $this->config->get($k); - } - $info['arch'] = $arch; - $fp = @fopen($spec_template, "r"); - if (!$fp) { - return $this->raiseError("could not open RPM spec file template $spec_template: $php_errormsg"); - } - $info['package'] = $pf->getPackage(); - $info['version'] = $pf->getVersion(); - $info['release_license'] = $pf->getLicense(); - if ($pf->getDeps()) { - if ($pf->getPackagexmlVersion() == '1.0') { - $requires = $conflicts = array(); - foreach ($pf->getDeps() as $dep) { - if (isset($dep['optional']) && $dep['optional'] == 'yes') { - continue; - } - if ($dep['type'] != 'pkg') { - continue; - } - if (isset($dep['channel']) && $dep['channel'] != 'pear.php.net' && - $dep['channel'] != 'pecl.php.net') { - $chan = &$reg->getChannel($dep['channel']); - $package = strtoupper($chan->getAlias()) . '::' . $dep['name']; - } else { - $package = 'PEAR::' . $dep['name']; - } - $trans = array( - '>' => '>', - '<' => '<', - '>=' => '>=', - '<=' => '<=', - '=' => '=', - 'gt' => '>', - 'lt' => '<', - 'ge' => '>=', - 'le' => '<=', - 'eq' => '=', - ); - if ($dep['rel'] == 'has') { - $requires[] = $package; - } elseif ($dep['rel'] == 'not') { - $conflicts[] = $package; - } elseif ($dep['rel'] == 'ne') { - $conflicts[] = $package . ' = ' . $dep['version']; - } elseif (isset($trans[$dep['rel']])) { - $requires[] = $package . ' ' . $trans[$dep['rel']] . ' ' . $dep['version']; - } - } - if (count($requires)) { - $info['extra_headers'] .= 'Requires: ' . implode(', ', $requires) . "\n"; - } - if (count($conflicts)) { - $info['extra_headers'] .= 'Conflicts: ' . implode(', ', $conflicts) . "\n"; - } - } else { - $info['package2xml'] = '2'; // tell the spec to use package2.xml - $requires = $conflicts = array(); - $deps = $pf->getDeps(true); - if (isset($deps['required']['package'])) { - if (!isset($deps['required']['package'][0])) { - $deps['required']['package'] = array($deps['required']['package']); - } - foreach ($deps['required']['package'] as $dep) { - if ($dep['channel'] != 'pear.php.net' && $dep['channel'] != 'pecl.php.net') { - $chan = &$reg->getChannel($dep['channel']); - $package = strtoupper($chan->getAlias()) . '::' . $dep['name']; - } else { - $package = 'PEAR::' . $dep['name']; - } - if (isset($dep['conflicts']) && (isset($dep['min']) || - isset($dep['max']))) { - $deprange = array(); - if (isset($dep['min'])) { - $deprange[] = array($dep['min'],'>='); - } - if (isset($dep['max'])) { - $deprange[] = array($dep['max'], '<='); - } - if (isset($dep['exclude'])) { - if (!is_array($dep['exclude']) || - !isset($dep['exclude'][0])) { - $dep['exclude'] = array($dep['exclude']); - } - if (count($deprange)) { - $excl = $dep['exclude']; - // change >= to > if excluding the min version - // change <= to < if excluding the max version - for($i = 0; $i < count($excl); $i++) { - if (isset($deprange[0]) && - $excl[$i] == $deprange[0][0]) { - $deprange[0][1] = '<'; - unset($dep['exclude'][$i]); - } - if (isset($deprange[1]) && - $excl[$i] == $deprange[1][0]) { - $deprange[1][1] = '>'; - unset($dep['exclude'][$i]); - } - } - } - if (count($dep['exclude'])) { - $dep['exclude'] = array_values($dep['exclude']); - $newdeprange = array(); - // remove excludes that are outside the existing range - for ($i = 0; $i < count($dep['exclude']); $i++) { - if ($dep['exclude'][$i] < $dep['min'] || - $dep['exclude'][$i] > $dep['max']) { - unset($dep['exclude'][$i]); - } - } - $dep['exclude'] = array_values($dep['exclude']); - usort($dep['exclude'], 'version_compare'); - // take the remaining excludes and - // split the dependency into sub-ranges - $lastmin = $deprange[0]; - for ($i = 0; $i < count($dep['exclude']) - 1; $i++) { - $newdeprange[] = '(' . - $package . " {$lastmin[1]} {$lastmin[0]} and " . - $package . ' < ' . $dep['exclude'][$i] . ')'; - $lastmin = array($dep['exclude'][$i], '>'); - } - if (isset($dep['max'])) { - $newdeprange[] = '(' . $package . - " {$lastmin[1]} {$lastmin[0]} and " . - $package . ' < ' . $dep['max'] . ')'; - } - $conflicts[] = implode(' or ', $deprange); - } else { - $conflicts[] = $package . - " {$deprange[0][1]} {$deprange[0][0]}" . - (isset($deprange[1]) ? - " and $package {$deprange[1][1]} {$deprange[1][0]}" - : ''); - } - } - continue; - } - if (!isset($dep['min']) && !isset($dep['max']) && - !isset($dep['exclude'])) { - if (isset($dep['conflicts'])) { - $conflicts[] = $package; - } else { - $requires[] = $package; - } - } else { - if (isset($dep['min'])) { - $requires[] = $package . ' >= ' . $dep['min']; - } - if (isset($dep['max'])) { - $requires[] = $package . ' <= ' . $dep['max']; - } - if (isset($dep['exclude'])) { - $ex = $dep['exclude']; - if (!is_array($ex)) { - $ex = array($ex); - } - foreach ($ex as $ver) { - $conflicts[] = $package . ' = ' . $ver; - } - } - } - } - require_once 'Archive/Tar.php'; - $tar = new Archive_Tar($pf->getArchiveFile()); - $tar->pushErrorHandling(PEAR_ERROR_RETURN); - $a = $tar->extractInString('package2.xml'); - $tar->popErrorHandling(); - if ($a === null || PEAR::isError($a)) { - $info['package2xml'] = ''; - // this doesn't have a package.xml version 1.0 - $requires[] = 'PEAR::PEAR >= ' . - $deps['required']['pearinstaller']['min']; - } - if (count($requires)) { - $info['extra_headers'] .= 'Requires: ' . implode(', ', $requires) . "\n"; - } - if (count($conflicts)) { - $info['extra_headers'] .= 'Conflicts: ' . implode(', ', $conflicts) . "\n"; - } - } - } - } - - // remove the trailing newline - $info['extra_headers'] = trim($info['extra_headers']); - if (function_exists('file_get_contents')) { - fclose($fp); - $spec_contents = preg_replace('/@([a-z0-9_-]+)@/e', '$info["\1"]', - file_get_contents($spec_template)); - } else { - $spec_contents = preg_replace('/@([a-z0-9_-]+)@/e', '$info["\1"]', - fread($fp, filesize($spec_template))); - fclose($fp); - } - $spec_file = "$info[rpm_package]-$info[version].spec"; - $wp = fopen($spec_file, "wb"); - if (!$wp) { - return $this->raiseError("could not write RPM spec file $spec_file: $php_errormsg"); - } - fwrite($wp, $spec_contents); - fclose($wp); - $this->ui->outputData("Wrote RPM spec file $spec_file", $command); - return true; } diff --git a/includes/pear/PEAR/Command/Package.xml b/includes/pear/PEAR/Command/Package.xml index 69bc6267..e3f6a553 100644 --- a/includes/pear/PEAR/Command/Package.xml +++ b/includes/pear/PEAR/Command/Package.xml @@ -133,7 +133,7 @@ use the "slide" option to move the release tag. pd -List all depencies the package has. +List all dependencies the package has. Sign a package distribution file @@ -191,4 +191,4 @@ This is not the most intelligent conversion, and should only be used for automated conversion or learning the format. - \ No newline at end of file + diff --git a/includes/pear/PEAR/Command/Pickle.php b/includes/pear/PEAR/Command/Pickle.php index d360c091..d59396ac 100644 --- a/includes/pear/PEAR/Command/Pickle.php +++ b/includes/pear/PEAR/Command/Pickle.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 2005 The PHP Group + * @copyright 2005-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Pickle.php,v 1.4 2005/09/27 04:12:52 cellog Exp $ + * @version CVS: $Id: Pickle.php,v 1.8 2008/01/29 03:21:01 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.1 */ @@ -31,9 +31,9 @@ require_once 'PEAR/Command/Common.php'; * @category pear * @package PEAR * @author Greg Beaver - * @copyright 2005 The PHP Group + * @copyright 2005-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.1 */ @@ -63,8 +63,8 @@ disk in the current directory as "package.xml". Note that only simple package.xml 2.0 will be converted. package.xml 2.0 with: - dependency types other than required/optional PECL package/ext/php/pearinstaller - - more than one extsrcrelease - - extbinrelease, phprelease, or bundle release type + - more than one extsrcrelease or zendextsrcrelease + - zendextbinrelease, extbinrelease, phprelease, or bundle release type - dependency groups - ignore tags in release filelist - tasks other than replace @@ -115,7 +115,7 @@ generate both package.xml. if (!class_exists('PEAR_Common')) { require_once 'PEAR/Common.php'; } - if (!class_exists('PEAR/PackageFile.php')) { + if (!class_exists('PEAR_PackageFile')) { require_once 'PEAR/PackageFile.php'; } $a = &new PEAR_PackageFile($config, $debug, $tmpdir); @@ -156,7 +156,7 @@ generate both package.xml. require_once 'PEAR/PackageFile/v1.php'; $pf = new PEAR_PackageFile_v1; $pf->setConfig($this->config); - if (is_array($pf2->getPackageType() != 'extsrc')) { + if ($pf2->getPackageType() != 'extsrc' && $pf2->getPackageType() != 'zendextsrc') { return $this->raiseError('Cannot safely convert "' . $packagexml . '", is not an extension source package. Using a PEAR_PackageFileManager-based ' . 'script is an option'); @@ -307,7 +307,7 @@ generate both package.xml. $release = $pf2->getReleases(); if (isset($releases[0])) { return $this->raiseError('Cannot safely process "' . $packagexml . '" contains ' - . 'multiple extsrcrelease tags. Using a PEAR_PackageFileManager-based script ' . + . 'multiple extsrcrelease/zendextsrcrelease tags. Using a PEAR_PackageFileManager-based script ' . 'or the convert command is an option'); } if ($configoptions = $pf2->getConfigureOptions()) { diff --git a/includes/pear/PEAR/Command/Pickle.xml b/includes/pear/PEAR/Command/Pickle.xml index 550186fd..04c85bc7 100644 --- a/includes/pear/PEAR/Command/Pickle.xml +++ b/includes/pear/PEAR/Command/Pickle.xml @@ -26,8 +26,8 @@ an automatic conversion will be made to a package.xml 1.0. Note that only simple package.xml 2.0 will be converted. package.xml 2.0 with: - dependency types other than required/optional PECL package/ext/php/pearinstaller - - more than one extsrcrelease - - extbinrelease, phprelease, or bundle release type + - more than one extsrcrelease/zendextsrcrelease + - zendextbinrelease, extbinrelease, phprelease, or bundle release type - dependency groups - ignore tags in release filelist - tasks other than replace diff --git a/includes/pear/PEAR/Command/Registry.php b/includes/pear/PEAR/Command/Registry.php index 6e0b26dc..d2f1dd1b 100644 --- a/includes/pear/PEAR/Command/Registry.php +++ b/includes/pear/PEAR/Command/Registry.php @@ -14,9 +14,9 @@ * @package PEAR * @author Stig Bakken * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Registry.php,v 1.68 2005/11/01 22:28:38 cellog Exp $ + * @version CVS: $Id: Registry.php,v 1.81 2008/01/03 20:26:36 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ @@ -33,9 +33,9 @@ require_once 'PEAR/Command/Common.php'; * @package PEAR * @author Stig Bakken * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ @@ -58,6 +58,10 @@ class PEAR_Command_Registry extends PEAR_Command_Common 'shortopt' => 'a', 'doc' => 'list installed packages from all channels', ), + 'channelinfo' => array( + 'shortopt' => 'i', + 'doc' => 'output fully channel-aware data, even on failure', + ), ), 'doc' => ' If invoked without parameters, this command lists the PEAR packages @@ -123,10 +127,33 @@ installed package.' function doList($command, $options, $params) { - if (isset($options['allchannels'])) { + $reg = &$this->config->getRegistry(); + $channelinfo = isset($options['channelinfo']); + if (isset($options['allchannels']) && !$channelinfo) { return $this->doListAll($command, array(), $params); } - $reg = &$this->config->getRegistry(); + if (isset($options['allchannels']) && $channelinfo) { + // allchannels with $channelinfo + unset($options['allchannels']); + $channels = $reg->getChannels(); + $errors = array(); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + foreach ($channels as $channel) { + $options['channel'] = $channel->getName(); + $ret = $this->doList($command, $options, $params); + + if (PEAR::isError($ret)) { + $errors[] = $ret; + } + } + PEAR::staticPopErrorHandling(); + if (count($errors)) { + // for now, only give first error + return PEAR::raiseError($errors[0]); + } + return true; + } + if (count($params) == 1) { return $this->doFileList($command, $options, $params); } @@ -141,21 +168,46 @@ installed package.' } $installed = $reg->packageInfo(null, null, $channel); usort($installed, array(&$this, '_sortinfo')); - $i = $j = 0; + $data = array( 'caption' => 'Installed packages, channel ' . $channel . ':', 'border' => true, - 'headline' => array('Package', 'Version', 'State') + 'headline' => array('Package', 'Version', 'State'), + 'channel' => $channel, ); + if ($channelinfo) { + $data['headline'] = array('Channel', 'Package', 'Version', 'State'); + } + + if (count($installed) && !isset($data['data'])) { + $data['data'] = array(); + } + foreach ($installed as $package) { $pobj = $reg->getPackage(isset($package['package']) ? $package['package'] : $package['name'], $channel); - $data['data'][] = array($pobj->getPackage(), $pobj->getVersion(), + if ($channelinfo) { + $packageinfo = array($pobj->getChannel(), $pobj->getPackage(), $pobj->getVersion(), $pobj->getState() ? $pobj->getState() : null); + } else { + $packageinfo = array($pobj->getPackage(), $pobj->getVersion(), + $pobj->getState() ? $pobj->getState() : null); + } + $data['data'][] = $packageinfo; } - if (count($installed)==0) { - $data = '(no packages installed from channel ' . $channel . ')'; + if (count($installed) == 0) { + if (!$channelinfo) { + $data = '(no packages installed from channel ' . $channel . ')'; + } else { + $data = array( + 'caption' => 'Installed packages, channel ' . + $channel . ':', + 'border' => true, + 'channel' => $channel, + 'data' => '(no packages installed)', + ); + } } $this->ui->outputData($data, $command); return true; @@ -163,15 +215,18 @@ installed package.' function doListAll($command, $options, $params) { + // This duplicate code is deprecated over + // list --channelinfo, which gives identical + // output for list and list --allchannels. $reg = &$this->config->getRegistry(); $installed = $reg->packageInfo(null, null, null); foreach ($installed as $channel => $packages) { usort($packages, array($this, '_sortinfo')); - $i = $j = 0; $data = array( 'caption' => 'Installed packages, channel ' . $channel . ':', 'border' => true, - 'headline' => array('Package', 'Version', 'State') + 'headline' => array('Package', 'Version', 'State'), + 'channel' => $channel ); foreach ($packages as $package) { $pobj = $reg->getPackage(isset($package['package']) ? @@ -184,6 +239,7 @@ installed package.' 'caption' => 'Installed packages, channel ' . $channel . ':', 'border' => true, 'data' => array(array('(no packages installed)')), + 'channel' => $channel ); } $this->ui->outputData($data, $command); @@ -197,9 +253,12 @@ installed package.' return $this->raiseError('list-files expects 1 parameter'); } $reg = &$this->config->getRegistry(); + $fp = false; if (!is_dir($params[0]) && (file_exists($params[0]) || $fp = @fopen($params[0], 'r'))) { - @fclose($fp); + if ($fp) { + fclose($fp); + } if (!class_exists('PEAR_PackageFile')) { require_once 'PEAR/PackageFile.php'; } @@ -309,7 +368,10 @@ installed package.' function doShellTest($command, $options, $params) { - $this->pushErrorHandling(PEAR_ERROR_RETURN); + if (count($params) < 1) { + return PEAR::raiseError('ERROR, usage: pear shell-test packagename [[relation] version]'); + } + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $reg = &$this->config->getRegistry(); $info = $reg->parsePackageName($params[0], $this->config->get('default_channel')); if (PEAR::isError($info)) { @@ -342,7 +404,7 @@ installed package.' exit(1); } } else { - $this->popErrorHandling(); + PEAR::staticPopErrorHandling(); $this->raiseError("$command: expects 1 to 3 parameters"); exit(1); } @@ -356,10 +418,12 @@ installed package.' if (count($params) != 1) { return $this->raiseError('pear info expects 1 parameter'); } - $info = false; + $info = $fp = false; $reg = &$this->config->getRegistry(); - if ((@is_file($params[0]) && !is_dir($params[0])) || $fp = @fopen($params[0], 'r')) { - @fclose($fp); + if ((file_exists($params[0]) && is_file($params[0]) && !is_dir($params[0])) || $fp = @fopen($params[0], 'r')) { + if ($fp) { + fclose($fp); + } if (!class_exists('PEAR_PackageFile')) { require_once 'PEAR/PackageFile.php'; } @@ -524,7 +588,7 @@ installed package.' unset($info[$key]); $info['Last Modified'] = $hdate; } elseif ($key == '_lastversion') { - $info['Last Installed Version'] = $info[$key] ? $info[$key] : '- None -'; + $info['Previous Installed Version'] = $info[$key] ? $info[$key] : '- None -'; unset($info[$key]); } else { $info[$key] = trim($info[$key]); @@ -566,9 +630,15 @@ installed package.' case 'extsrc' : $release = 'PECL-style PHP extension (source code)'; break; + case 'zendextsrc' : + $release = 'PECL-style Zend extension (source code)'; + break; case 'extbin' : $release = 'PECL-style PHP extension (binary)'; break; + case 'zendextbin' : + $release = 'PECL-style Zend extension (binary)'; + break; case 'bundle' : $release = 'Package bundle (collection of packages)'; break; @@ -623,9 +693,12 @@ installed package.' } $info['Release Notes'] = $obj->getNotes(); if ($compat = $obj->getCompatible()) { + if (!isset($compat[0])) { + $compat = array($compat); + } $info['Compatible with'] = ''; foreach ($compat as $package) { - $info['Compatible with'] .= $package['channel'] . '/' . $package['package'] . + $info['Compatible with'] .= $package['channel'] . '/' . $package['name'] . "\nVersions >= " . $package['min'] . ', <= ' . $package['max']; if (isset($package['exclude'])) { if (is_array($package['exclude'])) { @@ -637,7 +710,7 @@ installed package.' $info['Not Compatible with'] .= "\n"; } $info['Not Compatible with'] .= $package['channel'] . '/' . - $package['package'] . "\nVersions " . $package['exclude']; + $package['name'] . "\nVersions " . $package['exclude']; } } } @@ -980,10 +1053,10 @@ installed package.' $info['package.xml version'] = '2.0'; if ($installed) { if ($obj->getLastModified()) { - $info['Last Modified'] = date('Y-m-d H:m', $obj->getLastModified()); + $info['Last Modified'] = date('Y-m-d H:i', $obj->getLastModified()); } $v = $obj->getLastInstalledVersion(); - $info['Last Installed Version'] = $v ? $v : '- None -'; + $info['Previous Installed Version'] = $v ? $v : '- None -'; } foreach ($info as $key => $value) { $data['data'][] = array($key, $value); diff --git a/includes/pear/PEAR/Command/Registry.xml b/includes/pear/PEAR/Command/Registry.xml index 57a55b9a..9f4e2149 100644 --- a/includes/pear/PEAR/Command/Registry.xml +++ b/includes/pear/PEAR/Command/Registry.xml @@ -13,6 +13,10 @@ a list installed packages from all channels + + i + output fully channel-aware data, even on failure + <package> If invoked without parameters, this command lists the PEAR packages diff --git a/includes/pear/PEAR/Command/Remote.php b/includes/pear/PEAR/Command/Remote.php index ee768de1..c4fa9088 100644 --- a/includes/pear/PEAR/Command/Remote.php +++ b/includes/pear/PEAR/Command/Remote.php @@ -15,9 +15,9 @@ * @package PEAR * @author Stig Bakken * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Remote.php,v 1.86 2005/11/14 14:11:05 cellog Exp $ + * @version CVS: $Id: Remote.php,v 1.107 2008/04/11 01:16:40 dufuz Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ @@ -35,9 +35,9 @@ require_once 'PEAR/REST.php'; * @package PEAR * @author Stig Bakken * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ @@ -58,7 +58,12 @@ Get details on a package from the server.', 'summary' => 'List Available Upgrades', 'function' => 'doListUpgrades', 'shortcut' => 'lu', - 'options' => array(), + 'options' => array( + 'channelinfo' => array( + 'shortopt' => 'i', + 'doc' => 'output fully channel-aware data, even on failure', + ), + ), 'doc' => '[preferred_state] List releases on the server of packages you have installed where a newer version is available with the same release state (stable etc.) @@ -90,7 +95,15 @@ latest stable release of each package.', 'shortopt' => 'c', 'doc' => 'specify a channel other than the default channel', 'arg' => 'CHAN', - ) + ), + 'allchannels' => array( + 'shortopt' => 'a', + 'doc' => 'search packages from all known channels', + ), + 'channelinfo' => array( + 'shortopt' => 'i', + 'doc' => 'output fully channel-aware data, even on failure', + ), ), 'doc' => '[packagename] [packageinfo] Lists all packages which match the search parameters. The first @@ -108,7 +121,11 @@ will be used to match any portion of the summary/description', 'shortopt' => 'c', 'doc' => 'specify a channel other than the default channel', 'arg' => 'CHAN', - ) + ), + 'channelinfo' => array( + 'shortopt' => 'i', + 'doc' => 'output fully channel-aware data, even on failure', + ), ), 'doc' => ' Lists the packages available on the configured server along with the @@ -158,8 +175,17 @@ parameter. function _checkChannelForStatus($channel, $chan) { + if (PEAR::isError($chan)) { + $this->raiseError($chan); + } + if (!is_a($chan, 'PEAR_ChannelFile')) { + return $this->raiseError('Internal corruption error: invalid channel "' . + $channel . '"'); + } $rest = new PEAR_REST($this->config); PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $mirror = $this->config->get('preferred_mirror', null, + $channel); $a = $rest->downloadHttp('http://' . $channel . '/channel.xml', $chan->lastModified()); PEAR::staticPopErrorHandling(); @@ -184,15 +210,17 @@ parameter. if (PEAR::isError($parsed)) { return $this->raiseError('Invalid package name "' . $package . '"'); } - + $channel = $parsed['channel']; $this->config->set('default_channel', $channel); $chan = $reg->getChannel($channel); - $this->_checkChannelForStatus($channel, $chan); + if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { + return $e; + } if ($chan->supportsREST($this->config->get('preferred_mirror')) && $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { $rest = &$this->config->getREST('1.0', array()); - $info = $rest->packageInfo($base, $parsed['package']); + $info = $rest->packageInfo($base, $parsed['package'], $channel); } else { $r = &$this->config->getRemote(); $info = $r->call('package.info', $parsed['package']); @@ -233,7 +261,9 @@ parameter. } } $chan = $reg->getChannel($channel); - $this->_checkChannelForStatus($channel, $chan); + if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { + return $e; + } $list_options = false; if ($this->config->get('preferred_state') == 'stable') { $list_options = true; @@ -242,11 +272,11 @@ parameter. $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))) { // use faster list-all if available $rest = &$this->config->getREST('1.1', array()); - $available = $rest->listAll($base, $list_options); + $available = $rest->listAll($base, $list_options, true, false, false, $chan->getName()); } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) && $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { $rest = &$this->config->getREST('1.0', array()); - $available = $rest->listAll($base, $list_options); + $available = $rest->listAll($base, $list_options, true, false, false, $chan->getName()); } else { $r = &$this->config->getRemote(); if ($channel == 'pear.php.net') { @@ -265,6 +295,7 @@ parameter. 'caption' => 'Channel ' . $channel . ' Available packages:', 'border' => true, 'headline' => array('Package', 'Version'), + 'channel' => $channel ); if (count($available)==0) { $data = '(no packages available yet)'; @@ -299,16 +330,18 @@ parameter. $list_options = true; } $chan = $reg->getChannel($channel); - $this->_checkChannelForStatus($channel, $chan); + if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { + return $e; + } if ($chan->supportsREST($this->config->get('preferred_mirror')) && $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))) { // use faster list-all if available $rest = &$this->config->getREST('1.1', array()); - $available = $rest->listAll($base, $list_options, false); + $available = $rest->listAll($base, $list_options, false, false, false, $chan->getName()); } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) && $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { $rest = &$this->config->getREST('1.0', array()); - $available = $rest->listAll($base, $list_options, false); + $available = $rest->listAll($base, $list_options, false, false, false, $chan->getName()); } else { $r = &$this->config->getRemote(); if ($channel == 'pear.php.net') { @@ -323,10 +356,17 @@ parameter. return $this->raiseError('The package list could not be fetched from the remote server. Please try again. (Debug info: "' . $available->getMessage() . '")'); } $data = array( - 'caption' => 'All packages:', + 'caption' => 'All packages [Channel ' . $channel . ']:', 'border' => true, 'headline' => array('Package', 'Latest', 'Local'), + 'channel' => $channel, ); + if (isset($options['channelinfo'])) { + // add full channelinfo + $data['caption'] = 'Channel ' . $channel . ' All packages:'; + $data['headline'] = array('Channel', 'Package', 'Latest', 'Local', + 'Description', 'Dependencies'); + } $local_pkgs = $reg->listPackages($channel); foreach ($available as $name => $info) { @@ -360,13 +400,39 @@ parameter. if (isset($info['stable']) && !$info['stable']) { $info['stable'] = null; } - $data['data'][$info['category']][] = array( - $reg->channelAlias($channel) . '/' . $name, - @$info['stable'], - @$installed['version'], - @$desc, - @$info['deps'], + + if (isset($options['channelinfo'])) { + // add full channelinfo + if ($info['stable'] === $info['unstable']) { + $state = $info['state']; + } else { + $state = 'stable'; + } + $latest = $info['stable'].' ('.$state.')'; + $local = ''; + if (isset($installed['version'])) { + $inst_state = $reg->packageInfo($name, 'release_state', $channel); + $local = $installed['version'].' ('.$inst_state.')'; + } + + $packageinfo = array( + $channel, + $name, + $latest, + $local, + isset($desc) ? $desc : null, + isset($info['deps']) ? $info['deps'] : null, ); + } else { + $packageinfo = array( + $reg->channelAlias($channel) . '/' . $name, + isset($info['stable']) ? $info['stable'] : null, + isset($installed['version']) ? $installed['version'] : null, + isset($desc) ? $desc : null, + isset($info['deps']) ? $info['deps'] : null, + ); + } + $data['data'][$info['category']][] = $packageinfo; } if (isset($options['mode']) && in_array($options['mode'], array('notinstalled', 'upgrades'))) { @@ -401,8 +467,33 @@ parameter. return $this->raiseError('no valid search string supplied'); }; - $savechannel = $channel = $this->config->get('default_channel'); + $channelinfo = isset($options['channelinfo']); $reg = &$this->config->getRegistry(); + if (isset($options['allchannels'])) { + // search all channels + unset($options['allchannels']); + $channels = $reg->getChannels(); + $errors = array(); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + foreach ($channels as $channel) { + if ($channel->getName() != '__uri') { + $options['channel'] = $channel->getName(); + $ret = $this->doSearch($command, $options, $params); + if (PEAR::isError($ret)) { + $errors[] = $ret; + } + } + } + PEAR::staticPopErrorHandling(); + if (count($errors) !== 0) { + // for now, only give first error + return PEAR::raiseError($errors[0]); + } + + return true; + } + + $savechannel = $channel = $this->config->get('default_channel'); $package = $params[0]; $summary = isset($params[1]) ? $params[1] : false; if (isset($options['channel'])) { @@ -415,50 +506,85 @@ parameter. } } $chan = $reg->getChannel($channel); - $this->_checkChannelForStatus($channel, $chan); + if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { + return $e; + } if ($chan->supportsREST($this->config->get('preferred_mirror')) && $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { $rest = &$this->config->getREST('1.0', array()); - $available = $rest->listAll($base, false, false, $package, $summary); + $available = $rest->listAll($base, false, false, $package, $summary, $chan->getName()); } else { $r = &$this->config->getRemote(); - $available = $r->call('package.search', $package, $summary, true, + $available = $r->call('package.search', $package, $summary, true, $this->config->get('preferred_state') == 'stable', true); } if (PEAR::isError($available)) { $this->config->set('default_channel', $savechannel); return $this->raiseError($available); } - if (!$available) { - return $this->raiseError('no packages found that match pattern "' . $package . '"'); + if (!$available && !$channelinfo) { + // clean exit when not found, no error ! + $data = 'no packages found that match pattern "' . $package . '", for channel '.$channel.'.'; + $this->ui->outputData($data); + $this->config->set('default_channel', $channel); + return true; + } + if ($channelinfo) { + $data = array( + 'caption' => 'Matched packages, channel ' . $channel . ':', + 'border' => true, + 'headline' => array('Channel', 'Package', 'Stable/(Latest)', 'Local'), + 'channel' => $channel + ); + } else { + $data = array( + 'caption' => 'Matched packages, channel ' . $channel . ':', + 'border' => true, + 'headline' => array('Package', 'Stable/(Latest)', 'Local'), + 'channel' => $channel + ); } - $data = array( - 'caption' => 'Matched packages, channel ' . $channel . ':', - 'border' => true, - 'headline' => array('Package', 'Stable/(Latest)', 'Local'), - ); + if (!$available && $channelinfo) { + unset($data['headline']); + $data['data'] = 'No packages found that match pattern "' . $package . '".'; + $available = array(); + } foreach ($available as $name => $info) { $installed = $reg->packageInfo($name, null, $channel); $desc = $info['summary']; if (isset($params[$name])) $desc .= "\n\n".$info['description']; - $unstable = ''; - if ($info['unstable']) { - $unstable = '/(' . $info['unstable'] . ' ' . $info['state'] . ')'; - } if (!isset($info['stable']) || !$info['stable']) { - $info['stable'] = 'none'; + $version_remote = 'none'; + } else { + if ($info['unstable']) { + $version_remote = $info['unstable']; + } else { + $version_remote = $info['stable']; + } + $version_remote .= ' ('.$info['state'].')'; } $version = is_array($installed['version']) ? $installed['version']['release'] : $installed['version']; - $data['data'][$info['category']][] = array( - $name, - $info['stable'] . $unstable, - $version, - $desc, + if ($channelinfo) { + $packageinfo = array( + $channel, + $name, + $version_remote, + $version, + $desc, ); + } else { + $packageinfo = array( + $name, + $version_remote, + $version, + $desc, + ); + } + $data['data'][$info['category']][] = $packageinfo; } $this->ui->outputData($data, $command); $this->config->set('default_channel', $channel); @@ -480,8 +606,20 @@ parameter. { // make certain that dependencies are ignored $options['downloadonly'] = 1; + + // eliminate error messages for preferred_state-related errors + /* TODO: Should be an option, but until now download does respect + prefered state */ + /* $options['ignorepreferred_state'] = 1; */ + // eliminate error messages for preferred_state-related errors + $downloader = &$this->getDownloader($options); - $downloader->setDownloadDir(getcwd()); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $e = $downloader->setDownloadDir(getcwd()); + PEAR::staticPopErrorHandling(); + if (PEAR::isError($e)) { + return $this->raiseError('Current directory is not writeable, cannot download'); + } $errors = array(); $downloaded = array(); $err = $downloader->download($params); @@ -490,10 +628,9 @@ parameter. } $errors = $downloader->getErrorMsgs(); if (count($errors)) { - $errinfo = array(); - $errinfo['data'] = array($errors); - $errinfo['headline'] = 'Download Errors'; - $this->ui->outputData($errinfo); + foreach ($errors as $error) { + $this->ui->outputData($error); + } return $this->raiseError("$command failed"); } $downloaded = $downloader->getDownloadedPackages(); @@ -516,6 +653,9 @@ parameter. function doListUpgrades($command, $options, $params) { require_once 'PEAR/Common.php'; + if (isset($params[0]) && !is_array(PEAR_Common::betterStates($params[0]))) { + return $this->raiseError($params[0] . ' is not a valid state (stable/beta/alpha/devel/etc.) try "pear help list-upgrades"'); + } $savechannel = $channel = $this->config->get('default_channel'); $reg = &$this->config->getRegistry(); foreach ($reg->listChannels() as $channel) { @@ -534,7 +674,9 @@ parameter. } $caption = $channel . ' Available Upgrades'; $chan = $reg->getChannel($channel); - $this->_checkChannelForStatus($channel, $chan); + if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { + return $e; + } if ($chan->supportsREST($this->config->get('preferred_mirror')) && $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { $rest = &$this->config->getREST('1.0', array()); @@ -570,6 +712,7 @@ parameter. 'caption' => $caption, 'border' => 1, 'headline' => array('Channel', 'Package', 'Local', 'Remote', 'Size'), + 'channel' => $channel ); foreach ((array)$latest as $pkg => $info) { $package = strtolower($pkg); @@ -595,10 +738,22 @@ parameter. } $data['data'][] = array($channel, $pkg, "$inst_version ($inst_state)", "$version ($state)", $fs); } - if (empty($data['data'])) { - $this->ui->outputData('Channel ' . $channel . ': No upgrades available'); - } else { + if (isset($options['channelinfo'])) { + if (empty($data['data'])) { + unset($data['headline']); + if (count($inst) == 0) { + $data['data'] = '(no packages installed)'; + } else { + $data['data'] = '(no upgrades available)'; + } + } $this->ui->outputData($data, $command); + } else { + if (empty($data['data'])) { + $this->ui->outputData('Channel ' . $channel . ': No upgrades available'); + } else { + $this->ui->outputData($data, $command); + } } } $this->config->set('default_channel', $savechannel); @@ -613,6 +768,9 @@ parameter. $cache_dir = $this->config->get('cache_dir'); $verbose = $this->config->get('verbose'); $output = ''; + if (!file_exists($cache_dir) || !is_dir($cache_dir)) { + return $this->raiseError("$cache_dir does not exist or is not a directory"); + } if (!($dp = @opendir($cache_dir))) { return $this->raiseError("opendir($cache_dir) failed: $php_errormsg"); } @@ -621,17 +779,22 @@ parameter. } $num = 0; while ($ent = readdir($dp)) { - if (preg_match('/^xmlrpc_cache_[a-z0-9]{32}$/', $ent) || - preg_match('/rest.cache(file|id)$/', $ent)) { + if (preg_match('/^xmlrpc_cache_[a-z0-9]{32}\\z/', $ent) || + preg_match('/rest.cache(file|id)\\z/', $ent)) { $path = $cache_dir . DIRECTORY_SEPARATOR . $ent; - $ok = @unlink($path); + if (file_exists($path)) { + $ok = @unlink($path); + } else { + $ok = false; + $php_errormsg = ''; + } if ($ok) { if ($verbose >= 2) { $output .= "deleted $path\n"; } $num++; } elseif ($verbose >= 1) { - $output .= "failed to delete $path\n"; + $output .= "failed to delete $path $php_errormsg\n"; } } } diff --git a/includes/pear/PEAR/Command/Remote.xml b/includes/pear/PEAR/Command/Remote.xml index 7c43a885..d06f2227 100644 --- a/includes/pear/PEAR/Command/Remote.xml +++ b/includes/pear/PEAR/Command/Remote.xml @@ -27,6 +27,10 @@ or the state passed as the second parameter. specify a channel other than the default channel CHAN + + i + output fully channel-aware data, even on failure + Lists the packages available on the configured server along with the @@ -42,6 +46,14 @@ latest stable release of each package. specify a channel other than the default channel CHAN + + a + search packages from all known channels + + + i + output fully channel-aware data, even on failure + [packagename] [packageinfo] Lists all packages which match the search parameters. The first @@ -59,6 +71,10 @@ will be used to match any portion of the summary/description specify a channel other than the default channel CHAN + + i + output fully channel-aware data, even on failure + Lists the packages available on the configured server along with the diff --git a/includes/pear/PEAR/Command/Test.php b/includes/pear/PEAR/Command/Test.php index 8b778613..4cf40f61 100644 --- a/includes/pear/PEAR/Command/Test.php +++ b/includes/pear/PEAR/Command/Test.php @@ -15,9 +15,9 @@ * @author Stig Bakken * @author Martin Jansen * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Test.php,v 1.5 2005/08/31 07:18:46 pajoye Exp $ + * @version CVS: $Id: Test.php,v 1.27 2008/01/03 20:26:36 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ @@ -35,9 +35,9 @@ require_once 'PEAR/Command/Common.php'; * @author Stig Bakken * @author Martin Jansen * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ @@ -77,6 +77,24 @@ class PEAR_Command_Test extends PEAR_Command_Common 'shortopt' => 'p', 'doc' => 'Treat parameters as installed packages from which to run tests', ), + 'phpunit' => array( + 'shortopt' => 'u', + 'doc' => 'Search parameters for AllTests.php, and use that to run phpunit-based tests +If none is found, all .phpt tests will be tried instead.', + ), + 'tapoutput' => array( + 'shortopt' => 't', + 'doc' => 'Output run-tests.log in TAP-compliant format', + ), + 'cgi' => array( + 'shortopt' => 'c', + 'doc' => 'CGI php executable (needed for tests with POST/GET section)', + 'arg' => 'PHPCGI', + ), + 'coverage' => array( + 'shortopt' => 'x', + 'doc' => 'Generate a code coverage report (requires Xdebug 2.0.0+)', + ), ), 'doc' => '[testfile|dir ...] Run regression tests with PHP\'s regression testing script (run-tests.php).', @@ -103,18 +121,16 @@ Run regression tests with PHP\'s regression testing script (run-tests.php).', function doRunTests($command, $options, $params) { + if (isset($options['phpunit']) && isset($options['tapoutput'])) { + return $this->raiseError('ERROR: cannot use both --phpunit and --tapoutput at the same time'); + } require_once 'PEAR/Common.php'; - require_once 'PEAR/RunTest.php'; require_once 'System.php'; $log = new PEAR_Common; $log->ui = &$this->ui; // slightly hacky, but it will work - $run = new PEAR_RunTest($log, $options); $tests = array(); - if (isset($options['recur'])) { - $depth = 4; - } else { - $depth = 1; - } + $depth = isset($options['recur']) ? 4 : 1; + if (!count($params)) { $params[] = '.'; } @@ -127,79 +143,140 @@ Run regression tests with PHP\'s regression testing script (run-tests.php).', if (PEAR::isError($pname)) { return $this->raiseError($pname); } + $package = &$reg->getPackage($pname['package'], $pname['channel']); if (!$package) { return PEAR::raiseError('Unknown package "' . $reg->parsedPackageNameToString($pname) . '"'); } + $filelist = $package->getFilelist(); foreach ($filelist as $name => $atts) { if (isset($atts['role']) && $atts['role'] != 'test') { continue; } - if (!preg_match('/\.phpt$/', $name)) { + + if (isset($options['phpunit']) && preg_match('/AllTests\.php\\z/i', $name)) { + $params[] = $atts['installed_as']; + continue; + } elseif (!preg_match('/\.phpt\\z/', $name)) { continue; } $params[] = $atts['installed_as']; } } } + foreach ($params as $p) { if (is_dir($p)) { + if (isset($options['phpunit'])) { + $dir = System::find(array($p, '-type', 'f', + '-maxdepth', $depth, + '-name', 'AllTests.php')); + if (count($dir)) { + foreach ($dir as $p) { + $p = realpath($p); + if (!count($tests) || + (count($tests) && strlen($p) < strlen($tests[0]))) { + // this is in a higher-level directory, use this one instead. + $tests = array($p); + } + } + } + continue; + } $dir = System::find(array($p, '-type', 'f', '-maxdepth', $depth, '-name', '*.phpt')); $tests = array_merge($tests, $dir); } else { - if (!@file_exists($p)) { - if (!preg_match('/\.phpt$/', $p)) { - $p .= '.phpt'; + if (isset($options['phpunit'])) { + if (preg_match('/AllTests\.php\\z/i', $p)) { + $p = realpath($p); + if (!count($tests) || + (count($tests) && strlen($p) < strlen($tests[0]))) { + // this is in a higher-level directory, use this one instead. + $tests = array($p); + } } - $dir = System::find(array(dirname($p), '-type', 'f', - '-maxdepth', $depth, - '-name', $p)); - $tests = array_merge($tests, $dir); - } else { - $tests[] = $p; + continue; } + + if (file_exists($p) && preg_match('/\.phpt$/', $p)) { + $tests[] = $p; + continue; + } + + if (!preg_match('/\.phpt\\z/', $p)) { + $p .= '.phpt'; + } + $dir = System::find(array(dirname($p), '-type', 'f', + '-maxdepth', $depth, + '-name', $p)); + $tests = array_merge($tests, $dir); } } + $ini_settings = ''; if (isset($options['ini'])) { $ini_settings .= $options['ini']; } + if (isset($_ENV['TEST_PHP_INCLUDE_PATH'])) { $ini_settings .= " -d include_path={$_ENV['TEST_PHP_INCLUDE_PATH']}"; } + if ($ini_settings) { $this->ui->outputData('Using INI settings: "' . $ini_settings . '"'); } $skipped = $passed = $failed = array(); - $this->ui->outputData('Running ' . count($tests) . ' tests', $command); + $tests_count = count($tests); + $this->ui->outputData('Running ' . $tests_count . ' tests', $command); $start = time(); - if (isset($options['realtimelog'])) { - @unlink('run-tests.log'); + if (isset($options['realtimelog']) && file_exists('run-tests.log')) { + unlink('run-tests.log'); } + + if (isset($options['tapoutput'])) { + $tap = '1..' . $tests_count . "\n"; + } + + require_once 'PEAR/RunTest.php'; + $run = new PEAR_RunTest($log, $options); + $run->tests_count = $tests_count; + + if (isset($options['coverage']) && extension_loaded('xdebug')){ + $run->xdebug_loaded = true; + } else { + $run->xdebug_loaded = false; + } + + $j = $i = 1; foreach ($tests as $t) { if (isset($options['realtimelog'])) { $fp = @fopen('run-tests.log', 'a'); if ($fp) { - fwrite($fp, "Running test $t..."); + fwrite($fp, "Running test [$i / $tests_count] $t..."); fclose($fp); } } PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); - $result = $run->run($t, $ini_settings); + if (isset($options['phpunit'])) { + $result = $run->runPHPUnit($t, $ini_settings); + } else { + $result = $run->run($t, $ini_settings, $j); + } PEAR::staticPopErrorHandling(); if (PEAR::isError($result)) { - $this->ui->log(0, $result->getMessage()); + $this->ui->log($result->getMessage()); continue; } - if (OS_WINDOWS) { - for($i=0;$i<2000;$i++) { - $i = $i; // delay - race conditions on windows - } + + if (isset($options['tapoutput'])) { + $tap .= $result[0] . ' ' . $i . $result[1] . "\n"; + continue; } + if (isset($options['realtimelog'])) { $fp = @fopen('run-tests.log', 'a'); if ($fp) { @@ -207,6 +284,7 @@ Run regression tests with PHP\'s regression testing script (run-tests.php).', fclose($fp); } } + if ($result == 'FAILED') { $failed[] = $t; } @@ -216,28 +294,40 @@ Run regression tests with PHP\'s regression testing script (run-tests.php).', if ($result == 'SKIPPED') { $skipped[] = $t; } + + $j++; } + $total = date('i:s', time() - $start); - if (count($failed)) { - $output = "TOTAL TIME: $total\n"; - $output .= count($passed) . " PASSED TESTS\n"; - $output .= count($skipped) . " SKIPPED TESTS\n"; - $output .= count($failed) . " FAILED TESTS:\n"; - foreach ($failed as $failure) { - $output .= $failure . "\n"; - } - if (isset($options['realtimelog'])) { - $fp = @fopen('run-tests.log', 'a'); - } else { - $fp = @fopen('run-tests.log', 'w'); - } + if (isset($options['tapoutput'])) { + $fp = @fopen('run-tests.log', 'w'); if ($fp) { - fwrite($fp, $output, strlen($output)); + fwrite($fp, $tap, strlen($tap)); fclose($fp); - $this->ui->outputData('wrote log to "' . realpath('run-tests.log') . '"', $command); + $this->ui->outputData('wrote TAP-format log to "' .realpath('run-tests.log') . + '"', $command); + } + } else { + if (count($failed)) { + $output = "TOTAL TIME: $total\n"; + $output .= count($passed) . " PASSED TESTS\n"; + $output .= count($skipped) . " SKIPPED TESTS\n"; + $output .= count($failed) . " FAILED TESTS:\n"; + foreach ($failed as $failure) { + $output .= $failure . "\n"; + } + + $mode = isset($options['realtimelog']) ? 'a' : 'w'; + $fp = @fopen('run-tests.log', $mode); + + if ($fp) { + fwrite($fp, $output, strlen($output)); + fclose($fp); + $this->ui->outputData('wrote log to "' . realpath('run-tests.log') . '"', $command); + } + } elseif (file_exists('run-tests.log') && !is_dir('run-tests.log')) { + @unlink('run-tests.log'); } - } elseif (@file_exists('run-tests.log') && !@is_dir('run-tests.log')) { - @unlink('run-tests.log'); } $this->ui->outputData('TOTAL TIME: ' . $total); $this->ui->outputData(count($passed) . ' PASSED TESTS', $command); @@ -252,6 +342,4 @@ Run regression tests with PHP\'s regression testing script (run-tests.php).', return true; } // }}} -} - -?> +} \ No newline at end of file diff --git a/includes/pear/PEAR/Command/Test.xml b/includes/pear/PEAR/Command/Test.xml index 30659bcd..68e8f538 100644 --- a/includes/pear/PEAR/Command/Test.xml +++ b/includes/pear/PEAR/Command/Test.xml @@ -29,6 +29,24 @@ p Treat parameters as installed packages from which to run tests + + u + Search parameters for AllTests.php, and use that to run phpunit-based tests. +If none is found, all .phpt tests will be tried instead. + + + t + Output run-tests.log in TAP-compliant format + + + c + CGI php executable (needed for tests with POST/GET section) + PHPCGI + + + x + Generate a code coverage report (requires Xdebug 2.0.0+) + [testfile|dir ...] Run regression tests with PHP's regression testing script (run-tests.php). diff --git a/includes/pear/PEAR/Common.php b/includes/pear/PEAR/Common.php index d7b1361f..73ec384f 100644 --- a/includes/pear/PEAR/Common.php +++ b/includes/pear/PEAR/Common.php @@ -15,9 +15,9 @@ * @author Stig Bakken * @author Tomas V. V. Cox * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Common.php,v 1.152 2005/11/12 02:26:59 cellog Exp $ + * @version CVS: $Id: Common.php,v 1.160 2008/01/03 20:26:34 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1.0 * @deprecated File deprecated since Release 1.4.0a1 @@ -35,32 +35,32 @@ require_once 'PEAR.php'; */ define('PEAR_COMMON_ERROR_INVALIDPHP', 1); define('_PEAR_COMMON_PACKAGE_NAME_PREG', '[A-Za-z][a-zA-Z0-9_]+'); -define('PEAR_COMMON_PACKAGE_NAME_PREG', '/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '$/'); +define('PEAR_COMMON_PACKAGE_NAME_PREG', '/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/'); // this should allow: 1, 1.0, 1.0RC1, 1.0dev, 1.0dev123234234234, 1.0a1, 1.0b1, 1.0pl1 define('_PEAR_COMMON_PACKAGE_VERSION_PREG', '\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?'); -define('PEAR_COMMON_PACKAGE_VERSION_PREG', '/^' . _PEAR_COMMON_PACKAGE_VERSION_PREG . '$/i'); +define('PEAR_COMMON_PACKAGE_VERSION_PREG', '/^' . _PEAR_COMMON_PACKAGE_VERSION_PREG . '\\z/i'); // XXX far from perfect :-) define('_PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '(' . _PEAR_COMMON_PACKAGE_NAME_PREG . ')(-([.0-9a-zA-Z]+))?'); define('PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_PACKAGE_DOWNLOAD_PREG . - '$/'); + '\\z/'); -define('_PEAR_CHANNELS_NAME_PREG', '[A-Za-z][a-zA-Z0-9_\.]+'); -define('PEAR_CHANNELS_NAME_PREG', '/^' . _PEAR_CHANNELS_NAME_PREG . '$/'); +define('_PEAR_CHANNELS_NAME_PREG', '[A-Za-z][a-zA-Z0-9\.]+'); +define('PEAR_CHANNELS_NAME_PREG', '/^' . _PEAR_CHANNELS_NAME_PREG . '\\z/'); // this should allow any dns or IP address, plus a path - NO UNDERSCORES ALLOWED -define('_PEAR_CHANNELS_SERVER_PREG', '[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*(\/[a-zA-Z0-9-]+)*'); -define('PEAR_CHANNELS_SERVER_PREG', '/^' . _PEAR_CHANNELS_SERVER_PREG . '$/i'); +define('_PEAR_CHANNELS_SERVER_PREG', '[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*(\/[a-zA-Z0-9\-]+)*'); +define('PEAR_CHANNELS_SERVER_PREG', '/^' . _PEAR_CHANNELS_SERVER_PREG . '\\z/i'); define('_PEAR_CHANNELS_PACKAGE_PREG', '(' ._PEAR_CHANNELS_SERVER_PREG . ')\/(' . _PEAR_COMMON_PACKAGE_NAME_PREG . ')'); -define('PEAR_CHANNELS_PACKAGE_PREG', '/^' . _PEAR_CHANNELS_PACKAGE_PREG . '$/i'); +define('PEAR_CHANNELS_PACKAGE_PREG', '/^' . _PEAR_CHANNELS_PACKAGE_PREG . '\\z/i'); define('_PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '(' . _PEAR_CHANNELS_NAME_PREG . ')::(' . _PEAR_COMMON_PACKAGE_NAME_PREG . ')(-([.0-9a-zA-Z]+))?'); -define('PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_CHANNEL_DOWNLOAD_PREG . '$/'); +define('PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_CHANNEL_DOWNLOAD_PREG . '\\z/'); /** * List of temporary files and directories registered by @@ -126,9 +126,9 @@ $GLOBALS['_PEAR_Common_script_phases'] = array('pre-install', 'post-install', 'p * @author Stig Bakken * @author Tomas V. V. Cox * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 * @deprecated This class will disappear, and its components will be spread @@ -159,7 +159,7 @@ class PEAR_Common extends PEAR /** * Configuration object (PEAR_Config). - * @var object + * @var PEAR_Config */ var $config = null; @@ -453,7 +453,9 @@ class PEAR_Common extends PEAR unset($arr['dependencies']); unset($arr['phprelease']); unset($arr['extsrcrelease']); + unset($arr['zendextsrcrelease']); unset($arr['extbinrelease']); + unset($arr['zendextbinrelease']); unset($arr['bundle']); unset($arr['lead']); unset($arr['developer']); @@ -660,13 +662,8 @@ class PEAR_Common extends PEAR if (!$fp = @fopen($file, "r")) { return false; } - if (function_exists('file_get_contents')) { - fclose($fp); - $contents = file_get_contents($file); - } else { - $contents = fread($fp, filesize($file)); - fclose($fp); - } + fclose($fp); + $contents = file_get_contents($file); $tokens = token_get_all($contents); /* for ($i = 0; $i < sizeof($tokens); $i++) { diff --git a/includes/pear/PEAR/Config.php b/includes/pear/PEAR/Config.php index 3989bf61..fe37037e 100644 --- a/includes/pear/PEAR/Config.php +++ b/includes/pear/PEAR/Config.php @@ -14,9 +14,9 @@ * @package PEAR * @author Stig Bakken * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Config.php,v 1.122 2005/11/03 04:52:26 cellog Exp $ + * @version CVS: $Id: Config.php,v 1.146 2008/05/14 04:16:08 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ @@ -84,7 +84,7 @@ if (getenv('PHP_PEAR_HTTP_PROXY')) { if (getenv('PHP_PEAR_INSTALL_DIR')) { define('PEAR_CONFIG_DEFAULT_PHP_DIR', getenv('PHP_PEAR_INSTALL_DIR')); } else { - if (@is_dir($PEAR_INSTALL_DIR)) { + if (file_exists($PEAR_INSTALL_DIR) && is_dir($PEAR_INSTALL_DIR)) { define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR); } else { @@ -98,7 +98,8 @@ if (getenv('PHP_PEAR_EXTENSION_DIR')) { } else { if (ini_get('extension_dir')) { define('PEAR_CONFIG_DEFAULT_EXT_DIR', ini_get('extension_dir')); - } elseif (defined('PEAR_EXTENSION_DIR') && @is_dir(PEAR_EXTENSION_DIR)) { + } elseif (defined('PEAR_EXTENSION_DIR') && + file_exists(PEAR_EXTENSION_DIR) && is_dir(PEAR_EXTENSION_DIR)) { define('PEAR_CONFIG_DEFAULT_EXT_DIR', PEAR_EXTENSION_DIR); } elseif (defined('PHP_EXTENSION_DIR')) { define('PEAR_CONFIG_DEFAULT_EXT_DIR', PHP_EXTENSION_DIR); @@ -130,6 +131,22 @@ if (getenv('PHP_PEAR_DATA_DIR')) { $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'data'); } +// Default for cfg_dir +if (getenv('PHP_PEAR_CFG_DIR')) { + define('PEAR_CONFIG_DEFAULT_CFG_DIR', getenv('PHP_PEAR_CFG_DIR')); +} else { + define('PEAR_CONFIG_DEFAULT_CFG_DIR', + $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'cfg'); +} + +// Default for www_dir +if (getenv('PHP_PEAR_WWW_DIR')) { + define('PEAR_CONFIG_DEFAULT_WWW_DIR', getenv('PHP_PEAR_WWW_DIR')); +} else { + define('PEAR_CONFIG_DEFAULT_WWW_DIR', + $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'www'); +} + // Default for test_dir if (getenv('PHP_PEAR_TEST_DIR')) { define('PEAR_CONFIG_DEFAULT_TEST_DIR', getenv('PHP_PEAR_TEST_DIR')); @@ -138,6 +155,15 @@ if (getenv('PHP_PEAR_TEST_DIR')) { $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'tests'); } +// Default for temp_dir +if (getenv('PHP_PEAR_TEMP_DIR')) { + define('PEAR_CONFIG_DEFAULT_TEMP_DIR', getenv('PHP_PEAR_TEMP_DIR')); +} else { + define('PEAR_CONFIG_DEFAULT_TEMP_DIR', + System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' . + DIRECTORY_SEPARATOR . 'temp'); +} + // Default for cache_dir if (getenv('PHP_PEAR_CACHE_DIR')) { define('PEAR_CONFIG_DEFAULT_CACHE_DIR', getenv('PHP_PEAR_CACHE_DIR')); @@ -147,6 +173,15 @@ if (getenv('PHP_PEAR_CACHE_DIR')) { DIRECTORY_SEPARATOR . 'cache'); } +// Default for download_dir +if (getenv('PHP_PEAR_DOWNLOAD_DIR')) { + define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR', getenv('PHP_PEAR_DOWNLOAD_DIR')); +} else { + define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR', + System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' . + DIRECTORY_SEPARATOR . 'download'); +} + // Default for php_bin if (getenv('PHP_PEAR_PHP_BIN')) { define('PEAR_CONFIG_DEFAULT_PHP_BIN', getenv('PHP_PEAR_PHP_BIN')); @@ -214,9 +249,9 @@ if (getenv('PHP_PEAR_SIG_KEYDIR')) { * @package PEAR * @author Stig Bakken * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ @@ -262,9 +297,9 @@ class PEAR_Config extends PEAR * @access private */ var $_channelConfigInfo = array( - 'php_dir', 'ext_dir', 'doc_dir', 'bin_dir', 'data_dir', - 'test_dir', 'php_bin', 'username', 'password', 'verbose', - 'preferred_state', 'umask', 'preferred_mirror', + 'php_dir', 'ext_dir', 'doc_dir', 'bin_dir', 'data_dir', 'cfg_dir', + 'test_dir', 'www_dir', 'php_bin', 'username', 'password', 'verbose', + 'preferred_state', 'umask', 'preferred_mirror', 'php_ini' ); /** @@ -398,6 +433,20 @@ class PEAR_Config extends PEAR 'prompt' => 'PEAR data directory', 'group' => 'File Locations (Advanced)', ), + 'cfg_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_CFG_DIR, + 'doc' => 'directory where modifiable configuration files are installed', + 'prompt' => 'PEAR configuration file directory', + 'group' => 'File Locations (Advanced)', + ), + 'www_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_WWW_DIR, + 'doc' => 'directory where www frontend files (html/js) are installed', + 'prompt' => 'PEAR www files directory', + 'group' => 'File Locations (Advanced)', + ), 'test_dir' => array( 'type' => 'directory', 'default' => PEAR_CONFIG_DEFAULT_TEST_DIR, @@ -412,6 +461,20 @@ class PEAR_Config extends PEAR 'prompt' => 'PEAR Installer cache directory', 'group' => 'File Locations (Advanced)', ), + 'temp_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_TEMP_DIR, + 'doc' => 'directory which is used for all temp files', + 'prompt' => 'PEAR Installer temp directory', + 'group' => 'File Locations (Advanced)', + ), + 'download_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR, + 'doc' => 'directory which is used for all downloaded files', + 'prompt' => 'PEAR Installer download directory', + 'group' => 'File Locations (Advanced)', + ), 'php_bin' => array( 'type' => 'file', 'default' => PEAR_CONFIG_DEFAULT_PHP_BIN, @@ -419,6 +482,13 @@ class PEAR_Config extends PEAR 'prompt' => 'PHP CLI/CGI binary', 'group' => 'File Locations (Advanced)', ), + 'php_ini' => array( + 'type' => 'file', + 'default' => '', + 'doc' => 'location of php.ini in which to enable PECL extensions on install', + 'prompt' => 'php.ini location', + 'group' => 'File Locations (Advanced)', + ), // Maintainers 'username' => array( 'type' => 'string', @@ -543,7 +613,7 @@ class PEAR_Config extends PEAR $this->layers = array_keys($this->configuration); $this->files['user'] = $user_file; $this->files['system'] = $system_file; - if ($user_file && @file_exists($user_file)) { + if ($user_file && file_exists($user_file)) { $this->pushErrorHandling(PEAR_ERROR_RETURN); $this->readConfigFile($user_file, 'user', $strict); $this->popErrorHandling(); @@ -552,7 +622,7 @@ class PEAR_Config extends PEAR } } - if ($system_file && @file_exists($system_file)) { + if ($system_file && file_exists($system_file)) { $this->mergeConfigFile($system_file, false, 'system', $strict); if ($this->_errorsFound > 0) { return; @@ -573,12 +643,31 @@ class PEAR_Config extends PEAR } $this->_registry['default'] = &new PEAR_Registry($this->configuration['default']['php_dir']); - $this->_registry['default']->setConfig($this); + $this->_registry['default']->setConfig($this, false); $this->_regInitialized['default'] = false; //$GLOBALS['_PEAR_Config_instance'] = &$this; } // }}} + /** + * Return the default locations of user and system configuration files + * @static + */ + function getDefaultConfigFiles() + { + $sl = DIRECTORY_SEPARATOR; + if (OS_WINDOWS) { + return array( + 'user' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini', + 'system' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pearsys.ini' + ); + } else { + return array( + 'user' => getenv('HOME') . $sl . '.pearrc', + 'system' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.conf' + ); + } + } // {{{ singleton([file], [defaults_file]) /** @@ -670,7 +759,7 @@ class PEAR_Config extends PEAR $this->_setupChannels(); if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) { $this->_registry[$layer] = &new PEAR_Registry($phpdir); - $this->_registry[$layer]->setConfig($this); + $this->_registry[$layer]->setConfig($this, false); $this->_regInitialized[$layer] = false; } else { unset($this->_registry[$layer]); @@ -687,17 +776,15 @@ class PEAR_Config extends PEAR function readFTPConfigFile($path) { do { // poor man's try - if (!class_exists('Net_FTP')) { + if (!class_exists('PEAR_FTP')) { if (!class_exists('PEAR_Common')) { require_once 'PEAR/Common.php'; } - if (PEAR_Common::isIncludeable('Net/FTP.php')) { - include_once 'Net/FTP.php'; + if (PEAR_Common::isIncludeable('PEAR/FTP.php')) { + require_once 'PEAR/FTP.php'; } } - if (class_exists('Net_FTP') && - (class_exists('PEAR_FTP') || PEAR_Common::isIncludeable('PEAR/FTP.php'))) { - require_once 'PEAR/FTP.php'; + if (class_exists('PEAR_FTP')) { $this->_ftp = &new PEAR_FTP; $this->_ftp->pushErrorHandling(PEAR_ERROR_RETURN); $e = $this->_ftp->init($path); @@ -743,7 +830,7 @@ class PEAR_Config extends PEAR return true; } } else { - return PEAR::raiseError('Net_FTP must be installed to use remote config'); + return PEAR::raiseError('PEAR_RemoteInstaller must be installed to use remote config'); } } while (false); // poor man's catch unset($this->files['ftp']); @@ -760,7 +847,7 @@ class PEAR_Config extends PEAR $set = array_flip(array_values($this->_channels)); foreach ($this->configuration as $layer => $data) { $i = 1000; - if (isset($data['__channels'])) { + if (isset($data['__channels']) && is_array($data['__channels'])) { foreach ($data['__channels'] as $channel => $info) { $set[$channel] = $i++; } @@ -830,7 +917,7 @@ class PEAR_Config extends PEAR $this->_setupChannels(); if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) { $this->_registry[$layer] = &new PEAR_Registry($phpdir); - $this->_registry[$layer]->setConfig($this); + $this->_registry[$layer]->setConfig($this, false); $this->_regInitialized[$layer] = false; } else { unset($this->_registry[$layer]); @@ -904,16 +991,16 @@ class PEAR_Config extends PEAR if (!@System::mkDir($opt)) { return $this->raiseError("could not create directory: " . dirname($file)); } - if (@is_file($file) && !@is_writeable($file)) { + if (file_exists($file) && is_file($file) && !is_writeable($file)) { return $this->raiseError("no write access to $file!"); } $fp = @fopen($file, "w"); if (!$fp) { - return $this->raiseError("PEAR_Config::writeConfigFile fopen('$file','w') failed"); + return $this->raiseError("PEAR_Config::writeConfigFile fopen('$file','w') failed ($php_errormsg)"); } $contents = "#PEAR_Config 0.9\n" . serialize($data); if (!@fwrite($fp, $contents)) { - return $this->raiseError("PEAR_Config::writeConfigFile: fwrite failed"); + return $this->raiseError("PEAR_Config::writeConfigFile: fwrite failed ($php_errormsg)"); } return true; } @@ -933,20 +1020,18 @@ class PEAR_Config extends PEAR */ function _readConfigDataFrom($file) { - $fp = @fopen($file, "r"); + $fp = false; + if (file_exists($file)) { + $fp = @fopen($file, "r"); + } if (!$fp) { return $this->raiseError("PEAR_Config::readConfigFile fopen('$file','r') failed"); } $size = filesize($file); $rt = get_magic_quotes_runtime(); set_magic_quotes_runtime(0); - if (function_exists('file_get_contents')) { - fclose($fp); - $contents = file_get_contents($file); - } else { - $contents = @fread($fp, $size); - fclose($fp); - } + fclose($fp); + $contents = file_get_contents($file); if (empty($contents)) { return $this->raiseError('Configuration file "' . $file . '" is empty'); } @@ -1011,12 +1096,18 @@ class PEAR_Config extends PEAR // }}} /** + * @param string Configuration class name, used for detecting duplicate calls * @param array information on a role as parsed from its xml file * @return true|PEAR_Error * @access private */ - function _addConfigVars($vars) + function _addConfigVars($class, $vars) { + static $called = array(); + if (isset($called[$class])) { + return; + } + $called[$class] = 1; if (count($vars) > 3) { return $this->raiseError('Roles can only define 3 new config variables or less'); } @@ -1085,6 +1176,8 @@ class PEAR_Config extends PEAR '" already exists'); } $this->configuration_info[$name] = $var; + // fix bug #7351: setting custom config variable in a channel fails + $this->_channelConfigInfo[] = $name; } return true; } @@ -1265,6 +1358,9 @@ class PEAR_Config extends PEAR $reg = &$this->getRegistry(); if (is_object($reg)) { $chan = &$reg->getChannel($channel); + if (PEAR::isError($chan)) { + return $channel; + } if (!$chan->getMirror($test) && $chan->getName() != $test) { return $channel; // mirror does not exist } @@ -1286,6 +1382,9 @@ class PEAR_Config extends PEAR $reg = &$this->getRegistry(); if (is_object($reg)) { $chan = &$reg->getChannel($channel); + if (PEAR::isError($chan)) { + return $channel; + } if (!$chan->getMirror($test) && $chan->getName() != $test) { return $channel; // mirror does not exist } @@ -1329,13 +1428,16 @@ class PEAR_Config extends PEAR $reg = &$this->getRegistry($layer); if (is_object($reg)) { $chan = &$reg->getChannel($channel); + if (PEAR::isError($chan)) { + return $channel; + } if (!$chan->getMirror($ret) && $chan->getName() != $ret) { return $channel; // mirror does not exist } } return $ret; } - if ($channel == $this->getDefaultChannel($layer)) { + if ($channel != $this->getDefaultChannel($layer)) { return $channel; // we must use the channel name as the preferred mirror // if the user has not chosen an alternate } else { @@ -1383,12 +1485,15 @@ class PEAR_Config extends PEAR $reg = &$this->getRegistry($layer); if (is_object($reg)) { $chan = &$reg->getChannel($channel ? $channel : 'pear.php.net'); + if (PEAR::isError($chan)) { + return false; + } if (!$chan->getMirror($value) && $chan->getName() != $value) { return false; // mirror does not exist } } } - if (empty($this->configuration_info[$key])) { + if (!isset($this->configuration_info[$key])) { return false; } extract($this->configuration_info[$key]); @@ -1453,7 +1558,7 @@ class PEAR_Config extends PEAR $value != $this->_registry[$layer]->install_dir) { $this->_registry[$layer] = &new PEAR_Registry($value); $this->_regInitialized[$layer] = false; - $this->_registry[$layer]->setConfig($this); + $this->_registry[$layer]->setConfig($this, false); } } return true; @@ -1479,7 +1584,7 @@ class PEAR_Config extends PEAR if (!is_object($this->_registry[$layer])) { if ($phpdir = $this->get('php_dir', $layer, 'pear.php.net')) { $this->_registry[$layer] = &new PEAR_Registry($phpdir); - $this->_registry[$layer]->setConfig($this); + $this->_registry[$layer]->setConfig($this, false); $this->_regInitialized[$layer] = false; } else { unset($this->_registry[$layer]); @@ -1518,6 +1623,9 @@ class PEAR_Config extends PEAR continue; } foreach ($this->layers as $layer) { + if (!isset($this->configuration[$layer]['__channels'])) { + $this->configuration[$layer]['__channels'] = array(); + } if (!isset($this->configuration[$layer]['__channels'][$channel]) || !is_array($this->configuration[$layer]['__channels'][$channel])) { $this->configuration[$layer]['__channels'][$channel] = array(); @@ -1941,7 +2049,8 @@ class PEAR_Config extends PEAR return $a; } else { // only go here if null was passed in - die("CRITICAL ERROR: Registry could not be initialized from any value"); + echo "CRITICAL ERROR: Registry could not be initialized from any value"; + exit(1); } } /** @@ -1959,7 +2068,7 @@ class PEAR_Config extends PEAR } $this->_registry[$layer] = &$reg; if (is_object($reg)) { - $this->_registry[$layer]->setConfig($this); + $this->_registry[$layer]->setConfig($this, false); } return true; } @@ -2044,7 +2153,7 @@ class PEAR_Config extends PEAR } $this->_registry[$layer] = &new PEAR_Registry($this->get('php_dir', $layer, 'pear.php.net')); - $this->_registry[$layer]->setConfig($this); + $this->_registry[$layer]->setConfig($this, false); $this->_regInitialized[$layer] = false; } } diff --git a/includes/pear/PEAR/Dependency.php b/includes/pear/PEAR/Dependency.php index b5f54d02..0265f6f7 100644 --- a/includes/pear/PEAR/Dependency.php +++ b/includes/pear/PEAR/Dependency.php @@ -1,24 +1,27 @@ | -// | Stig Bakken | -// +----------------------------------------------------------------------+ -// -// THIS FILE IS DEPRECATED IN FAVOR OF DEPENDENCY2.PHP, AND IS NOT USED IN THE INSTALLER -// $Id: Dependency.php,v 1.40 2005/02/02 04:57:23 cellog Exp $ +/** + * PEAR_Dependency + * + * PHP versions 4 and 5 + * + * LICENSE: This source file is subject to version 3.0 of the PHP license + * that is available through the world-wide-web at the following URI: + * 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 web, please + * send a note to license@php.net so we can mail you a copy immediately. + * + * THIS FILE IS DEPRECATED IN FAVOR OF DEPENDENCY2.PHP, AND IS NOT USED IN THE INSTALLER + * + * @category pear + * @package PEAR + * @author Tomas V.V.Cox + * @author Stig Bakken + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Dependency.php,v 1.43 2008/01/03 20:26:34 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a1 + */ require_once "PEAR.php"; require_once "OS/Guess.php"; @@ -365,7 +368,7 @@ class PEAR_Dependency $path_elements = explode(PATH_SEPARATOR, getenv('PATH')); foreach ($path_elements as $dir) { $file = $dir . DIRECTORY_SEPARATOR . $program . $exe_suffix; - if (@file_exists($file) && @is_executable($file)) { + if (file_exists($file) && is_executable($file)) { return false; } } diff --git a/includes/pear/PEAR/Dependency2.php b/includes/pear/PEAR/Dependency2.php index 13d2fbb8..802e9bfa 100644 --- a/includes/pear/PEAR/Dependency2.php +++ b/includes/pear/PEAR/Dependency2.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Dependency2.php,v 1.48 2005/10/29 21:23:19 cellog Exp $ + * @version CVS: $Id: Dependency2.php,v 1.56 2008/01/03 20:26:35 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -35,9 +35,9 @@ require_once 'PEAR/Validate.php'; * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -85,11 +85,18 @@ class PEAR_Dependency2 $state = PEAR_VALIDATE_INSTALLING) { $this->_config = &$config; - $this->_registry = &$config->getRegistry(); if (!class_exists('PEAR_DependencyDB')) { require_once 'PEAR/DependencyDB.php'; } + if (isset($installoptions['packagingroot'])) { + // make sure depdb is in the right location + $config->setInstallRoot($installoptions['packagingroot']); + } + $this->_registry = &$config->getRegistry(); $this->_dependencydb = &PEAR_DependencyDB::singleton($config); + if (isset($installoptions['packagingroot'])) { + $config->setInstallRoot(false); + } $this->_options = $installoptions; $this->_state = $state; if (!class_exists('OS_Guess')) { @@ -518,7 +525,7 @@ class PEAR_Dependency2 */ function getPEARVersion() { - return '1.4.5'; + return '1.7.2'; } function validatePearinstallerDependency($dep) @@ -860,53 +867,185 @@ class PEAR_Dependency2 $dp->setPackageFile($downloaded[$i]); $params[$i] = &$dp; } - $deps = $this->_dependencydb->getDependentPackageDependencies($this->_currentPackage); - $fail = false; - if ($deps) { - foreach ($deps as $channel => $info) { - foreach ($info as $package => $ds) { - foreach ($ds as $d) { - $d['dep']['package'] = $d['dep']['name']; - $checker = &new PEAR_Dependency2($this->_config, $this->_options, - array('channel' => $channel, 'package' => $package), $this->_state); - $dep = $d['dep']; - $required = $d['type'] == 'required'; - $ret = $checker->_validatePackageUninstall($dep, $required, $params, $dl); - if (is_array($ret)) { - $dl->log(0, $ret[0]); - } elseif (PEAR::isError($ret)) { - $dl->log(0, $ret->getMessage()); - $fail = true; + // check cache + $memyselfandI = strtolower($this->_currentPackage['channel']) . '/' . + strtolower($this->_currentPackage['package']); + if (isset($dl->___uninstall_package_cache)) { + $badpackages = $dl->___uninstall_package_cache; + if (isset($badpackages[$memyselfandI]['warnings'])) { + foreach ($badpackages[$memyselfandI]['warnings'] as $warning) { + $dl->log(0, $warning[0]); + } + } + if (isset($badpackages[$memyselfandI]['errors'])) { + foreach ($badpackages[$memyselfandI]['errors'] as $error) { + if (is_array($error)) { + $dl->log(0, $error[0]); + } else { + $dl->log(0, $error->getMessage()); + } + } + if (isset($this->_options['nodeps']) || isset($this->_options['force'])) { + return $this->warning( + 'warning: %s should not be uninstalled, other installed packages depend ' . + 'on this package'); + } else { + return $this->raiseError( + '%s cannot be uninstalled, other installed packages depend on this package'); + } + } + return true; + } + // first, list the immediate parents of each package to be uninstalled + $perpackagelist = array(); + $allparents = array(); + foreach ($params as $i => $param) { + $a = array('channel' => strtolower($param->getChannel()), + 'package' => strtolower($param->getPackage())); + $deps = $this->_dependencydb->getDependentPackages($a); + if ($deps) { + foreach ($deps as $d) { + $pardeps = $this->_dependencydb->getDependencies($d); + foreach ($pardeps as $dep) { + if (strtolower($dep['dep']['channel']) == $a['channel'] && + strtolower($dep['dep']['name']) == $a['package']) { + if (!isset($perpackagelist[$a['channel'] . '/' . $a['package']])) { + $perpackagelist[$a['channel'] . '/' . $a['package']] = array(); + } + $perpackagelist[$a['channel'] . '/' . $a['package']][] + = array($d['channel'] . '/' . $d['package'], $dep); + if (!isset($allparents[$d['channel'] . '/' . $d['package']])) { + $allparents[$d['channel'] . '/' . $d['package']] = array(); + } + if (!isset($allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']])) { + $allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']] = array(); + } + $allparents[$d['channel'] . '/' . $d['package']] + [$a['channel'] . '/' . $a['package']][] + = array($d, $dep); } } } } } - if ($fail) { - if (isset($this->_options['nodeps']) || isset($this->_options['force'])) { - return $this->warning( - 'warning: %s should not be uninstalled, other installed packages depend ' . - 'on this package'); - } else { - return $this->raiseError( - '%s cannot be uninstalled, other installed packages depend on this package'); + // next, remove any packages from the parents list that are not installed + $remove = array(); + foreach ($allparents as $parent => $d1) { + foreach ($d1 as $d) { + if ($this->_registry->packageExists($d[0][0]['package'], $d[0][0]['channel'])) { + continue; + } + $remove[$parent] = true; + } + } + // next remove any packages from the parents list that are not passed in for + // uninstallation + foreach ($allparents as $parent => $d1) { + foreach ($d1 as $d) { + foreach ($params as $param) { + if (strtolower($param->getChannel()) == $d[0][0]['channel'] && + strtolower($param->getPackage()) == $d[0][0]['package']) { + // found it + continue 3; + } + } + $remove[$parent] = true; + } + } + // remove all packages whose dependencies fail + // save which ones failed for error reporting + $badchildren = array(); + do { + $fail = false; + foreach ($remove as $package => $unused) { + if (!isset($allparents[$package])) { + continue; + } + foreach ($allparents[$package] as $kid => $d1) { + foreach ($d1 as $depinfo) { + if ($depinfo[1]['type'] != 'optional') { + if (isset($badchildren[$kid])) { + continue; + } + $badchildren[$kid] = true; + $remove[$kid] = true; + $fail = true; + continue 2; + } + } + } + if ($fail) { + // start over, we removed some children + continue 2; + } + } + } while ($fail); + // next, construct the list of packages that can't be uninstalled + $badpackages = array(); + $save = $this->_currentPackage; + foreach ($perpackagelist as $package => $packagedeps) { + foreach ($packagedeps as $parent) { + if (!isset($remove[$parent[0]])) { + continue; + } + $packagename = $this->_registry->parsePackageName($parent[0]); + $packagename['channel'] = $this->_registry->channelAlias($packagename['channel']); + $pa = $this->_registry->getPackage($packagename['package'], $packagename['channel']); + $packagename['package'] = $pa->getPackage(); + $this->_currentPackage = $packagename; + // parent is not present in uninstall list, make sure we can actually + // uninstall it (parent dep is optional) + $parentname['channel'] = $this->_registry->channelAlias($parent[1]['dep']['channel']); + $pa = $this->_registry->getPackage($parent[1]['dep']['name'], $parent[1]['dep']['channel']); + $parentname['package'] = $pa->getPackage(); + $parent[1]['dep']['package'] = $parentname['package']; + $parent[1]['dep']['channel'] = $parentname['channel']; + if ($parent[1]['type'] == 'optional') { + $test = $this->_validatePackageUninstall($parent[1]['dep'], false, $dl); + if ($test !== true) { + $badpackages[$package]['warnings'][] = $test; + } + } else { + $test = $this->_validatePackageUninstall($parent[1]['dep'], true, $dl); + if ($test !== true) { + $badpackages[$package]['errors'][] = $test; + } + } + } + } + $this->_currentPackage = $save; + $dl->___uninstall_package_cache = $badpackages; + if (isset($badpackages[$memyselfandI])) { + if (isset($badpackages[$memyselfandI]['warnings'])) { + foreach ($badpackages[$memyselfandI]['warnings'] as $warning) { + $dl->log(0, $warning[0]); + } + } + if (isset($badpackages[$memyselfandI]['errors'])) { + foreach ($badpackages[$memyselfandI]['errors'] as $error) { + if (is_array($error)) { + $dl->log(0, $error[0]); + } else { + $dl->log(0, $error->getMessage()); + } + } + if (isset($this->_options['nodeps']) || isset($this->_options['force'])) { + return $this->warning( + 'warning: %s should not be uninstalled, other installed packages depend ' . + 'on this package'); + } else { + return $this->raiseError( + '%s cannot be uninstalled, other installed packages depend on this package'); + } } } return true; } - function _validatePackageUninstall($dep, $required, $params, &$dl) + function _validatePackageUninstall($dep, $required, $dl) { - $dep['package'] = $dep['name']; $depname = $this->_registry->parsedPackageNameToString($dep, true); - $found = false; - foreach ($params as $param) { - if ($param->isEqual($this->_currentPackage)) { - $found = true; - break; - } - } - $version = $this->_registry->packageinfo($dep['name'], 'version', + $version = $this->_registry->packageinfo($dep['package'], 'version', $dep['channel']); if (!$version) { return true; @@ -923,15 +1062,15 @@ class PEAR_Dependency2 if (!isset($dep['min']) && !isset($dep['max'])) { if ($required) { if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { - return $this->raiseError('%s' . $extra . ' is required by installed package "' . - $depname . '"'); + return $this->raiseError('"' . $depname . '" is required by ' . + 'installed package %s' . $extra); } else { - return $this->warning('warning: %s' . $extra . - ' is required by installed package "' . $depname . '"'); + return $this->warning('warning: "' . $depname . '" is required by ' . + 'installed package %s' . $extra); } } else { - return $this->warning('%s' . $extra . - ' can be optionally used by installed package "' . $depname . '"'); + return $this->warning('"' . $depname . '" can be optionally used by ' . + 'installed package %s' . $extra); } } $fail = false; @@ -945,54 +1084,19 @@ class PEAR_Dependency2 $fail = true; } } - if ($fail) { - if ($found) { - if (!isset($dl->___checked[$this->_currentPackage['channel']] - [$this->_currentPackage['package']])) { - $dl->___checked[$this->_currentPackage['channel']] - [$this->_currentPackage['package']] = true; - $deps = $this->_dependencydb->getDependentPackageDependencies( - $this->_currentPackage); - if ($deps) { - foreach ($deps as $channel => $info) { - foreach ($info as $package => $ds) { - foreach ($ds as $d) { - $d['dep']['package'] = $d['dep']['name']; - $checker = &new PEAR_Dependency2($this->_config, $this->_options, - array('channel' => $channel, 'package' => $package), - $this->_state); - $dep = $d['dep']; - $required = $d['type'] == 'required'; - $ret = $checker->_validatePackageUninstall($dep, $required, $params, - $dl); - if (PEAR::isError($ret)) { - $fail = true; - break 3; - } - } - } - $fail = false; - } - } - } else { - return true; - } - } - if (!$fail) { - return true; - } - if ($required) { - if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { - return $this->raiseError($depname . $extra . ' is required by installed package' . - ' "%s"'); - } else { - return $this->warning('warning: ' . $depname . $extra . - ' is required by installed package "%s"'); - } + // we re-use this variable, preserve the original value + $saverequired = $required; + if ($required) { + if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) { + return $this->raiseError($depname . $extra . ' is required by installed package' . + ' "%s"'); } else { - return $this->warning($depname . $extra . ' can be optionally used by installed package' . - ' "%s"'); + return $this->raiseError('warning: ' . $depname . $extra . + ' is required by installed package "%s"'); } + } else { + return $this->warning($depname . $extra . ' can be optionally used by installed package' . + ' "%s"'); } return true; } diff --git a/includes/pear/PEAR/DependencyDB.php b/includes/pear/PEAR/DependencyDB.php index 6e9c4273..f79ae81e 100644 --- a/includes/pear/PEAR/DependencyDB.php +++ b/includes/pear/PEAR/DependencyDB.php @@ -14,9 +14,9 @@ * @package PEAR * @author Tomas V. V. Cox * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: DependencyDB.php,v 1.29 2005/09/15 20:10:11 cellog Exp $ + * @version CVS: $Id: DependencyDB.php,v 1.37 2008/01/03 20:26:35 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -27,15 +27,16 @@ require_once 'PEAR.php'; require_once 'PEAR/Config.php'; +$GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'] = array(); /** * Track dependency relationships between installed packages * @category pear * @package PEAR * @author Greg Beaver * @author Tomas V.V.Cox - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -137,12 +138,12 @@ class PEAR_DependencyDB function hasWriteAccess() { - if (!@file_exists($this->_depdb)) { + if (!file_exists($this->_depdb)) { $dir = $this->_depdb; while ($dir && $dir != '.') { $dir = dirname($dir); // cd .. - if ($dir != '.' && @file_exists($dir)) { - if (@is_writeable($dir)) { + if ($dir != '.' && file_exists($dir)) { + if (is_writeable($dir)) { return true; } else { return false; @@ -151,7 +152,7 @@ class PEAR_DependencyDB } return false; } - return @is_writeable($this->_depdb); + return is_writeable($this->_depdb); } // {{{ assertDepsDB() @@ -226,6 +227,12 @@ class PEAR_DependencyDB foreach ($temp as $dep) { if (strtolower($dep['dep']['channel']) == strtolower($channel) && strtolower($dep['dep']['name']) == strtolower($package)) { + if (!isset($dependencies[$info['channel']])) { + $dependencies[$info['channel']] = array(); + } + if (!isset($dependencies[$info['channel']][$info['package']])) { + $dependencies[$info['channel']][$info['package']] = array(); + } $dependencies[$info['channel']][$info['package']][] = $dep; } } @@ -290,16 +297,36 @@ class PEAR_DependencyDB return false; } foreach ($this->_cache['dependencies'][$channel][$package] as $info) { + if (isset($info['dep']['uri'])) { + if (is_object($child)) { + if ($info['dep']['uri'] == $child->getURI()) { + return true; + } + } elseif (isset($child['uri'])) { + if ($info['dep']['uri'] == $child['uri']) { + return true; + } + } + return false; + } if (strtolower($info['dep']['channel']) == strtolower($depchannel) && strtolower($info['dep']['name']) == strtolower($deppackage)) { return true; } } foreach ($this->_cache['dependencies'][$channel][$package] as $info) { - if ($this->_dependsOn(array( - 'channel' => $info['dep']['channel'], - 'package' => $info['dep']['name']), $child, $checked)) { - return true; + if (isset($info['dep']['uri'])) { + if ($this->_dependsOn(array( + 'uri' => $info['dep']['uri'], + 'package' => $info['dep']['name']), $child, $checked)) { + return true; + } + } else { + if ($this->_dependsOn(array( + 'channel' => $info['dep']['channel'], + 'package' => $info['dep']['name']), $child, $checked)) { + return true; + } } } return false; @@ -394,9 +421,15 @@ class PEAR_DependencyDB return $depdb; } $packages = $this->_registry->listAllPackages(); + if (PEAR::isError($packages)) { + return $packages; + } foreach ($packages as $channel => $ps) { foreach ($ps as $package) { $package = $this->_registry->getPackage($package, $channel); + if (PEAR::isError($package)) { + return $package; + } $this->_setPackageDeps($depdb, $package); } } @@ -424,8 +457,11 @@ class PEAR_DependencyDB $open_mode = 'w'; // XXX People reported problems with LOCK_SH and 'w' if ($mode === LOCK_SH) { - if (@!is_file($this->_lockfile)) { + if (!file_exists($this->_lockfile)) { touch($this->_lockfile); + } elseif (!is_file($this->_lockfile)) { + return PEAR::raiseError('could not create Dependency lock file, ' . + 'it exists and is not a regular file'); } $open_mode = 'r'; } @@ -484,13 +520,8 @@ class PEAR_DependencyDB $rt = get_magic_quotes_runtime(); set_magic_quotes_runtime(0); clearstatcache(); - if (function_exists('file_get_contents')) { - fclose($fp); - $data = unserialize(file_get_contents($this->_depdb)); - } else { - $data = unserialize(fread($fp, filesize($this->_depdb))); - fclose($fp); - } + fclose($fp); + $data = unserialize(file_get_contents($this->_depdb)); set_magic_quotes_runtime($rt); $this->_cache = $data; return $data; @@ -540,6 +571,15 @@ class PEAR_DependencyDB if (!$deps) { return; } + if (!is_array($data)) { + $data = array(); + } + if (!isset($data['dependencies'])) { + $data['dependencies'] = array(); + } + if (!isset($data['dependencies'][strtolower($pkg->getChannel())])) { + $data['dependencies'][strtolower($pkg->getChannel())] = array(); + } $data['dependencies'][strtolower($pkg->getChannel())][strtolower($pkg->getPackage())] = array(); if (isset($deps['required']['package'])) { @@ -628,6 +668,15 @@ class PEAR_DependencyDB } else { $depchannel = '__uri'; } + if (!isset($data['dependencies'])) { + $data['dependencies'] = array(); + } + if (!isset($data['dependencies'][strtolower($pkg->getChannel())])) { + $data['dependencies'][strtolower($pkg->getChannel())] = array(); + } + if (!isset($data['dependencies'][strtolower($pkg->getChannel())][strtolower($pkg->getPackage())])) { + $data['dependencies'][strtolower($pkg->getChannel())][strtolower($pkg->getPackage())] = array(); + } $data['dependencies'][strtolower($pkg->getChannel())][strtolower($pkg->getPackage())][] = $info; if (isset($data['packages'][strtolower($depchannel)][strtolower($dep['name'])])) { @@ -646,6 +695,15 @@ class PEAR_DependencyDB 'package' => strtolower($pkg->getPackage())); } } else { + if (!isset($data['packages'])) { + $data['packages'] = array(); + } + if (!isset($data['packages'][strtolower($depchannel)])) { + $data['packages'][strtolower($depchannel)] = array(); + } + if (!isset($data['packages'][strtolower($depchannel)][strtolower($dep['name'])])) { + $data['packages'][strtolower($depchannel)][strtolower($dep['name'])] = array(); + } $data['packages'][strtolower($depchannel)][strtolower($dep['name'])][] = array('channel' => strtolower($pkg->getChannel()), 'package' => strtolower($pkg->getPackage())); diff --git a/includes/pear/PEAR/Downloader.php b/includes/pear/PEAR/Downloader.php index cc9049e0..c70a07b1 100644 --- a/includes/pear/PEAR/Downloader.php +++ b/includes/pear/PEAR/Downloader.php @@ -16,9 +16,9 @@ * @author Stig Bakken * @author Tomas V. V. Cox * @author Martin Jansen - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Downloader.php,v 1.94 2005/10/29 21:23:19 cellog Exp $ + * @version CVS: $Id: Downloader.php,v 1.138 2008/04/11 01:16:40 dufuz Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.3.0 */ @@ -43,9 +43,9 @@ define('PEAR_INSTALLER_ERROR_NO_PREF_STATE', 2); * @author Stig Bakken * @author Tomas V. V. Cox * @author Martin Jansen - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.3.0 */ @@ -132,7 +132,7 @@ class PEAR_Downloader extends PEAR_Common * @access private */ var $_errorStack = array(); - + /** * @var boolean * @access private @@ -182,7 +182,8 @@ class PEAR_Downloader extends PEAR_Common if (!count($unused)) { continue; } - @array_walk($this->_installed[$key], 'strtolower'); + $strtolower = create_function('$a','return strtolower($a);'); + array_walk($this->_installed[$key], $strtolower); } } } @@ -208,12 +209,12 @@ class PEAR_Downloader extends PEAR_Common return false; } list($a, $lastmodified) = $a; - if (!class_exists('PEAR/ChannelFile.php')) { + if (!class_exists('PEAR_ChannelFile')) { require_once 'PEAR/ChannelFile.php'; } $b = new PEAR_ChannelFile; if ($b->fromXmlFile($a)) { - @unlink($a); + unlink($a); if ($this->config->get('auto_discover')) { $this->_registry->addChannel($b, $lastmodified); $alias = $b->getName(); @@ -225,7 +226,7 @@ class PEAR_Downloader extends PEAR_Common } return true; } - @unlink($a); + unlink($a); return false; } @@ -252,7 +253,7 @@ class PEAR_Downloader extends PEAR_Common */ function &getDependency2Object(&$c, $i, $p, $s) { - if (!class_exists('PEAR/Dependency2.php')) { + if (!class_exists('PEAR_Dependency2')) { require_once 'PEAR/Dependency2.php'; } $z = &new PEAR_Dependency2($c, $i, $p, $s); @@ -278,6 +279,10 @@ class PEAR_Downloader extends PEAR_Common PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $err = $params[$i]->initialize($param); PEAR::staticPopErrorHandling(); + if (!$err) { + // skip parameters that were missed by preferred_state + continue; + } if (PEAR::isError($err)) { if (!isset($this->_options['soft'])) { $this->log(0, $err->getMessage()); @@ -289,34 +294,58 @@ class PEAR_Downloader extends PEAR_Common $this->pushError('Package "' . $param . '" is not valid', PEAR_INSTALLER_SKIPPED); } else { - if ($params[$i] && !isset($channelschecked[$params[$i]->getChannel()]) && - !isset($this->_options['offline'])) { - $channelschecked[$params[$i]->getChannel()] = true; - PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); - if (!class_exists('System')) { - require_once 'System.php'; + do { + if ($params[$i] && $params[$i]->getType() == 'local') { + // bug #7090 + // skip channel.xml check for local packages + break; } - $curchannel = &$this->_registry->getChannel($params[$i]->getChannel()); - $a = $this->downloadHttp('http://' . $params[$i]->getChannel() . - '/channel.xml', $this->ui, - System::mktemp(array('-d')), null, $curchannel->lastModified()); - PEAR::staticPopErrorHandling(); - if (PEAR::isError($a) || !$a) { - continue; + if ($params[$i] && !isset($channelschecked[$params[$i]->getChannel()]) && + !isset($this->_options['offline'])) { + $channelschecked[$params[$i]->getChannel()] = true; + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + if (!class_exists('System')) { + require_once 'System.php'; + } + $curchannel = &$this->_registry->getChannel($params[$i]->getChannel()); + if (PEAR::isError($curchannel)) { + PEAR::staticPopErrorHandling(); + return $this->raiseError($curchannel); + } + if (PEAR::isError($dir = $this->getDownloadDir())) { + PEAR::staticPopErrorHandling(); + break; + } + $mirror = $this->config->get('preferred_mirror', null, + $params[$i]->getChannel()); + $a = $this->downloadHttp('http://' . $mirror . + '/channel.xml', $this->ui, $dir, null, $curchannel->lastModified()); + + PEAR::staticPopErrorHandling(); + if (PEAR::isError($a) || !$a) { + break; + } + $this->log(0, 'WARNING: channel "' . $params[$i]->getChannel() . '" has ' . + 'updated its protocols, use "channel-update ' . $params[$i]->getChannel() . + '" to update'); } - $this->log(0, 'WARNING: channel "' . $params[$i]->getChannel() . '" has ' . - 'updated its protocols, use "channel-update ' . $params[$i]->getChannel() . - '" to update'); - } + } while (false); if ($params[$i] && !isset($this->_options['downloadonly'])) { - $checkdir = $this->config->get('php_dir', null, $params[$i]->getChannel()); + if (isset($this->_options['packagingroot'])) { + $checkdir = $this->_prependPath( + $this->config->get('php_dir', null, $params[$i]->getChannel()), + $this->_options['packagingroot']); + } else { + $checkdir = $this->config->get('php_dir', + null, $params[$i]->getChannel()); + } while ($checkdir && $checkdir != '/' && !file_exists($checkdir)) { $checkdir = dirname($checkdir); } if ($checkdir == '.') { $checkdir = '/'; } - if (!@is_writeable($checkdir)) { + if (!is_writeable($checkdir)) { return PEAR::raiseError('Cannot install, php_dir for channel "' . $params[$i]->getChannel() . '" is not writeable by the current user'); } @@ -334,6 +363,9 @@ class PEAR_Downloader extends PEAR_Common while ($reverify) { $reverify = false; foreach ($params as $i => $param) { + //PHP Bug 40768 / PEAR Bug #10944 + //Nested foreaches fail in PHP 5.2.1 + key($params); $ret = $params[$i]->detectDependencies($params); if (PEAR::isError($ret)) { $reverify = true; @@ -355,6 +387,18 @@ class PEAR_Downloader extends PEAR_Common return $a; } while (PEAR_Downloader_Package::mergeDependencies($params)); + PEAR_Downloader_Package::removeDuplicates($params, true); + $errorparams = array(); + if (PEAR_Downloader_Package::detectStupidDuplicates($params, $errorparams)) { + if (count($errorparams)) { + foreach ($errorparams as $param) { + $name = $this->_registry->parsedPackageNameToString($param->getParsedPackage()); + $this->pushError('Duplicate package ' . $name . ' found', PEAR_INSTALLER_FAILED); + } + $a = array(); + return $a; + } + } PEAR_Downloader_Package::removeInstalled($params); if (!count($params)) { $this->pushError('No valid packages found', PEAR_INSTALLER_FAILED); @@ -374,6 +418,7 @@ class PEAR_Downloader extends PEAR_Common if (isset($this->_options['pretend'])) { return $params; } + $somefailed = false; foreach ($params as $i => $package) { PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $pf = &$params[$i]->download(); @@ -386,6 +431,7 @@ class PEAR_Downloader extends PEAR_Common true) . '"'); } + $somefailed = true; continue; } $newparams[] = &$params[$i]; @@ -393,6 +439,17 @@ class PEAR_Downloader extends PEAR_Common 'info' => &$pf, 'pkg' => $pf->getPackage()); } + if ($somefailed) { + // remove params that did not download successfully + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $err = $this->analyzeDependencies($newparams, true); + PEAR::popErrorHandling(); + if (!count($newparams)) { + $this->pushError('Download failed', PEAR_INSTALLER_FAILED); + $a = array(); + return $a; + } + } $this->_downloadedPackages = $ret; return $newparams; } @@ -400,7 +457,7 @@ class PEAR_Downloader extends PEAR_Common /** * @param array all packages to be installed */ - function analyzeDependencies(&$params) + function analyzeDependencies(&$params, $force = false) { $hasfailed = $failed = false; if (isset($this->_options['downloadonly'])) { @@ -436,7 +493,7 @@ class PEAR_Downloader extends PEAR_Common } continue; } - if (!$reset && $param->alreadyValidated()) { + if (!$reset && $param->alreadyValidated() && !$force) { continue; } if (count($deps)) { @@ -622,7 +679,12 @@ class PEAR_Downloader extends PEAR_Common return $this->_downloadDir; } $downloaddir = $this->config->get('download_dir'); - if (empty($downloaddir)) { + if (empty($downloaddir) || (is_dir($downloaddir) && !is_writable($downloaddir))) { + if (is_dir($downloaddir) && !is_writable($downloaddir)) { + $this->log(0, 'WARNING: configuration download directory "' . $downloaddir . + '" is not writeable. Change download_dir config variable to ' . + 'a writeable dir to avoid this warning'); + } if (!class_exists('System')) { require_once 'System.php'; } @@ -631,11 +693,26 @@ class PEAR_Downloader extends PEAR_Common } $this->log(3, '+ tmp dir created at ' . $downloaddir); } + if (!is_writable($downloaddir)) { + if (PEAR::isError(System::mkdir(array('-p', $downloaddir))) || + !is_writable($downloaddir)) { + return PEAR::raiseError('download directory "' . $downloaddir . + '" is not writeable. Change download_dir config variable to ' . + 'a writeable dir'); + } + } return $this->_downloadDir = $downloaddir; } function setDownloadDir($dir) { + if (!@is_writable($dir)) { + if (PEAR::isError(System::mkdir(array('-p', $dir)))) { + return PEAR::raiseError('download directory "' . $dir . + '" is not writeable. Change download_dir config variable to ' . + 'a writeable dir'); + } + } $this->_downloadDir = $dir; } @@ -703,22 +780,37 @@ class PEAR_Downloader extends PEAR_Common break; } } + $this->configSet('default_channel', $curchannel); return PEAR::raiseError('Unknown remote channel: ' . $remotechannel); } while (false); } $chan = &$this->_registry->getChannel($parr['channel']); + if (PEAR::isError($chan)) { + return $chan; + } + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $version = $this->_registry->packageInfo($parr['package'], 'version', $parr['channel']); + PEAR::staticPopErrorHandling(); + $base2 = false; if ($chan->supportsREST($this->config->get('preferred_mirror')) && - $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { - $rest = &$this->config->getREST('1.0', $this->_options); - if (!isset($parr['version']) && !isset($parr['state']) && $version - && !isset($this->_options['downloadonly'])) { - $url = $rest->getDownloadURL($base, $parr, $state, $version); + (($base2 = $chan->getBaseURL('REST1.3', $this->config->get('preferred_mirror'))) || + ($base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))))) { + if ($base2) { + $rest = &$this->config->getREST('1.3', $this->_options); + $base = $base2; } else { - $url = $rest->getDownloadURL($base, $parr, $state, false); + $rest = &$this->config->getREST('1.0', $this->_options); + } + if (!isset($parr['version']) && !isset($parr['state']) && $version + && !PEAR::isError($version) + && !isset($this->_options['downloadonly'])) { + $url = $rest->getDownloadURL($base, $parr, $state, $version, $chan->getName()); + } else { + $url = $rest->getDownloadURL($base, $parr, $state, false, $chan->getName()); } if (PEAR::isError($url)) { + $this->configSet('default_channel', $curchannel); return $url; } if ($parr['channel'] != $curchannel) { @@ -732,6 +824,17 @@ class PEAR_Downloader extends PEAR_Common return PEAR::raiseError('Invalid remote dependencies retrieved from REST - ' . 'this should never happen'); } + if (!isset($this->_options['force']) && + !isset($this->_options['downloadonly']) && + $version && + !PEAR::isError($version) && + !isset($parr['group'])) { + if (version_compare($version, $url['version'], '>=')) { + return PEAR::raiseError($this->_registry->parsedPackageNameToString( + $parr, true) . ' is already installed and is newer than detected ' . + 'release version ' . $url['version'], -976); + } + } if (isset($url['info']['required']) || $url['compatible']) { require_once 'PEAR/PackageFile/v2.php'; $pf = new PEAR_PackageFile_v2; @@ -745,6 +848,9 @@ class PEAR_Downloader extends PEAR_Common } $pf->setRawPackage($url['package']); $pf->setDeps($url['info']); + if ($url['compatible']) { + $pf->setCompatible($url['compatible']); + } $pf->setRawState($url['stability']); $url['info'] = &$pf; if (!extension_loaded("zlib") || isset($this->_options['nocompress'])) { @@ -787,8 +893,13 @@ class PEAR_Downloader extends PEAR_Common if (isset($this->_options['downloadonly'])) { $pkg = &$this->getPackagefileObject($this->config, $this->debug); } else { - $pkg = &$this->getPackagefileObject($this->config, $this->debug, - $this->getDownloadDir()); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + if (PEAR::isError($dir = $this->getDownloadDir())) { + PEAR::staticPopErrorHandling(); + return $dir; + } + PEAR::staticPopErrorHandling(); + $pkg = &$this->getPackagefileObject($this->config, $this->debug, $dir); } PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $pinfo = &$pkg->fromXmlString($url['info'], PEAR_VALIDATE_DOWNLOADING, 'remote'); @@ -823,34 +934,66 @@ class PEAR_Downloader extends PEAR_Common { $xsdversion = isset($dep['rel']) ? '1.0' : '2.0'; $curchannel = $this->config->get('default_channel'); - if (isset($dep['channel'])) { - $remotechannel = $dep['channel']; + if (isset($dep['uri'])) { + $xsdversion = '2.0'; + $chan = &$this->_registry->getChannel('__uri'); + if (PEAR::isError($chan)) { + return $chan; + } + $version = $this->_registry->packageInfo($dep['name'], 'version', '__uri'); + $this->configSet('default_channel', '__uri'); } else { - $remotechannel = 'pear.php.net'; - } - if (!$this->_registry->channelExists($remotechannel)) { - do { - if ($this->config->get('auto_discover')) { - if ($this->discover($remotechannel)) { - break; + if (isset($dep['channel'])) { + $remotechannel = $dep['channel']; + } else { + $remotechannel = 'pear.php.net'; + } + if (!$this->_registry->channelExists($remotechannel)) { + do { + if ($this->config->get('auto_discover')) { + if ($this->discover($remotechannel)) { + break; + } } - } - return PEAR::raiseError('Unknown remote channel: ' . $remotechannel); - } while (false); + return PEAR::raiseError('Unknown remote channel: ' . $remotechannel); + } while (false); + } + $chan = &$this->_registry->getChannel($remotechannel); + if (PEAR::isError($chan)) { + return $chan; + } + $version = $this->_registry->packageInfo($dep['name'], 'version', + $remotechannel); + $this->configSet('default_channel', $remotechannel); } - $this->configSet('default_channel', $remotechannel); $state = isset($parr['state']) ? $parr['state'] : $this->config->get('preferred_state'); if (isset($parr['state']) && isset($parr['version'])) { unset($parr['state']); } - $chan = &$this->_registry->getChannel($remotechannel); - $version = $this->_registry->packageInfo($dep['name'], 'version', - $remotechannel); - if ($chan->supportsREST($this->config->get('preferred_mirror')) && + if (isset($dep['uri'])) { + $info = &$this->newDownloaderPackage($this); + PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $err = $info->initialize($dep); + PEAR::staticPopErrorHandling(); + if (!$err) { + // skip parameters that were missed by preferred_state + return PEAR::raiseError('Cannot initialize dependency'); + } + if (PEAR::isError($err)) { + if (!isset($this->_options['soft'])) { + $this->log(0, $err->getMessage()); + } + if (is_object($info)) { + $param = $info->getChannel() . '/' . $info->getPackage(); + } + return PEAR::raiseError('Package "' . $param . '" is not valid'); + } + return $info; + } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) && $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { $rest = &$this->config->getREST('1.0', $this->_options); $url = $rest->getDepDownloadURL($base, $xsdversion, $dep, $parr, - $state, $version); + $state, $version, $chan->getName()); if (PEAR::isError($url)) { return $url; } @@ -879,6 +1022,9 @@ class PEAR_Downloader extends PEAR_Common } $pf->setRawPackage($url['package']); $pf->setDeps($url['info']); + if ($url['compatible']) { + $pf->setCompatible($url['compatible']); + } $pf->setRawState($url['stability']); $url['info'] = &$pf; if (!extension_loaded("zlib") || isset($this->_options['nocompress'])) { @@ -903,7 +1049,7 @@ class PEAR_Downloader extends PEAR_Common } else { $url = $this->_remote->call('package.getDepDownloadURL', $xsdversion, $dep, $parr, $state); } - if ($parr['channel'] != $curchannel) { + if ($this->config->get('default_channel') != $curchannel) { $this->configSet('default_channel', $curchannel); } if (!is_array($url)) { @@ -951,6 +1097,9 @@ class PEAR_Downloader extends PEAR_Common $package = "http://pear.php.net/get/$package"; } else { $chan = $this->_registry->getChannel($channel); + if (PEAR::isError($chan)) { + return ''; + } $package = "http://" . $chan->getServer() . "/get/$package"; } if (!extension_loaded("zlib")) { @@ -999,7 +1148,12 @@ class PEAR_Downloader extends PEAR_Common $bytes += $params; break; case 'start': - $this->log(1, "Starting to download {$params[0]} (".number_format($params[1], 0, '', ',')." bytes)"); + if($params[1] == -1) { + $length = "Unknown size"; + } else { + $length = number_format($params[1], 0, '', ',')." bytes"; + } + $this->log(1, "Starting to download {$params[0]} ($length)"); break; } if (method_exists($this->ui, '_downloadCallback')) @@ -1058,126 +1212,240 @@ class PEAR_Downloader extends PEAR_Common */ function sortPkgDeps(&$packages, $uninstall = false) { - $uninstall ? + $uninstall ? $this->sortPackagesForUninstall($packages) : $this->sortPackagesForInstall($packages); } - function _getDepTreeDP($package, $packages, &$deps, &$checked) - { - $pf = $package->getPackageFile(); - $checked[strtolower($package->getChannel())][strtolower($package->getPackage())] - = true; - $pdeps = $pf->getDeps(true); - if (!$pdeps) { - return; - } - if ($pf->getPackagexmlVersion() == '1.0') { - foreach ($pdeps as $dep) { - if ($dep['type'] != 'pkg') { - continue; - } - $deps['pear.php.net'][strtolower($dep['name'])] = true; - foreach ($packages as $p) { - $dep['channel'] = 'pear.php.net'; - $dep['package'] = $dep['name']; - if ($p->isEqual($dep)) { - if (!isset($checked[strtolower($p->getChannel())] - [strtolower($p->getPackage())])) { - // add the dependency's dependencies to the tree - $this->_getDepTreeDP($p, $packages, $deps, $checked); - } - } - } - } - } else { - $tdeps = array(); - if (isset($pdeps['required']['package'])) { - $t = $pdeps['required']['package']; - if (!isset($t[0])) { - $t = array($t); - } - $tdeps = array_merge($tdeps, $t); - } - if (isset($pdeps['required']['subpackage'])) { - $t = $pdeps['required']['subpackage']; - if (!isset($t[0])) { - $t = array($t); - } - $tdeps = array_merge($tdeps, $t); - } - if (isset($pdeps['optional']['package'])) { - $t = $pdeps['optional']['package']; - if (!isset($t[0])) { - $t = array($t); - } - $tdeps = array_merge($tdeps, $t); - } - if (isset($pdeps['optional']['subpackage'])) { - $t = $pdeps['optional']['subpackage']; - if (!isset($t[0])) { - $t = array($t); - } - $tdeps = array_merge($tdeps, $t); - } - if (isset($pdeps['group'])) { - if (!isset($pdeps['group'][0])) { - $pdeps['group'] = array($pdeps['group']); - } - foreach ($pdeps['group'] as $group) { - if (isset($group['package'])) { - $t = $group['package']; - if (!isset($t[0])) { - $t = array($t); - } - $tdeps = array_merge($tdeps, $t); - } - if (isset($group['subpackage'])) { - $t = $group['subpackage']; - if (!isset($t[0])) { - $t = array($t); - } - $tdeps = array_merge($tdeps, $t); - } - } - } - foreach ($tdeps as $dep) { - if (!isset($dep['channel'])) { - $depchannel = '__uri'; - } else { - $depchannel = $dep['channel']; - } - $deps[$depchannel][strtolower($dep['name'])] = true; - foreach ($packages as $p) { - $dep['channel'] = $depchannel; - $dep['package'] = $dep['name']; - if ($p->isEqual($dep)) { - if (!isset($checked[strtolower($p->getChannel())] - [strtolower($p->getPackage())])) { - // add the dependency's dependencies to the tree - $this->_getDepTreeDP($p, $packages, $deps, $checked); - } - } - } - } - } - } - /** * Sort a list of arrays of array(downloaded packagefilename) by dependency. * - * It also removes duplicate dependencies + * This uses the topological sort method from graph theory, and the + * Structures_Graph package to properly sort dependencies for installation. * @param array an array of downloaded PEAR_Downloader_Packages * @return array array of array(packagefilename, package.xml contents) */ function sortPackagesForInstall(&$packages) { + require_once 'Structures/Graph.php'; + require_once 'Structures/Graph/Node.php'; + require_once 'Structures/Graph/Manipulator/TopologicalSorter.php'; + $depgraph = new Structures_Graph(true); + $nodes = array(); + $reg = &$this->config->getRegistry(); foreach ($packages as $i => $package) { - $checked = $deps = array(); - $this->_getDepTreeDP($packages[$i], $packages, $deps, $checked); - $this->_depTree[$package->getChannel()][$package->getPackage()] = $deps; + $pname = $reg->parsedPackageNameToString( + array( + 'channel' => $package->getChannel(), + 'package' => strtolower($package->getPackage()), + )); + $nodes[$pname] = new Structures_Graph_Node; + $nodes[$pname]->setData($packages[$i]); + $depgraph->addNode($nodes[$pname]); + } + $deplinks = array(); + foreach ($nodes as $package => $node) { + $pf = &$node->getData(); + $pdeps = $pf->getDeps(true); + if (!$pdeps) { + continue; + } + if ($pf->getPackagexmlVersion() == '1.0') { + foreach ($pdeps as $dep) { + if ($dep['type'] != 'pkg' || + (isset($dep['optional']) && $dep['optional'] == 'yes')) { + continue; + } + $dname = $reg->parsedPackageNameToString( + array( + 'channel' => 'pear.php.net', + 'package' => strtolower($dep['name']), + )); + if (isset($nodes[$dname])) + { + if (!isset($deplinks[$dname])) { + $deplinks[$dname] = array(); + } + $deplinks[$dname][$package] = 1; + // dependency is in installed packages + continue; + } + $dname = $reg->parsedPackageNameToString( + array( + 'channel' => 'pecl.php.net', + 'package' => strtolower($dep['name']), + )); + if (isset($nodes[$dname])) + { + if (!isset($deplinks[$dname])) { + $deplinks[$dname] = array(); + } + $deplinks[$dname][$package] = 1; + // dependency is in installed packages + continue; + } + } + } else { + // the only ordering we care about is: + // 1) subpackages must be installed before packages that depend on them + // 2) required deps must be installed before packages that depend on them + if (isset($pdeps['required']['subpackage'])) { + $t = $pdeps['required']['subpackage']; + if (!isset($t[0])) { + $t = array($t); + } + $this->_setupGraph($t, $reg, $deplinks, $nodes, $package); + } + if (isset($pdeps['group'])) { + if (!isset($pdeps['group'][0])) { + $pdeps['group'] = array($pdeps['group']); + } + foreach ($pdeps['group'] as $group) { + if (isset($group['subpackage'])) { + $t = $group['subpackage']; + if (!isset($t[0])) { + $t = array($t); + } + $this->_setupGraph($t, $reg, $deplinks, $nodes, $package); + } + } + } + if (isset($pdeps['optional']['subpackage'])) { + $t = $pdeps['optional']['subpackage']; + if (!isset($t[0])) { + $t = array($t); + } + $this->_setupGraph($t, $reg, $deplinks, $nodes, $package); + } + if (isset($pdeps['required']['package'])) { + $t = $pdeps['required']['package']; + if (!isset($t[0])) { + $t = array($t); + } + $this->_setupGraph($t, $reg, $deplinks, $nodes, $package); + } + if (isset($pdeps['group'])) { + if (!isset($pdeps['group'][0])) { + $pdeps['group'] = array($pdeps['group']); + } + foreach ($pdeps['group'] as $group) { + if (isset($group['package'])) { + $t = $group['package']; + if (!isset($t[0])) { + $t = array($t); + } + $this->_setupGraph($t, $reg, $deplinks, $nodes, $package); + } + } + } + } + } + $this->_detectDepCycle($deplinks); + foreach ($deplinks as $dependent => $parents) { + foreach ($parents as $parent => $unused) { + $nodes[$dependent]->connectTo($nodes[$parent]); + } + } + $installOrder = Structures_Graph_Manipulator_TopologicalSorter::sort($depgraph); + $ret = array(); + for ($i = 0; $i < count($installOrder); $i++) { + foreach ($installOrder[$i] as $index => $sortedpackage) { + $data = &$installOrder[$i][$index]->getData(); + $ret[] = &$nodes[$reg->parsedPackageNameToString( + array( + 'channel' => $data->getChannel(), + 'package' => strtolower($data->getPackage()), + ))]->getData(); + } + } + $packages = $ret; + return; + } + + /** + * Detect recursive links between dependencies and break the cycles + * + * @param array + * @access private + */ + function _detectDepCycle(&$deplinks) + { + do { + $keepgoing = false; + foreach ($deplinks as $dep => $parents) { + foreach ($parents as $parent => $unused) { + // reset the parent cycle detector + $this->_testCycle(null, null, null); + if ($this->_testCycle($dep, $deplinks, $parent)) { + $keepgoing = true; + unset($deplinks[$dep][$parent]); + if (count($deplinks[$dep]) == 0) { + unset($deplinks[$dep]); + } + continue 3; + } + } + } + } while ($keepgoing); + } + + function _testCycle($test, $deplinks, $dep) + { + static $visited = array(); + if ($test === null) { + $visited = array(); + return; + } + // this happens when a parent has a dep cycle on another dependency + // but the child is not part of the cycle + if (isset($visited[$dep])) { + return false; + } + $visited[$dep] = 1; + if ($test == $dep) { + return true; + } + if (isset($deplinks[$dep])) { + if (in_array($test, array_keys($deplinks[$dep]), true)) { + return true; + } + foreach ($deplinks[$dep] as $parent => $unused) { + if ($this->_testCycle($test, $deplinks, $parent)) { + return true; + } + } + } + return false; + } + + /** + * Set up the dependency for installation parsing + * + * @param array $t dependency information + * @param PEAR_Registry $reg + * @param array $deplinks list of dependency links already established + * @param array $nodes all existing package nodes + * @param string $package parent package name + * @access private + */ + function _setupGraph($t, $reg, &$deplinks, &$nodes, $package) + { + foreach ($t as $dep) { + $depchannel = !isset($dep['channel']) ? + '__uri': $dep['channel']; + $dname = $reg->parsedPackageNameToString( + array( + 'channel' => $depchannel, + 'package' => strtolower($dep['name']), + )); + if (isset($nodes[$dname])) + { + if (!isset($deplinks[$dname])) { + $deplinks[$dname] = array(); + } + $deplinks[$dname][$package] = 1; + } } - usort($packages, array(&$this, '_sortInstall')); } function _dependsOn($a, $b) @@ -1265,6 +1533,7 @@ class PEAR_Downloader extends PEAR_Common * @param false|string|array $lastmodified header values to check against for caching * use false to return the header values from this download * @param false|array $accept Accept headers to send + * @param false|string $channel Channel to use for retrieving authentication * @return string|array Returns the full path of the downloaded file or a PEAR * error on failure. If the error is caused by * socket-related errors, the error object will @@ -1275,8 +1544,12 @@ class PEAR_Downloader extends PEAR_Common * @access public */ function downloadHttp($url, &$ui, $save_dir = '.', $callback = null, $lastmodified = null, - $accept = false) + $accept = false, $channel = false) { + static $redirect = 0; + // allways reset , so we are clean case of error + $wasredirect = $redirect; + $redirect = 0; if ($callback) { call_user_func($callback, 'setup', array(&$ui)); } @@ -1287,9 +1560,9 @@ class PEAR_Downloader extends PEAR_Common if (!isset($info['host'])) { return PEAR::raiseError('Cannot download from non-URL "' . $url . '"'); } else { - $host = @$info['host']; - $port = @$info['port']; - $path = @$info['path']; + $host = isset($info['host']) ? $info['host'] : null; + $port = isset($info['port']) ? $info['port'] : null; + $path = isset($info['path']) ? $info['path'] : null; } if (isset($this)) { $config = &$this->config; @@ -1297,19 +1570,16 @@ class PEAR_Downloader extends PEAR_Common $config = &PEAR_Config::singleton(); } $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; - if ($config->get('http_proxy')&& + if ($config->get('http_proxy') && $proxy = parse_url($config->get('http_proxy'))) { - $proxy_host = @$proxy['host']; + $proxy_host = isset($proxy['host']) ? $proxy['host'] : null; if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') { $proxy_host = 'ssl://' . $proxy_host; } - $proxy_port = @$proxy['port']; - $proxy_user = @$proxy['user']; - $proxy_pass = @$proxy['pass']; + $proxy_port = isset($proxy['port']) ? $proxy['port'] : 8080; + $proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null; + $proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null; - if ($proxy_port == '') { - $proxy_port = 8080; - } if ($callback) { call_user_func($callback, 'message', "Using HTTP proxy $host:$port"); } @@ -1349,8 +1619,10 @@ class PEAR_Downloader extends PEAR_Common } if ($lastmodified === false || $lastmodified) { $request = "GET $path HTTP/1.1\r\n"; + $request .= "Host: $host:$port\r\n"; } else { $request = "GET $path HTTP/1.0\r\n"; + $request .= "Host: $host\r\n"; } } $ifmodifiedsince = ''; @@ -1364,11 +1636,11 @@ class PEAR_Downloader extends PEAR_Common } else { $ifmodifiedsince = ($lastmodified ? "If-Modified-Since: $lastmodified\r\n" : ''); } - $request .= "Host: $host:$port\r\n" . $ifmodifiedsince . - "User-Agent: PEAR/1.4.5/PHP/" . PHP_VERSION . "\r\n"; + $request .= $ifmodifiedsince . "User-Agent: PEAR/1.7.2/PHP/" . + PHP_VERSION . "\r\n"; if (isset($this)) { // only pass in authentication for non-static calls - $username = $config->get('username'); - $password = $config->get('password'); + $username = $config->get('username', null, $channel); + $password = $config->get('password', null, $channel); if ($username && $password) { $tmp = base64_encode("$username:$password"); $request .= "Authorization: Basic $tmp\r\n"; @@ -1385,20 +1657,35 @@ class PEAR_Downloader extends PEAR_Common $request .= "\r\n"; fwrite($fp, $request); $headers = array(); + $reply = 0; while (trim($line = fgets($fp, 1024))) { - if (preg_match('/^([^:]+):\s+(.*)\s*$/', $line, $matches)) { + if (preg_match('/^([^:]+):\s+(.*)\s*\\z/', $line, $matches)) { $headers[strtolower($matches[1])] = trim($matches[2]); } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) { - if ($matches[1] == 304 && ($lastmodified || ($lastmodified === false))) { + $reply = (int) $matches[1]; + if ($reply == 304 && ($lastmodified || ($lastmodified === false))) { return false; } - if ($matches[1] != 200) { + if (! in_array($reply, array(200, 301, 302, 303, 305, 307))) { return PEAR::raiseError("File http://$host:$port$path not valid (received: $line)"); } } } + if ($reply != 200) { + if (isset($headers['location'])) { + if ($wasredirect < 5) { + $redirect = $wasredirect + 1; + return $this->downloadHttp($headers['location'], + $ui, $save_dir, $callback, $lastmodified, $accept); + } else { + return PEAR::raiseError("File http://$host:$port$path not valid (redirection looped more than 5 times)"); + } + } else { + return PEAR::raiseError("File http://$host:$port$path not valid (redirected but no location)"); + } + } if (isset($headers['content-disposition']) && - preg_match('/\sfilename=\"([^;]*\S)\"\s*(;|$)/', $headers['content-disposition'], $matches)) { + preg_match('/\sfilename=\"([^;]*\S)\"\s*(;|\\z)/', $headers['content-disposition'], $matches)) { $save_as = basename($matches[1]); } else { $save_as = basename($url); @@ -1426,7 +1713,7 @@ class PEAR_Downloader extends PEAR_Common if ($callback) { call_user_func($callback, 'start', array(basename($dest_file), $length)); } - while ($data = @fread($fp, 1024)) { + while ($data = fread($fp, 1024)) { $bytes += strlen($data); if ($callback) { call_user_func($callback, 'bytesread', $bytes); @@ -1462,4 +1749,4 @@ class PEAR_Downloader extends PEAR_Common } // }}} -?> \ No newline at end of file +?> diff --git a/includes/pear/PEAR/Downloader/Package.php b/includes/pear/PEAR/Downloader/Package.php index c16e29db..90eaa2d2 100644 --- a/includes/pear/PEAR/Downloader/Package.php +++ b/includes/pear/PEAR/Downloader/Package.php @@ -13,12 +13,22 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Package.php,v 1.88 2005/10/29 22:09:45 cellog Exp $ + * @version CVS: $Id: Package.php,v 1.113 2008/03/29 14:18:36 dufuz Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ +/** + * Error code when parameter initialization fails because no releases + * exist within preferred_state, but releases do exist + */ +define('PEAR_DOWNLOADER_PACKAGE_STATE', -1003); +/** + * Error code when parameter initialization fails because no releases + * exist that will work with the existing PHP version + */ +define('PEAR_DOWNLOADER_PACKAGE_PHPVERSION', -1004); /** * Coordinates download parameters and manages their dependencies * prior to downloading them. @@ -42,9 +52,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -62,6 +72,11 @@ class PEAR_Downloader_Package * @var PEAR_Registry */ var $_registry; + /** + * Used to implement packagingroot properly + * @var PEAR_Registry + */ + var $_installRegistry; /** * @var PEAR_PackageFile_v1|PEAR_PackageFile|v2 */ @@ -117,13 +132,21 @@ class PEAR_Downloader_Package var $_validated = false; /** - * @param PEAR_Config + * @param PEAR_Downloader */ function PEAR_Downloader_Package(&$downloader) { $this->_downloader = &$downloader; $this->_config = &$this->_downloader->config; $this->_registry = &$this->_config->getRegistry(); + $options = $downloader->getOptions(); + if (isset($options['packagingroot'])) { + $this->_config->setInstallRoot($options['packagingroot']); + $this->_installRegistry = &$this->_config->getRegistry(); + $this->_config->setInstallRoot(false); + } else { + $this->_installRegistry = &$this->_registry; + } $this->_valid = $this->_analyzed = false; } @@ -134,7 +157,7 @@ class PEAR_Downloader_Package * This is the heart of the PEAR_Downloader_Package(), and is used in * {@link PEAR_Downloader::download()} * @param string - * @return void|PEAR_Error + * @return bool|PEAR_Error */ function initialize($param) { @@ -161,6 +184,10 @@ class PEAR_Downloader_Package } $err = $this->_fromString($param); if (PEAR::isError($err) || !$this->_valid) { + if (PEAR::isError($err) && + $err->getCode() == PEAR_DOWNLOADER_PACKAGE_STATE) { + return false; // instruct the downloader to silently skip + } if (isset($this->_type) && $this->_type == 'local' && PEAR::isError($origErr)) { if (is_array($origErr->getUserInfo())) { @@ -196,6 +223,7 @@ class PEAR_Downloader_Package } } } + return true; } /** @@ -252,7 +280,7 @@ class PEAR_Downloader_Package return $this->_downloader; } - function getType() + function getType() { return $this->_type; } @@ -345,8 +373,8 @@ class PEAR_Downloader_Package foreach ($params as $i => $param) { // remove self if already installed with this version // this does not need any pecl magic - we only remove exact matches - if ($param->_registry->packageExists($param->getPackage(), $param->getChannel())) { - if (version_compare($param->_registry->packageInfo($param->getPackage(), 'version', + if ($param->_installRegistry->packageExists($param->getPackage(), $param->getChannel())) { + if (version_compare($param->_installRegistry->packageInfo($param->getPackage(), 'version', $param->getChannel()), $param->getVersion(), '==')) { if (!isset($options['force'])) { $info = $param->getParsedPackage(); @@ -356,7 +384,7 @@ class PEAR_Downloader_Package $param->_downloader->log(1, 'Skipping package "' . $param->getShortName() . '", already installed as version ' . - $param->_registry->packageInfo($param->getPackage(), + $param->_installRegistry->packageInfo($param->getPackage(), 'version', $param->getChannel())); } $params[$i] = false; @@ -367,7 +395,7 @@ class PEAR_Downloader_Package $param->_downloader->log(1, 'Skipping package "' . $param->getShortName() . '", already installed as version ' . - $param->_registry->packageInfo($param->getPackage(), 'version', + $param->_installRegistry->packageInfo($param->getPackage(), 'version', $param->getChannel())); $params[$i] = false; } @@ -430,7 +458,9 @@ class PEAR_Downloader_Package } if (!($ret = $this->_detect2Dep($dep, $pname, 'optional', $params))) { $dep['package'] = $dep['name']; - if (@$skipnames[count($skipnames) - 1] == + $skip = count($skipnames) ? + $skipnames[count($skipnames) - 1] : ''; + if ($skip == $this->_registry->parsedPackageNameToString($dep, true)) { array_pop($skipnames); } @@ -551,7 +581,7 @@ class PEAR_Downloader_Package } $dep['package'] = $dep['name']; $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params, $group == 'optional' && - !isset($options['alldeps'])); + !isset($options['alldeps']), true); PEAR::popErrorHandling(); if (PEAR::isError($ret)) { if (!isset($options['soft'])) { @@ -569,7 +599,7 @@ class PEAR_Downloader_Package // we can't determine whether upgrade is necessary until we know what // version would be downloaded if (!isset($options['force']) && $this->isInstalled($ret, $oper)) { - $version = $this->_registry->packageInfo($dep['name'], 'version', + $version = $this->_installRegistry->packageInfo($dep['name'], 'version', $dep['channel']); $dep['package'] = $dep['name']; if (!isset($options['soft'])) { @@ -645,7 +675,7 @@ class PEAR_Downloader_Package $chan = 'pecl.php.net'; $url = $this->_downloader->_getDepPackageDownloadUrl($newdep, $pname); - $obj = &$this->_registry->getPackage($dep['name']); + $obj = &$this->_installRegistry->getPackage($dep['name']); if (PEAR::isError($url)) { PEAR::popErrorHandling(); if ($obj !== null && $this->isInstalled($obj, $dep['rel'])) { @@ -659,7 +689,9 @@ class PEAR_Downloader_Package $this->_registry->parsedPackageNameToString($dep, true) . '", already installed as version ' . $obj->getVersion()); } - if (@$skipnames[count($skipnames) - 1] == + $skip = count($skipnames) ? + $skipnames[count($skipnames) - 1] : ''; + if ($skip == $this->_registry->parsedPackageNameToString($dep, true)) { array_pop($skipnames); } @@ -667,8 +699,7 @@ class PEAR_Downloader_Package } else { if (isset($dep['optional']) && $dep['optional'] == 'yes') { $this->_downloader->log(2, $this->getShortName() . - ': Skipping ' . $group - . ' dependency "' . + ': Skipping optional dependency "' . $this->_registry->parsedPackageNameToString($dep, true) . '", no releases exist'); continue; @@ -724,10 +755,10 @@ class PEAR_Downloader_Package 'optional'; $dep['package'] = $dep['name']; if (isset($newdep)) { - $version = $this->_registry->packageInfo($newdep['name'], 'version', + $version = $this->_installRegistry->packageInfo($newdep['name'], 'version', $newdep['channel']); } else { - $version = $this->_registry->packageInfo($dep['name'], 'version'); + $version = $this->_installRegistry->packageInfo($dep['name'], 'version'); } $dep['version'] = $url['version']; if (!isset($options['soft'])) { @@ -736,7 +767,9 @@ class PEAR_Downloader_Package $this->_registry->parsedPackageNameToString($dep, true) . '", already installed as version ' . $version); } - if (@$skipnames[count($skipnames) - 1] == + $skip = count($skipnames) ? + $skipnames[count($skipnames) - 1] : ''; + if ($skip == $this->_registry->parsedPackageNameToString($dep, true)) { array_pop($skipnames); } @@ -752,7 +785,7 @@ class PEAR_Downloader_Package $dep['package'] = $dep['name']; $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params, isset($dep['optional']) && $dep['optional'] == 'yes' && - !isset($options['alldeps'])); + !isset($options['alldeps']), true); PEAR::popErrorHandling(); if (PEAR::isError($ret)) { if (!isset($options['soft'])) { @@ -794,7 +827,7 @@ class PEAR_Downloader_Package } function getParsedPackage() - { + { if (isset($this->_packagefile) || isset($this->_parsedname)) { return array('channel' => $this->getChannel(), 'package' => $this->getPackage(), @@ -937,7 +970,11 @@ class PEAR_Downloader_Package if (isset($this->_packagefile)) { return $this->_packagefile->isExtension($name); } elseif (isset($this->_downloadURL['info'])) { - return $this->_downloadURL['info']->getProvidesExtension() == $name; + if ($this->_downloadURL['info']->getPackagexmlVersion() == '2.0') { + return $this->_downloadURL['info']->getProvidesExtension() == $name; + } else { + return false; + } } else { return false; } @@ -946,13 +983,15 @@ class PEAR_Downloader_Package function getDeps() { if (isset($this->_packagefile)) { - if ($this->_packagefile->getPackagexmlVersion() == '2.0') { + $ver = $this->_packagefile->getPackagexmlVersion(); + if (version_compare($ver, '2.0', '>=')) { return $this->_packagefile->getDeps(true); } else { return $this->_packagefile->getDeps(); } } elseif (isset($this->_downloadURL['info'])) { - if ($this->_downloadURL['info']->getPackagexmlVersion() == '2.0') { + $ver = $this->_downloadURL['info']->getPackagexmlVersion(); + if (version_compare($ver, '2.0', '>=')) { return $this->_downloadURL['info']->getDeps(true); } else { return $this->_downloadURL['info']->getDeps(); @@ -987,8 +1026,10 @@ class PEAR_Downloader_Package } } else { if (isset($param['uri'])) { - $param['channel'] = '__uri'; - $param['package'] = $param['dep']['name']; + if ($this->getChannel() != '__uri') { + return false; + } + return $param['uri'] == $this->getURI(); } $package = isset($param['package']) ? $param['package'] : $param['info']->getPackage(); @@ -1075,21 +1116,21 @@ class PEAR_Downloader_Package } } $options = $this->_downloader->getOptions(); - $test = $this->_registry->packageExists($package, $channel); + $test = $this->_installRegistry->packageExists($package, $channel); if (!$test && $channel == 'pecl.php.net') { // do magic to allow upgrading from old pecl packages to new ones - $test = $this->_registry->packageExists($package, 'pear.php.net'); + $test = $this->_installRegistry->packageExists($package, 'pear.php.net'); $channel = 'pear.php.net'; } if ($test) { if (isset($dep['uri'])) { - if ($this->_registry->packageInfo($package, 'uri', '__uri') == $dep['uri']) { + if ($this->_installRegistry->packageInfo($package, 'uri', '__uri') == $dep['uri']) { return true; } } if (isset($options['upgrade'])) { if ($oper == 'has') { - if (version_compare($this->_registry->packageInfo( + if (version_compare($this->_installRegistry->packageInfo( $package, 'version', $channel), $dep['version'], '>=')) { return true; @@ -1097,7 +1138,7 @@ class PEAR_Downloader_Package return false; } } else { - if (version_compare($this->_registry->packageInfo( + if (version_compare($this->_installRegistry->packageInfo( $package, 'version', $channel), $dep['version'], '>=')) { return true; @@ -1110,11 +1151,55 @@ class PEAR_Downloader_Package return false; } + /** + * Detect duplicate package names with differing versions + * + * If a user requests to install Date 1.4.6 and Date 1.4.7, + * for instance, this is a logic error. This method + * detects this situation. + * + * @param array $params array of PEAR_Downloader_Package objects + * @param array $errorparams empty array + * @return array array of stupid duplicated packages in PEAR_Downloader_Package obejcts + */ + function detectStupidDuplicates($params, &$errorparams) + { + $existing = array(); + foreach ($params as $i => $param) { + $package = $param->getPackage(); + $channel = $param->getChannel(); + $group = $param->getGroup(); + if (!isset($existing[$channel . '/' . $package])) { + $existing[$channel . '/' . $package] = array(); + } + if (!isset($existing[$channel . '/' . $package][$group])) { + $existing[$channel . '/' . $package][$group] = array(); + } + $existing[$channel . '/' . $package][$group][] = $i; + } + + $indices = array(); + foreach ($existing as $package => $groups) { + foreach ($groups as $group => $dupes) { + if (count($dupes) > 1) { + $indices = $indices + $dupes; + } + } + } + + $indices = array_unique($indices); + foreach ($indices as $index) { + $errorparams[] = $params[$index]; + } + return count($errorparams); + } + /** * @param array + * @param bool ignore install groups - for final removal of dupe packages * @static */ - function removeDuplicates(&$params) + function removeDuplicates(&$params, $ignoreGroups = false) { $pnames = array(); foreach ($params as $i => $param) { @@ -1122,8 +1207,13 @@ class PEAR_Downloader_Package continue; } if ($param->getPackage()) { + if ($ignoreGroups) { + $group = ''; + } else { + $group = $param->getGroup(); + } $pnames[$i] = $param->getChannel() . '/' . - $param->getPackage() . '-' . $param->getVersion() . '#' . $param->getGroup(); + $param->getPackage() . '-' . $param->getVersion() . '#' . $group; } } $pnames = array_unique($pnames); @@ -1138,8 +1228,13 @@ class PEAR_Downloader_Package $unset[] = $i; continue; } + if ($ignoreGroups) { + $group = ''; + } else { + $group = $param->getGroup(); + } if (!isset($testp[$param->getChannel() . '/' . $param->getPackage() . '-' . - $param->getVersion() . '#' . $param->getGroup()])) { + $param->getVersion() . '#' . $group])) { $unset[] = $i; } } @@ -1188,7 +1283,10 @@ class PEAR_Downloader_Package $filecontents = $pf->getFileContents($file); $dl = &$param->getDownloader(); $options = $dl->getOptions(); - $fp = @fopen($dl->getDownloadDir() . DIRECTORY_SEPARATOR . $file, 'wb'); + if (PEAR::isError($dir = $dl->getDownloadDir())) { + return $dir; + } + $fp = @fopen($dir . DIRECTORY_SEPARATOR . $file, 'wb'); if (!$fp) { continue; } @@ -1199,7 +1297,11 @@ class PEAR_Downloader_Package } $obj = &new PEAR_Downloader_Package($params[$i]->getDownloader()); PEAR::pushErrorHandling(PEAR_ERROR_RETURN); - $e = $obj->_fromFile($a = $dl->getDownloadDir() . DIRECTORY_SEPARATOR . $file); + if (PEAR::isError($dir = $dl->getDownloadDir())) { + PEAR::popErrorHandling(); + return $dir; + } + $e = $obj->_fromFile($a = $dir . DIRECTORY_SEPARATOR . $file); PEAR::popErrorHandling(); if (PEAR::isError($e)) { if (!isset($options['soft'])) { @@ -1309,38 +1411,46 @@ class PEAR_Downloader_Package */ function _fromFile(&$param) { - if (is_string($param) && !@is_file($param)) { - $test = explode('#', $param); - $group = array_pop($test); - if (@is_file(implode('#', $test))) { - $this->setGroup($group); - $param = implode('#', $test); - $this->_explicitGroup = true; + $saveparam = $param; + if (is_string($param)) { + if (!@file_exists($param)) { + $test = explode('#', $param); + $group = array_pop($test); + if (@file_exists(implode('#', $test))) { + $this->setGroup($group); + $param = implode('#', $test); + $this->_explicitGroup = true; + } + } + if (@is_file($param)) { + $this->_type = 'local'; + $options = $this->_downloader->getOptions(); + if (isset($options['downloadonly'])) { + $pkg = &$this->getPackagefileObject($this->_config, + $this->_downloader->_debug); + } else { + if (PEAR::isError($dir = $this->_downloader->getDownloadDir())) { + return $dir; + } + $pkg = &$this->getPackagefileObject($this->_config, + $this->_downloader->_debug, $dir); + } + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $pf = &$pkg->fromAnyFile($param, PEAR_VALIDATE_INSTALLING); + PEAR::popErrorHandling(); + if (PEAR::isError($pf)) { + $this->_valid = false; + $param = $saveparam; + return $pf; + } + $this->_packagefile = &$pf; + if (!$this->getGroup()) { + $this->setGroup('default'); // install the default dependency group + } + return $this->_valid = true; } } - if (@is_file($param)) { - $this->_type = 'local'; - $options = $this->_downloader->getOptions(); - if (isset($options['downloadonly'])) { - $pkg = &$this->getPackagefileObject($this->_config, - $this->_downloader->_debug); - } else { - $pkg = &$this->getPackagefileObject($this->_config, - $this->_downloader->_debug, $this->_downloader->getDownloadDir()); - } - PEAR::pushErrorHandling(PEAR_ERROR_RETURN); - $pf = &$pkg->fromAnyFile($param, PEAR_VALIDATE_INSTALLING); - PEAR::popErrorHandling(); - if (PEAR::isError($pf)) { - $this->_valid = false; - return $pf; - } - $this->_packagefile = &$pf; - if (!$this->getGroup()) { - $this->setGroup('default'); // install the default dependency group - } - return $this->_valid = true; - } + $param = $saveparam; return $this->_valid = false; } @@ -1353,15 +1463,20 @@ class PEAR_Downloader_Package $callback = $this->_downloader->ui ? array(&$this->_downloader, '_downloadCallback') : null; $this->_downloader->pushErrorHandling(PEAR_ERROR_RETURN); + if (PEAR::isError($dir = $this->_downloader->getDownloadDir())) { + $this->_downloader->popErrorHandling(); + return $dir; + } + $this->_downloader->log(3, 'Downloading "' . $param . '"'); $file = $this->_downloader->downloadHttp($param, $this->_downloader->ui, - $this->_downloader->getDownloadDir(), $callback); + $dir, $callback, null, false, $this->getChannel()); $this->_downloader->popErrorHandling(); if (PEAR::isError($file)) { if (!empty($saveparam)) { $saveparam = ", cannot download \"$saveparam\""; } $err = PEAR::raiseError('Could not download from "' . $param . - '"' . $saveparam); + '"' . $saveparam . ' (' . $file->getMessage() . ')'); return $err; } if ($this->_rawpackagefile) { @@ -1391,8 +1506,11 @@ class PEAR_Downloader_Package if (isset($options['downloadonly'])) { $pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->debug); } else { + if (PEAR::isError($dir = $this->_downloader->getDownloadDir())) { + return $dir; + } $pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->debug, - $this->_downloader->getDownloadDir()); + $dir); } PEAR::pushErrorHandling(PEAR_ERROR_RETURN); $pf = &$pkg->fromAnyFile($file, PEAR_VALIDATE_INSTALLING); @@ -1500,7 +1618,7 @@ class PEAR_Downloader_Package } $info = $this->_downloader->_getPackageDownloadUrl($pname); if (PEAR::isError($info)) { - if ($pname['channel'] == 'pear.php.net') { + if ($info->getCode() != -976 && $pname['channel'] == 'pear.php.net') { // try pecl $pname['channel'] = 'pecl.php.net'; if ($test = $this->_downloader->_getPackageDownloadUrl($pname)) { @@ -1509,7 +1627,11 @@ class PEAR_Downloader_Package $this->_registry->parsedPackageNameToString($pname, true) . ' can be installed with "pecl install ' . $pname['package'] . '"'); + } else { + $pname['channel'] = 'pear.php.net'; } + } else { + $pname['channel'] = 'pear.php.net'; } } return $info; @@ -1532,9 +1654,11 @@ class PEAR_Downloader_Package * @param array name information of the package * @param array|null packages to be downloaded * @param bool is this an optional dependency? + * @param bool is this any kind of dependency? * @access private */ - function _analyzeDownloadURL($info, $param, $pname, $params = null, $optional = false) + function _analyzeDownloadURL($info, $param, $pname, $params = null, $optional = false, + $isdependency = false) { if (!is_string($param) && PEAR_Downloader_Package::willDownload($param, $params)) { return false; @@ -1569,6 +1693,16 @@ class PEAR_Downloader_Package } } if (!isset($info['url'])) { + if ($this->isInstalled($info)) { + if ($isdependency && version_compare($info['version'], + $this->_registry->packageInfo($info['info']->getPackage(), + 'version', $info['info']->getChannel()), '<=')) { + // ignore bogus errors of "failed to download dependency" + // if it is already installed and the one that would be + // downloaded is older or the same version (Bug #7219) + return false; + } + } $instead = ', will instead download version ' . $info['version'] . ', stability "' . $info['info']->getState() . '"'; // releases exist, but we failed to get any @@ -1620,6 +1754,21 @@ class PEAR_Downloader_Package 'channel' => $pname['channel'], 'version' => $info['version'])); } else { + if (isset($info['php']) && $info['php']) { + $err = PEAR::raiseError('Failed to download ' . + $this->_registry->parsedPackageNameToString( + array('channel' => $pname['channel'], + 'package' => $pname['package']), + true) . + ', latest release is version ' . $info['php']['v'] . + ', but it requires PHP version "' . + $info['php']['m'] . '", use "' . + $this->_registry->parsedPackageNameToString( + array('channel' => $pname['channel'], 'package' => $pname['package'], + 'version' => $info['php']['v'])) . '" to install', + PEAR_DOWNLOADER_PACKAGE_PHPVERSION); + return $err; + } // construct helpful error message if (isset($pname['version'])) { $vs = ', version "' . $pname['version'] . '"'; @@ -1659,6 +1808,22 @@ class PEAR_Downloader_Package $vs = ' within preferred state "' . $this->_downloader->config->get( 'preferred_state') . '"'; } + $options = $this->_downloader->getOptions(); + // this is only set by the "download-all" command + if (isset($options['ignorepreferred_state'])) { + $err = PEAR::raiseError( + 'Failed to download ' . $this->_registry->parsedPackageNameToString( + array('channel' => $pname['channel'], 'package' => $pname['package']), + true) + . $vs . + ', latest release is version ' . $info['version'] . + ', stability "' . $info['info']->getState() . '", use "' . + $this->_registry->parsedPackageNameToString( + array('channel' => $pname['channel'], 'package' => $pname['package'], + 'version' => $info['version'])) . '" to install', + PEAR_DOWNLOADER_PACKAGE_STATE); + return $err; + } $err = PEAR::raiseError( 'Failed to download ' . $this->_registry->parsedPackageNameToString( array('channel' => $pname['channel'], 'package' => $pname['package']), @@ -1672,6 +1837,16 @@ class PEAR_Downloader_Package return $err; } } + if (isset($info['deprecated']) && $info['deprecated']) { + $this->_downloader->log(0, + 'WARNING: "' . + $this->_registry->parsedPackageNameToString( + array('channel' => $info['info']->getChannel(), + 'package' => $info['info']->getPackage()), true) . + '" is deprecated in favor of "' . + $this->_registry->parsedPackageNameToString($info['deprecated'], true) . + '"'); + } return $info; } } diff --git a/includes/pear/PEAR/ErrorStack.php b/includes/pear/PEAR/ErrorStack.php index 34ff3658..ad049011 100644 --- a/includes/pear/PEAR/ErrorStack.php +++ b/includes/pear/PEAR/ErrorStack.php @@ -21,9 +21,9 @@ * @category Debugging * @package PEAR_ErrorStack * @author Greg Beaver - * @copyright 2004-2005 Greg Beaver + * @copyright 2004-2008 Greg Beaver * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: ErrorStack.php,v 1.21 2005/09/04 23:29:50 cellog Exp $ + * @version CVS: $Id: ErrorStack.php,v 1.28 2008/01/03 20:26:35 cellog Exp $ * @link http://pear.php.net/package/PEAR_ErrorStack */ @@ -132,12 +132,12 @@ define('PEAR_ERRORSTACK_ERR_OBJTOSTRING', 2); * $local_stack = new PEAR_ErrorStack('MyPackage'); * * @author Greg Beaver - * @version 1.4.5 + * @version 1.7.2 * @package PEAR_ErrorStack * @category Debugging - * @copyright 2004-2005 Greg Beaver + * @copyright 2004-2008 Greg Beaver * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: ErrorStack.php,v 1.21 2005/09/04 23:29:50 cellog Exp $ + * @version CVS: $Id: ErrorStack.php,v 1.28 2008/01/03 20:26:35 cellog Exp $ * @link http://pear.php.net/package/PEAR_ErrorStack */ class PEAR_ErrorStack { @@ -476,19 +476,10 @@ class PEAR_ErrorStack { * @param array $backtrace Protected parameter: use this to pass in the * {@link debug_backtrace()} that should be used * to find error context - * @return PEAR_Error|array|Exception - * if compatibility mode is on, a PEAR_Error is also - * thrown. If the class Exception exists, then one - * is returned to allow code like: - * - * throw ($stack->push(MY_ERROR_CODE, 'error', array('username' => 'grob'))); - * + * @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also + * thrown. If a PEAR_Error is returned, the userinfo + * property is set to the following array: * - * The errorData property of the exception class will be set to the array - * that would normally be returned. If a PEAR_Error is returned, the userinfo - * property is set to the array - * - * Otherwise, an array is returned in this format: * * array( * 'code' => $code, @@ -501,6 +492,8 @@ class PEAR_ErrorStack { * //['repackage' => $err] repackaged error array/Exception class * ); * + * + * Normally, the previous array is returned. */ function push($code, $level = 'error', $params = array(), $msg = false, $repackage = false, $backtrace = false) @@ -575,6 +568,9 @@ class PEAR_ErrorStack { } if ($push) { array_unshift($this->_errors, $err); + if (!isset($this->_errorsByLevel[$err['level']])) { + $this->_errorsByLevel[$err['level']] = array(); + } $this->_errorsByLevel[$err['level']][] = &$this->_errors[0]; } if ($log) { @@ -606,13 +602,8 @@ class PEAR_ErrorStack { * @param array $backtrace Protected parameter: use this to pass in the * {@link debug_backtrace()} that should be used * to find error context - * @return PEAR_Error|null|Exception - * if compatibility mode is on, a PEAR_Error is also - * thrown. If the class Exception exists, then one - * is returned to allow code like: - * - * throw ($stack->push(MY_ERROR_CODE, 'error', array('username' => 'grob'))); - * + * @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also + * thrown. see docs for {@link push()} * @static */ function staticPush($package, $code, $level = 'error', $params = array(), @@ -673,9 +664,33 @@ class PEAR_ErrorStack { */ function pop() { - return @array_shift($this->_errors); + $err = @array_shift($this->_errors); + if (!is_null($err)) { + @array_pop($this->_errorsByLevel[$err['level']]); + if (!count($this->_errorsByLevel[$err['level']])) { + unset($this->_errorsByLevel[$err['level']]); + } + } + return $err; } - + + /** + * Pop an error off of the error stack, static method + * + * @param string package name + * @return boolean + * @since PEAR1.5.0a1 + */ + function staticPop($package) + { + if ($package) { + if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { + return false; + } + return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->pop(); + } + } + /** * Determine whether there are any errors on the stack * @param string|array Level name. Use to determine if any errors @@ -842,7 +857,7 @@ class PEAR_ErrorStack { 'line' => $filebacktrace['line']); // rearrange for eval'd code or create function errors if (strpos($filebacktrace['file'], '(') && - preg_match(';^(.*?)\((\d+)\) : (.*?)$;', $filebacktrace['file'], + preg_match(';^(.*?)\((\d+)\) : (.*?)\\z;', $filebacktrace['file'], $matches)) { $ret['file'] = $matches[1]; $ret['line'] = $matches[2] + 0; diff --git a/includes/pear/PEAR/Exception.php b/includes/pear/PEAR/Exception.php index e376b82e..b3d75b20 100644 --- a/includes/pear/PEAR/Exception.php +++ b/includes/pear/PEAR/Exception.php @@ -17,9 +17,9 @@ * @author Hans Lellelid * @author Bertrand Mansion * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Exception.php,v 1.22 2005/09/13 04:56:41 cellog Exp $ + * @version CVS: $Id: Exception.php,v 1.29 2008/01/03 20:26:35 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.3.3 */ @@ -93,9 +93,9 @@ * @author Hans Lellelid * @author Bertrand Mansion * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.3.3 * @@ -112,19 +112,31 @@ class PEAR_Exception extends Exception /** * Supported signatures: - * PEAR_Exception(string $message); - * PEAR_Exception(string $message, int $code); - * PEAR_Exception(string $message, Exception $cause); - * PEAR_Exception(string $message, Exception $cause, int $code); - * PEAR_Exception(string $message, array $causes); - * PEAR_Exception(string $message, array $causes, int $code); + * - PEAR_Exception(string $message); + * - PEAR_Exception(string $message, int $code); + * - PEAR_Exception(string $message, Exception $cause); + * - PEAR_Exception(string $message, Exception $cause, int $code); + * - PEAR_Exception(string $message, PEAR_Error $cause); + * - PEAR_Exception(string $message, PEAR_Error $cause, int $code); + * - PEAR_Exception(string $message, array $causes); + * - PEAR_Exception(string $message, array $causes, int $code); + * @param string exception message + * @param int|Exception|PEAR_Error|array|null exception cause + * @param int|null exception code or null */ public function __construct($message, $p2 = null, $p3 = null) { if (is_int($p2)) { $code = $p2; $this->cause = null; - } elseif ($p2 instanceof Exception || is_array($p2)) { + } elseif (is_object($p2) || is_array($p2)) { + // using is_object allows both Exception and PEAR_Error + if (is_object($p2) && !($p2 instanceof Exception)) { + if (!class_exists('PEAR_Error') || !($p2 instanceof PEAR_Error)) { + throw new PEAR_Exception('exception cause must be Exception, ' . + 'array, or PEAR_Error'); + } + } $code = $p3; if (is_array($p2) && isset($p2['message'])) { // fix potential problem of passing in a single warning @@ -242,11 +254,15 @@ class PEAR_Exception extends Exception if ($this->cause instanceof PEAR_Exception) { $this->cause->getCauseMessage($causes); } elseif ($this->cause instanceof Exception) { - $causes[] = array('class' => get_class($cause), - 'message' => $cause->getMessage(), - 'file' => $cause->getFile(), - 'line' => $cause->getLine()); - + $causes[] = array('class' => get_class($this->cause), + 'message' => $this->cause->getMessage(), + 'file' => $this->cause->getFile(), + 'line' => $this->cause->getLine()); + } elseif (class_exists('PEAR_Error') && $this->cause instanceof PEAR_Error) { + $causes[] = array('class' => get_class($this->cause), + 'message' => $this->cause->getMessage(), + 'file' => 'unknown', + 'line' => 'unknown'); } elseif (is_array($this->cause)) { foreach ($this->cause as $cause) { if ($cause instanceof PEAR_Exception) { @@ -256,6 +272,11 @@ class PEAR_Exception extends Exception 'message' => $cause->getMessage(), 'file' => $cause->getFile(), 'line' => $cause->getLine()); + } elseif (class_exists('PEAR_Error') && $cause instanceof PEAR_Error) { + $causes[] = array('class' => get_class($cause), + 'message' => $cause->getMessage(), + 'file' => 'unknown', + 'line' => 'unknown'); } elseif (is_array($cause) && isset($cause['message'])) { // PEAR_ErrorStack warning $causes[] = array( diff --git a/includes/pear/PEAR/FixPHP5PEARWarnings.php b/includes/pear/PEAR/FixPHP5PEARWarnings.php new file mode 100644 index 00000000..be5dc3ce --- /dev/null +++ b/includes/pear/PEAR/FixPHP5PEARWarnings.php @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/includes/pear/PEAR/Frontend.php b/includes/pear/PEAR/Frontend.php index f4554a80..bf7d4ba6 100644 --- a/includes/pear/PEAR/Frontend.php +++ b/includes/pear/PEAR/Frontend.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Frontend.php,v 1.4 2005/04/13 04:17:45 cellog Exp $ + * @version CVS: $Id: Frontend.php,v 1.13 2008/01/03 20:26:35 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -34,12 +34,13 @@ $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = null; /** * Singleton-based frontend for PEAR user input/output + * * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -64,6 +65,15 @@ class PEAR_Frontend extends PEAR } } + /** + * Set the frontend class that will be used by calls to {@link singleton()} + * + * Frontends are expected to conform to the PEAR naming standard of + * _ => DIRECTORY_SEPARATOR (PEAR_Frontend_CLI is in PEAR/Frontend/CLI.php) + * @param string $uiclass full class name + * @return PEAR_Frontend + * @static + */ function &setFrontendClass($uiclass) { if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) && @@ -80,7 +90,7 @@ class PEAR_Frontend extends PEAR $obj = &new $uiclass; // quick test to see if this class implements a few of the most // important frontend methods - if (method_exists($obj, 'userConfirm')) { + if (is_a($obj, 'PEAR_Frontend')) { $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = &$obj; $GLOBALS['_PEAR_FRONTEND_CLASS'] = $uiclass; return $obj; @@ -93,6 +103,30 @@ class PEAR_Frontend extends PEAR return $err; } + /** + * Set the frontend class that will be used by calls to {@link singleton()} + * + * Frontends are expected to be a descendant of PEAR_Frontend + * @param PEAR_Frontend + * @return PEAR_Frontend + * @static + */ + function &setFrontendObject($uiobject) + { + if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) && + is_a($GLOBALS['_PEAR_FRONTEND_SINGLETON'], get_class($uiobject))) { + return $GLOBALS['_PEAR_FRONTEND_SINGLETON']; + } + if (!is_a($uiobject, 'PEAR_Frontend')) { + $err = PEAR::raiseError('not a valid frontend class: (' . + get_class($uiobject) . ')'); + return $err; + } + $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = &$uiobject; + $GLOBALS['_PEAR_FRONTEND_CLASS'] = get_class($uiobject); + return $uiobject; + } + /** * @param string $path relative or absolute include path * @return boolean @@ -103,15 +137,10 @@ class PEAR_Frontend extends PEAR if (file_exists($path) && is_readable($path)) { return true; } - $ipath = explode(PATH_SEPARATOR, ini_get('include_path')); - foreach ($ipath as $include) { - $test = realpath($include . DIRECTORY_SEPARATOR . $path); - if (!$test) { // support wrappers like phar (realpath just don't work with them) - $test = $include . DIRECTORY_SEPARATOR . $path; - } - if (file_exists($test) && is_readable($test)) { - return true; - } + $fp = @fopen($path, 'r', true); + if ($fp) { + fclose($fp); + return true; } return false; } @@ -135,7 +164,59 @@ class PEAR_Frontend extends PEAR $GLOBALS['_PEAR_Common_tempfiles'][] = $file; } - function log($level, $msg, $append_crlf = true) + /** + * Log an action + * + * @param string $msg the message to log + * @param boolean $append_crlf + * @return boolean true + * @abstract + */ + function log($msg, $append_crlf = true) + { + } + + /** + * Run a post-installation script + * + * @param array $scripts array of post-install scripts + * @abstract + */ + function runPostinstallScripts(&$scripts) + { + } + + /** + * Display human-friendly output formatted depending on the + * $command parameter. + * + * This should be able to handle basic output data with no command + * @param mixed $data data structure containing the information to display + * @param string $command command from which this method was called + * @abstract + */ + function outputData($data, $command = '_default') + { + } + + /** + * Display a modal form dialog and return the given input + * + * A frontend that requires multiple requests to retrieve and process + * data must take these needs into account, and implement the request + * handling code. + * @param string $command command from which this method was called + * @param array $prompts associative array. keys are the input field names + * and values are the description + * @param array $types array of input field types (text, password, + * etc.) keys have to be the same like in $prompts + * @param array $defaults array of default values. again keys have + * to be the same like in $prompts. Do not depend + * on a default value being set. + * @return array input sent by the user + * @abstract + */ + function userDialog($command, $prompts, $types = array(), $defaults = array()) { } } diff --git a/includes/pear/PEAR/Frontend/CLI.php b/includes/pear/PEAR/Frontend/CLI.php index 240afe8a..0655aba1 100644 --- a/includes/pear/PEAR/Frontend/CLI.php +++ b/includes/pear/PEAR/Frontend/CLI.php @@ -14,9 +14,9 @@ * @package PEAR * @author Stig Bakken * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: CLI.php,v 1.56 2005/10/19 04:11:26 cellog Exp $ + * @version CVS: $Id: CLI.php,v 1.68 2008/01/03 20:26:36 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ @@ -31,9 +31,9 @@ require_once 'PEAR/Frontend.php'; * @package PEAR * @author Stig Bakken * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ @@ -143,7 +143,19 @@ class PEAR_Frontend_CLI extends PEAR_Frontend continue; } } - @$this->_displayLine("#$i: $frame[class]$frame[type]$frame[function] $frame[line]"); + if (!isset($frame['class'])) { + $frame['class'] = ''; + } + if (!isset($frame['type'])) { + $frame['type'] = ''; + } + if (!isset($frame['function'])) { + $frame['function'] = ''; + } + if (!isset($frame['line'])) { + $frame['line'] = ''; + } + $this->_displayLine("#$i: $frame[class]$frame[type]$frame[function] $frame[line]"); } } } @@ -309,50 +321,43 @@ class PEAR_Frontend_CLI extends PEAR_Frontend $answers[$param['name']] = ''; } } + $tried = false; do { - $ok = array('yesno' => 'no'); - do { - $answers = $this->userDialog('', $prompts, $types, $answers); - } while (count(array_filter($answers)) != count($prompts)); - $this->outputData('Your choices:'); - foreach ($prompts as $name => $prompt) { - $this->outputData($prompt . ': ' . $answers[$name]); + if ($tried) { + $i = 1; + foreach ($answers as $var => $value) { + if (!strlen($value)) { + echo $this->bold("* Enter an answer for #" . $i . ": ({$prompts[$var]})\n"); + } + $i++; + } } - $ok = $this->userDialog('', - array( - 'yesno' => 'These Choices OK? (use "abort" to halt)' - ), - array( - 'yesno' => 'string', - ), - array( - 'yesno' => 'yes' - ) - ); - if ($ok['yesno'] == 'abort') { - return false; - } - } while ($ok['yesno'] != 'yes'); + $answers = $this->userDialog('', $prompts, $types, $answers); + $tried = true; + } while (is_array($answers) && count(array_filter($answers)) != count($prompts)); return $answers; } // {{{ userDialog(prompt, [type], [default]) - function userDialog($command, $prompts, $types = array(), $defaults = array()) + function userDialog($command, $prompts, $types = array(), $defaults = array(), + $screensize = 20) { - $result = array(); - if (is_array($prompts)) { - // php 5.0.0 inexplicably breaks BC with this behavior - // now reading from STDIN is the intended syntax - if (version_compare(phpversion(), '5.0.0', '<')) { - $fp = fopen("php://stdin", "r"); - } + if (!is_array($prompts)) { + return array(); + } + $testprompts = array_keys($prompts); + $result = $defaults; + if (!defined('STDIN')) { + $fp = fopen('php://stdin', 'r'); + } else { + $fp = STDIN; + } + reset($prompts); + if (count($prompts) == 1 && $types[key($prompts)] == 'yesno') { foreach ($prompts as $key => $prompt) { $type = $types[$key]; $default = @$defaults[$key]; - if ($type == 'password') { - system('stty -echo'); - } - print "$this->lp$prompt "; + print "$prompt "; if ($default) { print "[$default] "; } @@ -365,19 +370,55 @@ class PEAR_Frontend_CLI extends PEAR_Frontend } $line = fgets(STDIN, 2048); } - if ($type == 'password') { - system('stty echo'); - print "\n"; - } if ($default && trim($line) == "") { $result[$key] = $default; } else { $result[$key] = trim($line); } } - if (version_compare(phpversion(), '5.0.0', '<')) { - fclose($fp); + return $result; + } + while (true) { + $descLength = max(array_map('strlen', $prompts)); + $descFormat = "%-{$descLength}s"; + $last = count($prompts); + + $i = 0; + foreach ($prompts as $n => $var) { + printf("%2d. $descFormat : %s\n", ++$i, $prompts[$n], isset($result[$n]) ? + $result[$n] : null); } + + print "\n1-$last, 'all', 'abort', or Enter to continue: "; + $tmp = trim(fgets($fp, 1024)); + if (empty($tmp)) { + break; + } + if ($tmp == 'abort') { + return false; + } + if (isset($testprompts[(int)$tmp - 1])) { + $var = $testprompts[(int)$tmp - 1]; + $desc = $prompts[$var]; + $current = @$result[$var]; + print "$desc [$current] : "; + $tmp = trim(fgets($fp, 1024)); + if (trim($tmp) !== '') { + $result[$var] = trim($tmp); + } + } elseif ($tmp == 'all') { + foreach ($prompts as $var => $desc) { + $current = $result[$var]; + print "$desc [$current] : "; + $tmp = trim(fgets($fp, 1024)); + if (trim($tmp) !== '') { + $result[$var] = trim($tmp); + } + } + } + } + if (!defined('STDIN')) { + fclose($fp); } return $result; } @@ -455,12 +496,17 @@ class PEAR_Frontend_CLI extends PEAR_Frontend } else { $w = strlen($col); } - if ($w > @$this->params['widest'][$i]) { + + if (isset($this->params['widest'][$i])) { + if ($w > $this->params['widest'][$i]) { + $this->params['widest'][$i] = $w; + } + } else { $this->params['widest'][$i] = $w; } $tmp = count_chars($columns[$i], 1); // handle unix, mac and windows formats - $lines = (isset($tmp[10]) ? $tmp[10] : @$tmp[13]) + 1; + $lines = (isset($tmp[10]) ? $tmp[10] : (isset($tmp[13]) ? $tmp[13] : 0)) + 1; if ($lines > $highest) { $highest = $lines; } @@ -626,6 +672,10 @@ class PEAR_Frontend_CLI extends PEAR_Frontend $this->_endTable(); break; case 'list-all': + if (!isset($data['data'])) { + $this->_displayLine('No packages in channel'); + break; + } $this->_startTable($data); if (isset($data['headline']) && is_array($data['headline'])) { $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55))); @@ -662,6 +712,7 @@ class PEAR_Frontend_CLI extends PEAR_Frontend $this->_endTable(); break; case 'remote-info': + $d = $data; $data = array( 'caption' => 'Package details:', 'border' => false, @@ -675,6 +726,12 @@ class PEAR_Frontend_CLI extends PEAR_Frontend array("Description", $data['description']), ), ); + if (isset($d['deprecated']) && $d['deprecated']) { + $conf = &PEAR_Config::singleton(); + $reg = $conf->getRegistry(); + $name = $reg->parsedPackageNameToString($d['deprecated'], true); + $data['data'][] = array('Deprecated! use', $name); + } default: { if (is_array($data)) { $this->_startTable($data); diff --git a/includes/pear/PEAR/Installer.php b/includes/pear/PEAR/Installer.php index a92046a4..d3f31621 100644 --- a/includes/pear/PEAR/Installer.php +++ b/includes/pear/PEAR/Installer.php @@ -16,9 +16,9 @@ * @author Tomas V.V. Cox * @author Martin Jansen * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Installer.php,v 1.222 2005/11/12 06:42:33 cellog Exp $ + * @version CVS: $Id: Installer.php,v 1.253 2008/05/13 22:46:07 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ @@ -40,9 +40,9 @@ define('PEAR_INSTALLER_NOBINARY', -240); * @author Tomas V.V. Cox * @author Martin Jansen * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ @@ -239,6 +239,10 @@ class PEAR_Installer extends PEAR_Downloader $channel = $this->pkginfo->getChannel(); // {{{ assemble the destination paths switch ($atts['role']) { + case 'src': + case 'extsrc': + $this->source_files++; + return; case 'doc': case 'data': case 'test': @@ -253,10 +257,6 @@ class PEAR_Installer extends PEAR_Downloader case 'script': $dest_dir = $this->config->get('bin_dir', null, $channel); break; - case 'src': - case 'extsrc': - $this->source_files++; - return; default: return $this->raiseError("Invalid role `$atts[role]' for file $file"); } @@ -282,154 +282,181 @@ class PEAR_Installer extends PEAR_Downloader DIRECTORY_SEPARATOR), array($dest_file, $orig_file)); $final_dest_file = $installed_as = $dest_file; + if (isset($this->_options['packagingroot'])) { + $installedas_dest_dir = dirname($final_dest_file); + $installedas_dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file); + $final_dest_file = $this->_prependPath($final_dest_file, + $this->_options['packagingroot']); + } else { + $installedas_dest_dir = dirname($final_dest_file); + $installedas_dest_file = $installedas_dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file); + } $dest_dir = dirname($final_dest_file); $dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file); + if (preg_match('~/\.\.(/|\\z)|^\.\./~', str_replace('\\', '/', $dest_file))) { + return $this->raiseError("SECURITY ERROR: file $file (installed to $dest_file) contains parent directory reference ..", PEAR_INSTALLER_FAILED); + } // }}} - if (!@is_dir($dest_dir)) { + if (empty($this->_options['register-only']) && + (!file_exists($dest_dir) || !is_dir($dest_dir))) { if (!$this->mkDirHier($dest_dir)) { return $this->raiseError("failed to mkdir $dest_dir", PEAR_INSTALLER_FAILED); } $this->log(3, "+ mkdir $dest_dir"); } - if (empty($atts['replacements'])) { - if (!file_exists($orig_file)) { - return $this->raiseError("file $orig_file does not exist", - PEAR_INSTALLER_FAILED); - } - if (!@copy($orig_file, $dest_file)) { - return $this->raiseError("failed to write $dest_file", - PEAR_INSTALLER_FAILED); - } - $this->log(3, "+ cp $orig_file $dest_file"); - if (isset($atts['md5sum'])) { - $md5sum = md5_file($dest_file); - } - } else { - // {{{ file with replacements - if (!file_exists($orig_file)) { - return $this->raiseError("file does not exist", - PEAR_INSTALLER_FAILED); - } - if (function_exists('file_get_contents')) { - $contents = file_get_contents($orig_file); + // pretty much nothing happens if we are only registering the install + if (empty($this->_options['register-only'])) { + if (empty($atts['replacements'])) { + if (!file_exists($orig_file)) { + return $this->raiseError("file $orig_file does not exist", + PEAR_INSTALLER_FAILED); + } + if (!@copy($orig_file, $dest_file)) { + return $this->raiseError("failed to write $dest_file: $php_errormsg", + PEAR_INSTALLER_FAILED); + } + $this->log(3, "+ cp $orig_file $dest_file"); + if (isset($atts['md5sum'])) { + $md5sum = md5_file($dest_file); + } } else { - $fp = fopen($orig_file, "r"); - $contents = @fread($fp, filesize($orig_file)); - fclose($fp); - } - if ($contents === false) { - $contents = ''; - } - if (isset($atts['md5sum'])) { - $md5sum = md5($contents); - } - $subst_from = $subst_to = array(); - foreach ($atts['replacements'] as $a) { - $to = ''; - if ($a['type'] == 'php-const') { - if (preg_match('/^[a-z0-9_]+$/i', $a['to'])) { - eval("\$to = $a[to];"); - } else { - if (!isset($options['soft'])) { - $this->log(0, "invalid php-const replacement: $a[to]"); + // {{{ file with replacements + if (!file_exists($orig_file)) { + return $this->raiseError("file does not exist", + PEAR_INSTALLER_FAILED); + } + $contents = file_get_contents($orig_file); + if ($contents === false) { + $contents = ''; + } + if (isset($atts['md5sum'])) { + $md5sum = md5($contents); + } + $subst_from = $subst_to = array(); + foreach ($atts['replacements'] as $a) { + $to = ''; + if ($a['type'] == 'php-const') { + if (preg_match('/^[a-z0-9_]+\\z/i', $a['to'])) { + eval("\$to = $a[to];"); + } else { + if (!isset($options['soft'])) { + $this->log(0, "invalid php-const replacement: $a[to]"); + } + continue; } - continue; - } - } elseif ($a['type'] == 'pear-config') { - if ($a['to'] == 'master_server') { - $chan = $this->_registry->getChannel($channel); - if ($chan) { - $to = $chan->getServer(); + } elseif ($a['type'] == 'pear-config') { + if ($a['to'] == 'master_server') { + $chan = $this->_registry->getChannel($channel); + if (!PEAR::isError($chan)) { + $to = $chan->getServer(); + } else { + $to = $this->config->get($a['to'], null, $channel); + } } else { $to = $this->config->get($a['to'], null, $channel); } - } else { - $to = $this->config->get($a['to'], null, $channel); - } - if (is_null($to)) { - if (!isset($options['soft'])) { - $this->log(0, "invalid pear-config replacement: $a[to]"); + if (is_null($to)) { + if (!isset($options['soft'])) { + $this->log(0, "invalid pear-config replacement: $a[to]"); + } + continue; } - continue; - } - } elseif ($a['type'] == 'package-info') { - if ($t = $this->pkginfo->packageInfo($a['to'])) { - $to = $t; - } else { - if (!isset($options['soft'])) { - $this->log(0, "invalid package-info replacement: $a[to]"); + } elseif ($a['type'] == 'package-info') { + if ($t = $this->pkginfo->packageInfo($a['to'])) { + $to = $t; + } else { + if (!isset($options['soft'])) { + $this->log(0, "invalid package-info replacement: $a[to]"); + } + continue; } - continue; + } + if (!is_null($to)) { + $subst_from[] = $a['from']; + $subst_to[] = $to; } } - if (!is_null($to)) { - $subst_from[] = $a['from']; - $subst_to[] = $to; + $this->log(3, "doing ".sizeof($subst_from)." substitution(s) for $final_dest_file"); + if (sizeof($subst_from)) { + $contents = str_replace($subst_from, $subst_to, $contents); } - } - $this->log(3, "doing ".sizeof($subst_from)." substitution(s) for $final_dest_file"); - if (sizeof($subst_from)) { - $contents = str_replace($subst_from, $subst_to, $contents); - } - $wp = @fopen($dest_file, "wb"); - if (!is_resource($wp)) { - return $this->raiseError("failed to create $dest_file: $php_errormsg", - PEAR_INSTALLER_FAILED); - } - if (fwrite($wp, $contents) === false) { - return $this->raiseError("failed writing to $dest_file: $php_errormsg", - PEAR_INSTALLER_FAILED); - } - fclose($wp); - // }}} - } - // {{{ check the md5 - if (isset($md5sum)) { - if (strtolower($md5sum) == strtolower($atts['md5sum'])) { - $this->log(2, "md5sum ok: $final_dest_file"); - } else { - if (empty($options['force'])) { - // delete the file - @unlink($dest_file); - if (!isset($options['ignore-errors'])) { - return $this->raiseError("bad md5sum for file $final_dest_file", + $wp = @fopen($dest_file, "wb"); + if (!is_resource($wp)) { + return $this->raiseError("failed to create $dest_file: $php_errormsg", PEAR_INSTALLER_FAILED); + } + if (@fwrite($wp, $contents) === false) { + return $this->raiseError("failed writing to $dest_file: $php_errormsg", + PEAR_INSTALLER_FAILED); + } + fclose($wp); + // }}} + } + // {{{ check the md5 + if (isset($md5sum)) { + if (strtolower($md5sum) === strtolower($atts['md5sum'])) { + $this->log(2, "md5sum ok: $final_dest_file"); + } else { + if (empty($options['force'])) { + // delete the file + if (file_exists($dest_file)) { + unlink($dest_file); + } + if (!isset($options['ignore-errors'])) { + return $this->raiseError("bad md5sum for file $final_dest_file", + PEAR_INSTALLER_FAILED); + } else { + if (!isset($options['soft'])) { + $this->log(0, "warning : bad md5sum for file $final_dest_file"); + } + } } else { if (!isset($options['soft'])) { $this->log(0, "warning : bad md5sum for file $final_dest_file"); } } + } + } + // }}} + // {{{ set file permissions + if (!OS_WINDOWS) { + if ($atts['role'] == 'script') { + $mode = 0777 & ~(int)octdec($this->config->get('umask')); + $this->log(3, "+ chmod +x $dest_file"); } else { - if (!isset($options['soft'])) { - $this->log(0, "warning : bad md5sum for file $final_dest_file"); + $mode = 0666 & ~(int)octdec($this->config->get('umask')); + } + if ($atts['role'] != 'src') { + $this->addFileOperation("chmod", array($mode, $dest_file)); + if (!@chmod($dest_file, $mode)) { + if (!isset($options['soft'])) { + $this->log(0, "failed to change mode of $dest_file: $php_errormsg"); + } } } } - } - // }}} - // {{{ set file permissions - if (!OS_WINDOWS) { - if ($atts['role'] == 'script') { - $mode = 0777 & ~(int)octdec($this->config->get('umask')); - $this->log(3, "+ chmod +x $dest_file"); + // }}} + if ($atts['role'] == 'src') { + rename($dest_file, $final_dest_file); + $this->log(2, "renamed source file $dest_file to $final_dest_file"); } else { - $mode = 0666 & ~(int)octdec($this->config->get('umask')); - } - $this->addFileOperation("chmod", array($mode, $dest_file)); - if (!@chmod($dest_file, $mode)) { - if (!isset($options['soft'])) { - $this->log(0, "failed to change mode of $dest_file"); - } + $this->addFileOperation("rename", array($dest_file, $final_dest_file, + $atts['role'] == 'ext')); } } - // }}} - $this->addFileOperation("rename", array($dest_file, $final_dest_file, - $atts['role'] == 'ext')); // Store the full path where the file was installed for easy unistall - $this->addFileOperation("installed_as", array($file, $installed_as, - $save_destdir, dirname(substr($dest_file, strlen($save_destdir))))); + if ($atts['role'] != 'script') { + $loc = $this->config->get($atts['role'] . '_dir'); + } else { + $loc = $this->config->get('bin_dir'); + } + if ($atts['role'] != 'src') { + $this->addFileOperation("installed_as", array($file, $installed_as, + $loc, + dirname(substr($installedas_dest_file, strlen($loc))))); + } //$this->log(2, "installed: $dest_file"); return PEAR_INSTALLER_OK; @@ -446,8 +473,9 @@ class PEAR_Installer extends PEAR_Downloader * @param array options from command-line * @access private */ - function _installFile2(&$pkg, $file, $atts, $tmp_path, $options) + function _installFile2(&$pkg, $file, &$real_atts, $tmp_path, $options) { + $atts = $real_atts; if (!isset($this->_registry)) { $this->_registry = &$this->config->getRegistry(); } @@ -473,122 +501,144 @@ class PEAR_Installer extends PEAR_Downloader } else { list($save_destdir, $dest_dir, $dest_file, $orig_file) = $info; } + if (preg_match('~/\.\.(/|\\z)|^\.\./~', str_replace('\\', '/', $dest_file))) { + return $this->raiseError("SECURITY ERROR: file $file (installed to $dest_file) contains parent directory reference ..", PEAR_INSTALLER_FAILED); + } $final_dest_file = $installed_as = $dest_file; + if (isset($this->_options['packagingroot'])) { + $final_dest_file = $this->_prependPath($final_dest_file, + $this->_options['packagingroot']); + } $dest_dir = dirname($final_dest_file); $dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file); // }}} - if (!@is_dir($dest_dir)) { - if (!$this->mkDirHier($dest_dir)) { - return $this->raiseError("failed to mkdir $dest_dir", - PEAR_INSTALLER_FAILED); + if (empty($this->_options['register-only'])) { + if (!file_exists($dest_dir) || !is_dir($dest_dir)) { + if (!$this->mkDirHier($dest_dir)) { + return $this->raiseError("failed to mkdir $dest_dir", + PEAR_INSTALLER_FAILED); + } + $this->log(3, "+ mkdir $dest_dir"); } - $this->log(3, "+ mkdir $dest_dir"); } $attribs = $atts['attribs']; unset($atts['attribs']); - if (!count($atts)) { // no tasks - if (!file_exists($orig_file)) { - return $this->raiseError("file $orig_file does not exist", - PEAR_INSTALLER_FAILED); - } - if (!@copy($orig_file, $dest_file)) { - return $this->raiseError("failed to write $dest_file", - PEAR_INSTALLER_FAILED); - } - $this->log(3, "+ cp $orig_file $dest_file"); - if (isset($attribs['md5sum'])) { - $md5sum = md5_file($dest_file); - } - } else { // file with tasks - if (!file_exists($orig_file)) { - return $this->raiseError("file $orig_file does not exist", - PEAR_INSTALLER_FAILED); - } - if (function_exists('file_get_contents')) { + // pretty much nothing happens if we are only registering the install + if (empty($this->_options['register-only'])) { + if (!count($atts)) { // no tasks + if (!file_exists($orig_file)) { + return $this->raiseError("file $orig_file does not exist", + PEAR_INSTALLER_FAILED); + } + if (!@copy($orig_file, $dest_file)) { + return $this->raiseError("failed to write $dest_file: $php_errormsg", + PEAR_INSTALLER_FAILED); + } + $this->log(3, "+ cp $orig_file $dest_file"); + if (isset($attribs['md5sum'])) { + $md5sum = md5_file($dest_file); + } + } else { // file with tasks + if (!file_exists($orig_file)) { + return $this->raiseError("file $orig_file does not exist", + PEAR_INSTALLER_FAILED); + } $contents = file_get_contents($orig_file); - } else { - $fp = fopen($orig_file, "r"); - $contents = @fread($fp, filesize($orig_file)); // filesize can be 0 - fclose($fp); - } - if ($contents === false) { - $contents = ''; - } - if (isset($attribs['md5sum'])) { - $md5sum = md5($contents); - } - foreach ($atts as $tag => $raw) { - $tag = str_replace($pkg->getTasksNs() . ':', '', $tag); - $task = "PEAR_Task_$tag"; - $task = &new $task($this->config, $this, PEAR_TASK_INSTALL); - if (!$task->isScript()) { // scripts are only handled after installation - $task->init($raw, $attribs, $pkg->getLastInstalledVersion()); - $res = $task->startSession($pkg, $contents, $final_dest_file); - if ($res === false) { - continue; // skip this file + if ($contents === false) { + $contents = ''; + } + if (isset($attribs['md5sum'])) { + $md5sum = md5($contents); + } + foreach ($atts as $tag => $raw) { + $tag = str_replace(array($pkg->getTasksNs() . ':', '-'), + array('', '_'), $tag); + $task = "PEAR_Task_$tag"; + $task = &new $task($this->config, $this, PEAR_TASK_INSTALL); + if (!$task->isScript()) { // scripts are only handled after installation + $task->init($raw, $attribs, $pkg->getLastInstalledVersion()); + $res = $task->startSession($pkg, $contents, $final_dest_file); + if ($res === false) { + continue; // skip this file + } + if (PEAR::isError($res)) { + return $res; + } + $contents = $res; // save changes } - if (PEAR::isError($res)) { - return $res; - } - $contents = $res; // save changes - } - $wp = @fopen($dest_file, "wb"); - if (!is_resource($wp)) { - return $this->raiseError("failed to create $dest_file: $php_errormsg", - PEAR_INSTALLER_FAILED); - } - if (fwrite($wp, $contents) === false) { - return $this->raiseError("failed writing to $dest_file: $php_errormsg", - PEAR_INSTALLER_FAILED); - } - fclose($wp); - } - } - // {{{ check the md5 - if (isset($md5sum)) { - if (strtolower($md5sum) == strtolower($attribs['md5sum'])) { - $this->log(2, "md5sum ok: $final_dest_file"); - } else { - if (empty($options['force'])) { - // delete the file - @unlink($dest_file); - if (!isset($options['ignore-errors'])) { - return $this->raiseError("bad md5sum for file $final_dest_file", + $wp = @fopen($dest_file, "wb"); + if (!is_resource($wp)) { + return $this->raiseError("failed to create $dest_file: $php_errormsg", PEAR_INSTALLER_FAILED); + } + if (fwrite($wp, $contents) === false) { + return $this->raiseError("failed writing to $dest_file: $php_errormsg", + PEAR_INSTALLER_FAILED); + } + fclose($wp); + } + } + // {{{ check the md5 + if (isset($md5sum)) { + if (strtolower($md5sum) === strtolower($attribs['md5sum'])) { + $this->log(2, "md5sum ok: $final_dest_file"); + } else { + if (empty($options['force'])) { + // delete the file + if (file_exists($dest_file)) { + unlink($dest_file); + } + if (!isset($options['ignore-errors'])) { + return $this->raiseError("bad md5sum for file $final_dest_file", + PEAR_INSTALLER_FAILED); + } else { + if (!isset($options['soft'])) { + $this->log(0, "warning : bad md5sum for file $final_dest_file"); + } + } } else { if (!isset($options['soft'])) { $this->log(0, "warning : bad md5sum for file $final_dest_file"); } } + } + } else { + $real_atts['attribs']['md5sum'] = md5_file($dest_file); + } + // }}} + // {{{ set file permissions + if (!OS_WINDOWS) { + if ($role->isExecutable()) { + $mode = 0777 & ~(int)octdec($this->config->get('umask')); + $this->log(3, "+ chmod +x $dest_file"); } else { - if (!isset($options['soft'])) { - $this->log(0, "warning : bad md5sum for file $final_dest_file"); + $mode = 0666 & ~(int)octdec($this->config->get('umask')); + } + if ($attribs['role'] != 'src') { + $this->addFileOperation("chmod", array($mode, $dest_file)); + if (!@chmod($dest_file, $mode)) { + if (!isset($options['soft'])) { + $this->log(0, "failed to change mode of $dest_file: $php_errormsg"); + } } } } - } - // }}} - // {{{ set file permissions - if (!OS_WINDOWS) { - if ($role->isExecutable()) { - $mode = 0777 & ~(int)octdec($this->config->get('umask')); - $this->log(3, "+ chmod +x $dest_file"); + // }}} + if ($attribs['role'] == 'src') { + rename($dest_file, $final_dest_file); + $this->log(2, "renamed source file $dest_file to $final_dest_file"); } else { - $mode = 0666 & ~(int)octdec($this->config->get('umask')); - } - $this->addFileOperation("chmod", array($mode, $dest_file)); - if (!@chmod($dest_file, $mode)) { - if (!isset($options['soft'])) { - $this->log(0, "failed to change mode of $dest_file"); - } + $this->addFileOperation("rename", array($dest_file, $final_dest_file, $role->isExtension())); } } - // }}} - $this->addFileOperation("rename", array($dest_file, $final_dest_file, $role->isExtension())); // Store the full path where the file was installed for easy uninstall - $this->addFileOperation("installed_as", array($file, $installed_as, - $save_destdir, dirname(substr($dest_file, strlen($save_destdir))))); + if ($attribs['role'] != 'src') { + $loc = $this->config->get($role->getLocationConfig(), null, $channel); + $this->addFileOperation("installed_as", array($file, $installed_as, + $loc, + dirname(substr($installed_as, strlen($loc))))); + } //$this->log(2, "installed: $dest_file"); return PEAR_INSTALLER_OK; @@ -685,7 +735,8 @@ class PEAR_Installer extends PEAR_Downloader } else { // make sure the file to be deleted can be opened for writing $fp = false; - if (!is_dir($data[0]) && !($fp = @fopen($data[0], 'a'))) { + if (!is_dir($data[0]) && + (!is_writable($data[0]) || !($fp = @fopen($data[0], 'a')))) { $errors[] = "permission denied ($type): $data[0]"; } elseif ($fp) { fclose($fp); @@ -710,19 +761,37 @@ class PEAR_Installer extends PEAR_Downloader } $this->_dirtree = array(); // {{{ really commit the transaction - foreach ($this->file_operations as $tr) { + foreach ($this->file_operations as $i => $tr) { + if (!$tr) { + // support removal of non-existing backups + continue; + } list($type, $data) = $tr; switch ($type) { case 'backup': - @copy($data[0], $data[0] . '.bak'); + if (!file_exists($data[0])) { + $this->file_operations[$i] = false; + break; + } + if (!@copy($data[0], $data[0] . '.bak')) { + $this->log(1, 'Could not copy ' . $data[0] . ' to ' . $data[0] . + '.bak ' . $php_errormsg); + return false; + } $this->log(3, "+ backup $data[0] to $data[0].bak"); break; case 'removebackup': - @unlink($data[0] . '.bak'); - $this->log(3, "+ rm backup of $data[0] ($data[0].bak)"); + if (file_exists($data[0] . '.bak') && is_writable($data[0] . '.bak')) { + unlink($data[0] . '.bak'); + $this->log(3, "+ rm backup of $data[0] ($data[0].bak)"); + } break; case 'rename': - $test = @unlink($data[1]); + if (file_exists($data[1])) { + $test = @unlink($data[1]); + } else { + $test = null; + } if (!$test && file_exists($data[1])) { if ($data[2]) { $extra = ', this extension must be installed manually. Rename to "' . @@ -738,21 +807,58 @@ class PEAR_Installer extends PEAR_Downloader return false; } } - @rename($data[0], $data[1]); + // permissions issues with rename - copy() is far superior + $perms = @fileperms($data[0]); + if (!@copy($data[0], $data[1])) { + $this->log(1, 'Could not rename ' . $data[0] . ' to ' . $data[1] . + ' ' . $php_errormsg); + return false; + } + // copy over permissions, otherwise they are lost + @chmod($data[1], $perms); + @unlink($data[0]); $this->log(3, "+ mv $data[0] $data[1]"); break; case 'chmod': - @chmod($data[1], $data[0]); + if (!@chmod($data[1], $data[0])) { + $this->log(1, 'Could not chmod ' . $data[1] . ' to ' . + decoct($data[0]) . ' ' . $php_errormsg); + return false; + } $octmode = decoct($data[0]); $this->log(3, "+ chmod $octmode $data[1]"); break; case 'delete': - @unlink($data[0]); - $this->log(3, "+ rm $data[0]"); + if (file_exists($data[0])) { + if (!@unlink($data[0])) { + $this->log(1, 'Could not delete ' . $data[0] . ' ' . + $php_errormsg); + return false; + } + $this->log(3, "+ rm $data[0]"); + } break; case 'rmdir': - @rmdir($data[0]); - $this->log(3, "+ rmdir $data[0]"); + if (file_exists($data[0])) { + do { + $testme = opendir($data[0]); + while (false !== ($entry = readdir($testme))) { + if ($entry == '.' || $entry == '..') { + continue; + } + closedir($testme); + break 2; // this directory is not empty and can't be + // deleted + } + closedir($testme); + if (!@rmdir($data[0])) { + $this->log(1, 'Could not rmdir ' . $data[0] . ' ' . + $php_errormsg); + return false; + } + $this->log(3, "+ rmdir $data[0]"); + } while (false); + } break; case 'installed_as': $this->pkginfo->setInstalledAs($data[0], $data[1]); @@ -760,8 +866,8 @@ class PEAR_Installer extends PEAR_Downloader $this->_dirtree[dirname($data[1])] = true; $this->pkginfo->setDirtree(dirname($data[1])); - while(!empty($data[3]) && $data[3] != '/' && $data[3] != '\\' - && $data[3] != '.') { + while(!empty($data[3]) && dirname($data[3]) != $data[3] && + $data[3] != '/' && $data[3] != '\\') { $this->pkginfo->setDirtree($pp = $this->_prependPath($data[3], $data[2])); $this->_dirtree[$pp] = true; @@ -789,11 +895,19 @@ class PEAR_Installer extends PEAR_Downloader switch ($type) { case 'backup': if (file_exists($data[0] . '.bak')) { - @unlink($data[0]); + if (file_exists($data[0] && is_writable($data[0]))) { + unlink($data[0]); + } @copy($data[0] . '.bak', $data[0]); $this->log(3, "+ restore $data[0] from $data[0].bak"); } break; + case 'removebackup': + if (file_exists($data[0] . '.bak') && is_writable($data[0] . '.bak')) { + unlink($data[0] . '.bak'); + $this->log(3, "+ rm backup of $data[0] ($data[0].bak)"); + } + break; case 'rename': @unlink($data[0]); $this->log(3, "+ rm $data[0]"); @@ -973,33 +1087,58 @@ class PEAR_Installer extends PEAR_Downloader if (realpath($descfile) != realpath($pkgfile)) { $tar = new Archive_Tar($pkgfile); - if (!@$tar->extract($tmpdir)) { + if (!$tar->extract($tmpdir)) { return $this->raiseError("unable to unpack $pkgfile"); } } $pkgname = $pkg->getName(); $channel = $pkg->getChannel(); + if (isset($this->_options['packagingroot'])) { + $regdir = $this->_prependPath( + $this->config->get('php_dir', null, 'pear.php.net'), + $this->_options['packagingroot']); + $packrootphp_dir = $this->_prependPath( + $this->config->get('php_dir', null, $channel), + $this->_options['packagingroot']); + } if (isset($options['installroot'])) { $this->config->setInstallRoot($options['installroot']); $this->_registry = &$this->config->getRegistry(); + $installregistry = &$this->_registry; $this->installroot = ''; // all done automagically now + $php_dir = $this->config->get('php_dir', null, $channel); } else { $this->config->setInstallRoot(false); $this->_registry = &$this->config->getRegistry(); + if (isset($this->_options['packagingroot'])) { + $installregistry = &new PEAR_Registry($regdir); + if (!$installregistry->channelExists($channel, true)) { + // we need to fake a channel-discover of this channel + $chanobj = $this->_registry->getChannel($channel, true); + $installregistry->addChannel($chanobj); + } + $php_dir = $packrootphp_dir; + } else { + $installregistry = &$this->_registry; + $php_dir = $this->config->get('php_dir', null, $channel); + } $this->installroot = ''; } - $php_dir = $this->config->get('php_dir', null, $channel); // {{{ checks to do when not in "force" mode - if (empty($options['force']) && @is_dir($this->config->get('php_dir'))) { + if (empty($options['force']) && + (file_exists($this->config->get('php_dir')) && + is_dir($this->config->get('php_dir')))) { $testp = $channel == 'pear.php.net' ? $pkgname : array($channel, $pkgname); $instfilelist = $pkg->getInstallationFileList(true); if (PEAR::isError($instfilelist)) { return $instfilelist; } - $test = $this->_registry->checkFileMap($instfilelist, $testp, '1.1'); + // ensure we have the most accurate registry + $installregistry->flushFileMap(); + $test = $installregistry->checkFileMap($instfilelist, $testp, '1.1'); if (PEAR::isError($test)) { return $test; } @@ -1014,7 +1153,7 @@ class PEAR_Installer extends PEAR_Downloader } if ($found) { // subpackages can conflict with earlier versions of parent packages - $parentreg = $this->_registry->packageInfo($param->getPackage(), null, $param->getChannel()); + $parentreg = $installregistry->packageInfo($param->getPackage(), null, $param->getChannel()); $tmp = $test; foreach ($tmp as $file => $info) { if (is_array($info)) { @@ -1035,7 +1174,7 @@ class PEAR_Installer extends PEAR_Downloader } $pfk = &new PEAR_PackageFile($this->config); $parentpkg = &$pfk->fromArray($parentreg); - $this->_registry->updatePackage2($parentpkg); + $installregistry->updatePackage2($parentpkg); } if ($param->getChannel() == 'pecl.php.net' && isset($options['upgrade'])) { $tmp = $test; @@ -1077,12 +1216,12 @@ class PEAR_Installer extends PEAR_Downloader if (empty($options['upgrade']) && empty($options['soft'])) { // checks to do only when installing new packages if ($channel == 'pecl.php.net') { - $test = $this->_registry->packageExists($pkgname, $channel); + $test = $installregistry->packageExists($pkgname, $channel); if (!$test) { - $test = $this->_registry->packageExists($pkgname, 'pear.php.net'); + $test = $installregistry->packageExists($pkgname, 'pear.php.net'); } } else { - $test = $this->_registry->packageExists($pkgname, $channel); + $test = $installregistry->packageExists($pkgname, $channel); } if (empty($options['force']) && $test) { return $this->raiseError("$channel/$pkgname is already installed"); @@ -1090,16 +1229,16 @@ class PEAR_Installer extends PEAR_Downloader } else { $usechannel = $channel; if ($channel == 'pecl.php.net') { - $test = $this->_registry->packageExists($pkgname, $channel); + $test = $installregistry->packageExists($pkgname, $channel); if (!$test) { - $test = $this->_registry->packageExists($pkgname, 'pear.php.net'); + $test = $installregistry->packageExists($pkgname, 'pear.php.net'); $usechannel = 'pear.php.net'; } } else { - $test = $this->_registry->packageExists($pkgname, $channel); + $test = $installregistry->packageExists($pkgname, $channel); } if ($test) { - $v1 = $this->_registry->packageInfo($pkgname, 'version', $usechannel); + $v1 = $installregistry->packageInfo($pkgname, 'version', $usechannel); $v2 = $pkg->getVersion(); $cmp = version_compare("$v1", "$v2", 'gt'); if (empty($options['force']) && !version_compare("$v2", "$v1", 'gt')) { @@ -1131,74 +1270,77 @@ class PEAR_Installer extends PEAR_Downloader $this->source_files = 0; $savechannel = $this->config->get('default_channel'); - if (empty($options['register-only'])) { - if (!is_dir($php_dir)) { - if (PEAR::isError(System::mkdir(array('-p'), $php_dir))) { - return $this->raiseError("no installation destination directory '$php_dir'\n"); - } + if (empty($options['register-only']) && !is_dir($php_dir)) { + if (PEAR::isError(System::mkdir(array('-p'), $php_dir))) { + return $this->raiseError("no installation destination directory '$php_dir'\n"); } + } - $tmp_path = dirname($descfile); - if (substr($pkgfile, -4) != '.xml') { - $tmp_path .= DIRECTORY_SEPARATOR . $pkgname . '-' . $pkg->getVersion(); - } + $tmp_path = dirname($descfile); + if (substr($pkgfile, -4) != '.xml') { + $tmp_path .= DIRECTORY_SEPARATOR . $pkgname . '-' . $pkg->getVersion(); + } - $this->configSet('default_channel', $channel); - // {{{ install files - - if ($pkg->getPackagexmlVersion() == '2.0') { - $filelist = $pkg->getInstallationFilelist(); - if (PEAR::isError($filelist)) { - return $filelist; - } + $this->configSet('default_channel', $channel); + // {{{ install files + + $ver = $pkg->getPackagexmlVersion(); + if (version_compare($ver, '2.0', '>=')) { + $filelist = $pkg->getInstallationFilelist(); + } else { + $filelist = $pkg->getFileList(); + } + if (PEAR::isError($filelist)) { + return $filelist; + } + $p = &$installregistry->getPackage($pkgname, $channel); + if (empty($options['register-only']) && $p) { + $dirtree = $p->getDirTree(); + } else { + $dirtree = false; + } + $pkg->resetFilelist(); + $pkg->setLastInstalledVersion($installregistry->packageInfo($pkg->getPackage(), + 'version', $pkg->getChannel())); + foreach ($filelist as $file => $atts) { + if ($pkg->getPackagexmlVersion() == '1.0') { + $this->expectError(PEAR_INSTALLER_FAILED); + $res = $this->_installFile($file, $atts, $tmp_path, $options); + $this->popExpect(); } else { - $filelist = $pkg->getFileList(); + $this->expectError(PEAR_INSTALLER_FAILED); + $res = $this->_installFile2($pkg, $file, $atts, $tmp_path, $options); + $this->popExpect(); } - if (PEAR::isError($filelist)) { - return $filelist; - } - $pkg->resetFilelist(); - $pkg->setLastInstalledVersion($this->_registry->packageInfo($pkg->getPackage(), - 'version', $pkg->getChannel())); - foreach ($filelist as $file => $atts) { - if ($pkg->getPackagexmlVersion() == '1.0') { - $this->expectError(PEAR_INSTALLER_FAILED); - $res = $this->_installFile($file, $atts, $tmp_path, $options); - $this->popExpect(); + if (PEAR::isError($res)) { + if (empty($options['ignore-errors'])) { + $this->rollbackFileTransaction(); + if ($res->getMessage() == "file does not exist") { + $this->raiseError("file $file in package.xml does not exist"); + } + return $this->raiseError($res); } else { - $this->expectError(PEAR_INSTALLER_FAILED); - $res = $this->_installFile2($pkg, $file, $atts, $tmp_path, $options); - $this->popExpect(); - } - if (PEAR::isError($res)) { - if (empty($options['ignore-errors'])) { - $this->rollbackFileTransaction(); - if ($res->getMessage() == "file does not exist") { - $this->raiseError("file $file in package.xml does not exist"); - } - return $this->raiseError($res); - } else { - if (!isset($options['soft'])) { - $this->log(0, "Warning: " . $res->getMessage()); - } + if (!isset($options['soft'])) { + $this->log(0, "Warning: " . $res->getMessage()); } } - if ($res == PEAR_INSTALLER_OK) { - // Register files that were installed - $pkg->installedFile($file, $atts); - } } - // }}} - - // {{{ compile and install source files - if ($this->source_files > 0 && empty($options['nobuild'])) { - if (PEAR::isError($err = - $this->_compileSourceFiles($savechannel, $pkg))) { - return $err; - } + $real = isset($atts['attribs']) ? $atts['attribs'] : $atts; + if ($res == PEAR_INSTALLER_OK && $real['role'] != 'src') { + // Register files that were installed + $pkg->installedFile($file, $atts); } - // }}} } + // }}} + + // {{{ compile and install source files + if ($this->source_files > 0 && empty($options['nobuild'])) { + if (PEAR::isError($err = + $this->_compileSourceFiles($savechannel, $pkg))) { + return $err; + } + } + // }}} if (isset($backedup)) { $this->_removeBackups($backedup); @@ -1218,39 +1360,48 @@ class PEAR_Installer extends PEAR_Downloader // if 'force' is used, replace the info in registry $usechannel = $channel; if ($channel == 'pecl.php.net') { - $test = $this->_registry->packageExists($pkgname, $channel); + $test = $installregistry->packageExists($pkgname, $channel); if (!$test) { - $test = $this->_registry->packageExists($pkgname, 'pear.php.net'); + $test = $installregistry->packageExists($pkgname, 'pear.php.net'); $usechannel = 'pear.php.net'; } } else { - $test = $this->_registry->packageExists($pkgname, $channel); + $test = $installregistry->packageExists($pkgname, $channel); } if (!empty($options['force']) && $test) { - $oldversion = $this->_registry->packageInfo($pkgname, 'version', $usechannel); - $this->_registry->deletePackage($pkgname, $usechannel); + $oldversion = $installregistry->packageInfo($pkgname, 'version', $usechannel); + $installregistry->deletePackage($pkgname, $usechannel); } - $ret = $this->_registry->addPackage2($pkg); + $ret = $installregistry->addPackage2($pkg); } else { + if ($dirtree) { + $this->startFileTransaction(); + // attempt to delete empty directories + uksort($dirtree, array($this, '_sortDirs')); + foreach($dirtree as $dir => $notused) { + $this->addFileOperation('rmdir', array($dir)); + } + $this->commitFileTransaction(); + } $usechannel = $channel; if ($channel == 'pecl.php.net') { - $test = $this->_registry->packageExists($pkgname, $channel); + $test = $installregistry->packageExists($pkgname, $channel); if (!$test) { - $test = $this->_registry->packageExists($pkgname, 'pear.php.net'); + $test = $installregistry->packageExists($pkgname, 'pear.php.net'); $usechannel = 'pear.php.net'; } } else { - $test = $this->_registry->packageExists($pkgname, $channel); + $test = $installregistry->packageExists($pkgname, $channel); } // new: upgrade installs a package if it isn't installed if (!$test) { - $ret = $this->_registry->addPackage2($pkg); + $ret = $installregistry->addPackage2($pkg); } else { if ($usechannel != $channel) { - $this->_registry->deletePackage($pkgname, $usechannel); - $ret = $this->_registry->addPackage2($pkg); + $installregistry->deletePackage($pkgname, $usechannel); + $ret = $installregistry->addPackage2($pkg); } else { - $ret = $this->_registry->updatePackage2($pkg); + $ret = $installregistry->updatePackage2($pkg); } $installphase = 'upgrade'; } @@ -1303,28 +1454,39 @@ class PEAR_Installer extends PEAR_Downloader $role = 'src'; } $dest = $ext['dest']; - $this->log(1, "Installing '$ext[file]'"); - $copyto = $this->_prependPath($dest, $this->installroot); + $packagingroot = ''; + if (isset($this->_options['packagingroot'])) { + $packagingroot = $this->_options['packagingroot']; + } + $copyto = $this->_prependPath($dest, $packagingroot); + if ($copyto != $dest) { + $this->log(1, "Installing '$dest' as '$copyto'"); + } else { + $this->log(1, "Installing '$dest'"); + } $copydir = dirname($copyto); - if (!@is_dir($copydir)) { - if (!$this->mkDirHier($copydir)) { - return $this->raiseError("failed to mkdir $copydir", - PEAR_INSTALLER_FAILED); + // pretty much nothing happens if we are only registering the install + if (empty($this->_options['register-only'])) { + if (!file_exists($copydir) || !is_dir($copydir)) { + if (!$this->mkDirHier($copydir)) { + return $this->raiseError("failed to mkdir $copydir", + PEAR_INSTALLER_FAILED); + } + $this->log(3, "+ mkdir $copydir"); } - $this->log(3, "+ mkdir $copydir"); - } - if (!@copy($ext['file'], $copyto)) { - return $this->raiseError("failed to write $copyto", PEAR_INSTALLER_FAILED); - } - $this->log(3, "+ cp $ext[file] $copyto"); - if (!OS_WINDOWS) { - $mode = 0666 & ~(int)octdec($this->config->get('umask')); - $this->addFileOperation('chmod', array($mode, $copyto)); - if (!@chmod($copyto, $mode)) { - $this->log(0, "failed to change mode of $copyto"); + if (!@copy($ext['file'], $copyto)) { + return $this->raiseError("failed to write $copyto ($php_errormsg)", PEAR_INSTALLER_FAILED); + } + $this->log(3, "+ cp $ext[file] $copyto"); + $this->addFileOperation('rename', array($ext['file'], $copyto)); + if (!OS_WINDOWS) { + $mode = 0666 & ~(int)octdec($this->config->get('umask')); + $this->addFileOperation('chmod', array($mode, $copyto)); + if (!@chmod($copyto, $mode)) { + $this->log(0, "failed to change mode of $copyto ($php_errormsg)"); + } } } - $this->addFileOperation('rename', array($ext['file'], $copyto)); if ($filelist->getPackageXmlVersion() == '1.0') { $filelist->installedFile($bn, array( @@ -1364,6 +1526,7 @@ class PEAR_Installer extends PEAR_Downloader * @param array Command-line options. Possibilities include: * * - installroot: base installation dir, if not the default + * - register-only : update registry but don't remove files * - nodeps: do not process dependencies of other packages to ensure * uninstallation does not break things */ @@ -1428,47 +1591,56 @@ class PEAR_Installer extends PEAR_Downloader $this->log(0, $e[0]); } } - // {{{ Delete the files - $this->startFileTransaction(); - PEAR::pushErrorHandling(PEAR_ERROR_RETURN); - if (PEAR::isError($err = $this->_deletePackageFiles($package, $channel))) { - PEAR::popErrorHandling(); - $this->rollbackFileTransaction(); - $this->configSet('default_channel', $savechannel); - if (!isset($options['ignore-errors'])) { - return $this->raiseError($err); - } else { - if (!isset($options['soft'])) { - $this->log(0, 'WARNING: ' . $err->getMessage()); - } - } - } else { - PEAR::popErrorHandling(); - } - if (!$this->commitFileTransaction()) { - $this->rollbackFileTransaction(); - if (!isset($options['ignore-errors'])) { - return $this->raiseError("uninstall failed"); - } elseif (!isset($options['soft'])) { - $this->log(0, 'WARNING: uninstall failed'); - } - } else { + $this->pkginfo = &$pkg; + // pretty much nothing happens if we are only registering the uninstall + if (empty($options['register-only'])) { + // {{{ Delete the files $this->startFileTransaction(); - if ($dirtree = $pkg->getDirTree()) { - // attempt to delete empty directories - uksort($dirtree, array($this, '_sortDirs')); - foreach($dirtree as $dir => $notused) { - $this->addFileOperation('rmdir', array($dir)); + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + if (PEAR::isError($err = $this->_deletePackageFiles($package, $channel))) { + PEAR::popErrorHandling(); + $this->rollbackFileTransaction(); + $this->configSet('default_channel', $savechannel); + if (!isset($options['ignore-errors'])) { + return $this->raiseError($err); + } else { + if (!isset($options['soft'])) { + $this->log(0, 'WARNING: ' . $err->getMessage()); + } } } else { - $this->configSet('default_channel', $savechannel); - return $this->_registry->deletePackage($package, $channel); + PEAR::popErrorHandling(); } if (!$this->commitFileTransaction()) { $this->rollbackFileTransaction(); + if (!isset($options['ignore-errors'])) { + return $this->raiseError("uninstall failed"); + } elseif (!isset($options['soft'])) { + $this->log(0, 'WARNING: uninstall failed'); + } + } else { + $this->startFileTransaction(); + if ($dirtree = $pkg->getDirTree()) { + // attempt to delete empty directories + uksort($dirtree, array($this, '_sortDirs')); + foreach($dirtree as $dir => $notused) { + $this->addFileOperation('rmdir', array($dir)); + } + } else { + $this->configSet('default_channel', $savechannel); + return $this->_registry->deletePackage($package, $channel); + } + if (!$this->commitFileTransaction()) { + $this->rollbackFileTransaction(); + if (!isset($options['ignore-errors'])) { + return $this->raiseError("uninstall failed"); + } elseif (!isset($options['soft'])) { + $this->log(0, 'WARNING: uninstall failed'); + } + } } + // }}} } - // }}} $this->configSet('default_channel', $savechannel); // Register that the package is no longer installed @@ -1539,16 +1711,11 @@ class PEAR_Installer extends PEAR_Downloader // {{{ md5_file() utility function if (!function_exists("md5_file")) { function md5_file($filename) { - $fp = fopen($filename, "r"); - if (!$fp) return null; - if (function_exists('file_get_contents')) { - fclose($fp); - $contents = file_get_contents($filename); - } else { - $contents = fread($fp, filesize($filename)); - fclose($fp); + if (!$fd = @fopen($file, 'r')) { + return false; } - return md5($contents); + fclose($fd); + return md5(file_get_contents($filename)); } } // }}} diff --git a/includes/pear/PEAR/Installer/Role.php b/includes/pear/PEAR/Installer/Role.php index c3b8d7a2..3b50db3c 100644 --- a/includes/pear/PEAR/Installer/Role.php +++ b/includes/pear/PEAR/Installer/Role.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Role.php,v 1.12 2005/11/01 06:18:14 cellog Exp $ + * @version CVS: $Id: Role.php,v 1.20 2008/01/03 20:26:36 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -25,14 +25,13 @@ */ require_once 'PEAR/Installer/Role/Common.php'; require_once 'PEAR/XMLParser.php'; -//$GLOBALS['_PEAR_INSTALLER_ROLES'] = array(); /** * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -55,7 +54,7 @@ class PEAR_Installer_Role if (!$info['config_vars']) { continue; } - $config->_addConfigVars($info['config_vars']); + $config->_addConfigVars($class, $info['config_vars']); } } @@ -86,8 +85,7 @@ class PEAR_Installer_Role /** * Get a list of file roles that are valid for the particular release type. * - * For instance, src files serve no purpose in regular php releases. php files - * serve no purpose in extsrc or extbin releases + * For instance, src files serve no purpose in regular php releases. * @param string * @param bool clear cache * @return array @@ -134,6 +132,7 @@ class PEAR_Installer_Role unset($ret); } if (!isset($ret)) { + $ret = array(); foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) { if ($okreleases['installable']) { $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role)); @@ -163,6 +162,7 @@ class PEAR_Installer_Role unset($ret); } if (!isset($ret)) { + $ret = array(); foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) { if ($okreleases['honorsbaseinstall']) { $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role)); @@ -189,6 +189,7 @@ class PEAR_Installer_Role unset($ret); } if (!isset($ret)) { + $ret = array(); foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) { if ($okreleases['phpfile']) { $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role)); @@ -212,13 +213,17 @@ class PEAR_Installer_Role */ function registerRoles($dir = null) { + $GLOBALS['_PEAR_INSTALLER_ROLES'] = array(); $parser = new PEAR_XMLParser; if ($dir === null) { $dir = dirname(__FILE__) . '/Role'; } + if (!file_exists($dir) || !is_dir($dir)) { + return PEAR::raiseError("registerRoles: opendir($dir) failed: does not exist/is not directory"); + } $dp = @opendir($dir); if (empty($dp)) { - return PEAR::raiseError("registerRoles: opendir($dir) failed"); + return PEAR::raiseError("registerRoles: opendir($dir) failed: $php_errmsg"); } while ($entry = readdir($dp)) { if ($entry{0} == '.' || substr($entry, -4) != '.xml') { @@ -226,7 +231,7 @@ class PEAR_Installer_Role } $class = "PEAR_Installer_Role_".substr($entry, 0, -4); // List of roles - if (empty($GLOBALS['_PEAR_INSTALLER_ROLES'][$class])) { + if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'][$class])) { $file = "$dir/$entry"; $parser->parse(file_get_contents($file)); $data = $parser->getData(); @@ -236,7 +241,7 @@ class PEAR_Installer_Role $GLOBALS['_PEAR_INSTALLER_ROLES'][$class] = $data; } } - @closedir($dp); + closedir($dp); ksort($GLOBALS['_PEAR_INSTALLER_ROLES']); PEAR_Installer_Role::getBaseinstallRoles(true); PEAR_Installer_Role::getInstallableRoles(true); diff --git a/includes/pear/PEAR/Installer/Role/Cfg.php b/includes/pear/PEAR/Installer/Role/Cfg.php new file mode 100644 index 00000000..1f85ebb5 --- /dev/null +++ b/includes/pear/PEAR/Installer/Role/Cfg.php @@ -0,0 +1,108 @@ + + * @copyright 2007-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Cfg.php,v 1.8 2008/05/14 21:26:30 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.7.0 + */ + +/** + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 2007-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.7.0 + */ +class PEAR_Installer_Role_Cfg extends PEAR_Installer_Role_Common +{ + /** + * @var PEAR_Installer + */ + var $installer; + /** + * the md5 of the original file + * + * @var unknown_type + */ + var $md5 = null; + /** + * Do any unusual setup here + * @param PEAR_Installer + * @param PEAR_PackageFile_v2 + * @param array file attributes + * @param string file name + */ + function setup(&$installer, $pkg, $atts, $file) + { + $this->installer = &$installer; + $reg = &$this->installer->config->getRegistry(); + $package = $reg->getPackage($pkg->getPackage(), $pkg->getChannel()); + if ($package) { + $filelist = $package->getFilelist(); + if (isset($filelist[$file]) && isset($filelist[$file]['md5sum'])) { + $this->md5 = $filelist[$file]['md5sum']; + } + } + } + + function processInstallation($pkg, $atts, $file, $tmp_path, $layer = null) + { + $test = parent::processInstallation($pkg, $atts, $file, $tmp_path, $layer); + if (@file_exists($test[2]) && @file_exists($test[3])) { + $md5 = md5_file($test[2]); + // configuration has already been installed, check for mods + if ($md5 !== $this->md5 && $md5 !== md5_file($test[3])) { + // configuration has been modified, so save our version as + // configfile-version + $old = $test[2]; + $test[2] .= '.new-' . $pkg->getVersion(); + // backup original and re-install it + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $tmpcfg = $this->config->get('temp_dir'); + $newloc = System::mkdir(array('-p', $tmpcfg)); + if (!$newloc) { + // try temp_dir + $newloc = System::mktemp(array('-d')); + if (!$newloc || PEAR::isError($newloc)) { + PEAR::popErrorHandling(); + return PEAR::raiseError('Could not save existing configuration file '. + $old . ', unable to install. Please set temp_dir ' . + 'configuration variable to a writeable location and try again'); + } + } else { + $newloc = $tmpcfg; + } + $temp_file = $newloc . DIRECTORY_SEPARATOR . uniqid('savefile'); + if (!@copy($old, $temp_file)) { + PEAR::popErrorHandling(); + return PEAR::raiseError('Could not save existing configuration file '. + $old . ', unable to install. Please set temp_dir ' . + 'configuration variable to a writeable location and try again'); + } + PEAR::popErrorHandling(); + $this->installer->log(0, "WARNING: configuration file $old is being installed as $test[2], you should manually merge in changes to the existing configuration file"); + $this->installer->addFileOperation('rename', array($temp_file, $old, false)); + $this->installer->addFileOperation('delete', array($temp_file)); + } + } + return $test; + } +} +?> diff --git a/includes/pear/PEAR/Installer/Role/Cfg.xml b/includes/pear/PEAR/Installer/Role/Cfg.xml new file mode 100644 index 00000000..7a415dc4 --- /dev/null +++ b/includes/pear/PEAR/Installer/Role/Cfg.xml @@ -0,0 +1,15 @@ + + php + extsrc + extbin + zendextsrc + zendextbin + 1 + cfg_dir + + 1 + + + + + \ No newline at end of file diff --git a/includes/pear/PEAR/Installer/Role/Common.php b/includes/pear/PEAR/Installer/Role/Common.php index fd01521b..32cd8217 100644 --- a/includes/pear/PEAR/Installer/Role/Common.php +++ b/includes/pear/PEAR/Installer/Role/Common.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2006 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Common.php,v 1.9 2005/11/01 22:28:42 cellog Exp $ + * @version CVS: $Id: Common.php,v 1.12 2006/10/19 23:55:32 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -28,9 +28,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2006 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -94,13 +94,13 @@ class PEAR_Installer_Role_Common } } elseif ($roleInfo['unusualbaseinstall']) { $dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'], - null, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage(); + $layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage(); if (!empty($atts['baseinstalldir'])) { $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir']; } } else { $dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'], - null, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage(); + $layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage(); } if (dirname($file) != '.' && empty($atts['install-as'])) { $dest_dir .= DIRECTORY_SEPARATOR . dirname($file); diff --git a/includes/pear/PEAR/Installer/Role/Data.php b/includes/pear/PEAR/Installer/Role/Data.php index 9811e464..394f68ce 100644 --- a/includes/pear/PEAR/Installer/Role/Data.php +++ b/includes/pear/PEAR/Installer/Role/Data.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Data.php,v 1.5 2005/11/01 22:28:42 cellog Exp $ + * @version CVS: $Id: Data.php,v 1.7 2008/01/03 20:26:36 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -24,9 +24,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ diff --git a/includes/pear/PEAR/Installer/Role/Data.xml b/includes/pear/PEAR/Installer/Role/Data.xml index 4382b707..eae63720 100644 --- a/includes/pear/PEAR/Installer/Role/Data.xml +++ b/includes/pear/PEAR/Installer/Role/Data.xml @@ -2,6 +2,8 @@ php extsrc extbin + zendextsrc + zendextbin 1 data_dir diff --git a/includes/pear/PEAR/Installer/Role/Doc.php b/includes/pear/PEAR/Installer/Role/Doc.php index e38311d2..b974dc68 100644 --- a/includes/pear/PEAR/Installer/Role/Doc.php +++ b/includes/pear/PEAR/Installer/Role/Doc.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Doc.php,v 1.5 2005/11/01 22:28:42 cellog Exp $ + * @version CVS: $Id: Doc.php,v 1.7 2008/01/03 20:26:36 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -24,9 +24,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ diff --git a/includes/pear/PEAR/Installer/Role/Doc.xml b/includes/pear/PEAR/Installer/Role/Doc.xml index 0c593ef3..173afba0 100644 --- a/includes/pear/PEAR/Installer/Role/Doc.xml +++ b/includes/pear/PEAR/Installer/Role/Doc.xml @@ -2,6 +2,8 @@ php extsrc extbin + zendextsrc + zendextbin 1 doc_dir diff --git a/includes/pear/PEAR/Installer/Role/Ext.php b/includes/pear/PEAR/Installer/Role/Ext.php index c1ca4f1b..38c0e9af 100644 --- a/includes/pear/PEAR/Installer/Role/Ext.php +++ b/includes/pear/PEAR/Installer/Role/Ext.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Ext.php,v 1.5 2005/11/01 22:28:42 cellog Exp $ + * @version CVS: $Id: Ext.php,v 1.7 2008/01/03 20:26:36 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -24,9 +24,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ diff --git a/includes/pear/PEAR/Installer/Role/Ext.xml b/includes/pear/PEAR/Installer/Role/Ext.xml index d5c1c485..e2940fe1 100644 --- a/includes/pear/PEAR/Installer/Role/Ext.xml +++ b/includes/pear/PEAR/Installer/Role/Ext.xml @@ -1,5 +1,6 @@ extbin + zendextbin 1 ext_dir 1 diff --git a/includes/pear/PEAR/Installer/Role/Php.php b/includes/pear/PEAR/Installer/Role/Php.php index 93c4ff7d..f232b723 100644 --- a/includes/pear/PEAR/Installer/Role/Php.php +++ b/includes/pear/PEAR/Installer/Role/Php.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Php.php,v 1.6 2005/11/01 22:28:42 cellog Exp $ + * @version CVS: $Id: Php.php,v 1.8 2008/01/03 20:26:36 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -24,9 +24,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ diff --git a/includes/pear/PEAR/Installer/Role/Php.xml b/includes/pear/PEAR/Installer/Role/Php.xml index 037c2a11..6b9a0e67 100644 --- a/includes/pear/PEAR/Installer/Role/Php.xml +++ b/includes/pear/PEAR/Installer/Role/Php.xml @@ -2,6 +2,8 @@ php extsrc extbin + zendextsrc + zendextbin 1 php_dir 1 diff --git a/includes/pear/PEAR/Installer/Role/Script.php b/includes/pear/PEAR/Installer/Role/Script.php index 82882028..b8affdbb 100644 --- a/includes/pear/PEAR/Installer/Role/Script.php +++ b/includes/pear/PEAR/Installer/Role/Script.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Script.php,v 1.5 2005/11/01 22:28:42 cellog Exp $ + * @version CVS: $Id: Script.php,v 1.7 2008/01/03 20:26:36 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -24,9 +24,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ diff --git a/includes/pear/PEAR/Installer/Role/Script.xml b/includes/pear/PEAR/Installer/Role/Script.xml index bc2df176..e732cf2a 100644 --- a/includes/pear/PEAR/Installer/Role/Script.xml +++ b/includes/pear/PEAR/Installer/Role/Script.xml @@ -2,6 +2,8 @@ php extsrc extbin + zendextsrc + zendextbin 1 bin_dir 1 diff --git a/includes/pear/PEAR/Installer/Role/Src.php b/includes/pear/PEAR/Installer/Role/Src.php index 9ba2e05d..68d07e4d 100644 --- a/includes/pear/PEAR/Installer/Role/Src.php +++ b/includes/pear/PEAR/Installer/Role/Src.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Src.php,v 1.5 2005/11/01 22:28:42 cellog Exp $ + * @version CVS: $Id: Src.php,v 1.7 2008/01/03 20:26:36 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -24,9 +24,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ diff --git a/includes/pear/PEAR/Installer/Role/Src.xml b/includes/pear/PEAR/Installer/Role/Src.xml index c2fb4d18..10348340 100644 --- a/includes/pear/PEAR/Installer/Role/Src.xml +++ b/includes/pear/PEAR/Installer/Role/Src.xml @@ -1,7 +1,8 @@ extsrc - - + zendextsrc + 1 + temp_dir diff --git a/includes/pear/PEAR/Installer/Role/Test.php b/includes/pear/PEAR/Installer/Role/Test.php index 48e50ea1..63979b93 100644 --- a/includes/pear/PEAR/Installer/Role/Test.php +++ b/includes/pear/PEAR/Installer/Role/Test.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Test.php,v 1.5 2005/11/01 22:28:42 cellog Exp $ + * @version CVS: $Id: Test.php,v 1.7 2008/01/03 20:26:36 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -24,9 +24,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ diff --git a/includes/pear/PEAR/Installer/Role/Test.xml b/includes/pear/PEAR/Installer/Role/Test.xml index dd486426..51d5b894 100644 --- a/includes/pear/PEAR/Installer/Role/Test.xml +++ b/includes/pear/PEAR/Installer/Role/Test.xml @@ -2,6 +2,8 @@ php extsrc extbin + zendextsrc + zendextbin 1 test_dir diff --git a/includes/pear/PEAR/Installer/Role/Www.php b/includes/pear/PEAR/Installer/Role/Www.php new file mode 100644 index 00000000..801097f9 --- /dev/null +++ b/includes/pear/PEAR/Installer/Role/Www.php @@ -0,0 +1,34 @@ + + * @copyright 2007-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Www.php,v 1.2 2008/01/03 20:26:36 cellog Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.7.0 + */ + +/** + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 2007-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.7.0 + */ +class PEAR_Installer_Role_Www extends PEAR_Installer_Role_Common {} +?> \ No newline at end of file diff --git a/includes/pear/PEAR/Installer/Role/Www.xml b/includes/pear/PEAR/Installer/Role/Www.xml new file mode 100644 index 00000000..7598be38 --- /dev/null +++ b/includes/pear/PEAR/Installer/Role/Www.xml @@ -0,0 +1,15 @@ + + php + extsrc + extbin + zendextsrc + zendextbin + 1 + www_dir + 1 + + + + + + \ No newline at end of file diff --git a/includes/pear/PEAR/PackageFile.php b/includes/pear/PEAR/PackageFile.php index 783017ec..0dc42e97 100644 --- a/includes/pear/PEAR/PackageFile.php +++ b/includes/pear/PEAR/PackageFile.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: PackageFile.php,v 1.31 2005/09/15 20:42:25 cellog Exp $ + * @version CVS: $Id: PackageFile.php,v 1.41 2008/01/03 20:26:36 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -39,9 +39,9 @@ define('PEAR_PACKAGEFILE_ERROR_INVALID_PACKAGEVERSION', 2); * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -186,9 +186,9 @@ class PEAR_PackageFile function &fromXmlString($data, $state, $file, $archive = false) { if (preg_match('/]+version="([0-9]+\.[0-9]+)"/', $data, $packageversion)) { - if (!in_array($packageversion[1], array('1.0', '2.0'))) { + if (!in_array($packageversion[1], array('1.0', '2.0', '2.1'))) { return PEAR::raiseError('package.xml version "' . $packageversion[1] . - '" is not supported, only 1.0 and 2.0 are supported.'); + '" is not supported, only 1.0, 2.0, and 2.1 are supported.'); } $object = &$this->parserFactory($packageversion[1]); if ($this->_logger) { @@ -306,7 +306,8 @@ class PEAR_PackageFile $tar->popErrorHandling(); } if (!is_array($content)) { - if (is_string($file) && strlen($file < 255) && !@is_file($file)) { + if (is_string($file) && strlen($file < 255) && + (!file_exists($file) || !@is_file($file))) { $ret = PEAR::raiseError("could not open file \"$file\""); return $ret; } @@ -332,7 +333,7 @@ class PEAR_PackageFile $xml = $name; break; } elseif (ereg('package.xml$', $name, $match)) { - $xml = $match[0]; + $xml = $name; break; } } @@ -342,15 +343,48 @@ class PEAR_PackageFile $tmpdir = System::mkTemp(array('-d', 'pear')); PEAR_PackageFile::addTempFile($tmpdir); } + $this->_extractErrors(); + PEAR::staticPushErrorHandling(PEAR_ERROR_CALLBACK, array($this, '_extractErrors')); if (!$xml || !$tar->extractList(array($xml), $tmpdir)) { + $extra = implode("\n", $this->_extractErrors()); + if ($extra) { + $extra = ' ' . $extra; + } + PEAR::staticPopErrorHandling(); $ret = PEAR::raiseError('could not extract the package.xml file from "' . - $origfile . '"'); + $origfile . '"' . $extra); return $ret; } + PEAR::staticPopErrorHandling(); $ret = &PEAR_PackageFile::fromPackageFile("$tmpdir/$xml", $state, $origfile); return $ret; } + /** + * helper for extracting Archive_Tar errors + * @var array + * @access private + */ + var $_extractErrors = array(); + + /** + * helper callback for extracting Archive_Tar errors + * + * @param PEAR_Error|null $err + * @return array + * @access private + */ + function _extractErrors($err = null) + { + static $errors = array(); + if ($err === null) { + $e = $errors; + $errors = array(); + return $e; + } + $errors[] = $err->getMessage(); + } + /** * Create a PEAR_PackageFile_v* from a package.xml file. * @@ -366,24 +400,16 @@ class PEAR_PackageFile function &fromPackageFile($descfile, $state, $archive = false) { if (is_string($descfile) && strlen($descfile) < 255 && - !@is_file($descfile) || !is_readable($descfile) || - (!$fp = @fopen($descfile, 'r'))) { + (!file_exists($descfile) || !is_file($descfile) || !is_readable($descfile) || + (!$fp = @fopen($descfile, 'r')))) { $a = PEAR::raiseError("Unable to open $descfile"); return $a; } // read the whole thing so we only get one cdata callback // for each block of cdata - if (function_exists('file_get_contents')) { - @fclose($fp); - $data = file_get_contents($descfile); - } else { - $data = ''; - while (!feof($fp)) { - $data .= @fread($fp, 8192); - } - fclose($fp); - } + fclose($fp); + $data = file_get_contents($descfile); $ret = &PEAR_PackageFile::fromXmlString($data, $state, $descfile, $archive); return $ret; } @@ -404,6 +430,18 @@ class PEAR_PackageFile */ function &fromAnyFile($info, $state) { + if (is_dir($info)) { + $dir_name = realpath($info); + if (file_exists($dir_name . '/package.xml')) { + $info = PEAR_PackageFile::fromPackageFile($dir_name . '/package.xml', $state); + } elseif (file_exists($dir_name . '/package2.xml')) { + $info = PEAR_PackageFile::fromPackageFile($dir_name . '/package2.xml', $state); + } else { + $info = PEAR::raiseError("No package definition found in '$info' directory"); + } + return $info; + } + $fp = false; if (is_string($info) && strlen($info) < 255 && (file_exists($info) || ($fp = @fopen($info, 'r')))) { @@ -433,4 +471,4 @@ class PEAR_PackageFile } } -?> \ No newline at end of file +?> diff --git a/includes/pear/PEAR/PackageFile/Generator/v1.php b/includes/pear/PEAR/PackageFile/Generator/v1.php index 3677b204..e6c5c94c 100644 --- a/includes/pear/PEAR/PackageFile/Generator/v1.php +++ b/includes/pear/PEAR/PackageFile/Generator/v1.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: v1.php,v 1.69 2005/09/25 03:48:59 cellog Exp $ + * @version CVS: $Id: v1.php,v 1.74 2008/01/03 20:26:37 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -33,9 +33,9 @@ require_once 'PEAR/PackageFile/v2.php'; * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -52,7 +52,7 @@ class PEAR_PackageFile_Generator_v1 function getPackagerVersion() { - return '1.4.5'; + return '1.7.2'; } /** @@ -206,7 +206,7 @@ class PEAR_PackageFile_Generator_v1 ); $ret = "\n"; $ret .= "\n"; - $ret .= "\n" . + $ret .= "\n" . " $pkginfo[package]"; if (isset($pkginfo['extends'])) { $ret .= "\n$pkginfo[extends]"; @@ -321,7 +321,10 @@ class PEAR_PackageFile_Generator_v1 $ret .= $this->recursiveXmlFilelist($pkginfo['filelist']); } else { foreach ($pkginfo['filelist'] as $file => $fa) { - @$ret .= "$indent _fixXmlEncoding($fa['baseinstalldir']) . '"'; @@ -348,7 +351,7 @@ class PEAR_PackageFile_Generator_v1 } $ret .= "/>\n"; } - @$ret .= "$indent \n"; + $ret .= "$indent \n"; } } } @@ -680,7 +683,9 @@ class PEAR_PackageFile_Generator_v1 } $ret = new $class; $ret->setConfig($this->_packagefile->_config); - $ret->setLogger($this->_packagefile->_logger); + if (isset($this->_packagefile->_logger) && is_object($this->_packagefile->_logger)) { + $ret->setLogger($this->_packagefile->_logger); + } $ret->fromArray($arr); return $ret; } @@ -695,7 +700,7 @@ class PEAR_PackageFile_Generator_v1 $peardep = array('pearinstaller' => array('min' => '1.4.0b1')); // this is a lot safer $required = $optional = array(); - $release['dependencies'] = array(); + $release['dependencies'] = array('required' => array()); if ($this->_packagefile->hasDeps()) { foreach ($this->_packagefile->getDeps() as $dep) { if (!isset($dep['optional']) || $dep['optional'] == 'no') { diff --git a/includes/pear/PEAR/PackageFile/Generator/v2.php b/includes/pear/PEAR/PackageFile/Generator/v2.php index 0631b4a2..fb8d2f97 100644 --- a/includes/pear/PEAR/PackageFile/Generator/v2.php +++ b/includes/pear/PEAR/PackageFile/Generator/v2.php @@ -14,9 +14,9 @@ * @package PEAR * @author Greg Beaver * @author Stephan Schmidt (original XML_Serializer code) - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: v2.php,v 1.32 2005/10/02 06:29:24 cellog Exp $ + * @version CVS: $Id: v2.php,v 1.39 2008/05/13 05:29:24 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -33,9 +33,9 @@ require_once 'System.php'; * @package PEAR * @author Greg Beaver * @author Stephan Schmidt (original XML_Serializer code) - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -61,7 +61,7 @@ class PEAR_PackageFile_Generator_v2 'indentAttributes' => false, // indent the attributes, if set to '_auto', it will indent attributes so they all start at the same column 'mode' => 'simplexml', // use 'simplexml' to use parent name as tagname if transforming an indexed array 'addDoctype' => false, // add a doctype declaration - 'doctype' => null, // supply a string or an array with id and uri ({@see XML_Util::getDoctypeDeclaration()} + 'doctype' => null, // supply a string or an array with id and uri ({@see PEAR_PackageFile_Generator_v2_PEAR_PackageFile_Generator_v2_XML_Util::getDoctypeDeclaration()} 'rootName' => 'package', // name of the root tag 'rootAttributes' => array( 'version' => '2.0', @@ -114,7 +114,7 @@ http://pear.php.net/dtd/package-2.0.xsd', */ function getPackagerVersion() { - return '1.4.5'; + return '1.7.2'; } /** @@ -213,19 +213,16 @@ http://pear.php.net/dtd/package-2.0.xsd', if (!file_exists($file)) { return $packager->raiseError("File does not exist: $fname"); } else { + $origperms = fileperms($file); $tfile = $packageDir . DIRECTORY_SEPARATOR . $fname; unset($orig['attribs']); if (count($orig)) { // file with tasks // run any package-time tasks - if (function_exists('file_get_contents')) { - $contents = file_get_contents($file); - } else { - $fp = fopen($file, "r"); - $contents = @fread($fp, filesize($file)); - fclose($fp); - } + $contents = file_get_contents($file); foreach ($orig as $tag => $raw) { - $tag = str_replace($this->_packagefile->getTasksNs() . ':', '', $tag); + $tag = str_replace( + array($this->_packagefile->getTasksNs() . ':', '-'), + array('', '_'), $tag); $task = "PEAR_Task_$tag"; $task = &new $task($this->_packagefile->_config, $this->_packagefile->_logger, @@ -249,6 +246,7 @@ http://pear.php.net/dtd/package-2.0.xsd', System::mkdir(array('-p', dirname($tfile))); copy($file, $tfile); } + chmod($tfile, $origperms); $filelist[$i++] = $tfile; $this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($tfile), $i - 1); $packager->log(2, "Adding file $fname"); @@ -358,7 +356,7 @@ http://pear.php.net/dtd/package-2.0.xsd', } $this->options['beautifyFilelist'] = true; } - $arr['attribs']['packagerversion'] = '1.4.5'; + $arr['attribs']['packagerversion'] = '1.7.2'; if ($this->serialize($arr, $options)) { return $this->_serializedData . "\n"; } @@ -537,7 +535,7 @@ http://pear.php.net/dtd/package-2.0.xsd', // add doctype declaration if ($this->options['addDoctype'] === true) { - $this->_serializedData = XML_Util::getDoctypeDeclaration($tagName, $this->options['doctype']) + $this->_serializedData = PEAR_PackageFile_Generator_v2_XML_Util::getDoctypeDeclaration($tagName, $this->options['doctype']) . $this->options['linebreak'] . $this->_serializedData; } @@ -550,7 +548,7 @@ http://pear.php.net/dtd/package-2.0.xsd', } else { $encoding = null; } - $this->_serializedData = XML_Util::getXMLDeclaration('1.0', $encoding) + $this->_serializedData = PEAR_PackageFile_Generator_v2_XML_Util::getXMLDeclaration('1.0', $encoding) . $this->options['linebreak'] . $this->_serializedData; } @@ -613,7 +611,7 @@ http://pear.php.net/dtd/package-2.0.xsd', * @param string $tagName name of the root tag * @param array $attributes attributes for the root tag * @return string $string serialized data - * @uses XML_Util::isValidName() to check, whether key has to be substituted + * @uses PEAR_PackageFile_Generator_v2_XML_Util::isValidName() to check, whether key has to be substituted */ function _serializeArray(&$array, $tagName = null, $attributes = array()) { @@ -695,7 +693,7 @@ http://pear.php.net/dtd/package-2.0.xsd', if ($this->options['scalarAsAttributes'] === true) { foreach ($array as $key => $value) { - if (is_scalar($value) && (XML_Util::isValidName($key) === true)) { + if (is_scalar($value) && (PEAR_PackageFile_Generator_v2_XML_Util::isValidName($key) === true)) { unset($array[$key]); $attributes[$this->options['prependAttributes'].$key] = $value; } @@ -722,7 +720,7 @@ http://pear.php.net/dtd/package-2.0.xsd', // copy key $origKey = $key; // key cannot be used as tagname => use default tag - $valid = XML_Util::isValidName($key); + $valid = PEAR_PackageFile_Generator_v2_XML_Util::isValidName($key); if (PEAR::isError($valid)) { if ($this->options['classAsTagName'] && is_object($value)) { $key = get_class($value); @@ -842,31 +840,23 @@ http://pear.php.net/dtd/package-2.0.xsd', if (is_scalar($tag['content']) || is_null($tag['content'])) { if ($this->options['encoding'] == 'UTF-8' && version_compare(phpversion(), '5.0.0', 'lt')) { - $encoding = XML_UTIL_ENTITIES_UTF8_XML; + $encoding = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_UTF8_XML; } else { - $encoding = XML_UTIL_ENTITIES_XML; + $encoding = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML; } - $tag = XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $this->options['linebreak'], $encoding); + $tag = PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $this->options['linebreak'], $encoding); } elseif (is_array($tag['content'])) { $tag = $this->_serializeArray($tag['content'], $tag['qname'], $tag['attributes']); } elseif (is_object($tag['content'])) { $tag = $this->_serializeObject($tag['content'], $tag['qname'], $tag['attributes']); } elseif (is_resource($tag['content'])) { settype($tag['content'], 'string'); - $tag = XML_Util::createTagFromArray($tag, $replaceEntities); + $tag = PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray($tag, $replaceEntities); } return $tag; } } -//foreach (explode(PATH_SEPARATOR, ini_get('include_path')) as $path) { -// $t = $path . DIRECTORY_SEPARATOR . 'XML' . DIRECTORY_SEPARATOR . -// 'Util'; -// if (file_exists($t) && is_readable($t)) { -// include_once 'XML/Util'; -// } -//} -//if (!class_exists('XML_Util')) { // well, it's one way to do things without extra deps ... /* vim: set expandtab tabstop=4 shiftwidth=4: */ // +----------------------------------------------------------------------+ @@ -885,76 +875,79 @@ http://pear.php.net/dtd/package-2.0.xsd', // | Authors: Stephan Schmidt | // +----------------------------------------------------------------------+ // -// $Id: v2.php,v 1.32 2005/10/02 06:29:24 cellog Exp $ +// $Id: v2.php,v 1.39 2008/05/13 05:29:24 cellog Exp $ /** * error code for invalid chars in XML name */ -define("XML_UTIL_ERROR_INVALID_CHARS", 51); +define("PEAR_PackageFile_Generator_v2_XML_Util_ERROR_INVALID_CHARS", 51); /** * error code for invalid chars in XML name */ -define("XML_UTIL_ERROR_INVALID_START", 52); +define("PEAR_PackageFile_Generator_v2_XML_Util_ERROR_INVALID_START", 52); /** * error code for non-scalar tag content */ -define("XML_UTIL_ERROR_NON_SCALAR_CONTENT", 60); +define("PEAR_PackageFile_Generator_v2_XML_Util_ERROR_NON_SCALAR_CONTENT", 60); /** * error code for missing tag name */ -define("XML_UTIL_ERROR_NO_TAG_NAME", 61); +define("PEAR_PackageFile_Generator_v2_XML_Util_ERROR_NO_TAG_NAME", 61); /** * replace XML entities */ -define("XML_UTIL_REPLACE_ENTITIES", 1); +define("PEAR_PackageFile_Generator_v2_XML_Util_REPLACE_ENTITIES", 1); /** * embedd content in a CData Section */ -define("XML_UTIL_CDATA_SECTION", 2); +define("PEAR_PackageFile_Generator_v2_XML_Util_CDATA_SECTION", 2); /** * do not replace entitites */ -define("XML_UTIL_ENTITIES_NONE", 0); +define("PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_NONE", 0); /** * replace all XML entitites * This setting will replace <, >, ", ' and & */ -define("XML_UTIL_ENTITIES_XML", 1); +define("PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML", 1); /** * replace only required XML entitites * This setting will replace <, " and & */ -define("XML_UTIL_ENTITIES_XML_REQUIRED", 2); +define("PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML_REQUIRED", 2); /** * replace HTML entitites * @link http://www.php.net/htmlentities */ -define("XML_UTIL_ENTITIES_HTML", 3); +define("PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_HTML", 3); /** * replace all XML entitites, and encode from ISO-8859-1 to UTF-8 * This setting will replace <, >, ", ' and & */ -define("XML_UTIL_ENTITIES_UTF8_XML", 4); +define("PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_UTF8_XML", 4); /** * utility class for working with XML documents + * + * customized version of XML_Util 0.6.0 * * @category XML - * @package XML_Util + * @package PEAR * @version 0.6.0 * @author Stephan Schmidt + * @author Gregory Beaver */ -class XML_Util { +class PEAR_PackageFile_Generator_v2_XML_Util { /** * return API version @@ -978,19 +971,19 @@ class XML_Util { * require_once 'XML/Util.php'; * * // replace XML entites: - * $string = XML_Util::replaceEntities("This string contains < & >."); + * $string = PEAR_PackageFile_Generator_v2_XML_Util::replaceEntities("This string contains < & >."); * * * @access public * @static * @param string string where XML special chars should be replaced - * @param integer setting for entities in attribute values (one of XML_UTIL_ENTITIES_XML, XML_UTIL_ENTITIES_XML_REQUIRED, XML_UTIL_ENTITIES_HTML) + * @param integer setting for entities in attribute values (one of PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML, PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML_REQUIRED, PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_HTML) * @return string string with replaced chars */ - function replaceEntities($string, $replaceEntities = XML_UTIL_ENTITIES_XML) + function replaceEntities($string, $replaceEntities = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML) { switch ($replaceEntities) { - case XML_UTIL_ENTITIES_UTF8_XML: + case PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_UTF8_XML: return strtr(utf8_encode($string),array( '&' => '&', '>' => '>', @@ -998,7 +991,7 @@ class XML_Util { '"' => '"', '\'' => ''' )); break; - case XML_UTIL_ENTITIES_XML: + case PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML: return strtr($string,array( '&' => '&', '>' => '>', @@ -1006,13 +999,13 @@ class XML_Util { '"' => '"', '\'' => ''' )); break; - case XML_UTIL_ENTITIES_XML_REQUIRED: + case PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML_REQUIRED: return strtr($string,array( '&' => '&', '<' => '<', '"' => '"' )); break; - case XML_UTIL_ENTITIES_HTML: + case PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_HTML: return htmlspecialchars($string); break; } @@ -1026,7 +1019,7 @@ class XML_Util { * require_once 'XML/Util.php'; * * // get an XML declaration: - * $xmlDecl = XML_Util::getXMLDeclaration("1.0", "UTF-8", true); + * $xmlDecl = PEAR_PackageFile_Generator_v2_XML_Util::getXMLDeclaration("1.0", "UTF-8", true); * * * @access public @@ -1035,7 +1028,7 @@ class XML_Util { * @param string $encoding character encoding * @param boolean $standAlone document is standalone (or not) * @return string $decl xml declaration - * @uses XML_Util::attributesToString() to serialize the attributes of the XML declaration + * @uses PEAR_PackageFile_Generator_v2_XML_Util::attributesToString() to serialize the attributes of the XML declaration */ function getXMLDeclaration($version = "1.0", $encoding = null, $standalone = null) { @@ -1051,7 +1044,7 @@ class XML_Util { $attributes["standalone"] = $standalone ? "yes" : "no"; } - return sprintf("", XML_Util::attributesToString($attributes, false)); + return sprintf("", PEAR_PackageFile_Generator_v2_XML_Util::attributesToString($attributes, false)); } /** @@ -1061,7 +1054,7 @@ class XML_Util { * require_once 'XML/Util.php'; * * // get a doctype declaration: - * $xmlDecl = XML_Util::getDocTypeDeclaration("rootTag","myDocType.dtd"); + * $xmlDecl = PEAR_PackageFile_Generator_v2_XML_Util::getDocTypeDeclaration("rootTag","myDocType.dtd"); * * * @access public @@ -1101,7 +1094,7 @@ class XML_Util { * "argh" => "tomato" * ); * - * $attList = XML_Util::attributesToString($att); + * $attList = PEAR_PackageFile_Generator_v2_XML_Util::attributesToString($att); * * * @access public @@ -1111,12 +1104,12 @@ class XML_Util { * @param boolean $multiline use linebreaks, if more than one attribute is given * @param string $indent string used for indentation of multiline attributes * @param string $linebreak string used for linebreaks of multiline attributes - * @param integer $entities setting for entities in attribute values (one of XML_UTIL_ENTITIES_NONE, XML_UTIL_ENTITIES_XML, XML_UTIL_ENTITIES_XML_REQUIRED, XML_UTIL_ENTITIES_HTML) + * @param integer $entities setting for entities in attribute values (one of PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_NONE, PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML, PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML_REQUIRED, PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_HTML) * @return string string representation of the attributes - * @uses XML_Util::replaceEntities() to replace XML entities in attribute values + * @uses PEAR_PackageFile_Generator_v2_XML_Util::replaceEntities() to replace XML entities in attribute values * @todo allow sort also to be an options array */ - function attributesToString($attributes, $sort = true, $multiline = false, $indent = ' ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML) + function attributesToString($attributes, $sort = true, $multiline = false, $indent = ' ', $linebreak = "\n", $entities = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML) { /** * second parameter may be an array @@ -1147,16 +1140,16 @@ class XML_Util { } if( !$multiline || count($attributes) == 1) { foreach ($attributes as $key => $value) { - if ($entities != XML_UTIL_ENTITIES_NONE) { - $value = XML_Util::replaceEntities($value, $entities); + if ($entities != PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_NONE) { + $value = PEAR_PackageFile_Generator_v2_XML_Util::replaceEntities($value, $entities); } $string .= ' '.$key.'="'.$value.'"'; } } else { $first = true; foreach ($attributes as $key => $value) { - if ($entities != XML_UTIL_ENTITIES_NONE) { - $value = XML_Util::replaceEntities($value, $entities); + if ($entities != PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_NONE) { + $value = PEAR_PackageFile_Generator_v2_XML_Util::replaceEntities($value, $entities); } if ($first) { $string .= " ".$key.'="'.$value.'"'; @@ -1173,14 +1166,14 @@ class XML_Util { /** * create a tag * - * This method will call XML_Util::createTagFromArray(), which + * This method will call PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray(), which * is more flexible. * * * require_once 'XML/Util.php'; * * // create an XML tag: - * $tag = XML_Util::createTag("myNs:myTag", array("foo" => "bar"), "This is inside the tag", "http://www.w3c.org/myNs#"); + * $tag = PEAR_PackageFile_Generator_v2_XML_Util::createTag("myNs:myTag", array("foo" => "bar"), "This is inside the tag", "http://www.w3c.org/myNs#"); * * * @access public @@ -1195,10 +1188,10 @@ class XML_Util { * @param string $linebreak string used for linebreaks * @param string $encoding encoding that should be used to translate content * @return string $string XML tag - * @see XML_Util::createTagFromArray() - * @uses XML_Util::createTagFromArray() to create the tag + * @see PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray() + * @uses PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray() to create the tag */ - function createTag($qname, $attributes = array(), $content = null, $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES, $multiline = false, $indent = "_auto", $linebreak = "\n", $encoding = XML_UTIL_ENTITIES_XML) + function createTag($qname, $attributes = array(), $content = null, $namespaceUri = null, $replaceEntities = PEAR_PackageFile_Generator_v2_XML_Util_REPLACE_ENTITIES, $multiline = false, $indent = "_auto", $linebreak = "\n", $encoding = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML) { $tag = array( "qname" => $qname, @@ -1215,7 +1208,7 @@ class XML_Util { $tag["namespaceUri"] = $namespaceUri; } - return XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $linebreak, $encoding); + return PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $linebreak, $encoding); } /** @@ -1242,7 +1235,7 @@ class XML_Util { * "content" => "I'm inside the tag", * ); * // creating a tag with qualified name and namespaceUri - * $string = XML_Util::createTagFromArray($tag); + * $string = PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray($tag); * * * @access public @@ -1253,18 +1246,18 @@ class XML_Util { * @param string $indent string used to indent attributes (_auto indents attributes so they start at the same column) * @param string $linebreak string used for linebreaks * @return string $string XML tag - * @see XML_Util::createTag() - * @uses XML_Util::attributesToString() to serialize the attributes of the tag - * @uses XML_Util::splitQualifiedName() to get local part and namespace of a qualified name + * @see PEAR_PackageFile_Generator_v2_XML_Util::createTag() + * @uses PEAR_PackageFile_Generator_v2_XML_Util::attributesToString() to serialize the attributes of the tag + * @uses PEAR_PackageFile_Generator_v2_XML_Util::splitQualifiedName() to get local part and namespace of a qualified name */ - function createTagFromArray($tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES, $multiline = false, $indent = "_auto", $linebreak = "\n", $encoding = XML_UTIL_ENTITIES_XML) + function createTagFromArray($tag, $replaceEntities = PEAR_PackageFile_Generator_v2_XML_Util_REPLACE_ENTITIES, $multiline = false, $indent = "_auto", $linebreak = "\n", $encoding = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML) { if (isset($tag["content"]) && !is_scalar($tag["content"])) { - return XML_Util::raiseError( "Supplied non-scalar value as tag content", XML_UTIL_ERROR_NON_SCALAR_CONTENT ); + return PEAR_PackageFile_Generator_v2_XML_Util::raiseError( "Supplied non-scalar value as tag content", PEAR_PackageFile_Generator_v2_XML_Util_ERROR_NON_SCALAR_CONTENT ); } if (!isset($tag['qname']) && !isset($tag['localPart'])) { - return XML_Util::raiseError( 'You must either supply a qualified name (qname) or local tag name (localPart).', XML_UTIL_ERROR_NO_TAG_NAME ); + return PEAR_PackageFile_Generator_v2_XML_Util::raiseError( 'You must either supply a qualified name (qname) or local tag name (localPart).', PEAR_PackageFile_Generator_v2_XML_Util_ERROR_NO_TAG_NAME ); } // if no attributes hav been set, use empty attributes @@ -1282,7 +1275,7 @@ class XML_Util { } // namespace URI is set, but no namespace } elseif (isset($tag["namespaceUri"]) && !isset($tag["namespace"])) { - $parts = XML_Util::splitQualifiedName($tag["qname"]); + $parts = PEAR_PackageFile_Generator_v2_XML_Util::splitQualifiedName($tag["qname"]); $tag["localPart"] = $parts["localPart"]; if (isset($parts["namespace"])) { $tag["namespace"] = $parts["namespace"]; @@ -1307,14 +1300,14 @@ class XML_Util { } // create attribute list - $attList = XML_Util::attributesToString($tag["attributes"], true, $multiline, $indent, $linebreak ); + $attList = PEAR_PackageFile_Generator_v2_XML_Util::attributesToString($tag["attributes"], true, $multiline, $indent, $linebreak ); if (!isset($tag["content"]) || (string)$tag["content"] == '') { $tag = sprintf("<%s%s />", $tag["qname"], $attList); } else { - if ($replaceEntities == XML_UTIL_REPLACE_ENTITIES) { - $tag["content"] = XML_Util::replaceEntities($tag["content"], $encoding); - } elseif ($replaceEntities == XML_UTIL_CDATA_SECTION) { - $tag["content"] = XML_Util::createCDataSection($tag["content"]); + if ($replaceEntities == PEAR_PackageFile_Generator_v2_XML_Util_REPLACE_ENTITIES) { + $tag["content"] = PEAR_PackageFile_Generator_v2_XML_Util::replaceEntities($tag["content"], $encoding); + } elseif ($replaceEntities == PEAR_PackageFile_Generator_v2_XML_Util_CDATA_SECTION) { + $tag["content"] = PEAR_PackageFile_Generator_v2_XML_Util::createCDataSection($tag["content"]); } $tag = sprintf("<%s%s>%s", $tag["qname"], $attList, $tag["content"], $tag["qname"] ); } @@ -1328,7 +1321,7 @@ class XML_Util { * require_once 'XML/Util.php'; * * // create an XML start element: - * $tag = XML_Util::createStartElement("myNs:myTag", array("foo" => "bar") ,"http://www.w3c.org/myNs#"); + * $tag = PEAR_PackageFile_Generator_v2_XML_Util::createStartElement("myNs:myTag", array("foo" => "bar") ,"http://www.w3c.org/myNs#"); * * * @access public @@ -1340,7 +1333,7 @@ class XML_Util { * @param string $indent string used to indent attributes (_auto indents attributes so they start at the same column) * @param string $linebreak string used for linebreaks * @return string $string XML start element - * @see XML_Util::createEndElement(), XML_Util::createTag() + * @see PEAR_PackageFile_Generator_v2_XML_Util::createEndElement(), PEAR_PackageFile_Generator_v2_XML_Util::createTag() */ function createStartElement($qname, $attributes = array(), $namespaceUri = null, $multiline = false, $indent = '_auto', $linebreak = "\n") { @@ -1350,7 +1343,7 @@ class XML_Util { } if ($namespaceUri != null) { - $parts = XML_Util::splitQualifiedName($qname); + $parts = PEAR_PackageFile_Generator_v2_XML_Util::splitQualifiedName($qname); } // check for multiline attributes @@ -1371,7 +1364,7 @@ class XML_Util { } // create attribute list - $attList = XML_Util::attributesToString($attributes, true, $multiline, $indent, $linebreak); + $attList = PEAR_PackageFile_Generator_v2_XML_Util::attributesToString($attributes, true, $multiline, $indent, $linebreak); $element = sprintf("<%s%s>", $qname, $attList); return $element; } @@ -1383,14 +1376,14 @@ class XML_Util { * require_once 'XML/Util.php'; * * // create an XML start element: - * $tag = XML_Util::createEndElement("myNs:myTag"); + * $tag = PEAR_PackageFile_Generator_v2_XML_Util::createEndElement("myNs:myTag"); * * * @access public * @static * @param string $qname qualified tagname (including namespace) * @return string $string XML end element - * @see XML_Util::createStartElement(), XML_Util::createTag() + * @see PEAR_PackageFile_Generator_v2_XML_Util::createStartElement(), PEAR_PackageFile_Generator_v2_XML_Util::createTag() */ function createEndElement($qname) { @@ -1405,7 +1398,7 @@ class XML_Util { * require_once 'XML/Util.php'; * * // create an XML start element: - * $tag = XML_Util::createComment("I am a comment"); + * $tag = PEAR_PackageFile_Generator_v2_XML_Util::createComment("I am a comment"); * * * @access public @@ -1426,7 +1419,7 @@ class XML_Util { * require_once 'XML/Util.php'; * * // create a CData section - * $tag = XML_Util::createCDataSection("I am content."); + * $tag = PEAR_PackageFile_Generator_v2_XML_Util::createCDataSection("I am content."); * * * @access public @@ -1446,7 +1439,7 @@ class XML_Util { * require_once 'XML/Util.php'; * * // split qualified tag - * $parts = XML_Util::splitQualifiedName("xslt:stylesheet"); + * $parts = PEAR_PackageFile_Generator_v2_XML_Util::splitQualifiedName("xslt:stylesheet"); * * the returned array will contain two elements: *
@@ -1491,8 +1484,8 @@ class XML_Util {
     * require_once 'XML/Util.php';
     * 
     * // verify tag name
-    * $result = XML_Util::isValidName("invalidTag?");
-    * if (XML_Util::isError($result)) {
+    * $result = PEAR_PackageFile_Generator_v2_XML_Util::isValidName("invalidTag?");
+    * if (PEAR_PackageFile_Generator_v2_XML_Util::isError($result)) {
     *    print "Invalid XML name: " . $result->getMessage();
     * }
     * 
@@ -1506,20 +1499,20 @@ class XML_Util {
     function isValidName($string)
     {
         // check for invalid chars
-        if (!preg_match("/^[[:alnum:]_\-.]$/", $string{0})) {
-            return XML_Util::raiseError( "XML names may only start with letter or underscore", XML_UTIL_ERROR_INVALID_START );
+        if (!preg_match("/^[[:alnum:]_\-.]\\z/", $string{0})) {
+            return PEAR_PackageFile_Generator_v2_XML_Util::raiseError( "XML names may only start with letter or underscore", PEAR_PackageFile_Generator_v2_XML_Util_ERROR_INVALID_START );
         }
         
         // check for invalid chars
-        if (!preg_match("/^([a-zA-Z_]([a-zA-Z0-9_\-\.]*)?:)?[a-zA-Z_]([a-zA-Z0-9_\-\.]+)?$/", $string)) {
-            return XML_Util::raiseError( "XML names may only contain alphanumeric chars, period, hyphen, colon and underscores", XML_UTIL_ERROR_INVALID_CHARS );
+        if (!preg_match("/^([a-zA-Z_]([a-zA-Z0-9_\-\.]*)?:)?[a-zA-Z_]([a-zA-Z0-9_\-\.]+)?\\z/", $string)) {
+            return PEAR_PackageFile_Generator_v2_XML_Util::raiseError( "XML names may only contain alphanumeric chars, period, hyphen, colon and underscores", PEAR_PackageFile_Generator_v2_XML_Util_ERROR_INVALID_CHARS );
          }
         // XML name is valid
         return true;
     }
 
    /**
-    * replacement for XML_Util::raiseError
+    * replacement for PEAR_PackageFile_Generator_v2_XML_Util::raiseError
     *
     * Avoids the necessity to always require
     * PEAR.php
@@ -1535,5 +1528,4 @@ class XML_Util {
         return PEAR::raiseError($msg, $code);
     }
 }
-//} // if (!class_exists('XML_Util'))
 ?>
\ No newline at end of file
diff --git a/includes/pear/PEAR/PackageFile/Parser/v1.php b/includes/pear/PEAR/PackageFile/Parser/v1.php
index eea8760b..1134dc60 100644
--- a/includes/pear/PEAR/PackageFile/Parser/v1.php
+++ b/includes/pear/PEAR/PackageFile/Parser/v1.php
@@ -13,9 +13,9 @@
  * @category   pear
  * @package    PEAR
  * @author     Greg Beaver 
- * @copyright  1997-2005 The PHP Group
+ * @copyright  1997-2008 The PHP Group
  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
- * @version    CVS: $Id: v1.php,v 1.20 2005/09/25 03:49:00 cellog Exp $
+ * @version    CVS: $Id: v1.php,v 1.27 2008/01/03 20:55:16 cellog Exp $
  * @link       http://pear.php.net/package/PEAR
  * @since      File available since Release 1.4.0a1
  */
@@ -28,7 +28,7 @@ require_once 'PEAR/PackageFile/v1.php';
  * @category   pear
  * @package    PEAR
  * @author     Greg Beaver 
- * @copyright  1997-2005 The PHP Group
+ * @copyright  1997-2008 The PHP Group
  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  * @version    Release: @PEAR-VER@
  * @link       http://pear.php.net/package/PEAR
@@ -66,14 +66,15 @@ class PEAR_PackageFile_Parser_v1
      * @param string contents of package.xml file, version 1.0
      * @return bool success of parsing
      */
-    function parse($data, $file, $archive = false)
+    function &parse($data, $file, $archive = false)
     {
         if (!extension_loaded('xml')) {
             return PEAR::raiseError('Cannot create xml parser for parsing package.xml, no xml extension');
         }
-        $xp = @xml_parser_create();
+        $xp = xml_parser_create();
         if (!$xp) {
-            return PEAR::raiseError('Cannot create xml parser for parsing package.xml');
+            $a = &PEAR::raiseError('Cannot create xml parser for parsing package.xml');
+            return $a;
         }
         xml_set_object($xp, $this);
         xml_set_element_handler($xp, '_element_start_1_0', '_element_end_1_0');
@@ -96,8 +97,9 @@ class PEAR_PackageFile_Parser_v1
             $code = xml_get_error_code($xp);
             $line = xml_get_current_line_number($xp);
             xml_parser_free($xp);
-            return PEAR::raiseError(sprintf("XML error: %s at line %d",
+            $a = &PEAR::raiseError(sprintf("XML error: %s at line %d",
                            $str = xml_error_string($code), $line), 2);
+            return $a;
         }
 
         xml_parser_free($xp);
@@ -132,6 +134,8 @@ class PEAR_PackageFile_Parser_v1
         foreach (explode("\n", $str) as $line) {
             if (substr($line, 0, $indent_len) == $indent) {
                 $data .= substr($line, $indent_len) . "\n";
+            } elseif (trim(substr($line, 0, $indent_len))) {
+                $data .= ltrim($line);
             }
         }
         return $data;
@@ -167,7 +171,7 @@ class PEAR_PackageFile_Parser_v1
                 if (array_key_exists('name', $attribs) && $attribs['name'] != '/') {
                     $attribs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
                         $attribs['name']);
-                    if (strrpos($attribs['name'], '/') == strlen($attribs['name']) - 1) {
+                    if (strrpos($attribs['name'], '/') === strlen($attribs['name']) - 1) {
                         $attribs['name'] = substr($attribs['name'], 0,
                             strlen($attribs['name']) - 1);
                     }
diff --git a/includes/pear/PEAR/PackageFile/Parser/v2.php b/includes/pear/PEAR/PackageFile/Parser/v2.php
index df905553..7cbc5851 100644
--- a/includes/pear/PEAR/PackageFile/Parser/v2.php
+++ b/includes/pear/PEAR/PackageFile/Parser/v2.php
@@ -13,9 +13,9 @@
  * @category   pear
  * @package    PEAR
  * @author     Greg Beaver 
- * @copyright  1997-2005 The PHP Group
+ * @copyright  1997-2008 The PHP Group
  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
- * @version    CVS: $Id: v2.php,v 1.17 2005/09/25 03:49:00 cellog Exp $
+ * @version    CVS: $Id: v2.php,v 1.21 2008/01/03 20:26:37 cellog Exp $
  * @link       http://pear.php.net/package/PEAR
  * @since      File available since Release 1.4.0a1
  */
@@ -29,7 +29,7 @@ require_once 'PEAR/PackageFile/v2.php';
  * @category   pear
  * @package    PEAR
  * @author     Greg Beaver 
- * @copyright  1997-2005 The PHP Group
+ * @copyright  1997-2008 The PHP Group
  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  * @version    Release: @PEAR-VER@
  * @link       http://pear.php.net/package/PEAR
@@ -70,6 +70,8 @@ class PEAR_PackageFile_Parser_v2 extends PEAR_XMLParser
         foreach (explode("\n", $str) as $line) {
             if (substr($line, 0, $indent_len) == $indent) {
                 $data .= substr($line, $indent_len) . "\n";
+            } else {
+                $data .= $line . "\n";
             }
         }
         return $data;
@@ -97,7 +99,7 @@ class PEAR_PackageFile_Parser_v2 extends PEAR_XMLParser
      *               a subclass
      * @return PEAR_PackageFile_v2
      */
-    function parse($data, $file, $archive = false, $class = 'PEAR_PackageFile_v2')
+    function &parse($data, $file, $archive = false, $class = 'PEAR_PackageFile_v2')
     {
         if (PEAR::isError($err = parent::parse($data, $file))) {
             return $err;
diff --git a/includes/pear/PEAR/PackageFile/v1.php b/includes/pear/PEAR/PackageFile/v1.php
index 15e8b116..d2895507 100644
--- a/includes/pear/PEAR/PackageFile/v1.php
+++ b/includes/pear/PEAR/PackageFile/v1.php
@@ -13,9 +13,9 @@
  * @category   pear
  * @package    PEAR
  * @author     Greg Beaver 
- * @copyright  1997-2005 The PHP Group
+ * @copyright  1997-2008 The PHP Group
  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
- * @version    CVS: $Id: v1.php,v 1.67 2005/10/27 05:07:24 cellog Exp $
+ * @version    CVS: $Id: v1.php,v 1.74 2008/01/03 20:26:36 cellog Exp $
  * @link       http://pear.php.net/package/PEAR
  * @since      File available since Release 1.4.0a1
  */
@@ -279,9 +279,9 @@ define('PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME', 52);
  * @category   pear
  * @package    PEAR
  * @author     Greg Beaver 
- * @copyright  1997-2005 The PHP Group
+ * @copyright  1997-2008 The PHP Group
  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
- * @version    Release: 1.4.5
+ * @version    Release: 1.7.2
  * @link       http://pear.php.net/package/PEAR
  * @since      Class available since Release 1.4.0a1
  */
@@ -457,6 +457,9 @@ class PEAR_PackageFile_v1
 
     function setDirtree($path)
     {
+        if (!isset($this->_packageInfo['dirtree'])) {
+            $this->_packageInfo['dirtree'] = array();
+        }
         $this->_packageInfo['dirtree'][$path] = true;
     }
 
@@ -858,6 +861,11 @@ class PEAR_PackageFile_v1
         return false;
     }
 
+    function getProvidesExtension()
+    {
+        return false;
+    }
+
     function addFile($dir, $file, $attrs)
     {
         $dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir);
@@ -1192,14 +1200,33 @@ class PEAR_PackageFile_v1
                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE,
                         array('file' => $file, 'role' => $fa['role'], 'roles' => PEAR_Common::getFileRoles()));
                 }
-                if ($file{0} == '.' && $file{1} == '/') {
+                if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', str_replace('\\', '/', $file))) {
+                    // file contains .. parent directory or . cur directory references
                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
                         array('file' => $file));
                 }
+                if (isset($fa['install-as']) &&
+                      preg_match('~/\.\.?(/|\\z)|^\.\.?/~', 
+                                 str_replace('\\', '/', $fa['install-as']))) {
+                    // install-as contains .. parent directory or . cur directory references
+                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
+                        array('file' => $file . ' [installed as ' . $fa['install-as'] . ']'));
+                }
+                if (isset($fa['baseinstalldir']) &&
+                      preg_match('~/\.\.?(/|\\z)|^\.\.?/~', 
+                                 str_replace('\\', '/', $fa['baseinstalldir']))) {
+                    // install-as contains .. parent directory or . cur directory references
+                    $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
+                        array('file' => $file . ' [baseinstalldir ' . $fa['baseinstalldir'] . ']'));
+                }
             }
         }
         if (isset($this->_registry) && $this->_isValid) {
             $chan = $this->_registry->getChannel('pear.php.net');
+            if (PEAR::isError($chan)) {
+                $this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $chan->getMessage());
+                return $this->_isValid = 0;
+            }
             $validator = $chan->getValidationObject();
             $validator->setPackageFile($this);
             $validator->validate($state);
@@ -1349,13 +1376,8 @@ class PEAR_PackageFile_v1
         if (!$fp = @fopen($file, "r")) {
             return false;
         }
-        if (function_exists('file_get_contents')) {
-            fclose($fp);
-            $contents = file_get_contents($file);
-        } else {
-            $contents = @fread($fp, filesize($file));
-            fclose($fp);
-        }
+        fclose($fp);
+        $contents = file_get_contents($file);
         $tokens = token_get_all($contents);
 /*
         for ($i = 0; $i < sizeof($tokens); $i++) {
diff --git a/includes/pear/PEAR/PackageFile/v2.php b/includes/pear/PEAR/PackageFile/v2.php
index 12e119e8..4638a77f 100644
--- a/includes/pear/PEAR/PackageFile/v2.php
+++ b/includes/pear/PEAR/PackageFile/v2.php
@@ -13,9 +13,9 @@
  * @category   pear
  * @package    PEAR
  * @author     Greg Beaver 
- * @copyright  1997-2005 The PHP Group
+ * @copyright  1997-2008 The PHP Group
  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
- * @version    CVS: $Id: v2.php,v 1.120 2005/11/14 14:06:17 cellog Exp $
+ * @version    CVS: $Id: v2.php,v 1.143 2008/05/13 05:28:51 cellog Exp $
  * @link       http://pear.php.net/package/PEAR
  * @since      File available since Release 1.4.0a1
  */
@@ -27,9 +27,9 @@ require_once 'PEAR/ErrorStack.php';
  * @category   pear
  * @package    PEAR
  * @author     Greg Beaver 
- * @copyright  1997-2005 The PHP Group
+ * @copyright  1997-2008 The PHP Group
  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
- * @version    Release: 1.4.5
+ * @version    Release: 1.7.2
  * @link       http://pear.php.net/package/PEAR
  * @since      Class available since Release 1.4.0a1
  */
@@ -121,12 +121,17 @@ class PEAR_PackageFile_v2
      *
      * - package name
      * - channel name
-     * - dependencies 
+     * - dependencies
      * @var boolean
      * @access private
      */
     var $_incomplete = true;
 
+    /**
+     * @var PEAR_PackageFile_v2_Validator
+     */
+    var $_v2Validator;
+
     /**
      * The constructor merely sets up the private error stack
      */
@@ -186,23 +191,24 @@ class PEAR_PackageFile_v2
             $a = false;
             return $a;
         }
-        if ($this->getPackageType() == 'extsrc') {
+        if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
+            $releasetype = $this->getPackageType() . 'release';
             if (!is_array($installer->getInstallPackages())) {
                 $a = false;
                 return $a;
             }
             foreach ($installer->getInstallPackages() as $p) {
                 if ($p->isExtension($this->_packageInfo['providesextension'])) {
-                    if ($p->getPackageType() != 'extsrc') {
+                    if ($p->getPackageType() != 'extsrc' && $p->getPackageType() != 'zendextsrc') {
                         $a = false;
                         return $a; // the user probably downloaded it separately
                     }
                 }
             }
-            if (isset($this->_packageInfo['extsrcrelease']['binarypackage'])) {
+            if (isset($this->_packageInfo[$releasetype]['binarypackage'])) {
                 $installer->log(0, 'Attempting to download binary version of extension "' .
                     $this->_packageInfo['providesextension'] . '"');
-                $params = $this->_packageInfo['extsrcrelease']['binarypackage'];
+                $params = $this->_packageInfo[$releasetype]['binarypackage'];
                 if (!is_array($params) || !isset($params[0])) {
                     $params = array($params);
                 }
@@ -259,7 +265,8 @@ class PEAR_PackageFile_v2
      */
     function getProvidesExtension()
     {
-        if (in_array($this->getPackageType(), array('extsrc', 'extbin'))) {
+        if (in_array($this->getPackageType(),
+              array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
             if (isset($this->_packageInfo['providesextension'])) {
                 return $this->_packageInfo['providesextension'];
             }
@@ -273,7 +280,8 @@ class PEAR_PackageFile_v2
      */
     function isExtension($extension)
     {
-        if (in_array($this->getPackageType(), array('extsrc', 'extbin'))) {
+        if (in_array($this->getPackageType(),
+              array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
             return $this->_packageInfo['providesextension'] == $extension;
         }
         return false;
@@ -465,6 +473,9 @@ class PEAR_PackageFile_v2
      */
     function setRawState($state)
     {
+        if (!isset($this->_packageInfo['stability'])) {
+            $this->_packageInfo['stability'] = array();
+        }
         $this->_packageInfo['stability']['release'] = $state;
     }
 
@@ -598,6 +609,10 @@ class PEAR_PackageFile_v2
         $common->debug = $this->_config->get('verbose');
         $this->_scripts = array();
         foreach ($taskfiles as $name => $tasks) {
+            if (!isset($filelist[$name])) {
+                // file was not installed due to installconditions
+                continue;
+            }
             $atts = $filelist[$name];
             foreach ($tasks as $tag => $raw) {
                 $taskname = $this->getTask($tag);
@@ -658,12 +673,17 @@ class PEAR_PackageFile_v2
             if (isset($this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'])) {
                 if (isset($this->_packageInfo['contents']['dir']['file'][0])) {
                     foreach ($this->_packageInfo['contents']['dir']['file'] as $i => $file) {
+                        if (isset($file['attribs']['baseinstalldir'])) {
+                            continue;
+                        }
                         $this->_packageInfo['contents']['dir']['file'][$i]['attribs']['baseinstalldir']
                             = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'];
                     }
                 } else {
-                    $this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir']
-                        = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'];
+                    if (!isset($this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir'])) {
+                       $this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir']
+                            = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'];
+                    }
                 }
             }
         }
@@ -705,7 +725,7 @@ class PEAR_PackageFile_v2
             foreach ($dir['file'] as $file) {
                 $attrs = $file['attribs'];
                 $name = $attrs['name'];
-                if ($baseinstall) {
+                if ($baseinstall && !isset($attrs['baseinstalldir'])) {
                     $attrs['baseinstalldir'] = $baseinstall;
                 }
                 $attrs['name'] = empty($path) ? $name : $path . '/' . $name;
@@ -725,7 +745,7 @@ class PEAR_PackageFile_v2
 
     function setLogger(&$logger)
     {
-        if ($logger && (!is_object($logger) || !method_exists($logger, 'log'))) {
+        if (!is_object($logger) || !method_exists($logger, 'log')) {
             return PEAR::raiseError('Logger must be compatible with PEAR_Common::log');
         }
         $this->_logger = &$logger;
@@ -739,6 +759,14 @@ class PEAR_PackageFile_v2
         $this->_packageInfo['dependencies'] = $deps;
     }
 
+    /**
+     * WARNING - do not use this function directly unless you know what you're doing
+     */
+    function setCompatible($compat)
+    {
+        $this->_packageInfo['compatible'] = $compat;
+    }
+
     function setPackagefile($file, $archive = false)
     {
         $this->_packageFile = $file;
@@ -909,7 +937,7 @@ class PEAR_PackageFile_v2
 
     function getMaintainers($raw = false)
     {
-        if (!$this->_isValid && !$this->validate()) {
+        if (!isset($this->_packageInfo['lead'])) {
             return false;
         }
         if ($raw) {
@@ -1013,8 +1041,8 @@ class PEAR_PackageFile_v2
                 array('time', 'version',
                     'stability', 'license', 'notes', 'contents', 'compatible',
                     'dependencies', 'providesextension', 'srcpackage', 'srcuri',
-                    'phprelease', 'extsrcrelease',
-                    'extbinrelease', 'bundle', 'changelog'), array(), 'date');
+                    'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease',
+                    'zendextbinrelease', 'bundle', 'changelog'), array(), 'date');
         }
         $this->_packageInfo['date'] = $date;
         $this->_isValid = 0;
@@ -1029,8 +1057,8 @@ class PEAR_PackageFile_v2
                     array('version',
                     'stability', 'license', 'notes', 'contents', 'compatible',
                     'dependencies', 'providesextension', 'srcpackage', 'srcuri',
-                    'phprelease', 'extsrcrelease',
-                    'extbinrelease', 'bundle', 'changelog'), $time, 'time');
+                    'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease',
+                    'zendextbinrelease', 'bundle', 'changelog'), $time, 'time');
         }
         $this->_packageInfo['time'] = $time;
     }
@@ -1144,6 +1172,9 @@ class PEAR_PackageFile_v2
         $this->flattenFilelist();
         if ($contents = $this->getContents()) {
             $ret = array();
+            if (!isset($contents['dir'])) {
+                return false;
+            }
             if (!isset($contents['dir']['file'][0])) {
                 $contents['dir']['file'] = array($contents['dir']['file']);
             }
@@ -1169,12 +1200,12 @@ class PEAR_PackageFile_v2
      */
     function getConfigureOptions()
     {
-        if ($this->getPackageType() != 'extsrc') {
+        if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
             return false;
         }
         $releases = $this->getReleases();
         if (isset($releases[0])) {
-            $releases = $release[0];
+            $releases = $releases[0];
         }
         if (isset($releases['configureoption'])) {
             if (!isset($releases['configureoption'][0])) {
@@ -1378,6 +1409,9 @@ class PEAR_PackageFile_v2
 
     function setDirtree($path)
     {
+        if (!isset($this->_packageInfo['dirtree'])) {
+            $this->_packageInfo['dirtree'] = array();
+        }
         $this->_packageInfo['dirtree'][$path] = true;
     }
 
@@ -1535,7 +1569,7 @@ class PEAR_PackageFile_v2
                         if (strtolower($dep['name']) == strtolower($package) &&
                               $depchannel == $channel) {
                             return true;
-                        }  
+                        }
                     }
                 }
             }
@@ -1553,7 +1587,7 @@ class PEAR_PackageFile_v2
                             if (strtolower($dep['name']) == strtolower($package) &&
                                   $depchannel == $channel) {
                                 return true;
-                            }  
+                            }
                         }
                     }
                 }
@@ -1613,7 +1647,8 @@ class PEAR_PackageFile_v2
                 );
             foreach (array('required', 'optional') as $type) {
                 $optional = ($type == 'optional') ? 'yes' : 'no';
-                if (!isset($this->_packageInfo['dependencies'][$type])) {
+                if (!isset($this->_packageInfo['dependencies'][$type])
+                    || empty($this->_packageInfo['dependencies'][$type])) {
                     continue;
                 }
                 foreach ($this->_packageInfo['dependencies'][$type] as $dtype => $deps) {
@@ -1648,6 +1683,7 @@ class PEAR_PackageFile_v2
                             if (!isset($dep['min']) &&
                                   !isset($dep['max'])) {
                                 $s['rel'] = 'has';
+                                $s['optional'] = $optional;
                             } elseif (isset($dep['min']) &&
                                   isset($dep['max'])) {
                                 $s['rel'] = 'ge';
@@ -1666,14 +1702,24 @@ class PEAR_PackageFile_v2
                                 $s1['optional'] = $optional;
                                 $ret[] = $s1;
                             } elseif (isset($dep['min'])) {
-                                $s['rel'] = 'ge';
+                                if (isset($dep['exclude']) &&
+                                      $dep['exclude'] == $dep['min']) {
+                                    $s['rel'] = 'gt';
+                                } else {
+                                    $s['rel'] = 'ge';
+                                }
                                 $s['version'] = $dep['min'];
                                 $s['optional'] = $optional;
                                 if ($dtype != 'php') {
                                     $s['name'] = $dep['name'];
                                 }
                             } elseif (isset($dep['max'])) {
-                                $s['rel'] = 'le';
+                                if (isset($dep['exclude']) &&
+                                      $dep['exclude'] == $dep['max']) {
+                                    $s['rel'] = 'lt';
+                                } else {
+                                    $s['rel'] = 'le';
+                                }
                                 $s['version'] = $dep['max'];
                                 $s['optional'] = $optional;
                                 if ($dtype != 'php') {
@@ -1693,7 +1739,7 @@ class PEAR_PackageFile_v2
     }
 
     /**
-     * @return php|extsrc|extbin|bundle|false
+     * @return php|extsrc|extbin|zendextsrc|zendextbin|bundle|false
      */
     function getPackageType()
     {
@@ -1706,6 +1752,12 @@ class PEAR_PackageFile_v2
         if (isset($this->_packageInfo['extbinrelease'])) {
             return 'extbin';
         }
+        if (isset($this->_packageInfo['zendextsrcrelease'])) {
+            return 'zendextsrc';
+        }
+        if (isset($this->_packageInfo['zendextbinrelease'])) {
+            return 'zendextbin';
+        }
         if (isset($this->_packageInfo['bundle'])) {
             return 'bundle';
         }
@@ -1745,6 +1797,12 @@ class PEAR_PackageFile_v2
 
     function getPackagexmlVersion()
     {
+        if (isset($this->_packageInfo['zendextsrcrelease'])) {
+            return '2.1';
+        }
+        if (isset($this->_packageInfo['zendextbinrelease'])) {
+            return '2.1';
+        }
         return '2.0';
     }
 
@@ -1753,7 +1811,8 @@ class PEAR_PackageFile_v2
      */
     function getSourcePackage()
     {
-        if (isset($this->_packageInfo['extbinrelease'])) {
+        if (isset($this->_packageInfo['extbinrelease']) ||
+              isset($this->_packageInfo['zendextbinrelease'])) {
             return array('channel' => $this->_packageInfo['srcchannel'],
                          'package' => $this->_packageInfo['srcpackage']);
         }
@@ -1837,7 +1896,8 @@ class PEAR_PackageFile_v2
 
     function analyzeSourceCode($file, $string = false)
     {
-        if (!isset($this->_v2Validator)) {
+        if (!isset($this->_v2Validator) ||
+              !is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) {
             if (!class_exists('PEAR_PackageFile_v2_Validator')) {
                 require_once 'PEAR/PackageFile/v2/Validator.php';
             }
@@ -1851,7 +1911,8 @@ class PEAR_PackageFile_v2
         if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) {
             return false;
         }
-        if (!isset($this->_v2Validator)) {
+        if (!isset($this->_v2Validator) ||
+              !is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) {
             if (!class_exists('PEAR_PackageFile_v2_Validator')) {
                 require_once 'PEAR/PackageFile/v2/Validator.php';
             }
@@ -1893,16 +1954,16 @@ class PEAR_PackageFile_v2
         $this->getTasksNs();
         // transform all '-' to '/' and 'tasks:' to '' so tasks:replace becomes replace
         $task = str_replace(array($this->_tasksNs . ':', '-'), array('', ' '), $task);
-        $task = str_replace(' ', '/', ucwords($task));
-        $ps = (strtolower(substr(PHP_OS, 0, 3)) == 'win') ? ';' : ':';
-        foreach (explode($ps, ini_get('include_path')) as $path) {
-            if (file_exists($path . "/PEAR/Task/$task.php")) {
-                include_once "PEAR/Task/$task.php";
-                $task = str_replace('/', '_', $task);
-                if (class_exists("PEAR_Task_$task")) {
-                    return "PEAR_Task_$task";
-                }
-            }
+        $taskfile = str_replace(' ', '/', ucwords($task));
+        $task = str_replace(array(' ', '/'), '_', ucwords($task));
+        if (class_exists("PEAR_Task_$task")) {
+            return "PEAR_Task_$task";
+        }
+        $fp = @fopen("PEAR/Task/$taskfile.php", 'r', true);
+        if ($fp) {
+            fclose($fp);
+            require_once "PEAR/Task/$taskfile.php";
+            return "PEAR_Task_$task";
         }
         return false;
     }
diff --git a/includes/pear/PEAR/PackageFile/v2/Validator.php b/includes/pear/PEAR/PackageFile/v2/Validator.php
index 4db03546..10efbbb6 100644
--- a/includes/pear/PEAR/PackageFile/v2/Validator.php
+++ b/includes/pear/PEAR/PackageFile/v2/Validator.php
@@ -1,27 +1,35 @@
                                  |
-// |                                                                      |
-// +----------------------------------------------------------------------+
-//
-// $Id: Validator.php,v 1.82 2005/10/27 05:07:24 cellog Exp $
+/**
+ * PEAR_PackageFile_v2, package.xml version 2.0, read/write version
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.0 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * 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 web, please
+ * send a note to license@php.net so we can mail you a copy immediately.
+ *
+ * @category   pear
+ * @package    PEAR
+ * @author     Greg Beaver 
+ * @copyright  1997-2008 The PHP Group
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version    CVS: $Id: Validator.php,v 1.106 2008/03/28 22:23:41 dufuz Exp $
+ * @link       http://pear.php.net/package/PEAR
+ * @since      File available since Release 1.4.0a8
+ */
 /**
  * Private validation class used by PEAR_PackageFile_v2 - do not use directly, its
  * sole purpose is to split up the PEAR/PackageFile/v2.php file to make it smaller
- * @author Greg Beaver 
+ * @category   pear
+ * @package    PEAR
+ * @author     Greg Beaver 
+ * @copyright  1997-2008 The PHP Group
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version    Release: 1.7.2
+ * @link       http://pear.php.net/package/PEAR
+ * @since      Class available since Release 1.4.0a8
  * @access private
  */
 class PEAR_PackageFile_v2_Validator
@@ -42,6 +50,10 @@ class PEAR_PackageFile_v2_Validator
      * @var int
      */
     var $_isValid = 0;
+    /**
+     * @var int
+     */
+    var $_filesValid = 0;
     /**
      * @var int
      */
@@ -66,7 +78,9 @@ class PEAR_PackageFile_v2_Validator
             return false;
         }
         if (!isset($this->_packageInfo['attribs']['version']) ||
-              $this->_packageInfo['attribs']['version'] != '2.0') {
+              ($this->_packageInfo['attribs']['version'] != '2.0' &&
+               $this->_packageInfo['attribs']['version'] != '2.1')
+        ) {
             $this->_noPackageVersion();
         }
         $structure =
@@ -95,10 +109,21 @@ class PEAR_PackageFile_v2_Validator
                          // needs a certain package installed in order to implement a role or task
             '*providesextension',
             '*srcpackage|*srcuri',
-            '+phprelease|+extsrcrelease|+extbinrelease|bundle', //special validation needed
+            '+phprelease|+extsrcrelease|+extbinrelease|' .
+                '+zendextsrcrelease|+zendextbinrelease|bundle', //special validation needed
             '*changelog',
         );
         $test = $this->_packageInfo;
+        if (isset($test['dependencies']) &&
+              isset($test['dependencies']['required']) &&
+              isset($test['dependencies']['required']['pearinstaller']) &&
+              isset($test['dependencies']['required']['pearinstaller']['min']) &&
+              version_compare('1.7.2',
+                $test['dependencies']['required']['pearinstaller']['min'], '<')
+        ) {
+            $this->_pearVersionTooLow($test['dependencies']['required']['pearinstaller']['min']);
+            return false;
+        }
         // ignore post-installation array fields
         if (array_key_exists('filelist', $test)) {
             unset($test['filelist']);
@@ -115,18 +140,13 @@ class PEAR_PackageFile_v2_Validator
         if (array_key_exists('_lastversion', $test)) {
             unset($test['_lastversion']);
         }
-        if (!$this->_stupidSchemaValidate($structure,
-                                          $test, '')) {
+        if (!$this->_stupidSchemaValidate($structure, $test, '')) {
             return false;
         }
         if (empty($this->_packageInfo['name'])) {
             $this->_tagCannotBeEmpty('name');
         }
-        if (isset($this->_packageInfo['uri'])) {
-            $test = 'uri';
-        } else {
-            $test = 'channel';
-        }
+        $test = isset($this->_packageInfo['uri']) ? 'uri' :'channel';
         if (empty($this->_packageInfo[$test])) {
             $this->_tagCannotBeEmpty($test);
         }
@@ -159,6 +179,9 @@ class PEAR_PackageFile_v2_Validator
             $this->_validateCompatible();
         }
         if (!isset($this->_packageInfo['bundle'])) {
+            if (empty($this->_packageInfo['contents'])) {
+                $this->_tagCannotBeEmpty('contents');
+            }
             if (!isset($this->_packageInfo['contents']['dir'])) {
                 $this->_filelistMustContainDir('contents');
                 return false;
@@ -218,11 +241,16 @@ class PEAR_PackageFile_v2_Validator
         if ($fail) {
             return false;
         }
+        $list = $this->_packageInfo['contents'];
+        if (isset($list['dir']) && is_array($list['dir']) && isset($list['dir'][0])) {
+            $this->_multipleToplevelDirNotAllowed();
+            return $this->_isValid = 0;
+        }
         $this->_validateFilelist();
         $this->_validateRelease();
         if (!$this->_stack->hasErrors()) {
             $chan = $this->_pf->_registry->getChannel($this->_pf->getChannel(), true);
-            if (!$chan) {
+            if (PEAR::isError($chan)) {
                 $this->_unknownChannel($this->_pf->getChannel());
             } else {
                 $valpack = $chan->getValidationPackage();
@@ -417,6 +445,7 @@ class PEAR_PackageFile_v2_Validator
     {
         $ret = array();
         if (count($pieces = explode('|', $key)) > 1) {
+            $ret['choices'] = array();
             foreach ($pieces as $piece) {
                 $ret['choices'][] = $this->_processStructure($piece);
             }
@@ -442,21 +471,21 @@ class PEAR_PackageFile_v2_Validator
         $a = $this->_stupidSchemaValidate($structure, $this->_packageInfo['version'], '');
         $a &= $this->_stupidSchemaValidate($structure, $this->_packageInfo['stability'], '');
         if ($a) {
-            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
+            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   $this->_packageInfo['version']['release'])) {
                 $this->_invalidVersion('release', $this->_packageInfo['version']['release']);
             }
-            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
+            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   $this->_packageInfo['version']['api'])) {
                 $this->_invalidVersion('api', $this->_packageInfo['version']['api']);
             }
             if (!in_array($this->_packageInfo['stability']['release'],
                   array('snapshot', 'devel', 'alpha', 'beta', 'stable'))) {
-                $this->_invalidState('release', $this->_packageinfo['stability']['release']);
+                $this->_invalidState('release', $this->_packageInfo['stability']['release']);
             }
             if (!in_array($this->_packageInfo['stability']['api'],
                   array('devel', 'alpha', 'beta', 'stable'))) {
-                $this->_invalidState('api', $this->_packageinfo['stability']['api']);
+                $this->_invalidState('api', $this->_packageInfo['stability']['api']);
             }
         }
     }
@@ -495,17 +524,29 @@ class PEAR_PackageFile_v2_Validator
         $type = $installcondition ? '' : '';
         $this->_stupidSchemaValidate($structure, $dep, $type);
         if (isset($dep['min'])) {
-            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?$/',
+            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
                   $dep['min'])) {
                 $this->_invalidVersion($type . '', $dep['min']);
             }
         }
         if (isset($dep['max'])) {
-            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?$/',
+            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
                   $dep['max'])) {
                 $this->_invalidVersion($type . '', $dep['max']);
             }
         }
+        if (isset($dep['exclude'])) {
+            if (!is_array($dep['exclude'])) {
+                $dep['exclude'] = array($dep['exclude']);
+            }
+            foreach ($dep['exclude'] as $exclude) {
+                if (!preg_match(
+                     '/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
+                     $exclude)) {
+                    $this->_invalidVersion($type . '', $exclude);
+                }
+            }
+        }
     }
 
     function _validatePearinstallerDep($dep)
@@ -518,21 +559,21 @@ class PEAR_PackageFile_v2_Validator
         );
         $this->_stupidSchemaValidate($structure, $dep, '');
         if (isset($dep['min'])) {
-            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
+            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   $dep['min'])) {
                 $this->_invalidVersion('',
                     $dep['min']);
             }
         }
         if (isset($dep['max'])) {
-            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
+            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   $dep['max'])) {
                 $this->_invalidVersion('',
                     $dep['max']);
             }
         }
         if (isset($dep['recommended'])) {
-            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
+            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   $dep['recommended'])) {
                 $this->_invalidVersion('',
                     $dep['recommended']);
@@ -543,7 +584,7 @@ class PEAR_PackageFile_v2_Validator
                 $dep['exclude'] = array($dep['exclude']);
             }
             foreach ($dep['exclude'] as $exclude) {
-                if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
+                if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                       $exclude)) {
                     $this->_invalidVersion('',
                         $exclude);
@@ -605,19 +646,19 @@ class PEAR_PackageFile_v2_Validator
             $this->_DepchannelCannotBeUri('' . $group . $type);
         }
         if (isset($dep['min'])) {
-            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
+            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   $dep['min'])) {
                 $this->_invalidVersion('' . $group . $type . '', $dep['min']);
             }
         }
         if (isset($dep['max'])) {
-            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
+            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   $dep['max'])) {
                 $this->_invalidVersion('' . $group . $type . '', $dep['max']);
             }
         }
         if (isset($dep['recommended'])) {
-            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
+            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   $dep['recommended'])) {
                 $this->_invalidVersion('' . $group . $type . '',
                     $dep['recommended']);
@@ -628,7 +669,7 @@ class PEAR_PackageFile_v2_Validator
                 $dep['exclude'] = array($dep['exclude']);
             }
             foreach ($dep['exclude'] as $exclude) {
-                if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
+                if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                       $exclude)) {
                     $this->_invalidVersion('' . $group . $type . '',
                         $exclude);
@@ -641,10 +682,10 @@ class PEAR_PackageFile_v2_Validator
     {
         $this->_validatePackageDep($dep, $group, '');
         if (isset($dep['providesextension'])) {
-            $this->_subpackageCannotProvideExtension(@$dep['name']);
+            $this->_subpackageCannotProvideExtension(isset($dep['name']) ? $dep['name'] : '');
         }
         if (isset($dep['conflicts'])) {
-            $this->_subpackagesCannotConflict(@$dep['name']);
+            $this->_subpackagesCannotConflict(isset($dep['name']) ? $dep['name'] : '');
         }
     }
 
@@ -677,19 +718,19 @@ class PEAR_PackageFile_v2_Validator
         }
         $this->_stupidSchemaValidate($structure, $dep, $type);
         if (isset($dep['min'])) {
-            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
+            if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   $dep['min'])) {
                 $this->_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '_stupidSchemaValidate($required, $package, $type);
             if (is_array($package) && array_key_exists('min', $package)) {
-                if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
+                if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                       $package['min'])) {
                     $this->_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '' : $unknown;
         } else {
             $dirname = '';
+            if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
+                          str_replace('\\', '/', $list['attribs']['name']))) {
+                // file contains .. parent directory or . cur directory
+                $this->_invalidDirName($list['attribs']['name']);
+            }
         }
         $res = $this->_stupidSchemaValidate($struc, $list, $dirname);
         if ($allowignore && $res) {
+            $ignored_or_installed = array();
             $this->_pf->getFilelist();
             $fcontents = $this->_pf->getContents();
             $filelist = array();
@@ -990,6 +1037,20 @@ class PEAR_PackageFile_v2_Validator
                 foreach ($list['install'] as $file) {
                     if (!isset($filelist[$file['attribs']['name']])) {
                         $this->_notInContents($file['attribs']['name'], 'install');
+                        continue;
+                    }
+                    if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) {
+                        $this->_multipleInstallAs($file['attribs']['name']);
+                    }
+                    if (!isset($ignored_or_installed[$file['attribs']['name']])) {
+                        $ignored_or_installed[$file['attribs']['name']] = array();
+                    }
+                    $ignored_or_installed[$file['attribs']['name']][] = 1;
+                    if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
+                                  str_replace('\\', '/', $file['attribs']['as']))) {
+                        // file contains .. parent directory or . cur directory references
+                        $this->_invalidFileInstallAs($file['attribs']['name'],
+                            $file['attribs']['as']);
                     }
                 }
             }
@@ -1000,22 +1061,36 @@ class PEAR_PackageFile_v2_Validator
                 foreach ($list['ignore'] as $file) {
                     if (!isset($filelist[$file['attribs']['name']])) {
                         $this->_notInContents($file['attribs']['name'], 'ignore');
+                        continue;
+                    }
+                    if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) {
+                        $this->_ignoreAndInstallAs($file['attribs']['name']);
                     }
                 }
             }
         }
         if (!$allowignore && isset($list['file'])) {
+            if (is_string($list['file'])) {
+                $this->_oldStyleFileNotAllowed();
+                return false;
+            }
             if (!isset($list['file'][0])) {
                 // single file
                 $list['file'] = array($list['file']);
             }
             foreach ($list['file'] as $i => $file)
             {
-                if (isset($file['attribs']) && isset($file['attribs']['name']) &&
-                      $file['attribs']['name']{0} == '.' &&
-                        $file['attribs']['name']{1} == '/') {
-                    // name is something like "./doc/whatever.txt"
-                    $this->_invalidFileName($file['attribs']['name']);
+                if (isset($file['attribs']) && isset($file['attribs']['name'])) {
+                    if ($file['attribs']['name']{0} == '.' &&
+                          $file['attribs']['name']{1} == '/') {
+                        // name is something like "./doc/whatever.txt"
+                        $this->_invalidFileName($file['attribs']['name'], $dirname);
+                    }
+                    if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
+                                  str_replace('\\', '/', $file['attribs']['name']))) {
+                        // file contains .. parent directory or . cur directory
+                        $this->_invalidFileName($file['attribs']['name'], $dirname);
+                    }
                 }
                 if (isset($file['attribs']) && isset($file['attribs']['role'])) {
                     if (!$this->_validateRole($file['attribs']['role'])) {
@@ -1064,7 +1139,8 @@ class PEAR_PackageFile_v2_Validator
                                 $ret = call_user_func(array($tagClass, 'validateXml'),
                                     $this->_pf, $v, $this->_pf->_config, $save);
                                 if (is_array($ret)) {
-                                    $this->_invalidTask($task, $ret, @$save['name']);
+                                    $this->_invalidTask($task, $ret, isset($save['name']) ?
+                                        $save['name'] : '');
                                 }
                             }
                         } else {
@@ -1164,64 +1240,68 @@ class PEAR_PackageFile_v2_Validator
                 ), $rel, '');
             }
         }
-        if (isset($this->_packageInfo['extsrcrelease'])) {
-            $release = 'extsrcrelease';
-            if (!isset($this->_packageInfo['providesextension'])) {
-                $this->_mustProvideExtension($release);
-            }
-            if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
-                $this->_cannotHaveSrcpackage($release);
-            }
-            $releases = $this->_packageInfo['extsrcrelease'];
-            if (!is_array($releases)) {
-                return true;
-            }
-            if (!isset($releases[0])) {
-                $releases = array($releases);
-            }
-            foreach ($releases as $rel) {
-                $this->_stupidSchemaValidate(array(
-                    '*installconditions',
-                    '*configureoption->name->prompt->?default',
-                    '*binarypackage',
-                    '*filelist',
-                ), $rel, '');
-                if (isset($rel['binarypackage'])) {
-                    if (!is_array($rel['binarypackage']) || !isset($rel['binarypackage'][0])) {
-                        $rel['binarypackage'] = array($rel['binarypackage']);
-                    }
-                    foreach ($rel['binarypackage'] as $bin) {
-                        if (!is_string($bin)) {
-                            $this->_binaryPackageMustBePackagename();
+        foreach (array('', 'zend') as $prefix) {
+            $releasetype = $prefix . 'extsrcrelease';
+            if (isset($this->_packageInfo[$releasetype])) {
+                $release = $releasetype;
+                if (!isset($this->_packageInfo['providesextension'])) {
+                    $this->_mustProvideExtension($release);
+                }
+                if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
+                    $this->_cannotHaveSrcpackage($release);
+                }
+                $releases = $this->_packageInfo[$releasetype];
+                if (!is_array($releases)) {
+                    return true;
+                }
+                if (!isset($releases[0])) {
+                    $releases = array($releases);
+                }
+                foreach ($releases as $rel) {
+                    $this->_stupidSchemaValidate(array(
+                        '*installconditions',
+                        '*configureoption->name->prompt->?default',
+                        '*binarypackage',
+                        '*filelist',
+                    ), $rel, '<' . $releasetype . '>');
+                    if (isset($rel['binarypackage'])) {
+                        if (!is_array($rel['binarypackage']) || !isset($rel['binarypackage'][0])) {
+                            $rel['binarypackage'] = array($rel['binarypackage']);
+                        }
+                        foreach ($rel['binarypackage'] as $bin) {
+                            if (!is_string($bin)) {
+                                $this->_binaryPackageMustBePackagename();
+                            }
                         }
                     }
                 }
             }
-        }
-        if (isset($this->_packageInfo['extbinrelease'])) {
-            $release = 'extbinrelease';
-            if (!isset($this->_packageInfo['providesextension'])) {
-                $this->_mustProvideExtension($release);
-            }
-            if (isset($this->_packageInfo['channel']) &&
-                  !isset($this->_packageInfo['srcpackage'])) {
-                $this->_mustSrcPackage($release);
-            }
-            if (isset($this->_packageInfo['uri']) && !isset($this->_packageInfo['srcuri'])) {
-                $this->_mustSrcuri($release);
-            }
-            $releases = $this->_packageInfo['extbinrelease'];
-            if (!is_array($releases)) {
-                return true;
-            }
-            if (!isset($releases[0])) {
-                $releases = array($releases);
-            }
-            foreach ($releases as $rel) {
-                $this->_stupidSchemaValidate(array(
-                    '*installconditions',
-                    '*filelist',
-                ), $rel, '');
+            $releasetype = 'extbinrelease';
+            if (isset($this->_packageInfo[$releasetype])) {
+                $release = $releasetype;
+                if (!isset($this->_packageInfo['providesextension'])) {
+                    $this->_mustProvideExtension($release);
+                }
+                if (isset($this->_packageInfo['channel']) &&
+                      !isset($this->_packageInfo['srcpackage'])) {
+                    $this->_mustSrcPackage($release);
+                }
+                if (isset($this->_packageInfo['uri']) && !isset($this->_packageInfo['srcuri'])) {
+                    $this->_mustSrcuri($release);
+                }
+                $releases = $this->_packageInfo[$releasetype];
+                if (!is_array($releases)) {
+                    return true;
+                }
+                if (!isset($releases[0])) {
+                    $releases = array($releases);
+                }
+                foreach ($releases as $rel) {
+                    $this->_stupidSchemaValidate(array(
+                        '*installconditions',
+                        '*filelist',
+                    ), $rel, '<' . $releasetype . '>');
+                }
             }
         }
         if (isset($this->_packageInfo['bundle'])) {
@@ -1250,7 +1330,7 @@ class PEAR_PackageFile_v2_Validator
             }
             if (is_array($rel) && array_key_exists('filelist', $rel)) {
                 if ($rel['filelist']) {
-                    
+
                     $this->_validateFilelist($rel['filelist'], true);
                 }
             }
@@ -1266,6 +1346,14 @@ class PEAR_PackageFile_v2_Validator
         return in_array($role, PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType()));
     }
 
+    function _pearVersionTooLow($version)
+    {
+        $this->_stack->push(__FUNCTION__, 'error',
+            array('version' => $version),
+            'This package.xml requires PEAR version %version% to parse properly, we are ' .
+            'version 1.7.2');
+    }
+
     function _invalidTagOrder($oktags, $actual, $root)
     {
         $this->_stack->push(__FUNCTION__, 'error',
@@ -1277,7 +1365,7 @@ class PEAR_PackageFile_v2_Validator
     {
         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
             '<%type%> is not allowed inside global , only inside ' .
-            '/, use  and  only');
+            '//, use  and  only');
     }
 
     function _fileNotAllowed($type)
@@ -1287,6 +1375,13 @@ class PEAR_PackageFile_v2_Validator
             ', use  and  only');
     }
 
+    function _oldStyleFileNotAllowed()
+    {
+        $this->_stack->push(__FUNCTION__, 'error', array(),
+            'Old-style name is not allowed.  Use' .
+            '');
+    }
+
     function _tagMissingAttribute($tag, $attr, $context)
     {
         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag,
@@ -1319,7 +1414,21 @@ class PEAR_PackageFile_v2_Validator
     {
         $this->_stack->push(__FUNCTION__, 'error', array(
             'file' => $file),
-            'File "%file%" cannot begin with "."');
+            'File "%file%" in directory "%dir%" cannot begin with "./" or contain ".."');
+    }
+
+    function _invalidFileInstallAs($file, $as)
+    {
+        $this->_stack->push(__FUNCTION__, 'error', array(
+            'file' => $file, 'as' => $as),
+            'File "%file%"  cannot contain "./" or contain ".."');
+    }
+
+    function _invalidDirName($dir)
+    {
+        $this->_stack->push(__FUNCTION__, 'error', array(
+            'dir' => $file),
+            'Directory "%dir%" cannot begin with "./" or contain ".."');
     }
 
     function _filelistCannotContainFile($filelist)
@@ -1481,7 +1590,7 @@ class PEAR_PackageFile_v2_Validator
     function _cannotProvideExtension($release)
     {
         $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
-            '<%release%> packages cannot use , only extbinrelease and extsrcrelease can provide a PHP extension');
+            '<%release%> packages cannot use , only extbinrelease, extsrcrelease, zendextsrcrelease, and zendextbinrelease can provide a PHP extension');
     }
 
     function _mustProvideExtension($release)
@@ -1499,13 +1608,13 @@ class PEAR_PackageFile_v2_Validator
     function _mustSrcPackage($release)
     {
         $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
-            ' packages must specify a source code package with ');
+            '/ packages must specify a source code package with ');
     }
 
     function _mustSrcuri($release)
     {
         $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
-            ' packages must specify a source code package with ');
+            '/ packages must specify a source code package with ');
     }
 
     function _uriDepsCannotHaveVersioning($type)
@@ -1539,7 +1648,7 @@ class PEAR_PackageFile_v2_Validator
     {
         $this->_stack->push(__FUNCTION__, 'error', array(),
             ' tags must contain the name of a package that is ' .
-            'a compiled version of this extsrc package');
+            'a compiled version of this extsrc/zendextsrc package');
     }
 
     function _fileNotFound($file)
@@ -1563,13 +1672,13 @@ class PEAR_PackageFile_v2_Validator
     function _usesroletaskMustHaveChannelOrUri($role, $tag)
     {
         $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag),
-            '<%tag%> must contain either , or  and ');
+            '<%tag%> for role "%role%" must contain either , or  and ');
     }
 
     function _usesroletaskMustHavePackage($role, $tag)
     {
         $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag),
-            '<%tag%> must contain ');
+            '<%tag%> for role "%role%" must contain ');
     }
 
     function _usesroletaskMustHaveRoleTask($tag, $type)
@@ -1586,10 +1695,29 @@ class PEAR_PackageFile_v2_Validator
 
     function _invalidDepGroupName($name)
     {
-        $this->_stack->push(__FUNCTION__, 'error', array('group' => $name),
+        $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
             'Invalid dependency group name "%name%"');
     }
 
+    function _multipleToplevelDirNotAllowed()
+    {
+        $this->_stack->push(__FUNCTION__, 'error', array(),
+            'Multiple top-level  tags are not allowed.  Enclose them ' .
+                'in a ');
+    }
+
+    function _multipleInstallAs($file)
+    {
+        $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
+            'Only one  tag is allowed for file "%file%"');
+    }
+
+    function _ignoreAndInstallAs($file)
+    {
+        $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
+            'Cannot have both  and  tags for file "%file%"');
+    }
+
     function _analyzeBundledPackages()
     {
         if (!$this->_isValid) {
@@ -1602,8 +1730,9 @@ class PEAR_PackageFile_v2_Validator
             return false;
         }
         $dir_prefix = dirname($this->_pf->_packageFile);
+        $common = new PEAR_Common;
         $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') :
-            array('PEAR_Common', 'log');
+            array($common, 'log');
         $info = $this->_pf->getContents();
         $info = $info['bundledpackage'];
         if (!is_array($info)) {
@@ -1650,6 +1779,10 @@ class PEAR_PackageFile_v2_Validator
         $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') :
             array(&$common, 'log');
         $info = $this->_pf->getContents();
+        if (!$info || !isset($info['dir']['file'])) {
+            $this->_tagCannotBeEmpty('contents>_stack->push(__FUNCTION__, 'error', array('file' => $file),
+                'Parser error: token_get_all() function must exist to analyze source code, PHP may have been compiled with --disable-tokenizer');
             return false;
         }
         if (!defined('T_DOC_COMMENT')) {
@@ -1726,15 +1861,20 @@ class PEAR_PackageFile_v2_Validator
             if (!$fp = @fopen($file, "r")) {
                 return false;
             }
-            if (function_exists('file_get_contents')) {
-                fclose($fp);
-                $contents = file_get_contents($file);
-            } else {
-                $contents = @fread($fp, filesize($file));
-                fclose($fp);
-            }
+            fclose($fp);
+            $contents = file_get_contents($file);
+        }
+
+        // Silence this function so we can catch PHP Warnings and show our own custom message
+        $tokens = @token_get_all($contents);
+        if (isset($php_errormsg)) {
+            $pn = $this->_pf->getPackage();
+            $this->_stack->push(__FUNCTION__, 'warning',
+                    array('file' => $file, 'package' => $pn),
+                    'in %file%: Could not process file for unkown reasons,' .
+                    ' possibly a PHP parse error in %file% from %package%');
+
         }
-        $tokens = token_get_all($contents);
 /*
         for ($i = 0; $i < sizeof($tokens); $i++) {
             @list($token, $data) = $tokens[$i];
@@ -1831,7 +1971,7 @@ class PEAR_PackageFile_v2_Validator
                     if (version_compare(zend_version(), '2.0', '<')) {
                         if (in_array(strtolower($data),
                             array('public', 'private', 'protected', 'abstract',
-                                  'interface', 'implements', 'throw') 
+                                  'interface', 'implements', 'throw')
                                  )) {
                             $this->_stack->push(__FUNCTION__, 'warning', array(
                                 'file' => $file),
diff --git a/includes/pear/PEAR/PackageFile/v2/rw.php b/includes/pear/PEAR/PackageFile/v2/rw.php
index 5f04868a..383042bd 100644
--- a/includes/pear/PEAR/PackageFile/v2/rw.php
+++ b/includes/pear/PEAR/PackageFile/v2/rw.php
@@ -13,9 +13,9 @@
  * @category   pear
  * @package    PEAR
  * @author     Greg Beaver 
- * @copyright  1997-2005 The PHP Group
+ * @copyright  1997-2008 The PHP Group
  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
- * @version    CVS: $Id: rw.php,v 1.12 2005/09/27 03:34:02 cellog Exp $
+ * @version    CVS: $Id: rw.php,v 1.22 2008/01/18 22:47:49 cellog Exp $
  * @link       http://pear.php.net/package/PEAR
  * @since      File available since Release 1.4.0a8
  */
@@ -27,9 +27,9 @@ require_once 'PEAR/PackageFile/v2.php';
  * @category   pear
  * @package    PEAR
  * @author     Greg Beaver 
- * @copyright  1997-2005 The PHP Group
+ * @copyright  1997-2008 The PHP Group
  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
- * @version    Release: 1.4.5
+ * @version    Release: 1.7.2
  * @link       http://pear.php.net/package/PEAR
  * @since      Class available since Release 1.4.0a8
  */
@@ -41,12 +41,14 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
      */
     function setProvidesExtension($extension)
     {
-        if (in_array($this->getPackageType(), array('extsrc', 'extbin'))) {
+        if (in_array($this->getPackageType(),
+              array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
             if (!isset($this->_packageInfo['providesextension'])) {
                 // ensure that the channel tag is set up in the right location
                 $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                     array('usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease',
-                    'extsrcrelease', 'extbinrelease', 'bundle', 'changelog'),
+                    'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
+                    'bundle', 'changelog'),
                     $extension, 'providesextension');
             }
             $this->_packageInfo['providesextension'] = $extension;
@@ -77,6 +79,29 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
         $this->_packageInfo['name'] = $package;
     }
 
+    /**
+     * set this as a package.xml version 2.1
+     * @access private
+     */
+    function _setPackageVersion2_1()
+    {
+        $info = array(
+                                 'version' => '2.1',
+                                 'xmlns' => 'http://pear.php.net/dtd/package-2.1',
+                                 'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
+                                 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
+                                 'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0
+    http://pear.php.net/dtd/tasks-1.0.xsd
+    http://pear.php.net/dtd/package-2.1
+    http://pear.php.net/dtd/package-2.1.xsd',
+                             );
+        if (!isset($this->_packageInfo['attribs'])) {
+            $this->_packageInfo = array_merge(array('attribs' => $info), $this->_packageInfo);
+        } else {
+            $this->_packageInfo['attribs'] = $info;
+        }
+    }
+
     function setUri($uri)
     {
         unset($this->_packageInfo['channel']);
@@ -88,7 +113,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
                 'stability', 'license', 'notes', 'contents', 'compatible',
                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
-                'phprelease', 'extsrcrelease',
+                'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                 'extbinrelease', 'bundle', 'changelog'), $uri, 'uri');
         }
         $this->_packageInfo['uri'] = $uri;
@@ -105,7 +130,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
                 'stability', 'license', 'notes', 'contents', 'compatible',
                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
-                'phprelease', 'extsrcrelease',
+                'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                 'extbinrelease', 'bundle', 'changelog'), $channel, 'channel');
         }
         $this->_packageInfo['channel'] = $channel;
@@ -121,7 +146,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
                 'stability', 'license', 'notes', 'contents', 'compatible',
                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
-                'phprelease', 'extsrcrelease',
+                'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                 'extbinrelease', 'bundle', 'changelog'), $extends, 'extends');
         }
         $this->_packageInfo['extends'] = $extends;
@@ -137,7 +162,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
                 'stability', 'license', 'notes', 'contents', 'compatible',
                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
-                'phprelease', 'extsrcrelease',
+                'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                 'extbinrelease', 'bundle', 'changelog'), $summary, 'summary');
         }
         $this->_packageInfo['summary'] = $summary;
@@ -153,7 +178,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
                 'stability', 'license', 'notes', 'contents', 'compatible',
                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
-                'phprelease', 'extsrcrelease',
+                'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                 'extbinrelease', 'bundle', 'changelog'), $desc, 'description');
         }
         $this->_packageInfo['description'] = $desc;
@@ -185,7 +210,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
                     'stability', 'license', 'notes', 'contents', 'compatible',
                     'dependencies', 'providesextension', 'usesrole', 'usestask',
                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
-                    'extbinrelease', 'bundle', 'changelog');
+                    'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog');
             foreach (array('lead', 'developer', 'contributor', 'helper') as $testrole) {
                 array_shift($testarr);
                 if ($role == $testrole) {
@@ -240,7 +265,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
                 $this->_packageInfo[$role] = array_values($this->_packageInfo[$role]);
             }
         }
-        $this->addMaintainer($newrole, $handle, $name, $email);
+        $this->addMaintainer($newrole, $handle, $name, $email, $active);
         $this->_isValid = 0;
     }
 
@@ -292,7 +317,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array(
             'version' => array('stability', 'license', 'notes', 'contents', 'compatible',
                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
-                'phprelease', 'extsrcrelease',
+                'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                 'extbinrelease', 'bundle', 'changelog'),
             'release' => array('api')));
         $this->_isValid = 0;
@@ -307,7 +332,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array(
             'version' => array('stability', 'license', 'notes', 'contents', 'compatible',
                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
-                'phprelease', 'extsrcrelease',
+                'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                 'extbinrelease', 'bundle', 'changelog'),
             'api' => array()));
         $this->_isValid = 0;
@@ -325,7 +350,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array(
             'stability' => array('license', 'notes', 'contents', 'compatible',
                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
-                'phprelease', 'extsrcrelease',
+                'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                 'extbinrelease', 'bundle', 'changelog'),
             'release' => array('api')));
         $this->_isValid = 0;
@@ -343,7 +368,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array(
             'stability' => array('license', 'notes', 'contents', 'compatible',
                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
-                'phprelease', 'extsrcrelease',
+                'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                 'extbinrelease', 'bundle', 'changelog'),
             'api' => array()));
         $this->_isValid = 0;
@@ -356,7 +381,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                 array('notes', 'contents', 'compatible',
                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
-                'phprelease', 'extsrcrelease',
+                'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                 'extbinrelease', 'bundle', 'changelog'), 0, 'license');
         }
         if ($uri || $filesource) {
@@ -382,7 +407,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                 array('contents', 'compatible',
                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
-                'phprelease', 'extsrcrelease',
+                'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                 'extbinrelease', 'bundle', 'changelog'), $notes, 'notes');
         }
         $this->_packageInfo['notes'] = $notes;
@@ -429,7 +454,8 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
                 array('compatible',
                     'dependencies', 'providesextension', 'usesrole', 'usestask',
                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
-                    'extbinrelease', 'bundle', 'changelog'), array(), 'contents');
+                    'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
+                    'bundle', 'changelog'), array(), 'contents');
         }
         if ($this->getPackageType() != 'bundle') {
             $this->_packageInfo['contents'] = 
@@ -437,6 +463,8 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
             if ($baseinstall) {
                 $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'] = $baseinstall;
             }
+        } else {
+            $this->_packageInfo['contents'] = array('bundledpackage' => array());
         }
     }
 
@@ -453,7 +481,8 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $path, array(
                 'contents' => array('compatible', 'dependencies', 'providesextension',
                 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease',
-                'extsrcrelease', 'extbinrelease', 'bundle', 'changelog'),
+                'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
+                'bundle', 'changelog'),
                 'bundledpackage' => array()));
     }
 
@@ -546,7 +575,8 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                 array('compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask',
                 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
-                'extbinrelease', 'bundle', 'changelog'), array(), 'contents');
+                'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
+                'bundle', 'changelog'), array(), 'contents');
         }
         if (isset($this->_packageInfo['contents']['dir']['file'])) {
             if (!isset($this->_packageInfo['contents']['dir']['file'][0])) {
@@ -584,7 +614,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
                 'compatible' => array('dependencies', 'providesextension', 'usesrole', 'usestask',
                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
-                    'bundle', 'changelog')
+                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
             ));
     }
 
@@ -614,7 +644,8 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
         $this->_isValid = 0;
         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
                 'usesrole' => array('usestask', 'srcpackage', 'srcuri',
-                    'phprelease', 'extsrcrelease', 'extbinrelease', 'bundle', 'changelog')
+                    'phprelease', 'extsrcrelease', 'extbinrelease',
+                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
             ));
     }
 
@@ -645,7 +676,8 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
         $this->_isValid = 0;
         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
                 'usestask' => array('srcpackage', 'srcuri',
-                    'phprelease', 'extsrcrelease', 'extbinrelease', 'bundle', 'changelog')
+                    'phprelease', 'extsrcrelease', 'extbinrelease',
+                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
             ));
     }
 
@@ -667,7 +699,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
                 array(
                     'dependencies' => array('providesextension', 'usesrole', 'usestask',
                         'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
-                        'bundle', 'changelog')));
+                        'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')));
         }
         $this->_packageInfo['dependencies'] = array();
     }
@@ -703,7 +735,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
             array(
                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
-                    'bundle', 'changelog'),
+                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                 'required' => array('optional', 'group'),
                 'php' => array('pearinstaller', 'package', 'subpackage', 'extension', 'os', 'arch')
             ));
@@ -745,7 +777,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
             array(
                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
-                    'bundle', 'changelog'),
+                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                 'required' => array('optional', 'group'),
                 'pearinstaller' => array('package', 'subpackage', 'extension', 'os', 'arch')
             ));
@@ -756,24 +788,21 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
      * @param string package name
      * @param string package channel
      * @param string extension this package provides, if any
+     * @param string|false minimum version required
+     * @param string|false maximum version allowed
+     * @param array|false versions to exclude from installation
      */
-    function addConflictingPackageDepWithChannel($name, $channel, $providesextension = false)
+    function addConflictingPackageDepWithChannel($name, $channel,
+                $providesextension = false, $min = false, $max = false, $exclude = false)
     {
         $this->_isValid = 0;
-        $dep =
-            array(
-                'name' => $name,
-                'channel' => $channel,
-                'conflicts' => '',
-            );
-        if ($providesextension) {
-            $dep['providesextension'] = $providesextension;
-        }
+        $dep = $this->_constructDep($name, $channel, false, $min, $max, false,
+            $exclude, $providesextension, false, true);
         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
             array(
                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
-                    'bundle', 'changelog'),
+                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                 'required' => array('optional', 'group'),
                 'package' => array('subpackage', 'extension', 'os', 'arch')
             ));
@@ -801,7 +830,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
             array(
                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
-                    'bundle', 'changelog'),
+                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                 'required' => array('optional', 'group'),
                 'package' => array('subpackage', 'extension', 'os', 'arch')
             ));
@@ -815,7 +844,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
             array(
                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
-                    'bundle', 'changelog'),
+                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                 'group' => array(),
             ));
     }
@@ -831,11 +860,13 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
      * @param string extension this package provides, if any
      * @param bool if true, tells the installer to ignore the default optional dependency group
      *             when installing this package
+     * @param bool if true, tells the installer to negate this dependency (conflicts)
      * @return array
      * @access private
      */
     function _constructDep($name, $channel, $uri, $min, $max, $recommended, $exclude,
-                           $providesextension = false, $nodefault = false)
+                           $providesextension = false, $nodefault = false,
+                           $conflicts = false)
     {
         $dep =
             array(
@@ -861,6 +892,9 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
             }
             $dep['exclude'] = $exclude;
         }
+        if ($conflicts) {
+            $dep['conflicts'] = '';
+        }
         if ($nodefault) {
             $dep['nodefault'] = '';
         }
@@ -1000,6 +1034,9 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
                                       $recommended = false, $exclude = false,
                                       $providesextension = false, $nodefault = false)
     {
+        if (!in_array($type, array('optional', 'required'), true)) {
+            $type = 'required';
+        }
         $this->_isValid = 0;
         $arr = array('optional', 'group');
         if ($type != 'required') {
@@ -1011,7 +1048,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
             array(
                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
-                    'bundle', 'changelog'),
+                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                 $type => $arr,
                 'package' => array('subpackage', 'extension', 'os', 'arch')
             ));
@@ -1039,7 +1076,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
             array(
                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
-                    'bundle', 'changelog'),
+                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                 $type => $arr,
                 'package' => array('subpackage', 'extension', 'os', 'arch')
             ));
@@ -1071,7 +1108,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
             array(
                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
-                    'bundle', 'changelog'),
+                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                 $type => $arr,
                 'subpackage' => array('extension', 'os', 'arch')
             ));
@@ -1096,7 +1133,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
             array(
                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
-                    'bundle', 'changelog'),
+                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                 $type => $arr,
                 'subpackage' => array('extension', 'os', 'arch')
             ));
@@ -1123,7 +1160,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
             array(
                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
-                    'bundle', 'changelog'),
+                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                 $type => $arr,
                 'extension' => array('os', 'arch')
             ));
@@ -1144,7 +1181,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
             array(
                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
-                    'bundle', 'changelog'),
+                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                 'required' => array('optional', 'group'),
                 'os' => array('arch')
             ));
@@ -1165,7 +1202,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
             array(
                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
-                    'bundle', 'changelog'),
+                    'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                 'required' => array('optional', 'group'),
                 'arch' => array()
             ));
@@ -1177,20 +1214,27 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
      * - a php package is a PEAR-style package
      * - an extbin package is a PECL-style extension binary
      * - an extsrc package is a PECL-style source for a binary
+     * - an zendextbin package is a PECL-style zend extension binary
+     * - an zendextsrc package is a PECL-style source for a zend extension binary
      * - a bundle package is a collection of other pre-packaged packages
-     * @param php|extbin|extsrc|bundle
+     * @param php|extbin|extsrc|zendextsrc|zendextbin|bundle
      * @return bool success
      */
     function setPackageType($type)
     {
         $this->_isValid = 0;
-        if (!in_array($type, array('php', 'extbin', 'extsrc', 'bundle'))) {
+        if (!in_array($type, array('php', 'extbin', 'extsrc', 'zendextsrc',
+                                   'zendextbin', 'bundle'))) {
             return false;
         }
+        if (in_array($type, array('zendextsrc', 'zendextbin'))) {
+            $this->_setPackageVersion2_1();
+        }
         if ($type != 'bundle') {
             $type .= 'release';
         }
-        foreach (array('phprelease', 'extbinrelease', 'extsrcrelease', 'bundle') as $test) {
+        foreach (array('phprelease', 'extbinrelease', 'extsrcrelease',
+                       'zendextsrcrelease', 'zendextbinrelease', 'bundle') as $test) {
             unset($this->_packageInfo[$test]);
         }
         if (!isset($this->_packageInfo[$type])) {
@@ -1227,7 +1271,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
     {
         if ($p = $this->getPackageType()) {
             if ($strict) {
-                if ($p == 'extsrc') {
+                if ($p == 'extsrc' || $p == 'zendextsrc') {
                     $a = null;
                     return $a;
                 }
@@ -1292,7 +1336,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
      */
     function addBinarypackage($package)
     {
-        if ($this->getPackageType() != 'extsrc') {
+        if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
             return false;
         }
         $r = &$this->_getCurrentRelease(false);
@@ -1314,7 +1358,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
      */
     function addConfigureOption($name, $prompt, $default = null)
     {
-        if ($this->getPackageType() != 'extsrc') {
+        if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
             return false;
         }
         $r = &$this->_getCurrentRelease(false);
@@ -1323,7 +1367,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
         }
         $opt = array('attribs' => array('name' => $name, 'prompt' => $prompt));
         if ($default !== null) {
-            $opt['default'] = $default;
+            $opt['attribs']['default'] = $default;
         }
         $this->_isValid = 0;
         $r = $this->_mergeTag($r, $opt,
@@ -1355,7 +1399,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
             }
             $dep['exclude'] = $exclude;
         }
-        if ($this->getPackageType() == 'extsrc') {
+        if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
             $r = $this->_mergeTag($r, $dep,
                 array(
                     'installconditions' => array('configureoption', 'binarypackage',
@@ -1388,7 +1432,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
         }
         $this->_isValid = 0;
         $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
-        if ($this->getPackageType() == 'extsrc') {
+        if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
             $r = $this->_mergeTag($r, $dep,
                 array(
                     'installconditions' => array('configureoption', 'binarypackage',
@@ -1423,7 +1467,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
         if ($conflicts) {
             $dep['conflicts'] = '';
         }
-        if ($this->getPackageType() == 'extsrc') {
+        if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
             $r = $this->_mergeTag($r, $dep,
                 array(
                     'installconditions' => array('configureoption', 'binarypackage',
@@ -1458,7 +1502,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
         if ($conflicts) {
             $dep['conflicts'] = '';
         }
-        if ($this->getPackageType() == 'extsrc') {
+        if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
             $r = $this->_mergeTag($r, $dep,
                 array(
                     'installconditions' => array('configureoption', 'binarypackage',
@@ -1476,20 +1520,22 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
 
     /**
      * For extension binary releases, this is used to specify either the
-     * static URI to a source package, or the package name and channel of the extsrc
+     * static URI to a source package, or the package name and channel of the extsrc/zendextsrc
      * package it is based on.
-     * @param string Package name, or full URI to source package (extsrc type)
+     * @param string Package name, or full URI to source package (extsrc/zendextsrc type)
      */
     function setSourcePackage($packageOrUri)
     {
         $this->_isValid = 0;
         if (isset($this->_packageInfo['channel'])) {
             $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease',
-                'extsrcrelease', 'extbinrelease', 'bundle', 'changelog'),
+                'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
+                'bundle', 'changelog'),
                 $packageOrUri, 'srcpackage');
         } else {
             $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease',
-                'extsrcrelease', 'extbinrelease', 'bundle', 'changelog'), $packageOrUri, 'srcuri');
+                'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
+                'bundle', 'changelog'), $packageOrUri, 'srcuri');
         }
     }
 
@@ -1508,7 +1554,7 @@ class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
             'stability' =>
                 $this->getStability(),
             'date' => $this->getDate(),
-            'license' => $this->getLicense(),
+            'license' => $this->getLicense(true),
             'notes' => $notes ? $notes : $this->getNotes()
             );
     }
diff --git a/includes/pear/PEAR/Packager.php b/includes/pear/PEAR/Packager.php
index 3b4a50f4..bae92823 100644
--- a/includes/pear/PEAR/Packager.php
+++ b/includes/pear/PEAR/Packager.php
@@ -15,9 +15,9 @@
  * @author     Stig Bakken 
  * @author     Tomas V. V. Cox 
  * @author     Greg Beaver 
- * @copyright  1997-2005 The PHP Group
+ * @copyright  1997-2008 The PHP Group
  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
- * @version    CVS: $Id: Packager.php,v 1.67 2005/08/14 06:49:19 cellog Exp $
+ * @version    CVS: $Id: Packager.php,v 1.71 2008/01/03 20:26:36 cellog Exp $
  * @link       http://pear.php.net/package/PEAR
  * @since      File available since Release 0.1
  */
@@ -35,9 +35,9 @@ require_once 'System.php';
  * @category   pear
  * @package    PEAR
  * @author     Greg Beaver 
- * @copyright  1997-2005 The PHP Group
+ * @copyright  1997-2008 The PHP Group
  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
- * @version    Release: 1.4.5
+ * @version    Release: 1.7.2
  * @link       http://pear.php.net/package/PEAR
  * @since      Class available since Release 0.1
  */
@@ -93,14 +93,16 @@ class PEAR_Packager extends PEAR_Common
                     $this->log(1, 'Warning: ' . $warning['message']);
                 }
             }
-            if ($pf2->getPackagexmlVersion() == '2.0') {
+            if ($pf2->getPackagexmlVersion() == '2.0' ||
+                  $pf2->getPackagexmlVersion() == '2.1') {
                 $main = &$pf2;
                 $other = &$pf;
             } else {
                 $main = &$pf;
                 $other = &$pf2;
             }
-            if ($main->getPackagexmlVersion() != '2.0') {
+            if ($main->getPackagexmlVersion() != '2.0' &&
+                  $main->getPackagexmlVersion() != '2.1') {
                 return PEAR::raiseError('Error: cannot package two package.xml version 1.0, can ' .
                     'only package together a package.xml 1.0 and package.xml 2.0');
             }
@@ -187,13 +189,8 @@ if (!function_exists('md5_file')) {
         if (!$fd = @fopen($file, 'r')) {
             return false;
         }
-        if (function_exists('file_get_contents')) {
-            fclose($fd);
-            $md5 = md5(file_get_contents($file));
-        } else {
-            $md5 = md5(fread($fd, filesize($file)));
-            fclose($fd);
-        }
+        fclose($fd);
+        $md5 = md5(file_get_contents($file));
         return $md5;
     }
 }
diff --git a/includes/pear/PEAR/REST.php b/includes/pear/PEAR/REST.php
index 30052daa..c32946c6 100644
--- a/includes/pear/PEAR/REST.php
+++ b/includes/pear/PEAR/REST.php
@@ -1,380 +1,397 @@
-
- * @copyright  1997-2005 The PHP Group
- * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
- * @version    CVS: $Id: REST.php,v 1.15 2005/09/24 04:15:13 cellog Exp $
- * @link       http://pear.php.net/package/PEAR
- * @since      File available since Release 1.4.0a1
- */
-
-/**
- * For downloading xml files
- */
-require_once 'PEAR.php';
-require_once 'PEAR/XMLParser.php';
-
-/**
- * Intelligently retrieve data, following hyperlinks if necessary, and re-directing
- * as well
- * @category   pear
- * @package    PEAR
- * @author     Greg Beaver 
- * @copyright  1997-2005 The PHP Group
- * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
- * @version    Release: 1.4.5
- * @link       http://pear.php.net/package/PEAR
- * @since      Class available since Release 1.4.0a1
- */
-class PEAR_REST
-{
-    var $config;
-    var $_options;
-    function PEAR_REST(&$config, $options = array())
-    {
-        $this->config = &$config;
-        $this->_options = $options;
-    }
-
-    /**
-     * Retrieve REST data, but always retrieve the local cache if it is available.
-     *
-     * This is useful for elements that should never change, such as information on a particular
-     * release
-     * @param string full URL to this resource
-     * @param array|false contents of the accept-encoding header
-     * @param boolean     if true, xml will be returned as a string, otherwise, xml will be
-     *                    parsed using PEAR_XMLParser
-     * @return string|array
-     */
-    function retrieveCacheFirst($url, $accept = false, $forcestring = false)
-    {
-        $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
-            md5($url) . 'rest.cachefile';
-        if (@file_exists($cachefile)) {
-            return unserialize(implode('', file($cachefile)));
-        }
-        return $this->retrieveData($url, $accept, $forcestring);
-    }
-
-    /**
-     * Retrieve a remote REST resource
-     * @param string full URL to this resource
-     * @param array|false contents of the accept-encoding header
-     * @param boolean     if true, xml will be returned as a string, otherwise, xml will be
-     *                    parsed using PEAR_XMLParser
-     * @return string|array
-     */
-    function retrieveData($url, $accept = false, $forcestring = false)
-    {
-        $cacheId = $this->getCacheId($url);
-        if ($ret = $this->useLocalCache($url, $cacheId)) {
-            return $ret;
-        }
-        if (!isset($this->_options['offline'])) {
-            $trieddownload = true;
-            $file = $this->downloadHttp($url, $cacheId ? $cacheId['lastChange'] : false, $accept);
-        } else {
-            $trieddownload = false;
-            $file = false;
-        }
-        if (PEAR::isError($file)) {
-            if ($file->getCode() == -9276) {
-                $trieddownload = false;
-                $file = false; // use local copy if available on socket connect error
-            } else {
-                return $file;
-            }
-        }
-        if (!$file) {
-            $ret = $this->getCache($url);
-            if (!PEAR::isError($ret) && $trieddownload) {
-                // reset the age of the cache if the server says it was unmodified
-                $this->saveCache($url, $ret, null, true, $cacheId);
-            }
-            return $ret;
-        }
-        $headers = $file[2];
-        $lastmodified = $file[1];
-        $content = $file[0];
-        if ($forcestring) {
-            $this->saveCache($url, $content, $lastmodified, false, $cacheId);
-            return $content;
-        }
-        if (isset($headers['content-type'])) {
-            switch ($headers['content-type']) {
-                case 'text/xml' :
-                case 'application/xml' :
-                    $parser = new PEAR_XMLParser;
-                    PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
-                    $err = $parser->parse($content);
-                    PEAR::popErrorHandling();
-                    if (PEAR::isError($err)) {
-                        return PEAR::raiseError('Invalid xml downloaded from "' . $url . '": ' .
-                            $err->getMessage());
-                    }
-                    $content = $parser->getData();
-                case 'text/html' :
-                default :
-                    // use it as a string
-            }
-        } else {
-            // assume XML
-            $parser = new PEAR_XMLParser;
-            $parser->parse($file);
-            $content = $parser->getData();
-        }
-        $this->saveCache($url, $content, $lastmodified, false, $cacheId);
-        return $content;
-    }
-
-    function useLocalCache($url, $cacheid = null)
-    {
-        if ($cacheid === null) {
-            $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
-                md5($url) . 'rest.cacheid';
-            if (@file_exists($cacheidfile)) {
-                $cacheid = unserialize(implode('', file($cacheidfile)));
-            } else {
-                return false;
-            }
-        }
-        $cachettl = $this->config->get('cache_ttl');
-        // If cache is newer than $cachettl seconds, we use the cache!
-        if (time() - $cacheid['age'] < $cachettl) {
-            return $this->getCache($url);
-        }
-        return false;
-    }
-
-    function getCacheId($url)
-    {
-        $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
-            md5($url) . 'rest.cacheid';
-        if (@file_exists($cacheidfile)) {
-            $ret = unserialize(implode('', file($cacheidfile)));
-            return $ret;
-        } else {
-            return false;
-        }
-    }
-
-    function getCache($url)
-    {
-        $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
-            md5($url) . 'rest.cachefile';
-        if (@file_exists($cachefile)) {
-            return unserialize(implode('', file($cachefile)));
-        } else {
-            return PEAR::raiseError('No cached content available for "' . $url . '"');
-        }
-    }
-
-    /**
-     * @param string full URL to REST resource
-     * @param string original contents of the REST resource
-     * @param array  HTTP Last-Modified and ETag headers
-     * @param bool   if true, then the cache id file should be regenerated to
-     *               trigger a new time-to-live value
-     */
-    function saveCache($url, $contents, $lastmodified, $nochange = false, $cacheid = null)
-    {
-        $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
-            md5($url) . 'rest.cacheid';
-        $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
-            md5($url) . 'rest.cachefile';
-        if ($cacheid === null && $nochange) {
-            $cacheid = unserialize(implode('', file($cacheidfile)));
-        }
-        $fp = @fopen($cacheidfile, 'wb');
-        if (!$fp) {
-            return false;
-        }
-        if ($nochange) {
-            fwrite($fp, serialize(array(
-                'age'        => time(),
-                'lastChange' => $cacheid['lastChange'],
-                )));
-            fclose($fp);
-            return true;
-        } else {
-            fwrite($fp, serialize(array(
-                'age'        => time(),
-                'lastChange' => $lastmodified,
-                )));
-        }
-        fclose($fp);
-        $fp = @fopen($cachefile, 'wb');
-        if (!$fp) {
-            @unlink($cacheidfile);
-            return false;
-        }
-        fwrite($fp, serialize($contents));
-        fclose($fp);
-        return true;
-    }
-
-    /**
-     * Efficiently Download a file through HTTP.  Returns downloaded file as a string in-memory
-     * This is best used for small files
-     *
-     * If an HTTP proxy has been configured (http_proxy PEAR_Config
-     * setting), the proxy will be used.
-     *
-     * @param string  $url       the URL to download
-     * @param string  $save_dir  directory to save file in
-     * @param false|string|array $lastmodified header values to check against for caching
-     *                           use false to return the header values from this download
-     * @param false|array $accept Accept headers to send
-     * @return string|array  Returns the contents of the downloaded file or a PEAR
-     *                       error on failure.  If the error is caused by
-     *                       socket-related errors, the error object will
-     *                       have the fsockopen error code available through
-     *                       getCode().  If caching is requested, then return the header
-     *                       values.
-     *
-     * @access public
-     */
-    function downloadHttp($url, $lastmodified = null, $accept = false)
-    {
-        $info = parse_url($url);
-        if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) {
-            return PEAR::raiseError('Cannot download non-http URL "' . $url . '"');
-        }
-        if (!isset($info['host'])) {
-            return PEAR::raiseError('Cannot download from non-URL "' . $url . '"');
-        } else {
-            $host = $info['host'];
-            if (!array_key_exists('port', $info)) {
-                $info['port'] = null;
-            }
-            if (!array_key_exists('path', $info)) {
-                $info['path'] = null;
-            }
-            $port = $info['port'];
-            $path = $info['path'];
-        }
-        $proxy_host = $proxy_port = $proxy_user = $proxy_pass = '';
-        if ($this->config->get('http_proxy')&& 
-              $proxy = parse_url($this->config->get('http_proxy'))) {
-            $proxy_host = @$proxy['host'];
-            if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') {
-                $proxy_host = 'ssl://' . $proxy_host;
-            }
-            $proxy_port = @$proxy['port'];
-            $proxy_user = @$proxy['user'];
-            $proxy_pass = @$proxy['pass'];
-
-            if ($proxy_port == '') {
-                $proxy_port = 8080;
-            }
-        }
-        if (empty($port)) {
-            if (isset($info['scheme']) && $info['scheme'] == 'https') {
-                $port = 443;
-            } else {
-                $port = 80;
-            }
-        }
-        If (isset($proxy['host'])) {
-            $request = "GET $url HTTP/1.1\r\n";
-        } else {
-            $request = "GET $path HTTP/1.1\r\n";
-        }
-
-        $ifmodifiedsince = '';
-        if (is_array($lastmodified)) {
-            if (isset($lastmodified['Last-Modified'])) {
-                $ifmodifiedsince = 'If-Modified-Since: ' . $lastmodified['Last-Modified'] . "\r\n";
-            }
-            if (isset($lastmodified['ETag'])) {
-                $ifmodifiedsince .= "If-None-Match: $lastmodified[ETag]\r\n";
-            }
-        } else {
-            $ifmodifiedsince = ($lastmodified ? "If-Modified-Since: $lastmodified\r\n" : '');
-        }
-        $request .= "Host: $host:$port\r\n" . $ifmodifiedsince .
-            "User-Agent: PEAR/1.4.5/PHP/" . PHP_VERSION . "\r\n";
-        $username = $this->config->get('username');
-        $password = $this->config->get('password');
-        if ($username && $password) {
-            $tmp = base64_encode("$username:$password");
-            $request .= "Authorization: Basic $tmp\r\n";
-        }
-        if ($proxy_host != '' && $proxy_user != '') {
-            $request .= 'Proxy-Authorization: Basic ' .
-                base64_encode($proxy_user . ':' . $proxy_pass) . "\r\n";
-        }
-        if ($accept) {
-            $request .= 'Accept: ' . implode(', ', $accept) . "\r\n";
-        }
-        $request .= "Connection: close\r\n";
-        $request .= "\r\n";
-        if ($proxy_host != '') {
-            $fp = @fsockopen($proxy_host, $proxy_port, $errno, $errstr, 15);
-            if (!$fp) {
-                return PEAR::raiseError("Connection to `$proxy_host:$proxy_port' failed: $errstr",
-                    -9276);
-            }
-        } else {
-            if (isset($info['scheme']) && $info['scheme'] == 'https') {
-                $host = 'ssl://' . $host;
-            }
-            $fp = @fsockopen($host, $port, $errno, $errstr);
-            if (!$fp) {
-                return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno);
-            }
-        }
-        fwrite($fp, $request);
-        $headers = array();
-        while (trim($line = fgets($fp, 1024))) {
-            if (preg_match('/^([^:]+):\s+(.*)\s*$/', $line, $matches)) {
-                $headers[strtolower($matches[1])] = trim($matches[2]);
-            } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) {
-                if ($matches[1] == 304 && ($lastmodified || ($lastmodified === false))) {
-                    return false;
-                }
-                if ($matches[1] != 200) {
-                    return PEAR::raiseError("File http://$host:$port$path not valid (received: $line)");
-                }
-            }
-        }
-        if (isset($headers['content-length'])) {
-            $length = $headers['content-length'];
-        } else {
-            $length = -1;
-        }
-        $data = '';
-        while ($chunk = @fread($fp, 8192)) {
-            $data .= $chunk;
-        }
-        fclose($fp);
-        if ($lastmodified === false || $lastmodified) {
-            if (isset($headers['etag'])) {
-                $lastmodified = array('ETag' => $headers['etag']);
-            }
-            if (isset($headers['last-modified'])) {
-                if (is_array($lastmodified)) {
-                    $lastmodified['Last-Modified'] = $headers['last-modified'];
-                } else {
-                    $lastmodified = $headers['last-modified'];
-                }
-            }
-            return array($data, $lastmodified, $headers);
-        }
-        return $data;
-    }
-}
-?>
\ No newline at end of file
+
+ * @copyright  1997-2008 The PHP Group
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version    CVS: $Id: REST.php,v 1.31 2008/05/13 18:03:36 cellog Exp $
+ * @link       http://pear.php.net/package/PEAR
+ * @since      File available since Release 1.4.0a1
+ */
+
+/**
+ * For downloading xml files
+ */
+require_once 'PEAR.php';
+require_once 'PEAR/XMLParser.php';
+
+/**
+ * Intelligently retrieve data, following hyperlinks if necessary, and re-directing
+ * as well
+ * @category   pear
+ * @package    PEAR
+ * @author     Greg Beaver 
+ * @copyright  1997-2008 The PHP Group
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version    Release: 1.7.2
+ * @link       http://pear.php.net/package/PEAR
+ * @since      Class available since Release 1.4.0a1
+ */
+class PEAR_REST
+{
+    var $config;
+    var $_options;
+    function PEAR_REST(&$config, $options = array())
+    {
+        $this->config = &$config;
+        $this->_options = $options;
+    }
+
+    /**
+     * Retrieve REST data, but always retrieve the local cache if it is available.
+     *
+     * This is useful for elements that should never change, such as information on a particular
+     * release
+     * @param string full URL to this resource
+     * @param array|false contents of the accept-encoding header
+     * @param boolean     if true, xml will be returned as a string, otherwise, xml will be
+     *                    parsed using PEAR_XMLParser
+     * @return string|array
+     */
+    function retrieveCacheFirst($url, $accept = false, $forcestring = false, $channel = false)
+    {
+        $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
+            md5($url) . 'rest.cachefile';
+        if (file_exists($cachefile)) {
+            return unserialize(implode('', file($cachefile)));
+        }
+        return $this->retrieveData($url, $accept, $forcestring, $channel);
+    }
+
+    /**
+     * Retrieve a remote REST resource
+     * @param string full URL to this resource
+     * @param array|false contents of the accept-encoding header
+     * @param boolean     if true, xml will be returned as a string, otherwise, xml will be
+     *                    parsed using PEAR_XMLParser
+     * @return string|array
+     */
+    function retrieveData($url, $accept = false, $forcestring = false, $channel = false)
+    {
+        $cacheId = $this->getCacheId($url);
+        if ($ret = $this->useLocalCache($url, $cacheId)) {
+            return $ret;
+        }
+        if (!isset($this->_options['offline'])) {
+            $trieddownload = true;
+            $file = $this->downloadHttp($url, $cacheId ? $cacheId['lastChange'] : false, $accept, $channel);
+        } else {
+            $trieddownload = false;
+            $file = false;
+        }
+        if (PEAR::isError($file)) {
+            if ($file->getCode() == -9276) {
+                $trieddownload = false;
+                $file = false; // use local copy if available on socket connect error
+            } else {
+                return $file;
+            }
+        }
+        if (!$file) {
+            $ret = $this->getCache($url);
+            if (!PEAR::isError($ret) && $trieddownload) {
+                // reset the age of the cache if the server says it was unmodified
+                $this->saveCache($url, $ret, null, true, $cacheId);
+            }
+            return $ret;
+        }
+        if (is_array($file)) {
+            $headers = $file[2];
+            $lastmodified = $file[1];
+            $content = $file[0];
+        } else {
+            $content = $file;
+            $lastmodified = false;
+            $headers = array();
+        }
+        if ($forcestring) {
+            $this->saveCache($url, $content, $lastmodified, false, $cacheId);
+            return $content;
+        }
+        if (isset($headers['content-type'])) {
+            switch ($headers['content-type']) {
+                case 'text/xml' :
+                case 'application/xml' :
+                    $parser = new PEAR_XMLParser;
+                    PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
+                    $err = $parser->parse($content);
+                    PEAR::popErrorHandling();
+                    if (PEAR::isError($err)) {
+                        return PEAR::raiseError('Invalid xml downloaded from "' . $url . '": ' .
+                            $err->getMessage());
+                    }
+                    $content = $parser->getData();
+                case 'text/html' :
+                default :
+                    // use it as a string
+            }
+        } else {
+            // assume XML
+            $parser = new PEAR_XMLParser;
+            $parser->parse($content);
+            $content = $parser->getData();
+        }
+        $this->saveCache($url, $content, $lastmodified, false, $cacheId);
+        return $content;
+    }
+
+    function useLocalCache($url, $cacheid = null)
+    {
+        if ($cacheid === null) {
+            $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
+                md5($url) . 'rest.cacheid';
+            if (file_exists($cacheidfile)) {
+                $cacheid = unserialize(implode('', file($cacheidfile)));
+            } else {
+                return false;
+            }
+        }
+        $cachettl = $this->config->get('cache_ttl');
+        // If cache is newer than $cachettl seconds, we use the cache!
+        if (time() - $cacheid['age'] < $cachettl) {
+            return $this->getCache($url);
+        }
+        return false;
+    }
+
+    function getCacheId($url)
+    {
+        $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
+            md5($url) . 'rest.cacheid';
+        if (file_exists($cacheidfile)) {
+            $ret = unserialize(implode('', file($cacheidfile)));
+            return $ret;
+        } else {
+            return false;
+        }
+    }
+
+    function getCache($url)
+    {
+        $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
+            md5($url) . 'rest.cachefile';
+        if (file_exists($cachefile)) {
+            return unserialize(implode('', file($cachefile)));
+        } else {
+            return PEAR::raiseError('No cached content available for "' . $url . '"');
+        }
+    }
+
+    /**
+     * @param string full URL to REST resource
+     * @param string original contents of the REST resource
+     * @param array  HTTP Last-Modified and ETag headers
+     * @param bool   if true, then the cache id file should be regenerated to
+     *               trigger a new time-to-live value
+     */
+    function saveCache($url, $contents, $lastmodified, $nochange = false, $cacheid = null)
+    {
+        $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
+            md5($url) . 'rest.cacheid';
+        $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
+            md5($url) . 'rest.cachefile';
+        if ($cacheid === null && $nochange) {
+            $cacheid = unserialize(implode('', file($cacheidfile)));
+        }
+
+        $fp = @fopen($cacheidfile, 'wb');
+        if (!$fp) {
+            $cache_dir = $this->config->get('cache_dir');
+            if (!is_dir($cache_dir)) {
+                System::mkdir(array('-p', $cache_dir));
+                $fp = @fopen($cacheidfile, 'wb');
+                if (!$fp) {
+                    return false;
+                }
+            } else {
+                return false;
+            }
+        }
+
+        if ($nochange) {
+            fwrite($fp, serialize(array(
+                'age'        => time(),
+                'lastChange' => $cacheid['lastChange'],
+                )));
+            fclose($fp);
+            return true;
+        } else {
+            fwrite($fp, serialize(array(
+                'age'        => time(),
+                'lastChange' => $lastmodified,
+                )));
+        }
+        fclose($fp);
+        $fp = @fopen($cachefile, 'wb');
+        if (!$fp) {
+            if (file_exists($cacheidfile)) {
+                @unlink($cacheidfile);
+            }
+            return false;
+        }
+        fwrite($fp, serialize($contents));
+        fclose($fp);
+        return true;
+    }
+
+    /**
+     * Efficiently Download a file through HTTP.  Returns downloaded file as a string in-memory
+     * This is best used for small files
+     *
+     * If an HTTP proxy has been configured (http_proxy PEAR_Config
+     * setting), the proxy will be used.
+     *
+     * @param string  $url       the URL to download
+     * @param string  $save_dir  directory to save file in
+     * @param false|string|array $lastmodified header values to check against for caching
+     *                           use false to return the header values from this download
+     * @param false|array $accept Accept headers to send
+     * @return string|array  Returns the contents of the downloaded file or a PEAR
+     *                       error on failure.  If the error is caused by
+     *                       socket-related errors, the error object will
+     *                       have the fsockopen error code available through
+     *                       getCode().  If caching is requested, then return the header
+     *                       values.
+     *
+     * @access public
+     */
+    function downloadHttp($url, $lastmodified = null, $accept = false, $channel = false)
+    {
+        $info = parse_url($url);
+        if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) {
+            return PEAR::raiseError('Cannot download non-http URL "' . $url . '"');
+        }
+        if (!isset($info['host'])) {
+            return PEAR::raiseError('Cannot download from non-URL "' . $url . '"');
+        } else {
+            $host = $info['host'];
+            if (!array_key_exists('port', $info)) {
+                $info['port'] = null;
+            }
+            if (!array_key_exists('path', $info)) {
+                $info['path'] = null;
+            }
+            $port = $info['port'];
+            $path = $info['path'];
+        }
+        $proxy_host = $proxy_port = $proxy_user = $proxy_pass = '';
+        if ($this->config->get('http_proxy')&&
+              $proxy = parse_url($this->config->get('http_proxy'))) {
+            $proxy_host = isset($proxy['host']) ? $proxy['host'] : null;
+            if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') {
+                $proxy_host = 'ssl://' . $proxy_host;
+            }
+            $proxy_port = isset($proxy['port']) ? $proxy['port'] : 8080;
+            $proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null;
+            $proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null;
+        }
+        if (empty($port)) {
+            if (isset($info['scheme']) && $info['scheme'] == 'https') {
+                $port = 443;
+            } else {
+                $port = 80;
+            }
+        }
+        If (isset($proxy['host'])) {
+            $request = "GET $url HTTP/1.1\r\n";
+        } else {
+            $request = "GET $path HTTP/1.1\r\n";
+        }
+        $request .= "Host: $host:$port\r\n";
+
+        $ifmodifiedsince = '';
+        if (is_array($lastmodified)) {
+            if (isset($lastmodified['Last-Modified'])) {
+                $ifmodifiedsince = 'If-Modified-Since: ' . $lastmodified['Last-Modified'] . "\r\n";
+            }
+            if (isset($lastmodified['ETag'])) {
+                $ifmodifiedsince .= "If-None-Match: $lastmodified[ETag]\r\n";
+            }
+        } else {
+            $ifmodifiedsince = ($lastmodified ? "If-Modified-Since: $lastmodified\r\n" : '');
+        }
+        $request .= $ifmodifiedsince .
+            "User-Agent: PEAR/1.7.2/PHP/" . PHP_VERSION . "\r\n";
+        $username = $this->config->get('username', null, $channel);
+        $password = $this->config->get('password', null, $channel);
+        if ($username && $password) {
+            $tmp = base64_encode("$username:$password");
+            $request .= "Authorization: Basic $tmp\r\n";
+        }
+        if ($proxy_host != '' && $proxy_user != '') {
+            $request .= 'Proxy-Authorization: Basic ' .
+                base64_encode($proxy_user . ':' . $proxy_pass) . "\r\n";
+        }
+        if ($accept) {
+            $request .= 'Accept: ' . implode(', ', $accept) . "\r\n";
+        }
+        $request .= "Accept-Encoding:\r\n";
+        $request .= "Connection: close\r\n";
+        $request .= "\r\n";
+        if ($proxy_host != '') {
+            $fp = @fsockopen($proxy_host, $proxy_port, $errno, $errstr, 15);
+            if (!$fp) {
+                return PEAR::raiseError("Connection to `$proxy_host:$proxy_port' failed: $errstr",
+                    -9276);
+            }
+        } else {
+            if (isset($info['scheme']) && $info['scheme'] == 'https') {
+                $host = 'ssl://' . $host;
+            }
+            $fp = @fsockopen($host, $port, $errno, $errstr);
+            if (!$fp) {
+                return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno);
+            }
+        }
+        fwrite($fp, $request);
+        $headers = array();
+        while (trim($line = fgets($fp, 1024))) {
+            if (preg_match('/^([^:]+):\s+(.*)\s*\\z/', $line, $matches)) {
+                $headers[strtolower($matches[1])] = trim($matches[2]);
+            } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) {
+                if ($matches[1] == 304 && ($lastmodified || ($lastmodified === false))) {
+                    return false;
+                }
+                if ($matches[1] != 200) {
+                    return PEAR::raiseError("File http://$host:$port$path not valid (received: $line)", (int) $matches[1]);
+                }
+            }
+        }
+        if (isset($headers['content-length'])) {
+            $length = $headers['content-length'];
+        } else {
+            $length = -1;
+        }
+        $data = '';
+        while ($chunk = @fread($fp, 8192)) {
+            $data .= $chunk;
+        }
+        fclose($fp);
+        if ($lastmodified === false || $lastmodified) {
+            if (isset($headers['etag'])) {
+                $lastmodified = array('ETag' => $headers['etag']);
+            }
+            if (isset($headers['last-modified'])) {
+                if (is_array($lastmodified)) {
+                    $lastmodified['Last-Modified'] = $headers['last-modified'];
+                } else {
+                    $lastmodified = $headers['last-modified'];
+                }
+            }
+            return array($data, $lastmodified, $headers);
+        }
+        return $data;
+    }
+}
+?>
diff --git a/includes/pear/PEAR/REST/10.php b/includes/pear/PEAR/REST/10.php
index 81bcdf22..d2f44fe9 100644
--- a/includes/pear/PEAR/REST/10.php
+++ b/includes/pear/PEAR/REST/10.php
@@ -1,624 +1,797 @@
-
- * @copyright  1997-2005 The PHP Group
- * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
- * @version    CVS: $Id: 10.php,v 1.39 2005/11/16 03:34:17 cellog Exp $
- * @link       http://pear.php.net/package/PEAR
- * @since      File available since Release 1.4.0a12
- */
-
-/**
- * For downloading REST xml/txt files
- */
-require_once 'PEAR/REST.php';
-
-/**
- * Implement REST 1.0
- *
- * @category   pear
- * @package    PEAR
- * @author     Greg Beaver 
- * @copyright  1997-2005 The PHP Group
- * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
- * @version    Release: 1.4.5
- * @link       http://pear.php.net/package/PEAR
- * @since      Class available since Release 1.4.0a12
- */
-class PEAR_REST_10
-{
-    /**
-     * @var PEAR_REST
-     */
-    var $_rest;
-    function PEAR_REST_10($config, $options = array())
-    {
-        $this->_rest = &new PEAR_REST($config, $options);
-    }
-
-    function getDownloadURL($base, $packageinfo, $prefstate, $installed)
-    {
-        $channel = $packageinfo['channel'];
-        $package = $packageinfo['package'];
-        $states = $this->betterStates($prefstate, true);
-        if (!$states) {
-            return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
-        }
-        $state = $version = null;
-        if (isset($packageinfo['state'])) {
-            $state = $packageinfo['state'];
-        }
-        if (isset($packageinfo['version'])) {
-            $version = $packageinfo['version'];
-        }
-        $info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . '/allreleases.xml');
-        if (PEAR::isError($info)) {
-            return PEAR::raiseError('No releases available for package "' .
-                $channel . '/' . $package . '"');
-        }
-        if (!isset($info['r'])) {
-            return false;
-        }
-        $found = false;
-        $release = false;
-        if (!is_array($info['r']) || !isset($info['r'][0])) {
-            $info['r'] = array($info['r']);
-        }
-        foreach ($info['r'] as $release) {
-            if (!isset($this->_rest->_options['force']) && ($installed &&
-                  version_compare($release['v'], $installed, '<'))) {
-                continue;
-            }
-            if (isset($state)) {
-                if ($release['s'] == $state) {
-                    $found = true;
-                    break;
-                }
-            } elseif (isset($version)) {
-                if ($release['v'] == $version) {
-                    $found = true;
-                    break;
-                }
-            } else {
-                if (in_array($release['s'], $states)) {
-                    $found = true;
-                    break;
-                }
-            }
-        }
-        return $this->_returnDownloadURL($base, $package, $release, $info, $found);
-    }
-
-    function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage,
-                               $prefstate = 'stable', $installed = false)
-    {
-        $channel = $dependency['channel'];
-        $package = $dependency['name'];
-        $states = $this->betterStates($prefstate, true);
-        if (!$states) {
-            return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
-        }
-        $state = $version = null;
-        if (isset($packageinfo['state'])) {
-            $state = $packageinfo['state'];
-        }
-        if (isset($packageinfo['version'])) {
-            $version = $packageinfo['version'];
-        }
-        $info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . '/allreleases.xml');
-        if (PEAR::isError($info)) {
-            return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package']
-                . '" dependency "' . $channel . '/' . $package . '" has no releases');
-        }
-        if (!is_array($info) || !isset($info['r'])) {
-            return false;
-        }
-        $exclude = array();
-        $min = $max = $recommended = false;
-        if ($xsdversion == '1.0') {
-            $pinfo['package'] = $dependency['name'];
-            $pinfo['channel'] = 'pear.php.net'; // this is always true - don't change this
-            switch ($dependency['rel']) {
-                case 'ge' :
-                    $min = $dependency['version'];
-                break;
-                case 'gt' :
-                    $min = $dependency['version'];
-                    $exclude = array($dependency['version']);
-                break;
-                case 'eq' :
-                    $recommended = $dependency['version'];
-                break;
-                case 'lt' :
-                    $max = $dependency['version'];
-                    $exclude = array($dependency['version']);
-                break;
-                case 'le' :
-                    $max = $dependency['version'];
-                break;
-                case 'ne' :
-                    $exclude = array($dependency['version']);
-                break;
-            }
-        } else {
-            $pinfo['package'] = $dependency['name'];
-            $min = isset($dependency['min']) ? $dependency['min'] : false;
-            $max = isset($dependency['max']) ? $dependency['max'] : false;
-            $recommended = isset($dependency['recommended']) ?
-                $dependency['recommended'] : false;
-            if (isset($dependency['exclude'])) {
-                if (!isset($dependency['exclude'][0])) {
-                    $exclude = array($dependency['exclude']);
-                }
-            }
-        }
-        $found = false;
-        $release = false;
-        if (!is_array($info['r']) || !isset($info['r'][0])) {
-            $info['r'] = array($info['r']);
-        }
-        foreach ($info['r'] as $release) {
-            if (!isset($this->_rest->_options['force']) && ($installed &&
-                  version_compare($release['v'], $installed, '<'))) {
-                continue;
-            }
-            if (in_array($release['v'], $exclude)) { // skip excluded versions
-                continue;
-            }
-            // allow newer releases to say "I'm OK with the dependent package"
-            if ($xsdversion == '2.0' && isset($release['co'])) {
-                if (!is_array($release['co']) || !isset($release['co'][0])) {
-                    $release['co'] = array($release['co']);
-                }
-                foreach ($release['co'] as $entry) {
-                    if (isset($entry['x']) && !is_array($entry['x'])) {
-                        $entry['x'] = array($entry['x']);
-                    } elseif (!isset($entry['x'])) {
-                        $entry['x'] = array();
-                    }
-                    if ($entry['c'] == $deppackage['channel'] &&
-                          strtolower($entry['p']) == strtolower($deppackage['package']) &&
-                          version_compare($deppackage['version'], $entry['min'], '>=') &&
-                          version_compare($deppackage['version'], $entry['max'], '<=') &&
-                          !in_array($release['v'], $entry['x'])) {
-                        $recommended = $release['v'];
-                        break;
-                    }
-                }
-            }
-            if ($recommended) {
-                if ($release['v'] != $recommended) { // if we want a specific
-                    // version, then skip all others
-                    continue;
-                } else {
-                    if (!in_array($release['s'], $states)) {
-                        // the stability is too low, but we must return the
-                        // recommended version if possible
-                        return $this->_returnDownloadURL($base, $package, $release, $info, true);
-                    }
-                }
-            }
-            if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions
-                continue;
-            }
-            if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions
-                continue;
-            }
-            if ($installed && version_compare($release['v'], $installed, '<')) {
-                continue;
-            }
-            if (in_array($release['s'], $states)) { // if in the preferred state...
-                $found = true; // ... then use it
-                break;
-            }
-        }
-        return $this->_returnDownloadURL($base, $package, $release, $info, $found);
-    }
-
-    function _returnDownloadURL($base, $package, $release, $info, $found)
-    {
-        if (!$found) {
-            $release = $info['r'][0];
-        }
-        $releaseinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' . 
-            $release['v'] . '.xml');
-        if (PEAR::isError($releaseinfo)) {
-            return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] .
-                '" does not have REST xml available');
-        }
-        $packagexml = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' .
-            'deps.' . $release['v'] . '.txt', false, true);
-        if (PEAR::isError($packagexml)) {
-            return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] .
-                '" does not have REST dependency information available');
-        }
-        $packagexml = unserialize($packagexml);
-        if (!$packagexml) {
-            $packagexml = array();
-        }
-        $allinfo = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
-            '/allreleases.xml');
-        if (!is_array($allinfo['r']) || !isset($allinfo['r'][0])) {
-            $allinfo['r'] = array($allinfo['r']);
-        }
-        $compatible = false;
-        foreach ($allinfo['r'] as $release) {
-            if ($release['v'] != $releaseinfo['v']) {
-                continue;
-            }
-            if (!isset($release['co'])) {
-                break;
-            }
-            $compatible = array();
-            if (!is_array($release['co']) || !isset($release['co'][0])) {
-                $release['co'] = array($release['co']);
-            }
-            foreach ($release['co'] as $entry) {
-                $comp = array();
-                $comp['name'] = $entry['p'];
-                $comp['channel'] = $entry['c'];
-                $comp['min'] = $entry['min'];
-                $comp['max'] = $entry['max'];
-                if (isset($entry['x']) && !is_array($entry['x'])) {
-                    $comp['exclude'] = $entry['x'];
-                }
-                $compatible[] = $comp;
-            }
-            if (count($compatible) == 1) {
-                $compatible = $compatible[0];
-            }
-            break;
-        }
-        if ($found) {
-            return 
-                array('version' => $releaseinfo['v'],
-                      'info' => $packagexml,
-                      'package' => $releaseinfo['p']['_content'],
-                      'stability' => $releaseinfo['st'],
-                      'url' => $releaseinfo['g'],
-                      'compatible' => $compatible);
-        } else {
-            return
-                array('version' => $releaseinfo['v'],
-                      'package' => $releaseinfo['p']['_content'],
-                      'stability' => $releaseinfo['st'],
-                      'info' => $packagexml,
-                      'compatible' => $compatible);
-        }
-    }
-
-    function listPackages($base)
-    {
-        $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml');
-        if (PEAR::isError($packagelist)) {
-            return $packagelist;
-        }
-        if (!is_array($packagelist) || !isset($packagelist['p'])) {
-            return array();
-        }
-        if (!is_array($packagelist['p'])) {
-            $packagelist['p'] = array($packagelist['p']);
-        }
-        return $packagelist['p'];
-    }
-
-    function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false)
-    {
-        $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml');
-        if (PEAR::isError($packagelist)) {
-            return $packagelist;
-        }
-        if ($this->_rest->config->get('verbose') > 0) {
-            $ui = &PEAR_Frontend::singleton();
-            $ui->log('Retrieving data...0%', false);
-        }
-        $ret = array();
-        if (!is_array($packagelist) || !isset($packagelist['p'])) {
-            return $ret;
-        }
-        if (!is_array($packagelist['p'])) {
-            $packagelist['p'] = array($packagelist['p']);
-        }
-        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
-        $next = .1;
-        foreach ($packagelist['p'] as $progress => $package) {
-            if ($this->_rest->config->get('verbose') > 0) {
-                if ($progress / count($packagelist['p']) >= $next) {
-                    if ($next == .5) {
-                        $ui->log('50%', false);
-                    } else {
-                        $ui->log('.', false);
-                    }
-                    $next += .1;
-                }
-            }
-            if ($basic) { // remote-list command
-                if ($dostable) {
-                    $latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
-                        '/stable.txt');
-                } else {
-                    $latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
-                        '/latest.txt');
-                }
-                if (PEAR::isError($latest)) {
-                    $latest = false;
-                }
-                $info = array('stable' => $latest);
-            } else { // list-all command
-                $inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml');
-                if (PEAR::isError($inf)) {
-                    PEAR::popErrorHandling();
-                    return $inf;
-                }
-                if ($searchpackage) {
-                    $found = (!empty($searchpackage) && stristr($package, $searchpackage) !== false);
-                    if (!$found && !(isset($searchsummary) && !empty($searchsummary)
-                        && (stristr($inf['s'], $searchsummary) !== false
-                            || stristr($inf['d'], $searchsummary) !== false)))
-                    {
-                        continue;
-                    };
-                }
-                $releases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
-                    '/allreleases.xml');
-                if (PEAR::isError($releases)) {
-                    continue;
-                }
-                if (!isset($releases['r'][0])) {
-                    $releases['r'] = array($releases['r']);
-                }
-                unset($latest);
-                unset($unstable);
-                unset($stable);
-                unset($state);
-                foreach ($releases['r'] as $release) {
-                    if (!isset($latest)) {
-                        if ($dostable && $release['s'] == 'stable') {
-                            $latest = $release['v'];
-                            $state = 'stable';
-                        }
-                        if (!$dostable) {
-                            $latest = $release['v'];
-                            $state = $release['s'];
-                        }
-                    }
-                    if (!isset($stable) && $release['s'] == 'stable') {
-                        $stable = $release['v'];
-                        if (!isset($unstable)) {
-                            $unstable = $stable;
-                        }
-                    }
-                    if (!isset($unstable) && $release['s'] != 'stable') {
-                        $latest = $unstable = $release['v'];
-                        $state = $release['s'];
-                    }
-                    if (isset($latest) && !isset($state)) {
-                        $state = $release['s'];
-                    }
-                    if (isset($latest) && isset($stable) && isset($unstable)) {
-                        break;
-                    }
-                }
-                $deps = array();
-                if (!isset($unstable)) {
-                    $unstable = false;
-                    $state = 'stable';
-                    if (isset($stable)) {
-                        $latest = $unstable = $stable;
-                    }
-                } else {
-                    $latest = $unstable;
-                }
-                if (!isset($latest)) {
-                    $latest = false;
-                }
-                if ($latest) {
-                    $d = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' .
-                        $latest . '.txt');
-                    if (!PEAR::isError($d)) {
-                        $d = unserialize($d);
-                        if ($d) {
-                            if (isset($d['required'])) {
-                                if (!class_exists('PEAR_PackageFile_v2')) {
-                                    require_once 'PEAR/PackageFile/v2.php';
-                                }
-                                if (!isset($pf)) {
-                                    $pf = new PEAR_PackageFile_v2;
-                                }
-                                $pf->setDeps($d);
-                                $tdeps = $pf->getDeps();
-                            } else {
-                                $tdeps = $d;
-                            }
-                            foreach ($tdeps as $dep) {
-                                if ($dep['type'] !== 'pkg') {
-                                    continue;
-                                }
-                                $deps[] = $dep;
-                            }
-                        }
-                    }
-                }
-                if (!isset($stable)) {
-                    $stable = '-n/a-';
-                }
-                if (!$searchpackage) {
-                    $info = array('stable' => $latest, 'summary' => $inf['s'], 'description' =>
-                        $inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'],
-                        'unstable' => $unstable, 'state' => $state);
-                } else {
-                    $info = array('stable' => $stable, 'summary' => $inf['s'], 'description' =>
-                        $inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'],
-                        'unstable' => $unstable, 'state' => $state);
-                }
-            }
-            $ret[$package] = $info;
-        }
-        PEAR::popErrorHandling();
-        return $ret;
-    }
-
-    function listLatestUpgrades($base, $state, $installed, $channel, &$reg)
-    {
-        $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml');
-        if (PEAR::isError($packagelist)) {
-            return $packagelist;
-        }
-        $ret = array();
-        if (!is_array($packagelist) || !isset($packagelist['p'])) {
-            return $ret;
-        }
-        if (!is_array($packagelist['p'])) {
-            $packagelist['p'] = array($packagelist['p']);
-        }
-        if ($state) {
-            $states = $this->betterStates($state, true);
-        }
-        foreach ($packagelist['p'] as $package) {
-            if (!isset($installed[strtolower($package)])) {
-                continue;
-            }
-            $inst_version = $reg->packageInfo($package, 'version', $channel);
-            PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
-            $info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
-                '/allreleases.xml');
-            PEAR::popErrorHandling();
-            if (PEAR::isError($info)) {
-                continue; // no remote releases
-            }
-            if (!isset($info['r'])) {
-                continue;
-            }
-            $found = false;
-            $release = false;
-            if (!is_array($info['r']) || !isset($info['r'][0])) {
-                $info['r'] = array($info['r']);
-            }
-            foreach ($info['r'] as $release) {
-                if ($inst_version && version_compare($release['v'], $inst_version, '<=')) {
-                    continue;
-                }
-                if ($state) {
-                    if (in_array($release['s'], $states)) {
-                        $found = true;
-                        break;
-                    }
-                } else {
-                    $found = true;
-                    break;
-                }
-            }
-            if (!$found) {
-                continue;
-            }
-            $relinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' . 
-                $release['v'] . '.xml');
-            if (PEAR::isError($relinfo)) {
-                return $relinfo;
-            }
-            $ret[$package] = array(
-                    'version' => $release['v'],
-                    'state' => $release['s'],
-                    'filesize' => $relinfo['f'],
-                );
-        }
-        return $ret;
-    }
-
-    function packageInfo($base, $package)
-    {
-        PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
-        $pinfo = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml');
-        if (PEAR::isError($pinfo)) {
-            PEAR::popErrorHandling();
-            return PEAR::raiseError('Unknown package: "' . $package . '" (Debug: ' .
-                $pinfo->getMessage() . ')');
-        }
-        $releases = array();
-        $allreleases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
-            '/allreleases.xml');
-        if (!PEAR::isError($allreleases)) {
-            if (!class_exists('PEAR_PackageFile_v2')) {
-                require_once 'PEAR/PackageFile/v2.php';
-            }
-            if (!is_array($allreleases['r'])) {
-                $allreleases['r'] = array($allreleases['r']);
-            }
-            $pf = new PEAR_PackageFile_v2;
-            foreach ($allreleases['r'] as $release) {
-                $ds = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' .
-                    $release['v'] . '.txt');
-                if (PEAR::isError($ds)) {
-                    continue;
-                }
-                if (!isset($latest)) {
-                    $latest = $release['v'];
-                }
-                $pf->setDeps(unserialize($ds));
-                $ds = $pf->getDeps();
-                $info = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package)
-                    . '/' . $release['v'] . '.xml');
-                if (PEAR::isError($info)) {
-                    continue;
-                }
-                $releases[$release['v']] = array(
-                    'doneby' => $info['m'],
-                    'license' => $info['l'],
-                    'summary' => $info['s'],
-                    'description' => $info['d'],
-                    'releasedate' => $info['da'],
-                    'releasenotes' => $info['n'],
-                    'state' => $release['s'],
-                    'deps' => $ds ? $ds : array(),
-                );
-            }
-        } else {
-            $latest = '';
-        }
-        PEAR::popErrorHandling();
-        return array(
-            'name' => $pinfo['n'],
-            'channel' => $pinfo['c'],
-            'category' => $pinfo['ca']['_content'],
-            'stable' => $latest,
-            'license' => $pinfo['l'],
-            'summary' => $pinfo['s'],
-            'description' => $pinfo['d'],
-            'releases' => $releases,
-            );
-    }
-
-    /**
-     * Return an array containing all of the states that are more stable than
-     * or equal to the passed in state
-     *
-     * @param string Release state
-     * @param boolean Determines whether to include $state in the list
-     * @return false|array False if $state is not a valid release state
-     */
-    function betterStates($state, $include = false)
-    {
-        static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
-        $i = array_search($state, $states);
-        if ($i === false) {
-            return false;
-        }
-        if ($include) {
-            $i--;
-        }
-        return array_slice($states, $i + 1);
-    }
-}
+
+ * @copyright  1997-2008 The PHP Group
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version    CVS: $Id: 10.php,v 1.53 2008/04/11 01:16:40 dufuz Exp $
+ * @link       http://pear.php.net/package/PEAR
+ * @since      File available since Release 1.4.0a12
+ */
+
+/**
+ * For downloading REST xml/txt files
+ */
+require_once 'PEAR/REST.php';
+
+/**
+ * Implement REST 1.0
+ *
+ * @category   pear
+ * @package    PEAR
+ * @author     Greg Beaver 
+ * @copyright  1997-2008 The PHP Group
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version    Release: 1.7.2
+ * @link       http://pear.php.net/package/PEAR
+ * @since      Class available since Release 1.4.0a12
+ */
+class PEAR_REST_10
+{
+    /**
+     * @var PEAR_REST
+     */
+    var $_rest;
+    function PEAR_REST_10($config, $options = array())
+    {
+        $this->_rest = &new PEAR_REST($config, $options);
+    }
+
+    /**
+     * Retrieve information about a remote package to be downloaded from a REST server
+     *
+     * @param string $base The uri to prepend to all REST calls
+     * @param array $packageinfo an array of format:
+     * 
+     *  array(
+     *   'package' => 'packagename',
+     *   'channel' => 'channelname',
+     *  ['state' => 'alpha' (or valid state),]
+     *  -or-
+     *  ['version' => '1.whatever']
+     * 
+ * @param string $prefstate Current preferred_state config variable value + * @param bool $installed the installed version of this package to compare against + * @return array|false|PEAR_Error see {@link _returnDownloadURL()} + */ + function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false) + { + $channel = $packageinfo['channel']; + $package = $packageinfo['package']; + $states = $this->betterStates($prefstate, true); + if (!$states) { + return PEAR::raiseError('"' . $prefstate . '" is not a valid state'); + } + $state = isset($packageinfo['state']) ? $packageinfo['state'] : null; + $version = isset($packageinfo['version']) ? $packageinfo['version'] : null; + $info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . '/allreleases.xml', false, false, $channel); + if (PEAR::isError($info)) { + return PEAR::raiseError('No releases available for package "' . + $channel . '/' . $package . '"'); + } + if (!isset($info['r'])) { + return false; + } + $release = $found = false; + if (!is_array($info['r']) || !isset($info['r'][0])) { + $info['r'] = array($info['r']); + } + foreach ($info['r'] as $release) { + if (!isset($this->_rest->_options['force']) && ($installed && + version_compare($release['v'], $installed, '<'))) { + continue; + } + if (isset($state)) { + // try our preferred state first + if ($release['s'] == $state) { + $found = true; + break; + } + // see if there is something newer and more stable + // bug #7221 + if (in_array($release['s'], $this->betterStates($state), true)) { + $found = true; + break; + } + } elseif (isset($version)) { + if ($release['v'] == $version) { + $found = true; + break; + } + } else { + if (in_array($release['s'], $states)) { + $found = true; + break; + } + } + } + return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel); + } + + function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage, + $prefstate = 'stable', $installed = false, $channel = false) + { + $channel = $dependency['channel']; + $package = $dependency['name']; + $states = $this->betterStates($prefstate, true); + if (!$states) { + return PEAR::raiseError('"' . $prefstate . '" is not a valid state'); + } + $state = isset($dependency['state']) ? $dependency['state'] : null; + $version = isset($dependency['version']) ? $dependency['version'] : null; + $info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . '/allreleases.xml', false, false, $channel); + if (PEAR::isError($info)) { + return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package'] + . '" dependency "' . $channel . '/' . $package . '" has no releases'); + } + if (!is_array($info) || !isset($info['r'])) { + return false; + } + $exclude = array(); + $min = $max = $recommended = false; + if ($xsdversion == '1.0') { + switch ($dependency['rel']) { + case 'ge' : + $min = $dependency['version']; + break; + case 'gt' : + $min = $dependency['version']; + $exclude = array($dependency['version']); + break; + case 'eq' : + $recommended = $dependency['version']; + break; + case 'lt' : + $max = $dependency['version']; + $exclude = array($dependency['version']); + break; + case 'le' : + $max = $dependency['version']; + break; + case 'ne' : + $exclude = array($dependency['version']); + break; + } + } else { + $min = isset($dependency['min']) ? $dependency['min'] : false; + $max = isset($dependency['max']) ? $dependency['max'] : false; + $recommended = isset($dependency['recommended']) ? + $dependency['recommended'] : false; + if (isset($dependency['exclude'])) { + if (!isset($dependency['exclude'][0])) { + $exclude = array($dependency['exclude']); + } + } + } + $release = $found = false; + if (!is_array($info['r']) || !isset($info['r'][0])) { + $info['r'] = array($info['r']); + } + foreach ($info['r'] as $release) { + if (!isset($this->_rest->_options['force']) && ($installed && + version_compare($release['v'], $installed, '<'))) { + continue; + } + if (in_array($release['v'], $exclude)) { // skip excluded versions + continue; + } + // allow newer releases to say "I'm OK with the dependent package" + if ($xsdversion == '2.0' && isset($release['co'])) { + if (!is_array($release['co']) || !isset($release['co'][0])) { + $release['co'] = array($release['co']); + } + foreach ($release['co'] as $entry) { + if (isset($entry['x']) && !is_array($entry['x'])) { + $entry['x'] = array($entry['x']); + } elseif (!isset($entry['x'])) { + $entry['x'] = array(); + } + if ($entry['c'] == $deppackage['channel'] && + strtolower($entry['p']) == strtolower($deppackage['package']) && + version_compare($deppackage['version'], $entry['min'], '>=') && + version_compare($deppackage['version'], $entry['max'], '<=') && + !in_array($release['v'], $entry['x'])) { + $recommended = $release['v']; + break; + } + } + } + if ($recommended) { + if ($release['v'] != $recommended) { // if we want a specific + // version, then skip all others + continue; + } else { + if (!in_array($release['s'], $states)) { + // the stability is too low, but we must return the + // recommended version if possible + return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel); + } + } + } + if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions + continue; + } + if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions + continue; + } + if ($installed && version_compare($release['v'], $installed, '<')) { + continue; + } + if (in_array($release['s'], $states)) { // if in the preferred state... + $found = true; // ... then use it + break; + } + } + return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel); + } + + /** + * Take raw data and return the array needed for processing a download URL + * + * @param string $base REST base uri + * @param string $package Package name + * @param array $release an array of format array('v' => version, 's' => state) + * describing the release to download + * @param array $info list of all releases as defined by allreleases.xml + * @param bool|null $found determines whether the release was found or this is the next + * best alternative. If null, then versions were skipped because + * of PHP dependency + * @return array|PEAR_Error + * @access private + */ + function _returnDownloadURL($base, $package, $release, $info, $found, $phpversion = false, $channel = false) + { + if (!$found) { + $release = $info['r'][0]; + } + $pinfo = $this->_rest->retrieveCacheFirst($base . 'p/' . strtolower($package) . '/' . + 'info.xml', false, false, $channel); + if (PEAR::isError($pinfo)) { + return PEAR::raiseError('Package "' . $package . + '" does not have REST info xml available'); + } + $releaseinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' . + $release['v'] . '.xml', false, false, $channel); + if (PEAR::isError($releaseinfo)) { + return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] . + '" does not have REST xml available'); + } + $packagexml = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' . + 'deps.' . $release['v'] . '.txt', false, true, $channel); + if (PEAR::isError($packagexml)) { + return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] . + '" does not have REST dependency information available'); + } + $packagexml = unserialize($packagexml); + if (!$packagexml) { + $packagexml = array(); + } + $allinfo = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . + '/allreleases.xml', false, false, $channel); + if (!is_array($allinfo['r']) || !isset($allinfo['r'][0])) { + $allinfo['r'] = array($allinfo['r']); + } + $compatible = false; + foreach ($allinfo['r'] as $release) { + if ($release['v'] != $releaseinfo['v']) { + continue; + } + if (!isset($release['co'])) { + break; + } + $compatible = array(); + if (!is_array($release['co']) || !isset($release['co'][0])) { + $release['co'] = array($release['co']); + } + foreach ($release['co'] as $entry) { + $comp = array(); + $comp['name'] = $entry['p']; + $comp['channel'] = $entry['c']; + $comp['min'] = $entry['min']; + $comp['max'] = $entry['max']; + if (isset($entry['x']) && !is_array($entry['x'])) { + $comp['exclude'] = $entry['x']; + } + $compatible[] = $comp; + } + if (count($compatible) == 1) { + $compatible = $compatible[0]; + } + break; + } + if (isset($pinfo['dc']) && isset($pinfo['dp'])) { + if (is_array($pinfo['dp'])) { + $deprecated = array('channel' => (string) $pinfo['dc'], + 'package' => trim($pinfo['dp']['_content'])); + } else { + $deprecated = array('channel' => (string) $pinfo['dc'], + 'package' => trim($pinfo['dp'])); + } + } else { + $deprecated = false; + } + if ($found) { + return + array('version' => $releaseinfo['v'], + 'info' => $packagexml, + 'package' => $releaseinfo['p']['_content'], + 'stability' => $releaseinfo['st'], + 'url' => $releaseinfo['g'], + 'compatible' => $compatible, + 'deprecated' => $deprecated, + ); + } else { + return + array('version' => $releaseinfo['v'], + 'package' => $releaseinfo['p']['_content'], + 'stability' => $releaseinfo['st'], + 'info' => $packagexml, + 'compatible' => $compatible, + 'deprecated' => $deprecated, + 'php' => $phpversion + ); + } + } + + function listPackages($base, $channel = false) + { + $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel); + if (PEAR::isError($packagelist)) { + return $packagelist; + } + if (!is_array($packagelist) || !isset($packagelist['p'])) { + return array(); + } + if (!is_array($packagelist['p'])) { + $packagelist['p'] = array($packagelist['p']); + } + return $packagelist['p']; + } + + /** + * List all categories of a REST server + * + * @param string $base base URL of the server + * @return array of categorynames + */ + function listCategories($base, $channel = false) + { + $categories = array(); + + // c/categories.xml does not exist; + // check for every package its category manually + // This is SLOOOWWWW : /// + $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel); + if (PEAR::isError($packagelist)) { + return $packagelist; + } + if (!is_array($packagelist) || !isset($packagelist['p'])) { + $ret = array(); + return $ret; + } + if (!is_array($packagelist['p'])) { + $packagelist['p'] = array($packagelist['p']); + } + + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + foreach ($packagelist['p'] as $package) { + $inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel); + if (PEAR::isError($inf)) { + PEAR::popErrorHandling(); + return $inf; + } + $cat = $inf['ca']['_content']; + if (!isset($categories[$cat])) { + $categories[$cat] = $inf['ca']; + } + } + return array_values($categories); + } + + /** + * List a category of a REST server + * + * @param string $base base URL of the server + * @param string $category name of the category + * @param boolean $info also download full package info + * @return array of packagenames + */ + function listCategory($base, $category, $info = false, $channel = false) + { + // gives '404 Not Found' error when category doesn't exist + $packagelist = $this->_rest->retrieveData($base.'c/'.urlencode($category).'/packages.xml', false, false, $channel); + if (PEAR::isError($packagelist)) { + return $packagelist; + } + if (!is_array($packagelist) || !isset($packagelist['p'])) { + return array(); + } + if (!is_array($packagelist['p']) || + !isset($packagelist['p'][0])) { // only 1 pkg + $packagelist = array($packagelist['p']); + } else { + $packagelist = $packagelist['p']; + } + + if ($info == true) { + // get individual package info + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + foreach ($packagelist as $i => $packageitem) { + $url = sprintf('%s'.'r/%s/latest.txt', + $base, + strtolower($packageitem['_content'])); + $version = $this->_rest->retrieveData($url, false, false, $channel); + if (PEAR::isError($version)) { + break; // skipit + } + $url = sprintf('%s'.'r/%s/%s.xml', + $base, + strtolower($packageitem['_content']), + $version); + $info = $this->_rest->retrieveData($url, false, false, $channel); + if (PEAR::isError($info)) { + break; // skipit + } + $packagelist[$i]['info'] = $info; + } + PEAR::popErrorHandling(); + } + + return $packagelist; + } + + + function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false, $channel = false) + { + $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel); + if (PEAR::isError($packagelist)) { + return $packagelist; + } + if ($this->_rest->config->get('verbose') > 0) { + $ui = &PEAR_Frontend::singleton(); + $ui->log('Retrieving data...0%', false); + } + $ret = array(); + if (!is_array($packagelist) || !isset($packagelist['p'])) { + return $ret; + } + if (!is_array($packagelist['p'])) { + $packagelist['p'] = array($packagelist['p']); + } + + // only search-packagename = quicksearch ! + if ($searchpackage && (!$searchsummary || empty($searchpackage))) { + $newpackagelist = array(); + foreach ($packagelist['p'] as $package) { + if (!empty($searchpackage) && stristr($package, $searchpackage) !== false) { + $newpackagelist[] = $package; + } + } + $packagelist['p'] = $newpackagelist; + } + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $next = .1; + foreach ($packagelist['p'] as $progress => $package) { + if ($this->_rest->config->get('verbose') > 0) { + if ($progress / count($packagelist['p']) >= $next) { + if ($next == .5) { + $ui->log('50%', false); + } else { + $ui->log('.', false); + } + $next += .1; + } + } + if ($basic) { // remote-list command + if ($dostable) { + $latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . + '/stable.txt', false, false, $channel); + } else { + $latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . + '/latest.txt', false, false, $channel); + } + if (PEAR::isError($latest)) { + $latest = false; + } + $info = array('stable' => $latest); + } else { // list-all command + $inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel); + if (PEAR::isError($inf)) { + PEAR::popErrorHandling(); + return $inf; + } + if ($searchpackage) { + $found = (!empty($searchpackage) && stristr($package, $searchpackage) !== false); + if (!$found && !(isset($searchsummary) && !empty($searchsummary) + && (stristr($inf['s'], $searchsummary) !== false + || stristr($inf['d'], $searchsummary) !== false))) + { + continue; + }; + } + $releases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . + '/allreleases.xml', false, false, $channel); + if (PEAR::isError($releases)) { + continue; + } + if (!isset($releases['r'][0])) { + $releases['r'] = array($releases['r']); + } + unset($latest); + unset($unstable); + unset($stable); + unset($state); + foreach ($releases['r'] as $release) { + if (!isset($latest)) { + if ($dostable && $release['s'] == 'stable') { + $latest = $release['v']; + $state = 'stable'; + } + if (!$dostable) { + $latest = $release['v']; + $state = $release['s']; + } + } + if (!isset($stable) && $release['s'] == 'stable') { + $stable = $release['v']; + if (!isset($unstable)) { + $unstable = $stable; + } + } + if (!isset($unstable) && $release['s'] != 'stable') { + $latest = $unstable = $release['v']; + $state = $release['s']; + } + if (isset($latest) && !isset($state)) { + $state = $release['s']; + } + if (isset($latest) && isset($stable) && isset($unstable)) { + break; + } + } + $deps = array(); + if (!isset($unstable)) { + $unstable = false; + $state = 'stable'; + if (isset($stable)) { + $latest = $unstable = $stable; + } + } else { + $latest = $unstable; + } + if (!isset($latest)) { + $latest = false; + } + if ($latest) { + $d = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' . + $latest . '.txt', false, false, $channel); + if (!PEAR::isError($d)) { + $d = unserialize($d); + if ($d) { + if (isset($d['required'])) { + if (!class_exists('PEAR_PackageFile_v2')) { + require_once 'PEAR/PackageFile/v2.php'; + } + if (!isset($pf)) { + $pf = new PEAR_PackageFile_v2; + } + $pf->setDeps($d); + $tdeps = $pf->getDeps(); + } else { + $tdeps = $d; + } + foreach ($tdeps as $dep) { + if ($dep['type'] !== 'pkg') { + continue; + } + $deps[] = $dep; + } + } + } + } + if (!isset($stable)) { + $stable = '-n/a-'; + } + if (!$searchpackage) { + $info = array('stable' => $latest, 'summary' => $inf['s'], 'description' => + $inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'], + 'unstable' => $unstable, 'state' => $state); + } else { + $info = array('stable' => $stable, 'summary' => $inf['s'], 'description' => + $inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'], + 'unstable' => $unstable, 'state' => $state); + } + } + $ret[$package] = $info; + } + PEAR::popErrorHandling(); + return $ret; + } + + function listLatestUpgrades($base, $pref_state, $installed, $channel, &$reg) + { + $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel); + if (PEAR::isError($packagelist)) { + return $packagelist; + } + $ret = array(); + if (!is_array($packagelist) || !isset($packagelist['p'])) { + return $ret; + } + if (!is_array($packagelist['p'])) { + $packagelist['p'] = array($packagelist['p']); + } + foreach ($packagelist['p'] as $package) { + if (!isset($installed[strtolower($package)])) { + continue; + } + $inst_version = $reg->packageInfo($package, 'version', $channel); + $inst_state = $reg->packageInfo($package, 'release_state', $channel); + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . + '/allreleases.xml', false, false, $channel); + PEAR::popErrorHandling(); + if (PEAR::isError($info)) { + continue; // no remote releases + } + if (!isset($info['r'])) { + continue; + } + $found = false; + $release = false; + if (!is_array($info['r']) || !isset($info['r'][0])) { + $info['r'] = array($info['r']); + } + // $info['r'] is sorted by version number + foreach ($info['r'] as $release) { + if ($inst_version && version_compare($release['v'], $inst_version, '<=')) { + // not newer than the one installed + break; + } + + // new version > installed version + if (!$pref_state) { + // every state is a good state + $found = true; + break; + } else { + $new_state = $release['s']; + // if new state >= installed state: go + if (in_array($new_state, $this->betterStates($inst_state, true))) { + $found = true; + break; + } else { + // only allow to lower the state of package, + // if new state >= preferred state: go + if (in_array($new_state, $this->betterStates($pref_state, true))) { + $found = true; + break; + } + } + } + } + if (!$found) { + continue; + } + $relinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' . + $release['v'] . '.xml', false, false, $channel); + if (PEAR::isError($relinfo)) { + return $relinfo; + } + $ret[$package] = array( + 'version' => $release['v'], + 'state' => $release['s'], + 'filesize' => $relinfo['f'], + ); + } + return $ret; + } + + function packageInfo($base, $package, $channel = false) + { + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $pinfo = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel); + if (PEAR::isError($pinfo)) { + PEAR::popErrorHandling(); + return PEAR::raiseError('Unknown package: "' . $package . '" (Debug: ' . + $pinfo->getMessage() . ')'); + } + $releases = array(); + $allreleases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . + '/allreleases.xml', false, false, $channel); + if (!PEAR::isError($allreleases)) { + if (!class_exists('PEAR_PackageFile_v2')) { + require_once 'PEAR/PackageFile/v2.php'; + } + if (!is_array($allreleases['r']) || !isset($allreleases['r'][0])) { + $allreleases['r'] = array($allreleases['r']); + } + $pf = new PEAR_PackageFile_v2; + foreach ($allreleases['r'] as $release) { + $ds = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' . + $release['v'] . '.txt', false, false, $channel); + if (PEAR::isError($ds)) { + continue; + } + if (!isset($latest)) { + $latest = $release['v']; + } + $pf->setDeps(unserialize($ds)); + $ds = $pf->getDeps(); + $info = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) + . '/' . $release['v'] . '.xml', false, false, $channel); + if (PEAR::isError($info)) { + continue; + } + $releases[$release['v']] = array( + 'doneby' => $info['m'], + 'license' => $info['l'], + 'summary' => $info['s'], + 'description' => $info['d'], + 'releasedate' => $info['da'], + 'releasenotes' => $info['n'], + 'state' => $release['s'], + 'deps' => $ds ? $ds : array(), + ); + } + } else { + $latest = ''; + } + PEAR::popErrorHandling(); + if (isset($pinfo['dc']) && isset($pinfo['dp'])) { + if (is_array($pinfo['dp'])) { + $deprecated = array('channel' => (string) $pinfo['dc'], + 'package' => trim($pinfo['dp']['_content'])); + } else { + $deprecated = array('channel' => (string) $pinfo['dc'], + 'package' => trim($pinfo['dp'])); + } + } else { + $deprecated = false; + } + return array( + 'name' => $pinfo['n'], + 'channel' => $pinfo['c'], + 'category' => $pinfo['ca']['_content'], + 'stable' => $latest, + 'license' => $pinfo['l'], + 'summary' => $pinfo['s'], + 'description' => $pinfo['d'], + 'releases' => $releases, + 'deprecated' => $deprecated, + ); + } + + /** + * Return an array containing all of the states that are more stable than + * or equal to the passed in state + * + * @param string Release state + * @param boolean Determines whether to include $state in the list + * @return false|array False if $state is not a valid release state + */ + function betterStates($state, $include = false) + { + static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable'); + $i = array_search($state, $states); + if ($i === false) { + return false; + } + if ($include) { + $i--; + } + return array_slice($states, $i + 1); + } +} ?> \ No newline at end of file diff --git a/includes/pear/PEAR/REST/11.php b/includes/pear/PEAR/REST/11.php index aaedc468..effa6890 100644 --- a/includes/pear/PEAR/REST/11.php +++ b/includes/pear/PEAR/REST/11.php @@ -1,206 +1,317 @@ - - * @copyright 1997-2005 The PHP Group - * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: 11.php,v 1.2 2005/10/27 05:54:37 cellog Exp $ - * @link http://pear.php.net/package/PEAR - * @since File available since Release 1.4.3 - */ - -/** - * For downloading REST xml/txt files - */ -require_once 'PEAR/REST.php'; - -/** - * Implement REST 1.1 - * - * @category pear - * @package PEAR - * @author Greg Beaver - * @copyright 1997-2005 The PHP Group - * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 - * @link http://pear.php.net/package/PEAR - * @since Class available since Release 1.4.3 - */ -class PEAR_REST_11 -{ - /** - * @var PEAR_REST - */ - var $_rest; - - function PEAR_REST_11($config, $options = array()) - { - $this->_rest = &new PEAR_REST($config, $options); - } - - function listAll($base, $dostable, $basic = true) - { - $categorylist = $this->_rest->retrieveData($base . 'c/categories.xml'); - if (PEAR::isError($categorylist)) { - return $categorylist; - } - $ret = array(); - if (!is_array($categorylist['c'])) { - $categorylist['c'] = array($categorylist['c']); - } - PEAR::pushErrorHandling(PEAR_ERROR_RETURN); - foreach ($categorylist['c'] as $progress => $category) { - $category = $category['_content']; - $packagesinfo = $this->_rest->retrieveData($base . - 'c/' . urlencode($category) . '/packagesinfo.xml'); - if (PEAR::isError($packagesinfo)) { - continue; - } - if (!is_array($packagesinfo) || !isset($packagesinfo['pi'])) { - continue; - } - if (!is_array($packagesinfo['pi']) || !isset($packagesinfo['pi'][0])) { - $packagesinfo['pi'] = array($packagesinfo['pi']); - } - foreach ($packagesinfo['pi'] as $packageinfo) { - $info = $packageinfo['p']; - $package = $info['n']; - $releases = isset($packageinfo['a']) ? $packageinfo['a'] : false; - unset($latest); - unset($unstable); - unset($stable); - unset($state); - if ($releases) { - if (!isset($releases['r'][0])) { - $releases['r'] = array($releases['r']); - } - foreach ($releases['r'] as $release) { - if (!isset($latest)) { - if ($dostable && $release['s'] == 'stable') { - $latest = $release['v']; - $state = 'stable'; - } - if (!$dostable) { - $latest = $release['v']; - $state = $release['s']; - } - } - if (!isset($stable) && $release['s'] == 'stable') { - $stable = $release['v']; - if (!isset($unstable)) { - $unstable = $stable; - } - } - if (!isset($unstable) && $release['s'] != 'stable') { - $latest = $unstable = $release['v']; - $state = $release['s']; - } - if (isset($latest) && !isset($state)) { - $state = $release['s']; - } - if (isset($latest) && isset($stable) && isset($unstable)) { - break; - } - } - } - if ($basic) { // remote-list command - if (!isset($latest)) { - $latest = false; - } - $ret[$package] = array('stable' => $latest); - continue; - } - // list-all command - $deps = array(); - if (!isset($unstable)) { - $unstable = false; - $state = 'stable'; - if (isset($stable)) { - $latest = $unstable = $stable; - } - } else { - $latest = $unstable; - } - if (!isset($latest)) { - $latest = false; - } - if ($latest) { - if (isset($packageinfo['deps'])) { - if (!isset($packageinfo['deps'][0])) { - $packageinfo['deps'] = array($packageinfo['deps']); - } - } - $d = false; - foreach ($packageinfo['deps'] as $dep) { - if ($dep['v'] == $latest) { - $d = unserialize($dep['d']); - } - } - if ($d) { - if (isset($d['required'])) { - if (!class_exists('PEAR_PackageFile_v2')) { - require_once 'PEAR/PackageFile/v2.php'; - } - if (!isset($pf)) { - $pf = new PEAR_PackageFile_v2; - } - $pf->setDeps($d); - $tdeps = $pf->getDeps(); - } else { - $tdeps = $d; - } - foreach ($tdeps as $dep) { - if ($dep['type'] !== 'pkg') { - continue; - } - $deps[] = $dep; - } - } - } - if (!isset($stable)) { - $stable = '-n/a-'; - } - $info = array('stable' => $latest, 'summary' => $info['s'], - 'description' => - $info['d'], 'deps' => $deps, 'category' => $info['ca']['_content'], - 'unstable' => $unstable, 'state' => $state); - $ret[$package] = $info; - } - } - PEAR::popErrorHandling(); - return $ret; - } - - /** - * Return an array containing all of the states that are more stable than - * or equal to the passed in state - * - * @param string Release state - * @param boolean Determines whether to include $state in the list - * @return false|array False if $state is not a valid release state - */ - function betterStates($state, $include = false) - { - static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable'); - $i = array_search($state, $states); - if ($i === false) { - return false; - } - if ($include) { - $i--; - } - return array_slice($states, $i + 1); - } -} + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: 11.php,v 1.14 2008/04/11 01:16:40 dufuz Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.3 + */ + +/** + * For downloading REST xml/txt files + */ +require_once 'PEAR/REST.php'; + +/** + * Implement REST 1.1 + * + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.3 + */ +class PEAR_REST_11 +{ + /** + * @var PEAR_REST + */ + var $_rest; + + function PEAR_REST_11($config, $options = array()) + { + $this->_rest = &new PEAR_REST($config, $options); + } + + function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false, $channel = false) + { + $categorylist = $this->_rest->retrieveData($base . 'c/categories.xml', false, false, $channel); + if (PEAR::isError($categorylist)) { + return $categorylist; + } + $ret = array(); + if (!is_array($categorylist['c']) || !isset($categorylist['c'][0])) { + $categorylist['c'] = array($categorylist['c']); + } + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + + foreach ($categorylist['c'] as $progress => $category) { + $category = $category['_content']; + $packagesinfo = $this->_rest->retrieveData($base . + 'c/' . urlencode($category) . '/packagesinfo.xml', false, false, $channel); + + if (PEAR::isError($packagesinfo)) { + continue; + } + + if (!is_array($packagesinfo) || !isset($packagesinfo['pi'])) { + continue; + } + + if (!is_array($packagesinfo['pi']) || !isset($packagesinfo['pi'][0])) { + $packagesinfo['pi'] = array($packagesinfo['pi']); + } + + foreach ($packagesinfo['pi'] as $packageinfo) { + $info = $packageinfo['p']; + $package = $info['n']; + $releases = isset($packageinfo['a']) ? $packageinfo['a'] : false; + unset($latest); + unset($unstable); + unset($stable); + unset($state); + + if ($releases) { + if (!isset($releases['r'][0])) { + $releases['r'] = array($releases['r']); + } + foreach ($releases['r'] as $release) { + if (!isset($latest)) { + if ($dostable && $release['s'] == 'stable') { + $latest = $release['v']; + $state = 'stable'; + } + if (!$dostable) { + $latest = $release['v']; + $state = $release['s']; + } + } + if (!isset($stable) && $release['s'] == 'stable') { + $stable = $release['v']; + if (!isset($unstable)) { + $unstable = $stable; + } + } + if (!isset($unstable) && $release['s'] != 'stable') { + $unstable = $release['v']; + $state = $release['s']; + } + if (isset($latest) && !isset($state)) { + $state = $release['s']; + } + if (isset($latest) && isset($stable) && isset($unstable)) { + break; + } + } + } + + if ($basic) { // remote-list command + if (!isset($latest)) { + $latest = false; + } + if ($dostable) { + // $state is not set if there are no releases + if (isset($state) && $state == 'stable') { + $ret[$package] = array('stable' => $latest); + } else { + $ret[$package] = array('stable' => '-n/a-'); + } + } else { + $ret[$package] = array('stable' => $latest); + } + continue; + } + + // list-all command + $deps = array(); + if (!isset($unstable)) { + $unstable = false; + $state = 'stable'; + if (isset($stable)) { + $latest = $unstable = $stable; + } + } else { + $latest = $unstable; + } + + if (!isset($latest)) { + $latest = false; + } + + if ($latest && isset($packageinfo['deps'])) { + if (!is_array($packageinfo['deps']) || + !isset($packageinfo['deps'][0])) { + $packageinfo['deps'] = array($packageinfo['deps']); + } + $d = false; + foreach ($packageinfo['deps'] as $dep) { + if ($dep['v'] == $latest) { + $d = unserialize($dep['d']); + } + } + if ($d) { + if (isset($d['required'])) { + if (!class_exists('PEAR_PackageFile_v2')) { + require_once 'PEAR/PackageFile/v2.php'; + } + if (!isset($pf)) { + $pf = new PEAR_PackageFile_v2; + } + $pf->setDeps($d); + $tdeps = $pf->getDeps(); + } else { + $tdeps = $d; + } + foreach ($tdeps as $dep) { + if ($dep['type'] !== 'pkg') { + continue; + } + $deps[] = $dep; + } + } + } + + $info = array('stable' => $latest, 'summary' => $info['s'], + 'description' => + $info['d'], 'deps' => $deps, 'category' => $info['ca']['_content'], + 'unstable' => $unstable, 'state' => $state); + $ret[$package] = $info; + } + } + PEAR::popErrorHandling(); + return $ret; + } + + /** + * List all categories of a REST server + * + * @param string $base base URL of the server + * @return array of categorynames + */ + function listCategories($base, $channel = false) + { + $categorylist = $this->_rest->retrieveData($base . 'c/categories.xml', false, false, $channel); + if (PEAR::isError($categorylist)) { + return $categorylist; + } + if (!is_array($categorylist) || !isset($categorylist['c'])) { + return array(); + } + if (isset($categorylist['c']['_content'])) { + // only 1 category + $categorylist['c'] = array($categorylist['c']); + } + return $categorylist['c']; + } + + /** + * List packages in a category of a REST server + * + * @param string $base base URL of the server + * @param string $category name of the category + * @param boolean $info also download full package info + * @return array of packagenames + */ + function listCategory($base, $category, $info = false, $channel = false) + { + if ($info == false) { + $url = '%s'.'c/%s/packages.xml'; + } else { + $url = '%s'.'c/%s/packagesinfo.xml'; + } + $url = sprintf($url, + $base, + urlencode($category)); + + // gives '404 Not Found' error when category doesn't exist + $packagelist = $this->_rest->retrieveData($url, false, false, $channel); + if (PEAR::isError($packagelist)) { + return $packagelist; + } + if (!is_array($packagelist)) { + return array(); + } + + if ($info == false) { + if (!isset($packagelist['p'])) { + return array(); + } + if (!is_array($packagelist['p']) || + !isset($packagelist['p'][0])) { // only 1 pkg + $packagelist = array($packagelist['p']); + } else { + $packagelist = $packagelist['p']; + } + return $packagelist; + } else { + // info == true + if (!isset($packagelist['pi'])) { + return array(); + } + if (!is_array($packagelist['pi']) || + !isset($packagelist['pi'][0])) { // only 1 pkg + $packagelist_pre = array($packagelist['pi']); + } else { + $packagelist_pre = $packagelist['pi']; + } + + $packagelist = array(); + foreach ($packagelist_pre as $i => $item) { + // compatibility with r/.xml + if (isset($item['a']['r'][0])) { + // multiple releases + $item['p']['v'] = $item['a']['r'][0]['v']; + $item['p']['st'] = $item['a']['r'][0]['s']; + } elseif (isset($item['a'])) { + // first and only release + $item['p']['v'] = $item['a']['r']['v']; + $item['p']['st'] = $item['a']['r']['s']; + } + + $packagelist[$i] = array('attribs' => $item['p']['r'], + '_content' => $item['p']['n'], + 'info' => $item['p']); + } + } + + return $packagelist; + } + + /** + * Return an array containing all of the states that are more stable than + * or equal to the passed in state + * + * @param string Release state + * @param boolean Determines whether to include $state in the list + * @return false|array False if $state is not a valid release state + */ + function betterStates($state, $include = false) + { + static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable'); + $i = array_search($state, $states); + if ($i === false) { + return false; + } + if ($include) { + $i--; + } + return array_slice($states, $i + 1); + } +} ?> \ No newline at end of file diff --git a/includes/pear/PEAR/REST/13.php b/includes/pear/PEAR/REST/13.php new file mode 100644 index 00000000..875fd390 --- /dev/null +++ b/includes/pear/PEAR/REST/13.php @@ -0,0 +1,280 @@ + + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: 13.php,v 1.6 2008/04/11 01:16:40 dufuz Exp $ + * @link http://pear.php.net/package/PEAR + * @since File available since Release 1.4.0a12 + */ + +/** + * For downloading REST xml/txt files + */ +require_once 'PEAR/REST.php'; +require_once 'PEAR/REST/10.php'; + +/** + * Implement REST 1.3 + * + * @category pear + * @package PEAR + * @author Greg Beaver + * @copyright 1997-2008 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.2 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 1.4.0a12 + */ +class PEAR_REST_13 extends PEAR_REST_10 +{ + /** + * Retrieve information about a remote package to be downloaded from a REST server + * + * This is smart enough to resolve the minimum PHP version dependency prior to download + * @param string $base The uri to prepend to all REST calls + * @param array $packageinfo an array of format: + *
+     *  array(
+     *   'package' => 'packagename',
+     *   'channel' => 'channelname',
+     *  ['state' => 'alpha' (or valid state),]
+     *  -or-
+     *  ['version' => '1.whatever']
+     * 
+ * @param string $prefstate Current preferred_state config variable value + * @param bool $installed the installed version of this package to compare against + * @return array|false|PEAR_Error see {@link _returnDownloadURL()} + */ + function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false) + { + $channel = $packageinfo['channel']; + $package = $packageinfo['package']; + $states = $this->betterStates($prefstate, true); + if (!$states) { + return PEAR::raiseError('"' . $prefstate . '" is not a valid state'); + } + $state = isset($packageinfo['state']) ? $packageinfo['state'] : null; + $version = isset($packageinfo['version']) ? $packageinfo['version'] : null; + $info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . + '/allreleases2.xml'); + if (PEAR::isError($info)) { + return PEAR::raiseError('No releases available for package "' . + $channel . '/' . $package . '"'); + } + if (!isset($info['r'])) { + return false; + } + $release = $found = false; + if (!is_array($info['r']) || !isset($info['r'][0])) { + $info['r'] = array($info['r']); + } + $skippedphp = false; + foreach ($info['r'] as $release) { + if (!isset($this->_rest->_options['force']) && ($installed && + version_compare($release['v'], $installed, '<'))) { + continue; + } + if (isset($state)) { + // try our preferred state first + if ($release['s'] == $state) { + if (!isset($version) && version_compare($release['m'], phpversion(), '>')) { + // skip releases that require a PHP version newer than our PHP version + $skippedphp = $release; + continue; + } + $found = true; + break; + } + // see if there is something newer and more stable + // bug #7221 + if (in_array($release['s'], $this->betterStates($state), true)) { + if (!isset($version) && version_compare($release['m'], phpversion(), '>')) { + // skip releases that require a PHP version newer than our PHP version + $skippedphp = $release; + continue; + } + $found = true; + break; + } + } elseif (isset($version)) { + if ($release['v'] == $version) { + if (!isset($this->_rest->_options['force']) && + !isset($version) && + version_compare($release['m'], phpversion(), '>')) { + // skip releases that require a PHP version newer than our PHP version + $skippedphp = $release; + continue; + } + $found = true; + break; + } + } else { + if (in_array($release['s'], $states)) { + if (version_compare($release['m'], phpversion(), '>')) { + // skip releases that require a PHP version newer than our PHP version + $skippedphp = $release; + continue; + } + $found = true; + break; + } + } + } + if (!$found && $skippedphp) { + $found = null; + } + return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel); + } + + function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage, + $prefstate = 'stable', $installed = false, $channel = false) + { + $channel = $dependency['channel']; + $package = $dependency['name']; + $states = $this->betterStates($prefstate, true); + if (!$states) { + return PEAR::raiseError('"' . $prefstate . '" is not a valid state'); + } + $state = isset($dependency['state']) ? $dependency['state'] : null; + $version = isset($dependency['version']) ? $dependency['version'] : null; + $info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) . + '/allreleases2.xml'); + if (PEAR::isError($info)) { + return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package'] + . '" dependency "' . $channel . '/' . $package . '" has no releases'); + } + if (!is_array($info) || !isset($info['r'])) { + return false; + } + $exclude = array(); + $min = $max = $recommended = false; + if ($xsdversion == '1.0') { + $pinfo['package'] = $dependency['name']; + $pinfo['channel'] = 'pear.php.net'; // this is always true - don't change this + switch ($dependency['rel']) { + case 'ge' : + $min = $dependency['version']; + break; + case 'gt' : + $min = $dependency['version']; + $exclude = array($dependency['version']); + break; + case 'eq' : + $recommended = $dependency['version']; + break; + case 'lt' : + $max = $dependency['version']; + $exclude = array($dependency['version']); + break; + case 'le' : + $max = $dependency['version']; + break; + case 'ne' : + $exclude = array($dependency['version']); + break; + } + } else { + $pinfo['package'] = $dependency['name']; + $min = isset($dependency['min']) ? $dependency['min'] : false; + $max = isset($dependency['max']) ? $dependency['max'] : false; + $recommended = isset($dependency['recommended']) ? + $dependency['recommended'] : false; + if (isset($dependency['exclude'])) { + if (!isset($dependency['exclude'][0])) { + $exclude = array($dependency['exclude']); + } + } + } + $found = false; + $release = false; + $skippedphp = false; + if (!is_array($info['r']) || !isset($info['r'][0])) { + $info['r'] = array($info['r']); + } + foreach ($info['r'] as $release) { + if (!isset($this->_rest->_options['force']) && ($installed && + version_compare($release['v'], $installed, '<'))) { + continue; + } + if (in_array($release['v'], $exclude)) { // skip excluded versions + continue; + } + // allow newer releases to say "I'm OK with the dependent package" + if ($xsdversion == '2.0' && isset($release['co'])) { + if (!is_array($release['co']) || !isset($release['co'][0])) { + $release['co'] = array($release['co']); + } + foreach ($release['co'] as $entry) { + if (isset($entry['x']) && !is_array($entry['x'])) { + $entry['x'] = array($entry['x']); + } elseif (!isset($entry['x'])) { + $entry['x'] = array(); + } + if ($entry['c'] == $deppackage['channel'] && + strtolower($entry['p']) == strtolower($deppackage['package']) && + version_compare($deppackage['version'], $entry['min'], '>=') && + version_compare($deppackage['version'], $entry['max'], '<=') && + !in_array($release['v'], $entry['x'])) { + if (version_compare($release['m'], phpversion(), '>')) { + // skip dependency releases that require a PHP version + // newer than our PHP version + $skippedphp = $release; + continue; + } + $recommended = $release['v']; + break; + } + } + } + if ($recommended) { + if ($release['v'] != $recommended) { // if we want a specific + // version, then skip all others + continue; + } else { + if (!in_array($release['s'], $states)) { + // the stability is too low, but we must return the + // recommended version if possible + return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel); + } + } + } + if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions + continue; + } + if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions + continue; + } + if ($installed && version_compare($release['v'], $installed, '<')) { + continue; + } + if (in_array($release['s'], $states)) { // if in the preferred state... + if (version_compare($release['m'], phpversion(), '>')) { + // skip dependency releases that require a PHP version + // newer than our PHP version + $skippedphp = $release; + continue; + } + $found = true; // ... then use it + break; + } + } + if (!$found && $skippedphp) { + $found = null; + } + return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel); + } +} +?> \ No newline at end of file diff --git a/includes/pear/PEAR/Registry.php b/includes/pear/PEAR/Registry.php index 088207ff..556366d3 100644 --- a/includes/pear/PEAR/Registry.php +++ b/includes/pear/PEAR/Registry.php @@ -15,9 +15,9 @@ * @author Stig Bakken * @author Tomas V. V. Cox * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Registry.php,v 1.143 2005/10/31 05:06:43 cellog Exp $ + * @version CVS: $Id: Registry.php,v 1.171 2008/05/14 04:16:08 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ @@ -41,9 +41,9 @@ define('PEAR_REGISTRY_ERROR_CHANNEL_FILE', -6); * @author Stig Bakken * @author Tomas V. V. Cox * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -141,39 +141,51 @@ class PEAR_Registry extends PEAR $pecl_channel = false) { parent::PEAR(); + $this->setInstallDir($pear_install_dir); + $this->_pearChannel = $pear_channel; + $this->_peclChannel = $pecl_channel; + $this->_config = false; + } + + function setInstallDir($pear_install_dir = PEAR_INSTALL_DIR) + { $ds = DIRECTORY_SEPARATOR; $this->install_dir = $pear_install_dir; $this->channelsdir = $pear_install_dir.$ds.'.channels'; $this->statedir = $pear_install_dir.$ds.'.registry'; $this->filemap = $pear_install_dir.$ds.'.filemap'; $this->lockfile = $pear_install_dir.$ds.'.lock'; - $this->_pearChannel = $pear_channel; - $this->_peclChannel = $pecl_channel; - $this->_config = false; } function hasWriteAccess() { - if (!@file_exists($this->install_dir)) { + if (!file_exists($this->install_dir)) { $dir = $this->install_dir; while ($dir && $dir != '.') { + $olddir = $dir; $dir = dirname($dir); // cd .. - if ($dir != '.' && @file_exists($dir)) { - if (@is_writeable($dir)) { + if ($dir != '.' && file_exists($dir)) { + if (is_writeable($dir)) { return true; } else { return false; } } + if ($dir == $olddir) { // this can happen in safe mode + return @is_writable($dir); + } } return false; } - return @is_writeable($this->install_dir); + return is_writeable($this->install_dir); } - function setConfig(&$config) + function setConfig(&$config, $resetInstallDir = true) { $this->_config = &$config; + if ($resetInstallDir) { + $this->setInstallDir($config->get('php_dir')); + } } function _initializeChannelDirs() @@ -250,10 +262,11 @@ class PEAR_Registry extends PEAR $ds = DIRECTORY_SEPARATOR; // XXX Compatibility code should be removed in the future // rename all registry files if any to lowercase - if (!OS_WINDOWS && $handle = @opendir($this->statedir)) { + if (!OS_WINDOWS && file_exists($this->statedir) && is_dir($this->statedir) && + $handle = opendir($this->statedir)) { $dest = $this->statedir . $ds; while (false !== ($file = readdir($handle))) { - if (preg_match('/^.*[A-Z].*\.reg$/', $file)) { + if (preg_match('/^.*[A-Z].*\.reg\\z/', $file)) { rename($dest . $file, $dest . strtolower($file)); } } @@ -286,12 +299,16 @@ class PEAR_Registry extends PEAR $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config); if (PEAR::isError($this->_dependencyDB)) { // attempt to recover by removing the dep db - @unlink($this->_config->get('php_dir', null, 'pear.php.net') . - DIRECTORY_SEPARATOR . '.depdb'); + if (file_exists($this->_config->get('php_dir', null, 'pear.php.net') . + DIRECTORY_SEPARATOR . '.depdb')) { + @unlink($this->_config->get('php_dir', null, 'pear.php.net') . + DIRECTORY_SEPARATOR . '.depdb'); + } $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config); if (PEAR::isError($this->_dependencyDB)) { echo $this->_dependencyDB->getMessage(); - die('Unrecoverable error'); + echo 'Unrecoverable error'; + exit(1); } } $initializing = false; @@ -332,7 +349,7 @@ class PEAR_Registry extends PEAR return $this->_assertChannelStateDir($channel); } static $init = false; - if (!@is_dir($this->statedir)) { + if (!file_exists($this->statedir)) { if (!$this->hasWriteAccess()) { return false; } @@ -341,13 +358,20 @@ class PEAR_Registry extends PEAR return $this->raiseError("could not create directory '{$this->statedir}'"); } $init = true; + } elseif (!is_dir($this->statedir)) { + return $this->raiseError('Cannot create directory ' . $this->statedir . ', ' . + 'it already exists and is not a directory'); } $ds = DIRECTORY_SEPARATOR; - if (!@is_dir($this->channelsdir) || - !file_exists($this->channelsdir . $ds . 'pear.php.net.reg') || - !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') || - !file_exists($this->channelsdir . $ds . '__uri.reg')) { - $init = true; + if (!file_exists($this->channelsdir)) { + if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg') || + !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') || + !file_exists($this->channelsdir . $ds . '__uri.reg')) { + $init = true; + } + } elseif (!is_dir($this->channelsdir)) { + return $this->raiseError('Cannot create directory ' . $this->channelsdir . ', ' . + 'it already exists and is not a directory'); } if ($init) { static $running = false; @@ -389,7 +413,7 @@ class PEAR_Registry extends PEAR !file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) { $this->_initializeChannelDirs(); } - if (!@is_dir($channelDir)) { + if (!file_exists($channelDir)) { if (!$this->hasWriteAccess()) { return false; } @@ -398,6 +422,9 @@ class PEAR_Registry extends PEAR return $this->raiseError("could not create directory '" . $channelDir . "'"); } + } elseif (!is_dir($channelDir)) { + return $this->raiseError("could not create directory '" . $channelDir . + "', already exists and is not a directory"); } return true; } @@ -415,7 +442,7 @@ class PEAR_Registry extends PEAR */ function _assertChannelDir() { - if (!@is_dir($this->channelsdir)) { + if (!file_exists($this->channelsdir)) { if (!$this->hasWriteAccess()) { return false; } @@ -423,8 +450,12 @@ class PEAR_Registry extends PEAR if (!System::mkdir(array('-p', $this->channelsdir))) { return $this->raiseError("could not create directory '{$this->channelsdir}'"); } + } elseif (!is_dir($this->channelsdir)) { + return $this->raiseError("could not create directory '{$this->channelsdir}" . + "', it already exists and is not a directory"); + } - if (!@is_dir($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) { + if (!file_exists($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) { if (!$this->hasWriteAccess()) { return false; } @@ -432,6 +463,10 @@ class PEAR_Registry extends PEAR if (!System::mkdir(array('-p', $this->channelsdir . DIRECTORY_SEPARATOR . '.alias'))) { return $this->raiseError("could not create directory '{$this->channelsdir}/.alias'"); } + } elseif (!is_dir($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) { + return $this->raiseError("could not create directory '{$this->channelsdir}" . + "/.alias', it already exists and is not a directory"); + } return true; } @@ -469,7 +504,7 @@ class PEAR_Registry extends PEAR function _channelFileName($channel, $noaliases = false) { if (!$noaliases) { - if (@file_exists($this->_getChannelAliasFileName($channel))) { + if (file_exists($this->_getChannelAliasFileName($channel))) { $channel = implode('', file($this->_getChannelAliasFileName($channel))); } } @@ -536,6 +571,9 @@ class PEAR_Registry extends PEAR return false; } $channel = $this->_getChannel($channel); + if (PEAR::isError($channel)) { + return $channel; + } return $channel->getAlias(); } // }}} @@ -577,6 +615,9 @@ class PEAR_Registry extends PEAR return null; } $file = $this->_packageFileName($package, $channel); + if (!file_exists($file) && $mode == 'r' || $mode == 'rb') { + return null; + } $fp = @fopen($file, $mode); if (!$fp) { return null; @@ -593,7 +634,7 @@ class PEAR_Registry extends PEAR } // }}} - // {{{ _openPackageFile() + // {{{ _openChannelFile() function _openChannelFile($channel, $mode) { @@ -604,6 +645,9 @@ class PEAR_Registry extends PEAR return null; } $file = $this->_channelFileName($channel); + if (!file_exists($file) && $mode == 'r' || $mode == 'rb') { + return null; + } $fp = @fopen($file, $mode); if (!$fp) { return null; @@ -661,9 +705,15 @@ class PEAR_Registry extends PEAR } $file = preg_replace(',^/+,', '', $file); if ($channel != 'pear.php.net') { + if (!isset($files[$attrs['role']])) { + $files[$attrs['role']] = array(); + } $files[$attrs['role']][$file] = array(strtolower($channel), strtolower($package)); } else { + if (!isset($files[$attrs['role']])) { + $files[$attrs['role']] = array(); + } $files[$attrs['role']][$file] = strtolower($package); } } @@ -688,21 +738,19 @@ class PEAR_Registry extends PEAR function _readFileMap() { + if (!file_exists($this->filemap)) { + return array(); + } $fp = @fopen($this->filemap, 'r'); if (!$fp) { - return $this->raiseError('PEAR_Registry: could not open filemap', PEAR_REGISTRY_ERROR_FILE, null, null, $php_errormsg); + return $this->raiseError('PEAR_Registry: could not open filemap "' . $this->filemap . '"', PEAR_REGISTRY_ERROR_FILE, null, null, $php_errormsg); } clearstatcache(); $rt = get_magic_quotes_runtime(); set_magic_quotes_runtime(0); $fsize = filesize($this->filemap); - if (function_exists('file_get_contents')) { - fclose($fp); - $data = file_get_contents($this->filemap); - } else { - $data = fread($fp, $fsize); - fclose($fp); - } + fclose($fp); + $data = file_get_contents($this->filemap); set_magic_quotes_runtime($rt); $tmp = unserialize($data); if (!$tmp && $fsize > 7) { @@ -744,7 +792,7 @@ class PEAR_Registry extends PEAR $open_mode = 'w'; // XXX People reported problems with LOCK_SH and 'w' if ($mode === LOCK_SH || $mode === LOCK_UN) { - if (@!is_file($this->lockfile)) { + if (!file_exists($this->lockfile)) { touch($this->lockfile); } $open_mode = 'r'; @@ -755,6 +803,7 @@ class PEAR_Registry extends PEAR } if (!is_resource($this->lock_fp)) { + $this->lock_fp = null; return $this->raiseError("could not create lock file" . (isset($php_errormsg) ? ": " . $php_errormsg : "")); } @@ -765,6 +814,9 @@ class PEAR_Registry extends PEAR case LOCK_UN: $str = 'unlock'; break; default: $str = 'unknown'; break; } + //is resource at this point, close it on error. + fclose($this->lock_fp); + $this->lock_fp = null; return $this->raiseError("could not acquire $str lock ($this->lockfile)", PEAR_REGISTRY_ERROR_LOCK); } @@ -836,8 +888,13 @@ class PEAR_Registry extends PEAR return false; } $checker = $this->_getChannel($channel->getName()); + if (PEAR::isError($checker)) { + return $checker; + } if ($channel->getAlias() != $checker->getAlias()) { - @unlink($this->_getChannelAliasFileName($checker->getAlias())); + if (file_exists($this->_getChannelAliasFileName($checker->getAlias()))) { + @unlink($this->_getChannelAliasFileName($checker->getAlias())); + } } } else { if ($update && !in_array($channel->getName(), array('pear.php.net', 'pecl.php.net'))) { @@ -930,14 +987,17 @@ class PEAR_Registry extends PEAR return false; } $file = $this->_getChannelAliasFileName($this->_getAlias($channel)); - if (@file_exists($file)) { + if (file_exists($file)) { $test = @unlink($file); if (!$test) { return false; } } $file = $this->_channelFileName($channel); - $ret = @unlink($file); + $ret = true; + if (file_exists($file)) { + $ret = @unlink($file); + } return $ret; } @@ -995,13 +1055,8 @@ class PEAR_Registry extends PEAR $rt = get_magic_quotes_runtime(); set_magic_quotes_runtime(0); clearstatcache(); - if (function_exists('file_get_contents')) { - $this->_closePackageFile($fp); - $data = file_get_contents($this->_packageFileName($package, $channel)); - } else { - $data = fread($fp, filesize($this->_packageFileName($package, $channel))); - $this->_closePackageFile($fp); - } + $this->_closePackageFile($fp); + $data = file_get_contents($this->_packageFileName($package, $channel)); set_magic_quotes_runtime($rt); $data = unserialize($data); if ($key === null) { @@ -1037,13 +1092,8 @@ class PEAR_Registry extends PEAR $rt = get_magic_quotes_runtime(); set_magic_quotes_runtime(0); clearstatcache(); - if (function_exists('file_get_contents')) { - $this->_closeChannelFile($fp); - $data = file_get_contents($this->_channelFileName($channel)); - } else { - $data = fread($fp, filesize($this->_channelFileName($channel))); - $this->_closeChannelFile($fp); - } + $this->_closeChannelFile($fp); + $data = file_get_contents($this->_channelFileName($channel)); set_magic_quotes_runtime($rt); $data = unserialize($data); return $data; @@ -1055,15 +1105,19 @@ class PEAR_Registry extends PEAR function _listChannels() { $channellist = array(); - $dp = @opendir($this->channelsdir); - if (!$dp || !@is_dir($this->channelsdir)) { + if (!file_exists($this->channelsdir) || !is_dir($this->channelsdir)) { return array('pear.php.net', 'pecl.php.net', '__uri'); } + $dp = opendir($this->channelsdir); while ($ent = readdir($dp)) { if ($ent{0} == '.' || substr($ent, -4) != '.reg') { continue; } - $channellist[] = substr($ent, 0, -4); + if ($ent == '__uri.reg') { + $channellist[] = '__uri'; + continue; + } + $channellist[] = str_replace('_', '/', substr($ent, 0, -4)); } closedir($dp); if (!in_array('pear.php.net', $channellist)) { @@ -1074,7 +1128,9 @@ class PEAR_Registry extends PEAR } if (!in_array('__uri', $channellist)) { $channellist[] = '__uri'; - } + } + + natsort($channellist); return $channellist; } @@ -1086,8 +1142,11 @@ class PEAR_Registry extends PEAR if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') { return $this->_listChannelPackages($channel); } + if (!file_exists($this->statedir) || !is_dir($this->statedir)) { + return array(); + } $pkglist = array(); - $dp = @opendir($this->statedir); + $dp = opendir($this->statedir); if (!$dp) { return $pkglist; } @@ -1107,7 +1166,11 @@ class PEAR_Registry extends PEAR function _listChannelPackages($channel) { $pkglist = array(); - $dp = @opendir($this->_channelDirectoryName($channel)); + if (!file_exists($this->_channelDirectoryName($channel)) || + !is_dir($this->_channelDirectoryName($channel))) { + return array(); + } + $dp = opendir($this->_channelDirectoryName($channel)); if (!$dp) { return $pkglist; } @@ -1164,12 +1227,16 @@ class PEAR_Registry extends PEAR */ function _addPackage2($info) { + if (!is_a($info, 'PEAR_PackageFile_v1') && !is_a($info, 'PEAR_PackageFile_v2')) { + return false; + } + if (!$info->validate()) { if (class_exists('PEAR_Common')) { $ui = PEAR_Frontend::singleton(); if ($ui) { foreach ($info->getValidationWarnings() as $err) { - $ui->log(2, $err['message']); + $ui->log($err['message'], true); } } } @@ -1284,19 +1351,29 @@ class PEAR_Registry extends PEAR /** * @param string channel name * @param bool whether to strictly retrieve channel names - * @return PEAR_ChannelFile|false + * @return PEAR_ChannelFile|PEAR_Error * @access private */ function &_getChannel($channel, $noaliases = false) { $ch = false; if ($this->_channelExists($channel, $noaliases)) { - if (!class_exists('PEAR_ChannelFile')) { - require_once 'PEAR/ChannelFile.php'; + $chinfo = $this->_channelInfo($channel, $noaliases); + if ($chinfo) { + if (!class_exists('PEAR_ChannelFile')) { + require_once 'PEAR/ChannelFile.php'; + } + $ch = &PEAR_ChannelFile::fromArrayWithErrors($chinfo); } - $ch = &PEAR_ChannelFile::fromArray($this->_channelInfo($channel, $noaliases)); } if ($ch) { + if ($ch->validate()) { + return $ch; + } + foreach ($ch->getErrors(true) as $err) { + $message = $err['message'] . "\n"; + } + $ch = PEAR::raiseError($message); return $ch; } if ($this->_getChannelFromAlias($channel) == 'pear.php.net') { @@ -1628,7 +1705,11 @@ class PEAR_Registry extends PEAR return $e; } $file = $this->_packageFileName($package, $channel); - $ret = @unlink($file); + if (file_exists($file)) { + $ret = @unlink($file); + } else { + $ret = false; + } $this->_rebuildFileMap(); $this->_unlock(); $p = array('channel' => $channel, 'package' => $package); @@ -1650,6 +1731,9 @@ class PEAR_Registry extends PEAR $ret = $this->_updatePackage($package, $info, $merge); $this->_unlock(); if ($ret) { + if (!class_exists('PEAR_PackageFile_v1')) { + require_once 'PEAR/PackageFile/v1.php'; + } $pf = new PEAR_PackageFile_v1; $pf->setConfig($this->_config); $pf->fromArray($this->packageInfo($package)); @@ -1687,7 +1771,7 @@ class PEAR_Registry extends PEAR /** * @param string channel name * @param bool whether to strictly return raw channels (no aliases) - * @return PEAR_ChannelFile|false + * @return PEAR_ChannelFile|PEAR_Error */ function &getChannel($channel, $noaliases = false) { @@ -1696,6 +1780,9 @@ class PEAR_Registry extends PEAR } $ret = &$this->_getChannel($channel, $noaliases); $this->_unlock(); + if (!$ret) { + return PEAR::raiseError('Unknown channel: ' . $channel); + } return $ret; } @@ -1769,7 +1856,7 @@ class PEAR_Registry extends PEAR function &getChannelValidator($channel) { $chan = $this->getChannel($channel); - if (!$chan) { + if (PEAR::isError($chan)) { return $chan; } $val = $chan->getValidationObject(); @@ -1788,7 +1875,11 @@ class PEAR_Registry extends PEAR return $e; } foreach ($this->_listChannels() as $channel) { - $ret[] = &$this->_getChannel($channel); + $e = &$this->_getChannel($channel); + if (!$e || PEAR::isError($e)) { + continue; + } + $ret[] = $e; } $this->_unlock(); return $ret; @@ -1879,6 +1970,18 @@ class PEAR_Registry extends PEAR return false; } + // }}} + // {{{ flush() + /** + * Force a reload of the filemap + * @since 1.5.0RC3 + */ + function flushFileMap() + { + $this->filemap_cache = null; + clearstatcache(); // ensure that the next read gets the full, current filemap + } + // }}} // {{{ apiVersion() /** @@ -1926,7 +2029,7 @@ class PEAR_Registry extends PEAR $param['channel'] = '__uri'; } } else { - $components = @parse_url($param); + $components = @parse_url((string) $param); if (isset($components['scheme'])) { if ($components['scheme'] == 'http') { // uri package @@ -2109,7 +2212,9 @@ class PEAR_Registry extends PEAR } $ret = 'channel://' . $upass . $parsed['channel'] . '/' . $parsed['package']; if (isset($parsed['version']) || isset($parsed['state'])) { - $ret .= '-' . @$parsed['version'] . @$parsed['state']; + $ver = isset($parsed['version']) ? $parsed['version'] : ''; + $ver .= isset($parsed['state']) ? $parsed['state'] : ''; + $ret .= '-' . $ver; } if (isset($parsed['extension'])) { $ret .= '.' . $parsed['extension']; diff --git a/includes/pear/PEAR/Remote.php b/includes/pear/PEAR/Remote.php index e22d4a6e..09ddb997 100644 --- a/includes/pear/PEAR/Remote.php +++ b/includes/pear/PEAR/Remote.php @@ -14,9 +14,9 @@ * @package PEAR * @author Stig Bakken * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Remote.php,v 1.74 2005/09/11 18:00:20 cellog Exp $ + * @version CVS: $Id: Remote.php,v 1.80 2008/01/03 20:26:36 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ @@ -38,9 +38,9 @@ require_once 'PEAR/Config.php'; * @package PEAR * @author Stig Bakken * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ @@ -91,13 +91,8 @@ class PEAR_Remote extends PEAR if (!$fp) { return null; } - if (function_exists('file_get_contents')) { - fclose($fp); - $content = file_get_contents($filename); - } else { - $content = fread($fp, filesize($filename)); - fclose($fp); - } + fclose($fp); + $content = file_get_contents($filename); $result = array( 'age' => time() - filemtime($filename), 'lastChange' => filemtime($filename), @@ -151,7 +146,7 @@ class PEAR_Remote extends PEAR $server_channel = $this->config->get('default_channel'); $channel = $this->_registry->getChannel($server_channel); - if ($channel) { + if (!PEAR::isError($channel)) { $mirror = $this->config->get('preferred_mirror'); if ($channel->getMirror($mirror)) { if ($channel->supports('xmlrpc', $method, $mirror)) { @@ -182,15 +177,20 @@ class PEAR_Remote extends PEAR if ($this->cache !== null && $this->cache['age'] < $cachettl) { return $this->cache['content']; } + $fp = false; if (extension_loaded("xmlrpc")) { $result = call_user_func_array(array(&$this, 'call_epi'), $args); if (!PEAR::isError($result)) { $this->saveCache($_args, $result); } return $result; - } elseif (!@include_once 'XML/RPC.php') { + } elseif (!($fp = fopen('XML/RPC.php', 'r', true))) { return $this->raiseError("For this remote PEAR operation you need to load the xmlrpc extension or install XML_RPC"); } + include_once 'XML/RPC.php'; + if ($fp) { + fclose($fp); + } array_shift($args); $username = $this->config->get('username'); @@ -207,13 +207,13 @@ class PEAR_Remote extends PEAR } $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; if ($proxy = parse_url($this->config->get('http_proxy'))) { - $proxy_host = @$proxy['host']; + $proxy_host = isset($proxy['host']) ? $proxy['host'] : null; if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') { $proxy_host = 'https://' . $proxy_host; } - $proxy_port = @$proxy['port']; - $proxy_user = @urldecode(@$proxy['user']); - $proxy_pass = @urldecode(@$proxy['pass']); + $proxy_port = isset($proxy['port']) ? $proxy['port'] : 8080; + $proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null; + $proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null; } $shost = $server_host; if ($channel->getSSL()) { @@ -251,33 +251,12 @@ class PEAR_Remote extends PEAR function call_epi($method) { - do { - if (extension_loaded("xmlrpc")) { - break; - } - if (OS_WINDOWS) { - $ext = 'dll'; - } elseif (PHP_OS == 'HP-UX') { - $ext = 'sl'; - } elseif (PHP_OS == 'AIX') { - $ext = 'a'; - } else { - $ext = 'so'; - } - $ext = OS_WINDOWS ? 'dll' : 'so'; - @dl("xmlrpc-epi.$ext"); - if (extension_loaded("xmlrpc")) { - break; - } - @dl("xmlrpc.$ext"); - if (extension_loaded("xmlrpc")) { - break; - } - return $this->raiseError("unable to load xmlrpc extension"); - } while (false); + if (!extension_loaded("xmlrpc")) { + return $this->raiseError("xmlrpc extension is not loaded"); + } $server_channel = $this->config->get('default_channel'); $channel = $this->_registry->getChannel($server_channel); - if ($channel) { + if (!PEAR::isError($channel)) { $mirror = $this->config->get('preferred_mirror'); if ($channel->getMirror($mirror)) { if ($channel->supports('xmlrpc', $method, $mirror)) { @@ -307,13 +286,13 @@ class PEAR_Remote extends PEAR if ($http_proxy = $this->config->get('http_proxy')) { $proxy = parse_url($http_proxy); $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; - $proxy_host = @$proxy['host']; + $proxy_host = isset($proxy['host']) ? $proxy['host'] : null; if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') { - $proxy_host = 'ssl://' . $proxy_host; + $proxy_host = 'https://' . $proxy_host; } - $proxy_port = @$proxy['port']; - $proxy_user = @urldecode(@$proxy['user']); - $proxy_pass = @urldecode(@$proxy['pass']); + $proxy_port = isset($proxy['port']) ? $proxy['port'] : null; + $proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null; + $proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null; $fp = @fsockopen($proxy_host, $proxy_port); $use_proxy = true; if ($channel->getSSL()) { diff --git a/includes/pear/PEAR/RunTest.php b/includes/pear/PEAR/RunTest.php index 7c337c20..85f49d9b 100644 --- a/includes/pear/PEAR/RunTest.php +++ b/includes/pear/PEAR/RunTest.php @@ -14,9 +14,9 @@ * @package PEAR * @author Tomas V.V.Cox * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: RunTest.php,v 1.15 2005/09/13 15:20:42 cellog Exp $ + * @version CVS: $Id: RunTest.php,v 1.67 2008/05/14 02:30:16 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.3.3 */ @@ -42,16 +42,49 @@ putenv("PHP_PEAR_RUNTESTS=1"); * @package PEAR * @author Tomas V.V.Cox * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.3.3 */ class PEAR_RunTest { + var $_headers = array(); var $_logger; var $_options; + var $_php; + var $tests_count; + var $xdebug_loaded; + /** + * Saved value of php executable, used to reset $_php when we + * have a test that uses cgi + * + * @var unknown_type + */ + var $_savephp; + var $ini_overwrites = array( + 'output_handler=', + 'open_basedir=', + 'safe_mode=0', + 'disable_functions=', + 'output_buffering=Off', + 'display_errors=1', + 'log_errors=0', + 'html_errors=0', + 'track_errors=1', + 'report_memleaks=0', + 'report_zend_debug=0', + 'docref_root=', + 'docref_ext=.html', + 'error_prepend_string=', + 'error_append_string=', + 'auto_prepend_file=', + 'auto_append_file=', + 'magic_quotes_runtime=0', + 'xdebug.default_enable=0', + 'allow_url_fopen=1', + ); /** * An object that supports the PEAR_Common->log() signature, or null @@ -59,38 +92,706 @@ class PEAR_RunTest */ function PEAR_RunTest($logger = null, $options = array()) { + if (!defined('E_DEPRECATED')) { + define('E_DEPRECATED', 0); + } + if (!defined('E_STRICT')) { + define('E_STRICT', 0); + } + $this->ini_overwrites[] = 'error_reporting=' . (E_ALL & ~(E_DEPRECATED | E_STRICT)); if (is_null($logger)) { require_once 'PEAR/Common.php'; $logger = new PEAR_Common; } - $this->_logger = $logger; + $this->_logger = $logger; $this->_options = $options; + + $conf = &PEAR_Config::singleton(); + $this->_php = $conf->get('php_bin'); } - // - // Run an individual test case. - // - - function run($file, $ini_settings = '') + /** + * Taken from php-src/run-tests.php + * + * @param string $commandline command name + * @param array $env + * @param string $stdin standard input to pass to the command + * @return unknown + */ + function system_with_timeout($commandline, $env = null, $stdin = null) { - $cwd = getcwd(); - $conf = &PEAR_Config::singleton(); - $php = $conf->get('php_bin'); - //var_dump($php);exit; - global $log_format, $info_params, $ini_overwrites; + $data = ''; + if (version_compare(phpversion(), '5.0.0', '<')) { + $proc = proc_open($commandline, array( + 0 => array('pipe', 'r'), + 1 => array('pipe', 'w'), + 2 => array('pipe', 'w') + ), $pipes); + } else { + $proc = proc_open($commandline, array( + 0 => array('pipe', 'r'), + 1 => array('pipe', 'w'), + 2 => array('pipe', 'w') + ), $pipes, null, $env, array('suppress_errors' => true)); + } - $info_params = ''; - $log_format = 'LEOD'; + if (!$proc) { + return false; + } - // Load the sections of the test file. - $section_text = array( - 'TEST' => '(unnamed test)', - 'SKIPIF' => '', - 'GET' => '', - 'ARGS' => '', - ); + if (is_string($stdin)) { + fwrite($pipes[0], $stdin); + } + fclose($pipes[0]); + + while (true) { + /* hide errors from interrupted syscalls */ + $r = $pipes; + $e = $w = null; + $n = @stream_select($r, $w, $e, 60); + + if ($n === 0) { + /* timed out */ + $data .= "\n ** ERROR: process timed out **\n"; + proc_terminate($proc); + return array(1234567890, $data); + } else if ($n > 0) { + $line = fread($pipes[1], 8192); + if (strlen($line) == 0) { + /* EOF */ + break; + } + $data .= $line; + } + } + if (function_exists('proc_get_status')) { + $stat = proc_get_status($proc); + if ($stat['signaled']) { + $data .= "\nTermsig=".$stat['stopsig']; + } + } + $code = proc_close($proc); + if (function_exists('proc_get_status')) { + $code = $stat['exitcode']; + } + return array($code, $data); + } + + /** + * Turns a PHP INI string into an array + * + * Turns -d "include_path=/foo/bar" into this: + * array( + * 'include_path' => array( + * 'operator' => '-d', + * 'value' => '/foo/bar', + * ) + * ) + * Works both with quotes and without + * + * @param string an PHP INI string, -d "include_path=/foo/bar" + * @return array + */ + function iniString2array($ini_string) + { + if (!$ini_string) { + return array(); + } + $split = preg_split('/[\s]|=/', $ini_string, -1, PREG_SPLIT_NO_EMPTY); + $key = $split[1][0] == '"' ? substr($split[1], 1) : $split[1]; + $value = $split[2][strlen($split[2]) - 1] == '"' ? substr($split[2], 0, -1) : $split[2]; + // FIXME review if this is really the struct to go with + $array = array($key => array('operator' => $split[0], 'value' => $value)); + return $array; + } + + function settings2array($settings, $ini_settings) + { + foreach ($settings as $setting) { + if (strpos($setting, '=') !== false) { + $setting = explode('=', $setting, 2); + $name = trim(strtolower($setting[0])); + $value = trim($setting[1]); + $ini_settings[$name] = $value; + } + } + return $ini_settings; + } + + function settings2params($ini_settings) + { + $settings = ''; + foreach ($ini_settings as $name => $value) { + if (is_array($value)) { + $operator = $value['operator']; + $value = $value['value']; + } else { + $operator = '-d'; + } + $value = addslashes($value); + $settings .= " $operator \"$name=$value\""; + } + return $settings; + } + + function runPHPUnit($file, $ini_settings = '') + { + if (!file_exists($file) && file_exists(getcwd() . DIRECTORY_SEPARATOR . $file)) { + $file = realpath(getcwd() . DIRECTORY_SEPARATOR . $file); + break; + } elseif (file_exists($file)) { + $file = realpath($file); + } + $cmd = "$this->_php$ini_settings -f $file"; + if (isset($this->_logger)) { + $this->_logger->log(2, 'Running command "' . $cmd . '"'); + } + + $savedir = getcwd(); // in case the test moves us around + chdir(dirname($file)); + echo `$cmd`; + chdir($savedir); + return 'PASSED'; // we have no way of knowing this information so assume passing + } + + /** + * Runs an individual test case. + * + * @param string The filename of the test + * @param array|string INI settings to be applied to the test run + * @param integer Number what the current running test is of the + * whole test suite being runned. + * + * @return string|object Returns PASSED, WARNED, FAILED depending on how the + * test came out. + * PEAR Error when the tester it self fails + */ + function run($file, $ini_settings = array(), $test_number = 1) + { + if (isset($this->_savephp)) { + $this->_php = $this->_savephp; + unset($this->_savephp); + } + if (empty($this->_options['cgi'])) { + // try to see if php-cgi is in the path + $res = $this->system_with_timeout('php-cgi -v'); + if (false !== $res && !(is_array($res) && $res === array(127, ''))) { + $this->_options['cgi'] = 'php-cgi'; + } + } + if (1 < $len = strlen($this->tests_count)) { + $test_number = str_pad($test_number, $len, ' ', STR_PAD_LEFT); + $test_nr = "[$test_number/$this->tests_count] "; + } else { + $test_nr = ''; + } $file = realpath($file); + $section_text = $this->_readFile($file); + if (PEAR::isError($section_text)) { + return $section_text; + } + + if (isset($section_text['POST_RAW']) && isset($section_text['UPLOAD'])) { + return PEAR::raiseError("Cannot contain both POST_RAW and UPLOAD in test file: $file"); + } + + $cwd = getcwd(); + + $pass_options = ''; + if (!empty($this->_options['ini'])) { + $pass_options = $this->_options['ini']; + } + + if (is_string($ini_settings)) { + $ini_settings = $this->iniString2array($ini_settings); + } + + $ini_settings = $this->settings2array($this->ini_overwrites, $ini_settings); + if ($section_text['INI']) { + if (strpos($section_text['INI'], '{PWD}') !== false) { + $section_text['INI'] = str_replace('{PWD}', dirname($file), $section_text['INI']); + } + $ini = preg_split( "/[\n\r]+/", $section_text['INI']); + $ini_settings = $this->settings2array($ini, $ini_settings); + } + $ini_settings = $this->settings2params($ini_settings); + $shortname = str_replace($cwd . DIRECTORY_SEPARATOR, '', $file); + + $tested = trim($section_text['TEST']); + $tested.= !isset($this->_options['simple']) ? "[$shortname]" : ' '; + + if (!empty($section_text['POST']) || !empty($section_text['POST_RAW']) || + !empty($section_text['UPLOAD']) || !empty($section_text['GET']) || + !empty($section_text['COOKIE']) || !empty($section_text['EXPECTHEADERS'])) { + if (empty($this->_options['cgi'])) { + if (!isset($this->_options['quiet'])) { + $this->_logger->log(0, "SKIP $test_nr$tested (reason: --cgi option needed for this test, type 'pear help run-tests')"); + } + if (isset($this->_options['tapoutput'])) { + return array('ok', ' # skip --cgi option needed for this test, "pear help run-tests" for info'); + } + return 'SKIPPED'; + } + $this->_savephp = $this->_php; + $this->_php = $this->_options['cgi']; + } + + $temp_dir = realpath(dirname($file)); + $main_file_name = basename($file, 'phpt'); + $diff_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'diff'; + $log_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'log'; + $exp_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'exp'; + $output_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'out'; + $memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'mem'; + $temp_file = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'php'; + $temp_skipif = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'skip.php'; + $temp_clean = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'clean.php'; + $tmp_post = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.'); + + // unlink old test results + $this->_cleanupOldFiles($file); + + // Check if test should be skipped. + $res = $this->_runSkipIf($section_text, $temp_skipif, $tested, $ini_settings); + if (count($res) != 2) { + return $res; + } + $info = $res['info']; + $warn = $res['warn']; + + // We've satisfied the preconditions - run the test! + if (isset($this->_options['coverage']) && $this->xdebug_loaded) { + $len_f = 5; + if (substr($section_text['FILE'], 0, 5) != '')); + $xdebug_file = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'xdebug'; + $text .= "\n" . + "\n" . '$xdebug = var_export(xdebug_get_code_coverage(), true);'; + if (!function_exists('file_put_contents')) { + $text .= "\n" . '$fh = fopen(\'' . $xdebug_file . '\', "wb");' . + "\n" . 'if ($fh !== false) {' . + "\n" . ' fwrite($fh, $xdebug);' . + "\n" . ' fclose($fh);' . + "\n" . '}'; + } else { + $text .= "\n" . 'file_put_contents(\'' . $xdebug_file . '\', $xdebug);'; + } + $text .= "\n" . 'xdebug_stop_code_coverage();' . "\n" . '?>'; + + $this->save_text($temp_file, $text); + } else { + $this->save_text($temp_file, $section_text['FILE']); + } + + $args = $section_text['ARGS'] ? ' -- '.$section_text['ARGS'] : ''; + $cmd = "$this->_php$ini_settings -f \"$temp_file\" $args 2>&1"; + if (isset($this->_logger)) { + $this->_logger->log(2, 'Running command "' . $cmd . '"'); + } + + // Reset environment from any previous test. + $env = $this->_resetEnv($section_text, $temp_file); + + $section_text = $this->_processUpload($section_text, $file); + if (PEAR::isError($section_text)) { + return $section_text; + } + + if (array_key_exists('POST_RAW', $section_text) && !empty($section_text['POST_RAW'])) { + $post = trim($section_text['POST_RAW']); + $raw_lines = explode("\n", $post); + + $request = ''; + $started = false; + foreach ($raw_lines as $i => $line) { + if (empty($env['CONTENT_TYPE']) && + preg_match('/^Content-Type:(.*)/i', $line, $res)) { + $env['CONTENT_TYPE'] = trim(str_replace("\r", '', $res[1])); + continue; + } + if ($started) { + $request .= "\n"; + } + $started = true; + $request .= $line; + } + + $env['CONTENT_LENGTH'] = strlen($request); + $env['REQUEST_METHOD'] = 'POST'; + + $this->save_text($tmp_post, $request); + $cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post"; + } elseif (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) { + $post = trim($section_text['POST']); + $this->save_text($tmp_post, $post); + $content_length = strlen($post); + + $env['REQUEST_METHOD'] = 'POST'; + $env['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'; + $env['CONTENT_LENGTH'] = $content_length; + + $cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post"; + } else { + $env['REQUEST_METHOD'] = 'GET'; + $env['CONTENT_TYPE'] = ''; + $env['CONTENT_LENGTH'] = ''; + } + + if (OS_WINDOWS && isset($section_text['RETURNS'])) { + ob_start(); + system($cmd, $return_value); + $out = ob_get_contents(); + ob_end_clean(); + $section_text['RETURNS'] = (int) trim($section_text['RETURNS']); + $returnfail = ($return_value != $section_text['RETURNS']); + } else { + $returnfail = false; + $stdin = isset($section_text['STDIN']) ? $section_text['STDIN'] : null; + $out = $this->system_with_timeout($cmd, $env, $stdin); + $return_value = $out[0]; + $out = $out[1]; + } + + $output = preg_replace('/\r\n/', "\n", trim($out)); + + if (isset($tmp_post) && realpath($tmp_post) && file_exists($tmp_post)) { + @unlink(realpath($tmp_post)); + } + chdir($cwd); // in case the test moves us around + + $this->_testCleanup($section_text, $temp_clean); + + /* when using CGI, strip the headers from the output */ + $output = $this->_stripHeadersCGI($output); + + if (isset($section_text['EXPECTHEADERS'])) { + $testheaders = $this->_processHeaders($section_text['EXPECTHEADERS']); + $missing = array_diff_assoc($testheaders, $this->_headers); + $changed = ''; + foreach ($missing as $header => $value) { + if (isset($this->_headers[$header])) { + $changed .= "-$header: $value\n+$header: "; + $changed .= $this->_headers[$header]; + } else { + $changed .= "-$header: $value\n"; + } + } + if ($missing) { + // tack on failed headers to output: + $output .= "\n====EXPECTHEADERS FAILURE====:\n$changed"; + } + } + // Does the output match what is expected? + do { + if (isset($section_text['EXPECTF']) || isset($section_text['EXPECTREGEX'])) { + if (isset($section_text['EXPECTF'])) { + $wanted = trim($section_text['EXPECTF']); + } else { + $wanted = trim($section_text['EXPECTREGEX']); + } + $wanted_re = preg_replace('/\r\n/', "\n", $wanted); + if (isset($section_text['EXPECTF'])) { + $wanted_re = preg_quote($wanted_re, '/'); + // Stick to basics + $wanted_re = str_replace("%s", ".+?", $wanted_re); //not greedy + $wanted_re = str_replace("%i", "[+\-]?[0-9]+", $wanted_re); + $wanted_re = str_replace("%d", "[0-9]+", $wanted_re); + $wanted_re = str_replace("%x", "[0-9a-fA-F]+", $wanted_re); + $wanted_re = str_replace("%f", "[+\-]?\.?[0-9]+\.?[0-9]*(E-?[0-9]+)?", $wanted_re); + $wanted_re = str_replace("%c", ".", $wanted_re); + // %f allows two points "-.0.0" but that is the best *simple* expression + } + /* DEBUG YOUR REGEX HERE + var_dump($wanted_re); + print(str_repeat('=', 80) . "\n"); + var_dump($output); + */ + if (!$returnfail && preg_match("/^$wanted_re\$/s", $output)) { + if (file_exists($temp_file)) { + unlink($temp_file); + } + if (array_key_exists('FAIL', $section_text)) { + break; + } + if (!isset($this->_options['quiet'])) { + $this->_logger->log(0, "PASS $test_nr$tested$info"); + } + if (isset($this->_options['tapoutput'])) { + return array('ok', ' - ' . $tested); + } + return 'PASSED'; + } + } else { + if (isset($section_text['EXPECTFILE'])) { + $f = $temp_dir . '/' . trim($section_text['EXPECTFILE']); + if (!($fp = @fopen($f, 'rb'))) { + return PEAR::raiseError('--EXPECTFILE-- section file ' . + $f . ' not found'); + } + fclose($fp); + $section_text['EXPECT'] = file_get_contents($f); + } + $wanted = preg_replace('/\r\n/', "\n", trim($section_text['EXPECT'])); + // compare and leave on success + if (!$returnfail && 0 == strcmp($output, $wanted)) { + if (file_exists($temp_file)) { + unlink($temp_file); + } + if (array_key_exists('FAIL', $section_text)) { + break; + } + if (!isset($this->_options['quiet'])) { + $this->_logger->log(0, "PASS $test_nr$tested$info"); + } + if (isset($this->_options['tapoutput'])) { + return array('ok', ' - ' . $tested); + } + return 'PASSED'; + } + } + } while (false); + + if (array_key_exists('FAIL', $section_text)) { + // we expect a particular failure + // this is only used for testing PEAR_RunTest + $expectf = isset($section_text['EXPECTF']) ? $wanted_re : null; + $faildiff = $this->generate_diff($wanted, $output, null, $expectf); + $faildiff = preg_replace('/\r/', '', $faildiff); + $wanted = preg_replace('/\r/', '', trim($section_text['FAIL'])); + if ($faildiff == $wanted) { + if (!isset($this->_options['quiet'])) { + $this->_logger->log(0, "PASS $test_nr$tested$info"); + } + if (isset($this->_options['tapoutput'])) { + return array('ok', ' - ' . $tested); + } + return 'PASSED'; + } + unset($section_text['EXPECTF']); + $output = $faildiff; + if (isset($section_text['RETURNS'])) { + return PEAR::raiseError('Cannot have both RETURNS and FAIL in the same test: ' . + $file); + } + } + + // Test failed so we need to report details. + $txt = $warn ? 'WARN ' : 'FAIL '; + $this->_logger->log(0, $txt . $test_nr . $tested . $info); + + // write .exp + $res = $this->_writeLog($exp_filename, $wanted); + if (PEAR::isError($res)) { + return $res; + } + + // write .out + $res = $this->_writeLog($output_filename, $output); + if (PEAR::isError($res)) { + return $res; + } + + // write .diff + $returns = isset($section_text['RETURNS']) ? + array(trim($section_text['RETURNS']), $return_value) : null; + $expectf = isset($section_text['EXPECTF']) ? $wanted_re : null; + $data = $this->generate_diff($wanted, $output, $returns, $expectf); + $res = $this->_writeLog($diff_filename, $data); + if (PEAR::isError($res)) { + return $res; + } + + // write .log + $data = " +---- EXPECTED OUTPUT +$wanted +---- ACTUAL OUTPUT +$output +---- FAILED +"; + + if ($returnfail) { + $data .= " +---- EXPECTED RETURN +$section_text[RETURNS] +---- ACTUAL RETURN +$return_value +"; + } + + $res = $this->_writeLog($log_filename, $data); + if (PEAR::isError($res)) { + return $res; + } + + if (isset($this->_options['tapoutput'])) { + $wanted = explode("\n", $wanted); + $wanted = "# Expected output:\n#\n#" . implode("\n#", $wanted); + $output = explode("\n", $output); + $output = "#\n#\n# Actual output:\n#\n#" . implode("\n#", $output); + return array($wanted . $output . 'not ok', ' - ' . $tested); + } + return $warn ? 'WARNED' : 'FAILED'; + } + + function generate_diff($wanted, $output, $rvalue, $wanted_re) + { + $w = explode("\n", $wanted); + $o = explode("\n", $output); + $wr = explode("\n", $wanted_re); + $w1 = array_diff_assoc($w, $o); + $o1 = array_diff_assoc($o, $w); + $o2 = $w2 = array(); + foreach ($w1 as $idx => $val) { + if (!$wanted_re || !isset($wr[$idx]) || !isset($o1[$idx]) || + !preg_match('/^' . $wr[$idx] . '\\z/', $o1[$idx])) { + $w2[sprintf("%03d<", $idx)] = sprintf("%03d- ", $idx + 1) . $val; + } + } + foreach ($o1 as $idx => $val) { + if (!$wanted_re || !isset($wr[$idx]) || + !preg_match('/^' . $wr[$idx] . '\\z/', $val)) { + $o2[sprintf("%03d>", $idx)] = sprintf("%03d+ ", $idx + 1) . $val; + } + } + $diff = array_merge($w2, $o2); + ksort($diff); + $extra = $rvalue ? "##EXPECTED: $rvalue[0]\r\n##RETURNED: $rvalue[1]" : ''; + return implode("\r\n", $diff) . $extra; + } + + // Write the given text to a temporary file, and return the filename. + function save_text($filename, $text) + { + if (!$fp = fopen($filename, 'w')) { + return PEAR::raiseError("Cannot open file '" . $filename . "' (save_text)"); + } + fwrite($fp, $text); + fclose($fp); + if (1 < DETAILED) echo " +FILE $filename {{{ +$text +}}} +"; + } + + function _cleanupOldFiles($file) + { + $temp_dir = realpath(dirname($file)); + $mainFileName = basename($file, 'phpt'); + $diff_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'diff'; + $log_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'log'; + $exp_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'exp'; + $output_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'out'; + $memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'mem'; + $temp_file = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'php'; + $temp_skipif = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'skip.php'; + $temp_clean = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'clean.php'; + $tmp_post = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.'); + + // unlink old test results + @unlink($diff_filename); + @unlink($log_filename); + @unlink($exp_filename); + @unlink($output_filename); + @unlink($memcheck_filename); + @unlink($temp_file); + @unlink($temp_skipif); + @unlink($tmp_post); + @unlink($temp_clean); + } + + function _runSkipIf($section_text, $temp_skipif, $tested, $ini_settings) + { + $info = ''; + $warn = false; + if (array_key_exists('SKIPIF', $section_text) && trim($section_text['SKIPIF'])) { + $this->save_text($temp_skipif, $section_text['SKIPIF']); + $output = $this->system_with_timeout("$this->_php$ini_settings -f \"$temp_skipif\""); + $output = $output[1]; + $loutput = ltrim($output); + unlink($temp_skipif); + if (!strncasecmp('skip', $loutput, 4)) { + $skipreason = "SKIP $tested"; + if (preg_match('/^\s*skip\s*(.+)\s*/i', $output, $m)) { + $skipreason .= '(reason: ' . $m[1] . ')'; + } + if (!isset($this->_options['quiet'])) { + $this->_logger->log(0, $skipreason); + } + if (isset($this->_options['tapoutput'])) { + return array('ok', ' # skip ' . $reason); + } + return 'SKIPPED'; + } + + if (!strncasecmp('info', $loutput, 4) + && preg_match('/^\s*info\s*(.+)\s*/i', $output, $m)) { + $info = " (info: $m[1])"; + } + + if (!strncasecmp('warn', $loutput, 4) + && preg_match('/^\s*warn\s*(.+)\s*/i', $output, $m)) { + $warn = true; /* only if there is a reason */ + $info = " (warn: $m[1])"; + } + } + + return array('warn' => $warn, 'info' => $info); + } + + function _stripHeadersCGI($output) + { + $this->headers = array(); + if (!empty($this->_options['cgi']) && + $this->_php == $this->_options['cgi'] && + preg_match("/^(.*?)(?:\n\n(.*)|\\z)/s", $output, $match)) { + $output = isset($match[2]) ? trim($match[2]) : ''; + $this->_headers = $this->_processHeaders($match[1]); + } + + return $output; + } + + /** + * Return an array that can be used with array_diff() to compare headers + * + * @param string $text + */ + function _processHeaders($text) + { + $headers = array(); + $rh = preg_split("/[\n\r]+/", $text); + foreach ($rh as $line) { + if (strpos($line, ':')!== false) { + $line = explode(':', $line, 2); + $headers[trim($line[0])] = trim($line[1]); + } + } + return $headers; + } + + function _readFile($file) + { + // Load the sections of the test file. + $section_text = array( + 'TEST' => '(unnamed test)', + 'SKIPIF' => '', + 'GET' => '', + 'COOKIE' => '', + 'POST' => '', + 'ARGS' => '', + 'INI' => '', + 'CLEAN' => '', + ); + if (!is_file($file) || !$fp = fopen($file, "r")) { return PEAR::raiseError("Cannot open test file: $file"); } @@ -100,290 +801,127 @@ class PEAR_RunTest $line = fgets($fp); // Match the beginning of a section. - if (ereg('^--([A-Z]+)--',$line,$r)) { + if (preg_match('/^--([_A-Z]+)--/', $line, $r)) { $section = $r[1]; $section_text[$section] = ''; continue; } elseif (empty($section)) { fclose($fp); return PEAR::raiseError("Invalid sections formats in test file: $file"); - } + } // Add to the section text. $section_text[$section] .= $line; } fclose($fp); - $shortname = str_replace($cwd . DIRECTORY_SEPARATOR, '', $file); - if (!isset($this->_options['simple'])) { - $tested = trim($section_text['TEST']) . "[$shortname]"; - } else { - $tested = trim($section_text['TEST']) . ' '; - } - - $tmp = realpath(dirname($file)); - $tmp_skipif = $tmp . uniqid('/phpt.'); - $tmp_file = ereg_replace('\.phpt$','.php',$file); - $tmp_post = $tmp . uniqid('/phpt.'); - - @unlink($tmp_skipif); - @unlink($tmp_file); - @unlink($tmp_post); - - // unlink old test results - @unlink(ereg_replace('\.phpt$','.diff',$file)); - @unlink(ereg_replace('\.phpt$','.log',$file)); - @unlink(ereg_replace('\.phpt$','.exp',$file)); - @unlink(ereg_replace('\.phpt$','.out',$file)); - - // Check if test should be skipped. - $info = ''; - $warn = false; - if (array_key_exists('SKIPIF', $section_text)) { - if (trim($section_text['SKIPIF'])) { - $this->save_text($tmp_skipif, $section_text['SKIPIF']); - //$extra = substr(PHP_OS, 0, 3) !== "WIN" ? - // "unset REQUEST_METHOD;": ""; - - //$output = `$extra $php $info_params -f $tmp_skipif`; - $output = `$php $info_params -f $tmp_skipif`; - unlink($tmp_skipif); - if (eregi("^skip", trim($output))) { - $skipreason = "SKIP $tested"; - $reason = (eregi("^skip[[:space:]]*(.+)\$", trim($output))) ? eregi_replace("^skip[[:space:]]*(.+)\$", "\\1", trim($output)) : FALSE; - if ($reason) { - $skipreason .= " (reason: $reason)"; - } - if (!isset($this->_options['quiet'])) { - $this->_logger->log(0, $skipreason); - } - if (isset($old_php)) { - $php = $old_php; - } - return 'SKIPPED'; - } - if (eregi("^info", trim($output))) { - $reason = (ereg("^info[[:space:]]*(.+)\$", trim($output))) ? ereg_replace("^info[[:space:]]*(.+)\$", "\\1", trim($output)) : FALSE; - if ($reason) { - $info = " (info: $reason)"; - } - } - if (eregi("^warn", trim($output))) { - $reason = (ereg("^warn[[:space:]]*(.+)\$", trim($output))) ? ereg_replace("^warn[[:space:]]*(.+)\$", "\\1", trim($output)) : FALSE; - if ($reason) { - $warn = true; /* only if there is a reason */ - $info = " (warn: $reason)"; - } - } - } - } - - // We've satisfied the preconditions - run the test! - $this->save_text($tmp_file,$section_text['FILE']); - - $args = $section_text['ARGS'] ? ' -- '.$section_text['ARGS'] : ''; - - $cmd = "$php$ini_settings -f $tmp_file$args 2>&1"; - if (isset($this->_logger)) { - $this->_logger->log(2, 'Running command "' . $cmd . '"'); - } - - $savedir = getcwd(); // in case the test moves us around - if (isset($section_text['RETURNS'])) { - ob_start(); - system($cmd, $return_value); - $out = ob_get_contents(); - ob_end_clean(); - @unlink($tmp_post); - $section_text['RETURNS'] = (int) trim($section_text['RETURNS']); - $returnfail = ($return_value != $section_text['RETURNS']); - } else { - $out = `$cmd`; - $returnfail = false; - } - chdir($savedir); - // Does the output match what is expected? - $output = trim($out); - $output = preg_replace('/\r\n/', "\n", $output); - - if (isset($section_text['EXPECTF']) || isset($section_text['EXPECTREGEX'])) { - if (isset($section_text['EXPECTF'])) { - $wanted = trim($section_text['EXPECTF']); - } else { - $wanted = trim($section_text['EXPECTREGEX']); - } - $wanted_re = preg_replace('/\r\n/',"\n",$wanted); - if (isset($section_text['EXPECTF'])) { - $wanted_re = preg_quote($wanted_re, '/'); - // Stick to basics - $wanted_re = str_replace("%s", ".+?", $wanted_re); //not greedy - $wanted_re = str_replace("%i", "[+\-]?[0-9]+", $wanted_re); - $wanted_re = str_replace("%d", "[0-9]+", $wanted_re); - $wanted_re = str_replace("%x", "[0-9a-fA-F]+", $wanted_re); - $wanted_re = str_replace("%f", "[+\-]?\.?[0-9]+\.?[0-9]*(E-?[0-9]+)?", $wanted_re); - $wanted_re = str_replace("%c", ".", $wanted_re); - // %f allows two points "-.0.0" but that is the best *simple* expression - } - /* DEBUG YOUR REGEX HERE - var_dump($wanted_re); - print(str_repeat('=', 80) . "\n"); - var_dump($output); - */ - if (!$returnfail && preg_match("/^$wanted_re\$/s", $output)) { - @unlink($tmp_file); - if (!isset($this->_options['quiet'])) { - $this->_logger->log(0, "PASS $tested$info"); - } - if (isset($old_php)) { - $php = $old_php; - } - return 'PASSED'; - } - - } else { - $wanted = trim($section_text['EXPECT']); - $wanted = preg_replace('/\r\n/',"\n",$wanted); - // compare and leave on success - $ok = (0 == strcmp($output,$wanted)); - if (!$returnfail && $ok) { - @unlink($tmp_file); - if (!isset($this->_options['quiet'])) { - $this->_logger->log(0, "PASS $tested$info"); - } - if (isset($old_php)) { - $php = $old_php; - } - return 'PASSED'; - } - } - - // Test failed so we need to report details. - if ($warn) { - $this->_logger->log(0, "WARN $tested$info"); - } else { - $this->_logger->log(0, "FAIL $tested$info"); - } - - if (isset($section_text['RETURNS'])) { - $GLOBALS['__PHP_FAILED_TESTS__'][] = array( - 'name' => $file, - 'test_name' => $tested, - 'output' => ereg_replace('\.phpt$','.log', $file), - 'diff' => ereg_replace('\.phpt$','.diff', $file), - 'info' => $info, - 'return' => $return_value - ); - } else { - $GLOBALS['__PHP_FAILED_TESTS__'][] = array( - 'name' => $file, - 'test_name' => $tested, - 'output' => ereg_replace('\.phpt$','.log', $file), - 'diff' => ereg_replace('\.phpt$','.diff', $file), - 'info' => $info, - ); - } - - // write .exp - if (strpos($log_format,'E') !== FALSE) { - $logname = ereg_replace('\.phpt$','.exp',$file); - if (!$log = fopen($logname,'w')) { - return PEAR::raiseError("Cannot create test log - $logname"); - } - fwrite($log,$wanted); - fclose($log); - } - - // write .out - if (strpos($log_format,'O') !== FALSE) { - $logname = ereg_replace('\.phpt$','.out',$file); - if (!$log = fopen($logname,'w')) { - return PEAR::raiseError("Cannot create test log - $logname"); - } - fwrite($log,$output); - fclose($log); - } - - // write .diff - if (strpos($log_format,'D') !== FALSE) { - $logname = ereg_replace('\.phpt$','.diff',$file); - if (!$log = fopen($logname,'w')) { - return PEAR::raiseError("Cannot create test log - $logname"); - } - fwrite($log, $this->generate_diff($wanted, $output, - isset($section_text['RETURNS']) ? array(trim($section_text['RETURNS']), - $return_value) : null)); - fclose($log); - } - - // write .log - if (strpos($log_format,'L') !== FALSE) { - $logname = ereg_replace('\.phpt$','.log',$file); - if (!$log = fopen($logname,'w')) { - return PEAR::raiseError("Cannot create test log - $logname"); - } - fwrite($log," ----- EXPECTED OUTPUT -$wanted ----- ACTUAL OUTPUT -$output ----- FAILED -"); - if ($returnfail) { - fwrite($log," ----- EXPECTED RETURN -$section_text[RETURNS] ----- ACTUAL RETURN -$return_value -"); - } - fclose($log); - //error_report($file,$logname,$tested); - } - - if (isset($old_php)) { - $php = $old_php; - } - - return $warn ? 'WARNED' : 'FAILED'; + return $section_text; } - function generate_diff($wanted, $output, $return_value) + function _writeLog($logname, $data) { - $w = explode("\n", $wanted); - $o = explode("\n", $output); - $w1 = array_diff_assoc($w,$o); - $o1 = array_diff_assoc($o,$w); - $w2 = array(); - $o2 = array(); - foreach($w1 as $idx => $val) $w2[sprintf("%03d<",$idx)] = sprintf("%03d- ", $idx+1).$val; - foreach($o1 as $idx => $val) $o2[sprintf("%03d>",$idx)] = sprintf("%03d+ ", $idx+1).$val; - $diff = array_merge($w2, $o2); - ksort($diff); - if ($return_value) { - $extra = "##EXPECTED: $return_value[0]\r\n##RETURNED: $return_value[1]"; - } else { - $extra = ''; + if (!$log = fopen($logname, 'w')) { + return PEAR::raiseError("Cannot create test log - $logname"); } - return implode("\r\n", $diff) . $extra; + fwrite($log, $data); + fclose($log); } - // - // Write the given text to a temporary file, and return the filename. - // - - function save_text($filename, $text) + function _resetEnv($section_text, $temp_file) { - if (!$fp = fopen($filename, 'w')) { - return PEAR::raiseError("Cannot open file '" . $filename . "' (save_text)"); + $env = $_ENV; + $env['REDIRECT_STATUS'] = ''; + $env['QUERY_STRING'] = ''; + $env['PATH_TRANSLATED'] = ''; + $env['SCRIPT_FILENAME'] = ''; + $env['REQUEST_METHOD'] = ''; + $env['CONTENT_TYPE'] = ''; + $env['CONTENT_LENGTH'] = ''; + if (!empty($section_text['ENV'])) { + foreach (explode("\n", trim($section_text['ENV'])) as $e) { + $e = explode('=', trim($e), 2); + if (!empty($e[0]) && isset($e[1])) { + $env[$e[0]] = $e[1]; + } + } } - fwrite($fp,$text); - fclose($fp); - if (1 < DETAILED) echo " -FILE $filename {{{ -$text -}}} -"; + if (array_key_exists('GET', $section_text)) { + $env['QUERY_STRING'] = trim($section_text['GET']); + } else { + $env['QUERY_STRING'] = ''; + } + if (array_key_exists('COOKIE', $section_text)) { + $env['HTTP_COOKIE'] = trim($section_text['COOKIE']); + } else { + $env['HTTP_COOKIE'] = ''; + } + $env['REDIRECT_STATUS'] = '1'; + $env['PATH_TRANSLATED'] = $temp_file; + $env['SCRIPT_FILENAME'] = $temp_file; + + return $env; } -} -?> + function _processUpload($section_text, $file) + { + if (array_key_exists('UPLOAD', $section_text) && !empty($section_text['UPLOAD'])) { + $upload_files = trim($section_text['UPLOAD']); + $upload_files = explode("\n", $upload_files); + + $request = "Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737\n" . + "-----------------------------20896060251896012921717172737\n"; + foreach ($upload_files as $fileinfo) { + $fileinfo = explode('=', $fileinfo); + if (count($fileinfo) != 2) { + return PEAR::raiseError("Invalid UPLOAD section in test file: $file"); + } + if (!realpath(dirname($file) . '/' . $fileinfo[1])) { + return PEAR::raiseError("File for upload does not exist: $fileinfo[1] " . + "in test file: $file"); + } + $file_contents = file_get_contents(dirname($file) . '/' . $fileinfo[1]); + $fileinfo[1] = basename($fileinfo[1]); + $request .= "Content-Disposition: form-data; name=\"$fileinfo[0]\"; filename=\"$fileinfo[1]\"\n"; + $request .= "Content-Type: text/plain\n\n"; + $request .= $file_contents . "\n" . + "-----------------------------20896060251896012921717172737\n"; + } + + if (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) { + // encode POST raw + $post = trim($section_text['POST']); + $post = explode('&', $post); + foreach ($post as $i => $post_info) { + $post_info = explode('=', $post_info); + if (count($post_info) != 2) { + return PEAR::raiseError("Invalid POST data in test file: $file"); + } + $post_info[0] = rawurldecode($post_info[0]); + $post_info[1] = rawurldecode($post_info[1]); + $post[$i] = $post_info; + } + foreach ($post as $post_info) { + $request .= "Content-Disposition: form-data; name=\"$post_info[0]\"\n\n"; + $request .= $post_info[1] . "\n" . + "-----------------------------20896060251896012921717172737\n"; + } + unset($section_text['POST']); + } + $section_text['POST_RAW'] = $request; + } + + return $section_text; + } + + function _testCleanup($section_text, $temp_clean) + { + if ($section_text['CLEAN']) { + // perform test cleanup + $this->save_text($temp_clean, $section_text['CLEAN']); + $this->system_with_timeout("$this->_php $temp_clean"); + if (file_exists($temp_clean)) { + unlink($temp_clean); + } + } + } +} \ No newline at end of file diff --git a/includes/pear/PEAR/Task/Common.php b/includes/pear/PEAR/Task/Common.php index a5a31690..5841f286 100644 --- a/includes/pear/PEAR/Task/Common.php +++ b/includes/pear/PEAR/Task/Common.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Common.php,v 1.14 2005/09/18 06:32:00 cellog Exp $ + * @version CVS: $Id: Common.php,v 1.18 2008/05/13 21:28:20 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -51,9 +51,9 @@ define('PEAR_TASK_PACKAGEANDINSTALL', 3); * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 * @abstract @@ -121,7 +121,7 @@ class PEAR_Task_Common * @static * @abstract */ - function validXml($pkg, $xml, &$config, $fileXml) + function validateXml($pkg, $xml, $config, $fileXml) { } diff --git a/includes/pear/PEAR/Task/Postinstallscript.php b/includes/pear/PEAR/Task/Postinstallscript.php index 170a8591..024c0585 100644 --- a/includes/pear/PEAR/Task/Postinstallscript.php +++ b/includes/pear/PEAR/Task/Postinstallscript.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Postinstallscript.php,v 1.16 2005/10/19 04:52:54 cellog Exp $ + * @version CVS: $Id: Postinstallscript.php,v 1.20 2008/05/13 21:28:20 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -31,9 +31,9 @@ require_once 'PEAR/Task/Common.php'; * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -62,7 +62,7 @@ class PEAR_Task_Postinstallscript extends PEAR_Task_Common * @param array the entire parsed tag * @static */ - function validateXml($pkg, $xml, &$config, $fileXml) + function validateXml($pkg, $xml, $config, $fileXml) { if ($fileXml['role'] != 'php') { return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' . @@ -80,10 +80,14 @@ class PEAR_Task_Postinstallscript extends PEAR_Task_Common $fileXml['name'] . '" could not be retrieved for processing!'); } else { $analysis = $pkg->analyzeSourceCode($file, true); - if (PEAR::isError($analysis)) { + if (!$analysis) { PEAR::popErrorHandling(); + $warnings = ''; + foreach ($pkg->getValidationWarnings() as $warn) { + $warnings .= $warn['message'] . "\n"; + } return array(PEAR_TASK_ERROR_INVALID, 'Analysis of post-install script "' . - $fileXml['name'] . '" failed'); + $fileXml['name'] . '" failed: ' . $warnings); } if (count($analysis['declared_classes']) != 1) { PEAR::popErrorHandling(); diff --git a/includes/pear/PEAR/Task/Postinstallscript/rw.php b/includes/pear/PEAR/Task/Postinstallscript/rw.php index 0d4b3435..3f2a97cc 100644 --- a/includes/pear/PEAR/Task/Postinstallscript/rw.php +++ b/includes/pear/PEAR/Task/Postinstallscript/rw.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: rw.php,v 1.10 2005/10/19 04:47:34 cellog Exp $ + * @version CVS: $Id: rw.php,v 1.12 2008/01/03 20:26:37 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a10 */ @@ -28,9 +28,9 @@ require_once 'PEAR/Task/Postinstallscript.php'; * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a10 */ diff --git a/includes/pear/PEAR/Task/Replace.php b/includes/pear/PEAR/Task/Replace.php index 33830786..9a941819 100644 --- a/includes/pear/PEAR/Task/Replace.php +++ b/includes/pear/PEAR/Task/Replace.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Replace.php,v 1.12 2005/10/02 06:29:39 cellog Exp $ + * @version CVS: $Id: Replace.php,v 1.17 2008/05/13 21:28:20 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -28,9 +28,9 @@ require_once 'PEAR/Task/Common.php'; * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -47,7 +47,7 @@ class PEAR_Task_Replace extends PEAR_Task_Common * @param PEAR_Config * @static */ - function validateXml($pkg, $xml, &$config, $fileXml) + function validateXml($pkg, $xml, $config, $fileXml) { if (!isset($xml['attribs'])) { return array(PEAR_TASK_ERROR_NOATTRIBS); @@ -89,7 +89,7 @@ class PEAR_Task_Replace extends PEAR_Task_Common } } else { return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'type', $xml['attribs']['type'], - array('pear-config', 'package-info')); + array('pear-config', 'package-info', 'php-const')); } return true; } @@ -126,7 +126,7 @@ class PEAR_Task_Replace extends PEAR_Task_Common } if ($a['to'] == 'master_server') { $chan = $this->registry->getChannel($pkg->getChannel()); - if ($chan) { + if (!PEAR::isError($chan)) { $to = $chan->getServer(); } else { $this->logger->log(0, "$dest: invalid pear-config replacement: $a[to]"); diff --git a/includes/pear/PEAR/Task/Replace/rw.php b/includes/pear/PEAR/Task/Replace/rw.php index ab86dbe1..fe03d2e6 100644 --- a/includes/pear/PEAR/Task/Replace/rw.php +++ b/includes/pear/PEAR/Task/Replace/rw.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: rw.php,v 1.2 2005/05/20 22:57:42 cellog Exp $ + * @version CVS: $Id: rw.php,v 1.4 2008/01/03 20:26:37 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a10 */ @@ -28,9 +28,9 @@ require_once 'PEAR/Task/Replace.php'; * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a10 */ diff --git a/includes/pear/PEAR/Task/Unixeol.php b/includes/pear/PEAR/Task/Unixeol.php index fdccf8e2..bfd3f11c 100644 --- a/includes/pear/PEAR/Task/Unixeol.php +++ b/includes/pear/PEAR/Task/Unixeol.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Unixeol.php,v 1.7 2005/10/02 06:29:39 cellog Exp $ + * @version CVS: $Id: Unixeol.php,v 1.10 2008/05/13 21:28:20 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -28,9 +28,9 @@ require_once 'PEAR/Task/Common.php'; * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -47,7 +47,7 @@ class PEAR_Task_Unixeol extends PEAR_Task_Common * @param PEAR_Config * @static */ - function validateXml($pkg, $xml, &$config, $fileXml) + function validateXml($pkg, $xml, $config, $fileXml) { if ($xml != '') { return array(PEAR_TASK_ERROR_INVALID, 'no attributes allowed'); diff --git a/includes/pear/PEAR/Task/Unixeol/rw.php b/includes/pear/PEAR/Task/Unixeol/rw.php index 8be0325f..f04f0f00 100644 --- a/includes/pear/PEAR/Task/Unixeol/rw.php +++ b/includes/pear/PEAR/Task/Unixeol/rw.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: rw.php,v 1.3 2005/10/18 23:42:13 cellog Exp $ + * @version CVS: $Id: rw.php,v 1.5 2008/01/03 20:26:37 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a10 */ @@ -28,9 +28,9 @@ require_once 'PEAR/Task/Unixeol.php'; * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a10 */ diff --git a/includes/pear/PEAR/Task/Windowseol.php b/includes/pear/PEAR/Task/Windowseol.php index bf40e6c5..1a1be1e4 100644 --- a/includes/pear/PEAR/Task/Windowseol.php +++ b/includes/pear/PEAR/Task/Windowseol.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Windowseol.php,v 1.6 2005/10/02 06:29:39 cellog Exp $ + * @version CVS: $Id: Windowseol.php,v 1.9 2008/05/13 21:28:20 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -28,9 +28,9 @@ require_once 'PEAR/Task/Common.php'; * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -47,7 +47,7 @@ class PEAR_Task_Windowseol extends PEAR_Task_Common * @param PEAR_Config * @static */ - function validateXml($pkg, $xml, &$config, $fileXml) + function validateXml($pkg, $xml, $config, $fileXml) { if ($xml != '') { return array(PEAR_TASK_ERROR_INVALID, 'no attributes allowed'); diff --git a/includes/pear/PEAR/Task/Windowseol/rw.php b/includes/pear/PEAR/Task/Windowseol/rw.php index 31b8c496..c61a15d8 100644 --- a/includes/pear/PEAR/Task/Windowseol/rw.php +++ b/includes/pear/PEAR/Task/Windowseol/rw.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: rw.php,v 1.3 2005/10/18 23:42:00 cellog Exp $ + * @version CVS: $Id: rw.php,v 1.5 2008/01/03 20:26:37 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a10 */ @@ -28,9 +28,9 @@ require_once 'PEAR/Task/Windowseol.php'; * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a10 */ diff --git a/includes/pear/PEAR/Validate.php b/includes/pear/PEAR/Validate.php index 17f1b2db..34796b79 100644 --- a/includes/pear/PEAR/Validate.php +++ b/includes/pear/PEAR/Validate.php @@ -13,9 +13,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: Validate.php,v 1.44 2005/11/14 14:07:43 cellog Exp $ + * @version CVS: $Id: Validate.php,v 1.52 2008/01/03 20:26:36 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -36,9 +36,9 @@ require_once 'PEAR/Validator/PECL.php'; * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -68,7 +68,7 @@ class PEAR_Validate */ function _validPackageName($name) { - return (bool) preg_match('/^' . $this->packageregex . '$/', $name); + return (bool) preg_match('/^' . $this->packageregex . '\\z/', $name); } /** @@ -80,7 +80,7 @@ class PEAR_Validate { if ($validatepackagename) { if (strtolower($name) == strtolower($validatepackagename)) { - return (bool) preg_match('/^[a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)*$/', $name); + return (bool) preg_match('/^[a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)*\\z/', $name); } } return $this->_validPackageName($name); @@ -95,7 +95,7 @@ class PEAR_Validate */ function validGroupName($name) { - return (bool) preg_match('/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '$/', $name); + return (bool) preg_match('/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/', $name); } /** @@ -188,7 +188,8 @@ class PEAR_Validate if ($this->_packagexml->getPackagexmlVersion() == '1.0') { $this->validateState(); $this->validateFilelist(); - } elseif ($this->_packagexml->getPackagexmlVersion() == '2.0') { + } elseif ($this->_packagexml->getPackagexmlVersion() == '2.0' || + $this->_packagexml->getPackagexmlVersion() == '2.1') { $this->validateTime(); $this->validateStability(); $this->validateDeps(); @@ -207,7 +208,8 @@ class PEAR_Validate { if ($this->_state == PEAR_VALIDATE_PACKAGING || $this->_state == PEAR_VALIDATE_NORMAL) { - if ($this->_packagexml->getPackagexmlVersion() == '2.0' && + if (($this->_packagexml->getPackagexmlVersion() == '2.0' || + $this->_packagexml->getPackagexmlVersion() == '2.1') && $this->_packagexml->getExtends()) { $version = $this->_packagexml->getVersion() . ''; $name = $this->_packagexml->getPackage(); @@ -286,6 +288,13 @@ class PEAR_Validate case 'beta' : // check for a package that extends a package, // like Foo and Foo2 + if ($this->_state == PEAR_VALIDATE_PACKAGING) { + if (substr($versioncomponents[2], 1, 2) == 'rc') { + $this->_addFailure('version', 'Release Candidate versions ' . + 'must have capital RC, not lower-case rc'); + return false; + } + } if (!$this->_packagexml->getExtends()) { if ($versioncomponents[0] == '1') { if ($versioncomponents[2]{0} == '0') { @@ -438,17 +447,18 @@ class PEAR_Validate { if ($this->_state == PEAR_VALIDATE_NORMAL || $this->_state == PEAR_VALIDATE_PACKAGING) { - if (!preg_match('/\d\d\d\d\-\d\d\-\d\d/', - $this->_packagexml->getDate())) { - $this->_addFailure('date', 'invalid release date "' . - $this->_packagexml->getDate() . '"'); - return false; - } - if (strtotime($this->_packagexml->getDate()) == -1) { + + if (!preg_match('/(\d\d\d\d)\-(\d\d)\-(\d\d)/', + $this->_packagexml->getDate(), $res) || + count($res) < 4 + || !checkdate($res[2], $res[3], $res[1]) + ) { $this->_addFailure('date', 'invalid release date "' . $this->_packagexml->getDate() . '"'); return false; } + + if ($this->_state == PEAR_VALIDATE_PACKAGING && $this->_packagexml->getDate() != date('Y-m-d')) { $this->_addWarning('date', 'Release Date "' . @@ -621,4 +631,4 @@ class PEAR_Validate return true; } } -?> \ No newline at end of file +?> diff --git a/includes/pear/PEAR/Validator/PECL.php b/includes/pear/PEAR/Validator/PECL.php index f5e107a4..354a5bed 100644 --- a/includes/pear/PEAR/Validator/PECL.php +++ b/includes/pear/PEAR/Validator/PECL.php @@ -7,9 +7,9 @@ * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2006 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: PECL.php,v 1.4 2005/09/23 04:53:01 cellog Exp $ + * @version CVS: $Id: PECL.php,v 1.9 2008/01/03 20:26:37 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a5 */ @@ -22,9 +22,9 @@ require_once 'PEAR/Validate.php'; * @category pear * @package PEAR * @author Greg Beaver - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a5 */ @@ -32,13 +32,24 @@ class PEAR_Validator_PECL extends PEAR_Validate { function validateVersion() { + if ($this->_state == PEAR_VALIDATE_PACKAGING) { + $version = $this->_packagexml->getVersion(); + $versioncomponents = explode('.', $version); + $last = array_pop($versioncomponents); + if (substr($last, 1, 2) == 'rc') { + $this->_addFailure('version', 'Release Candidate versions must have ' . + 'upper-case RC, not lower-case rc'); + return false; + } + } return true; } function validatePackageName() { $ret = parent::validatePackageName(); - if ($this->_packagexml->getPackageType() == 'extsrc') { + if ($this->_packagexml->getPackageType() == 'extsrc' || + $this->_packagexml->getPackageType() == 'zendextsrc') { if (strtolower($this->_packagexml->getPackage()) != strtolower($this->_packagexml->getProvidesExtension())) { $this->_addWarning('providesextension', 'package name "' . diff --git a/includes/pear/PEAR/XMLParser.php b/includes/pear/PEAR/XMLParser.php index f703d74a..faabc073 100644 --- a/includes/pear/PEAR/XMLParser.php +++ b/includes/pear/PEAR/XMLParser.php @@ -1,6 +1,6 @@ * @author Stephan Schmidt (original XML_Unserializer code) - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: XMLParser.php,v 1.10 2005/09/25 03:49:02 cellog Exp $ + * @version CVS: $Id: XMLParser.php,v 1.13 2008/01/03 20:26:36 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 1.4.0a1 */ @@ -27,9 +27,9 @@ * @package PEAR * @author Greg Beaver * @author Stephan Schmidt (original XML_Unserializer code) - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version Release: 1.4.5 + * @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -91,12 +91,12 @@ class PEAR_XMLParser if (strpos($data, 'encoding="UTF-8"')) { $data = utf8_decode($data); } - $xp = @xml_parser_create('ISO-8859-1'); + $xp = xml_parser_create('ISO-8859-1'); } else { if (strpos($data, 'encoding="UTF-8"')) { - $xp = @xml_parser_create('UTF-8'); + $xp = xml_parser_create('UTF-8'); } else { - $xp = @xml_parser_create('ISO-8859-1'); + $xp = xml_parser_create('ISO-8859-1'); } } xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, 0); diff --git a/includes/pear/System.php b/includes/pear/System.php index e9cabdd6..534f0a97 100644 --- a/includes/pear/System.php +++ b/includes/pear/System.php @@ -13,9 +13,9 @@ * @category pear * @package System * @author Tomas V.V.Cox - * @copyright 1997-2005 The PHP Group + * @copyright 1997-2008 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 - * @version CVS: $Id: System.php,v 1.51 2005/11/16 03:28:56 cellog Exp $ + * @version CVS: $Id: System.php,v 1.62 2008/01/03 20:26:34 cellog Exp $ * @link http://pear.php.net/package/PEAR * @since File available since Release 0.1 */ @@ -35,7 +35,9 @@ $GLOBALS['_System_temp_files'] = array(); * Unix and Windows. The names and usage has been taken from its respectively * GNU commands. The functions will return (bool) false on error and will * trigger the error with the PHP trigger_error() function (you can silence -* the error by prefixing a '@' sign after the function call). +* the error by prefixing a '@' sign after the function call, but this +* is not recommended practice. Instead use an error handler with +* {@link set_error_handler()}). * * Documentation on this class you can find in: * http://pear.php.net/manual/ @@ -53,11 +55,12 @@ $GLOBALS['_System_temp_files'] = array(); * @category pear * @package System * @author Tomas V.V. Cox -* @copyright 1997-2005 The PHP Group +* @copyright 1997-2006 The PHP Group * @license http://www.php.net/license/3_0.txt PHP License 3.0 -* @version Release: 1.4.5 +* @version Release: 1.7.2 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 +* @static */ class System { @@ -68,6 +71,7 @@ class System * @param string $short_options the allowed option short-tags * @param string $long_options the allowed option long-tags * @return array the given options and there values + * @static * @access private */ function _parseArgs($argv, $short_options, $long_options = null) @@ -84,6 +88,7 @@ class System * * @param mixed $error a PEAR error or a string with the error message * @return bool false + * @static * @access private */ function raiseError($error) @@ -115,15 +120,19 @@ class System * @param string $sPath Name of the directory * @param integer $maxinst max. deep of the lookup * @param integer $aktinst starting deep of the lookup + * @param bool $silent if true, do not emit errors. * @return array the structure of the dir + * @static * @access private */ - function _dirToStruct($sPath, $maxinst, $aktinst = 0) + function _dirToStruct($sPath, $maxinst, $aktinst = 0, $silent = false) { $struct = array('dirs' => array(), 'files' => array()); if (($dir = @opendir($sPath)) === false) { - System::raiseError("Could not open dir $sPath"); + if (!$silent) { + System::raiseError("Could not open dir $sPath"); + } return $struct; // XXX could not open error } $struct['dirs'][] = $sPath = realpath($sPath); // XXX don't add if '.' or '..' ? @@ -136,10 +145,10 @@ class System closedir($dir); sort($list); if ($aktinst < $maxinst || $maxinst == 0) { - foreach($list as $val) { + foreach ($list as $val) { $path = $sPath . DIRECTORY_SEPARATOR . $val; if (is_dir($path) && !is_link($path)) { - $tmp = System::_dirToStruct($path, $maxinst, $aktinst+1); + $tmp = System::_dirToStruct($path, $maxinst, $aktinst+1, $silent); $struct = array_merge_recursive($tmp, $struct); } else { $struct['files'][] = $path; @@ -154,6 +163,7 @@ class System * * @param array $files Array listing files and dirs * @return array + * @static * @see System::_dirToStruct() */ function _multipleToStruct($files) @@ -177,15 +187,16 @@ class System * * @param string $args the arguments for rm * @return mixed PEAR_Error or true for success + * @static * @access public */ function rm($args) { - $opts = System::_parseArgs($args, 'rf'); // "f" do nothing but like it :-) + $opts = System::_parseArgs($args, 'rf'); // "f" does nothing but I like it :-) if (PEAR::isError($opts)) { return System::raiseError($opts); } - foreach($opts[0] as $opt) { + foreach ($opts[0] as $opt) { if ($opt[0] == 'r') { $do_recursive = true; } @@ -193,12 +204,12 @@ class System $ret = true; if (isset($do_recursive)) { $struct = System::_multipleToStruct($opts[1]); - foreach($struct['files'] as $file) { + foreach ($struct['files'] as $file) { if (!@unlink($file)) { $ret = false; } } - foreach($struct['dirs'] as $dir) { + foreach ($struct['dirs'] as $dir) { if (!@rmdir($dir)) { $ret = false; } @@ -220,6 +231,7 @@ class System * The -p option will create parent directories * @param string $args the name of the director(y|ies) to create * @return bool True for success + * @static * @access public */ function mkDir($args) @@ -229,10 +241,10 @@ class System return System::raiseError($opts); } $mode = 0777; // default mode - foreach($opts[0] as $opt) { + foreach ($opts[0] as $opt) { if ($opt[0] == 'p') { $create_parents = true; - } elseif($opt[0] == 'm') { + } elseif ($opt[0] == 'm') { // if the mode is clearly an octal number (starts with 0) // convert it to decimal if (strlen($opt[1]) && $opt[1]{0} == '0') { @@ -246,9 +258,10 @@ class System } $ret = true; if (isset($create_parents)) { - foreach($opts[1] as $dir) { + foreach ($opts[1] as $dir) { $dirstack = array(); - while (!@is_dir($dir) && $dir != DIRECTORY_SEPARATOR) { + while ((!file_exists($dir) || !is_dir($dir)) && + $dir != DIRECTORY_SEPARATOR) { array_unshift($dirstack, $dir); $dir = dirname($dir); } @@ -264,7 +277,7 @@ class System } } else { foreach($opts[1] as $dir) { - if (!@is_dir($dir) && !mkdir($dir, $mode)) { + if ((@file_exists($dir) || !is_dir($dir)) && !mkdir($dir, $mode)) { $ret = false; } } @@ -284,6 +297,7 @@ class System * * @param string $args the arguments * @return boolean true on success + * @static * @access public */ function &cat($args) @@ -293,7 +307,9 @@ class System if (!is_array($args)) { $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY); } - for($i=0; $i < count($args); $i++) { + + $count_args = count($args); + for ($i = 0; $i < $count_args; $i++) { if ($args[$i] == '>') { $mode = 'wb'; $outputfile = $args[$i+1]; @@ -306,6 +322,7 @@ class System $files[] = $args[$i]; } } + $outputfd = false; if (isset($mode)) { if (!$outputfd = fopen($outputfile, $mode)) { $err = System::raiseError("Could not open $outputfile"); @@ -319,7 +336,7 @@ class System continue; } while ($cont = fread($fd, 2048)) { - if (isset($outputfd)) { + if (is_resource($outputfd)) { fwrite($outputfd, $cont); } else { $ret .= $cont; @@ -327,7 +344,7 @@ class System } fclose($fd); } - if (@is_resource($outputfd)) { + if (is_resource($outputfd)) { fclose($outputfd); } return $ret; @@ -354,6 +371,7 @@ class System * @param string $args The arguments * @return mixed the full path of the created (file|dir) or false * @see System::tmpdir() + * @static * @access public */ function mktemp($args = null) @@ -363,10 +381,10 @@ class System if (PEAR::isError($opts)) { return System::raiseError($opts); } - foreach($opts[0] as $opt) { - if($opt[0] == 'd') { + foreach ($opts[0] as $opt) { + if ($opt[0] == 'd') { $tmp_is_dir = true; - } elseif($opt[0] == 't') { + } elseif ($opt[0] == 't') { $tmpdir = $opt[1]; } } @@ -396,6 +414,7 @@ class System * Remove temporary files created my mkTemp. This function is executed * at script shutdown time * + * @static * @access private */ function _removeTmpFiles() @@ -414,15 +433,19 @@ class System * Note: php.ini-recommended removes the "E" from the variables_order setting, * making unavaible the $_ENV array, that s why we do tests with _ENV * - * @return string The temporal directory on the system + * @static + * @return string The temporary directory on the system */ function tmpdir() { if (OS_WINDOWS) { + if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) { + return $var; + } if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) { return $var; } - if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) { + if ($var = isset($_ENV['USERPROFILE']) ? $_ENV['USERPROFILE'] : getenv('USERPROFILE')) { return $var; } if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) { @@ -433,7 +456,7 @@ class System if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) { return $var; } - return '/tmp'; + return realpath('/tmp'); } /** @@ -443,16 +466,16 @@ class System * @param mixed $fallback Value to return if $program is not found * * @return mixed A string with the full path or false if not found + * @static * @author Stig Bakken */ function which($program, $fallback = false) { - // avaible since 4.3.0RC2 - if (defined('PATH_SEPARATOR')) { - $path_delim = PATH_SEPARATOR; - } else { - $path_delim = OS_WINDOWS ? ';' : ':'; + // enforce API + if (!is_string($program) || '' == $program) { + return $fallback; } + // full path given if (basename($program) != $program) { $path_elements[] = dirname($program); @@ -465,12 +488,12 @@ class System $path = getenv('Path'); // some OSes are just stupid enough to do this } } - $path_elements = explode($path_delim, $path); + $path_elements = explode(PATH_SEPARATOR, $path); } if (OS_WINDOWS) { $exe_suffixes = getenv('PATHEXT') - ? explode($path_delim, getenv('PATHEXT')) + ? explode(PATH_SEPARATOR, getenv('PATHEXT')) : array('.exe','.bat','.cmd','.com'); // allow passing a command.exe param if (strpos($program, '.') !== false) { @@ -486,7 +509,7 @@ class System foreach ($exe_suffixes as $suff) { foreach ($path_elements as $dir) { $file = $dir . DIRECTORY_SEPARATOR . $program . $suff; - if ($pear_is_executable($file)) { + if (@$pear_is_executable($file)) { return $file; } } @@ -515,6 +538,7 @@ class System * * @param mixed Either array or string with the command line * @return array Array of found files + * @static * */ function find($args) @@ -522,11 +546,15 @@ class System if (!is_array($args)) { $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY); } - $dir = array_shift($args); + $dir = realpath(array_shift($args)); + if (!$dir) { + return array(); + } $patterns = array(); $depth = 0; $do_files = $do_dirs = true; - for ($i = 0; $i < count($args); $i++) { + $args_count = count($args); + for ($i = 0; $i < $args_count; $i++) { switch ($args[$i]) { case '-type': if (in_array($args[$i+1], array('d', 'f'))) { @@ -539,18 +567,11 @@ class System $i++; break; case '-name': - if (OS_WINDOWS) { - if ($args[$i+1]{0} == '\\') { - // prepend drive - $args[$i+1] = addslashes(substr(getcwd(), 0, 2) . $args[$i + 1]); - } - // escape path separators to avoid PCRE problems - $args[$i+1] = str_replace('\\', '\\\\', $args[$i+1]); - } - $patterns[] = "(" . preg_replace(array('/\./', '/\*/'), - array('\.', '.*', ), - $args[$i+1]) - . ")"; + $name = preg_quote($args[$i+1], '#'); + // our magic characters ? and * have just been escaped, + // so now we change the escaped versions to PCRE operators + $name = strtr($name, array('\?' => '.', '\*' => '.*')); + $patterns[] = '('.$name.')'; $i++; break; case '-maxdepth': @@ -558,7 +579,7 @@ class System break; } } - $path = System::_dirToStruct($dir, $depth); + $path = System::_dirToStruct($dir, $depth, 0, true); if ($do_files && $do_dirs) { $files = array_merge($path['files'], $path['dirs']); } elseif ($do_dirs) { @@ -567,10 +588,14 @@ class System $files = $path['files']; } if (count($patterns)) { - $patterns = implode('|', $patterns); + $dsq = preg_quote(DIRECTORY_SEPARATOR, '#'); + $pattern = '#(^|'.$dsq.')'.implode('|', $patterns).'($|'.$dsq.')#'; $ret = array(); - for ($i = 0; $i < count($files); $i++) { - if (preg_match("#^$patterns\$#", $files[$i])) { + $files_count = count($files); + for ($i = 0; $i < $files_count; $i++) { + // only search in the part of the file below the current directory + $filepart = basename($files[$i]); + if (preg_match($pattern, $filepart)) { $ret[] = $files[$i]; } } @@ -578,5 +603,4 @@ class System } return $files; } -} -?> +} \ No newline at end of file diff --git a/includes/pear/XML/Parser.php b/includes/pear/XML/Parser.php index 858fcbce..5706acc5 100644 --- a/includes/pear/XML/Parser.php +++ b/includes/pear/XML/Parser.php @@ -1,36 +1,52 @@ | -// | Tomas V.V.Cox | -// | Stephan Schmidt | -// +----------------------------------------------------------------------+ -// -// $Id: Parser.php,v 1.26 2005/09/23 11:51:10 schst Exp $ + +/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ /** - * XML Parser class. + * XML_Parser * - * This is an XML parser based on PHP's "xml" extension, - * based on the bundled expat library. + * XML Parser package * - * @category XML - * @package XML_Parser - * @author Stig Bakken - * @author Tomas V.V.Cox - * @author Stephan Schmidt + * PHP versions 4 and 5 + * + * LICENSE: + * + * Copyright (c) 2002-2008 The PHP Group + * 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. + * * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF 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. + * + * @category XML + * @package XML_Parser + * @author Stig Bakken + * @author Tomas V.V.Cox + * @author Stephan Schmidt + * @copyright 2002-2008 The PHP Group + * @license http://opensource.org/licenses/bsd-license New BSD License + * @version CVS: $Id: Parser.php,v 1.29 2008/08/24 21:48:21 ashnazg Exp $ + * @link http://pear.php.net/package/XML_Parser */ /** @@ -79,25 +95,29 @@ define('XML_PARSER_ERROR_REMOTE', 205); * - From revision 1.17, the function names used by the 'func' mode * are in the format "xmltag_$elem", for example: use "xmltag_name" * to handle the tags of your xml file. - * - * @category XML - * @package XML_Parser - * @author Stig Bakken - * @author Tomas V.V.Cox - * @author Stephan Schmidt - * @todo create XML_Parser_Namespace to parse documents with namespaces - * @todo create XML_Parser_Pull - * @todo Tests that need to be made: - * - mixing character encodings - * - a test using all expat handlers - * - options (folding, output charset) * - different parsing modes + * + * @category XML + * @package XML_Parser + * @author Stig Bakken + * @author Tomas V.V.Cox + * @author Stephan Schmidt + * @copyright 2002-2008 The PHP Group + * @license http://opensource.org/licenses/bsd-license New BSD License + * @version Release: @package_version@ + * @link http://pear.php.net/package/XML_Parser + * @todo create XML_Parser_Namespace to parse documents with namespaces + * @todo create XML_Parser_Pull + * @todo Tests that need to be made: + * - mixing character encodings + * - a test using all expat handlers + * - options (folding, output charset) */ class XML_Parser extends PEAR { // {{{ properties - /** + /** * XML parser handle * * @var resource @@ -164,8 +184,15 @@ class XML_Parser extends PEAR */ var $_handlerObj; + /** + * valid encodings + * + * @var array + */ + var $_validEncodings = array('ISO-8859-1', 'UTF-8', 'US-ASCII'); + // }}} - // {{{ constructor + // {{{ php4 constructor /** * Creates an XML parser. @@ -178,13 +205,14 @@ class XML_Parser extends PEAR * @param string $mode how this parser object should work, "event" for * startelement/endelement-type events, "func" * to have it call functions named after elements - * @param string $tgenc a valid target encoding + * @param string $tgtenc a valid target encoding */ function XML_Parser($srcenc = null, $mode = 'event', $tgtenc = null) { XML_Parser::__construct($srcenc, $mode, $tgtenc); } // }}} + // {{{ php5 constructor /** * PHP5 constructor @@ -194,7 +222,7 @@ class XML_Parser extends PEAR * @param string $mode how this parser object should work, "event" for * startelement/endelement-type events, "func" * to have it call functions named after elements - * @param string $tgenc a valid target encoding + * @param string $tgtenc a valid target encoding */ function __construct($srcenc = null, $mode = 'event', $tgtenc = null) { @@ -219,14 +247,16 @@ class XML_Parser extends PEAR * This method is only needed, when switching to a new * mode at a later point. * - * @access public - * @param string mode, either 'func' or 'event' - * @return boolean|object true on success, PEAR_Error otherwise + * @param string $mode mode, either 'func' or 'event' + * + * @return boolean|object true on success, PEAR_Error otherwise + * @access public */ function setMode($mode) { if ($mode != 'func' && $mode != 'event') { - $this->raiseError('Unsupported mode given', XML_PARSER_ERROR_UNSUPPORTED_MODE); + $this->raiseError('Unsupported mode given', + XML_PARSER_ERROR_UNSUPPORTED_MODE); } $this->mode = $mode; @@ -243,10 +273,11 @@ class XML_Parser extends PEAR * If no object will be set, XML_Parser assumes that you * extend this class and handle the events in $this. * - * @access public - * @param object object to handle the events - * @return boolean will always return true - * @since v1.2.0beta3 + * @param object &$obj object to handle the events + * + * @return boolean will always return true + * @access public + * @since v1.2.0beta3 */ function setHandlerObj(&$obj) { @@ -257,7 +288,8 @@ class XML_Parser extends PEAR /** * Init the element handlers * - * @access private + * @return mixed + * @access private */ function _initHandlers() { @@ -270,21 +302,22 @@ class XML_Parser extends PEAR } switch ($this->mode) { - case 'func': - xml_set_object($this->parser, $this->_handlerObj); - xml_set_element_handler($this->parser, array(&$this, 'funcStartHandler'), array(&$this, 'funcEndHandler')); - break; + case 'func': + xml_set_object($this->parser, $this->_handlerObj); + xml_set_element_handler($this->parser, + array(&$this, 'funcStartHandler'), array(&$this, 'funcEndHandler')); + break; - case 'event': - xml_set_object($this->parser, $this->_handlerObj); - xml_set_element_handler($this->parser, 'startHandler', 'endHandler'); - break; - default: - return $this->raiseError('Unsupported mode given', XML_PARSER_ERROR_UNSUPPORTED_MODE); - break; + case 'event': + xml_set_object($this->parser, $this->_handlerObj); + xml_set_element_handler($this->parser, 'startHandler', 'endHandler'); + break; + default: + return $this->raiseError('Unsupported mode given', + XML_PARSER_ERROR_UNSUPPORTED_MODE); + break; } - /** * set additional handlers for character data, entities, etc. */ @@ -293,7 +326,7 @@ class XML_Parser extends PEAR $xml_func = 'xml_set_' . $xml_func; $xml_func($this->parser, $method); } - } + } } // {{{ _create() @@ -307,9 +340,10 @@ class XML_Parser extends PEAR * Furthermore it allows us returning an error * if something fails. * - * @access private - * @return boolean|object true on success, PEAR_Error otherwise + * NOTE: uses '@' error suppresion in this method * + * @return bool|PEAR_Error true on success, PEAR_Error otherwise + * @access private * @see xml_parser_create */ function _create() @@ -321,21 +355,27 @@ class XML_Parser extends PEAR } if (is_resource($xp)) { if ($this->tgtenc !== null) { - if (!@xml_parser_set_option($xp, XML_OPTION_TARGET_ENCODING, - $this->tgtenc)) { - return $this->raiseError('invalid target encoding', XML_PARSER_ERROR_INVALID_ENCODING); + if (!@xml_parser_set_option($xp, XML_OPTION_TARGET_ENCODING, + $this->tgtenc) + ) { + return $this->raiseError('invalid target encoding', + XML_PARSER_ERROR_INVALID_ENCODING); } } $this->parser = $xp; - $result = $this->_initHandlers($this->mode); + $result = $this->_initHandlers($this->mode); if ($this->isError($result)) { return $result; } xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, $this->folding); - return true; } - return $this->raiseError('Unable to create XML parser resource.', XML_PARSER_ERROR_NO_RESOURCE); + if (!in_array(strtoupper($this->srcenc), $this->_validEncodings)) { + return $this->raiseError('invalid source encoding', + XML_PARSER_ERROR_INVALID_ENCODING); + } + return $this->raiseError('Unable to create XML parser resource.', + XML_PARSER_ERROR_NO_RESOURCE); } // }}} @@ -353,7 +393,7 @@ class XML_Parser extends PEAR function reset() { $result = $this->_create(); - if ($this->isError( $result )) { + if ($this->isError($result)) { return $result; } return true; @@ -365,11 +405,12 @@ class XML_Parser extends PEAR /** * Sets the input xml file to be parsed * - * @param string Filename (full path) - * @return resource fopen handle of the given file - * @throws XML_Parser_Error - * @see setInput(), setInputString(), parse() - * @access public + * @param string $file Filename (full path) + * + * @return resource fopen handle of the given file + * @access public + * @throws XML_Parser_Error + * @see setInput(), setInputString(), parse() */ function setInputFile($file) { @@ -378,35 +419,39 @@ class XML_Parser extends PEAR */ if (eregi('^(http|ftp)://', substr($file, 0, 10))) { if (!ini_get('allow_url_fopen')) { - return $this->raiseError('Remote files cannot be parsed, as safe mode is enabled.', XML_PARSER_ERROR_REMOTE); + return $this-> + raiseError('Remote files cannot be parsed, as safe mode is enabled.', + XML_PARSER_ERROR_REMOTE); } } - + $fp = @fopen($file, 'rb'); if (is_resource($fp)) { $this->fp = $fp; return $fp; } - return $this->raiseError('File could not be opened.', XML_PARSER_ERROR_FILE_NOT_READABLE); + return $this->raiseError('File could not be opened.', + XML_PARSER_ERROR_FILE_NOT_READABLE); } // }}} // {{{ setInputString() - + /** * XML_Parser::setInputString() - * + * * Sets the xml input from a string - * + * * @param string $data a string containing the XML document + * * @return null - **/ + */ function setInputString($data) { $this->fp = $data; return null; } - + // }}} // {{{ setInput() @@ -414,35 +459,35 @@ class XML_Parser extends PEAR * Sets the file handle to use with parse(). * * You should use setInputFile() or setInputString() if you - * pass a string + * pass a string * - * @param mixed $fp Can be either a resource returned from fopen(), - * a URL, a local filename or a string. - * @access public - * @see parse() - * @uses setInputString(), setInputFile() + * @param mixed $fp Can be either a resource returned from fopen(), + * a URL, a local filename or a string. + * + * @return mixed + * @access public + * @see parse() + * @uses setInputString(), setInputFile() */ function setInput($fp) { if (is_resource($fp)) { $this->fp = $fp; return true; - } - // see if it's an absolute URL (has a scheme at the beginning) - elseif (eregi('^[a-z]+://', substr($fp, 0, 10))) { + } elseif (eregi('^[a-z]+://', substr($fp, 0, 10))) { + // see if it's an absolute URL (has a scheme at the beginning) return $this->setInputFile($fp); - } - // see if it's a local file - elseif (file_exists($fp)) { + } elseif (file_exists($fp)) { + // see if it's a local file return $this->setInputFile($fp); - } - // it must be a string - else { + } else { + // it must be a string $this->fp = $fp; return true; } - return $this->raiseError('Illegal input format', XML_PARSER_ERROR_INVALID_INPUT); + return $this->raiseError('Illegal input format', + XML_PARSER_ERROR_INVALID_INPUT); } // }}} @@ -451,8 +496,8 @@ class XML_Parser extends PEAR /** * Central parsing function. * - * @return true|object PEAR error returns true on success, or a PEAR_Error otherwise - * @access public + * @return bool|PEAR_Error returns true on success, or a PEAR_Error otherwise + * @access public */ function parse() { @@ -465,7 +510,7 @@ class XML_Parser extends PEAR } // if $this->fp was fopened previously if (is_resource($this->fp)) { - + while ($data = fread($this->fp, 4096)) { if (!$this->_parseString($data, feof($this->fp))) { $error = &$this->raiseError(); @@ -473,8 +518,8 @@ class XML_Parser extends PEAR return $error; } } - // otherwise, $this->fp must be a string } else { + // otherwise, $this->fp must be a string if (!$this->_parseString($this->fp, true)) { $error = &$this->raiseError(); $this->free(); @@ -488,9 +533,10 @@ class XML_Parser extends PEAR /** * XML_Parser::_parseString() - * - * @param string $data - * @param boolean $eof + * + * @param string $data data + * @param bool $eof end-of-file flag + * * @return bool * @access private * @see parseString() @@ -499,31 +545,33 @@ class XML_Parser extends PEAR { return xml_parse($this->parser, $data, $eof); } - + // }}} // {{{ parseString() /** * XML_Parser::parseString() - * + * * Parses a string. * - * @param string $data XML data - * @param boolean $eof If set and TRUE, data is the last piece of data sent in this parser - * @throws XML_Parser_Error - * @return Pear Error|true true on success or a PEAR Error - * @see _parseString() + * @param string $data XML data + * @param boolean $eof If set and TRUE, data is the last piece + * of data sent in this parser + * + * @return bool|PEAR_Error true on success or a PEAR Error + * @throws XML_Parser_Error + * @see _parseString() */ function parseString($data, $eof = false) { if (!isset($this->parser) || !is_resource($this->parser)) { $this->reset(); } - + if (!$this->_parseString($data, $eof)) { - $error = &$this->raiseError(); - $this->free(); - return $error; + $error = &$this->raiseError(); + $this->free(); + return $error; } if ($eof === true) { @@ -531,12 +579,12 @@ class XML_Parser extends PEAR } return true; } - + /** * XML_Parser::free() - * + * * Free the internal resources associated with the parser - * + * * @return null **/ function free() @@ -551,15 +599,16 @@ class XML_Parser extends PEAR unset($this->fp); return null; } - + /** * XML_Parser::raiseError() - * + * * Throws a XML_Parser_Error - * + * * @param string $msg the error message * @param integer $ecode the error message code - * @return XML_Parser_Error + * + * @return XML_Parser_Error **/ function raiseError($msg = null, $ecode = 0) { @@ -567,32 +616,46 @@ class XML_Parser extends PEAR $err = &new XML_Parser_Error($msg, $ecode); return parent::raiseError($err); } - + // }}} // {{{ funcStartHandler() + /** + * derives and calls the Start Handler function + * + * @param mixed $xp ?? + * @param mixed $elem ?? + * @param mixed $attribs ?? + * + * @return void + */ function funcStartHandler($xp, $elem, $attribs) { $func = 'xmltag_' . $elem; - if (strchr($func, '.')) { - $func = str_replace('.', '_', $func); - } + $func = str_replace(array('.', '-', ':'), '_', $func); if (method_exists($this->_handlerObj, $func)) { call_user_func(array(&$this->_handlerObj, $func), $xp, $elem, $attribs); } elseif (method_exists($this->_handlerObj, 'xmltag')) { - call_user_func(array(&$this->_handlerObj, 'xmltag'), $xp, $elem, $attribs); + call_user_func(array(&$this->_handlerObj, 'xmltag'), + $xp, $elem, $attribs); } } // }}} // {{{ funcEndHandler() + /** + * derives and calls the End Handler function + * + * @param mixed $xp ?? + * @param mixed $elem ?? + * + * @return void + */ function funcEndHandler($xp, $elem) { $func = 'xmltag_' . $elem . '_'; - if (strchr($func, '.')) { - $func = str_replace('.', '_', $func); - } + $func = str_replace(array('.', '-', ':'), '_', $func); if (method_exists($this->_handlerObj, $func)) { call_user_func(array(&$this->_handlerObj, $func), $xp, $elem); } elseif (method_exists($this->_handlerObj, 'xmltag_')) { @@ -604,24 +667,35 @@ class XML_Parser extends PEAR // {{{ startHandler() /** + * abstract method signature for Start Handler * + * @param mixed $xp ?? + * @param mixed $elem ?? + * @param mixed &$attribs ?? + * + * @return null * @abstract */ function startHandler($xp, $elem, &$attribs) { - return NULL; + return null; } // }}} // {{{ endHandler() /** + * abstract method signature for End Handler * + * @param mixed $xp ?? + * @param mixed $elem ?? + * + * @return null * @abstract */ function endHandler($xp, $elem) { - return NULL; + return null; } @@ -639,47 +713,56 @@ class XML_Parser extends PEAR * - check for XML_Parser error, using is_a( $error, 'XML_Parser_Error' ) * - messages can be generated from the xml_parser resource * - * @package XML_Parser - * @access public - * @see PEAR_Error + * @category XML + * @package XML_Parser + * @author Stig Bakken + * @author Tomas V.V.Cox + * @author Stephan Schmidt + * @copyright 2002-2008 The PHP Group + * @license http://opensource.org/licenses/bsd-license New BSD License + * @version Release: @package_version@ + * @link http://pear.php.net/package/XML_Parser + * @see PEAR_Error */ class XML_Parser_Error extends PEAR_Error { // {{{ properties - /** + /** * prefix for all messages * * @var string - */ + */ var $error_message_prefix = 'XML_Parser: '; // }}} // {{{ constructor() - /** + /** * construct a new error instance * * You may either pass a message or an xml_parser resource as first * parameter. If a resource has been passed, the last error that * happened will be retrieved and returned. * + * @param string|resource $msgorparser message or parser resource + * @param integer $code error code + * @param integer $mode error handling + * @param integer $level error level + * * @access public - * @param string|resource message or parser resource - * @param integer error code - * @param integer error handling - * @param integer error level - */ + * @todo PEAR CS - can't meet 85char line limit without arg refactoring + */ function XML_Parser_Error($msgorparser = 'unknown error', $code = 0, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE) { if (is_resource($msgorparser)) { - $code = xml_get_error_code($msgorparser); + $code = xml_get_error_code($msgorparser); $msgorparser = sprintf('%s at XML input line %d:%d', - xml_error_string($code), - xml_get_current_line_number($msgorparser), - xml_get_current_column_number($msgorparser)); + xml_error_string($code), + xml_get_current_line_number($msgorparser), + xml_get_current_column_number($msgorparser)); } $this->PEAR_Error($msgorparser, $code, $mode, $level); } // }}} } -?> \ No newline at end of file +?> diff --git a/includes/pear/XML/Parser/Simple.php b/includes/pear/XML/Parser/Simple.php index 535692f5..2ba9fb51 100644 --- a/includes/pear/XML/Parser/Simple.php +++ b/includes/pear/XML/Parser/Simple.php @@ -1,37 +1,50 @@ | -// +----------------------------------------------------------------------+ -// -// $Id: Simple.php,v 1.6 2005/03/25 17:13:10 schst Exp $ + +/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ /** - * Simple XML parser class. + * XML_Parser * - * This class is a simplified version of XML_Parser. - * In most XML applications the real action is executed, - * when a closing tag is found. + * XML Parser's Simple parser class * - * XML_Parser_Simple allows you to just implement one callback - * for each tag that will receive the tag with its attributes - * and CData + * PHP versions 4 and 5 * - * @category XML - * @package XML_Parser - * @author Stephan Schmidt + * LICENSE: + * + * Copyright (c) 2002-2008 The PHP Group + * 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. + * * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF 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. + * + * @category XML + * @package XML_Parser + * @author Stephan Schmidt + * @copyright 2004-2008 Stephan Schmidt + * @license http://opensource.org/licenses/bsd-license New BSD License + * @version CVS: $Id: Simple.php,v 1.7 2008/08/24 21:48:21 ashnazg Exp $ + * @link http://pear.php.net/package/XML_Parser */ /** @@ -72,34 +85,38 @@ require_once 'XML/Parser.php'; * $result = $p->parse(); * * - * @category XML - * @package XML_Parser - * @author Stephan Schmidt + * @category XML + * @package XML_Parser + * @author Stephan Schmidt + * @copyright 2004-2008 The PHP Group + * @license http://opensource.org/licenses/bsd-license New BSD License + * @version Release: @package_version@ + * @link http://pear.php.net/package/XML_Parser */ class XML_Parser_Simple extends XML_Parser { - /** - * element stack - * - * @access private - * @var array - */ + /** + * element stack + * + * @access private + * @var array + */ var $_elStack = array(); - /** - * all character data - * - * @access private - * @var array - */ + /** + * all character data + * + * @access private + * @var array + */ var $_data = array(); - /** - * element depth - * - * @access private - * @var integer - */ + /** + * element depth + * + * @access private + * @var integer + */ var $_depth = 0; /** @@ -126,7 +143,7 @@ class XML_Parser_Simple extends XML_Parser * @param string $mode how this parser object should work, "event" for * handleElement(), "func" to have it call functions * named after elements (handleElement_$name()) - * @param string $tgenc a valid target encoding + * @param string $tgtenc a valid target encoding */ function XML_Parser_Simple($srcenc = null, $mode = 'event', $tgtenc = null) { @@ -136,7 +153,8 @@ class XML_Parser_Simple extends XML_Parser /** * inits the handlers * - * @access private + * @return mixed + * @access private */ function _initHandlers() { @@ -145,11 +163,13 @@ class XML_Parser_Simple extends XML_Parser } if ($this->mode != 'func' && $this->mode != 'event') { - return $this->raiseError('Unsupported mode given', XML_PARSER_ERROR_UNSUPPORTED_MODE); + return $this->raiseError('Unsupported mode given', + XML_PARSER_ERROR_UNSUPPORTED_MODE); } xml_set_object($this->parser, $this->_handlerObj); - xml_set_element_handler($this->parser, array(&$this, 'startHandler'), array(&$this, 'endHandler')); + xml_set_element_handler($this->parser, array(&$this, 'startHandler'), + array(&$this, 'endHandler')); xml_set_character_data_handler($this->parser, array(&$this, 'cdataHandler')); /** @@ -160,7 +180,7 @@ class XML_Parser_Simple extends XML_Parser $xml_func = 'xml_set_' . $xml_func; $xml_func($this->parser, $method); } - } + } } /** @@ -179,44 +199,47 @@ class XML_Parser_Simple extends XML_Parser $this->_depth = 0; $result = $this->_create(); - if ($this->isError( $result )) { + if ($this->isError($result)) { return $result; } return true; } - /** - * start handler - * - * Pushes attributes and tagname onto a stack - * - * @access private - * @final - * @param resource xml parser resource - * @param string element name - * @param array attributes - */ + /** + * start handler + * + * Pushes attributes and tagname onto a stack + * + * @param resource $xp xml parser resource + * @param string $elem element name + * @param array &$attribs attributes + * + * @return mixed + * @access private + * @final + */ function startHandler($xp, $elem, &$attribs) { array_push($this->_elStack, array( - 'name' => $elem, - 'attribs' => $attribs - ) - ); + 'name' => $elem, + 'attribs' => $attribs + )); $this->_depth++; $this->_data[$this->_depth] = ''; } - /** - * end handler - * - * Pulls attributes and tagname from a stack - * - * @access private - * @final - * @param resource xml parser resource - * @param string element name - */ + /** + * end handler + * + * Pulls attributes and tagname from a stack + * + * @param resource $xp xml parser resource + * @param string $elem element name + * + * @return mixed + * @access private + * @final + */ function endHandler($xp, $elem) { $el = array_pop($this->_elStack); @@ -224,72 +247,78 @@ class XML_Parser_Simple extends XML_Parser $this->_depth--; switch ($this->mode) { - case 'event': - $this->_handlerObj->handleElement($el['name'], $el['attribs'], $data); - break; - case 'func': - $func = 'handleElement_' . $elem; - if (strchr($func, '.')) { - $func = str_replace('.', '_', $func); - } - if (method_exists($this->_handlerObj, $func)) { - call_user_func(array(&$this->_handlerObj, $func), $el['name'], $el['attribs'], $data); - } - break; + case 'event': + $this->_handlerObj->handleElement($el['name'], $el['attribs'], $data); + break; + case 'func': + $func = 'handleElement_' . $elem; + if (strchr($func, '.')) { + $func = str_replace('.', '_', $func); + } + if (method_exists($this->_handlerObj, $func)) { + call_user_func(array(&$this->_handlerObj, $func), + $el['name'], $el['attribs'], $data); + } + break; } } - /** - * handle character data - * - * @access private - * @final - * @param resource xml parser resource - * @param string data - */ + /** + * handle character data + * + * @param resource $xp xml parser resource + * @param string $data data + * + * @return void + * @access private + * @final + */ function cdataHandler($xp, $data) { $this->_data[$this->_depth] .= $data; } - /** - * handle a tag - * - * Implement this in your parser - * - * @access public - * @abstract - * @param string element name - * @param array attributes - * @param string character data - */ + /** + * handle a tag + * + * Implement this in your parser + * + * @param string $name element name + * @param array $attribs attributes + * @param string $data character data + * + * @return void + * @access public + * @abstract + */ function handleElement($name, $attribs, $data) { } - /** - * get the current tag depth - * - * The root tag is in depth 0. - * - * @access public - * @return integer - */ + /** + * get the current tag depth + * + * The root tag is in depth 0. + * + * @access public + * @return integer + */ function getCurrentDepth() { return $this->_depth; } - /** - * add some string to the current ddata. - * - * This is commonly needed, when a document is parsed recursively. - * - * @access public - * @param string data to add - * @return void - */ - function addToData( $data ) + /** + * add some string to the current ddata. + * + * This is commonly needed, when a document is parsed recursively. + * + * @param string $data data to add + * + * @return void + * @access public + */ + function addToData($data) { $this->_data[$this->_depth] .= $data; } diff --git a/includes/pear/scripts/pear.bat b/includes/pear/scripts/pear.bat deleted file mode 100644 index 64130a88..00000000 --- a/includes/pear/scripts/pear.bat +++ /dev/null @@ -1,115 +0,0 @@ -@ECHO OFF - -REM ---------------------------------------------------------------------- -REM PHP version 5 -REM ---------------------------------------------------------------------- -REM Copyright (c) 1997-2004 The PHP Group -REM ---------------------------------------------------------------------- -REM This source file is subject to version 3.0 of the PHP license, -REM that is bundled with this package in the file LICENSE, and is -REM available at through the world-wide-web at -REM http://www.php.net/license/3_0.txt. -REM If you did not receive a copy of the PHP license and are unable to -REM obtain it through the world-wide-web, please send a note to -REM license@php.net so we can mail you a copy immediately. -REM ---------------------------------------------------------------------- -REM Authors: Alexander Merz (alexmerz@php.net) -REM ---------------------------------------------------------------------- -REM -REM Last updated 12/29/2004 ($Id$ is not replaced if the file is binary) - -REM change this lines to match the paths of your system -REM ------------------- - - -REM Test to see if this is a raw pear.bat (uninstalled version) -SET TMPTMPTMPTMPT=@includ -SET PMTPMTPMT=%TMPTMPTMPTMPT%e_path@ -FOR %%x IN ("@include_path@") DO (if %%x=="%PMTPMTPMT%" GOTO :NOTINSTALLED) - -REM Check PEAR global ENV, set them if they do not exist -IF "%PHP_PEAR_INSTALL_DIR%"=="" SET "PHP_PEAR_INSTALL_DIR=@include_path@" -IF "%PHP_PEAR_BIN_DIR%"=="" SET "PHP_PEAR_BIN_DIR=@bin_dir@" -IF "%PHP_PEAR_PHP_BIN%"=="" SET "PHP_PEAR_PHP_BIN=@php_bin@" -GOTO :INSTALLED - -:NOTINSTALLED -ECHO WARNING: This is a raw, uninstalled pear.bat - -REM Check to see if we can grab the directory of this file (Windows NT+) -IF %~n0 == pear ( -FOR %%x IN (cli\php.exe php.exe) DO (if "%%~$PATH:x" NEQ "" ( -SET "PHP_PEAR_PHP_BIN=%%~$PATH:x" -echo Using PHP Executable "%PHP_PEAR_PHP_BIN%" -"%PHP_PEAR_PHP_BIN%" -v -GOTO :NEXTTEST -)) -GOTO :FAILAUTODETECT -:NEXTTEST -IF "%PHP_PEAR_PHP_BIN%" NEQ "" ( - -REM We can use this PHP to run a temporary php file to get the dirname of pear - -echo ^ > ~~getloc.php -"%PHP_PEAR_PHP_BIN%" ~~getloc.php -set /p PHP_PEAR_BIN_DIR=fakeprompt < ~a.a -DEL ~a.a -DEL ~~getloc.php -set "PHP_PEAR_INSTALL_DIR=%PHP_PEAR_BIN_DIR%pear" - -REM Make sure there is a pearcmd.php at our disposal - -IF NOT EXIST %PHP_PEAR_INSTALL_DIR%\pearcmd.php ( -IF EXIST %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php COPY %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php -IF EXIST pearcmd.php COPY pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php -IF EXIST %~dp0\scripts\pearcmd.php COPY %~dp0\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php -) -) -GOTO :INSTALLED -) ELSE ( -REM Windows Me/98 cannot succeed, so allow the batch to fail -) -:FAILAUTODETECT -echo WARNING: failed to auto-detect pear information -:INSTALLED - -REM Check Folders and files -IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%" GOTO PEAR_INSTALL_ERROR -IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%\pearcmd.php" GOTO PEAR_INSTALL_ERROR2 -IF NOT EXIST "%PHP_PEAR_BIN_DIR%" GOTO PEAR_BIN_ERROR -IF NOT EXIST "%PHP_PEAR_PHP_BIN%" GOTO PEAR_PHPBIN_ERROR -REM launch pearcmd -GOTO RUN -:PEAR_INSTALL_ERROR -ECHO PHP_PEAR_INSTALL_DIR is not set correctly. -ECHO Please fix it using your environment variable or modify -ECHO the default value in pear.bat -ECHO The current value is: -ECHO %PHP_PEAR_INSTALL_DIR% -GOTO END -:PEAR_INSTALL_ERROR2 -ECHO PHP_PEAR_INSTALL_DIR is not set correctly. -ECHO pearcmd.php could not be found there. -ECHO Please fix it using your environment variable or modify -ECHO the default value in pear.bat -ECHO The current value is: -ECHO %PHP_PEAR_INSTALL_DIR% -GOTO END -:PEAR_BIN_ERROR -ECHO PHP_PEAR_BIN_DIR is not set correctly. -ECHO Please fix it using your environment variable or modify -ECHO the default value in pear.bat -ECHO The current value is: -ECHO %PHP_PEAR_BIN_DIR% -GOTO END -:PEAR_PHPBIN_ERROR -ECHO PHP_PEAR_PHP_BIN is not set correctly. -ECHO Please fix it using your environment variable or modify -ECHO the default value in pear.bat -ECHO The current value is: -ECHO %PHP_PEAR_PHP_BIN% -GOTO END -:RUN -"%PHP_PEAR_PHP_BIN%" -C -d output_buffering=1 -d include_path="%PHP_PEAR_INSTALL_DIR%" -f "%PHP_PEAR_INSTALL_DIR%\pearcmd.php" -- %1 %2 %3 %4 %5 %6 %7 %8 %9 -:END -@ECHO ON \ No newline at end of file diff --git a/includes/pear/scripts/pear.sh b/includes/pear/scripts/pear.sh deleted file mode 100644 index 6253b901..00000000 --- a/includes/pear/scripts/pear.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -# first find which PHP binary to use -if test "x$PHP_PEAR_PHP_BIN" != "x"; then - PHP="$PHP_PEAR_PHP_BIN" -else - if test "@php_bin@" = '@'php_bin'@'; then - PHP=php - else - PHP="@php_bin@" - fi -fi - -# then look for the right pear include dir -if test "x$PHP_PEAR_INSTALL_DIR" != "x"; then - INCDIR=$PHP_PEAR_INSTALL_DIR - INCARG="-d include_path=$PHP_PEAR_INSTALL_DIR" -else - if test "@php_dir@" = '@'php_dir'@'; then - INCDIR=`dirname $0` - INCARG="" - else - INCDIR="@php_dir@" - INCARG="-d include_path=@php_dir@" - fi -fi - -exec $PHP -C -q $INCARG -d output_buffering=1 $INCDIR/pearcmd.php "$@" diff --git a/includes/pear/scripts/pearcmd.php b/includes/pear/scripts/pearcmd.php deleted file mode 100644 index 71a3ac7e..00000000 --- a/includes/pear/scripts/pearcmd.php +++ /dev/null @@ -1,423 +0,0 @@ - | -// | Tomas V.V.Cox | -// | | -// +----------------------------------------------------------------------+ -// -// $Id: pearcmd.php,v 1.29 2005/11/12 02:26:53 cellog Exp $ - -ob_end_clean(); -if (!defined('PEAR_RUNTYPE')) { - // this is defined in peclcmd.php as 'pecl' - define('PEAR_RUNTYPE', 'pear'); -} -define('PEAR_IGNORE_BACKTRACE', 1); -if (!function_exists('file_get_contents')) { - function file_get_contents($filename) - { - $fp = fopen($filename, 'rb'); - $ret = ''; - while (!feof($fp)) { - $ret .= fread($fp, 8092);; - } - return $ret; - } -} -/** - * @nodep Gtk - */ -if ('@include_path@' != '@'.'include_path'.'@') { - ini_set('include_path', '@include_path@'); - $raw = false; -} else { - // this is a raw, uninstalled pear, either a cvs checkout, or php distro - $raw = true; -} -@ini_set('allow_url_fopen', true); -if (!ini_get('safe_mode')) { - @set_time_limit(0); -} -ob_implicit_flush(true); -@ini_set('track_errors', true); -@ini_set('html_errors', false); -@ini_set('magic_quotes_runtime', false); -$_PEAR_PHPDIR = '#$%^&*'; -set_error_handler('error_handler'); - -$pear_package_version = "@pear_version@"; - -require_once 'PEAR.php'; -require_once 'PEAR/Frontend.php'; -require_once 'PEAR/Config.php'; -require_once 'PEAR/Command.php'; -require_once 'Console/Getopt.php'; - - -PEAR_Command::setFrontendType('CLI'); -$all_commands = PEAR_Command::getCommands(); - -$argv = Console_Getopt::readPHPArgv(); -$progname = PEAR_RUNTYPE; -if (in_array('getopt2', get_class_methods('Console_Getopt'))) { - array_shift($argv); - $options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV"); -} else { - $options = Console_Getopt::getopt($argv, "c:C:d:D:Gh?sSqu:vV"); -} -if (PEAR::isError($options)) { - usage($options); -} - -$opts = $options[0]; - -$fetype = 'CLI'; -if ($progname == 'gpear' || $progname == 'pear-gtk') { - $fetype = 'Gtk'; -} else { - foreach ($opts as $opt) { - if ($opt[0] == 'G') { - $fetype = 'Gtk'; - } - } -} -$pear_user_config = ''; -$pear_system_config = ''; -$store_user_config = false; -$store_system_config = false; -$verbose = 1; - -foreach ($opts as $opt) { - switch ($opt[0]) { - case 'c': - $pear_user_config = $opt[1]; - break; - case 'C': - $pear_system_config = $opt[1]; - break; - } -} - -PEAR_Command::setFrontendType($fetype); -$ui = &PEAR_Command::getFrontendObject(); -$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config); - -if (PEAR::isError($config)) { - $_file = ''; - if ($pear_user_config !== false) { - $_file .= $pear_user_config; - } - if ($pear_system_config !== false) { - $_file .= '/' . $pear_system_config; - } - if ($_file == '/') { - $_file = 'The default config file'; - } - $config->getMessage(); - $ui->outputData("ERROR: $_file is not a valid config file or is corrupted."); - // We stop, we have no idea where we are :) - exit(); -} - -// this is used in the error handler to retrieve a relative path -$_PEAR_PHPDIR = $config->get('php_dir'); -$ui->setConfig($config); -PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")); -if (ini_get('safe_mode')) { - $ui->outputData('WARNING: running in safe mode requires that all files created ' . - 'be the same uid as the current script. PHP reports this script is uid: ' . - @getmyuid() . ', and current user is: ' . @get_current_user()); -} - -$verbose = $config->get("verbose"); -$cmdopts = array(); - -if ($raw) { - if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) { - $found = false; - foreach ($opts as $opt) { - if ($opt[0] == 'd' || $opt[0] == 'D') { - $found = true; // the user knows what they are doing, and are setting config values - } - } - if (!$found) { - // no prior runs, try to install PEAR - if (strpos(dirname(__FILE__), 'scripts')) { - $packagexml = dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'package2.xml'; - $pearbase = dirname(dirname(__FILE__)); - } else { - $packagexml = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'package2.xml'; - $pearbase = dirname(__FILE__); - } - if (file_exists($packagexml)) { - $options[1] = array( - 'install', - $packagexml - ); - $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php'); - $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data'); - $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs'); - $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests'); - $config->set('ext_dir', $pearbase . DIRECTORY_SEPARATOR . 'extensions'); - $config->set('bin_dir', $pearbase); - $config->mergeConfigFile($pearbase . 'pear.ini', false); - $config->store(); - $config->set('auto_discover', 1); - } - } - } -} -foreach ($opts as $opt) { - $param = !empty($opt[1]) ? $opt[1] : true; - switch ($opt[0]) { - case 'd': - list($key, $value) = explode('=', $param); - $config->set($key, $value, 'user'); - break; - case 'D': - list($key, $value) = explode('=', $param); - $config->set($key, $value, 'system'); - break; - case 's': - $store_user_config = true; - break; - case 'S': - $store_system_config = true; - break; - case 'u': - $config->remove($param, 'user'); - break; - case 'v': - $config->set('verbose', $config->get('verbose') + 1); - break; - case 'q': - $config->set('verbose', $config->get('verbose') - 1); - break; - case 'V': - usage(null, 'version'); - case 'c': - case 'C': - break; - default: - // all non pear params goes to the command - $cmdopts[$opt[0]] = $param; - break; - } -} - -if ($store_system_config) { - $config->store('system'); -} - -if ($store_user_config) { - $config->store('user'); -} - -$command = (isset($options[1][0])) ? $options[1][0] : null; - -if (empty($command) && ($store_user_config || $store_system_config)) { - exit; -} - -if ($fetype == 'Gtk') { - if (!$config->validConfiguration()) { - PEAR::raiseError('CRITICAL ERROR: no existing valid configuration files found in files ' . - "'$pear_user_config' or '$pear_system_config', please copy an existing configuration" . - 'file to one of these locations, or use the -c and -s options to create one'); - } - Gtk::main(); -} else do { - if ($command == 'help') { - usage(null, @$options[1][1]); - } - if (!$config->validConfiguration()) { - PEAR::raiseError('CRITICAL ERROR: no existing valid configuration files found in files ' . - "'$pear_user_config' or '$pear_system_config', please copy an existing configuration" . - 'file to one of these locations, or use the -c and -s options to create one'); - } - - PEAR::pushErrorHandling(PEAR_ERROR_RETURN); - $cmd = PEAR_Command::factory($command, $config); - PEAR::popErrorHandling(); - if (PEAR::isError($cmd)) { - usage(null, @$options[1][0]); - } - - $short_args = $long_args = null; - PEAR_Command::getGetoptArgs($command, $short_args, $long_args); - if (in_array('getopt2', get_class_methods('Console_Getopt'))) { - array_shift($options[1]); - $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args); - } else { - $tmp = Console_Getopt::getopt($options[1], $short_args, $long_args); - } - if (PEAR::isError($tmp)) { - break; - } - list($tmpopt, $params) = $tmp; - $opts = array(); - foreach ($tmpopt as $foo => $tmp2) { - list($opt, $value) = $tmp2; - if ($value === null) { - $value = true; // options without args - } - if (strlen($opt) == 1) { - $cmdoptions = $cmd->getOptions($command); - foreach ($cmdoptions as $o => $d) { - if (@$d['shortopt'] == $opt) { - $opts[$o] = $value; - } - } - } else { - if (substr($opt, 0, 2) == '--') { - $opts[substr($opt, 2)] = $value; - } - } - } - $ok = $cmd->run($command, $opts, $params); - if ($ok === false) { - PEAR::raiseError("unknown command `$command'"); - } - if (PEAR::isError($ok)) { - PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")); - PEAR::raiseError($ok); - } -} while (false); - -// {{{ usage() - -function usage($error = null, $helpsubject = null) -{ - global $progname, $all_commands; - $stderr = fopen('php://stderr', 'w'); - if (PEAR::isError($error)) { - fputs($stderr, $error->getMessage() . "\n"); - } elseif ($error !== null) { - fputs($stderr, "$error\n"); - } - if ($helpsubject != null) { - $put = cmdHelp($helpsubject); - } else { - $put = - "Commands:\n"; - $maxlen = max(array_map("strlen", $all_commands)); - $formatstr = "%-{$maxlen}s %s\n"; - ksort($all_commands); - foreach ($all_commands as $cmd => $class) { - $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd)); - } - $put .= - "Usage: $progname [options] command [command-options] \n". - "Type \"$progname help options\" to list all options.\n". - "Type \"$progname help shortcuts\" to list all command shortcuts.\n". - "Type \"$progname help \" to get the help for the specified command."; - } - fputs($stderr, "$put\n"); - fclose($stderr); - exit; -} - -function cmdHelp($command) -{ - global $progname, $all_commands, $config; - if ($command == "options") { - return - "Options:\n". - " -v increase verbosity level (default 1)\n". - " -q be quiet, decrease verbosity level\n". - " -c file find user configuration in `file'\n". - " -C file find system configuration in `file'\n". - " -d foo=bar set user config variable `foo' to `bar'\n". - " -D foo=bar set system config variable `foo' to `bar'\n". - " -G start in graphical (Gtk) mode\n". - " -s store user configuration\n". - " -S store system configuration\n". - " -u foo unset `foo' in the user configuration\n". - " -h, -? display help/usage (this message)\n". - " -V version information\n"; - } elseif ($command == "shortcuts") { - $sc = PEAR_Command::getShortcuts(); - $ret = "Shortcuts:\n"; - foreach ($sc as $s => $c) { - $ret .= sprintf(" %-8s %s\n", $s, $c); - } - return $ret; - - } elseif ($command == "version") { - return "PEAR Version: ".$GLOBALS['pear_package_version']. - "\nPHP Version: ".phpversion(). - "\nZend Engine Version: ".zend_version(). - "\nRunning on: ".php_uname(); - - } elseif ($help = PEAR_Command::getHelp($command)) { - if (is_string($help)) { - return "$progname $command [options] $help\n"; - } - if ($help[1] === null) { - return "$progname $command $help[0]"; - } else { - return "$progname $command [options] $help[0]\n$help[1]"; - } - } - return "Command '$command' is not valid, try 'pear help'"; -} - -// }}} - -function error_handler($errno, $errmsg, $file, $line, $vars) { - if ((defined('E_STRICT') && $errno & E_STRICT) || !error_reporting()) { - if (defined('E_STRICT') && $errno & E_STRICT) { - return; // E_STRICT - } - if ($GLOBALS['config']->get('verbose') < 4) { - return; // @silenced error, show all if debug is high enough - } - } - $errortype = array ( - E_ERROR => "Error", - E_WARNING => "Warning", - E_PARSE => "Parsing Error", - E_NOTICE => "Notice", - E_CORE_ERROR => "Core Error", - E_CORE_WARNING => "Core Warning", - E_COMPILE_ERROR => "Compile Error", - E_COMPILE_WARNING => "Compile Warning", - E_USER_ERROR => "User Error", - E_USER_WARNING => "User Warning", - E_USER_NOTICE => "User Notice" - ); - $prefix = $errortype[$errno]; - global $_PEAR_PHPDIR; - if (stristr($file, $_PEAR_PHPDIR)) { - $file = substr($file, strlen($_PEAR_PHPDIR) + 1); - } else { - $file = basename($file); - } - print "\n$prefix: $errmsg in $file on line $line\n"; -} - - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * indent-tabs-mode: nil - * mode: php - * End: - */ -// vim600:syn=php - -?> diff --git a/includes/pear/scripts/peardev.bat b/includes/pear/scripts/peardev.bat deleted file mode 100644 index 45b47e7f..00000000 --- a/includes/pear/scripts/peardev.bat +++ /dev/null @@ -1,229 +0,0 @@ -@ECHO OFF - - - -REM ---------------------------------------------------------------------- - -REM PHP version 5 - -REM ---------------------------------------------------------------------- - -REM Copyright (c) 1997-2004 The PHP Group - -REM ---------------------------------------------------------------------- - -REM This source file is subject to version 3.0 of the PHP license, - -REM that is bundled with this package in the file LICENSE, and is - -REM available at through the world-wide-web at - -REM http://www.php.net/license/3_0.txt. - -REM If you did not receive a copy of the PHP license and are unable to - -REM obtain it through the world-wide-web, please send a note to - -REM license@php.net so we can mail you a copy immediately. - -REM ---------------------------------------------------------------------- - -REM Authors: Alexander Merz (alexmerz@php.net) - -REM ---------------------------------------------------------------------- - -REM - -REM $Id: peardev.bat,v 1.2 2005/03/21 15:23:43 cellog Exp $ - - - -REM change this lines to match the paths of your system - -REM ------------------- - - - - - -REM Test to see if this is a raw pear.bat (uninstalled version) - -SET TMPTMPTMPTMPT=@includ - -SET PMTPMTPMT=%TMPTMPTMPTMPT%e_path@ - -FOR %%x IN ("@include_path@") DO (if %%x=="%PMTPMTPMT%" GOTO :NOTINSTALLED) - - - -REM Check PEAR global ENV, set them if they do not exist - -IF "%PHP_PEAR_INSTALL_DIR%"=="" SET "PHP_PEAR_INSTALL_DIR=@include_path@" - -IF "%PHP_PEAR_BIN_DIR%"=="" SET "PHP_PEAR_BIN_DIR=@bin_dir@" - -IF "%PHP_PEAR_PHP_BIN%"=="" SET "PHP_PEAR_PHP_BIN=@php_bin@" - -GOTO :INSTALLED - - - -:NOTINSTALLED - -ECHO WARNING: This is a raw, uninstalled pear.bat - - - -REM Check to see if we can grab the directory of this file (Windows NT+) - -IF %~n0 == pear ( - -FOR %%x IN (cli\php.exe php.exe) DO (if "%%~$PATH:x" NEQ "" ( - -SET "PHP_PEAR_PHP_BIN=%%~$PATH:x" - -echo Using PHP Executable "%PHP_PEAR_PHP_BIN%" - -"%PHP_PEAR_PHP_BIN%" -v - -GOTO :NEXTTEST - -)) - -GOTO :FAILAUTODETECT - -:NEXTTEST - -IF "%PHP_PEAR_PHP_BIN%" NEQ "" ( - - - -REM We can use this PHP to run a temporary php file to get the dirname of pear - - - -echo ^ > ~~getloc.php - -"%PHP_PEAR_PHP_BIN%" ~~getloc.php - -set /p PHP_PEAR_BIN_DIR=fakeprompt < ~a.a - -DEL ~a.a - -DEL ~~getloc.php - -set "PHP_PEAR_INSTALL_DIR=%PHP_PEAR_BIN_DIR%pear" - - - -REM Make sure there is a pearcmd.php at our disposal - - - -IF NOT EXIST %PHP_PEAR_INSTALL_DIR%\pearcmd.php ( - -IF EXIST %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php COPY %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php - -IF EXIST pearcmd.php COPY pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php - -IF EXIST %~dp0\scripts\pearcmd.php COPY %~dp0\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php - -) - -) - -GOTO :INSTALLED - -) ELSE ( - -REM Windows Me/98 cannot succeed, so allow the batch to fail - -) - -:FAILAUTODETECT - -echo WARNING: failed to auto-detect pear information - -:INSTALLED - - - -REM Check Folders and files - -IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%" GOTO PEAR_INSTALL_ERROR - -IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%\pearcmd.php" GOTO PEAR_INSTALL_ERROR2 - -IF NOT EXIST "%PHP_PEAR_BIN_DIR%" GOTO PEAR_BIN_ERROR - -IF NOT EXIST "%PHP_PEAR_PHP_BIN%" GOTO PEAR_PHPBIN_ERROR - -REM launch pearcmd - -GOTO RUN - -:PEAR_INSTALL_ERROR - -ECHO PHP_PEAR_INSTALL_DIR is not set correctly. - -ECHO Please fix it using your environment variable or modify - -ECHO the default value in pear.bat - -ECHO The current value is: - -ECHO %PHP_PEAR_INSTALL_DIR% - -GOTO END - -:PEAR_INSTALL_ERROR2 - -ECHO PHP_PEAR_INSTALL_DIR is not set correctly. - -ECHO pearcmd.php could not be found there. - -ECHO Please fix it using your environment variable or modify - -ECHO the default value in pear.bat - -ECHO The current value is: - -ECHO %PHP_PEAR_INSTALL_DIR% - -GOTO END - -:PEAR_BIN_ERROR - -ECHO PHP_PEAR_BIN_DIR is not set correctly. - -ECHO Please fix it using your environment variable or modify - -ECHO the default value in pear.bat - -ECHO The current value is: - -ECHO %PHP_PEAR_BIN_DIR% - -GOTO END - -:PEAR_PHPBIN_ERROR - -ECHO PHP_PEAR_PHP_BIN is not set correctly. - -ECHO Please fix it using your environment variable or modify - -ECHO the default value in pear.bat - -ECHO The current value is: - -ECHO %PHP_PEAR_PHP_BIN% - -GOTO END - -:RUN - -"%PHP_PEAR_PHP_BIN%" -C -d memory_limit="-1" -d output_buffering=1 -d include_path="%PHP_PEAR_INSTALL_DIR%" -f "%PHP_PEAR_INSTALL_DIR%\pearcmd.php" -- %1 %2 %3 %4 %5 %6 %7 %8 %9 - -:END - -@ECHO ON \ No newline at end of file diff --git a/includes/pear/scripts/peardev.sh b/includes/pear/scripts/peardev.sh deleted file mode 100644 index 7f1383ed..00000000 --- a/includes/pear/scripts/peardev.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -# first find which PHP binary to use -if test "x$PHP_PEAR_PHP_BIN" != "x"; then - PHP="$PHP_PEAR_PHP_BIN" -else - if test "@php_bin@" = '@'php_bin'@'; then - PHP=php - else - PHP="@php_bin@" - fi -fi - -# then look for the right pear include dir -if test "x$PHP_PEAR_INSTALL_DIR" != "x"; then - INCDIR=$PHP_PEAR_INSTALL_DIR - INCARG="-d include_path=$PHP_PEAR_INSTALL_DIR" -else - if test "@php_dir@" = '@'php_dir'@'; then - INCDIR=`dirname $0` - INCARG="" - else - INCDIR="@php_dir@" - INCARG="-d include_path=@php_dir@" - fi -fi - -exec $PHP -d memory_limit="-1" -C -q $INCARG -d output_buffering=1 $INCDIR/pearcmd.php "$@" diff --git a/includes/pear/scripts/pecl.bat b/includes/pear/scripts/pecl.bat deleted file mode 100644 index c6ba7831..00000000 --- a/includes/pear/scripts/pecl.bat +++ /dev/null @@ -1,115 +0,0 @@ -@ECHO OFF - -REM ---------------------------------------------------------------------- -REM PHP version 5 -REM ---------------------------------------------------------------------- -REM Copyright (c) 1997-2004 The PHP Group -REM ---------------------------------------------------------------------- -REM This source file is subject to version 3.0 of the PHP license, -REM that is bundled with this package in the file LICENSE, and is -REM available at through the world-wide-web at -REM http://www.php.net/license/3_0.txt. -REM If you did not receive a copy of the PHP license and are unable to -REM obtain it through the world-wide-web, please send a note to -REM license@php.net so we can mail you a copy immediately. -REM ---------------------------------------------------------------------- -REM Authors: Alexander Merz (alexmerz@php.net) -REM ---------------------------------------------------------------------- -REM -REM Last updated 02/08/2004 ($Id$ is not replaced if the file is binary) - -REM change this lines to match the paths of your system -REM ------------------- - - -REM Test to see if this is a raw pear.bat (uninstalled version) -SET TMPTMPTMPTMPT=@includ -SET PMTPMTPMT=%TMPTMPTMPTMPT%e_path@ -FOR %%x IN ("@include_path@") DO (if %%x=="%PMTPMTPMT%" GOTO :NOTINSTALLED) - -REM Check PEAR global ENV, set them if they do not exist -IF "%PHP_PEAR_INSTALL_DIR%"=="" SET "PHP_PEAR_INSTALL_DIR=@include_path@" -IF "%PHP_PEAR_BIN_DIR%"=="" SET "PHP_PEAR_BIN_DIR=@bin_dir@" -IF "%PHP_PEAR_PHP_BIN%"=="" SET "PHP_PEAR_PHP_BIN=@php_bin@" -GOTO :INSTALLED - -:NOTINSTALLED -ECHO WARNING: This is a raw, uninstalled pear.bat - -REM Check to see if we can grab the directory of this file (Windows NT+) -IF %~n0 == pear ( -FOR %%x IN (cli\php.exe php.exe) DO (if "%%~$PATH:x" NEQ "" ( -SET "PHP_PEAR_PHP_BIN=%%~$PATH:x" -echo Using PHP Executable "%PHP_PEAR_PHP_BIN%" -"%PHP_PEAR_PHP_BIN%" -v -GOTO :NEXTTEST -)) -GOTO :FAILAUTODETECT -:NEXTTEST -IF "%PHP_PEAR_PHP_BIN%" NEQ "" ( - -REM We can use this PHP to run a temporary php file to get the dirname of pear - -echo ^ > ~~getloc.php -"%PHP_PEAR_PHP_BIN%" ~~getloc.php -set /p PHP_PEAR_BIN_DIR=fakeprompt < ~a.a -DEL ~a.a -DEL ~~getloc.php -set "PHP_PEAR_INSTALL_DIR=%PHP_PEAR_BIN_DIR%pear" - -REM Make sure there is a pearcmd.php at our disposal - -IF NOT EXIST %PHP_PEAR_INSTALL_DIR%\pearcmd.php ( -IF EXIST %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php COPY %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php -IF EXIST pearcmd.php COPY pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php -IF EXIST %~dp0\scripts\pearcmd.php COPY %~dp0\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php -) -) -GOTO :INSTALLED -) ELSE ( -REM Windows Me/98 cannot succeed, so allow the batch to fail -) -:FAILAUTODETECT -echo WARNING: failed to auto-detect pear information -:INSTALLED - -REM Check Folders and files -IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%" GOTO PEAR_INSTALL_ERROR -IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%\pearcmd.php" GOTO PEAR_INSTALL_ERROR2 -IF NOT EXIST "%PHP_PEAR_BIN_DIR%" GOTO PEAR_BIN_ERROR -IF NOT EXIST "%PHP_PEAR_PHP_BIN%" GOTO PEAR_PHPBIN_ERROR -REM launch pearcmd -GOTO RUN -:PEAR_INSTALL_ERROR -ECHO PHP_PEAR_INSTALL_DIR is not set correctly. -ECHO Please fix it using your environment variable or modify -ECHO the default value in pear.bat -ECHO The current value is: -ECHO %PHP_PEAR_INSTALL_DIR% -GOTO END -:PEAR_INSTALL_ERROR2 -ECHO PHP_PEAR_INSTALL_DIR is not set correctly. -ECHO pearcmd.php could not be found there. -ECHO Please fix it using your environment variable or modify -ECHO the default value in pear.bat -ECHO The current value is: -ECHO %PHP_PEAR_INSTALL_DIR% -GOTO END -:PEAR_BIN_ERROR -ECHO PHP_PEAR_BIN_DIR is not set correctly. -ECHO Please fix it using your environment variable or modify -ECHO the default value in pear.bat -ECHO The current value is: -ECHO %PHP_PEAR_BIN_DIR% -GOTO END -:PEAR_PHPBIN_ERROR -ECHO PHP_PEAR_PHP_BIN is not set correctly. -ECHO Please fix it using your environment variable or modify -ECHO the default value in pear.bat -ECHO The current value is: -ECHO %PHP_PEAR_PHP_BIN% -GOTO END -:RUN -"%PHP_PEAR_PHP_BIN%" -C -n -d output_buffering=1 -d safe_mode=0 -d include_path="%PHP_PEAR_INSTALL_DIR%" -f "%PHP_PEAR_INSTALL_DIR%\peclcmd.php" -- %1 %2 %3 %4 %5 %6 %7 %8 %9 -:END -@ECHO ON \ No newline at end of file diff --git a/includes/pear/scripts/pecl.sh b/includes/pear/scripts/pecl.sh deleted file mode 100644 index 0ad593e5..00000000 --- a/includes/pear/scripts/pecl.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -# first find which PHP binary to use -if test "x$PHP_PEAR_PHP_BIN" != "x"; then - PHP="$PHP_PEAR_PHP_BIN" -else - if test "@php_bin@" = '@'php_bin'@'; then - PHP=php - else - PHP="@php_bin@" - fi -fi - -# then look for the right pear include dir -if test "x$PHP_PEAR_INSTALL_DIR" != "x"; then - INCDIR=$PHP_PEAR_INSTALL_DIR - INCARG="-d include_path=$PHP_PEAR_INSTALL_DIR" -else - if test "@php_dir@" = '@'php_dir'@'; then - INCDIR=`dirname $0` - INCARG="" - else - INCDIR="@php_dir@" - INCARG="-d include_path=@php_dir@" - fi -fi - -exec $PHP -C -n -q $INCARG -d output_buffering=1 -d safe_mode=0 $INCDIR/peclcmd.php "$@" diff --git a/includes/pear/scripts/peclcmd.php b/includes/pear/scripts/peclcmd.php deleted file mode 100644 index bdccc754..00000000 --- a/includes/pear/scripts/peclcmd.php +++ /dev/null @@ -1,45 +0,0 @@ - | -// | Tomas V.V.Cox | -// | | -// +----------------------------------------------------------------------+ -// -// $Id: peclcmd.php,v 1.1 2005/02/21 05:30:56 cellog Exp $ - -/** - * @nodep Gtk - */ -if ('@include_path@' != '@'.'include_path'.'@') { - ini_set('include_path', '@include_path@'); - $raw = false; -} else { - // this is a raw, uninstalled pear, either a cvs checkout, or php distro - $raw = true; -} -define('PEAR_RUNTYPE', 'pecl'); -require_once 'pearcmd.php'; -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * indent-tabs-mode: nil - * mode: php - * End: - */ -// vim600:syn=php - -?> diff --git a/modules/core/email_piping.inc.php b/modules/core/email_piping.inc.php index a759a017..b4ce6b99 100644 --- a/modules/core/email_piping.inc.php +++ b/modules/core/email_piping.inc.php @@ -154,7 +154,6 @@ class email_piping $filecontent = imap_fetchbody($mbox,$msg,$file+2); if(empty($filecontent)) return false; $tmp = PATH_FILES.'/'. md5('piping'.$filename.microtime()); - require_once('includes/pear/Compat/Function/file_put_contents.php'); file_put_contents($tmp,$filecontent); $this->attachments[$msg][] = Array('tmp'=>$tmp, 'file'=>$filename, 'type'=> $filetype); } @@ -267,4 +266,4 @@ class email_piping return string; } } -?> \ No newline at end of file +?> diff --git a/modules/core/import.inc.php b/modules/core/import.inc.php index 479993f4..494ace6e 100644 --- a/modules/core/import.inc.php +++ b/modules/core/import.inc.php @@ -62,7 +62,6 @@ class CORE_import } # open the file for parsing - require_once('includes/pear/Compat/Function/file_get_contents.php'); $data = file_get_contents($this->file); $rows = explode("\r\n", $data); @@ -142,7 +141,6 @@ class CORE_import { global $C_debug; $this->file = PATH_FILES.$VAR['file']; - require_once('includes/pear/Compat/Function/file_get_contents.php'); $data = file_get_contents($this->file); $rows = explode("\r\n", $data); @@ -242,7 +240,6 @@ class CORE_import { global $C_debug; $this->file = PATH_FILES.$VAR['file']; - require_once('includes/pear/Compat/Function/file_get_contents.php'); $data = file_get_contents($this->file); $rows = explode("\r\n", $data); @@ -342,4 +339,4 @@ class CORE_import } } } -?> \ No newline at end of file +?> diff --git a/modules/core/version.inc.php b/modules/core/version.inc.php index bcbcd7f2..ec95efb5 100644 --- a/modules/core/version.inc.php +++ b/modules/core/version.inc.php @@ -34,7 +34,6 @@ $fp = fopen('http://agileco.com/Version.txt', "r"); $abv = fread($fp, 255); fclose($fp); # get encoding version -require_once('includes/pear/Compat/Function/file_get_contents.php'); $tmp = file_get_contents(PATH_AGILE.'index.php'); if(eregi('ioncube', $tmp)) @@ -73,4 +72,4 @@ $smarty->assign('version',$ver); $smarty->assign('ab_version',$abv); $smarty->assign('encoding_version',$enc); $smarty->assign('modules',@$module_arr); -?> \ No newline at end of file +?> diff --git a/modules/invoice/invoice.inc.php b/modules/invoice/invoice.inc.php index c51a87c9..11da9971 100644 --- a/modules/invoice/invoice.inc.php +++ b/modules/invoice/invoice.inc.php @@ -704,7 +704,6 @@ class invoice # echo the custom tracking code to the screen: if(!is_file(PATH_FILES.'tracking.txt')) return false; - require_once('includes/pear/Compat/Function/file_get_contents.php'); $tracking = file_get_contents(PATH_FILES.'tracking.txt'); $tracking = ereg_replace('%%amount%%', "$total_amount", $tracking); $tracking = ereg_replace('%%invoice%%', $invoice, $tracking); @@ -4373,4 +4372,4 @@ class invoice $this->limit = $construct["construct"]["limit"]; } } -?> \ No newline at end of file +?> diff --git a/modules/module/module.inc.php b/modules/module/module.inc.php index 6f858f8e..b1ba5288 100644 --- a/modules/module/module.inc.php +++ b/modules/module/module.inc.php @@ -94,7 +94,6 @@ class module global $C_auth; if(!$C_auth->auth_method_by_name("module","upgrade")) return false; - require_once('includes/pear/Compat/Function/file_get_contents.php'); if(is_file(PATH_AGILE.'Version.txt')) $f['version']=trim(file_get_contents(PATH_AGILE.'Version.txt')); else @@ -114,9 +113,6 @@ class module ### Get remote hash file and check for inconsitancys in local files function remote_update($VAR) { - ## Load file_get_contents function for older versions: - require_once('includes/pear/Compat/Function/file_get_contents.php'); - $ver = $VAR['ver']; $mis=0; $md5=0; @@ -1521,4 +1517,4 @@ class module fclose($file); } } -?> \ No newline at end of file +?> diff --git a/modules/report/class.Level.php b/modules/report/class.Level.php index 2b072ec8..8fffa4da 100644 --- a/modules/report/class.Level.php +++ b/modules/report/class.Level.php @@ -744,7 +744,6 @@ class Level_Base { */ function addFieldCriteria($sql, $bIsAggregate = false, $field = '') { - require_once PATH_INCLUDES . 'pear/Compat/Function/stripos.php'; $this->lev_setting['SQL_criteria'] = $this->addToFilter($this->lev_setting['SQL_criteria'], $sql, $bIsAggregate); @@ -870,7 +869,6 @@ class Level_Base { function find_next_sql_keyword($sql,$offset=0) { - require_once PATH_INCLUDES . 'pear/Compat/Function/stripos.php'; $ret = false; if(is_string($sql) && is_numeric($offset)) { $arr = array( @@ -898,7 +896,6 @@ class Level_Base { function shuffleSQL($sql, $groupBy='') { - require_once PATH_INCLUDES . 'pear/Compat/Function/stripos.php'; if( ($p=stripos($sql,'HAVING')) !== false) { # found a having clause $leading = ''; @@ -1057,4 +1054,4 @@ class Level_Base { } } } -?> \ No newline at end of file +?> diff --git a/modules/ticket/ticket.inc.php b/modules/ticket/ticket.inc.php index 727c8862..c609c7e1 100644 --- a/modules/ticket/ticket.inc.php +++ b/modules/ticket/ticket.inc.php @@ -537,7 +537,6 @@ class ticket // insert any attachments if(!empty($arr['attach']) && is_array($arr['attach'])) { foreach($arr['attach'] as $attach) { - require_once('includes/pear/Compat/Function/file_get_contents.php'); @$data = file_get_contents($attach['tmp']); if(!empty($data)) { // get file size @@ -2708,4 +2707,4 @@ class ticket $this->limit = $construct["construct"]["limit"]; } } -?> \ No newline at end of file +?> diff --git a/test.php b/test.php index ec8057af..1718bffe 100644 --- a/test.php +++ b/test.php @@ -33,51 +33,6 @@ $php_info .= ob_get_contents(); ob_end_clean(); -############################################################### -### ENCODING ### - -if (eregi('Zend Optimizer', $php_info)) - $zend = true; -else - $zend = false; - - -if (function_exists("mmcache")) - $mmcache = true; -else - $mmcache = false; - -if (extension_loaded('ionCube Loader')) -{ - $ioncube = true; -} -else -{ - $ion = new ioncube_test; - $ioncube_arr = $ion->test(); - if($ioncube_arr[0] == true) - $ioncube = true; - else - $ioncube = false; -} - -if($ioncube || $mmcache || $zend ) -{ - $encoding['font'] = "FFFFFF"; - $encoding['back'] = "009900"; - $encoding['text'] = "OK:"; - if($ioncube) - $encoding['text'] .= " [Ioncube] "; - if ($mmcache) - $encoding['text'] .= " [MMCache] "; - if ($zend) - $encoding['text'] .= " [Zend] "; -} else { - $encoding['font'] = "FFFFFF"; - $encoding['back'] = "990000"; - $encoding['text'] = "Failed."; -} - ############################################################### # GD if (extension_loaded('gd')) @@ -121,7 +76,7 @@ if ($sslx == true) ############################################################### # PHP -if(phpversion() >= '4.3' ) +if(phpversion() >= '5.0' ) { $php['font'] = "FFFFFF"; $php['back'] = "009900"; @@ -129,7 +84,7 @@ if(phpversion() >= '4.3' ) } else { $php['font'] = "FFFFFF"; $php['back'] = "990000"; - $php['text'] = "Failed!"; + $php['text'] = "Failed! (PHP 5.0 or later is required)"; } ############################################################### @@ -142,7 +97,7 @@ if(is_callable("mysql_connect") && is_callable("mysql_get_client_info") && mysql } else { $mysql['font'] = "FFFFFF"; $mysql['back'] = "990000"; - $mysql['text'] = "Failed!"; + $mysql['text'] = "Failed! (MySQL 4.0 or later is required)"; } @@ -201,16 +156,6 @@ document.getElementById("help").src = "http://agilebill.com/Requirements#"+loca - "> - - - - ">
ENCODING - "> - - - -
MySQL "> @@ -289,226 +234,3 @@ document.getElementById("help").src = "http://agilebill.com/Requirements#"+loca

- - - - - -
| => |v\">)([^ <]*)(.* $thread_safe, - 'DEBUG_BUILD' => $debug_build, - 'PHP_INI' => $php_ini_path, - 'CGI_CLI' => $cgi_cli); -} - -function test() -{ - - $nl = ((php_sapi_name() == 'cli') ? "\n" : '
'); - $ok = true; - $already_installed = false; - $here = dirname(__FILE__); - - $sys_info = $this->ic_system_info(); - - if ($sys_info['THREAD_SAFE'] && !$sys_info['CGI_CLI']) { - $msg = "Your PHP install appears to have threading support and run-time Loading - is only possible on threaded web servers if using the CGI, FastCGI or - CLI interface.$nl${nl}To run encoded files please install the Loader in the php.ini file.$nl"; - $ok = false; - } - - if ($sys_info['DEBUG_BUILD']) { - $msg = "Your PHP installation appears to be built with debugging support - enabled and this is incompatible with ionCube Loaders.$nl${nl}Debugging support in PHP produces slower execution, is - not recommended for production builds and was probably a mistake.${nl}${nl}You should rebuild PHP without the --enable-debug option and if - you obtained your PHP install from an RPM then the producer of the - RPM should be notified so that it can be corrected.$nl"; - $ok = false; - } - - if (ini_get('safe_mode')) { - $msg = "PHP safe mode is enabled and run time loading will not be possible.$nl"; - $ok = false; - } - - - // If ok to try and find a Loader - if ($ok) { - - // Old style naming should be long gone now - $test_old_name = false; - - $_u = php_uname(); - $_os = substr($_u,0,strpos($_u,' ')); - $_os_key = strtolower(substr($_u,0,3)); - - $_php_version = phpversion(); - $_php_family = substr($_php_version,0,3); - - $_loader_sfix = (($_os_key == 'win') ? '.dll' : '.so'); - - $_ln_old="ioncube_loader.$_loader_sfix"; - $_ln_old_loc="/ioncube/$_ln_old"; - - $_ln_new="ioncube_loader_${_os_key}_${_php_family}${_loader_sfix}"; - $_ln_new_loc="/ioncube/$_ln_new"; - - #echo "${nl}Looking for Loader '$_ln_new'"; - if ($test_old_name) { - #echo " or '$_ln_old'"; - } - #echo $nl.$nl; - - $_extdir = ini_get('extension_dir'); - if ($_extdir == './') { - $_extdir = '.'; - } - - $_oid = $_id = realpath($_extdir); - - $_here = dirname(__FILE__); - if ((@$_id[1]) == ':') { - $_id = str_replace('\\','/',substr($_id,2)); - $_here = str_replace('\\','/',substr($_here,2)); - } - $_rd=str_repeat('/..',substr_count($_id,'/')).$_here.'/'; - - if ($_oid !== false) { - #echo "Extensions Dir: $_extdir ($_id)$nl"; - #echo "Relative Path: $_rd$nl"; - } else { - #echo "Extensions Dir: $_extdir (NOT FOUND)$nl$nl"; - - #echo "The directory set for the extension_dir entry in the - # php.ini file may not exist, and run time loading will not be possible. - # The system administrator should create the $_extdir directory, - # or install the Loader in the php.ini file.$nl"; - $ok = false; - } - - if ($ok) { - $_ln = ''; - $_i=strlen($_rd); - while($_i--) { - if($_rd[$_i]=='/') { - if ($test_old_name) { - // Try the old style Loader name - $_lp=substr($_rd,0,$_i).$_ln_old_loc; - $_fqlp=$_oid.$_lp; - if(@file_exists($_fqlp)) { - $msg = "Found Loader: $_fqlp$nl"; - return Array (true, $msg); - $_ln=$_lp; - break; - } - } - // Try the new style Loader name - $_lp=substr($_rd,0,$_i).$_ln_new_loc; - $_fqlp=$_oid.$_lp; - if(@file_exists($_fqlp)) { - $msg = "Found Loader: $_fqlp$nl"; - return Array (true, $msg); - $_ln=$_lp; - break; - } - } - } - - // - // If Loader not found, try the fallback of in the extensions directory - // - if (!$_ln) { - if ($test_old_name) { - if (@file_exists($_id.$_ln_old_loc)) { - $_ln = $_ln_old_loc; - } - } - if (@file_exists($_id.$_ln_new_loc)) { - $_ln = $_ln_new_loc; - } - - if ($_ln) { - $msg = "Found Loader $_ln in extensions directory.$nl"; - return Array (true, $msg); - } - } - - echo $nl; - - if ($_ln) { - #echo "Trying to install Loader - this may produce an error...$nl$nl"; - dl($_ln); - - if(extension_loaded('ionCube Loader')) { - $msg = "The Loader was successfully installed and encoded files should be able to - automatically install the Loader when needed. No changes to your php.ini file - are required to use encoded files on this system.${nl}"; - return Array (true, $msg); - } else { - $msg = "The Loader was not installed.$nl"; - return Array (false, $msg); - } - } else { - $msg = "Run-time loading should be possible on your system but no suitable Loader - was found.$nl$nl . The $_os Loader for PHP $_php_family releases is required.$nl"; - return Array (true, $msg); - } - } - } - return Array (false, $msg); -} -} -?> \ No newline at end of file