2021-04-28 20:10:26 +02:00

244 lines
8.5 KiB
PHP

<?php
/*************************************
* SPDX-FileCopyrightText: 2009-2020 Vtenext S.r.l. <info@vtenext.com>
* SPDX-License-Identifier: AGPL-3.0-only
************************************/
require_once("include/Webservices/Extra/ModuleTypes.php");
require_once("include/Webservices/Extra/DescribeObject.php");
function vtws_queryExtra($q,$user,$limit=false){
global $adb,$table_prefix;
$moduleRegex = "/[fF][rR][Oo][Mm]\s+([^\s;]+)/";
$moduleName = '';
if(preg_match($moduleRegex, $q, $m)) $moduleName = trim($m[1]);
$module_obj = WebserviceExtra::getInstance($moduleName);
if (!$module_obj){
throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED,"Permission to perform the operation is denied");
}
$obj = $module_obj->describe();
$mapping = $module_obj->columnMapping();
$fields = Array();
if (!empty($obj['fields'])){
foreach ($obj['fields'] as $field_arr){
$fields[$field_arr['name']] = $mapping[$field_arr['name']];
}
}
$modules_ids = Array();
$sql = "select id,name from ".$table_prefix."_ws_entity";
$res = $adb->query($sql);
if ($res){
while($row = $adb->fetchByAssoc($res,-1,false)){
$module_ids[$row['name']] = $row['id'];
}
}
$extramodule_id = $module_obj->id;
$function = Array();
$add_fields_arr = Array();
$replace = '';
$module_obj->query_parameters($function,$add_fields_arr,$replace);
if ($replace == ''){
throw new WebServiceException(WebServiceErrorCode::$QUERYSYNTAX,"No query defined for this module");
}
require_once 'include/Webservices/Extra/SQLParser/PHPSQLParser.php';
require_once 'include/Webservices/Extra/SQLParser/PHPSQLCreator.php';
$parser = new PHPSQLParser($q);
if (!isset($parser->parsed['SELECT']) || isset($parser->parsed['UPDATE']) || isset($parser->parsed['DELETE']) || isset($parser->parsed['CREATE']) || isset($parser->parsed['DROP']) || isset($parser->parsed['ALTER'])){
throw new WebServiceException(WebServiceErrorCode::$QUERYSYNTAX, "Only select statements allowed.");
}
//replace from fields
$add_fields = true;
$onlycount = false;
//permit cont(*)
if ($parser->parsed['SELECT'][0]['expr_type'] == 'aggregate_function'){
if ($parser->parsed['SELECT'][0]['base_expr'] == 'count' && $parser->parsed['SELECT'][0]['sub_tree'][0]['base_expr'] == '*' && empty($parser->parsed['SELECT'][0]['alias'])){
$add_fields = false;
$parser->parsed['SELECT'][0]['alias'] = Array(
'as'=>1,
'name'=>'count',
'base_expr'=>'as count',
'no_quotes'=>'count',
);
$parser->parsed['SELECT'] = Array($parser->parsed['SELECT'][0]);
$onlycount = true;
}
else{
throw new WebServiceException(WebServiceErrorCode::$QUERYSYNTAX, "Only count(*) is permitted as aggregate function");
}
}
//permit *
elseif ($parser->parsed['SELECT'][0]['expr_type'] == 'colref' && $parser->parsed['SELECT'][0]['base_expr'] == '*' ){
$parser->parsed['SELECT'] = Array($parser->parsed['SELECT'][0]);
$add_fields = false;
}
//control from fields
else{
foreach ($parser->parsed['SELECT'] as &$select){
if (!isset($fields[$select['base_expr']])){
throw new WebServiceException(WebServiceErrorCode::$QUERYSYNTAX, "Unknown column '{$select['base_expr']}' for select statement");
}
elseif (!empty($select['alias'])){
throw new WebServiceException(WebServiceErrorCode::$QUERYSYNTAX, "Alias for column '{$select['base_expr']}' not permitted in select statement");
}
else{ //transform select mapping real field
$select['base_expr'] = $select['no_quotes'] = $fields[$select['base_expr']];
}
}
}
//control where fields
if (isset($parser->parsed['WHERE'])){
foreach ($parser->parsed['WHERE'] as &$where){
if ($where['expr_type'] == 'colref'){
if(!isset($fields[$where['base_expr']])){
throw new WebServiceException(WebServiceErrorCode::$QUERYSYNTAX, "Unknown column '{$where['base_expr']}' for where statement");
}
else{//transform where mapping real field
$where['base_expr'] = $where['no_quotes'] = $fields[$where['base_expr']];
}
}
}
}
//control order by fields
if (isset($parser->parsed['ORDER'])){
foreach ($parser->parsed['ORDER'] as &$order){
if ($order['expr_type'] == 'colref'){
if(!isset($fields[$order['base_expr']])){
throw new WebServiceException(WebServiceErrorCode::$QUERYSYNTAX, "Unknown column '{$order['base_expr']}' for order by statement");
}
else{//transform where mapping real field
$order['base_expr'] = $order['no_quotes'] = $fields[$order['base_expr']];
}
}
}
}
$limit = false;
//control limit
if (isset($parser->parsed['LIMIT'])){
if ($parser->parsed['LIMIT']['offset'] != '' && $parser->parsed['LIMIT']['offset'] < 0){
throw new WebServiceException(WebServiceErrorCode::$QUERYSYNTAX, "Limit offset cannot be negative");
}
if ($parser->parsed['LIMIT']['rowcount'] != '' && $parser->parsed['LIMIT']['rowcount'] < 0){
throw new WebServiceException(WebServiceErrorCode::$QUERYSYNTAX, "Limit rowcount cannot be negative");
}
$limit = true;
if ($parser->parsed['LIMIT']['offset'] == ''){
$parser->parsed['LIMIT']['offset'] = 0;
}
$limit_arr = Array(
'offset'=>$parser->parsed['LIMIT']['offset'],
'rowcount'=>$parser->parsed['LIMIT']['rowcount'],
);
unset($parser->parsed['LIMIT']); //use adodb limit instead query
}
if ($add_fields){
//add extra fields
if (!empty($add_fields_arr)){
foreach ($add_fields_arr as $field_add){
$parser->parsed['SELECT'][] = Array(
'expr_type' => 'colref',
'alias' => '',
'base_expr' => $field_add,
'sub_tree' => '',
'delim' => ''
);
}
}
//add id field
$found_id = false;
foreach ($parser->parsed['SELECT'] as $select_){
if ($select_['base_expr'] == $mapping['id']){
$found_id = true;
}
}
if (!$found_id){
$parser->parsed['SELECT'][] = Array(
'expr_type' => 'colref',
'alias' => '',
'base_expr' => $mapping['id'],
'sub_tree' => '',
'delim' => ''
);
}
}
$cnt = 1;
$max = count($parser->parsed['SELECT']);
foreach ($parser->parsed['SELECT'] as &$select){
if ($cnt < $max){
$select['delim'] = ',';
}
else{
$select['delim'] = '';
}
$cnt++;
}
$creator = new PHPSQLCreator($parser->parsed);
$q = $creator->created;
$q = str_replace(" {$moduleName}",$replace,$q);
try{
if ($limit){
$res = $adb->limitQuery($q,$limit_arr['offset'],$limit_arr['rowcount']);
}
else{
$res = $adb->query($q);
}
if ($res){
$return_arr = Array();
while($row = $adb->fetchByAssoc($res)){
$row_change = Array();
if ($onlycount){
$row_change['count'] = $row['count'];
}
else{
foreach ($obj['fields'] as $field_arr){
if (isset($row[$mapping[$field_arr['name']]])){
//process field
switch($field_arr['type']['name']){
case 'autogenerated':
//transform id_modulexid_record
$row_change[$field_arr['name']] = $extramodule_id."x".$row[$mapping[$field_arr['name']]];
break;
case 'owner':
$row_change[$field_arr['name']] = $module_ids['Users']."x".$row[$mapping[$field_arr['name']]];
break;
case 'reference':
if (count($field_arr['type']['refersTo']) > 1){
if (isset($function[$field_arr['name']]) && $function[$field_arr['name']] != '' && $row[$mapping[$function[$field_arr['name']]]] != ''){
//take related module from another field
$row_change[$field_arr['name']] = $module_ids[$row[$mapping[$function[$field_arr['name']]]]]."x".$row[$mapping[$field_arr['name']]];
}
else{
$row_change[$field_arr['name']] = '';
//take related module from id
if ($row[$mapping[$field_arr['name']]] != ''){
//crmv@171021
$setype = getSalesEntityType($row[$mapping[$field_arr['name']]]);
if (!empty($setype)) {
$row_change[$field_arr['name']] = $module_ids[$setype]."x".$row[$mapping[$field_arr['name']]];
}
//crmv@171021e
}
}
}
else{
$row_change[$field_arr['name']] = $module_ids[$field_arr['type']['refersTo'][0]]."x".$row[$mapping[$field_arr['name']]];
}
break;
default:
$row_change[$field_arr['name']] = $row[$mapping[$field_arr['name']]];
break;
}
}
}
}
$return_arr[] = $row_change;
}
}
}
catch(Exception $e) {
throw new WebServiceException(WebServiceErrorCode::$QUERYSYNTAX, "Error running query");
}
return $return_arr;
}
?>