Exemple #1
0
 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;
 }