← Index
NYTProf Performance Profile   « line view »
For ./view
  Run on Fri Jul 31 18:42:36 2015
Reported on Fri Jul 31 18:48:14 2015

Filename/var/www/foswikidev/core/lib/Foswiki/Plugins/ChartPlugin.pm
StatementsExecuted 340 statements in 2.91ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
10811353µs353µsFoswiki::Plugins::ChartPlugin::::commonTagsHandlerFoswiki::Plugins::ChartPlugin::commonTagsHandler
11117µs102µsFoswiki::Plugins::ChartPlugin::::initPluginFoswiki::Plugins::ChartPlugin::initPlugin
11114µs28µsFoswiki::Plugins::ChartPlugin::::BEGIN@39Foswiki::Plugins::ChartPlugin::BEGIN@39
11110µs141µsFoswiki::Plugins::ChartPlugin::::BEGIN@42Foswiki::Plugins::ChartPlugin::BEGIN@42
0000s0sFoswiki::Plugins::ChartPlugin::::ChartPluginFoswiki::Plugins::ChartPlugin::ChartPlugin
0000s0sFoswiki::Plugins::ChartPlugin::::_ParametersFoswiki::Plugins::ChartPlugin::_Parameters
0000s0sFoswiki::Plugins::ChartPlugin::::_init_defaultsFoswiki::Plugins::ChartPlugin::_init_defaults
0000s0sFoswiki::Plugins::ChartPlugin::::_makeChartFoswiki::Plugins::ChartPlugin::_makeChart
0000s0sFoswiki::Plugins::ChartPlugin::::_make_errorFoswiki::Plugins::ChartPlugin::_make_error
0000s0sFoswiki::Plugins::ChartPlugin::::_make_filenameFoswiki::Plugins::ChartPlugin::_make_filename
0000s0sFoswiki::Plugins::ChartPlugin::::_maxFoswiki::Plugins::ChartPlugin::_max
0000s0sFoswiki::Plugins::ChartPlugin::::_minFoswiki::Plugins::ChartPlugin::_min
0000s0sFoswiki::Plugins::ChartPlugin::::_setParametersFoswiki::Plugins::ChartPlugin::_setParameters
0000s0sFoswiki::Plugins::ChartPlugin::::_setTablesFoswiki::Plugins::ChartPlugin::_setTables
0000s0sFoswiki::Plugins::ChartPlugin::::_setTopicContentsFoswiki::Plugins::ChartPlugin::_setTopicContents
0000s0sFoswiki::Plugins::ChartPlugin::::_tablesFoswiki::Plugins::ChartPlugin::_tables
0000s0sFoswiki::Plugins::ChartPlugin::::_timeitFoswiki::Plugins::ChartPlugin::_timeit
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1# ChartPlugin for Foswiki - The Free and Open Source Wiki, http://foswiki.org/
2#
3# Copyright (C) 2004-2006 Peter Thoeny, Peter@Thoeny.org
4# Plugin written by http://TWiki.org/cgi-bin/view/Main/TaitCyrus
5# Copyright (C) 2008-2011 Foswiki Contributors
6#
7# For licensing info read LICENSE file in the Foswiki root.
8# This program is free software; you can redistribute it and/or
9# modify it under the terms of the GNU General Public License
10# as published by the Free Software Foundation; either version 2
11# of the License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details, published at
17# http://www.gnu.org/copyleft/gpl.html
18#
19# As per the GPL, removal of this notice is prohibited.
20#
21# =========================
22#
23# This file contains routines for producing PNG graphic files containing
24# chart information, useful for building dashboards.
25# NOTE: ONLY in the case where an old version of GD (1.19 or earlier) is
26# available will GIF's be created. If the GD version is > 1.19, then
27# PNG's are created.
28#
29# This plugin uses Perl object oriented programming. The ChartPlugin
30# object contains several other Perl objects:
31# Table
32# Parameters
33# Chart
34# In addition to having it's own getter/setters.
35
36# =========================
37package Foswiki::Plugins::ChartPlugin;
38
39244µs241µs
# spent 28µs (14+13) within Foswiki::Plugins::ChartPlugin::BEGIN@39 which was called: # once (14µs+13µs) by Foswiki::Plugin::BEGIN@2.5 at line 39
use strict;
# spent 28µs making 1 call to Foswiki::Plugins::ChartPlugin::BEGIN@39 # spent 13µs making 1 call to strict::import
40
41# =========================
4216µs1131µs
# spent 141µs (10+131) within Foswiki::Plugins::ChartPlugin::BEGIN@42 which was called: # once (10µs+131µs) by Foswiki::Plugin::BEGIN@2.5 at line 50
use vars qw(
# spent 131µs making 1 call to vars::import
43 $installWeb $VERSION $RELEASE $debug
44 $pluginInitialized $initError
45 $defaultType @defaultAreaColors @defaultLineColors
46 $defaultWidth $defaultHeight $defaultBGcolor $defaultNumYGrids
47 $defaultDataValue $defaultScale $defaultGridColor $defaultPointSize
48 $defaultLineWidth
49 $defaultBarLeadingSpace $defaultBarTrailingSpace $defaultBarSpace
5012.50ms1141µs);
# spent 141µs making 1 call to Foswiki::Plugins::ChartPlugin::BEGIN@42
51
521700nsour $VERSION = '1.6.1';
531200nsour $RELEASE = '1.6.1';
541300nsour $SHORT_DESCRIPTION =
55 'Create area, bar, line and scatter charts to visualize table data';
56
571200ns$pluginInitialized = 0;
581200ns$initError = '';
59
60# =========================
61
# spent 102µs (17+86) within Foswiki::Plugins::ChartPlugin::initPlugin which was called: # once (17µs+86µs) by Foswiki::Plugin::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Plugin.pm:257] at line 250 of /var/www/foswikidev/core/lib/Foswiki/Plugin.pm
sub initPlugin {
6213µs ( my $topic, my $web, my $user, $installWeb ) = @_;
63
64 # check for Plugins.pm versions
65111µs15µs if ( $Foswiki::Plugins::VERSION < 1 ) {
# spent 5µs making 1 call to version::vxs::VCMP
66 &Foswiki::Func::writeWarning(
67 "Version mismatch between ChartPlugin and Plugins.pm");
68 return 0;
69 }
70
71 # Get plugin debug flag
7212µs180µs $debug = &Foswiki::Func::getPreferencesFlag("CHARTPLUGIN_DEBUG") || 0;
# spent 80µs making 1 call to Foswiki::Func::getPreferencesFlag
73
741500ns &Foswiki::Func::writeDebug(
75 "- Foswiki::Plugins::ChartPlugin::initPlugin($web.$topic) is OK")
76 if $debug;
77
78 # Mark that we are not fully initialized yet. Only get the default
79 # values from the plugin topic page iff a CHART is found in a topic
801300ns $pluginInitialized = 0;
8114µs return 1;
82}
83
84# =========================
85
86# Initialize all default values from the plugin topic page.
87sub _init_defaults {
88 return if $pluginInitialized;
89 $pluginInitialized = 1;
90 require Exporter;
91 foreach my $module (
92 qw( GD POSIX
93 Foswiki::Plugins::ChartPlugin::Chart
94 Foswiki::Plugins::ChartPlugin::Parameters
95 Foswiki::Plugins::ChartPlugin::Table)
96 )
97 {
98 eval "require $module";
99 if ($@) {
100 $initError = "Required Perl module '$module' not found: $@";
101 return;
102 }
103 }
104
105 # Get default chart type
106 $defaultType = Foswiki::Func::getPreferencesValue("CHARTPLUGIN_TYPE")
107 || 'line';
108
109 # Get default chart values
110 $defaultWidth = &Foswiki::Func::getPreferencesValue("CHARTPLUGIN_WIDTH")
111 || 60;
112 $defaultHeight = &Foswiki::Func::getPreferencesValue("CHARTPLUGIN_HEIGHT")
113 || 16;
114 my $defaultAreaColors =
115 &Foswiki::Func::getPreferencesValue("CHARTPLUGIN_AREA_COLORS")
116 || "#FF0000 #FFFF00 #00FF00";
117 @defaultAreaColors = split( /[\s,]+/, $defaultAreaColors );
118 my $defaultLineColors =
119 &Foswiki::Func::getPreferencesValue("CHARTPLUGIN_LINE_COLORS")
120 || "#FFFF00 #FF00FF #00FFFF";
121 @defaultLineColors = split( /[\s,]+/, $defaultLineColors );
122
123 # Get default chart bgcolor
124 $defaultBGcolor = &Foswiki::Func::getPreferencesValue("CHARTPLUGIN_BGCOLOR")
125 || '#FFFFFF #FFFFFF';
126
127 # Get default number of Y axis grids
128 $defaultNumYGrids =
129 &Foswiki::Func::getPreferencesValue("CHARTPLUGIN_NUMYGRIDS") || 10;
130
131 # Get default value to use if there is no data seen in the table
132 $defaultDataValue =
133 &Foswiki::Func::getPreferencesValue("CHARTPLUGIN_DEFAULTDATA");
134
135 # Get default value for the scale (linear/semilog)
136 $defaultScale = &Foswiki::Func::getPreferencesValue("CHARTPLUGIN_SCALE");
137
138 # Get default grid color.
139 $defaultGridColor =
140 &Foswiki::Func::getPreferencesValue("CHARTPLUGIN_GRIDCOLOR") || '#000000';
141
142 # Get default value for the size, in pixels, of drawn data points
143 $defaultPointSize =
144 &Foswiki::Func::getPreferencesValue("CHARTPLUGIN_POINTSIZE") || 2;
145
146 # Get default value for the width, in pixels, of drawn lines
147 $defaultLineWidth =
148 &Foswiki::Func::getPreferencesValue("CHARTPLUGIN_LINEWIDTH") || 3;
149
150 # Get default value for the leading space before the first bar.
151 $defaultBarLeadingSpace =
152 &Foswiki::Func::getPreferencesValue("CHARTPLUGIN_BARLEADINGSPACE") || 0;
153
154 # Get default value for the trailing space after the last bar.
155 $defaultBarTrailingSpace =
156 &Foswiki::Func::getPreferencesValue("CHARTPLUGIN_BARTRAILINGSPACE") || 0;
157
158 # Get default value for the space between bars.
159 $defaultBarSpace =
160 &Foswiki::Func::getPreferencesValue("CHARTPLUGIN_BARSPACE") || 0;
161}
162
163# Object constructor for creating a ChartPlugin Perl object. The object is
164# initialized with the current web.topic.
165sub ChartPlugin {
166 my ( $currentTopic, $currentWeb, $currentTopicContents ) = @_;
167 my $this = {};
168 bless $this;
169 $this->{CURRENT_TOPIC} = $currentTopic;
170 $this->{CURRENT_WEB} = $currentWeb;
171 $this->{CURRENT_TOPICONTENTS} = $currentTopicContents;
172 return $this;
173}
174
175# Setter for storing the Table object
176sub _setTables { my ( $this, $table ) = @_; $this->{TABLES} = $table; }
177
178# Getter for Table object
179sub _tables { my ($this) = @_; return $this->{TABLES}; }
180
181# Setter for storing the Parameters object
182sub _setParameters {
183 my ( $this, $args ) = @_;
184 $this->{PARAMETERS} = Foswiki::Plugins::ChartPlugin::Parameters->new($args);
185}
186
187# Getter for Parameters object
188sub _Parameters { my ($this) = @_; return $this->{PARAMETERS}; }
189
190# This routine sets the specified web.topic as the location from where to
191# get the table information. If the specified web.topic happen to be the
192# same as the web.topic from which the %CHART% was found, then the
193# web.topic contents is already part of the ChartPlugin object so there is
194# nothing to do. Otherwise, this routine will read in the specified
195# web.topic getting its contents and using that as the source to parse out
196# table information.
197sub _setTopicContents {
198 my ( $this, $inWeb, $inTopic ) = @_;
199 my $topicContents;
200
201 # If $inWeb and $inTopic match the current web/topic, then we already
202 # have the topic contents in the object so there is nothing to do.
203 # Otherwise, we need to open the specified web/topic and read in its
204 # contents.
205 if ( ( $inWeb eq $this->{CURRENT_WEB} )
206 && ( $inTopic eq $this->{CURRENT_TOPIC} ) )
207 {
208 $topicContents = $this->{CURRENT_TOPICONTENTS};
209 }
210 else {
211
212 # A difference, so read in the topic.
213 ( my $meta, $topicContents ) =
214 Foswiki::Func::readTopic( $inWeb, $inTopic );
215
216 # Check to make sure the web.topic actually exists. If not, return
217 # undef so the caller can catch the error.
218 return undef if ( !defined($topicContents) || $topicContents eq "" );
219 $topicContents =
220 Foswiki::Func::expandCommonVariables( $topicContents, $inTopic,
221 $inWeb );
222 }
223
224 # Lets parse the specified topic contents looking for tables.
225 $this->_setTables(
226 Foswiki::Plugins::ChartPlugin::Table->new($topicContents) );
227 return 1;
228}
229
230# Return the maximum value of the two specified numbers.
231sub _max {
232 my ( $v1, $v2 ) = @_;
233 return $v1 if ( $v1 > $v2 );
234 return $v2;
235}
236
237# Return the minimum value of the two specified numbers.
238sub _min {
239 my ( $v1, $v2 ) = @_;
240 return $v1 if ( $v1 < $v2 );
241 return $v2;
242}
243
244# Generate the file name in which the graphic file will be placed.
245sub _make_filename {
246 my ( $type, $name ) = @_;
247
248 # Generate the file name to be created
249 my $fullname;
250
251 # If GD version 1.19 or earlier, then create gif files else png files.
252 if ( $GD::VERSION > 1.19 ) {
253 $fullname = "_ChartPlugin_${type}_${name}.png";
254 }
255 else {
256 $fullname = "_ChartPlugin_${type}_${name}.gif";
257 }
258
259 return $fullname;
260}
261
262# This routine returns an red colored error message.
263sub _make_error {
264 my ($msg) = @_;
265 return "<font color=red>ChartPlugin error: $msg</font>";
266}
267
268# Actually construct the chart by parsing out each of the %CHART%
269# parameters, putting the parameters into the chart object, and then
270# creating the chart.
271sub _makeChart {
272 my ( $this, $args, $topic, $web ) = @_;
273
274 # Check to see if the GD module was found. If not, then create an
275 # error message to display back to the user.
276 if ($initError) {
277
278 # It appears that a library wasn't found so we return a
279 # different type of error that is just plain text.
280 return _make_error($initError);
281 }
282
283 # Set/parse the %CHART% parameters putting into the ChartPlugin object
284 $this->_setParameters($args);
285
286 # Make a chart object in which we will place user specified parameters
287 my $chart = Foswiki::Plugins::ChartPlugin::Chart->new();
288
289 # See if the parameter 'type' is available. This is a required
290 # parameter. If it is missing, then generate an error message.
291 my $type = $this->_Parameters->getParameter( "type", $defaultType );
292 return _make_error("parameter *type* must be specified")
293 if ( !defined $type );
294 my @unknownTypes = grep( !/area|line|bar|arealine|combo|scatter/, ($type) );
295
296 # Check for a valid type
297 return _make_error("Invalid value of *$type* for parameter *type* ")
298 if (@unknownTypes);
299 $chart->setType($type);
300
301 # See if the parameter 'subtype' (old name 'datatype') is available.
302 my $dataType = $this->_Parameters->getParameter( "datatype", undef );
303 my $subType = $this->_Parameters->getParameter( "subtype", undef );
304 return _make_error(
305 "paramters *datatype* and *subtype* can't both be specified")
306 if ( defined $dataType && defined $subType );
307 $subType = $dataType if ( defined $dataType );
308 if ( defined $subType ) {
309 my @subTypes = split( /[\s,]+/, $subType );
310
311 # Check for valid subtypes
312 my @unknownSubTypes =
313 grep( !/area|line|point|pline|scatter|bar/, @subTypes );
314 return _make_error(
315 "unknown subtypes: " . join( ", ", @unknownSubTypes ) )
316 if (@unknownSubTypes);
317
318 # Now check to make sure that the subtypes specified are valid for the
319 # specified type.
320 ### Check 'line' type
321 if ( $type eq "line" ) {
322 @unknownSubTypes = grep( !/line|point|pline/, @subTypes );
323 return _make_error( "unsupported subtypes: "
324 . join( ", ", @unknownSubTypes )
325 . " for type line" )
326 if (@unknownSubTypes);
327 }
328
329 ### Check 'area' type
330 if ( $type eq "area" ) {
331 @unknownSubTypes = grep( !/area/, @subTypes );
332 return _make_error( "unsupported subtypes: "
333 . join( ", ", @unknownSubTypes )
334 . " for type area" )
335 if (@unknownSubTypes);
336 }
337
338 ### Check 'scatter' type
339 if ( $type eq "scatter" ) {
340 @unknownSubTypes = grep( !/area|line|point|pline|bar/, @subTypes );
341 return _make_error( "unsupported subtypes: "
342 . join( ", ", @unknownSubTypes )
343 . " for type scatter" )
344 if (@unknownSubTypes);
345 }
346
347 ### Check 'combo' type
348 if ( $type eq "combo" ) {
349 @unknownSubTypes = grep( !/area|line|point|pline|bar/, @subTypes );
350 return _make_error( "unsupported subtypes: "
351 . join( ", ", @unknownSubTypes )
352 . " for type combo" )
353 if (@unknownSubTypes);
354 }
355
356 # All OK so set the subtype.
357 $chart->setSubTypes(@subTypes);
358 }
359
360 # See if the parameter 'scale' is available.
361 my $scale = $this->_Parameters->getParameter( "scale", $defaultScale );
362 if ( $scale ne "base10" and $scale ne "linear" and $scale ne "semilog" ) {
363 return _make_error("Invalid value of *$scale* for parameter *scale* ");
364 }
365 $chart->setScale($scale);
366
367 # See if the parameter 'name' is available. This is a required
368 # parameter. If it is missing, then generate an error message.
369 my $name = $this->_Parameters->getParameter( "name", undef );
370 return _make_error("parameter *name* must be specified")
371 if ( !defined $name );
372
373 # See if the parameter 'web' is available. If not, then default to
374 # looking for tables in the current web.
375 my $inWeb = $this->_Parameters->getParameter( "web", $web );
376
377 # See if the parameter 'topic' is available. If not, then default to
378 # looking for tables in the current topic.
379 my $inTopic = $this->_Parameters->getParameter( "topic", $topic );
380
381 # Before we parse any further parameters, lets get the contents of the
382 # specified web/topic.
383 if ( !$this->_setTopicContents( $inWeb, $inTopic ) ) {
384 return _make_error(
385 "Error retrieving Foswiki topic $inWeb<nop>.$inTopic");
386 }
387
388 # Determine which table the user wants to chart
389 my $tableName = $this->_Parameters->getParameter( "table", 1 );
390
391 # Verify that the table name is valid.
392 if ( !$this->_tables->checkTableExists($tableName) ) {
393 return _make_error(
394"parameter *table* is not valid table; the specified table '$tableName' does not exist."
395 );
396 }
397
398 # See if the parameter 'title' is available.
399 $chart->setTitle( $this->_Parameters->getParameter( "title", undef ) );
400
401 # See if the parameter 'xlabel' is available.
402 $chart->setXlabel( $this->_Parameters->getParameter( "xlabel", undef ) );
403
404 # See if the parameter 'ylabel' is available.
405 $chart->setYlabel( $this->_Parameters->getParameter( "ylabel", undef ) );
406
407 # See if the parameter 'data' is available. This is a required
408 # parameter. If it is missing, then generate an error message.
409 my $data = $this->_Parameters->getParameter( "data", undef );
410 return _make_error("parameter *data* must be specified")
411 if ( !defined $data );
412
413 # See if the parameter 'xaxis' is available.
414 my $xAxis = $this->_Parameters->getParameter( "xaxis", undef );
415
416 # See if the parameter 'yaxis' is available.
417 my $yAxis = $this->_Parameters->getParameter( "yaxis", "off" );
418 $chart->setYaxis($yAxis);
419
420 # See if the parameter 'ytic' is available.
421 my $yTic = $this->_Parameters->getParameter( "ytics", -1 );
422 $chart->setNumYTics($yTic);
423
424 # See if the parameter 'xaxisangle' is available.
425 my $xaxisangle = $this->_Parameters->getParameter( "xaxisangle", 0 );
426 $chart->setXaxisAngle($xaxisangle);
427
428 # See if the parameter 'ymin' is available.
429 my $yMin = $this->_Parameters->getParameter( "ymin", undef );
430 if ( defined $yMin ) {
431 if ( $scale eq "semilog" && $yMin <= 0 ) {
432 return _make_error(
433"user set ymin=$yMin is &lt;= 0 which is not valid when scale=semilog"
434 );
435 }
436 }
437 $chart->setYmin($yMin);
438
439 # See if the parameter 'ymax' is available.
440 my $yMax = $this->_Parameters->getParameter( "ymax", undef );
441 if ( defined $yMax ) {
442 if ( $scale eq "semilog" && $yMax <= 0 ) {
443 return _make_error(
444"user set ymax=$yMax is &lt;= 0 which is not valid when scale=semilog"
445 );
446 }
447 }
448 $chart->setYmax($yMax);
449
450 # See if the parameter 'numygrids' is available.
451 $chart->setNumYGrids(
452 $this->_Parameters->getParameter( "numygrids", $defaultNumYGrids ) );
453
454 # See if the parameter 'numxgrids' is available.
455 my $numxgrids = $this->_Parameters->getParameter( "numxgrids", 10 );
456 $chart->setNumXGrids($numxgrids);
457
458 # See if the parameter 'xgrid' is available.
459 my $xGrid = $this->_Parameters->getParameter( "xgrid", "dot" );
460 $chart->setXgrid($xGrid);
461
462 # See if the parameter 'ygrid' is available.
463 my $yGrid = $this->_Parameters->getParameter( "ygrid", "dot" );
464 $chart->setYgrid($yGrid);
465
466 # See if the parameter 'datalabel' is available.
467 my $dataLabels = $this->_Parameters->getParameter( "datalabel", "off" );
468 $chart->setDataLabels( split( /[\s,]+/, $dataLabels ) )
469 if ( defined $dataLabels );
470
471 # See if the parameter 'legend' is available.
472 my $legend = $this->_Parameters->getParameter( "legend", undef );
473
474 # Get the chart width and height
475 $chart->setImageWidth(
476 $this->_Parameters->getParameter( "width", $defaultWidth ) );
477 $chart->setImageHeight(
478 $this->_Parameters->getParameter( "height", $defaultHeight ) );
479
480 # Get the chart IMG 'alt' text.
481 my $alt = $this->_Parameters->getParameter( "alt", "" );
482
483 # Get the chart 'bgcolor' color.
484 my $bgcolor =
485 $this->_Parameters->getParameter( "bgcolor", $defaultBGcolor );
486 $chart->setBGcolor( split( /[\s,]+/, $bgcolor ) );
487
488 # Set line/area colors. If the parameter 'colors' is defined, then the
489 # chart will be made with the user specified colors. Otherwise the
490 # chart will be made with the default colors, and then it will depend
491 # on if an 'area' or 'line' is being drawn which will determine which
492 # set of colors to use.
493 $chart->setLineColors(@defaultLineColors);
494 $chart->setAreaColors(@defaultAreaColors);
495
496 # See if the parameter 'colors' is available.
497 my $colors = $this->_Parameters->getParameter( "colors", undef );
498 $chart->setColors( split( /[\s,]+/, $colors ) ) if ( defined $colors );
499
500 # Get the chart grid color.
501 my $gridColor =
502 $this->_Parameters->getParameter( "gridcolor", $defaultGridColor );
503 $chart->setGridColor( split( /[\s,]+/, $gridColor ) );
504
505 # See if the parameter 'defaultdata' is available.
506 my $DataValueDefault =
507 $this->_Parameters->getParameter( "defaultdata", $defaultDataValue );
508 $DataValueDefault = '' if ( $DataValueDefault eq "none" );
509 $chart->setDefaultDataValue($DataValueDefault);
510
511 # Get the filename in which to create the graphics file.
512 my $filename = _make_filename( $type, $name );
513 $chart->setAttachmentName( $web, $topic, $filename );
514
515 # Validate the legend data making sure it only specifies a single row
516 # or a single column.
517 my @legend;
518 if ($legend) {
519 my $cnt = my @d = $this->_tables->getData( $tableName, $legend );
520 if ( $cnt > 1 ) {
521 @d = Foswiki::Plugins::ChartPlugin::Table::transpose(@d);
522 $cnt = scalar(@d);
523 }
524 if ( $cnt > 1 ) {
525 return _make_error(
526 "parameter *legend* specifies multiple ($cnt) rows.");
527 }
528 if ( $cnt == 0 ) {
529 return _make_error(
530 "parameter *legend* contains an invalid value '$legend'.");
531 }
532 @legend = @{ $d[0] };
533
534 #die Data::Dumper->Dump([\@legend]);
535 $chart->setLegend(@legend);
536 }
537
538 # If the user specified an X axis range, then extract from the X axis
539 # data the starting and ending row/columns. This defines whether the
540 # data is row ordered or column ordered. If there is no X axis
541 # information specified, then assume that the data is in column order.
542 my $columnOrdered = 0;
543 my $rowOrdered = 0;
544 if ( defined($xAxis) ) {
545 my ( $xAxisRows, $xAxisColumns ) =
546 $this->_tables->getRowColumnCount( $tableName, $xAxis );
547 return _make_error("parameter *xaxis* value of '$xAxis' is not valid")
548 if ( !defined($xAxisRows) );
549 if ( abs($xAxisRows) > 1 ) {
550 if ( $xAxisColumns > 1 ) {
551 return _make_error(
552"parameter *xaxis* specifies multiple (${xAxisRows}X$xAxisColumns) rows and columns."
553 );
554 }
555 $columnOrdered = 1;
556 }
557 else {
558 $rowOrdered = 1;
559 }
560 my @d = $this->_tables->getData( $tableName, $xAxis, $columnOrdered );
561 return _make_error(
562 "no X axis data found in specified area of table [$xAxis]")
563 if ( !@d );
564 $chart->setXaxis( @{ $d[0] } );
565 }
566 else {
567 $columnOrdered = 1;
568 }
569
570# Validate the data range as valid
571#my ($dataRows, $dataColumns) =
572# $this->_tables->getRowColumnCount($tableName, $data);
573#return _make_error("parameter *data* value of '$data' is not valid") if (! defined($dataRows));
574
575 # Get the actual area data.
576 my @data = ();
577 @data = $this->_tables->getData( $tableName, $data, $columnOrdered );
578
579 # Validate that there is real data returned.
580 return _make_error("no data found in specified area of table [$data]")
581 if ( !@data );
582
583 #my @ranges = $this->_tables->getTableRanges($tableName, $data);
584 #die $data, ' ', Data::Dumper->Dump([\@ranges]);
585 $yMin = $chart->setData(@data);
586
587 # If scale=semilog and any data is <= 0, then error
588 if ( $scale eq "semilog" && $yMin <= 0 ) {
589 return _make_error("data ($yMin) &lt;= 0 not valid when scale=semilog");
590 }
591
592 # Make sure that there are enough legends to go with all specified
593 # data sets (if legends were specified)
594 if ($legend) {
595 my $numLegends = @legend;
596 my $numDataSets = @data;
597 if ( $numDataSets != $numLegends ) {
598 return _make_error(
599"parameter *legend* contains an invalid value '$legend' since it specifies $numLegends legends and there are $numDataSets data sets."
600 );
601 }
602 }
603
604 # Set the default point size
605 $chart->setPointSize(
606 $this->_Parameters->getParameter( "pointsize", $defaultPointSize ) );
607
608 # Set the default line width
609 $chart->setLineWidth(
610 $this->_Parameters->getParameter( "linewidth", $defaultLineWidth ) );
611
612 # Set default bar graph values
613 $chart->setBarLeadingSpace($defaultBarLeadingSpace);
614 $chart->setBarTrailingSpace($defaultBarTrailingSpace);
615 $chart->setBarSpace($defaultBarSpace);
616
617 # Create the actual chart.
618 my $err = $chart->makeChart();
619 return _make_error("chart error: name=$name: $err") if ($err);
620
621 # Get remaining parameters and pass to <img ... />
622 my $options = "";
623 my %parameters = $this->_Parameters->getAllParameters();
624 foreach my $k ( keys %parameters ) {
625 $options .= "$k=\"$parameters{$k}\" ";
626 }
627
628 # Make a unique value to append to the image name that forces a web
629 # browser to reload the image each time the image is viewed. This is
630 # done so changes to the values used to generate the chart, or the
631 # chart layout specifications, are seen immediately and not ignored
632 # because the browser has cached the image. Eventually a hash value
633 # should be used such that the user's browser CAN cache the image iff
634 # none of the values/parameters used in creating the chart have changed.
635 my $timestamp = time();
636 return
637"<img src=\"%ATTACHURL%/$filename?t=$timestamp\" alt=\"$alt\" $options />";
638}
639
640# The following is really for debugging and timing purposes and is not an
641# advertised interface. This routine basically creates a number of charts
642# and (roughly) times how long it took to create them.
643# Usage: %CHART_TIMER{### <parameters>}%
644# where ### is the number of charts to create and <parameters> are valid
645# %CHART% parameters ('name' is overridden by the timer so is ignored if
646# specified in <parameters>
647sub _timeit {
648 my ( $this, $loops, $params, $topic, $web ) = @_;
649 my $removeFiles = 0; # Flag on whether to remove the test graphics or not
650 my $start_time = time();
651 for ( my $i = 0 ; $i < $loops ; $i++ ) {
652 my $str = "$params name=\"timeit_$i\"";
653 $this->_makeChart( $str, $topic, $web );
654 }
655 my $finish_time = time();
656 my $diff = $finish_time - $start_time;
657
658 # Remove the just created test files.
659 if ($removeFiles) {
660 for ( my $i = 0 ; $i < $loops ; $i++ ) {
661 my ( $dir, $filename ) =
662 _make_filename( "area", "timeit_$i", $topic, $web );
663 unlink("$dir/$filename");
664 }
665 }
666 return "To make $loops charts it (roughly) took $diff seconds.<BR>";
667}
668
669# =========================
670
# spent 353µs within Foswiki::Plugins::ChartPlugin::commonTagsHandler which was called 108 times, avg 3µs/call: # 108 times (353µs+0s) by Foswiki::Plugin::invoke at line 310 of /var/www/foswikidev/core/lib/Foswiki/Plugin.pm, avg 3µs/call
sub commonTagsHandler {
671 ### my ( $text ) = @_; # do not uncomment, use $_[0] instead
67210832µs my $topic = $_[1];
67310818µs my $web = $_[2];
674
675 # If no %CHART%s on this page, then there is nothing to do so just
676 # return.
677108279µs if ( $_[0] !~ m/%CHART.*{.*}%/ ) {
678
679 # nothing to do
680 return;
681 }
682 _init_defaults();
683 my $chart = ChartPlugin( $topic, $web, $_[0] );
684 $_[0] =~ s/%CHART{(.*?)}%/$chart->_makeChart($1, $topic, $web)/eog;
685 $_[0] =~
686 s/%CHART_TIMER{(\d+) (.*)}%/$chart->_timeit($1, $2, $topic, $web)/eog;
687}
688
68914µs1;