public function query($q) { $parser = new Parser($this->user, $q); $error = $parser->parse(); if ($error) { return $parser->getError(); } $mysql_query = $parser->getSql(); $meta = $parser->getObjectMetaData(); $this->pearDB->startTransaction(); $result = $this->pearDB->pquery($mysql_query, array()); $error = $this->pearDB->hasFailedTransaction(); $this->pearDB->completeTransaction(); if ($error) { throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR, "Database error while performing required operation"); } $noofrows = $this->pearDB->num_rows($result); $output = array(); for ($i = 0; $i < $noofrows; $i++) { $row = $this->pearDB->fetchByAssoc($result, $i); if (!$meta->hasPermission(EntityMeta::$RETRIEVE, $row["crmid"])) { continue; } $output[] = DataTransform::sanitizeDataWithColumn($row, $meta); } return $output; }
public function query($q) { $parser = new Parser($this->user, $q); if (stripos($q, 'related.') > 0) { // related query require_once 'include/Webservices/Utils.php'; require_once 'include/Webservices/GetRelatedRecords.php'; $queryParameters['columns'] = trim(substr($q, 6, stripos($q, ' from ') - 5)); $moduleRegex = "/[fF][rR][Oo][Mm]\\s+([^\\s;]+)/"; preg_match($moduleRegex, $q, $m); $relatedModule = trim($m[1]); $moduleRegex = "/[rR][eE][lL][aA][tT][eE][dD]\\.([^\\s;]+)\\s*=\\s*([^\\s;]+)/"; preg_match($moduleRegex, $q, $m); $moduleName = trim($m[1]); $id = trim($m[2], "(')"); $mysql_query = __getRLQuery($id, $moduleName, $relatedModule, $queryParameters, $this->user); // where, limit and order $afterwhere = substr($q, stripos($q, ' where ') + 6); // eliminate related conditions $relatedCond = "/\\(*[rR][eE][lL][aA][tT][eE][dD]\\.([^\\s;]+)\\s*=\\s*([^\\s;]+)\\)*\\s*([aA][nN][dD]|[oO][rR]\\s)*/"; preg_match($relatedCond, $afterwhere, $pieces); $glue = isset($pieces[3]) ? trim($pieces[3]) : 'and'; $afterwhere = trim(preg_replace($relatedCond, '', $afterwhere), ' ;'); $relatedCond = "/\\s+([aA][nN][dD]|[oO][rR])+\\s+([oO][rR][dD][eE][rR])+/"; $afterwhere = trim(preg_replace($relatedCond, ' order ', $afterwhere), ' ;'); $relatedCond = "/\\s+([aA][nN][dD]|[oO][rR])+\\s+([lL][iI][mM][iI][tT])+/"; $afterwhere = trim(preg_replace($relatedCond, ' limit ', $afterwhere), ' ;'); // if related is at the end of condition we need to strip last and|or if (strtolower(substr($afterwhere, -3)) == 'and') { $afterwhere = substr($afterwhere, 0, strlen($afterwhere) - 3); } if (strtolower(substr($afterwhere, -2)) == 'or') { $afterwhere = substr($afterwhere, 0, strlen($afterwhere) - 2); } // transform REST ids $relatedCond = "/=\\s*'*\\d+x(\\d+)'*/"; $afterwhere = preg_replace($relatedCond, ' = $1 ', $afterwhere); // kill unbalanced parenthesis $balanced = 0; $pila = array(); for ($ch = 0; $ch < strlen($afterwhere); $ch++) { if ($afterwhere[$ch] == '(') { $pila[$balanced] = array('pos' => $ch, 'dir' => '('); $balanced++; } elseif ($afterwhere[$ch] == ')') { if ($balanced > 0 and $pila[$balanced - 1]['dir'] == '(') { array_pop($pila); $balanced--; } else { $pila[$balanced] = array('pos' => $ch, 'dir' => ')'); $balanced++; } } } foreach ($pila as $paren) { $afterwhere[$paren['pos']] = ' '; } // transform artificial commentcontent for FAQ and Ticket comments if (strtolower($relatedModule) == 'modcomments' and (strtolower($moduleName) == 'helpdesk' or strtolower($moduleName) == 'faq')) { $afterwhere = str_ireplace('commentcontent', 'comments', $afterwhere); } // transform fieldnames to columnnames $handler = vtws_getModuleHandlerFromName($relatedModule, $this->user); $meta = $handler->getMeta(); $fldmap = $meta->getFieldColumnMapping(); $tblmap = $meta->getColumnTableMapping(); $tok = strtok($afterwhere, ' '); $chgawhere = ''; while ($tok !== false) { if (!empty($fldmap[$tok])) { $chgawhere .= (strpos($tok, '.') ? '' : $tblmap[$fldmap[$tok]] . '.') . $fldmap[$tok] . ' '; } else { $chgawhere .= $tok . ' '; } $tok = strtok(' '); } $afterwhere = $chgawhere; if (!empty($afterwhere)) { $start = strtolower(substr(trim($afterwhere), 0, 5)); if ($start != 'limit' and $start != 'order') { // there is a condition we add the glue $mysql_query .= " {$glue} "; } $mysql_query .= " {$afterwhere}"; } if (stripos($q, 'count(*)') > 0) { $mysql_query = str_ireplace(' as count ', '', mkCountQuery($mysql_query)); } } else { $error = $parser->parse(); if ($error) { return $parser->getError(); } $mysql_query = $parser->getSql(); $meta = $parser->getObjectMetaData(); } $this->pearDB->startTransaction(); $result = $this->pearDB->pquery($mysql_query, array()); $error = $this->pearDB->hasFailedTransaction(); $this->pearDB->completeTransaction(); if ($error) { throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR, vtws_getWebserviceTranslatedString('LBL_' . WebServiceErrorCode::$DATABASEQUERYERROR)); } $noofrows = $this->pearDB->num_rows($result); $output = array(); for ($i = 0; $i < $noofrows; $i++) { $row = $this->pearDB->fetchByAssoc($result, $i); if (!$meta->hasPermission(EntityMeta::$RETRIEVE, $row["crmid"])) { continue; } $output[] = DataTransform::sanitizeDataWithColumn($row, $meta); } return $output; }
function vtws_sync($mtime, $elementType, $syncType, $user) { global $adb, $recordString, $modifiedTimeString; $numRecordsLimit = 100; $ignoreModules = array("Users"); $typed = true; $dformat = "Y-m-d H:i:s"; $datetime = date($dformat, $mtime); $setypeArray = array(); $setypeData = array(); $setypeHandler = array(); $setypeNoAccessArray = array(); $output = array(); $output["updated"] = array(); $output["deleted"] = array(); $applicationSync = false; if (is_object($syncType) && $syncType instanceof Users) { $user = $syncType; } else { if ($syncType == 'application') { $applicationSync = true; } else { if ($syncType == 'userandgroup') { $userAndGroupSync = true; } } } if ($applicationSync && !is_admin($user)) { throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED, "Only admin users can perform application sync"); } $ownerIds = array($user->id); // To get groupids in which this user exist if ($userAndGroupSync) { $groupresult = $adb->pquery("select groupid from vtiger_users2group where userid=?", array($user->id)); $numOfRows = $adb->num_rows($groupresult); if ($numOfRows > 0) { for ($i = 0; $i < $numOfRows; $i++) { $ownerIds[count($ownerIds)] = $adb->query_result($groupresult, $i, "groupid"); } } } // End if (!isset($elementType) || $elementType == '' || $elementType == null) { $typed = false; } $adb->startTransaction(); $accessableModules = array(); $entityModules = array(); $modulesDetails = vtws_listtypes(null, $user); $moduleTypes = $modulesDetails['types']; $modulesInformation = $modulesDetails["information"]; foreach ($modulesInformation as $moduleName => $entityInformation) { if ($entityInformation["isEntity"]) { $entityModules[] = $moduleName; } } if (!$typed) { $accessableModules = $entityModules; } else { if (!in_array($elementType, $entityModules)) { throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED, "Permission to perform the operation is denied"); } $accessableModules[] = $elementType; } $accessableModules = array_diff($accessableModules, $ignoreModules); if (count($accessableModules) <= 0) { $output['lastModifiedTime'] = $mtime; $output['more'] = false; return $output; } if ($typed) { $handler = vtws_getModuleHandlerFromName($elementType, $user); $moduleMeta = $handler->getMeta(); $entityDefaultBaseTables = $moduleMeta->getEntityDefaultTableList(); //since there will be only one base table for all entities $baseCRMTable = $entityDefaultBaseTables[0]; if ($elementType == "Calendar" || $elementType == "Events") { $baseCRMTable = getSyncQueryBaseTable($elementType); } } else { $baseCRMTable = " vtiger_crmentity "; } //modifiedtime - next token $q = "SELECT modifiedtime FROM {$baseCRMTable} WHERE modifiedtime>? and setype IN(" . generateQuestionMarks($accessableModules) . ") "; $params = array($datetime); foreach ($accessableModules as $entityModule) { if ($entityModule == "Events") { $entityModule = "Calendar"; } $params[] = $entityModule; } if (!$applicationSync) { $q .= ' and smownerid IN(' . generateQuestionMarks($ownerIds) . ')'; $params = array_merge($params, $ownerIds); } $q .= " order by modifiedtime limit {$numRecordsLimit}"; $result = $adb->pquery($q, $params); $modTime = array(); for ($i = 0; $i < $adb->num_rows($result); $i++) { $modTime[] = $adb->query_result($result, $i, 'modifiedtime'); } if (!empty($modTime)) { $maxModifiedTime = max($modTime); } if (!$maxModifiedTime) { $maxModifiedTime = $datetime; } foreach ($accessableModules as $elementType) { $handler = vtws_getModuleHandlerFromName($elementType, $user); $moduleMeta = $handler->getMeta(); $deletedQueryCondition = $moduleMeta->getEntityDeletedQuery(); preg_match_all("/(?:\\s+\\w+[ \t\n\r]+)?([^=]+)\\s*=([^\\s]+|'[^']+')/", $deletedQueryCondition, $deletedFieldDetails); $fieldNameDetails = $deletedFieldDetails[1]; $deleteFieldValues = $deletedFieldDetails[2]; $deleteColumnNames = array(); foreach ($fieldNameDetails as $tableName_fieldName) { $fieldComp = explode(".", $tableName_fieldName); $deleteColumnNames[$tableName_fieldName] = $fieldComp[1]; } $params = array($moduleMeta->getTabName(), $datetime, $maxModifiedTime); $queryGenerator = new QueryGenerator($elementType, $user); $fields = array(); $moduleFields = $moduleMeta->getModuleFields(); $moduleFieldNames = getSelectClauseFields($elementType, $moduleMeta, $user); $moduleFieldNames[] = 'id'; $queryGenerator->setFields($moduleFieldNames); $selectClause = "SELECT " . $queryGenerator->getSelectClauseColumnSQL(); // adding the fieldnames that are present in the delete condition to the select clause // since not all fields present in delete condition will be present in the fieldnames of the module foreach ($deleteColumnNames as $table_fieldName => $columnName) { if (!in_array($columnName, $moduleFieldNames)) { $selectClause .= ", " . $table_fieldName; } } if ($elementType == "Emails") { $fromClause = vtws_getEmailFromClause(); } else { $fromClause = $queryGenerator->getFromClause(); } $fromClause .= " INNER JOIN (select modifiedtime, crmid,deleted,setype FROM {$baseCRMTable} WHERE setype=? and modifiedtime >? and modifiedtime<=?"; if (!$applicationSync) { $fromClause .= 'and smownerid IN(' . generateQuestionMarks($ownerIds) . ')'; $params = array_merge($params, $ownerIds); } $fromClause .= ' ) vtiger_ws_sync ON (vtiger_crmentity.crmid = vtiger_ws_sync.crmid)'; $q = $selectClause . " " . $fromClause; $result = $adb->pquery($q, $params); $recordDetails = array(); $deleteRecordDetails = array(); while ($arre = $adb->fetchByAssoc($result)) { $key = $arre[$moduleMeta->getIdColumn()]; if (vtws_isRecordDeleted($arre, $deleteColumnNames, $deleteFieldValues)) { if (!$moduleMeta->hasAccess()) { continue; } $output["deleted"][] = vtws_getId($moduleMeta->getEntityId(), $key); } else { if (!$moduleMeta->hasAccess() || !$moduleMeta->hasPermission(EntityMeta::$RETRIEVE, $key)) { continue; } try { $output["updated"][] = DataTransform::sanitizeDataWithColumn($arre, $moduleMeta); } catch (WebServiceException $e) { //ignore records the user doesn't have access to. continue; } catch (Exception $e) { throw new WebServiceException(WebServiceErrorCode::$INTERNALERROR, "Unknown Error while processing request"); } } } } $q = "SELECT crmid FROM {$baseCRMTable} WHERE modifiedtime>? and setype IN(" . generateQuestionMarks($accessableModules) . ")"; $params = array($maxModifiedTime); foreach ($accessableModules as $entityModule) { if ($entityModule == "Events") { $entityModule = "Calendar"; } $params[] = $entityModule; } if (!$applicationSync) { $q .= 'and smownerid IN(' . generateQuestionMarks($ownerIds) . ')'; $params = array_merge($params, $ownerIds); } $result = $adb->pquery($q, $params); if ($adb->num_rows($result) > 0) { $output['more'] = true; } else { $output['more'] = false; } if (!$maxModifiedTime) { $modifiedtime = $mtime; } else { $modifiedtime = vtws_getSeconds($maxModifiedTime); } if (is_string($modifiedtime)) { $modifiedtime = intval($modifiedtime); } $output['lastModifiedTime'] = $modifiedtime; $error = $adb->hasFailedTransaction(); $adb->completeTransaction(); if ($error) { throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR, vtws_getWebserviceTranslatedString('LBL_' . WebServiceErrorCode::$DATABASEQUERYERROR)); } VTWS_PreserveGlobal::flush(); return $output; }
public function query($q) { $mysql_query = $this->wsVTQL2SQL($q, $meta, $queryRelatedModules); $this->pearDB->startTransaction(); $result = $this->pearDB->pquery($mysql_query, array()); $error = $this->pearDB->hasFailedTransaction(); $this->pearDB->completeTransaction(); if ($error) { throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR, vtws_getWebserviceTranslatedString('LBL_' . WebServiceErrorCode::$DATABASEQUERYERROR)); } $noofrows = $this->pearDB->num_rows($result); $output = array(); for ($i = 0; $i < $noofrows; $i++) { $row = $this->pearDB->fetchByAssoc($result, $i); if (!$meta->hasPermission(EntityMeta::$RETRIEVE, $row["crmid"])) { continue; } $newrow = DataTransform::sanitizeDataWithColumn($row, $meta); if (__FQNExtendedQueryIsFQNQuery($q)) { // related query $relflds = array_diff_key($row, $newrow); foreach ($queryRelatedModules as $relmod => $relmeta) { $lrm = strtolower($relmod); $newrflds = array(); foreach ($relflds as $fldname => $fldvalue) { $fldmod = substr($fldname, 0, strlen($relmod)); if (isset($row[$fldname]) and $fldmod == $lrm) { $newkey = substr($fldname, strlen($lrm)); $newrflds[$newkey] = $fldvalue; } } $relrow = DataTransform::sanitizeDataWithColumn($newrflds, $relmeta); $newrelrow = array(); foreach ($relrow as $key => $value) { $newrelrow[$lrm . $key] = $value; } $newrow = array_merge($newrow, $newrelrow); } } $output[] = $newrow; } return $output; }