summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Larabel <michael@phx-laptop.(none)>2008-11-27 11:02:12 -0500
committerMichael Larabel <michael@phx-laptop.(none)>2008-11-27 11:02:12 -0500
commit41c3d53a7f3e5bd1f62164e927fd77ef92f3de59 (patch)
treed34e29c75e7e594a5d3cb9074d96602661f6a2d9
parenta60a7fe1ee47c0175d30184029fc3ddbfd52a81b (diff)
downloadphoronix-test-suite-upstream-41c3d53a7f3e5bd1f62164e927fd77ef92f3de59.tar.gz
phoronix-test-suite-upstream-41c3d53a7f3e5bd1f62164e927fd77ef92f3de59.tar.xz
phoronix-test-suite-upstream-41c3d53a7f3e5bd1f62164e927fd77ef92f3de59.zip
pts-core: Add support for dynamically loading objects from
sub-directories of pts-core/objects/ (Forgot to git-add to previous commit)
-rw-r--r--pts-core/objects/pts_Graph/pts_BarGraph.php120
-rw-r--r--pts-core/objects/pts_Graph/pts_CustomGraph.php72
-rw-r--r--pts-core/objects/pts_Graph/pts_Graph.php900
-rw-r--r--pts-core/objects/pts_Graph/pts_LineGraph.php146
-rw-r--r--pts-core/objects/pts_Graph/pts_MultiPassFailGraph.php127
-rw-r--r--pts-core/objects/pts_Graph/pts_PassFailGraph.php99
-rw-r--r--pts-core/objects/tandem_Xml/pts_test_tandem_XmlReader.php53
-rw-r--r--pts-core/objects/tandem_Xml/tandem_XmlReader.php309
-rw-r--r--pts-core/objects/tandem_Xml/tandem_XmlWriter.php199
9 files changed, 2025 insertions, 0 deletions
diff --git a/pts-core/objects/pts_Graph/pts_BarGraph.php b/pts-core/objects/pts_Graph/pts_BarGraph.php
new file mode 100644
index 0000000..b928b49
--- /dev/null
+++ b/pts-core/objects/pts_Graph/pts_BarGraph.php
@@ -0,0 +1,120 @@
+<?php
+
+/*
+ Phoronix Test Suite
+ URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
+ Copyright (C) 2008, Phoronix Media
+ Copyright (C) 2008, Michael Larabel
+ pts_BarGraph.php: The bar graph object that extends pts_Graph.php.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+class pts_BarGraph extends pts_CustomGraph
+{
+ var $identifier_width = -1;
+ var $minimum_identifier_font = 7;
+
+ public function __construct($title, $sub_title, $y_axis_title)
+ {
+ parent::__construct($title, $sub_title, $y_axis_title);
+ $this->graph_type = "BAR_GRAPH";
+ }
+ protected function render_graph_pre_init()
+ {
+ // Do some common work to this object
+ $identifier_count = count($this->graph_identifiers);
+ $this->identifier_width = floor(($this->graph_left_end - $this->graph_left_start) / $identifier_count);
+
+ $longest_string = $this->find_longest_string($this->graph_identifiers);
+ $width = $this->identifier_width - 8;
+ $this->graph_font_size_identifiers = $this->text_size_bounds($longest_string, $this->graph_font, $this->graph_font_size_identifiers, $this->minimum_identifier_font, $width);
+
+ if($this->graph_font_size_identifiers == $this->minimum_identifier_font)
+ {
+ $this->update_graph_dimensions($this->graph_attr_width, $this->graph_attr_height + $this->text_string_width($longest_string, $this->graph_font, 9));
+ }
+ }
+ protected function render_graph_identifiers()
+ {
+ $px_from_top_start = $this->graph_top_end - 5;
+ $px_from_top_end = $this->graph_top_end + 5;
+
+ for($i = 0; $i < count($this->graph_identifiers); $i++)
+ {
+ $px_bound_left = $this->graph_left_start + ($this->identifier_width * $i);
+ $px_bound_right = $px_bound_left + $this->identifier_width;
+
+ if($i == 0)
+ {
+ $this->draw_line($this->graph_image, $px_bound_left, $px_from_top_start, $px_bound_left, $px_from_top_end, $this->graph_color_notches);
+ }
+
+ if($i == (count($this->graph_identifiers) - 1) && $px_bound_right != $this->graph_left_end)
+ {
+ $px_bound_right = $this->graph_left_end;
+ }
+
+ $this->draw_line($this->graph_image, $px_bound_right, $px_from_top_start, $px_bound_right, $px_from_top_end, $this->graph_color_notches);
+
+ if($this->graph_font_size_identifiers == $this->minimum_identifier_font)
+ {
+ $this->write_text_left($this->graph_identifiers[$i], 9, $this->graph_color_headers, $px_bound_left + ceil($this->identifier_width / 2), $px_from_top_end, $px_bound_left + ceil($this->identifier_width / 2), $px_from_top_end, true);
+ }
+ else
+ {
+ $this->write_text_center($this->graph_identifiers[$i], $this->graph_font_size_identifiers, $this->graph_color_headers, $px_bound_left, $px_from_top_end - 5, $px_bound_right, $px_from_top_end - 5, false, true);
+ }
+ }
+ }
+ protected function render_graph_bars()
+ {
+ $bar_count = count($this->graph_data);
+ $bar_width = floor($this->identifier_width / $bar_count) - ($bar_count * 16);
+
+ for($i_o = 0; $i_o < $bar_count; $i_o++)
+ {
+ $paint_color = $this->next_paint_color();
+
+ for($i = 0; $i < count($this->graph_data[$i_o]); $i++)
+ {
+ $value = $this->trim_double($this->graph_data[$i_o][$i], 2);
+ $graph_size = round(($value / $this->graph_maximum_value) * ($this->graph_top_end - $this->graph_top_start));
+ $value_plot_top = $this->graph_top_end + 1 - $graph_size;
+
+ $px_bound_left = $this->graph_left_start + ($this->identifier_width * $i) + ($bar_width * $i_o) + 8;
+ $px_bound_right = $px_bound_left + $bar_width;
+
+ if($value_plot_top < 1)
+ {
+ $value_plot_top = 1;
+ }
+
+ $this->draw_rectangle_border($this->graph_image, $px_bound_left, $value_plot_top - 1, $px_bound_right, $this->graph_top_end - 1, $this->graph_color_body_light);
+ $this->draw_rectangle($this->graph_image, $px_bound_left + 1, $value_plot_top, $px_bound_right - 1, $this->graph_top_end - 1, $paint_color);
+
+ if($graph_size > 20)
+ {
+ $this->write_text_center($this->graph_data[$i_o][$i], $this->graph_font_size_bars, $this->graph_color_body_text, $px_bound_left, $value_plot_top + 3, $px_bound_right, $value_plot_top + 3);
+ }
+ }
+ }
+ }
+ protected function render_graph_result()
+ {
+ $this->render_graph_bars();
+ }
+}
+
+?>
diff --git a/pts-core/objects/pts_Graph/pts_CustomGraph.php b/pts-core/objects/pts_Graph/pts_CustomGraph.php
new file mode 100644
index 0000000..59432f2
--- /dev/null
+++ b/pts-core/objects/pts_Graph/pts_CustomGraph.php
@@ -0,0 +1,72 @@
+<?php
+
+/*
+ Phoronix Test Suite
+ URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
+ Copyright (C) 2008, Phoronix Media
+ Copyright (C) 2008, Michael Larabel
+ pts_CustomGraph.php: A pass-through extension extending pts_Graph that over-rides attributes with the PTS user configuration options.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+class pts_CustomGraph extends pts_Graph
+{
+ function __construct($Title, $SubTitle, $YTitle)
+ {
+ if(is_file(PTS_USER_DIR . "graph-config.xml"))
+ {
+ $file = file_get_contents(PTS_USER_DIR . "graph-config.xml");
+ }
+ else
+ {
+ $file = "";
+ }
+
+ $read_config = new tandem_XmlReader($file);
+
+ $this->graph_attr_width = pts_read_graph_config(P_GRAPH_SIZE_WIDTH, null, $read_config); // Graph width
+ $this->graph_attr_height = pts_read_graph_config(P_GRAPH_SIZE_HEIGHT, null, $read_config); // Graph height
+ $this->graph_attr_big_border = pts_read_graph_config(P_GRAPH_BORDER, null, $read_config) == "TRUE"; // Graph border
+
+ // Colors
+ $this->graph_color_notches = pts_read_graph_config(P_GRAPH_COLOR_NOTCHES, null, $read_config); // Color for notches
+ $this->graph_color_text = pts_read_graph_config(P_GRAPH_COLOR_TEXT, null, $read_config); // Color for text
+ $this->graph_color_border = pts_read_graph_config(P_GRAPH_COLOR_BORDER, null, $read_config); // Color for border (if used)
+ $this->graph_color_main_headers = pts_read_graph_config(P_GRAPH_COLOR_MAINHEADERS, null, $read_config); // Color of main text headers
+ $this->graph_color_headers = pts_read_graph_config(P_GRAPH_COLOR_HEADERS, null, $read_config); // Color of other headers
+ $this->graph_color_background = pts_read_graph_config(P_GRAPH_COLOR_BACKGROUND, null, $read_config); // Color of background
+ $this->graph_color_body = pts_read_graph_config(P_GRAPH_COLOR_BODY, null, $read_config); // Color of graph body
+ $this->graph_color_body_text = pts_read_graph_config(P_GRAPH_COLOR_BODYTEXT, null, $read_config); // Color of graph body text
+ $this->graph_color_body_light = pts_read_graph_config(P_GRAPH_COLOR_ALTERNATE, null, $read_config); // Color of the border around graph bars (if doing a bar graph)
+
+ $this->graph_color_paint = explode(", ", pts_read_graph_config(P_GRAPH_COLOR_PAINT, null, $read_config)); // Colors to use for the bars / lines, one color for each key
+
+ // Text
+ $this->graph_watermark_text = pts_read_graph_config(P_GRAPH_WATERMARK, null, $read_config); // watermark
+ $this->graph_font = pts_read_graph_config(P_GRAPH_FONT_TYPE, null, $read_config); // TTF file name
+ $this->graph_font_size_heading = pts_read_graph_config(P_GRAPH_FONT_SIZE_HEADERS, null, $read_config); // Font size of headings
+ $this->graph_font_size_bars = pts_read_graph_config(P_GRAPH_FONT_SIZE_TEXT, null, $read_config); // Font size for text on the bars/objects
+ $this->graph_font_size_identifiers = pts_read_graph_config(P_GRAPH_FONT_SIZE_IDENTIFIERS, null, $read_config); // Font size of identifiers
+ $this->graph_font_size_sub_heading = pts_read_graph_config(P_GRAPH_FONT_SIZE_SUBHEADERS, null, $read_config); // Font size of headers
+ $this->graph_font_size_axis_heading = pts_read_graph_config(P_GRAPH_FONT_SIZE_AXIS, null, $read_config); // Font size of axis headers
+
+ $this->graph_attr_big_border = pts_read_graph_config(P_GRAPH_RENDERBORDER, null, $read_config); // Border around graph or not
+ $this->graph_attr_marks = pts_read_graph_config(P_GRAPH_MARKCOUNT, null, $read_config); // Number of marks to make on vertical axis
+
+ parent::__construct($Title, $SubTitle, $YTitle);
+ }
+}
+
+?>
diff --git a/pts-core/objects/pts_Graph/pts_Graph.php b/pts-core/objects/pts_Graph/pts_Graph.php
new file mode 100644
index 0000000..5a280d9
--- /dev/null
+++ b/pts-core/objects/pts_Graph/pts_Graph.php
@@ -0,0 +1,900 @@
+<?php
+
+/*
+ Phoronix Test Suite
+ URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
+ Copyright (C) 2008, Phoronix Media
+ Copyright (C) 2008, Michael Larabel
+ pts_Graph.php: The core graph object that is used by the different graphing objects.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+class pts_Graph
+{
+ // Defaults
+ var $graph_attr_marks = 6; // Number of marks to make on vertical axis
+ var $graph_attr_width = 580; // Graph width
+ var $graph_attr_height = 300; // Graph height
+ var $graph_attr_big_border = false; // Border around graph or not
+
+ var $graph_left_start = 20; // Distance in px to start graph from left side
+ var $graph_left_end_opp = 10; // Distance in px to end graph from right side
+ var $graph_top_start = 60; // Distance in px to start graph from top side
+ var $graph_top_end_opp = 22; // Distance in px to end graph from bottom side
+
+ // Colors
+ var $graph_color_notches = "#000000"; // Color for notches
+ var $graph_color_text = "#000000"; // Color for text
+ var $graph_color_border = "#000000"; // Color for border (if used)
+ var $graph_color_main_headers = "#2b6b29"; // Color of main text headers
+ var $graph_color_headers = "#2b6b29"; // Color of other headers
+ var $graph_color_background = "#FFFFFF"; // Color of background
+ var $graph_color_body = "#8b8f7c"; // Color of graph body
+ var $graph_color_body_text = "#FFFFFF"; // Color of graph body text
+ var $graph_color_body_light = "#B0B59E"; // Color of the border around graph bars (if doing a bar graph)
+
+ var $graph_color_paint = array("#3B433A", "#BB2413", "#FF9933", "#006C00", "#5028CA"); // Colors to use for the bars / lines, one color for each key
+
+ // Text
+ var $graph_font = "Sans.ttf"; // TTF file name
+ var $graph_font_size_tick_mark = 10; // Tick mark size
+ var $graph_font_size_key = 9; // Size of height for keys
+ var $graph_font_size_heading = 18; // Font size of headings
+ var $graph_font_size_bars = 12; // Font size for text on the bars/objects
+ var $graph_font_size_identifiers = 11; // Font size of identifiers
+ var $graph_font_size_sub_heading = 12; // Font size of headers
+ var $graph_font_size_axis_heading = 11; // Font size of axis headers
+ var $graph_watermark_text = "PHORONIX-TEST-SUITE.COM"; // Text for watermark in upper right hand corner. If null, no watermark will display
+ var $graph_version = "";
+ var $graph_proportion = "";
+
+ // CHANGE DIRECTORY FOR TTF FONT LOCATION INSIDE __construct FUNCTION
+
+ // Not user-friendly changes below this line
+ var $graph_body_image = false;
+ var $graph_hide_identifiers = false;
+ var $graph_show_key = false;
+ var $graph_background_lines = false;
+ var $graph_type = "GRAPH";
+ var $graph_value_type = "NUMERICAL";
+ var $graph_image;
+ var $graph_maximum_value;
+
+ var $graph_output = null;
+ var $graph_renderer = "PNG";
+ var $graph_data = array();
+ var $graph_data_title = array();
+ var $graph_color_paint_index = -1;
+ var $graph_identifiers;
+ var $graph_title;
+ var $graph_sub_title;
+ var $graph_y_title;
+ var $graph_y_title_hide = false;
+ var $graph_top_end;
+ var $graph_left_end;
+
+ var $graph_internal_identifiers = array();
+
+ public function __construct($title, $sub_title, $y_axis_title)
+ {
+ $this->graph_title = $title;
+ $this->graph_sub_title = $sub_title;
+ $this->graph_y_title = $y_axis_title;
+
+ $this->update_graph_dimensions(-1, -1, true);
+
+ // Directory for TTF Fonts
+ if(defined("FONT_DIR"))
+ {
+ putenv("GDFONTPATH=" . FONT_DIR);
+ }
+ else if(($font_env = getenv("FONT_DIR")) != false)
+ {
+ putenv("GDFONTPATH=" . $font_env);
+ }
+ else
+ {
+ putenv("GDFONTPATH=" . getcwd());
+ }
+ }
+ public function setRenderer($renderer)
+ {
+ if($renderer == "SVG")
+ {
+ $this->graph_renderer = "SVG";
+ $this->graph_left_start += 10;
+ }
+ else
+ {
+ $this->graph_renderer = "PNG";
+ }
+ }
+ public function getRenderer()
+ {
+ return $this->graph_renderer;
+ }
+
+ //
+ // Load Functions
+ //
+
+ public function loadGraphIdentifiers($data_array)
+ {
+ $this->graph_identifiers = $data_array;
+ }
+ public function hideGraphIdentifiers()
+ {
+ $this->graph_hide_identifiers = true;
+ }
+ public function loadGraphVersion($data)
+ {
+ if(!empty($data))
+ {
+ $this->graph_version = "Phoronix Test Suite " . $data;
+ }
+ }
+ public function loadGraphProportion($data)
+ {
+ if($data == "LIB")
+ {
+ $this->graph_proportion = "Less Is Better";
+ }
+ //else if($data == "HIB")
+ // $this->graph_proportion = "More Is Better";
+ }
+ public function loadGraphData($data_array)
+ {
+ loadGraphValues($data_array);
+ }
+ public function loadGraphValues($data_array, $data_title = null)
+ {
+ for($i = 0; $i < count($data_array); $i++)
+ {
+ if(is_float($data_array[$i]))
+ {
+ $data_array[$i] = $this->trim_double($data_array[$i], 2);
+ }
+ }
+
+ array_push($this->graph_data, $data_array);
+
+ if(!empty($data_title))
+ {
+ array_push($this->graph_data_title, $data_title);
+ }
+ }
+ public function setGraphBackgroundPNG($file)
+ {
+ $img = $this->read_png_image($file);
+
+ if($img != false)
+ {
+ $this->graph_body_image = $img;
+ }
+ }
+ public function renderGraph()
+ {
+ $this->graph_maximum_value = $this->maximum_graph_value();
+
+ // Make room for tick markings, left hand side
+ if($this->graph_value_type == "NUMERICAL")
+ {
+ $this->graph_left_start += $this->text_string_width($this->graph_maximum_value, $this->graph_font, $this->graph_font_size_tick_mark) + 2;
+ }
+
+ if($this->graph_hide_identifiers == true)
+ {
+ $this->graph_top_end += $this->graph_top_end_opp / 2;
+ }
+
+ // Do the actual work
+ $this->render_graph_pre_init();
+ $this->render_graph_init();
+ $this->render_graph_base();
+
+ if(!$this->graph_hide_identifiers)
+ {
+ $this->render_graph_identifiers();
+ }
+
+ if($this->graph_value_type == "NUMERICAL")
+ {
+ $this->render_graph_value_ticks();
+ }
+
+ $this->render_graph_key();
+ $this->render_graph_result();
+ $this->render_graph_watermark();
+ $this->return_graph_image();
+ }
+ public function addInternalIdentifier($identifier, $value)
+ {
+ $this->graph_internal_identifiers[$identifier] = $value;
+ }
+ public function saveGraphToFile($file)
+ {
+ $this->graph_output = $file;
+ }
+
+ //
+ // Misc Functions
+ //
+
+ protected function next_paint_color()
+ {
+ if($this->graph_color_paint_index + 1 < count($this->graph_color_paint))
+ {
+ $this->graph_color_paint_index += 1;
+ }
+ else
+ {
+ $this->graph_color_paint_index = 0;
+ }
+
+ return $this->graph_color_paint[$this->graph_color_paint_index];
+ }
+ protected function reset_paint_index()
+ {
+ $this->graph_color_paint_index = -1;
+ }
+ protected function maximum_graph_value()
+ {
+ $maximum = $this->graph_attr_marks;
+
+ foreach($this->graph_data as $graph_set)
+ {
+ foreach($graph_set as $set_item)
+ {
+ if((is_numeric($set_item) && $set_item > $maximum) || (!is_numeric($set_item) && strlen($set_item) > strlen($maximum)))
+ {
+ $maximum = $set_item;
+ }
+ }
+ }
+
+ if(is_numeric($maximum))
+ {
+ $maximum = (floor(round($maximum * 1.35) / $this->graph_attr_marks) + 1) * $this->graph_attr_marks;
+ }
+
+ return $maximum;
+ }
+ protected function text_string_width($string, $font, $size)
+ {
+ $dimensions = $this->text_string_dimensions($string, $font, $size);
+ return $dimensions[0];
+ }
+ protected function text_string_height($string, $font, $size)
+ {
+ $dimensions = $this->text_string_dimensions($string, $font, $size);
+ return $dimensions[1];
+ }
+ protected function text_size_bounds($string, $font, $font_size, $minimum_font_size, $bound_width, $bound_height = -1)
+ {
+ while($font_size > $minimum_font_size && ($this->text_string_width($string, $font, $font_size) > $bound_width || ($bound_height > 0 && $this->text_string_height($string, $font, $font_size) > $bound_height)))
+ {
+ $font_size -= 0.5;
+ }
+
+ return $font_size;
+ }
+ protected function find_longest_string($string_r)
+ {
+ $longest_string = "";
+ $longest_string_length = 0;
+
+ foreach($string_r as $one_string)
+ {
+ if(($new_length = strlen($one_string)) > $longest_string_length)
+ {
+ $longest_string = $one_string;
+ $longest_string_length = $new_length;
+ }
+ }
+
+ return $longest_string;
+ }
+ protected function update_graph_dimensions($width = -1, $height = -1, $recalculate_offsets = false)
+ {
+ // Allow render area to be increased, but not decreased
+ if($width > $this->graph_attr_width)
+ {
+ $this->graph_attr_width = $width;
+ }
+ if($height > $this->graph_attr_height)
+ {
+ $this->graph_attr_height = $height;
+ }
+
+ if($recalculate_offsets)
+ {
+ $this->graph_top_end = $this->graph_attr_height - $this->graph_top_end_opp;
+ $this->graph_left_end = $this->graph_attr_width - $this->graph_left_end_opp;
+ }
+ }
+
+ //
+ // Render Functions
+ //
+
+ protected function render_graph_pre_init()
+ {
+ return;
+ }
+ protected function render_graph_init()
+ {
+ $this->update_graph_dimensions();
+ $this->graph_image = $this->init_blank_image($this->graph_attr_width, $this->graph_attr_height);
+
+ // Initalize Colors
+
+ $this->graph_color_notches = $this->convert_hex_to_type($this->graph_color_notches);
+ $this->graph_color_text = $this->convert_hex_to_type($this->graph_color_text);
+ $this->graph_color_border = $this->convert_hex_to_type($this->graph_color_border);
+ $this->graph_color_main_headers = $this->convert_hex_to_type($this->graph_color_main_headers);
+ $this->graph_color_headers = $this->convert_hex_to_type($this->graph_color_headers);
+ $this->graph_color_background = $this->convert_hex_to_type($this->graph_color_background);
+ $this->graph_color_body = $this->convert_hex_to_type($this->graph_color_body);
+ $this->graph_color_body_text = $this->convert_hex_to_type($this->graph_color_body_text);
+ $this->graph_color_body_light = $this->convert_hex_to_type($this->graph_color_body_light);
+
+ for($i = 0; $i < count($this->graph_color_paint); $i++)
+ {
+ $this->graph_color_paint[$i] = $this->convert_hex_to_type($this->graph_color_paint[$i]);
+ }
+
+ // Background Color
+ $this->draw_rectangle($this->graph_image, 0, 0, $this->graph_attr_width, $this->graph_attr_height, $this->graph_color_background);
+
+ if($this->graph_attr_big_border == true)
+ {
+ $this->draw_rectangle_border($this->graph_image, 0, 0, $this->graph_attr_width - 1, $this->graph_attr_height - 1, $this->graph_color_border);
+ }
+ }
+ protected function render_graph_base()
+ {
+ if(count($this->graph_data_title) > 1 || $this->graph_show_key == true)
+ {
+ $num_key_lines = ceil(count($this->graph_data_title) / 4);
+ $this->graph_top_start = $this->graph_top_start + 8 + ($num_key_lines * 11);
+ }
+
+ $this->draw_rectangle($this->graph_image, $this->graph_left_start, $this->graph_top_start, $this->graph_left_end, $this->graph_top_end, $this->graph_color_body);
+ $this->draw_rectangle_border($this->graph_image, $this->graph_left_start, $this->graph_top_start, $this->graph_left_end, $this->graph_top_end, $this->graph_color_notches);
+
+ if($this->graph_body_image != false)
+ {
+ $this->image_copy_merge($this->graph_image, $this->graph_body_image, $this->graph_left_start + (($this->graph_left_end - $this->graph_left_start) / 2) - imagesx($this->graph_body_image) / 2, $this->graph_top_start + (($this->graph_top_end - $this->graph_top_start) / 2) - imagesy($this->graph_body_image) / 2);
+ }
+
+ // Text
+ $this->write_text_right($this->graph_version, 7, $this->graph_color_body_light, $this->graph_left_end, $this->graph_top_start - 9, $this->graph_left_end, $this->graph_top_start - 9);
+ $this->write_text_center($this->graph_title, $this->graph_font_size_heading, $this->graph_color_main_headers, $this->graph_left_start, 4, $this->graph_left_end, 4);
+ $this->write_text_center($this->graph_sub_title, $this->graph_font_size_sub_heading, $this->graph_color_main_headers, $this->graph_left_start, 26, $this->graph_left_end, 26, false, true);
+
+ if(!empty($this->graph_y_title) && !$this->graph_y_title_hide)
+ {
+ $str = $this->graph_y_title;
+
+ if(!empty($this->graph_proportion))
+ {
+ if(!empty($str))
+ {
+ $str .= ", ";
+ }
+
+ $str .= $this->graph_proportion;
+ }
+
+ $this->write_text_left($str, 7, $this->graph_color_main_headers, $this->graph_left_start, $this->graph_top_start - 9, $this->graph_left_start, $this->graph_top_start - 9);
+ }
+ }
+ protected function render_graph_value_ticks()
+ {
+ $tick_width = ($this->graph_top_end - $this->graph_top_start) / $this->graph_attr_marks;
+ $px_from_left_start = $this->graph_left_start - 5;
+ $px_from_left_end = $this->graph_left_start + 5;
+
+ $display_value = 0;
+
+ for($i = 0; $i < $this->graph_attr_marks; $i++)
+ {
+ $px_from_top = $this->graph_top_end - ($tick_width * $i);
+
+ $this->draw_line($this->graph_image, $px_from_left_start, $px_from_top, $px_from_left_end, $px_from_top, $this->graph_color_notches);
+
+ $this->write_text_right($display_value, $this->graph_font_size_tick_mark, $this->graph_color_text, $px_from_left_start - 1, $px_from_top - 2, $px_from_left_start - 1, $px_from_top - 2);
+
+ if($i != 0 && $this->graph_background_lines == true)
+ {
+ $line_width = 6;
+ for($y = $px_from_left_end + $line_width; $y < $this->graph_left_end; $y += ($line_width * 2))
+ {
+ if($y + $line_width < $this->graph_left_end)
+ {
+ $this->draw_line($this->graph_image, $y, $px_from_top, $y += $line_width, $px_from_top, $this->graph_color_body_light);
+ }
+ else
+ {
+ $this->draw_line($this->graph_image, $y, $px_from_top, $y += ($this->graph_left_end - $y) - 1, $px_from_top, $this->graph_color_body_light);
+ }
+ }
+ }
+
+ $display_value += $this->trim_double($this->graph_maximum_value / $this->graph_attr_marks, 2);
+ }
+ }
+ protected function render_graph_identifiers()
+ {
+ return;
+ }
+ protected function render_graph_result()
+ {
+ return;
+ }
+ protected function render_graph_key()
+ {
+ if(count($this->graph_data_title) < 2 && $this->graph_show_key == false)
+ {
+ return;
+ }
+
+ $key_counter = 0;
+ $component_y = $this->graph_top_start - 20;
+ $this->reset_paint_index();
+
+ for($i = 0; $i < count($this->graph_data_title); $i++)
+ {
+ if(!empty($this->graph_data_title))
+ {
+ $this_color = $this->next_paint_color();
+ $key_counter += 1;
+ $key_offset = $key_counter % 4;
+
+ $component_x = $this->graph_left_start + 15 + (($this->graph_left_end - $this->graph_left_start) / 4) * $key_offset;
+
+ $this->write_text_left($this->graph_data_title[$i], $this->graph_font_size_key, $this_color, $component_x, $component_y, $component_x, $component_y);
+
+ $this->draw_rectangle($this->graph_image, $component_x - 13, $component_y - 5, $component_x - 3, $component_y + 5, $this_color);
+ $this->draw_rectangle_border($this->graph_image, $component_x - 13, $component_y - 5, $component_x - 3, $component_y + 5, $this->graph_color_notches);
+
+ if($key_counter % 4 == 0)
+ {
+ $component_y -= 12;
+ }
+ }
+ }
+ $this->reset_paint_index();
+ }
+ protected function render_graph_watermark()
+ {
+ if(!empty($this->graph_watermark_text))
+ {
+ $this->write_text_right($this->graph_watermark_text, 10, $this->graph_color_text, $this->graph_left_end - 2, $this->graph_top_start + 8, $this->graph_left_end - 2, $this->graph_top_start + 8);
+ }
+ }
+ protected function return_graph_image()
+ {
+ $this->render_image($this->graph_image, $this->graph_output, 5);
+ $this->deinit_image($this->graph_image);
+ }
+ protected function trim_double($double, $accuracy = 2)
+ {
+ // Set precision for a variable's points after the decimal spot
+ $return = explode(".", $double);
+
+ if(count($return) == 1)
+ {
+ $return[1] = "00";
+ }
+
+ if(count($return) == 2 && $accuracy > 0)
+ {
+ $strlen = strlen($return[1]);
+
+ if($strlen > $accuracy)
+ {
+ $return[1] = substr($return[1], 0, $accuracy);
+ }
+ else if($strlen < $accuracy)
+ {
+ for($i = $strlen; $i < $accuracy; $i++)
+ {
+ $return[1] .= '0';
+ }
+ }
+
+ $return = $return[0] . "." . $return[1];
+ }
+ else
+ {
+ $return = $return[0];
+ }
+
+ return $return;
+ }
+
+
+ //
+ // Renderer-specific Functions
+ //
+
+ protected function init_blank_image($width, $height)
+ {
+ if($this->graph_renderer == "PNG")
+ {
+ $img = imagecreate($width, $height);
+
+ imageinterlace($img, true);
+
+ if(function_exists("imageantialias"))
+ {
+ imageantialias($img, true);
+ }
+ }
+ else if($this->graph_renderer == "SVG")
+ {
+ $img = "<?xml version=\"1.0\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n";
+
+ foreach($this->graph_internal_identifiers as $key => $value)
+ {
+ $img .= "<!-- " . $key . ": " . $value . " -->\n";
+ }
+
+ $img .= "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewbox=\"0 0 " . $width . " " . $height . "\" width=\"" . $width . "\" height=\"" . $height . "\">\n\n";
+ }
+
+ return $img;
+ }
+ protected function render_image(&$img_object, $output_file = null, $quality = 0)
+ {
+ if($this->graph_renderer == "PNG")
+ {
+ imagepng($img_object, $output_file, $quality);
+ }
+ else if($this->graph_renderer == "SVG")
+ {
+ $img_object .= "\n\n</svg>";
+
+ if($output_file != null)
+ {
+ @file_put_contents($output_file, $img_object);
+ }
+ }
+ }
+ protected function read_png_image($file)
+ {
+ if($this->graph_renderer == "PNG")
+ {
+ $img = @imagecreatefrompng($file);
+ }
+ else
+ {
+ $img = null;
+ }
+
+ return $img;
+ }
+ protected function deinit_image(&$img_object)
+ {
+ if($this->graph_renderer == "PNG")
+ {
+ imagedestroy($img_object);
+ }
+ else if($this->graph_renderer == "SVG")
+ {
+ $img_object = null;
+ }
+ }
+ protected function convert_hex_to_type($hex)
+ {
+ if($this->graph_renderer == "PNG")
+ {
+ $color = imagecolorallocate($this->graph_image, hexdec(substr($hex, 1, 2)), hexdec(substr($hex, 3, 2)), hexdec(substr($hex, 5, 2)));
+ }
+ else if($this->graph_renderer == "SVG")
+ {
+ $color = $hex;
+ }
+
+ return $color;
+ }
+ protected function write_text_left($text_string, $font_size, $font_color, $bound_x1, $bound_y1, $bound_x2, $bound_y2, $rotate = false)
+ {
+ if(empty($text_string))
+ {
+ return;
+ }
+
+ if($this->graph_renderer == "PNG")
+ {
+ $ttf_dimensions = $this->text_string_dimensions($text_string, $this->graph_font, $font_size);
+ $ttf_width = $ttf_dimensions[0];
+ $ttf_height = $ttf_dimensions[1];
+
+ if($rotate == false)
+ {
+ $text_x = $bound_x1;
+ $text_y = $bound_y1 + round($ttf_height / 2);
+ $rotation = 0;
+ }
+ else
+ {
+ $text_x = $bound_x1 - round($ttf_height / 4);
+ $text_y = $bound_y1 + round($ttf_height / 2);
+ $rotation = 270;
+ }
+ imagettftext($this->graph_image, $font_size, $rotation, $text_x, $text_y, $font_color, $this->graph_font, $text_string);
+ }
+ else if($this->graph_renderer == "SVG")
+ {
+ $ttf_dimensions = $this->text_string_dimensions($text_string, $this->graph_font, $font_size);
+ $ttf_width = $ttf_dimensions[0];
+ $ttf_height = $ttf_dimensions[1];
+
+ if($rotate == false)
+ {
+ $text_x = $bound_x1;
+ $text_y = $bound_y1 + round($ttf_height / 2);
+ $rotation = 0;
+ }
+ else
+ {
+ $text_x = $bound_x1 - round($ttf_height / 4);
+ $text_y = $bound_y1 + round($ttf_height / 2);
+ $rotation = 270;
+ }
+ $this->write_svg_text($this->graph_image, $font_size, $rotation, $text_x, $text_y, $font_color, $this->graph_font, $text_string, "LEFT");
+ }
+ }
+ protected function write_text_right($text_string, $font_size, $font_color, $bound_x1, $bound_y1, $bound_x2, $bound_y2, $rotate_text = false)
+ {
+ if(empty($text_string))
+ {
+ return;
+ }
+
+ if($this->graph_renderer == "PNG")
+ {
+ $ttf_dimensions = $this->text_string_dimensions($text_string, $this->graph_font, $font_size);
+ $ttf_width = $ttf_dimensions[0];
+ $ttf_height = $ttf_dimensions[1];
+
+ if($rotate_text == false)
+ {
+ $rotation = 0;
+ }
+ else
+ {
+ $rotation = 90;
+ }
+
+ $text_x = $bound_x2 - $ttf_width;
+ $text_y = $bound_y1 + round($ttf_height / 2);
+
+ imagettftext($this->graph_image, $font_size, $rotation, $text_x, $text_y, $font_color, $this->graph_font, $text_string);
+ }
+ else if($this->graph_renderer == "SVG")
+ {
+ $ttf_dimensions = $this->text_string_dimensions($text_string, $this->graph_font, $font_size);
+ $ttf_width = $ttf_dimensions[0];
+ $ttf_height = $ttf_dimensions[1];
+
+ $bound_x1 -= 2;
+ $bound_x2 -= 2;
+
+ if($rotate_text == false)
+ {
+ $rotation = 0;
+ }
+ else
+ {
+ $rotation = 90;
+ }
+
+ $text_x = $bound_x2 - $ttf_width;
+ $text_y = $bound_y1 + round($ttf_height / 2);
+
+ $this->write_svg_text($this->graph_image, $font_size, $rotation, $text_x, $text_y, $font_color, $this->graph_font, $text_string, "RIGHT");
+ }
+ }
+ protected function write_text_center($text_string, $font_size, $font_color, $bound_x1, $bound_y1, $bound_x2, $bound_y2, $rotate_text = false, $big_type = false)
+ {
+ if(empty($text_string))
+ {
+ return;
+ }
+
+ if($this->graph_renderer == "PNG")
+ {
+ if($bound_x1 != $bound_x2)
+ {
+ while($this->text_string_width($this->trim_double($text_string, 2), $this->graph_font, $font_size) > abs($bound_x2 - $bound_x1 - 3))
+ {
+ $font_size -= 0.5;
+ }
+ }
+
+ $ttf_dimensions = $this->text_string_dimensions(strtoupper($text_string), $this->graph_font, $font_size, $big_type);
+ $ttf_height = $ttf_dimensions[1];
+
+ $ttf_dimensions = $this->text_string_dimensions($text_string, $this->graph_font, $font_size, $big_type);
+ $ttf_width = $ttf_dimensions[0];
+
+ if($rotate_text == false)
+ {
+ $rotation = 0;
+ $text_x = (($bound_x2 - $bound_x1) / 2) + $bound_x1 - round($ttf_width / 2);
+ $text_y = $bound_y1 + $ttf_height;
+ }
+ else
+ {
+ $rotation = 90;
+ $text_x = $bound_x1 + $ttf_height;
+ $text_y = (($bound_y2 - $bound_y1) / 2) + $bound_y1 + round($ttf_width / 2);
+ }
+
+ imagettftext($this->graph_image, $font_size, $rotation, $text_x, $text_y, $font_color, $this->graph_font, $text_string);
+ }
+ else if($this->graph_renderer == "SVG")
+ {
+ // $font_size = $this->graph_font_size_bars;
+ // while($this->text_string_width($this->trim_double($this->graph_maximum_value, 3), $this->graph_font, $font_size) > ($bar_width - 6))
+ // $font_size -= 0.5;
+
+ $ttf_dimensions = $this->text_string_dimensions(strtoupper($text_string), $this->graph_font, $font_size, $big_type);
+ $ttf_height = $ttf_dimensions[1];
+
+ $ttf_dimensions = $this->text_string_dimensions($text_string, $this->graph_font, $font_size, $big_type);
+ $ttf_width = $ttf_dimensions[0];
+
+ if($rotate_text == false)
+ {
+ $rotation = 0;
+ $text_x = (($bound_x2 - $bound_x1) / 2) + $bound_x1 - round($ttf_width / 2);
+ $text_y = $bound_y1 + $ttf_height;
+ }
+ else
+ {
+ $rotation = 90;
+ $text_x = $bound_x1 + $ttf_height;
+ $text_y = (($bound_y2 - $bound_y1) / 2) + $bound_y1 + round($ttf_width / 2);
+ }
+
+ $this->write_svg_text($this->graph_image, $font_size, $rotation, $text_x, $text_y, $font_color, $this->graph_font, $text_string, "CENTER");
+ }
+ }
+ protected function write_svg_text(&$img_object, $font_size, $rotation, $text_x, $text_y, $color, $font, $string, $orientation = "LEFT")
+ {
+ $font_size += 1.5;
+ $baseline = "middle";
+
+ if($rotation != 0)
+ {
+ $text_y = (0 - ($text_y / 2));
+ $text_x = $text_y + 5;
+ }
+
+ switch($orientation)
+ {
+ case "CENTER":
+ $text_anchor = "middle";
+ $baseline = "text-before-edge";
+ break;
+ case "RIGHT":
+ $text_anchor = "end";
+ break;
+ case "LEFT":
+ default:
+ $text_anchor = "start";
+ break;
+ }
+
+ // TODO: Implement $font through style="font-family: $font;"
+ $img_object .= "<text x=\"" . round($text_x) . "\" y=\"" . round($text_y) . "\" fill=\"" . $color . "\" transform=\"rotate(" . (360 - $rotation) . ", " . $rotation . ", 0)\" font-size=\"" . $font_size . "\" text-anchor=\"" . $text_anchor . "\" dominant-baseline=\"" . $baseline . "\">" . $string . "</text>\n";
+ }
+ protected function draw_rectangle(&$img_object, $x1, $y1, $width, $height, $background_color)
+ {
+ if($this->graph_renderer == "PNG")
+ {
+ imagefilledrectangle($img_object, $x1, $y1, $width, $height, $background_color);
+ }
+ else if($this->graph_renderer == "SVG")
+ {
+ $width = $width - $x1;
+ $height = $height - $y1;
+
+ if($width < 0)
+ {
+ $x1 += $width;
+ }
+ if($height < 0)
+ {
+ $y1 += $height;
+ }
+
+ $img_object .= "<rect x=\"" . round($x1) . "\" y=\"" . round($y1) . "\" width=\"" . abs(round($width)) . "\" height=\"" . abs(round($height)) . "\" fill=\"" . $background_color . "\" />\n";
+ }
+ }
+ protected function draw_rectangle_border(&$img_object, $x1, $y1, $width, $height, $color)
+ {
+ if($this->graph_renderer == "PNG")
+ {
+ imagerectangle($img_object, $x1, $y1, $width, $height, $color);
+ }
+ else if($this->graph_renderer == "SVG")
+ {
+ $img_object .= "<rect x=\"" . round($x1) . "\" y=\"" . round($y1) . "\" width=\"" . round($width - $x1) . "\" height=\"" . round($height - $y1) . "\" fill=\"transparent\" stroke=\"" . $color . "\" stroke-width=\"1px\" />\n";
+ }
+ }
+ protected function draw_line(&$img_object, $left_start, $top_start, $from_left, $from_top, $color, $line_width = 1)
+ {
+ if($this->graph_renderer == "PNG")
+ {
+ for($i = 0; $i < $line_width; $i++)
+ {
+ imageline($img_object, $left_start, $top_start + $i, $from_left, $from_top + $i, $color);
+ }
+ }
+ else if($this->graph_renderer == "SVG")
+ {
+ for($i = 0; $i < $line_width; $i++)
+ {
+ $img_object .= "<line x1=\"" . round($left_start) . "\" y1=\"" . round($top_start + $i) . "\" x2=\"" . round($from_left) . "\" y2=\"" . round($from_top + $i) . "\" stroke=\"" . $color . "\" stroke-width=\"1px\" />\n";
+ }
+ }
+ }
+ protected function image_copy_merge(&$img_object, $source_img_object, $to_x, $to_y, $source_x = 0, $source_y = 0, $width = -1, $height = -1)
+ {
+ if($this->graph_renderer == "PNG")
+ {
+ if($width == -1)
+ {
+ $width = imagesx($source_img_object);
+ }
+ if($height == -1)
+ {
+ $height = imagesy($source_img_object);
+ }
+
+ imagecopy($img_object, $source_img_object, $to_x, $to_y, $source_x, $source_y, $width, $height);
+ }
+ }
+ protected function text_string_dimensions($string, $font, $size, $Big = false)
+ {
+ if($this->graph_renderer == "PNG" && function_exists("imagettfbbox"))
+ {
+ $box_array = imagettfbbox($size, 0, $font, $string);
+ $box_width = $box_array[4] - $box_array[6];
+
+ if($Big)
+ {
+ $box_array = imagettfbbox($size, 0, $font, "AZ@![]()@|_");
+ }
+ $box_height = $box_array[1] - $box_array[7];
+ }
+ else if($this->graph_renderer == "SVG")
+ {
+ // TODO: This needs to be implemented
+ $box_height = 0;
+ $box_width = 0;
+ }
+
+ // Width x Height
+ return array($box_width, $box_height);
+ }
+}
+
+?>
diff --git a/pts-core/objects/pts_Graph/pts_LineGraph.php b/pts-core/objects/pts_Graph/pts_LineGraph.php
new file mode 100644
index 0000000..140b693
--- /dev/null
+++ b/pts-core/objects/pts_Graph/pts_LineGraph.php
@@ -0,0 +1,146 @@
+<?php
+
+/*
+ Phoronix Test Suite
+ URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
+ Copyright (C) 2008, Phoronix Media
+ Copyright (C) 2008, Michael Larabel
+ pts_LineGraph.php: The line graph object that extends pts_Graph.php.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+class pts_LineGraph extends pts_CustomGraph
+{
+ var $identifier_width = -1;
+ var $minimum_identifier_font = 7;
+
+ public function __construct($title, $sub_title, $y_axis_title)
+ {
+ parent::__construct($title, $sub_title, $y_axis_title);
+ $this->graph_type = "LINE_GRAPH";
+ $this->graph_show_key = true;
+ $this->graph_background_lines = true;
+ }
+ protected function render_graph_pre_init()
+ {
+ // Do some common work to this object
+ $identifier_count = count($this->graph_identifiers) + 1;
+ $this->identifier_width = ($this->graph_left_end - $this->graph_left_start) / $identifier_count;
+
+ $longest_string = $this->find_longest_string($this->graph_identifiers);
+ $width = $this->identifier_width - 2;
+ $this->graph_font_size_identifiers = $this->text_size_bounds($longest_string, $this->graph_font, $this->graph_font_size_identifiers, $this->minimum_identifier_font, $width);
+
+ if($this->graph_font_size_identifiers == $this->minimum_identifier_font)
+ {
+ $this->update_graph_dimensions($this->graph_attr_width, $this->graph_attr_height + $this->text_string_width($longest_string, $this->graph_font, 9));
+ }
+ }
+ protected function render_graph_identifiers()
+ {
+ $px_from_top_start = $this->graph_top_end - 5;
+ $px_from_top_end = $this->graph_top_end + 5;
+
+ for($i = 0; $i < count($this->graph_identifiers); $i++)
+ {
+ $px_from_left = $this->graph_left_start + ($this->identifier_width * ($i + 1));
+
+ $this->draw_line($this->graph_image, $px_from_left, $px_from_top_start, $px_from_left, $px_from_top_end, $this->graph_color_notches);
+
+ if($this->graph_font_size_identifiers == $this->minimum_identifier_font)
+ {
+ $this->write_text_left($this->graph_identifiers[$i], 9, $this->graph_color_headers, $px_from_left, $px_from_top_end + 2, $px_from_left, $px_from_top_end + 2, true);
+ }
+ else
+ {
+ $this->write_text_center($this->graph_identifiers[$i], $this->graph_font_size_identifiers, $this->graph_color_headers, $px_from_left, $px_from_top_end + 2, $px_from_left, $px_from_top_end + 2);
+ }
+ }
+ }
+ protected function renderGraphLines()
+ {
+ for($i_o = 0; $i_o < count($this->graph_data); $i_o++)
+ {
+ $previous_placement = -1;
+ $previous_offset = -1;
+ $paint_color = $this->next_paint_color();
+
+ $point_counter = count($this->graph_data[$i_o]);
+ for($i = 0; $i < $point_counter; $i++)
+ {
+ $value = $this->graph_data[$i_o][$i];
+ $value_plot_top = $this->graph_top_end + 1 - round(($value / $this->graph_maximum_value) * ($this->graph_top_end - $this->graph_top_start));
+ $px_from_left = $this->graph_left_start + ($this->identifier_width * ($i + 1));
+
+ if($px_from_left > $this->graph_left_end)
+ {
+ $px_from_left = $this->graph_left_end - 1;
+ }
+
+ if($value_plot_top >= $this->graph_top_end)
+ {
+ $value_plot_top = $this->graph_top_end - 1;
+ }
+
+ if($previous_placement != -1 && $previous_offset != -1)
+ {
+ $this->draw_line($this->graph_image, $previous_offset, $previous_placement, $px_from_left, $value_plot_top, $paint_color, 2);
+ }
+
+ if($i == 0)
+ {
+ $this->draw_line($this->graph_image, $this->graph_left_start + 1, $value_plot_top, $px_from_left, $value_plot_top, $paint_color, 2);
+ }
+ else if($i == ($point_counter - 1))
+ {
+ $this->draw_line($this->graph_image, $px_from_left, $value_plot_top, $this->graph_left_end - 1, $value_plot_top, $paint_color, 2);
+ }
+
+ $previous_placement = $value_plot_top;
+ $previous_offset = $px_from_left;
+ }
+
+ if($point_counter < 10)
+ {
+ $previous_placement = -1;
+ $previous_offset = -1;
+
+ for($i = 0; $i < $point_counter; $i++)
+ {
+ $value = $this->graph_data[$i_o][$i];
+ $value_plot_top = $this->graph_top_end + 1 - round(($value / $this->graph_maximum_value) * ($this->graph_top_end - $this->graph_top_start));
+ $px_from_left = $this->graph_left_start + ($this->identifier_width * ($i + 1));
+
+ $this->render_graph_pointer($px_from_left, $value_plot_top);
+
+ $previous_placement = $value_plot_top;
+ $previous_offset = $px_from_left;
+ }
+ }
+ }
+ }
+ protected function render_graph_result()
+ {
+ $this->renderGraphLines();
+ }
+ protected function render_graph_pointer($x, $y)
+ {
+ $this->draw_line($this->graph_image, $x - 5, $y - 5, $x + 5, $y + 5, $this->graph_color_notches);
+ $this->draw_line($this->graph_image, $x + 5, $y - 5, $x - 5, $y + 5, $this->graph_color_notches);
+ $this->draw_rectangle($this->graph_image, $x - 2, $y - 2, $x + 3, $y + 3, $this->graph_color_notches);
+ }
+}
+
+?>
diff --git a/pts-core/objects/pts_Graph/pts_MultiPassFailGraph.php b/pts-core/objects/pts_Graph/pts_MultiPassFailGraph.php
new file mode 100644
index 0000000..bc7109d
--- /dev/null
+++ b/pts-core/objects/pts_Graph/pts_MultiPassFailGraph.php
@@ -0,0 +1,127 @@
+<?php
+
+/*
+ Phoronix Test Suite
+ URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
+ Copyright (C) 2008, Phoronix Media
+ Copyright (C) 2008, Michael Larabel
+ pts_PassFailGraph.php: An abstract graph object extending pts_Graph for showing results in a pass/fail scenario.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+class pts_MultiPassFailGraph extends pts_CustomGraph
+{
+ public function __construct($title, $sub_title, $y_axis_title)
+ {
+ $this->graph_y_title_hide = true;
+ parent::__construct($title, $sub_title, $y_axis_title);
+ $this->graph_type = "MULTI_PASS_FAIL";
+ $this->graph_value_type = "ABSTRACT";
+ $this->graph_hide_identifiers = true;
+ }
+ protected function render_graph_passfail()
+ {
+ $identifier_count = count($this->graph_identifiers);
+ $vertical_border = 20;
+ $horizontal_border = 14;
+ $heading_height = 24;
+ $graph_width = $this->graph_left_end - $this->graph_left_start - ($horizontal_border * 2);
+ $graph_height = $this->graph_top_end - $this->graph_top_start - ($vertical_border * 2) - $heading_height;
+ $line_height = floor($graph_height / $identifier_count);
+
+ $pass_color = $this->next_paint_color();
+ $fail_color = $this->next_paint_color();
+
+ $main_width = floor($graph_width * .24);
+ $main_font_size = $this->graph_font_size_bars;
+ $main_greatest_length = $this->find_longest_string($this->graph_identifiers);
+
+ $width = $main_width - 8;
+ $height = $line_height - 4;
+ $main_font_size = $this->text_size_bounds($main_greatest_length, $this->graph_font, $main_font_size, 4, $width, $height);
+
+ if(($new_size = $this->text_string_width($main_greatest_length, $this->graph_font, $main_font_size)) < ($main_width - 12))
+ {
+ $main_width = $new_size + 10;
+ }
+
+ $identifiers_total_width = $graph_width - $main_width - 2;
+
+ $headings = explode(",", $this->graph_y_title);
+ $identifiers_width = floor($identifiers_total_width / count($headings));
+ $headings_font_size = $this->graph_font_size_bars;
+ while(($this->text_string_width($this->find_longest_string($headings), $this->graph_font, $headings_font_size) > ($identifiers_width - 2)) || $this->text_string_height($this->graph_maximum_value, $this->graph_font, $headings_font_size) > ($line_height - 4))
+ {
+ $headings_font_size -= 0.5;
+ }
+
+ for($j = 0; $j < count($this->graph_data[0]); $j++)
+ {
+ $results = array_reverse(explode(",", $this->graph_data[0][$j]));
+ $line_ttf_height = $this->text_string_height("AZ@![]()@|_", $this->graph_font, $this->graph_font_size_bars);
+ for($i = 0; $i < count($headings) && $i < count($results); $i++)
+ {
+ if($results[$i] == "PASS")
+ {
+ $paint_color = $pass_color;
+ }
+ else
+ {
+ $paint_color = $fail_color;
+ }
+
+ $this_bottom_end = $this->graph_top_start + $vertical_border + (($j + 1) * $line_height) + $heading_height + 1;
+
+ if($this_bottom_end >= $this->graph_top_end - $vertical_border)
+ {
+ $this_bottom_end = $this->graph_top_end - $vertical_border - 1;
+ }
+ else if($j == (count($this->graph_data[0]) - 1) && $this_bottom_end < $this->graph_top_end - $vertical_border)
+ {
+ $this_bottom_end = $this->graph_top_end - $vertical_border - 1;
+ }
+
+ $this->draw_rectangle($this->graph_image, $this->graph_left_end - $horizontal_border - ($i * $identifiers_width), $this->graph_top_start + $vertical_border + ($j * $line_height) + $heading_height, $this->graph_left_end - $horizontal_border - (($i + 1) * $identifiers_width), $this_bottom_end, $paint_color);
+ $this->write_text_center($results[$i], $this->graph_font_size_bars, $this->graph_color_body_text, $this->graph_left_end - $horizontal_border - ($i * $identifiers_width) - $identifiers_width, $this->graph_top_start + $vertical_border + ($j * $line_height) + $heading_height + ($line_height / 2) - ($line_ttf_height / 2), $this->graph_left_end - $horizontal_border - ($i * $identifiers_width), $this->graph_top_start + $vertical_border + ($j * $line_height) + $heading_height + ($line_height / 2) - ($line_ttf_height / 2));
+ }
+ }
+
+ $headings = array_reverse($headings);
+ $line_ttf_height = $this->text_string_height("AZ@![]()@|_", $this->graph_font, $headings_font_size);
+ for($i = 0; $i < count($headings); $i++)
+ {
+ $this->draw_line($this->graph_image, $this->graph_left_end - $horizontal_border - (($i + 1) * $identifiers_width), $this->graph_top_start + $vertical_border, $this->graph_left_end - $horizontal_border - (($i + 1) * $identifiers_width), $this->graph_top_end - $vertical_border, $this->graph_color_body_light);
+ $this->write_text_center($headings[$i], $headings_font_size, $this->graph_color_headers, $this->graph_left_end - $horizontal_border - ($i * $identifiers_width) - $identifiers_width, $this->graph_top_start + $vertical_border + ($heading_height / 2) - ($line_ttf_height / 2), $this->graph_left_end - $horizontal_border - ($i * $identifiers_width), $this->graph_top_start + $vertical_border + ($heading_height / 2) - ($line_ttf_height / 2));
+ }
+
+ $line_ttf_height = $this->text_string_height("AZ@![]()@|_", $this->graph_font, $main_font_size);
+ for($i = 0; $i < count($this->graph_identifiers); $i++)
+ {
+ $this->draw_line($this->graph_image, $this->graph_left_start + $horizontal_border, $this->graph_top_start + $vertical_border + ($i * $line_height) + $heading_height, $this->graph_left_end - $horizontal_border, $this->graph_top_start + $vertical_border + ($i * $line_height) + $heading_height, $this->graph_color_body_light);
+ $this->write_text_right($this->graph_identifiers[$i], $main_font_size, $this->graph_color_headers, $this->graph_left_start + $horizontal_border + $main_width, $this->graph_top_start + $vertical_border + ($i * $line_height) + $heading_height + ($line_height / 2) - 2, $this->graph_left_start + $horizontal_border + $main_width, $this->graph_top_start + $vertical_border + ($i * $line_height) + $heading_height + ($line_height / 2) - 2, false);
+ }
+
+ $this->draw_line($this->graph_image, $this->graph_left_start + $horizontal_border, $this->graph_top_start + $vertical_border, $this->graph_left_end - $horizontal_border, $this->graph_top_start + $vertical_border, $this->graph_color_body_light);
+ $this->draw_line($this->graph_image, $this->graph_left_start + $horizontal_border, $this->graph_top_start + $vertical_border, $this->graph_left_start + $horizontal_border, $this->graph_top_end - $vertical_border, $this->graph_color_body_light);
+ $this->draw_line($this->graph_image, $this->graph_left_end - $horizontal_border, $this->graph_top_start + $vertical_border, $this->graph_left_end - $horizontal_border, $this->graph_top_end - $vertical_border, $this->graph_color_body_light);
+ $this->draw_line($this->graph_image, $this->graph_left_start + $horizontal_border, $this->graph_top_end - $vertical_border, $this->graph_left_end - $horizontal_border, $this->graph_top_end - $vertical_border, $this->graph_color_body_light);
+ }
+ protected function render_graph_result()
+ {
+ $this->render_graph_passfail();
+ }
+}
+
+?>
diff --git a/pts-core/objects/pts_Graph/pts_PassFailGraph.php b/pts-core/objects/pts_Graph/pts_PassFailGraph.php
new file mode 100644
index 0000000..cb466fd
--- /dev/null
+++ b/pts-core/objects/pts_Graph/pts_PassFailGraph.php
@@ -0,0 +1,99 @@
+<?php
+
+/*
+ Phoronix Test Suite
+ URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
+ Copyright (C) 2008, Phoronix Media
+ Copyright (C) 2008, Michael Larabel
+ pts_PassFailGraph.php: An abstract graph object extending pts_Graph for showing results in a pass/fail scenario.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+class pts_PassFailGraph extends pts_CustomGraph
+{
+ public function __construct($title, $sub_title, $y_axis_title)
+ {
+ parent::__construct($title, $sub_title, $y_axis_title);
+ $this->graph_type = "PASS_FAIL";
+ $this->graph_value_type = "ABSTRACT";
+ $this->graph_hide_identifiers = true;
+ $this->graph_data_title = array("PASSED", "FAILED");
+ }
+ protected function render_graph_passfail()
+ {
+ $identifier_count = count($this->graph_identifiers);
+ $vertical_border = 18;
+ $horizontal_border = 10;
+ $spacing = 8;
+ $columns = 1;
+ $graph_width = $this->graph_left_end - $this->graph_left_start - ($horizontal_border * 2);
+ $graph_height = $this->graph_top_end - $this->graph_top_start - ($vertical_border * 1.5);
+ $font_size = $this->graph_font_size_bars * 1.5;
+
+ $pass_color = $this->next_paint_color();
+ $fail_color = $this->next_paint_color();
+
+ for($i = 2; $i <= sqrt($identifier_count); $i++)
+ {
+ if(intval($identifier_count / $i) == ($identifier_count / $i))
+ {
+ $columns = $i;
+ }
+ }
+
+ $identifiers_per_column = $identifier_count / $columns;
+ $identifier_height = floor(($graph_height - (($identifiers_per_column - 1) * $spacing)) / $identifiers_per_column);
+ $identifier_width = floor(($graph_width - (($columns - 1) * $spacing)) / $columns);
+
+ $width = $identifier_width - 8;
+ $height = $line_height - 4;
+ $main_font_size = $this->text_size_bounds($this->graph_maximum_value, $this->graph_font, $font_size, 4, $width, $height);
+
+ for($c = 0; $c < $columns; $c++)
+ {
+ for($i = 0; $i < $identifiers_per_column; $i++)
+ {
+ $element_i = ($c * $identifiers_per_column) + $i;
+ $this_identifier = $this->graph_identifiers[$element_i];
+ $this_value = $this->graph_data[0][$element_i];
+
+ $this_horizontal_start = $this->graph_left_start + $horizontal_border + ($c * ($identifier_width + $spacing));
+ $this_horizontal_end = $this->graph_left_start + $horizontal_border + ($c * ($identifier_width + $spacing)) + $identifier_width;
+ $this_vertical_start = $this->graph_top_start + $vertical_border + ($i * ($identifier_height + $spacing));
+ $this_vertical_end = $this->graph_top_start + $vertical_border + ($i * ($identifier_height + $spacing)) + $identifier_height;
+
+ if($this_value == "PASS")
+ {
+ $paint_color = $pass_color;
+ }
+ else
+ {
+ $paint_color = $fail_color;
+ }
+
+ $this->draw_rectangle_border($this->graph_image, $this_horizontal_start, $this_vertical_start, $this_horizontal_end, $this_vertical_end, $this->graph_color_body_light);
+ $this->draw_rectangle($this->graph_image, $this_horizontal_start + 1, $this_vertical_start + 1, $this_horizontal_end - 1, $this_vertical_end - 1, $paint_color);
+
+ $this->write_text_center($this_identifier, $font_size, $this->graph_color_body_text, $this_horizontal_start, $this_vertical_start + (($this_vertical_end - $this_vertical_start) / 2) - ($this->text_string_height($this_identifier, $this->graph_font, $font_size) / 2), $this_horizontal_end, $this_vertical_start + (($this_vertical_end - $this_vertical_start) / 2) - ($this->text_string_height($this_identifier, $this->graph_font, $font_size) / 2));
+ }
+ }
+ }
+ protected function render_graph_result()
+ {
+ $this->render_graph_passfail();
+ }
+}
+
+?>
diff --git a/pts-core/objects/tandem_Xml/pts_test_tandem_XmlReader.php b/pts-core/objects/tandem_Xml/pts_test_tandem_XmlReader.php
new file mode 100644
index 0000000..096b356
--- /dev/null
+++ b/pts-core/objects/tandem_Xml/pts_test_tandem_XmlReader.php
@@ -0,0 +1,53 @@
+<?php
+
+/*
+ Phoronix Test Suite
+ URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
+ Copyright (C) 2008, Phoronix Media
+ Copyright (C) 2004-2008, Michael Larabel
+ pts_test_tandem_XmlReader.php: The XML reading object for the Phoronix Test Suite with optimizations for handling test profiles
+
+ Additional Notes: A very simple XML parser with a few extras... Does not currently support attributes on tags, etc.
+ A work in progress. This was originally designed for just some select needs in the past. No XML validation is done with this parser, etc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+class pts_test_tandem_XmlReader extends tandem_XmlReader
+{
+ function handleXmlZeroTagFallback($xml_tag)
+ {
+ // Cascading Test Profiles for finding a tag within an XML file being extended by another XML file
+ $fallback_value = $this->tag_fallback_value;
+
+ if(!empty($this->xml_file_name))
+ {
+ $test_extends = $this->getValue(P_TEST_CTPEXTENDS, null, null, true, true);
+
+ if(!empty($test_extends) && pts_is_test($test_extends))
+ {
+ $test_below_parser = new pts_test_tandem_XmlReader(pts_location_test($test_extends));
+ $test_below_tag = $test_below_parser->getXMLValue($xml_tag);
+
+ if(!empty($test_below_tag))
+ {
+ $fallback_value = $test_below_tag;
+ }
+ }
+ }
+
+ return $fallback_value;
+ }
+}
+?>
diff --git a/pts-core/objects/tandem_Xml/tandem_XmlReader.php b/pts-core/objects/tandem_Xml/tandem_XmlReader.php
new file mode 100644
index 0000000..7bc6707
--- /dev/null
+++ b/pts-core/objects/tandem_Xml/tandem_XmlReader.php
@@ -0,0 +1,309 @@
+<?php
+
+/*
+ Phoronix Test Suite
+ URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
+ Copyright (C) 2008, Phoronix Media
+ Copyright (C) 2004-2008, Michael Larabel
+ tandem_XmlReader.php: The XML reading object for the Phoronix Test Suite.
+
+ Additional Notes: A very simple XML parser with a few extras... Does not currently support attributes on tags, etc.
+ A work in progress. This was originally designed for just some select needs in the past. No XML validation is done with this parser, etc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+class tandem_XmlReader
+{
+ var $xml_data = ""; // XML contents
+ var $xml_file_time = null; // File modification time
+ var $xml_file_name = null; // File name
+
+ var $xml_cache_file = false; // Cache the entire XML file being parsed?
+ var $xml_cache_tags = true; // Cache the tags that are being called?
+
+ var $tag_fallback_value = null; // Fallback value if tag is not present
+
+ static $tag_cache = null; // The cache for the tag cache
+ static $file_cache = null; // The cache for the file cache
+
+ function __construct($read_xml, $cache_support = true)
+ {
+ if(is_readable($read_xml))
+ {
+ if($cache_support)
+ {
+ $this->xml_cache_file = false;
+ $this->xml_cache_tags = false;
+ }
+
+ // If you are going to be banging XML files hard through the course of the script, you will want to flush the PHP file cache
+ // clearstatcache();
+
+ $this->xml_file_time = filemtime($read_xml);
+ $this->xml_file_name = $read_xml;
+
+ if($this->xml_cache_file && isset(self::$file_cache[$this->xml_file_name][$this->xml_file_time]))
+ {
+ $this->xml_data = self::$file_cache[$this->xml_file_name][$this->xml_file_time];
+ }
+
+ if(empty($this->xml_data))
+ {
+ $this->xml_data = file_get_contents($read_xml);
+
+ if($this->xml_cache_file)
+ {
+ self::$file_cache[$this->xml_file_name][$this->xml_file_time] = $this->xml_data;
+ }
+ }
+ }
+ else
+ {
+ $this->xml_cache_file = false;
+ $this->xml_cache_tags = false;
+ $this->xml_data = $read_xml;
+ }
+ }
+ function getStatement($statement)
+ {
+ return $this->listStatements(true, $statement);
+ }
+ function listStatements($perform_search = false, $search_query = "")
+ {
+ $return_r = array();
+ $comment_statements = $this->parseLineCommentsFromFile();
+
+ foreach($comment_statements as $statement)
+ {
+ $name = substr($statement, 0, strpos($statement, ":"));
+ $name = trim(strstr($name, " "));
+
+ if($perform_search && !empty($search_query))
+ {
+ if($name == $search_query)
+ {
+ $value = trim(substr(strstr($statement, ":"), 1));
+ array_push($return_r, $value);
+ }
+ }
+ else
+ {
+ array_push($return_r, $name);
+ }
+ }
+
+ return $return_r;
+ }
+ function getXMLValue($xml_tag)
+ {
+ return $this->getValue($xml_tag);
+ }
+ function isDefined($xml_tag)
+ {
+ return $this->getValue($xml_tag) != null;
+ }
+ function getValue($xml_path, $xml_tag = null, $xml_match = null, $cache_tag = true, $is_fallback_call = false)
+ {
+ if($xml_tag == null)
+ {
+ $xml_tag = $xml_path;
+ }
+ if($xml_match == null)
+ {
+ $xml_match = $this->xml_data;
+ }
+
+ if($this->xml_cache_tags && $cache_tag && isset(self::$tag_cache[$this->xml_file_name][$this->xml_file_time][$xml_tag]))
+ {
+ $xml_match = self::$tag_cache[$this->xml_file_name][$this->xml_file_time][$xml_tag];
+ }
+ else
+ {
+ foreach(explode("/", $xml_tag) as $xml_step)
+ {
+ $xml_match = $this->parseXMLString($xml_step, $xml_match, false);
+
+ if($xml_match == false)
+ {
+ if($is_fallback_call != true)
+ {
+ $xml_match = $this->handleXmlZeroTagFallback($xml_path);
+ }
+ else
+ {
+ $xml_match = $this->tag_fallback_value;
+ }
+ }
+ }
+
+ if($this->xml_cache_tags && $cache_tag)
+ {
+ self::$tag_cache[$this->xml_file_name][$this->xml_file_time][$xml_tag] = $xml_match;
+ }
+ }
+
+ return $xml_match;
+ }
+ function parseXMLString($xml_tag, $to_parse, $multi_search = true)
+ {
+ $return = false;
+ $temp_r = array();
+ $temp = $to_parse;
+
+ $open_tag = "<" . $xml_tag . ">";
+ $close_tag = "</" . $xml_tag . ">";
+ $open_tag_length = strlen($open_tag);
+ $close_tag_length = strlen($close_tag);
+
+ do
+ {
+ $return = null;
+
+ if(($start = strpos($temp, $open_tag)) !== false)
+ {
+ $temp = substr($temp, $start + $open_tag_length);
+
+ if(($end = strpos($temp, $close_tag)) !== false)
+ {
+ $return = substr($temp, 0, $end);
+ $temp = substr($temp, strlen($return) + $close_tag_length);
+ }
+ }
+
+ if($return != null)
+ {
+ array_push($temp_r, $return);
+ }
+ }
+ while($return != null && $multi_search);
+
+ if(count($temp_r) > 0)
+ {
+ $return = $temp_r;
+
+ if($multi_search == false)
+ {
+ $return = $return[0];
+ }
+ }
+
+ return $return;
+ }
+ function parseLineCommentsFromFile($read_from = null)
+ {
+ if(empty($read_from))
+ {
+ $read_from = $this->xml_data;
+ }
+
+ $return_r = array();
+ $temp = $read_from;
+
+ do
+ {
+ $return = null;
+
+ if(($start = strpos($temp, "<!--")) !== false)
+ {
+ $temp = substr($temp, $start + 4);
+
+ if(($end = strpos($temp, "-->")) !== false)
+ {
+ $return = substr($temp, 0, $end);
+ $temp = substr($temp, strlen($return) + 3);
+ }
+ }
+
+ if($return != null)
+ {
+ array_push($return_r, $return);
+ }
+ }
+ while($return != null);
+
+ return $return_r;
+ }
+ function handleXmlZeroTagFallback($xml_tag)
+ {
+ return $this->tag_fallback_value;
+ }
+ function getXMLValues($xml_tag)
+ {
+ return $this->getXMLArrayValues($xml_tag);
+ }
+ function getXMLArrayValues($xml_tag)
+ {
+ return $this->getArrayValues($xml_tag, $this->xml_data);
+ }
+ function getArrayValues($xml_tag, $xml_match)
+ {
+ $xml_steps = explode("/", $xml_tag);
+ $xml_steps_count = count($xml_steps);
+ $this_xml = $xml_match;
+
+ for($i = 0; $i < ($xml_steps_count - 2); $i++)
+ {
+ $this_xml = $this->getValue($xml_tag, $xml_steps[$i], $this_xml, false);
+ }
+
+ $xml_matches = $this->parseXMLString($xml_steps[($xml_steps_count - 2)], $this_xml);
+ $xml_matches_count = count($xml_matches);
+
+ $return_r = array();
+ $extraction_tags = explode(",", end($xml_steps));
+ $extraction_tags_count = count($extraction_tags);
+
+ for($i = 0; $i < $xml_matches_count; $i++)
+ {
+ if($extraction_tags_count == 1)
+ {
+ $this_item = $this->getValue($xml_tag, $extraction_tags[0], $xml_matches[$i], false);
+ array_push($return_r, $this_item);
+ }
+ else
+ {
+ if($i == 0)
+ {
+ foreach($extraction_tags as $extract)
+ {
+ $return_r[$extract] = array();
+ }
+ }
+
+ foreach($extraction_tags as $extract)
+ {
+ $this_item = $this->getValue($xml_tag, $extract, $xml_matches[$i], false);
+ array_push($return_r[$extract], $this_item);
+ }
+ }
+ }
+ return $return_r;
+ }
+ function setFileCaching($do_cache)
+ {
+ $this->xml_cache_file = ($do_cache == true);
+ }
+ function setTagCaching($do_cache)
+ {
+ $this->xml_cache_tags = ($do_cache == true);
+ }
+ function setCaching($do_cache)
+ {
+ $this->setFileCaching($do_cache);
+ $this->setTagCaching($do_cache);
+ }
+}
+
+?>
diff --git a/pts-core/objects/tandem_Xml/tandem_XmlWriter.php b/pts-core/objects/tandem_Xml/tandem_XmlWriter.php
new file mode 100644
index 0000000..78a8c5e
--- /dev/null
+++ b/pts-core/objects/tandem_Xml/tandem_XmlWriter.php
@@ -0,0 +1,199 @@
+<?php
+
+/*
+ Phoronix Test Suite
+ URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/
+ Copyright (C) 2008, Phoronix Media
+ Copyright (C) 2004-2008, Michael Larabel
+ tandem_XmlReader.php: The XML writing object for the Phoronix Test Suite.
+
+ Additional Notes: A very simple XML writer with a few extras... Does not support attributes on tags, etc.
+ A work in progress. This was originally designed for just some select needs in the past. It does support linking to an XSL as
+ well as whether to format the XML or not, etc. Also provides a MD5 checksum of the XML body.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+class tandem_XmlWriter
+{
+ var $xml_objects = array();
+ var $xml_string_paths = array();
+ var $xml_statements = array();
+
+ var $xml_checksum = false;
+ var $format_xml = true;
+ var $xsl_binding = null;
+
+ function __construct($nice_formatting = true)
+ {
+ $this->format_xml = ($nice_formatting == true);
+ }
+ function setXslBinding($url)
+ {
+ $this->xsl_binding = $url;
+ }
+ function writeXmlCheckSum()
+ {
+ $this->xml_checksum = true;
+ }
+ function addXmlObject($xml_location, $unique_identifier = 0, $xml_value = "", $std_step = null, $step_id = null)
+ {
+ $xml_array = array();
+ $alt_step = -1;
+ $steps = 0;
+
+ if($std_step == null)
+ {
+ $std_step = 2;
+ }
+ if($step_id == null)
+ {
+ $step_id = $unique_identifier;
+ }
+
+ if(array_search($unique_identifier . "," . $xml_location, $this->xml_string_paths) !== false)
+ {
+ $alt_step = 2;
+ }
+ else
+ {
+ array_push($this->xml_string_paths, $unique_identifier . "," . $xml_location);
+ }
+
+ $xml_steps = explode('/', $xml_location);
+ foreach(array_reverse($xml_steps) as $current_tag)
+ {
+ $steps++;
+
+ if(empty($xml_array))
+ {
+ $xml_array = $xml_value;
+ }
+ if(!empty($current_tag))
+ {
+ $xml_array = array("$current_tag" => $xml_array);
+ }
+
+ if($steps == $std_step)
+ {
+ $xml_array = array("id_" . $unique_identifier => $xml_array);
+ }
+ if($steps == $alt_step)
+ {
+ $xml_array = array("id_" . $step_id => $xml_array);
+ }
+ }
+
+ $this->xml_objects = array_merge_recursive($this->xml_objects, $xml_array);
+ }
+ function addStatement($name, $value)
+ {
+ array_push($this->xml_statements, trim($name . ": " . $value));
+ }
+ function getXMLStatements()
+ {
+ $return_string = "";
+ $statements_to_print = array_reverse($this->xml_statements);
+
+ foreach($statements_to_print as $statement)
+ {
+ $return_string .= "<!-- " . $statement . " -->\n";
+ }
+
+ return $return_string;
+ }
+ function getXML()
+ {
+ $formatted_xml = $this->getXMLBelow($this->xml_objects, 0);
+
+ $this->addStatement("Generated", date("Y-m-d H:i:s"));
+
+ if($this->xml_checksum)
+ {
+ $this->addStatement("Checksum", md5($formatted_xml));
+ }
+
+ return "<?xml version=\"1.0\"?>\n" . $this->getXSL() . $this->getXMLStatements() . $formatted_xml;
+ }
+ function getXSL()
+ {
+ $str = "";
+
+ if($this->xsl_binding != null)
+ {
+ $str = "<?xml-stylesheet type=\"text/xsl\" href=\"" . $this->xsl_binding . "\" ?>\n";
+ }
+
+ return $str;
+ }
+ function getJustXML()
+ {
+ return $this->getXMLBelow($this->xml_objects, 0);
+ }
+ function getXMLBelow($statement_name, $times_deep)
+ {
+ $formatted_xml = "";
+
+ foreach($statement_name as $key => $value)
+ {
+ if(!is_array($value))
+ {
+ $formatted_xml .= $this->getXMLTabs($times_deep) . "<" . $key . ">" . $value . "</" . $key . ">" . $this->getXMLBreaks();
+ }
+ else
+ {
+ if(substr($key, 0, 3) === "id_")
+ {
+ $formatted_xml .= $this->getXMLBelow($value, $times_deep);
+ }
+ else
+ {
+ $formatted_xml .= $this->getXMLTabs($times_deep) . "<" . $key . ">" . $this->getXMLBreaks();
+ $formatted_xml .= $this->getXMLBelow($value, $times_deep + 1);
+ $formatted_xml .= $this->getXMLTabs($times_deep) . "</" . $key . ">" . $this->getXMLBreaks();
+ }
+ }
+ }
+
+ return $formatted_xml;
+ }
+ function getXMLTabs($times_deep)
+ {
+ $format = "";
+
+ if($this->format_xml)
+ {
+ $format = str_repeat("\t", $times_deep);
+ }
+
+ return $format;
+ }
+ function getXMLBreaks()
+ {
+ $format = "";
+
+ if($this->format_xml)
+ {
+ $format = "\n";
+ }
+
+ return $format;
+ }
+ function debugDumpArray()
+ {
+ return $this->xml_objects;
+ }
+}
+
+?>