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; }
/** * Get the list of changed record after $mtime * @param <type> $mtime * @param <type> $user * @param <type> $limit */ function getChangedRecords($uniqueId, $mtime, $limit = 100) { global $current_user, $adb; $datetime = date('Y-m-d H:i:s', $mtime); $accessibleModules = $this->getModTrackerEnabledModules(); if (empty($accessibleModules)) { throw new Exception('Modtracker not enabled for any modules'); } $query = "SELECT id, module, modifiedtime, vtiger_crmentity.crmid, smownerid, vtiger_modtracker_basic.status\n FROM vtiger_modtracker_basic\n INNER JOIN vtiger_crmentity ON vtiger_modtracker_basic.crmid = vtiger_crmentity.crmid\n AND vtiger_modtracker_basic.changedon = vtiger_crmentity.modifiedtime\n WHERE id > ? AND changedon >= ? AND module IN(" . generateQuestionMarks($accessibleModules) . ")\n ORDER BY id"; $params = array($uniqueId, $datetime); foreach ($accessibleModules as $entityModule) { $params[] = $entityModule; } if ($limit != false) { $query .= " LIMIT {$limit}"; } $result = $adb->pquery($query, $params); $modTime = array(); $rows = $adb->num_rows($result); for ($i = 0; $i < $rows; $i++) { $status = $adb->query_result($result, $i, 'status'); $record['uniqueid'] = $adb->query_result($result, $i, 'id'); $record['modifiedtime'] = $adb->query_result($result, $i, 'modifiedtime'); $record['module'] = $adb->query_result($result, $i, 'module'); $record['crmid'] = $adb->query_result($result, $i, 'crmid'); $record['assigneduserid'] = $adb->query_result($result, $i, 'smownerid'); if ($status == ModTracker::$DELETED) { $deletedRecords[] = $record; } elseif ($status == ModTracker::$CREATED) { $createdRecords[] = $record; } elseif ($status == ModTracker::$UPDATED) { $updatedRecords[] = $record; } $modTime[] = $record['modifiedtime']; $uniqueIds[] = $record['uniqueid']; } if (!empty($uniqueIds)) { $maxUniqueId = max($uniqueIds); } if (empty($maxUniqueId)) { $maxUniqueId = $uniqueId; } if (!empty($modTime)) { $maxModifiedTime = max($modTime); } if (!$maxModifiedTime) { $maxModifiedTime = $datetime; } $output['created'] = $createdRecords; $output['updated'] = $updatedRecords; $output['deleted'] = $deletedRecords; $moreQuery = "SELECT * FROM vtiger_modtracker_basic WHERE id > ? AND changedon >= ? AND module\n IN(" . generateQuestionMarks($accessibleModules) . ")"; $param = array($maxUniqueId, $maxModifiedTime); foreach ($accessibleModules as $entityModule) { $param[] = $entityModule; } $result = $adb->pquery($moreQuery, $param); if ($adb->num_rows($result) > 0) { $output['more'] = true; } else { $output['more'] = false; } $output['uniqueid'] = $maxUniqueId; if (!$maxModifiedTime) { $modifiedtime = $mtime; } else { $modifiedtime = vtws_getSeconds($maxModifiedTime); } if (is_string($modifiedtime)) { $modifiedtime = intval($modifiedtime); } $output['lastModifiedTime'] = $modifiedtime; return $output; }
function vtws_sync($mtime, $elementType, $user) { global $adb, $recordString, $modifiedTimeString; $ignoreModules = array(""); $typed = true; $dformat = "Y-m-d H:i:s"; $datetime = date($dformat, $mtime); $setypeArray = array(); $setypeData = array(); $setypeHandler = array(); $setypeNoAccessArray = array(); if (!isset($elementType) || $elementType == '' || $elementType == null) { $typed = false; } $adb->startTransaction(); $q = "select crmid,setype from vtiger_crmentity where modifiedtime >? and smownerid=? and deleted=0"; $params = array($datetime, $user->id); if ($typed) { $q = $q . " and setype=?"; array_push($params, $elementType); } $result = $adb->pquery($q, $params); do { if ($arre) { if (strpos($arre["setype"], " ") === FALSE) { if ($arre["setype"] == 'Calendar') { $seType = vtws_getCalendarEntityType($arre['crmid']); } else { $seType = $arre["setype"]; } if (array_search($seType, $ignoreModules) === FALSE) { $setypeArray[$arre["crmid"]] = $seType; if (!$setypeData[$seType]) { $webserviceObject = VtigerWebserviceObject::fromName($adb, $seType); $handlerPath = $webserviceObject->getHandlerPath(); $handlerClass = $webserviceObject->getHandlerClass(); require_once $handlerPath; $setypeHandler[$seType] = new $handlerClass($webserviceObject, $user, $adb, $log); $meta = $setypeHandler[$seType]->getMeta(); $setypeData[$seType] = new VtigerCRMObject(getTabId($meta->getEntityName()), true); } } } } $arre = $adb->fetchByAssoc($result); } while ($arre); $output = array(); $output["updated"] = array(); foreach ($setypeArray as $key => $val) { $handler = $setypeHandler[$val]; $meta = $handler->getMeta(); if (!$meta->hasAccess() || !$meta->hasWriteAccess() || !$meta->hasPermission(EntityMeta::$RETRIEVE, $key)) { if (!$setypeNoAccessArray[$val]) { $setypeNoAccessArray[] = $val; } continue; } try { $error = $setypeData[$val]->read($key); if (!$error) { //Ignore records whose fetch results in an error. continue; } $output["updated"][] = DataTransform::filterAndSanitize($setypeData[$val]->getFields(), $meta); } 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"); } } $setypeArray = array(); $setypeData = array(); $q = "select crmid,setype,modifiedtime from vtiger_crmentity where modifiedtime >? and smownerid=? and deleted=1"; $params = array($datetime, $user->id); if ($typed) { $q = $q . " and setype=?"; array_push($params, $elementType); } $result = $adb->pquery($q, $params); do { if ($arre) { if (strpos($arre["setype"], " ") === FALSE) { if ($arre["setype"] == 'Calendar') { $seType = vtws_getCalendarEntityType($arre['crmid']); } else { $seType = $arre["setype"]; } if (array_search($seType, $ignoreModules) === FALSE) { $setypeArray[$arre["crmid"]] = $seType; if (!$setypeData[$seType]) { $webserviceObject = VtigerWebserviceObject::fromName($adb, $seType); $handlerPath = $webserviceObject->getHandlerPath(); $handlerClass = $webserviceObject->getHandlerClass(); require_once $handlerPath; $setypeHandler[$seType] = new $handlerClass($webserviceObject, $user, $adb, $log); $meta = $setypeHandler[$seType]->getMeta(); $setypeData[$seType] = new VtigerCRMObject(getTabId($meta->getEntityName()), true); } } } } $arre = $adb->fetchByAssoc($result); } while ($arre); $output["deleted"] = array(); foreach ($setypeArray as $key => $val) { $handler = $setypeHandler[$val]; $meta = $handler->getMeta(); if (!$meta->hasAccess() || !$meta->hasWriteAccess()) { if (!$setypeNoAccessArray[$val]) { $setypeNoAccessArray[] = $val; } continue; } $output["deleted"][] = vtws_getId($meta->getEntityId(), $key); } $q = "select max(modifiedtime) as modifiedtime from vtiger_crmentity where modifiedtime >? and smownerid=?"; $params = array($datetime, $user->id); if ($typed) { $q = $q . " and setype=?"; array_push($params, $elementType); } else { if (sizeof($setypeNoAccessArray) > 0) { $q = $q . " and setype not in ('" . generateQuestionMarks($setypeNoAccessArray) . "')"; array_push($params, $setypeNoAccessArray); } } $result = $adb->pquery($q, $params); $arre = $adb->fetchByAssoc($result); $modifiedtime = $arre['modifiedtime']; if (!$modifiedtime) { $modifiedtime = $mtime; } else { $modifiedtime = vtws_getSeconds($modifiedtime); } if (is_string($modifiedtime)) { $modifiedtime = intval($modifiedtime); } $output['lastModifiedTime'] = $modifiedtime; $error = $adb->hasFailedTransaction(); $adb->completeTransaction(); if ($error) { throw new WebServiceException(WebServiceErrorCode::$DATABASEQUERYERROR, "Database error while performing required operation"); } VTWS_PreserveGlobal::flush(); return $output; }