%PDF- %PDF-
| Direktori : /home/bitrix/www/bitrix/components/bitrix/report.view/templates/admin/ |
| Current File : //home/bitrix/www/bitrix/components/bitrix/report.view/templates/admin/graph.php |
<?php
require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include.php");
require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/tools.php");
require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/img.php");
if (!check_bitrix_sessid()) exit;
Bitrix\Main\Localization\Loc::loadMessages(__FILE__);
function checkPostChartData(&$postData, $chartXValueTypes, $chartTypes)
{
$err = 0;
// check meta
$columnYValueTypes = array();
$nColumns = 0;
if (isset($postData['chartData']) && is_array($postData['chartData']))
{
$chartData = &$postData['chartData'];
$chartTypeIds = array();
foreach ($chartTypes as &$chartTypeInfo) $chartTypeIds[] = $chartTypeInfo['id'];
$chartTypesIndexes = array_flip($chartTypeIds);
$columnYValueTypes = $chartTypes[$chartTypesIndexes[$chartData['type']]]['value_types'];
if (isset($chartData['type']) && in_array($chartData['type'], $chartTypeIds))
{
if (isset($chartData['columnTypes']) && is_array($chartData['columnTypes']))
{
$nColumns = count($chartData['columnTypes']);
if ($nColumns >= 2)
{
if ($chartData['type'] == 'pie' && $nColumns != 2) $err = 5;
else
{
foreach ($chartData['columnTypes'] as $columnIndex => $columnType)
{
if (is_int($columnIndex) && $columnIndex >= 0)
{
if ($columnIndex === 0)
{
if (!in_array($columnType, $chartXValueTypes)) $err = 7;
}
else
{
if (!in_array($columnType, $columnYValueTypes)) $err = 8;
}
}
else $err = 6;
if ($err !== 0) break;
}
}
}
else $err = 4;
}
else $err = 3;
}
else $err = 2;
}
else $err = 1;
// check data
if ($err === 0)
{
if (isset($chartData['data']) && is_array($chartData['data']))
{
foreach ($chartData['data'] as $rowIndex => &$dataRow)
{
if (is_int($rowIndex) && $rowIndex >= 0)
{
if (is_array($dataRow))
{
$nDataColumns = count($dataRow);
if ($nDataColumns === $nColumns)
{
foreach ($dataRow as $columnIndex => &$dataValue)
{
if (is_int($columnIndex) && $columnIndex >= 0)
{
// convert type of value
switch ($chartData['columnTypes'][$columnIndex])
{
case 'boolean':
$dataValue = ($dataValue) ? true : false;
break;
case 'date':
case 'datetime':
if (!empty($dataValue))
{
if (!CheckDateTime($dataValue, CSite::GetDateFormat('SHORT'))) $err = 15;
}
break;
case 'float':
if (is_string($dataValue)) $dataValue = str_replace(' ', '', $dataValue);
$dataValue = (float)$dataValue;
break;
case 'integer':
if (is_string($dataValue)) $dataValue = str_replace(' ', '', $dataValue);
$dataValue = (int)$dataValue;
break;
case 'string':
case 'text':
case 'enum':
case 'file':
case 'disk_file':
case 'employee':
case 'crm':
case 'crm_status':
case 'iblock_element':
case 'iblock_section':
$dataValue = (string)$dataValue;
break;
default:
$err = 14;
}
}
else $err = 13;
if ($err !== 0) break;
}
}
else $err = 12;
}
else $err = 11;
}
else $err = 10;
if ($err !== 0) break;
}
}
else $err = 9;
}
return $err;
}
$chartXValueTypes = array('boolean', 'date', 'datetime', 'float', 'integer', 'string', 'text', 'enum', 'file',
'disk_file', 'employee', 'crm', 'crm_status', 'iblock_element', 'iblock_section');
// <editor-fold defaultstate="collapsed" desc="chart types">
$chartTypes = array(
array('id' => 'line', 'name' => GetMessage('REPORT_CHART_TYPE_LINE'), 'value_types' => array(
/*'boolean', 'date', 'datetime', */
'float', 'integer'/* , 'string', 'text', 'enum', 'file', 'disk_file', 'employee', 'crm', 'crm_status',
'iblock_element', 'iblock_section'*/)),
array('id' => 'bar', 'name' => GetMessage('REPORT_CHART_TYPE_BAR'), 'value_types' => array(
/*'boolean', 'date', 'datetime', */
'float', 'integer'/* , 'string', 'text', 'enum', 'file', 'disk_file', 'employee', 'crm', 'crm_status',
'iblock_element', 'iblock_section'*/)),
array('id' => 'pie', 'name' => GetMessage('REPORT_CHART_TYPE_PIE'), 'value_types' => array(
/*'boolean', 'date', 'datetime', */
'float', 'integer'/* , 'string', 'text', 'enum', 'file', 'disk_file', 'employee', 'crm', 'crm_status',
'iblock_element', 'iblock_section'*/)),
);
// </editor-fold>
CUtil::JSPostUnescape();
$errorCode = checkPostChartData($_POST, $chartXValueTypes, $chartTypes);
if ($errorCode === 0)
{
$chartData = &$_POST['chartData'];
// chart size
$minWidth = 192;
$minHeight = 120;
$maxWidth = 10000;
$maxHeight = 6250;
$baseColor = '6699CC';
$backgroundColor = 'FFFFFF';
if (isset($chartData['width']))
{
$width = intval($chartData['width']);
if ($width < $minWidth) $width = $minWidth;
if ($width > $maxWidth) $width = $maxWidth;
}
else $width = 670;
if (isset($chartData['height']))
{
$height = intval($chartData['height']);
if ($height < $minHeight) $height = $minHeight;
if ($height > $maxHeight) $height = $maxHeight;
}
else $height = 420;
if ($chartData['type'] === 'line')
{
if (count($chartData['data']) >= 2)
{
// <editor-fold defaultstate="collapsed" desc="prepare data for line chart">
$arXLabels = array();
$arXValues = array();
$arYValues = array();
$minX = null; $maxX = null;
$minY = null; $maxY = null;
$arYAll = array();
foreach ($chartData['data'] as $rowIndex => $dataRow)
{
foreach ($dataRow as $columnIndex => $dataValue)
{
if ($rowIndex === 0)
{
if ($columnIndex > 0) $arYValues[$columnIndex-1] = array();
}
if ($columnIndex === 0)
{
$arXLabels[$rowIndex] = $dataValue;
$arXValues[$rowIndex] = $rowIndex + 1;
if ($rowIndex === 0) $maxX = $minX = $arXValues[$rowIndex];
else
{
$minX = min($minX, $arXValues[$rowIndex]);
$maxX = max($maxX, $arXValues[$rowIndex]);
}
}
else
{
$arYAll[] = $arYValues[$columnIndex-1][$rowIndex] = $dataValue;
if ($rowIndex === 0 && $columnIndex === 1) $maxY = $minY = $dataValue;
else
{
$minY = min($minY, $dataValue);
$maxY = max($maxY, $dataValue);
}
}
}
}
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="paint line chart">
$imageHandle = $ImageHandle = CreateImageHandle($width, $height);
$arYNorm = GetArrayY($arYAll, $minY, $maxY);
$arrTTF_FONT = array(
'X' => array(
'FONT_PATH' => '/bitrix/components/bitrix/report.view/ttf/verdana.ttf',
'FONT_SIZE' => 8,
'FONT_SHIFT' => 12,
'FONT_BASE' => 3
),
'Y' => array(
'FONT_PATH' => '/bitrix/components/bitrix/report.view/ttf/verdana.ttf',
'FONT_SIZE' => 8,
'FONT_SHIFT' => 12,
'FONT_BASE' => 3
)
);
DrawCoordinatGrid($arXLabels, $arYNorm, $width, $height, $imageHandle,
$backgroundColor, 'B1B1B1', '000000', 10, 2, $arrTTF_FONT);
$nColors = count($arYValues);
$color = $baseColor;
$arLegendInfo = array();
foreach ($arYValues as $columnIndex => $arY)
{
$arLegendInfo[$columnIndex] = $color;
Graf($arXValues, $arY, $imageHandle, $minX, $maxX, $minY, $maxY, $color);
$color = GetNextRGB($color, $nColors);
}
// </editor-fold>
}
else $errorCode = 42; // At least two rows of values are required
}
else if ($chartData['type'] === 'bar')
{
if (count($chartData['data']) >= 2)
{
// <editor-fold defaultstate="collapsed" desc="prepare data for bar chart">
$arXLabels = array();
$arXValues = array();
$arData = array();
$minX = null; $maxX = null;
$minY = null; $maxY = null;
$arYAll = array();
$color = $baseColor;
$nColors = count($chartData['columnTypes']);
$arLegendInfo = array();
foreach ($chartData['data'] as $rowIndex => $dataRow)
{
$arData[$rowIndex] = array('DATA' => array(), 'COLORS' => array());
foreach ($dataRow as $columnIndex => $dataValue)
{
if ($columnIndex === 0)
{
$arXLabels[$rowIndex] = $dataValue;
$arXValues[$rowIndex] = $rowIndex + 1;
if ($rowIndex === 0)
{
$maxX = $minX = $arXValues[$rowIndex];
$arYAll[] = $maxY = $minY = 0;
}
else
{
$minX = min($minX, $arXValues[$rowIndex]);
$maxX = max($maxX, $arXValues[$rowIndex]);
}
$color = $baseColor;
}
else
{
$arYAll[] = $arData[$rowIndex]['DATA'][$columnIndex-1] = ($dataValue < 0) ? 0 : $dataValue;
$minY = min($minY, $dataValue);
$maxY = max($maxY, $dataValue);
$arData[$rowIndex]['COLORS'][$columnIndex-1][0] = $color;
if ($rowIndex === 0) $arLegendInfo[$columnIndex-1] = $color;
$color = GetNextRGB($color, $nColors);
}
}
}
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="paint bar diagram">
$imageHandle = $ImageHandle = CreateImageHandle($width, $height);
$arYNorm = GetArrayY($arYAll, $minY, $maxY);
$arrTTF_FONT = array(
'type' => 'bar',
'X' => array(
'FONT_PATH' => '/bitrix/components/bitrix/report.view/ttf/verdana.ttf',
'FONT_SIZE' => 8,
'FONT_SHIFT' => 12,
'FONT_BASE' => 3
),
'Y' => array(
'FONT_PATH' => '/bitrix/components/bitrix/report.view/ttf/verdana.ttf',
'FONT_SIZE' => 8,
'FONT_SHIFT' => 12,
'FONT_BASE' => 3
)
);
$gridInfo = DrawCoordinatGrid($arXLabels, $arYNorm, $width, $height, $imageHandle,
$backgroundColor, 'B1B1B1', '000000', 10, 2, $arrTTF_FONT);
Bar_Diagram($imageHandle, $arData, $minY, $maxY, $gridInfo);
// </editor-fold>
}
else $errorCode = 43; // At least one row of values is required
}
else if ($chartData['type'] === 'pie')
{
if (count($chartData['data']) >= 1)
{
// <editor-fold defaultstate="collapsed" desc="prepare data for pie chart">
$arConsolidated = array();
foreach ($chartData['data'] as $rowIndex => $dataRow)
{
$index = $dataRow[0];
$arConsolidated[$index] += $dataRow[1];
}
$sumAll = 0.0;
foreach ($arConsolidated as $k => $v)
{
if ($v <= 0.0) unset($arConsolidated[$k]);
else $sumAll += $v;
}
$arCounting = $arConsolidated;
$nValues = count($arCounting);
if ($nValues > 0)
{
$sumAllPrcnt = 0;
foreach ($arCounting as $k => $v)
{
$arCounting[$k] = $v * 100 / $sumAll;
$sumAllPrcnt =+ $arCounting[$k];
}
if (arsort($arCounting, SORT_NUMERIC))
{
$arTrifle = array();
$averageValuePrcnt = $sumAllPrcnt/$nValues;
$trifleFactor = max($averageValuePrcnt/50, 1.0);
$i = 0; $prcntCount = 0.0; $offset = 0;
foreach ($arCounting as $k => $v)
{
if ($v < $trifleFactor)
{
$offset = $i;
break;
}
else $prcntCount += $v;
$i++;
}
$sumTrifle = 0;
if ($offset > 0)
{
$arTrifle = array_slice($arCounting, $offset, null, true);
$arCounting = array_slice($arCounting, 0, $offset, true);
foreach (array_keys($arTrifle) as $k) $sumTrifle += $arConsolidated[$k];
}
if (round($prcntCount,2) < 100.0)
{
$arCounting['__trifle__'] = 100.0 - $prcntCount;
$arConsolidated['__trifle__'] = $sumTrifle;
$nValues++;
}
$arData = array();
$arLegendInfo = array();
$i = 0; $color = $baseColor;
foreach ($arCounting as $k => $v)
{
$arData[$i]['COUNTER'] = intval($v*100);
$arData[$i]['COLOR'] = $color;
$arLegendInfo[$i] = array(
'color' => $color,
'label' => CharsetConverter::ConvertCharset($k, LANG_CHARSET, 'UTF-8'),
'value' => $arConsolidated[$k],
'prcnt' => round($v,2)
);
$color = GetNextRGB($color, $nValues);
$i++;
}
}
else $errorCode = 46;
}
else $errorCode = 45;
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="paint pie diagram">
if ($errorCode === 0)
{
$diameter = min($width, $height);
$imageHandle = $ImageHandle = CreateImageHandle($diameter, $diameter);
Circular_Diagram($imageHandle, $arData, $backgroundColor, $diameter,
round($diameter/2), round($diameter/2));
$h = $diameter * 0.6;
$dh = 15;
$imageHandleTemp = CreateImageHandle($diameter, $h+$dh);
imagecopy($imageHandleTemp, $imageHandle, 0, 0, 0, ($diameter-$h)/2-$dh, $diameter, $h+$dh);
imagedestroy($imageHandle);
$imageHandle = $imageHandleTemp;
}
// </editor-fold>
}
else $errorCode = 44; // At least one value is required
}
else $errorCode = 41;
if ($errorCode === 0)
{
// <editor-fold defaultstate="collapsed" desc="render chart">
ob_start();
ShowImageHeader($imageHandle);
$img_base64 = base64_encode(ob_get_contents());
ob_end_clean();
if (substr($img_base64, 0, 5) === 'iVBOR')
{
$imageData = 'data:image/png;base64,'.PHP_EOL.chunk_split($img_base64);
$response = array(
'errorCode' => 0,
'errorMessage' => '',
'imageData' => $imageData,
'legendInfo' => $arLegendInfo
);
}
// </editor-fold>
}
}
if ($errorCode > 0)
{
$response = array(
'errorCode' => $errorCode,
'errorMessage' => CharsetConverter::ConvertCharset(
GetMessage('REPORT_CHART_ERR_'.sprintf('%02d', $errorCode)), LANG_CHARSET, 'UTF-8'
)
);
}
header("Content-type: application/x-www-form-urlencoded; charset=UTF-8");
echo CUtil::PhpToJSObject($response);
?>