1000)) { // Invalid width. return ERROR_INVALID_WIDTH; } if ((!ctype_digit( (string) $settings['height'] )) || ($settings['height'] < 1) || ($settings['height'] > 1000) ) { // Invalid height. return ERROR_INVALID_HEIGHT; } if (!in_array($settings['type'], array('lc', 'lxy', 'bhs', 'bvs', 'bhg', 'bvg', 'p', 'p3', 'v', 's')) ) { // Invalid chart type. return ERROR_INVALID_TYPE; } if (($settings['width'] * $settings['height']) >= 300000) { // The chart is too large. return ERROR_CHART_TOO_LARGE; } $url = 'http://chart.apis.google.com/chart?'. 'chs='. $settings['width'] .'x'. $settings['height'] . '&cht='. $settings['type'] . '&chd=e:'; if ($settings['type'] == 'lc') { // For a normal line chart, // quickly go through to find the maximum value to calculate the divider. $i = 0; foreach ($data as $val1) { if (is_array($val1)) { $maxVal[$i] = max($val1); ++$i; } else { $maxVal[0] = $val1; } } if ($float) { $divider = 4095 / (max($maxVal) * 10); } else { $divider = 4095 / max($maxVal); } } foreach ($data as $val1Index => $val1) { if (is_array($val1)) { // Multiple data sets. $single_data_set = false; ///< used when filling area under the graph if ($settings['type'] != 'lc') { // For any type other than lc, calculate the divider here. $divider = 4095 / max($val1); } foreach ($val1 as $val2Index => $val2) { // No need to check if it's an if ($float) { // array again. $url .= _googlechart_encode( (int)($val2 * 10 * $divider) ); } else { $url .= _googlechart_encode( (int)($val2 * $divider) ); } // Shape markers for that datapoint. $url_chm .= _googlechart_shape_markers( $val1Index, $val2Index, $settings); } $url .= ','; } else { // Single data set. $single_data_set = true; $divider = 4095 / max($data); if ($float) { $url .= _googlechart_encode( (int)($val1 * 10 * $divider) ); } else { $url .= _googlechart_encode( (int)($val1 * $divider) ); } // Shape markers for that datapoint. $url_chm .= _googlechart_shape_markers(0, $val1Index, $settings); } } $markers_defined = false; if ($url_chm != '') { $url .= '&chm='. rtrim($url_chm, '|'); $markers_defined = true; } // Range markers. if ((is_array($settings['range']['direction'])) && (is_array($settings['range']['start'])) && (is_array($settings['range']['end']))) { // Only if all these settings are $url_chm = ''; // defined. foreach ($settings['range']['direction'] as $key => $dir) { switch ($dir) { case 'v': // Vertical marker. $url_chm_dir = 'R'; break; case 'h': // Horizontal marker. $url_chm_dir = 'r'; break; } if (_googlechart_is_valid_color_code($settings['range']['color'][$key])) { $url_chm_color = $settings['range']['color'][$key]; } else { // If this is not a valid color, default it to light blue. $url_chm_color = 'eeeeff'; } $url_chm .= $url_chm_dir .','. $url_chm_color .',0,'. $settings['range']['start'][$key] .','. $settings['range']['end'][$key] .'|'; } if ($url_chm != '') { if (!$markers_defined) { $url .= '&chm='; } else { $url .= '|'; } $url .= rtrim($url_chm, '|'); $markers_defined = true; } } // Fill area. $url_chm = ''; if ($single_data_set) { // For single data set, just fill the area under the // graph. if (_googlechart_is_valid_color_code($settings['fill'])) { $url_chm = 'B,'. $settings['fill'] .',0,0,0|'; } } else { // For multiple data sets, fill areas in between the lines. if (is_array($settings['fill'])) { foreach ($settings['fill'] as $top => $topVal) { foreach ($topVal as $bottom => $color) { if (_googlechart_is_valid_color_code($color)) { $url_chm .= 'b,'. $color .','. $top .','. $bottom .',0|'; } } } } } if ($url_chm != '') { if (!$markers_defined) { $url .= '&chm='; } else { $url .= '|'; } $url .= rtrim($url_chm, '|'); $markers_defined = true; } // Bar width / space between bars. if (isset($settings['barwidth'])) { $url .= '&chbh='. $settings['barwidth']; if (isset($settings['barspace'])) { $url .= ','. $settings['barspace']; } } // Data set colors. if (isset($settings['datasetcolor'])) { // Are codes defined at all? if (is_array($settings['datasetcolor'])) { // Codes for several sets. $url .= '&chco='; $i = 0; foreach ($settings['datasetcolor'] as $key => $color) { if (_googlechart_is_valid_color_code($color)) { if ($key != $i) { // If a color declaration was omitted, a for (; $i < $key; ++$i) { // nice orange will be defaulted for each $url .= 'ff9900,'; // of the omitted sets. } $i = $key; } $url .= $color .','; // Append the current color ++$i; } } } } $url = rtrim($url, ','); // Data set line styles if (isset($settings['datasetstyle'])) { if (is_array($settings['datasetstyle'])) { $i = 0; foreach ($settings['datasetstyle'] as $key => $style) { if ($key != $i) { // If a declaration was omited, go for some defaults for (; $i < $key; ++$i) { // For each of the omitted sets $url_chls .= '1.5,1,0|'; } $i = $key; } if (!isset($style['thick'])) { $url_chls .= '1.5'; } else { $url_chls .= $style['thick']; } if (!isset($style['line'])) { $url_chls .= ',1'; } else { $url_chls .= ','. $style['line']; } if (!isset($style['blank'])) { $url_chls .= ',0'; } else { $url_chls .= ','. $style['blank']; } $url_chls .= '|'; ++$i; } $url .= '&chls='. rtrim($url_chls, '|'); } } // Chart and background fill. $declared = false; for ($counter = 0; $counter <= 1; ++$counter) { switch ($counter) { case 0: // Background fill first, $bgOrCFull = 'background'; $bgOrCShort = 'bg'; break; case 1: // and then chart fill. $bgOrCFull = 'chart'; $bgOrCShort = 'c'; break; } $success = false; ///< stores whether at least one color was added if ($settings[$bgOrCFull .'filltype'] == 's') { // Solid fill if (_googlechart_is_valid_color_code( $settings[$bgOrCFull .'fillcolor'])) { $url_add .= 's,'. $settings[$bgOrCFull .'fillcolor']; $success = true; } } elseif ($settings[$bgOrCFull .'filltype'] == 'lg') { // Linear gradient fill $url_add = 'lg,'; if ( (0 <= (int)$settings[$bgOrCFull .'fillangle']) && ((int)$settings[$bgOrCFull .'fillangle'] <= 90)) {//Is angle 0 - 90? $url_add .= $settings[$bgOrCFull .'fillangle']; if (is_array($settings[$bgOrCFull .'fillcolor'])) { // Array of colors. $i = 0; foreach ($settings[$bgOrCFull .'fillcolor'] as $color) { if (_googlechart_is_valid_color_code($color)) { if ( (isset($settings[$bgOrCFull .'filloffset'][$i])) && (0 <= (float)$settings[$bgOrCFull .'filloffset'][$i]) && ((float)$settings[$bgOrCFull .'filloffset'][$i] <= 1)) { $url_add .= ','. $color . ','. $settings[$bgOrCFull .'filloffset'][$i]; $success = true; // A color was added. } } ++$i; } } } } elseif ($settings[$bgOrCFull .'filltype'] == 'ls') { // Linear stripes fill $url_add = 'ls,'; if ( (0 <= (int)$settings[$bgOrCFull .'fillangle']) && ((int)$settings[$bgOrCFull .'fillangle'] <= 90)) {//Is angle 0 - 90? $url_add .= $settings[$bgOrCFull .'fillangle']; if (is_array($settings[$bgOrCFull .'fillcolor'])) { // Array of colors $i = 0; foreach ($settings[$bgOrCFull .'fillcolor'] as $color) { if (_googlechart_is_valid_color_code($color)) { if ( (isset($settings[$bgOrCFull .'fillwidth'][$i])) && (0 <= (float)$settings[$bgOrCFull .'fillwidth'][$i]) && ((float)$settings[$bgOrCFull .'fillwidth'][$i] <= 1)) { $url_add .= ','. $color .',' . $settings[$bgOrCFull .'fillwidth'][$i]; $success = true; // A color was added. } } ++$i; } } } } if ($success) { // If at least one color was added. if ($declared) { // If a previous (eg. background) definition was there, we can $url .= '|'. $bgOrCShort .','. $url_add; // add it to the final url } else { // There was no declaration, so make one. $url .= '&chf='. $bgOrCShort .','. $url_add; $declared = true; } } } // Labels // Chart title if (isset($settings['title'])) { $url .= '&chtt='. preg_replace("/\\%0D\\%0A|\\%0A|\\%0D/", '|', urlencode($settings['title'])); $colorDefined = false; ///< useful if only size is set if (_googlechart_is_valid_color_code($settings['titlecolor'])) { $colorDefined = true; $url .= '&chts='. $settings['titlecolor']; } if (ctype_digit($settings['titlesize'])) { if ($colorDefined) { $url .= ','. $settings['titlesize']; } else { $url .= '&chts=000000,'. $settings['titlesize']; } } } // Legend/pie chart labels if (is_array($settings['label'])) { $url .= '&'; if (($settings['type'] == 'p') || ($settings['type'] == 'p3')) { //Pie chart // Add a pie chart label declaration. $url .= 'chl='; } else { // Other chart type // Add a legend declaration. $url .= 'chdl='; } foreach ($settings['label'] as $key => $label) { $url .= $label; if (count($settings['label']) > ($key + 1)) { $url .= '|'; } } } // Axis labels. if (is_array($settings['axis'])) { $url_chxt = ''; $url_chxl = ''; $url_chxp = ''; $url_chxr = ''; $url_chxs = ''; $i = 0; foreach ($settings['axis'] as $axis => $values) { if ( ($axis == 'x') || ($axis == 't') || ($axis == 'y') || ($axis == 'r') ) { if (is_array($values)) { foreach ($values as $key => $value) { $url_chxt .= $axis; $url_chxt .= ','; if (isset($value)) { $url_chxl .= $i .':|'; if (is_array($value)) { $url_chxl .= implode('|', $value) .'|'; if (isset($settings['axisposition'][$axis][$key])) { $url_chxp .= $i .','; if (is_array($settings['axisposition'][$axis][$key])) { $url_chxp .= implode(',', $settings['axisposition'][$axis][$key]) .'|'; } else { $url_chxp .= $settings['axisposition'][$axis][$key] .'|'; } } } else { $url_chxl .= $value .'|'; if (isset($settings['axisposition'][$axis][$key])) { $url_chxp .= $i .','; $url_chxp .= $settings['axisposition'][$axis][$key] .'|'; } } if ((isset($settings['axisrange'][$axis][$key]['start'])) && (isset($settings['axisrange'][$axis][$key]['end']))) { $url_chxr .= $i .',' . $settings['axisrange'][$axis][$key]['start'] .',' . $settings['axisrange'][$axis][$key]['end'] .'|'; } $url_chxs_color = $settings['axiscolor'][$axis][$key]; $url_chxs_size = $settings['axissize'][$axis][$key]; switch ($settings['axisalign'][$axis][$key]) { case 'l': // Left align $url_chxs_align = '-1'; break; case 'c': // Centre align $url_chxs_align = '0'; break; case 'r': // Right align $url_chxs_align = '1'; break; } if (!isset($url_chxs_color)) { // If the color is not set, $url_chxs_color = '666666'; // default it to grey. } if (!isset($url_chxs_size)) { // If the size is not set, $url_chxs_size = '11.5'; // default it to 11.5. } $url_chxs_ = $i .','. $url_chxs_color .','. $url_chxs_size; if (!isset($url_chxs_align)) { // If the alignment is not present, $url_chxs_ .= '|'; // just omit the unneeded declaration. } else { $url_chxs_ .= ','. $url_chxs_align .'|'; } if ($url_chxs_ != ($i .',666666,11.5|')) { //If it's not just all $url_chxs .= $url_chxs_; // defaults then append it to the url. } ++$i; } } } } } // Check each declaration, and append it to the url if not empty. if ($url_chxt != '') { $url .= '&chxt='. rtrim($url_chxt, ','); } if ($url_chxl != '') { $url .= '&chxl='. rtrim($url_chxl, '|'); } if ($url_chxp != '') { $url .= '&chxp='. rtrim($url_chxp, '|'); } if ($url_chxr != '') { $url .= '&chxr='. rtrim($url_chxr, '|'); } if ($url_chxs != '') { $url .= '&chxs='. rtrim($url_chxs, '|'); } } // Grid lines. if (is_array($settings['grid'])) { if (isset($settings['grid']['xstep'])) { $url .= '&chg='. $settings['grid']['xstep']; } else { // If xstep is not defined, make every 1st level label of x axis if (isset($settings['axis']['x'][0])) { // where the gridlines appear. $count = count($settings['axis']['x'][0]) - 1; if ($count == 0) { // If there is only one label on x axis $count = 10000; // make 100/count very small so it is rounded up to 0. } $url .= '&chg='. number_format(100 / $count, 1, '.', ''); } else { // If that also fails, make no x-axis gridlines whatsoever $url .= '&chg=100'; } } if (isset($settings['grid']['ystep'])) { $url .= ','. $settings['grid']['ystep']; } else { // If ystep is not defined, make every 1st level label of y axis if (isset($settings['axis']['y'][0])) { // where the gridlines appear. $count = count($settings['axis']['y'][0]) - 1; if ($count == 0) { // If there is only one label on y axis, $count = 10000; // make 100/count very small so it is rounded up to 0. } $url .= ','. number_format(100 / $count, 1, '.', ''); } else { // If that also fails, make no y-axis gridlines whatsoever $url .= ',100'; } } $grid_defined = true; } // Grid line styles if (is_array($settings['gridstyle'])) { if ($grid_defined) { // Don't bother if there are no grids defined if ( (isset($settings['gridstyle']['line'])) && // Only add if all of the (isset($settings['gridstyle']['blank'])) ) { // settings are present. $url .= ','. $settings['gridstyle']['line'] . ','. $settings['gridstyle']['blank']; } } } // Return the whole resultant url. return $url; }