';
}
if(!function_exists('format_operation_field')) {
function format_operation_field($field)
{
// we used $parsedOperation instead of $table['operation'] because vars are replaced
// and we convert to english format
$expression = str_replace(',', '.', $field);// handle french format number
$expression = str_replace(' ', '', $expression);// handle french format number
return $expression;
}
}
if(!function_exists('parse_operation')) {
function parse_operation_field($field, $id = null)
{
global $sql_object;
// we prepare data
if (is_null($id)) $rscale = $sql_object->DBSelect(SQL_Get_root_scale());
else $rscale = $sql_object->DBSelect(SQL_getonescale($id));
$operationVars = ['pop' => $rscale[0]['scale_inhabitantsnumber'], 'surface' => $rscale[0]['scale_surface']];
$parsedOperation = str_replace('{pop}', $operationVars['pop'], $field);
$parsedOperation = str_replace('{surface}', $operationVars['surface'], $parsedOperation);
return $parsedOperation;
}
}
/**
* api_multivalue_javascript
* @return void
*/
if(!function_exists('api_multivalue_javascript')) {
function api_multivalue_javascript() {
$js = '$("#reload-discover-api").click(function() {
$("#api-url").change();
return false;
});
$("#sdi_value_type,#api-mode").change(function() {
let sdiType = $("#sdi_value_type").val();
let apiMode = $("#api-mode").val();
// console.log(apiMode);
if(sdiType == "unique") {
$("#api-value-field-cont").css("display", "block");
$("#api-multi-mapping-cont").css("display", "none");
} else {
$("#api-multi-mapping-cont").css("display", "block");
if(apiMode == "value") $("#api-value-field-cont,#api-criteria-field-cont").css("display", "block");
else $("#api-value-field-cont,#api-criteria-field-cont").css("display", "none");
}
});
$("#sdi_value_type").change();
$("#api-url").change(function() {
let sdiType = $("#sdi_value_type").val();
let apiMode = $("#api-mode").val();
let api_url = $("#api-url").val();
let api_value = $("#api-value-field").val();
let api_criteria = $("#api-value-criteria").val();
let content = CKEDITOR.instances["comment"].getData(); // we get content from comment textarea
var rval = /{(.*?)}/g.exec(content); // select what is between curly brackets : rval[0] returns content with brackets, rval[1] without
if(sdiType == "multiple" && !rval) { // no predefined values are set, we notify the user and exit
alertify.error("' . addslashes(sprintf(_t('sdi', 'api-no-predefined-values'), '#attached_to_dashboard')) . '");
return false;
}
if(api_url.length < 7) { // api_url is empty
// we do not do anything now
return false;
} else {
// we send the request to discover fields
$.ajax({
method: "GET",
url: "../dashboard/api-harvest.php?token='.SECRET_KEY.'",
data: { apiURL: api_url, apiMode: apiMode, apiCriteria: api_criteria},
dataType: "json",
}).done(function(data) {
if(data.status == 0) { // failure : we display a message
alertify.error(data.msg);
return false;
}
if(data.status == 1) { // success : we prepare data
console.log(data);
selectBoxOptions("api-date-field", data.keys, true); // we replace date field
if(sdiType == "unique" || apiMode == "value") {
selectBoxOptions("api-value-field", data.keys, true); // we replace value field
selectBoxOptions("api-value-criteria", data.keys, true); // we replace value field
// we bind change behavior on #api-value-criteria
$( "#api-value-criteria" ).bind( "change", function() {
$("#api-url").change();
return false;
});
}
if(sdiType == "multiple") {
if($(".api-mapping-field").length == 0) { // we prepare fields only if no existing data is there
entries = rval[1].split(";");
// @todo : idéalement récuperer les valeurs déjà peuplées
$("#api-multi-mapping-cont").empty();
for(var i = 0; i < entries.length; i++) {
if(entries[i] != "") $("#api-multi-mapping-cont").append("");
}
}
// we apply selectBox anyway
$( ".api-mapping-field").each(function( index ) {
// console.log(this.id);
if(apiMode == "attribute") selectBoxOptions(this.id, data.keys, true);
if(apiMode == "value") {
// console.log(data.values);
selectBoxOptions(this.id, data.values, true);
}
});
}
}
});
}
// console.log(content);
// console.log(rval);
});';
footerAddInlineJS($js);
}
}
/**
* unit_javascript_validation
* @return void
*/
if(!function_exists('unit_javascript_validation')) {
function unit_javascript_validation() {
$js = '$("#min_value, #max_value, #threshold_value").change(function() {
var minVal = $("#min_value").val().replace(",", ".");
var maxVal = $("#max_value").val().replace(",", ".");
var thresholdVal = $("#threshold_value").val().replace(",", ".");
var dashboardViz = $("#sdi_dashboard_viz").find(":selected").val();
console.log("min : " + minVal + " - max : " + maxVal + " - threshold : " + thresholdVal);
if(isNumeric(minVal) && isNumeric(maxVal) && maxVal <= minVal ) alertify.error("'._t("sdi","object_minmax_error").'");
// if thresold and min are provided, be sure thresold is superior to min
if(isNumeric(minVal) && isNumeric(thresholdVal) && thresholdVal < minVal ) alertify.error("'._t("sdi","object_minthreshold_error").'");
// if thresold and max are provided, be sure thresold is inferior to max
if(isNumeric(maxVal) && isNumeric(thresholdVal) && thresholdVal > maxVal ) alertify.error("'._t("sdi","object_maxthreshold_error").'");
// we add check if gauge
if(dashboardViz == "gauge") {
if(!isNumeric(maxVal) || !isNumeric(minVal) || !isNumeric(thresholdVal)) alertify.error("'.sprintf(_t('sdi','object_gauge_error1'), $GLOBALS['lang']['sdi']['select_dashboard_viz']['gauge']).'");
if(isNumeric(maxVal) && isNumeric(thresholdVal) && thresholdVal >= maxVal ) alertify.error("'.sprintf(_t('sdi','object_gauge_error2'), $GLOBALS['lang']['sdi']['select_dashboard_viz']['gauge']).'");
if(isNumeric(minVal) && isNumeric(thresholdVal) && thresholdVal <= minVal ) alertify.error("'.sprintf(_t('sdi','object_gauge_error3'), $GLOBALS['lang']['sdi']['select_dashboard_viz']['gauge']).'");
}
});';
footerAddInlineJS($js);
}
}
/**
* get_unique_indicators
* @param array $sdi
* @param boolean $noorphan
* @return array
*/
if(!function_exists('get_unique_indicators')) {
function get_unique_indicators($sdi, $noorphan = false) {
$uniques = [];
$cnt = 0;
if($noorphan) {
$levelExclude = 0;
} else {
$levelExclude = -999; // wich has no effect
}
if(!is_array($sdi)) return array('indicators' => [], 'count' => 0);
foreach ($sdi as $s) {
if(!in_array($s['sdii_id'], $uniques) && $s['sdii_level'] != $levelExclude) {
array_push($uniques, $s['sdii_id']);
$cnt++;
}
}
return array('indicators' => $uniques, 'count' => $cnt);
}
}
/**
* _format_results
* Format results all the same way, whatever it comes from distinct API with different formats
* Resulting array is like so : array('results' => array(0 => array( 'value' => 100, 'date' => '2022', 'something' => 'xxx'), 1 => array( 'value' => 100, 'date' => '2022', 'something' => 'xxx'));
* @param array $json_arr
* @param string $field attribute field to get all unique values
* @return array
*/
if(!function_exists('_format_results')) {
function _format_results(array $json_arr, string $field = '') {
$a = [];
// Linea21 formatting
// Linea21 multiple indicator values sample with null values : http://localhost/linea21-dv/api/index.php?m=indicator&a=values&id=204
if(isset($json_arr['values'])) {
$json_arr['results'] = $json_arr['values'];
unset($json_arr['values']);
}
// Koumoul 'aggs' formatting
// koumoul aggregation see : https://opendata.agenceore.fr/data-fair/api/v1/datasets/consommation-annuelle-d-electricite-et-gaz-par-epci/values_agg?field=annee&code_epci_eq=243400017&filiere_eq=Electricit%C3%A9&sort=annee&metric_field=conso_totale_mwh&metric=sum
if(isset($json_arr['aggs'])) {
$json_arr['results'] = $json_arr['aggs'];
unset($json_arr['aggs']);
}
// arcgis : 'features' + 'attributes' field in loop
// geoserver : 'features' + 'properties' field in loop
if(isset($json_arr['features'])) {
$tmp = [];
foreach ($json_arr['features'] as $rec) {
if(isset($rec['attributes'])) array_push($tmp, $rec['attributes']); // arcgis
if(isset($rec['properties'])) array_push($tmp, $rec['properties']); // geoserver
}
$json_arr['results'] = $tmp;
}
// opendatasoft and koumoul (default query type) : 'results'
if(isset($json_arr['results'])) $a = $json_arr;
// put returned values in results entry if 'results' key does not exists
// for example, no 'results' key when using https://api.atmosud.org/cigale/ges/territoire?variable=prg100.3ges&code_territoire=200030195&bool_sources_additionnelles=false&perimetre=pcaet&all_years=true&format=json
if(count($json_arr) > 0 && !isset($json_arr['results'])) $a = array('results' => $json_arr);
// print_r($a);
// if needed we flatten the given json based on attribute
// $a['results'] = json_flatten($a['results'] , 'sdiv_multivalue');
$a['results'] = json_flatten($a['results'], 'sdiv_multivalue'); // @todo @simo make field dynamic
// we get unique values to populate fields for 'multiple' indicator having 'value' api-mode
$unique_values = [];
if(!empty($field)) {
foreach ($a['results'] as $r) {
if(!in_array($r[$field], $unique_values)) array_push($unique_values, $r[$field]);
}
$a['unique_values'] = $unique_values;
} else $a['unique_values'] = [];
// print_r($a);
return $a;
}
}
/**
* flatten json based on a given attribute
* @param $data :
* @param $attribute
* @return false|string
*/
function json_flatten($data, $attribute = -1) {
if($attribute == -1) return $data;
foreach ($data as $entry) {
if(!isset($entry[$attribute])) return $data;
// this is not an array, nothing to flatten
if(gettype($entry[$attribute]) != 'array' && gettype($entry[$attribute]) != 'object') return $data;
foreach ($entry[$attribute] as $multi) {
// copy all parent fields except $attribute
$newRow = [];
foreach ($entry as $key => $value) {
if ($key !== $attribute) {
$newRow[$key] = $value;
}
}
// add dynamically fields from $attribute
foreach ($multi as $subKey => $subValue) {
$dynamicKey = $attribute."." . $subKey;
$newRow[$dynamicKey] = $subValue;
}
$flatData[] = $newRow;
}
}
$finalJson = $flatData;
// $finalJson = json_encode($flatData,JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
return $finalJson;
}
/**
* api_discover
* @param array $sdi
* @param boolean $initialImport
* @return boolean
*/
if(!function_exists('api_discover')) {
function api_discover($url, $mode, $criteriaField, $oneRow = true) {
# https://docs.guzzlephp.org/en/5.3/quickstart.html
// use GuzzleHttp\Client;
// $client = new Client();
// @see https://stackoverflow.com/questions/20847633/limit-connecting-time-with-guzzle-http-php-client
// we add a timeout to client not to block script
if(defined('PROXY_PARAMS')) {
$client = new GuzzleHttp\Client(['timeout' => 3, 'connect_timeout' => 6, 'proxy' => PROXY_PARAMS]);
} else {
$client = new GuzzleHttp\Client(['timeout' => 3, 'connect_timeout' => 3]);
}
// we check if url is responding, if not we log the error
try {
$response = $client->get($url);
$code = $response->getStatusCode();
if($code == '200') {
// we convert json response to array
$records = json_decode($response->getBody(), true);
// print_r($records);
// we format retrieved json file if needed
$records = _format_results($records, $criteriaField);
//echo "";
//print_r($records);
//echo "";
if($oneRow) $records['results'] = $records['results'][0];
return $records;
}
// if 404 exception is caught - others errors as well
} catch (Exception $e) {
logfile(LOG_MAINFILE, array('[API discover]', 'URL not responding', $url, $e->getMessage()));
return _t('sdi', 'api-no-response');
}
}
}
/**
* api_update_indicators
* @param array $sdi
* @param boolean $initialImport
* @return boolean
*/
if(!function_exists('api_update_indicators')) {
function api_update_indicators($sdi, $initialImport = false) {
global $sql_object;
$debug = false;
$scale_id = 1;
$rflag = 1; // 1 means 'success', 2 : 'partial import due to strange values', 3 : 'action failed'
# https://docs.guzzlephp.org/en/5.3/quickstart.html
// use GuzzleHttp\Client;
// $client = new Client();
// @see https://stackoverflow.com/questions/20847633/limit-connecting-time-with-guzzle-http-php-client
// @see https://docs.guzzlephp.org/en/5.3/clients.html?highlight=proxi
// we add a timeout to client not to block script
if(defined('PROXY_PARAMS')) {
$client = new GuzzleHttp\Client(['timeout' => 3, 'connect_timeout' => 6, 'proxy' => PROXY_PARAMS]);
} else {
$client = new GuzzleHttp\Client(['timeout' => 3, 'connect_timeout' => 3]);
}
foreach ($sdi as $indicator) {
// if API is enabled only
if($indicator['sdii_api_enabled'] == 'Y') {
// $initialImport flag is not used anymore
// we set $since value anyway, not only if initialImport
if(!empty($indicator['sdii_api_getvalues-since'])) $since = $indicator['sdii_api_getvalues-since'];
else $since='1900'; // we fake the date to import everything
// $sql_object -> DBQuery("DELETE FROM l21_sdi_value WHERE sdiv_sdi_info ='" . $indicator['sdii_id'] . "' AND sdiv_scale ='" .$scale_id."'");
// we check if url is responding, if not we log the error
try {
$response = $client->get($indicator['sdii_api_url']);
$code = $response->getStatusCode();
// no test on $indicator['sdii_api_getvalues'] == 'Y', because it is supposed to be done before calling the function
if($code == '200') {
// we convert json response to array
$records = json_decode($response->getBody(), true);
// print_r($records);
// we format retrieved json file if needed
$records = _format_results($records);
foreach ($records['results'] as $rec) {
if($debug) echo '
';
if($debug) echo '
Value from API :
';
if($debug) print_r($rec);
if($debug) echo '';
// we need to get the $dateSuffix here to format $recordDate
$lastV = $sql_object -> DBSelect(SQL_getlastInsertByPublicationDate($indicator['sdii_id'], $scale_id));
// if exists, it can override $since variable to prevent multiple imports on initial import - security
if(isset($lastV[0]['sdiv_value']) ) {
$dateSuffix = substr($lastV[0]['sdiv_date_published'],4); // return 2020-01-01, so 2020
}
else {
$dateSuffix = '-12-31';
}
// we prepare default threshold value - can be overwritten later
if(is_numeric($indicator['sdii_threshold_value'])) $threshold = $indicator['sdii_threshold_value'];
else $threshold = '';
$format = "Y-m-d"; // date object format
// we create date object for comparison
// if only year is passed, we add month and day and create the object
if(strlen($rec[$indicator['sdii_api_datefield']]) == 4) {
$rec[$indicator['sdii_api_datefield']] .= $dateSuffix;
$recordDateFormatted = $rec[$indicator['sdii_api_datefield']];
$recordDate = DateTime::createFromFormat($format, $rec[$indicator['sdii_api_datefield']]);
// else default format is similar to : "2012-01-01T00:00:00+00:00"
} else {
$recordDateFormatted = $rec[$indicator['sdii_api_datefield']];
$recordDate = new DateTime($rec[$indicator['sdii_api_datefield']]);
}
// we create a formatted date for display
$formattedDate = $recordDate->format("Y-m-d"); // Output format : 2023-06-04
// only year is passed to since, we add month and day
if(strlen($since) == 4) $since .= $dateSuffix;
//if(strlen($lastDate) == 4) $lastDate .= $dateSuffix;
$SinceDate = DateTime::createFromFormat($format, $since);
// if($indicator['sdii_api_overwritevalues'] == 'N' && $recordDate >= $triggerDate) {
// be sure we import values for desired years
if($recordDate >= $SinceDate) {
// we init array if it does not exist !
// WARNING : It can exist if $indicator['sdii_value_type'] == 'multiple' and mode = 'value'
if(!isset($tmpA[$formattedDate])) $tmpA[$formattedDate] = ['indicator' => $indicator['sdii_id'], 'threshold' => $threshold, 'scale' => $scale_id, 'formattedDate' => $formattedDate, 'recordDate' => $recordDate, 'recordDateFormatted' => $recordDateFormatted, 'since' => $since];
if(isset($rec[$indicator['sdii_api_datefield']])) {
$a = [];
$a['indicator_type'] = $indicator['sdii_value_type'];
// if is sdii_value_type == 'unique'
// !!!! WARNING : if( isset($rec[$indicator['sdii_api_valuefield']])) does not pass test
// when $rec[$indicator['sdii_api_valuefield']] == null
if ($indicator['sdii_value_type'] == 'unique') {
if (is_numeric($rec[$indicator['sdii_api_valuefield']])) {
if($indicator['sdii_decimal'] == 'auto') $dec =get_decimal_number($rec[$indicator['sdii_api_valuefield']]);
else $dec = $indicator['sdii_decimal'];
$tmpA[$formattedDate]['value'] = sys_number_format(round($rec[$indicator['sdii_api_valuefield']], $dec));
$tmpA[$formattedDate]['nodata'] = 0;
} else {
$tmpA[$formattedDate]['value'] = 0;
$tmpA[$formattedDate]['nodata'] = 1;
}
}
// if is sdii_value_type == 'multiple'
if ($indicator['sdii_value_type'] == 'multiple') {
//$mvalues = [];
$mapping = unserialize($indicator['sdii_api_multimapping']);
// For imformation : Multiple values format
// Array ( [0] => Array ( [value] => 45 [label] => chaleur ) [1] => Array ( [value] => 89 [label] => électricité ) [2] => Array ( [value] => 52 [label] => carburant ) )
// first iteration to be sure data exists and is numeric
//$flags = [];
foreach ($mapping as $k => $v) {
// we collect data based on distinct attribute name !
if($indicator['sdii_api_mode'] == 'attribute') {
if(!isset($tmpA[$formattedDate]['value'])) $tmpA[$formattedDate]['value'] = []; // we create value key if needed
if (isset($rec[$v]) && is_numeric($rec[$v])) {
// if nodata is already set, we do not complete record !
if(isset($tmpA[$formattedDate]['nodata']) && $tmpA[$formattedDate]['nodata'] == 1) {
array_push($tmpA[$formattedDate]['value'], array('value' => 0, 'label' => $k));
} else {
$tmpA[$formattedDate]['nodata'] = 0;
if($indicator['sdii_decimal'] == 'auto') $dec =get_decimal_number($rec[$v]);
else $dec = $indicator['sdii_decimal'];
array_push($tmpA[$formattedDate]['value'], array('value' => sys_number_format(round($rec[$v], $dec)), 'label' => $k));
}
}
else {
$tmpA[$formattedDate]['nodata'] = 1;
array_push($tmpA[$formattedDate]['value'], array('value' => 0, 'label' => $k));
}
} else {
// we collect data based on value !
// if ($rec[$indicator['sdii_api_valuecriteria']] == $v) echo $rec[$indicator['sdii_api_valuecriteria']] . ' == '. $v. ' on ajoute pour année ' . $formattedDate . ' .... '. $k . ' valeur : '. sys_number_format(round($rec[$indicator['sdii_api_valuefield']], $indicator['sdii_decimal'])) ." \n";
if ($rec[$indicator['sdii_api_valuecriteria']] == $v) {
if(!isset($tmpA[$formattedDate]['value'])) $tmpA[$formattedDate]['value'] = []; // we create value key if needed
if(is_numeric($rec[$indicator['sdii_api_valuefield']])) {
// array_push($flags, true);
// if nodata is already set, we do not complete record !
if(isset($tmpA[$formattedDate]['nodata']) && $tmpA[$formattedDate]['nodata'] == 1) {
array_push($tmpA[$formattedDate]['value'], array('value' => 0, 'label' => $k));
} else {
$tmpA[$formattedDate]['nodata'] = 0;
if($indicator['sdii_decimal'] == 'auto') $dec =get_decimal_number($rec[$indicator['sdii_api_valuefield']]);
else $dec = $indicator['sdii_decimal'];
array_push($tmpA[$formattedDate]['value'], array('value' => sys_number_format(round($rec[$indicator['sdii_api_valuefield']], $dec)), 'label' => $k));
}
}
else {
$tmpA[$formattedDate]['nodata'] = 1;
array_push($tmpA[$formattedDate]['value'], array('value' => 0, 'label' => $k));
}
}
}
}
}
// closing test if(isset($rec[$indicator['sdii_api_datefield']]))
} else {
// given keys are inconsistent
logfile(LOG_MAINFILE, array('[API call]', 'ERROR - given array keys are inconsistent : ' . $indicator['sdii_api_valuefield'] . ' / "'. $indicator['sdii_api_datefield']. ' - check url result and change fields values', 'indicator : ' . $indicator['sdii_id'], $indicator['sdii_api_url']));
$rflag = 2; // partial import due to strange values
// return false; // we do no return false to still execute the routine on dataset
}
} // closing test if($recordDate >= $SinceDate)
if($debug) echo '
'; // closing debug container
} // closing loop on records : foreach ($records['results'] as $rec)
// NOW ONLY, we do populate the database based on all prepared information
// we loop on recorded values
//print_r($tmpA);
//exit;
ksort($tmpA); // we order $tmpA in descending order, according to the key.
foreach($tmpA as $k => $v) {
// we select last entered values and compare with frequency to see if we have to execute update routine or not
// for all cases (even initial import) - if set, we get the latest indicator value and date for the given scale
$lastV = $sql_object -> DBSelect(SQL_getlastInsertByPublicationDate($v['indicator'], $v['scale']));
// we prepare $triggerDate based on last value date and interval
if(isset($lastV[0]['sdiv_value']) ) {
$lastDate = $lastV[0]['sdiv_date_published']; // return 2020-01-01
$dateSuffix = substr($lastDate,4);
}
else {
$lastDate = $v['since'];
$dateSuffix = '-12-31';
}
if(strlen($lastDate) == 4) $lastDate .= $dateSuffix;
// we get last date
$lastvalueDate = DateTime::createFromFormat($format, $lastDate);
$triggerDate = $lastvalueDate ;
// we add interval to latest retrieved date
$triggerDate->modify('+' . $indicator['sdii_frequency'] . 'days');
// we finally compare $triggerDate with $recordDate to check if we have to add records in database
if($debug) echo "
Indicator id : ".$indicator['sdii_id'] ." - Since date : " .$v['since'] . " / [comparison] current record \$recordDate - formattedDate (from API) : " . $v['formattedDate'] . ' / last value\'s date (from DB) : ' . $lastvalueDate->format("Y-m-d") . " / trigger date \$triggerdate (from DB) - pour ajout seulement : " . $triggerDate->format("Y-m-d") . ' / frequency : '.$indicator['sdii_frequency'] . " / overwrite values : " . $indicator['sdii_api_overwritevalues'] . '
';
// we overwrite threshold from old values if needed
if(isset($lastV[0]['sdiv_value']) && !is_null($lastV[0]['sdiv_threshold'])) {
$v['threshold'] = $lastV[0]['sdiv_threshold'];
}
// we prepare data for recording in database
$a['nodata'] = $v['nodata'];
$a[0] = $v['value'];
$a[1] = $v['indicator']; // indicator id
$a[2] = $v['threshold']; // threshold
$a[3] = $v['scale']; // scale id
$a[4] = $v['formattedDate'];; // date (format yyyy-mm-dd)
$a[5] = 'p'; // status
$a[6] = _t('sdi', 'api-retrieved'); // comment
$a[7] = 'N'; // comment status
$a['user_id'] = 0; // 0 stands for API
/**
echo "---------------- New record --------------------- ";
print_r($a);
echo "";
*/
$sdio = new sdi;
$integrity = $sdio->CheckDataIntegrity_value($a, $sql_object);
// Indicator is not set to update values, we just add new values if exists
if ($indicator['sdii_api_overwritevalues'] == 'N' && $v['recordDate'] >= $triggerDate) {
if (!is_string($integrity)) {
if ($debug) echo '
ADD VALUE / integrity : ' . $integrity . '
';
$r = $sdio->AddValue($a, $sql_object);
if (is_numeric($r)) logfile(LOG_MAINFILE, array('[API call]', 'SUCCESS - adding values to db', 'indicator : ' . $indicator['sdii_id'], 'added value ID : ' . $r));
} else {
// CheckDataIntegrity_value failed
logfile(LOG_MAINFILE, array('[API call]', 'ERROR - adding values / CheckDataIntegrity_value() failed', 'indicator : ' . $indicator['sdii_id'], $indicator['sdii_api_url'], 'error message : ' . strip_tags((string)$integrity)));
// return false; // we do no return false to still execute the routine on dataset
$rflag = 2; // partial import due to strange values
}
}
// Indicator is set to update values, we do it only if value has changed for a given date
if ($indicator['sdii_api_overwritevalues'] == 'Y') {
$res = $sql_object->DBSelect(SQL_getIndicValuesBydate($v['indicator'], $v['scale'], $v['recordDateFormatted']));
// check if value has changed for a given date and modify value if needed
if (value_has_changed($a, $res, $indicator)) {
if (!is_string($integrity)) {
// value already exists we modify it if needed !
if (isset($res[0]['sdiv_id'])) {
if ($debug) echo '
UPDATE VALUE / integrity : ' . $integrity . '
';
$r = $sdio->ModifyValue($res[0]['sdiv_id'], $a, $sql_object);
if (is_numeric($r)) logfile(LOG_MAINFILE, array('[API call]', 'SUCCESS - modifying values to db', 'indicator : ' . $indicator['sdii_id'], 'added value ID : ' . $r));
} elseif (!isset($res[0]['sdiv_id']) && $v['recordDate'] >= $triggerDate) {
if ($debug) echo '
ADD VALUE / integrity : ' . $integrity . '
';
$r = $sdio->AddValue($a, $sql_object);
if (is_numeric($r)) logfile(LOG_MAINFILE, array('[API call]', 'SUCCESS - adding values to db', 'indicator : ' . $indicator['sdii_id'], 'added value ID : ' . $r));
}
} else {
if (isset($res[0]['sdiv_id'])) {
// CheckDataIntegrity_value failed
logfile(LOG_MAINFILE, array('[API call]', 'ERROR - modifying values / CheckDataIntegrity_value() failed', 'indicator : ' . $indicator['sdii_id'], $res[0]['sdiv_id'], $indicator['sdii_api_url'], 'error message : ' . strip_tags((string)$integrity)));
} else {
logfile(LOG_MAINFILE, array('[API call]', 'ERROR - adding values / CheckDataIntegrity_value() failed', 'indicator : ' . $indicator['sdii_id'], $indicator['sdii_api_url'], 'error message : ' . strip_tags((string)$integrity)));
}
// return false; // we do no return false to still execute the routine on dataset
$rflag = 2; // partial import due to strange values
}
}
}
}
} // closing HTTP response test if($code == '200')
// if 404 exception is caught - others errors as well
} catch (Exception $e) {
logfile(LOG_MAINFILE, array('[API call]', 'URL not responding', $indicator['sdii_api_url'], 'indicator : ' . $indicator['sdii_id'], $e->getMessage()));
$rflag = 3;
}
} // closing $indicator['sdii_api_enabled'] == 'Y' test
}
return $rflag; // 1, 2 or 3 here
}
}
if(!function_exists('value_has_changed')) {
function value_has_changed($a, $res, $indicator) {
$debug = false;
// no record found for the given date, so no modification
if(!is_array($res)) {
if ($debug) echo '
No values is stored for the current year. So, no changes !
';
return true;
}
// for unique type indicator
if($indicator['sdii_value_type'] == 'unique') {
if($debug) {
echo '
'.$res[0]['sdiv_date_published'].' - Value in db : '.sys_number_format(round($res[0]['sdiv_value'], $indicator['sdii_decimal'])).' / Value from API '.sys_number_format(round($a[0], $indicator['sdii_decimal'])).'
';
if (sys_number_format(round($res[0]['sdiv_value'], $indicator['sdii_decimal'])) == sys_number_format(round($a[0], $indicator['sdii_decimal']))) echo '
No changes
';
else echo '
Changes ! Update is needed !
';
}
if($res[0]['sdiv_value'] != $a[0]) return true;
}
// for multiple type indicator
if($indicator['sdii_value_type'] == 'multiple') {
$mapping = unserialize($indicator['sdii_api_multimapping']);
// we format stored values to be able to compared retrieved values with existing ones
$tmp = [];
$currentval = unserialize ($res[0]['sdiv_multivalue']);
foreach ($currentval as $k => $v) {
array_push($tmp, ['value' => $v['value'], 'label' => $v['label']]);
}
if($debug) {
echo '
Formatted values from database : ';
print_r($tmp);
echo '
';
echo '
Formatted values from API : ';
print_r($a[0]);
echo '
';
// there is no value
if ($indicatorValues==false) {
$str .= '-';
// some values are there
} else {
$data = array();
$class = '';
// we reverse the array to display eldest first
$values = array_reverse($indicatorValues);
if(isset($indicatorValues[0]['sdiv_cumulative_value'])) $cumulative_value = $indicatorValues[0]['sdiv_cumulative_value'];
foreach($values as $value) {
// we handle multivalues
if(!empty($value['sdiv_multivalue'])) {
$dataindic = unserialize($value['sdiv_multivalue']);
array_push($data, $dataindic[0][$cfield]);
// we handle simple values
} else {
array_push($data, $value['sdiv_value']);
}
}
$str .= '