Commit 7d732675 authored by Chenu Denis's avatar Chenu Denis

[feature] Allow to send xml in surveys

[feature] Allow diffrent XML by questions (using Question code)
parent edb24c27
......@@ -16,6 +16,7 @@ A plugin for LimeSurvey to generate graph from question in question answer of th
## Documentation
- Activate the plugin
- Create a long text question type
- Use the new attribute to set label and value by other question code
......@@ -40,8 +41,10 @@ There is 2 solution to show the graph :
### Adapt the graph
The generated graph have only one option in question setting : the total size of the grap in pixel.
You can update all the default setting with a xml file in template upload file directory.
The plugin read the default settings and, if exist, `graphQuestion.xml` file, you can replace default value here.
You can update all the default setting with a xml file in template upload file directory or survey uploaded files directory.
The plugin read the default settings and, if exist, `graphQuestion.xml` and `graphQuestionRadar.xml` file in template directory, you can replace default value here.
The plugin look at survey uploaded files to get `graphQuestion.xml`, `graphQuestionRadar.xml` and `graphQuestionQuestionCode.xml` (replaceQuestionCode by the question code of the graph question) and add it in graph configuration.
You can update color, font size and some margin for the graph wrapper and for the header. Font used use included LimeSurvey system to choose the best font for your language, you can set it globally in your config file.
......
......@@ -6,7 +6,7 @@
* @copyright 2017-2018 Denis Chenu <https://www.sondages.pro>
* @copyright 2017 Réseau en scène Languedoc-Roussillon <https://www.reseauenscene.fr>
* @license AGPL v3
* @version 2.0.1
* @version 2.1.0
*
* 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
......@@ -104,7 +104,6 @@ class generateGraphQuestion extends PluginBase {
default:
$step=0;
}
$aDatasGraphSources['questions'][$aDataGraphSource['qid']]['step']=$step;
}
$aDatasGraphSources['state']='step';
......@@ -141,9 +140,9 @@ class generateGraphQuestion extends PluginBase {
$title=LimeExpressionManager::ProcessString($title);
/* Get the size */
$oGenerateGraphSize=QuestionAttribute::model()->find('qid=:qid and attribute=:attribute',array(':qid'=>$this->getEvent()->get('qid'),':attribute'=>'generateGraphSize'));
$generateGraphSize=($oGenerateGraphSize)? $oGenerateGraphSize->value : 400;
$generateGraphSize=!empty($oGenerateGraphSize) ? $oGenerateGraphSize->value : 400;
/* Generate graph */
$base64image=$this->generateGraphRadar($aGraphData,flattenText($title,false,true),$generateGraphSize);
$base64image=$this->generateGraphRadar($oQuestion->title,$aGraphData,flattenText($title,false,true),$generateGraphSize);
$_SESSION["survey_{$surveyId}"][$answerSGQ]=$base64image;
$_SESSION["survey_{$surveyId}"]['startingValues'][$answerSGQ]=$base64image;
/* Maybe must save the value in DB */
......@@ -175,7 +174,7 @@ class generateGraphQuestion extends PluginBase {
$oGenerateGraphSize=QuestionAttribute::model()->find('qid=:qid and attribute=:attribute',array(':qid'=>$this->getEvent()->get('qid'),':attribute'=>'generateGraphSize'));
$generateGraphSize=($oGenerateGraphSize)? $oGenerateGraphSize->value : null;
$base64image=$this->generateGraphRadar($aGraphData,flattenText($title,false,true),$generateGraphSize);
$base64image=$this->generateGraphRadar($oEvent->get('code'),$aGraphData,flattenText($title,false,true),$generateGraphSize);
/* Fill the session value */
$oQuestion=Question::model()->find("qid=:qid",array(':qid'=>$this->getEvent()->get('qid')));
$answerSGQ=$oQuestion->sid."X".$oQuestion->gid."X".$oQuestion->qid;
......@@ -209,7 +208,7 @@ class generateGraphQuestion extends PluginBase {
* @var string $sTitle of the graph
* @return string
*/
public function generateGraphRadar($aData,$sTitle='',$size=null){
public function generateGraphRadar($qCode,$aData,$sTitle='',$size=null){
$aLabels=array_column($aData, 'label');
$aValues=array_column($aData, 'value');/* Only one serie currently */
......@@ -219,7 +218,6 @@ class generateGraphQuestion extends PluginBase {
$fileName="generateGraph".hash("md5",json_encode($aData));
require_once(__DIR__ . '/vendor/pChart2/class/pData.class.php');
require_once(__DIR__ . '/vendor/pChart2/class/pDraw.class.php');
require_once(__DIR__ . '/vendor/pChart2/class/pRadar.class.php');
require_once(__DIR__ . '/vendor/pChart2/class/pImage.class.php');
$DataSet = new pData();
$DataSet->addPoints($aValues,"Serie1");
......@@ -229,7 +227,7 @@ class generateGraphQuestion extends PluginBase {
$DataSet->setAbscissa("Labels");
/* TODO : get color and size via a css file in template */
$graphConfig=$this->_getGraphConfig();
$graphConfig=$this->_getGraphConfig($qCode);
$size=intval($size) ? intval($size) : $graphConfig['size'];
$headerSize=$graphConfig['header']['size'];
$borderSize=$graphConfig['border'];
......@@ -243,12 +241,15 @@ class generateGraphQuestion extends PluginBase {
$Image->setFontProperties(array("FontName"=>$font,"FontSize"=>$graphConfig['header']['fontsize']));
$Image->drawText(10,$headerSize-4,$sTitle,$graphConfig['header']['color']);
$Image->setFontProperties(array("FontName"=>$font,"FontSize"=>$graphConfig['fontsize'],"R"=>$graphConfig['color']['R'],"G"=>$graphConfig['color']['G'],"B"=>$graphConfig['color']['B']));
/* Here start the radar */
require_once(__DIR__ . '/vendor/pChart2/class/pRadar.class.php');
$Chart = new pRadar();
$Image->setGraphArea($margin['left'],$headerSize+$margin['top'],$size-$margin['right'],$size-$margin['bottom']);
$chartOptions=$graphConfig['chart'];
$chartOptions['Layout']=$this->_getFixedValue($chartOptions['Layout']);
$chartOptions['LabelPos']=$this->_getFixedValue($chartOptions['LabelPos']);
$Chart->drawRadar($Image,$DataSet,$chartOptions);
/* Here end the radar */
$path=App()->getRuntimePath().DIRECTORY_SEPARATOR.$fileName.".png";
$Image->Render($path);
......@@ -416,8 +417,8 @@ class generateGraphQuestion extends PluginBase {
}
}
if(version_compare(App()->getConfig('versionnumber'),'3.0.0','>=')) {
return $rootdir.DIRECTORY_SEPARATOR.'assets'.DIRECTORY_SEPARATOR.'fonts'.DIRECTORY_SEPARATOR.$chartfontfile;
}
return $rootdir.DIRECTORY_SEPARATOR.'assets'.DIRECTORY_SEPARATOR.'fonts'.DIRECTORY_SEPARATOR.$chartfontfile;
}
return $rootdir.DIRECTORY_SEPARATOR.'fonts'.DIRECTORY_SEPARATOR.$chartfontfile;
}
......@@ -426,24 +427,48 @@ class generateGraphQuestion extends PluginBase {
* Get the config for this chart for this survey/template
* @return array
*/
private function _getGraphConfig()
private function _getGraphConfig($qCode, $graphType = "Radar")
{
$oldValue = libxml_disable_entity_loader(true);
$xmlDefaultConfigFile = file_get_contents( realpath (__DIR__ . DIRECTORY_SEPARATOR.'graphQuestion.xml'));
$xmlDefaultConfig=simplexml_load_string($xmlDefaultConfigFile);
$aConfig=$aDefaultConfig=json_decode(json_encode($xmlDefaultConfig), true);
$aConfig = $this->_addXmlConfig(realpath(__DIR__ .DIRECTORY_SEPARATOR.'graphQuestion.xml'));
$aConfig = $this->_addXmlConfig(realpath(__DIR__ .DIRECTORY_SEPARATOR.'graphQuestion'.$graphType.'.xml'),$aConfig);
/* By template files */
$oTemplate = \Template::model()->getInstance(null, $this->_iSurveyId);
if(is_file($oTemplate->filesPath.'graphQuestion.xml')){
$xmlTemplateConfigFile=file_get_contents($oTemplate->filesPath.'/graphQuestion.xml');
$xmlTemplateConfig=simplexml_load_string($xmlTemplateConfigFile);
$aTemplateConfig=json_decode(json_encode($xmlTemplateConfig), true);
$aConfig=\CMap::mergeArray($aConfig,$aTemplateConfig);
$aConfig = $this->_addXmlConfig($oTemplate->filesPath.'graphQuestion.xml',$aConfig);
}
if(is_file($oTemplate->filesPath.'graphQuestion'.$graphType.'.xml')){
$aConfig = $this->_addXmlConfig($oTemplate->filesPath.'graphQuestion'.$graphType.'.xml',$aConfig);
}
/* By survey files */
$surveyDir = Yii::app()->getConfig('uploaddir')."/surveys/{$this->_iSurveyId}/files/";
if(is_file($surveyDir.'graphQuestion.xml')){
$aConfig = $this->_addXmlConfig($surveyDir.'graphQuestion.xml',$aConfig);
}
if(is_file($surveyDir.'graphQuestion'.$graphType.'.xml')){
$aConfig = $this->_addXmlConfig($surveyDir.'graphQuestion'.$graphType.'.xml',$aConfig);
}
if(is_file($surveyDir.'graphQuestion'.$qCode.'.xml')){
$aConfig = $this->_addXmlConfig($surveyDir.'graphQuestion'.$qCode.'.xml',$aConfig);
}
libxml_disable_entity_loader($oldValue);
/* @todo : reset bad value to default config ( color between 0 and 255, intval for size ...) */
return $aConfig;
}
/**
* Add a config file to the config
* @param strinf $file that must exist
* @param array $config to update
* @return array updated config
*/
private function _addXmlConfig($file, $config = array())
{
$xmlConfigFile = file_get_contents($file);
$xmlConfig = simplexml_load_string($xmlConfigFile);
return \CMap::mergeArray($config,json_decode(json_encode($xmlConfig), true));
}
/**
* Fix some var (by constant)
* @param string $param name to test
......
......@@ -22,9 +22,9 @@
</color>
<!-- background color of graph -->
<bgcolor>
<R>250</R>
<G>250</G>
<B>250</B>
<R>255</R>
<G>255</G>
<B>255</B>
</bgcolor>
<!-- palette file used , see vendor/pChart2/palettes-->
<palette></palette>
......@@ -43,9 +43,4 @@
<B>40</B>
</bgcolor>
</header>
<!--Chart format see http://wiki.pchart.net/doc.draw.radar.html -->
<chart>
<Layout>RADAR_LAYOUT_CIRCLE</Layout>
<LabelPos>RADAR_LABELS_ROTATED</LabelPos>
</chart>
</graph>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Configuration for graphQuestion , default part, same xml file in templates/files/graphQuestionRadar.xml to update. -->
<graph>
<!--Chart format see http://wiki.pchart.net/doc.draw.radar.html -->
<chart>
<Layout>RADAR_LAYOUT_CIRCLE</Layout>
<LabelPos>RADAR_LABELS_ROTATED</LabelPos>
</chart>
</graph>
cloc-1.80.exe
php.exe
php.ini
php7.2/php.exe
php7.2/php7ts.dll
php7.2/php_gd2.dll
php7.2/php_pdo_sqlite.dll
php7.3/php.exe
php7.3/php7ts.dll
php7.3/php_gd2.dll
php7.3/php_pdo_sqlite.dll
php7ts.dll
php_gd2.dll
php_pdo_sqlite.dll
......@@ -3957,12 +3957,14 @@ class pDraw
list($XMargin, $XDivs) = $this->scaleGetXSettings();
foreach($Data["Series"] as $SerieName => $Serie) {
if ($Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"]) {
$R = $Serie["Color"]["R"];
$G = $Serie["Color"]["G"];
$B = $Serie["Color"]["B"];
$Alpha = $Serie["Color"]["Alpha"];
$Ticks = $Serie["Ticks"];
$Weight = $Serie["Weight"];
if ($BreakR == NULL) {
$BreakSettings = ["R" => $R,"G" => $G,"B" => $B,"Alpha" => $Alpha,"Ticks" => $VoidTicks];
} else {
......@@ -3976,13 +3978,16 @@ class pDraw
}
$AxisID = $Serie["Axis"];
$Mode = $Data["Axis"][$AxisID]["Display"];
$Mode = $Data["Axis"][$AxisID]["Display"];
$Format = $Data["Axis"][$AxisID]["Format"];
$Unit = $Data["Axis"][$AxisID]["Unit"];
$Unit = $Data["Axis"][$AxisID]["Unit"];
$SerieDescription = (isset($Serie["Description"])) ? $Serie["Description"] : $SerieName;
$PosArray = $this->scaleComputeY($Serie["Data"], ["AxisID" => $Serie["Axis"]]);
$this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0;
if ($Data["Orientation"] == SCALE_POS_LEFTRIGHT) {
if ($XDivs == 0) {
$XStep = ($this->GraphAreaX2 - $this->GraphAreaX1) / 4;
} else {
......@@ -3992,51 +3997,52 @@ class pDraw
$X = $this->GraphAreaX1 + $XMargin;
$WayPoints = [];
$Force = $XStep / 5;
$PosArray = $this->convertToArray($PosArray);
$LastGoodY = NULL;
$LastGoodX = NULL;
$LastX = 1;
$LastY = 1;
foreach($PosArray as $Key => $Y) {
if ($DisplayValues) $this->drawText($X, $Y - $DisplayOffset, $this->scaleFormat($Serie["Data"][$Key], $Mode, $Format, $Unit), array(
"R" => $DisplayR,
"G" => $DisplayG,
"B" => $DisplayB,
"Align" => TEXT_ALIGN_BOTTOMMIDDLE
));
if ($DisplayValues){
$this->drawText($X, $Y - $DisplayOffset, $this->scaleFormat($Serie["Data"][$Key], $Mode, $Format, $Unit), [
"R" => $DisplayR,
"G" => $DisplayG,
"B" => $DisplayB,
"Align" => TEXT_ALIGN_BOTTOMMIDDLE
]);
}
if ($RecordImageMap && $Y != VOID) {
$this->addToImageMap("CIRCLE", floor($X) . "," . floor($Y) . "," . $ImageMapPlotSize, $this->toHTMLColor($R, $G, $B), $SerieDescription, $this->scaleFormat($Serie["Data"][$Key], $Mode, $Format, $Unit));
}
if ($Y == VOID && $LastY != NULL) {
$this->drawSpline($WayPoints, ["R" => $R,"G" => $G,"B" => $B,"Alpha" => $Alpha,"Ticks" => $Ticks,"Weight" => $Weight]);
$WayPoints = [];
if ($Y == VOID && $LastY != NULL){
$this->drawSpline($WayPoints,["Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight]);
$WayPoints = [];
}
if ($Y != VOID && $LastY == NULL && $LastGoodY != NULL && !$BreakVoid) {
$this->drawLine($LastGoodX, $LastGoodY, $X, $Y, $BreakSettings);
}
if ($Y != VOID) $WayPoints[] = [$X,$Y];
if ($Y != VOID){
$WayPoints[] = [$X,$Y];
}
if ($Y != VOID) {
$LastGoodY = $Y;
$LastGoodX = $X;
}
if ($Y == VOID) {
} else {
$Y = NULL;
}
$LastX = $X;
$LastY = $Y;
$X = $X + $XStep;
$X += $XStep;
}
$this->drawSpline($WayPoints, ["Force" => $Force,"R" => $R,"G" => $G,"B" => $B,"Alpha" => $Alpha,"Ticks" => $Ticks,"Weight" => $Weight]);
} else {
if ($XDivs == 0) {
$YStep = ($this->GraphAreaY2 - $this->GraphAreaY1) / 4;
} else {
......@@ -4048,12 +4054,12 @@ class pDraw
$Force = $YStep / 5;
$PosArray = $this->convertToArray($PosArray);
$LastGoodY = NULL;
$LastGoodX = NULL;
$LastX = 1;
$LastY = 1;
foreach($PosArray as $Key => $X) {
if ($DisplayValues) {
$this->drawText($X + $DisplayOffset, $Y, $this->scaleFormat($Serie["Data"][$Key], $Mode, $Format, $Unit), ["Angle" => 270,"R" => $DisplayR,"G" => $DisplayG,"B" => $DisplayB,"Align" => TEXT_ALIGN_BOTTOMMIDDLE]);
}
......@@ -4071,20 +4077,19 @@ class pDraw
$this->drawLine($LastGoodX, $LastGoodY, $X, $Y, $BreakSettings);
}
if ($X != VOID){
$WayPoints[] = [$X,$Y];
}
if ($X != VOID) {
$WayPoints[] = [$X, $Y];
#} # Momchil
#if ($X != VOID) {
$LastGoodX = $X;
$LastGoodY = $Y;
} else {
#if ($X == VOID) {
$X = NULL;
}
$LastX = $X;
$LastY = $Y;
$Y = $Y + $YStep;
$Y += $YStep;
}
$this->drawSpline($WayPoints, ["Force" => $Force,"R" => $R,"G" => $G,"B" => $B,"Alpha" => $Alpha,"Ticks" => $Ticks,"Weight" => $Weight]);
......
Include pChart 2.1.4a
https://github.com/bozhinov/pChart2.0-for-PHP7/releases/tag/2.1.4a
Include pChart 2.1.4b
https://github.com/bozhinov/pChart2.0-for-PHP7/releases/tag/2.1.4b
Remove example directory
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment