* @version $Id$
* @access public
* @license http://opensource.org/licenses/gpl-3.0.html
*/
if(!function_exists('get_associated_projects')) {
function get_associated_projects($id) {
$str = '';
$projects = $GLOBALS['sql_object'] ->DBSelect(SQL_get_associated_projects($id));
if(isset($projects[0]['project_name'])) {
$str = '
';
$content = '';
foreach($projects as $project) {
$content .= ''.formatText($project['project_name'], '2HTML').'';
}
$str = sprintf($str, $content);
}
return empty_none($str);
}
}
if(!function_exists('getMenuFilter')) {
/**
* getMenuFilter()
*
* @param array $tags
* @return string
*/
function getMenuFilter ($tags = array()) {
footerAddJS('../lib/js/jquery-tag-filtering/jquery.tagfiltering.simo.js');
addDynamicCSS('../lib/js/jquery-tag-filtering/jquery.tagfiltering.simo.css');
// one call to apply many filters from several lists (ul) with same css class and using distincts data-* attributes
// to comment if individual filtering are applied
footerAddInlineJS('$("ul.filter-menu").tagfiltering({target_attr:"data-tags", separator:";"});');
// export Javascript part
$js =
'$("#save-export").click( function() {
var to_export = [];
var $items = $(".filter-items").children();
// we populate the array to send with ajax
$items.each(function() {
if($(this).is(":visible")) {
var curval = $(this).attr("data-id");
// we check if not in array yet
if($.inArray( curval,to_export) == -1) to_export.push($(this).attr("data-id"));
}
});
alertify.success("'. _t('items', 'selected').'".replace("%s", to_export.length));
$.ajax({
type: "POST",
data: {to_export:to_export},
url: "../dashboard/_ajax_save.php?token='.SECRET_KEY.'",
success: function(msg){
window.location = "../admin/index.php?rub=dashboard&todo=report";
}
});
});';
footerAddInlineJS($js);
$filter_menu = '';
$filter_menu .= '';
$filter_menu .= getTagsMenuFilter ($tags);
$filter_menu .= '
';
$filter_menu .= '
';
return $filter_menu;
}
}
if(!function_exists('getTagsMenuFilter')) {
/**
* getTagsMenuFilter()
*
* get tags menu filter
* @param array $tags
* @return string
*/
function getTagsMenuFilter ($tags) {
$filter = '';
// we display filter if at least 2 values exists
if(count($tags) > 1) {
$options = '';
$a = array();
foreach($tags as $item) {
if(!in_array($item['tag_id'], $a)) {
$options .= ''.$item['tag_name'].'';
array_push($a, $item['tag_id']);
}
}
$filter .= sprintf('%s
', _t('filter', 'by_tag'), $options);
}
return $filter;
}
}
if(!function_exists('getPositionfromValue')) {
function getPositionfromValue ($value, $indicator, $threshold_value){
if ($indicator['sdii_max_value']==0) {
$max_value=0.000001;
} else {
$max_value=$indicator['sdii_max_value'];
}
if ($indicator['sdii_min_value']==0) {
$min_value=0.000001;
} else {
$min_value=$indicator['sdii_min_value'];
}
if ($indicator['sdii_threshold_relative']=='Y') {
$unitup = 50 / ($max_value - $threshold_value);
$unitdown = 50 / ( $threshold_value - $min_value);
if ($value > $threshold_value) $result = 50 + (($value - $threshold_value) *$unitup);
else $result = 50 -( ($threshold_value - $value ) *$unitdown );
}
else{
if(($max_value - $threshold_value) <> 0) $unitdown = 50 / ($max_value - $threshold_value);
if(($threshold_value - $min_value) <> 0) $unitup = 50 / ($threshold_value - $min_value);
if ($value > $threshold_value) $result=50 -( ($value - $threshold_value) * $unitdown);
else $result = 50 + (( $threshold_value - $value ) * $unitup);
}
return (int)$result;
}
}
if(!function_exists('getIndicatorInfoBox')) {
function getIndicatorInfoBox($current_value, $indicator, $threshold_value, $class= '') {
if($indicator['sdii_type'] == 'quantitative') {
$display_min = empty_nc($indicator['sdii_min_value']);
$display_max = empty_nc($indicator['sdii_max_value']);
$display_threshold = empty_nc(fnumber_format($threshold_value, 'auto', false));
} else {
$a = getBooleanValues($indicator);
if($a) {
$index = array();
foreach ($a as $key => $value) {
array_push($index, $key);
}
}
$display_min = $a[min($index)];
$display_max = $a[max($index)];
if(!empty($threshold_value)) $display_threshold = $a[$threshold_value];
else $display_threshold = empty_nc('');
}
$content = "".ucfirst(_t('dashboard','value'))." : ".fnumber_format($current_value, 'auto', false)." (".formatText($indicator['sdii_unit']).")
".
"
".ucfirst(_t('sdi','min_value'))." : ".$display_min."
".
"
".ucfirst(_t('sdi','max_value'))." : ".$display_max."
".
"
".ucfirst(_t('sdi','threshold_value'))." : ".$display_threshold."
".
"
";
return $content;
}
}
if(!function_exists('getGaugeViz')) {
function getGaugeViz($sql_object, $scale_id, $indicator, $threshold_value, $cursorcssposition) {
//$cursorcssposition is used to adjust cursor position depending on the container/context
$req_sdiav=SQL_getAllValue("SCA", $scale_id, $indicator['sdii_id']);
$result_value = $sql_object -> DBSelect($req_sdiav);
// values are stored
if ($result_value <> false){
// we handle multivalues
if(!empty($result_value[0]['sdiv_multivalue'])) {
$data = unserialize($result_value[0]['sdiv_multivalue']);
$current_value = $data[0]['_total'];
// we handle simple values
} else {
$current_value = $result_value[0]['sdiv_value'];
}
$value_cursor1 = getPositionfromValue ($current_value, $indicator, $threshold_value);
$value_cursor = 111 - $value_cursor1 + $cursorcssposition;
$value_cursor = -111 + $value_cursor1 + $cursorcssposition; // 3 is half width of the cursor image. Positionning $value_cursor to -111 will display the cursor at the begining of the gauge
}
else {
$value_cursor = 0;
}
// there is no value
if ($result_value == false) {
$gauge= 'gauge_grey.gif';
$current_value = _t('dashboard','novalue');
$cursor_visibility = 'hidden';
$class="indicator-no-data";
}
// min, max and threshold are not set together. No display allowed
elseif(is_null($indicator['sdii_max_value']) || is_null($indicator['sdii_min_value']) || is_null($threshold_value)) {
$gauge= 'gauge_red.gif';
$current_value = $result_value[0]['sdiv_value'];
$cursor_visibility = 'hidden';
$class="indicator-no-cursor";
}
// there is at least one value and min, max and threshold are set together
else {
$gauge= 'gauge.gif';
$cursor_visibility = 'visible';
$class="";
// we handle multivalues
if(!empty($result_value[0]['sdiv_multivalue'])) {
$data = unserialize($result_value[0]['sdiv_multivalue']);
$current_value = $data[0]['_total'];
// we handle simple values
} else {
$current_value = $result_value[0]['sdiv_value'];
}
}
if(CURRENT_APP == 'admin') {
$link = "index.php?rub=dashboard&todo=det&id=".$indicator['sdii_id']."&scale_id=".$scale_id;
} else {
$link = HrefMaker(array('rub'=> $GLOBALS['links'][U_L]['dashboard']['linkvalue'],'id'=>$indicator['sdii_id'], 'parentid'=> $scale_id));
}
$link="javascript:void(0);";
$listing = "

";
$listing .= getIndicatorInfoBox($current_value, $indicator, $threshold_value, $class);
$listing .= "

";
$listing .= getTendency($result_value, $indicator);
$listing .= "\t
(".strtolower(fnumber_format($current_value, 'auto', false)).")\n";
$listing .= "\t
\n";
return $listing;
}
}
if(!function_exists('getRawViz')) {
function getRawViz($sql_object, $scale_id, $indicator, $threshold_value) {
$req_sdiav=SQL_getAllValue("SCA", $scale_id, $indicator['sdii_id']);
$result_value = $sql_object -> DBSelect($req_sdiav);
$str = '';
// there is no value
if ($result_value==false) {
$str .= '-';
$current_value = _t('dashboard','novalue');
$class="indicator-no-data";
// some values are there
} else {
// we handle multivalues
if(!empty($result_value[0]['sdiv_multivalue'])) {
$data = unserialize($result_value[0]['sdiv_multivalue']);
$str .= ''.fnumber_format($data[0]['_total'], 'auto', false).'';
$current_value = $data[0]['_total'];
// we handle simple values
} else {
$a = getBooleanValues($indicator);
$class= '';
if($a && ($indicator['sdii_type'] == 'boolean' || $indicator['sdii_type'] == 'qualitative')) {
if(count($a) == 2) {
if($result_value[0]['sdiv_value'] == 0) $class= " boolean-false";
else $class= " boolean-true";
} else $class = $class= " boolean-value-" . $result_value[0]['sdiv_value'];
$current_value = $a[$result_value[0]['sdiv_value']];
$classbmask = ' boolean-mask';
} else {
$classbmask = '';
$current_value = fnumber_format($result_value[0]['sdiv_value'], 'auto', false);
}
$str .= ''.$current_value.'';
}
$class="";
}
$str .= getIndicatorInfoBox($current_value, $indicator, $threshold_value, $class);
$str .= ''.formatText($indicator['sdii_unit']).'';
$str .= '
';
$str .= getTendency($result_value, $indicator);
return $str;
}
}
if(!function_exists('getSparklineViz')) {
function getSparklineViz($sql_object, $scale_id, $indicator, $threshold_value) {
// getting all values
$req_sdiav=SQL_getAllValue("SCA", $scale_id, $indicator['sdii_id']);
$result_value = $sql_object -> DBSelect($req_sdiav);
$str = '';
// there is no value
if ($result_value==false) {
$str .= '
-';
// some values are there
} else {
$data = array();
// we reverse the array to display eldest first
$values = array_reverse($result_value);
foreach($values as $value) {
// we handle multivalues
if(!empty($value['sdiv_multivalue'])) {
$dataindic = unserialize($value['sdiv_multivalue']);
array_push($data, $dataindic[0]['_total']);
// we handle simple values
} else {
array_push($data, $value['sdiv_value']);
}
}
$str .= '
'.join(',',$data).'
';
}
$str .= '
';
$str .= getTendency($result_value, $indicator);
return $str;
}
}
if(!function_exists('getViz')) {
function getViz($sql_object, $scale_id, $indicator, $threshold_value, $overwrite = null, $cursorcssposition = 0) {
if(!is_null($overwrite)) {
$vizualisation_type = $overwrite;
} else {
$vizualisation_type = $indicator['sdii_dashboard_viz'];
}
if($vizualisation_type == 'raw') {
$viz = getRawViz($sql_object, $scale_id, $indicator, $threshold_value);
}
if($vizualisation_type == 'gauge') {
$viz = getGaugeViz($sql_object, $scale_id, $indicator, $threshold_value, $cursorcssposition);
}
if($vizualisation_type == 'sparkline') {
$viz = getSparklineViz($sql_object, $scale_id, $indicator, $threshold_value, $cursorcssposition);
}
return $viz;
}
}
/**
* getBooleanValues()
* Return boolean values enter in comment fields
* or false if no mask is set or if not boolean
* as {0=oui;1=non} format
* @param array $indicator
* @return mixed (false or array)
*/
if(!function_exists('getBooleanValues')) {
function getBooleanValues($indicator) {
if($indicator['sdii_type'] == 'boolean' || $indicator['sdii_type'] == 'qualitative') {
// get content with the following pattern
// For example {0=non signée;1=signée}
$pattern = '/{(.*?)}/';
$r =preg_match($pattern, $indicator['sdii_comment'], $matches);
if($r == 0) return false;
$b = array();
$str = rtrim($matches[1], ";");
$a = explode(";", $str);
foreach($a as $entry) {
list($key, $value) = explode("=", $entry);
$key = trim($key);
$b[$key] = trim($value);
}
return $b;
}
return false;
}
}
/**
* getColorRamp()
* @param array $values
* @param array $colors
* @return array $hexa_colors
*/
if(!function_exists('getColorRamp')) {
function getColorRamp($values, $colors = array('1' => '#D73027', '2' => '#FFFFBF', '3' => '#1A9850')) {
$hexa_colors = array ();
// default colors taken from chroma 'RdYlGn'
// https://github.com/gka/chroma.js/wiki/Predefined-Colors
require_once ('../lib/vendor/PHP-Color/autoload.php');
// https://github.com/ProjectCleverWeb/PHP-Color/issues/4
// https://github.com/ProjectCleverWeb/PHP-Color/issues/3#issuecomment-255130522
/**
* * GRADIENTS/SCALES **
*/
$color1 = new projectcleverweb\color\main ( $colors ['1'] );
$color2 = new projectcleverweb\color\main ( $colors ['2'] );
$color3 = new projectcleverweb\color\main ( $colors ['3'] );
// ge number of classes
$nb_values = count ( $values );
$nb_classes = ( int ) (count ( $values ) / 2);
if ($nb_classes === 0)
return false;
// necessary to get number of wanted classes
if ($nb_values % 2 == 1)
$plus = 1;
else
$plus = 0;
// print_r ( $values );
// Gradient array with a custom number of colors (offset 0 is $color1 and offset 9 is $color2)
$gradient_array_1 = $color1->gradient ( $color2, ($nb_classes + $plus) );
// Gradient array with exactly enough non-duplicate colors
$gradient_array_2 = $color1->gradient ( $color2 );
// You can't currently create a gradient with more than 2 colors, but you can merge 2+ gradient arrays
$gradient_array_3 = $color2->gradient ( $color3, ($nb_classes + 1) );
array_shift ( $gradient_array_3 );
$gradient_array_4 = array_merge ( $gradient_array_1, $gradient_array_3 );
// print_r ( $gradient_array_4 );
foreach ( $values as $key => $value ) {
// foreach ($gradient_array_4 as $key) {
// we determine text color by contrat to background
$o = round ( (($gradient_array_4 [$key] ['r'] * 299) + ($gradient_array_4 [$key] ['g'] * 587) + ($gradient_array_4 [$key] ['b'] * 114)) / 1000 );
if ($o > 125)
$hexa_colors [$key] ['color'] = '000000';
else
$hexa_colors [$key] ['color'] = 'ffffff';
$color = new projectcleverweb\color\main ( $gradient_array_4 [$key], 'RGB' );
$hexa = $color->hex ();
// echo ''. $key.' #'.$hexa . '
';
$hexa_colors [$key] ['background-color'] = $hexa;
}
return $hexa_colors;
}
}
/**
* getQualitativeViz()
* Return global rate
* @param array $values
* @param array $indicator
*/
if(!function_exists('getQualitativeViz')) {
function getQualitativeViz($values, $indicator, $dateFormat = 'short', $legend = true, $topdf = false) {
// @todo implement PHP version
require_once('../lib/vendor/PHP-Color/autoload.php');
// https://github.com/ProjectCleverWeb/PHP-Color/issues/4
// https://github.com/ProjectCleverWeb/PHP-Color/issues/3#issuecomment-255130522
// $o = new projectcleverweb\color\main('FF0000');
// $hex_scheme = $o->scheme('compound');
// print_r($hex_scheme);
// test if there is record
if(!isset($values[0]['sdiv_id'])) return false;
// we retrieve values
$a = getBooleanValues($indicator);
// get get color ramp
$colors = getColorRamp($a);
if($a) {
$index = array();
foreach ($a as $key => $value) {
array_push($index, $key);
}
$minvalue = min($index);
$maxvalue = max($index);
// @todo to remove
//footerAddJS('../lib/js/chroma.js/chroma.min.js');
// https://github.com/gka/chroma.js/wiki/Predefined-Colors
$js = ' var viz_color = chroma.scale("RdYlGn").colors('.count($a).');
// http://jsfiddle.net/PXJ2C/
$("td.qualitative-value").each(function() {
var val = $(this).attr("data-value");
$(this).css("background-color", viz_color[val]);
var rgb = chroma(viz_color[val]).rgb();
var o = Math.round(((parseInt(rgb[0]) * 299) + (parseInt(rgb[1]) * 587) + (parseInt(rgb[2]) * 114)) /1000);
if(o > 125) $(this).css("color", "black");
else $(this).css("color", "white");
});';
// footerAddInlineJS($js);
}
// print_r($values);
$content = '';
$header = '';
$body = '';
$width = round(100 / count($values));
$values = $reversed = array_reverse($values);
for ($i=0; $i ';
$body .= ''. $a[$values[$i]['sdiv_value']] .' | ';
}
if($topdf == true) $content .= '';
$content .= '';
if($legend) {
$legend = '';
if($topdf == false) $legendblock = ' '; else $legendblock = 'xxxx';
foreach ($a as $key => $value) {
$legend .= ''.$legendblock.' '.$value.'';
if($topdf == true) $legend .= ''.$legendblock.'';
}
$content .= ''.$legend.'
';
}
return sprintf($content, $header, $body);
}
}
/**
* getRates()
* Return global rate and
* @param array $indicator
* @param numeric $firstValue
* @param numeric $firstValue
* @param integer $year_start
* @param integer $year_end
*/
if(!function_exists('getRates')) {
function getRates($firstValue, $lastValue, $year_start, $year_end, $format = 'html') {
if((int) $year_start > (int) $year_end) $years = $year_start - $year_end;
else $years = $year_end - $year_start;
if($firstValue == 0) {
$global_evol = empty_nc('');
$tcam = empty_nc('');
} else {
// gobal rate
$global_evol = (($lastValue - $firstValue) / $firstValue * 100);
// tcam
// $tcam = (pow ( (2349816 / 2339881) , 1/5 ) - 1) * 100; // doit retourner 0.085 %
if($years > 1) $tcam = (pow ( ($lastValue / $firstValue) , 1 / $years ) - 1) * 100;
else $tcam = empty_nc('');
}
if($format == 'html') {
return '
' . _t('dashboard', 'global_rate') . ' : ' . fnumber_format($global_evol, 2, false) . ' %
| ' . _t('dashboard', 'cagr'). ' : ' . fnumber_format($tcam, 2, false) . ' %
';
} else {
return _t('dashboard', 'global_rate') . ' : ' . fnumber_format($global_evol, 2, false) . ' % | '. strip_tags(_t('dashboard', 'cagr')). ' : ' . fnumber_format($tcam, 2, false) . ' %';
}
}
}
/**
* getTendency()
* Return indicator tendency based on value
* (not based on performance)
* @param array $values
* @param array $indicator
*/
if(!function_exists('getTendency')) {
function getTendency($values, $indicator) {
$tendency = '';
$percentage = '';
$evolution = '';
// we handle multivalues
// if there is a previous value
if(!empty($values[1]['sdiv_multivalue'])) {
$data = unserialize($values[0]['sdiv_multivalue']);
$dataPlusOne = unserialize($values[1]['sdiv_multivalue']);
if($indicator['sdii_type'] == 'quantitative') {
$percentage = ($data[0]['_total'] - $dataPlusOne[0]['_total']) / $dataPlusOne[0]['_total'] * 100;
$evolution = ' ('.round($percentage, 0). '%)';
}
if ($data[0]['_total'] > $dataPlusOne[0]['_total']) {
$tendency.="

";
} elseif($data[0]['_total'] < $dataPlusOne[0]['_total']) {
$tendency.="

";
} else {
$tendency.="

";
}
// we handle simple values
// if there is a previous value
} elseif(isset($values[1]['sdiv_value'])) {
$previous_value = fnumber_format($values[1]['sdiv_value'], 'auto', false);
if($indicator['sdii_type'] == 'quantitative') {
$percentage = ($values[0]['sdiv_value'] - $values[1]['sdiv_value']) / $values[1]['sdiv_value'] * 100;
$evolution = ' ('.round($percentage, 0). '%)';
} else {
$a = getBooleanValues($indicator);
if($a) {
$index = array();
foreach ($a as $key => $value) {
array_push($index, $key);
}
$previous_value = $a[$values[1]['sdiv_value']];
}
}
if ($values[0]['sdiv_value'] > $values[1]['sdiv_value']) {
$tendency.="

";
} elseif($values[0]['sdiv_value'] < $values[1]['sdiv_value']) {
$tendency.="

";
} else {
$tendency.="

";
}
}
$tendency .= '
';
return $tendency;
}
}