Пример #1
0
 /**
  * get relations for a given requirement ID
  * 
  * @author Andreas Simon
  * 
  * @param int $id Requirement ID
  * 
  * @return array $relations in which this req is either source or destination
  */
 public function get_relations($id)
 {
     $debugMsg = '/* Class:' . __CLASS__ . ' - Method: ' . __FUNCTION__ . ' */';
     $relations = array();
     $relations['num_relations'] = 0;
     $relations['req'] = current($this->get_by_id($id));
     $relations['relations'] = array();
     $tproject_mgr = new testproject($this->db);
     $interproject_linking = config_get('req_cfg')->relations->interproject_linking;
     $sql = " {$debugMsg} SELECT id, source_id, destination_id, relation_type, author_id, creation_ts " . " FROM {$this->tables['req_relations']} " . " WHERE source_id={$id} OR destination_id={$id} " . " ORDER BY id ASC ";
     $relations['relations'] = $this->db->get_recordset($sql);
     if (!is_null($relations['relations']) && count($relations['relations']) > 0) {
         $labels = $this->get_all_relation_labels();
         $label_keys = array_keys($labels);
         foreach ($relations['relations'] as $key => $rel) {
             // is this relation type is configured?
             if ($relTypeAllowed = in_array($rel['relation_type'], $label_keys)) {
                 $relations['relations'][$key]['source_localized'] = $labels[$rel['relation_type']]['source'];
                 $relations['relations'][$key]['destination_localized'] = $labels[$rel['relation_type']]['destination'];
                 if ($id == $rel['source_id']) {
                     $type_localized = 'source_localized';
                     $other_key = 'destination_id';
                 } else {
                     $type_localized = 'destination_localized';
                     $other_key = 'source_id';
                 }
                 $relations['relations'][$key]['type_localized'] = $relations['relations'][$key][$type_localized];
                 $other_req = $this->get_by_id($rel[$other_key]);
                 // only add it, if either interproject linking is on or if it is in the same project
                 $relTypeAllowed = false;
                 if ($interproject_linking || $other_req[0]['testproject_id'] == $relations['req']['testproject_id']) {
                     $relTypeAllowed = true;
                     $relations['relations'][$key]['related_req'] = $other_req[0];
                     $other_tproject = $tproject_mgr->get_by_id($other_req[0]['testproject_id']);
                     $relations['relations'][$key]['related_req']['testproject_name'] = $other_tproject['name'];
                     $user = tlUser::getByID($this->db, $rel['author_id']);
                     $relations['relations'][$key]['author'] = $user->getDisplayName();
                 }
             }
             if (!$relTypeAllowed) {
                 unset($relations['relations'][$key]);
             }
         }
         // end foreach
         $relations['num_relations'] = count($relations['relations']);
     }
     return $relations;
 }
Пример #2
0
 /**
  * initialize common test case information, useful when working on steps
  *
  */
 function initTestCaseBasicInfo(&$argsObj, &$guiObj)
 {
     $greenCard = array('tcase_id' => $argsObj->tcase_id, 'tcversion_id' => $argsObj->tcversion_id);
     foreach ($greenCard as $ky) {
         if ($ky == 0) {
             $greenCard = $this->tcaseMgr->getIdCardByStepID($argsObj->step_id);
             break;
         }
     }
     $tcaseInfo = $this->tcaseMgr->get_by_id($greenCard['tcase_id'], $greenCard['tcversion_id'], null, array('output' => 'full_without_steps', 'renderGhost' => true));
     $external = $this->tcaseMgr->getExternalID($greenCard['tcase_id'], $argsObj->testproject_id);
     $tcaseInfo[0]['tc_external_id'] = $external[0];
     $guiObj->testcase = $tcaseInfo[0];
     if (!isset($guiObj->testcase['ghost'])) {
         $guiObj->testcase['ghost'] = null;
     }
     $guiObj->authorObj = tlUser::getByID($this->db, $guiObj->testcase['author_id'], 'id');
     $guiObj->updaterObj = null;
     if (!is_null($guiObj->testcase['updater_id'])) {
         $guiObj->updaterObj = tlUser::getByID($this->db, $guiObj->testcase['updater_id'], 'id');
     }
 }
Пример #3
0
 /**
  * if everything ok returns an array on just one element with following user data
  *
  * firstName,lastName,emailAddress,locale,isActive,defaultTestprojectID,
  * globalRoleID 
  * globalRole    array with role info
  * tprojectRoles array  
  * tplanRoles    array
  * login 
  * dbID
  * loginRegExp
  *
  * ATTENTION: userApiKey will be set to NULL, because is worst that access to user password
  * 
  * @param struct $args
  * @param string $args["devKey"]   
  * @param string $args["userid"]   user ID as present on users table, column ID
  * 
  * @return mixed $ret
  * 
  */
 public function getUserByID($args)
 {
     $messagePrefix = "(" . __FUNCTION__ . ") - ";
     $this->_setArgs($args);
     $checkFunctions = array('authenticate');
     $ret = array();
     $status_ok = $this->_runChecks($checkFunctions, $messagePrefix);
     if ($status_ok) {
         $user = tlUser::getByID($this->dbObj, $this->args[self::$userIDParamName]);
         if (is_null($user)) {
             $status_ok = false;
             $msg = $messagePrefix . sprintf(NO_USER_BY_THIS_ID_STR, $this->args[self::$userIDParamName]);
             $this->errors[] = new IXR_Error(NO_USER_BY_ID_LOGIN, $msg);
         } else {
             $user->userApiKey = null;
             $ret[] = $user;
         }
     }
     return $status_ok ? $ret : $this->errors;
 }
 /**
  * initialize common test case information, useful when working on steps
  *
  */
 function initTestCaseBasicInfo(&$argsObj, &$guiObj, $opt = null)
 {
     $my['opt'] = array('accessByStepID' => true);
     $my['opt'] = array_merge($my['opt'], (array) $opt);
     $greenCard = array('tcase_id' => $argsObj->tcase_id, 'tcversion_id' => $argsObj->tcversion_id);
     if ($my['opt']['accessByStepID']) {
         foreach ($greenCard as $ky) {
             // this logic need to be explained BETTER
             if ($ky == 0) {
                 $greenCard = $this->tcaseMgr->getIdCardByStepID($argsObj->step_id);
                 break;
             }
         }
     }
     $tcaseInfo = $this->tcaseMgr->get_by_id($greenCard['tcase_id'], $greenCard['tcversion_id'], null, array('output' => 'full_without_steps', 'renderGhost' => true, 'renderImageInline' => true));
     $external = $this->tcaseMgr->getExternalID($greenCard['tcase_id'], $argsObj->testproject_id);
     $tcaseInfo[0]['tc_external_id'] = $external[0];
     $guiObj->testcase = $tcaseInfo[0];
     if (!isset($guiObj->testcase['ghost'])) {
         $guiObj->testcase['ghost'] = null;
     }
     $guiObj->authorObj = tlUser::getByID($this->db, $guiObj->testcase['author_id'], 'id');
     $guiObj->updaterObj = null;
     if (!is_null($guiObj->testcase['updater_id'])) {
         $guiObj->updaterObj = tlUser::getByID($this->db, $guiObj->testcase['updater_id'], 'id');
     }
 }
Пример #5
0
 /**
  * Inserts a testproject related role for a given user
  *
  * @param integer $userID the id of the user
  * @param integer $tproject_id
  * @param integer $roleID the role id
  * 
  * @return integer tl::OK on success, tl::ERROR else
  **/
 function addUserRole($userID, $tproject_id, $roleID)
 {
     $query = "INSERT INTO {$this->tables['user_testproject_roles']} " . "(user_id,testproject_id,role_id) VALUES ({$userID},{$tproject_id},{$roleID})";
     if ($this->db->exec_query($query)) {
         $testProject = $this->get_by_id($tproject_id);
         $role = tlRole::getByID($this->db, $roleID, tlRole::TLOBJ_O_GET_DETAIL_MINIMUM);
         $user = tlUser::getByID($this->db, $userID, tlUser::TLOBJ_O_GET_DETAIL_MINIMUM);
         if ($user && $testProject && $role) {
             logAuditEvent(TLS("audit_users_roles_added_testproject", $user->getDisplayName(), $testProject['name'], $role->name), "ASSIGN", $tproject_id, "testprojects");
         }
         return tl::OK;
     }
     return tl::ERROR;
 }
 /**
  * 
  *
  */
 function decode_users(&$rs)
 {
     $userCache = null;
     // key: user id, value: display name
     $key2loop = array_keys($rs);
     $labels['undefined'] = lang_get('undefined');
     $user_keys = array('author' => 'author_id', 'modifier' => 'modifier_id');
     foreach ($key2loop as $key) {
         foreach ($user_keys as $ukey => $userid_field) {
             $rs[$key][$ukey] = '';
             if (trim($rs[$key][$userid_field]) != "") {
                 if (!isset($userCache[$rs[$key][$userid_field]])) {
                     $user = tlUser::getByID($this->db, $rs[$key][$userid_field]);
                     $rs[$key][$ukey] = $user ? $user->getDisplayName() : $labels['undefined'];
                     $userCache[$rs[$key][$userid_field]] = $rs[$key][$ukey];
                 } else {
                     $rs[$key][$ukey] = $userCache[$rs[$key][$userid_field]];
                 }
             }
         }
     }
 }
Пример #7
0
 /**
  * authenticates a user based on the devKey provided 
  * 
  * This is the only method that should really be used directly to authenticate
  *
  * @param string $messagePrefix used to be prepended to error message
  *
  * @return boolean
  * @access protected
  */
 protected function authenticate($messagePrefix = '')
 {
     // check that the key was given as part of the args
     if (!$this->_isDevKeyPresent()) {
         $this->errors[] = new IXR_ERROR(NO_DEV_KEY, $messagePrefix . NO_DEV_KEY_STR);
         $this->authenticated = false;
         return false;
     } else {
         $this->devKey = $this->args[self::$devKeyParamName];
     }
     // make sure the key we have is valid
     if (!$this->_isDevKeyValid($this->devKey)) {
         $this->errors[] = new IXR_Error(INVALID_AUTH, $messagePrefix . INVALID_AUTH_STR);
         $this->authenticated = false;
         return false;
     } else {
         //Load User
         $this->user = tlUser::getByID($this->dbObj, $this->userID);
         $this->authenticated = true;
         return true;
     }
 }
Пример #8
0
         $resBlob .= $initial . '#' . $item['steps'][$sdx]['step_number'] . "\n" . $dummy . "\n";
         $initial = "\n";
     }
 }
 // Get CF values
 $tcCfields = $tcaseMgr->get_linked_cfields_at_design(null, $gui->matrix[$idx]['tcversionid'], null, null, $args->tproject_id);
 $cfieldsValues = array();
 foreach ($tcCfields as $cfid => $cf) {
     // $cfieldsValues[] = $cf['value'];
     $cfieldsValues[] = $tcaseMgr->cfield_mgr->string_custom_field_value($cf, null);
 }
 $uaccessKey =& $gui->matrix[$idx]['results'][0]['tester_id'];
 $testerName = '';
 if (!is_null($uaccessKey)) {
     if (!isset($userCache[uaccessKey])) {
         $userObj = tlUser::getByID($db, $uaccessKey);
         $userCache[$uaccessKey] = $userObj ? $userObj->firstName . ' ' . $userObj->lastName : $labels['undefined'];
     }
     $testerName = $userCache[$uaccessKey];
 }
 $line2write = array_merge($cfieldsValues, array($gui->matrix[$idx]['tcname'], str_replace($target, $replace, $item['summary']), str_replace($target, $replace, $item['preconditions']), $stepBlob, $resBlob, $gui->tc_status_labels[$gui->matrix[$idx]['results'][0]['value']], $testerName, str_replace($target, $replace, $gui->matrix[$idx]['results'][0]['notes'])));
 switch ($args->outputFormat) {
     case 'CSV':
         fputcsv($fp, $line2write);
         break;
     case 'XLSX':
         foreach ($line2write as $ldx => $field) {
             $cellID = $cellRange[$ldx] . $startingRow;
             $objPHPExcel->setActiveSheetIndex(0)->setCellValue($cellID, $field);
             if ($cellRange[$ldx] == $statusCellLetter) {
                 if (isset($i18n[$field])) {
Пример #9
0
 /**
  * initialize common test case information, useful when working on steps
  *
  */
 function initTestCaseBasicInfo(&$argsObj, &$guiObj)
 {
     $tcaseInfo = $this->tcaseMgr->get_by_id($argsObj->tcase_id, $argsObj->tcversion_id, null, array('output' => 'full_without_steps'));
     $external = $this->tcaseMgr->getExternalID($argsObj->tcase_id, $argsObj->testproject_id);
     $tcaseInfo[0]['tc_external_id'] = $external[0];
     $guiObj->testcase = $tcaseInfo[0];
     $guiObj->authorObj = tlUser::getByID($this->db, $guiObj->testcase['author_id'], 'id');
     $guiObj->updaterObj = null;
     if (!is_null($guiObj->testcase['updater_id'])) {
         $guiObj->updaterObj = tlUser::getByID($this->db, $guiObj->testcase['updater_id'], 'id');
     }
 }
Пример #10
0
function setTesterAssignment(&$db, $exec_info, &$tcase_mgr, $tplan_id, $platform_id)
{
    foreach ($exec_info as $version_id => $value) {
        $exec_info[$version_id]['assigned_user'] = '';
        $exec_info[$version_id]['assigned_user_id'] = 0;
        // map of map: main key version_id, secondary key: platform_id
        $p3 = $tcase_mgr->get_version_exec_assignment($version_id, $tplan_id);
        $assignedTesterId = intval($p3[$version_id][$platform_id]['user_id']);
        if ($assignedTesterId) {
            $user = tlUser::getByID($db, $assignedTesterId);
            if ($user) {
                $exec_info[$version_id]['assigned_user'] = $user->getDisplayName();
            }
            $exec_info[$version_id]['assigned_user_id'] = $assignedTesterId;
        }
    }
    return $exec_info;
}
 /**
  *
  */
 public function getRelations($id)
 {
     $debugMsg = "/* {$this->debugMsg}" . __FUNCTION__ . ' */';
     $safeID = intval($id);
     $relSet = array();
     $relSet['num_relations'] = 0;
     $relSet['item'] = current($this->get_by_id($id, self::LATEST_VERSION, null, array('output' => 'essential', 'getPrefix' => true, 'caller' => __FUNCTION__)));
     $relSet['relations'] = array();
     $tproject_mgr = new testproject($this->db);
     $sql = " {$debugMsg} SELECT id, source_id, destination_id, relation_type, author_id, creation_ts " . " FROM {$this->tables['testcase_relations']} " . " WHERE source_id={$safeID} OR destination_id={$safeID} " . " ORDER BY id ASC ";
     $relSet['relations'] = $this->db->get_recordset($sql);
     if (!is_null($relSet['relations']) && count($relSet['relations']) > 0) {
         $labels = $this->getRelationLabels();
         $label_keys = array_keys($labels);
         foreach ($relSet['relations'] as $key => $rel) {
             // is this relation type is configured?
             if ($relTypeAllowed = in_array($rel['relation_type'], $label_keys)) {
                 $relSet['relations'][$key]['source_localized'] = $labels[$rel['relation_type']]['source'];
                 $relSet['relations'][$key]['destination_localized'] = $labels[$rel['relation_type']]['destination'];
                 $type_localized = 'destination_localized';
                 $other_key = 'source_id';
                 if ($id == $rel['source_id']) {
                     $type_localized = 'source_localized';
                     $other_key = 'destination_id';
                 }
                 $relSet['relations'][$key]['type_localized'] = $relSet['relations'][$key][$type_localized];
                 $otherItem = $this->get_by_id($rel[$other_key], self::LATEST_VERSION, null, array('output' => 'essential', 'getPrefix' => true));
                 // only add it, if either interproject linking is on or if it is in the same project
                 $relTypeAllowed = false;
                 //if ($this->relationsCfg->interProjectLinking ||
                 //    ($otherItem[0]['testproject_id'] == $relSet['req']['testproject_id']))
                 //{
                 $relTypeAllowed = true;
                 $relSet['relations'][$key]['related_tcase'] = $otherItem[0];
                 // $other_tproject = $tproject_mgr->get_by_id($otherItem[0]['testproject_id']);
                 // $relSet['relations'][$key]['related_tcase']['testproject_name'] = $other_tproject['name'];
                 $user = tlUser::getByID($this->db, $rel['author_id']);
                 $relSet['relations'][$key]['author'] = $user->getDisplayName();
                 //}
             }
             if (!$relTypeAllowed) {
                 unset($relSet['relations'][$key]);
             }
         }
         // end foreach
         $relSet['num_relations'] = count($relSet['relations']);
     }
     return $relSet;
 }
 /**
  *
  */
 function authenticate(\Slim\Route $route)
 {
     $apiKey = null;
     if (is_null($apiKey)) {
         $request = $this->app->request();
         $apiKey = $request->headers('PHP_AUTH_USER');
     }
     $sql = "SELECT id FROM {$this->tables['users']} " . "WHERE script_key='" . $this->db->prepare_string($apiKey) . "'";
     $this->userID = $this->db->fetchFirstRowSingleColumn($sql, "id");
     if ($ok = !is_null($this->userID)) {
         $this->user = tlUser::getByID($this->db, $this->userID);
     } else {
         $this->app->status(400);
         echo json_encode(array('status' => 'ko', 'message' => 'authentication error'));
         $this->app->stop();
     }
     return $ok;
 }
Пример #13
0
function setTesterAssignment(&$db, $exec_info, &$tcase_mgr, $tplan_id, $platform_id, $build_id)
{
    foreach ($exec_info as $version_id => $value) {
        $exec_info[$version_id]['assigned_user'] = null;
        $exec_info[$version_id]['assigned_user_id'] = null;
        // map of map: main key version_id, secondary key: platform_id
        $p3 = $tcase_mgr->get_version_exec_assignment($version_id, $tplan_id, $build_id);
        if (!is_null($p3)) {
            foreach ($p3[$version_id][$platform_id] as $uu) {
                $assignedTesterId = intval($uu['user_id']);
                if ($assignedTesterId) {
                    $user = tlUser::getByID($db, $assignedTesterId);
                    if ($user) {
                        $exec_info[$version_id]['assigned_user'][] = $user->getDisplayName();
                    }
                    $exec_info[$version_id]['assigned_user_id'][] = $assignedTesterId;
                }
            }
        }
        $exec_info[$version_id]['assigned_user'] = implode(',', (array) $exec_info[$version_id]['assigned_user']);
        $exec_info[$version_id]['assigned_user_id'] = implode(',', (array) $exec_info[$version_id]['assigned_user_id']);
    }
    return $exec_info;
}
Пример #14
0
 /**
  * Inserts a testplan related role for a given user
  *
  * @param int $userID the id of the user
  * @param int $id the testplan id
  * @param int $roleID the role id
  * 
  * @return integer returns tl::OK on success, tl::ERROR else
  **/
 function addUserRole($userID, $id, $roleID)
 {
     $debugMsg = 'Class:' . __CLASS__ . ' - Method: ' . __FUNCTION__;
     $status = tl::ERROR;
     $sql = " /* {$debugMsg} */ INSERT INTO {$this->tables['user_testplan_roles']} (user_id,testplan_id,role_id) VALUES " . " ({$userID},{$id},{$roleID})";
     if ($this->db->exec_query($sql)) {
         $testPlan = $this->get_by_id($id);
         $role = tlRole::getByID($this->db, $roleID, tlRole::TLOBJ_O_GET_DETAIL_MINIMUM);
         $user = tlUser::getByID($this->db, $userID, tlUser::TLOBJ_O_GET_DETAIL_MINIMUM);
         if ($user && $testPlan && $role) {
             logAuditEvent(TLS("audit_users_roles_added_testplan", $user->getDisplayName(), $testPlan['name'], $role->name), "ASSIGN", $id, "testplans");
         }
         $status = tl::OK;
     }
     return $status;
 }
Пример #15
0
/**
 * get user name from pool (save used names in session to improve performance)
 * 
 * @param integer $db DB connection identifier 
 * @param integer $userId
 * 
 * @return string readable user name
 * @author havlatm
 */
function gendocGetUserName(&$db, $userId)
{
    $authorName = null;
    if (isset($_SESSION['userNamePool'][$userId])) {
        $authorName = $_SESSION['userNamePool'][$userId];
    } else {
        $user = tlUser::getByID($db, $userId);
        if ($user) {
            $authorName = $user->getDisplayName();
            $authorName = htmlspecialchars($authorName);
            $_SESSION['userNamePool'][$userId] = $authorName;
        } else {
            $authorName = lang_get('undefined');
            tLog('tlUser::getByID($db,$userId) failed', 'ERROR');
        }
    }
    return $authorName;
}
 function get_by_id($id)
 {
     $debugMsg = 'Class:' . __CLASS__ . ' - Method: ' . __FUNCTION__;
     $sql = "/* {$debugMsg} */ " . " SELECT '' AS author, '' AS modifier, NH.node_order, " . " RSPEC.id,testproject_id,RSPEC.scope,RSPEC.total_req,RSPEC.type," . " RSPEC.author_id,RSPEC.creation_ts,RSPEC.modifier_id," . " RSPEC.modification_ts,NH.name AS title,RSPEC.doc_id " . " FROM {$this->object_table} RSPEC,  {$this->tables['nodes_hierarchy']} NH" . " WHERE RSPEC.id = NH.id " . " AND RSPEC.id = {$id}";
     $recordset = $this->db->get_recordset($sql);
     $rs = null;
     if (!is_null($recordset)) {
         // Decode users
         $rs = $recordset[0];
         if (trim($rs['author_id']) != "") {
             $user = tlUser::getByID($this->db, $rs['author_id']);
             // need to manage deleted users
             if ($user) {
                 $rs['author'] = $user->getDisplayName();
             } else {
                 $rs['author'] = lang_get('undefined');
             }
         }
         if (trim($rs['modifier_id']) != "") {
             $user = tlUser::getByID($this->db, $rs['modifier_id']);
             // need to manage deleted users
             if ($user) {
                 $rs['modifier'] = $user->getDisplayName();
             } else {
                 $rs['modifier'] = lang_get('undefined');
             }
         }
     }
     return $rs;
 }
Пример #17
0
 function getByIDBulkLatestVersionRevision($id, $opt = null)
 {
     static $debugMsg;
     static $userCache;
     // key: user id, value: display name
     static $lables;
     static $user_keys;
     if (!$debugMsg) {
         $debugMsg = 'Class:' . __CLASS__ . ' - Method: ' . __FUNCTION__;
         $labels['undefined'] = lang_get('undefined');
         $user_keys = array('author' => 'author_id', 'modifier' => 'modifier_id');
     }
     $my['opt'] = array('outputFormat' => 'map');
     $my['opt'] = array_merge($my['opt'], (array) $opt);
     $in_clause = "IN (" . implode(",", (array) $id) . ") ";
     $where_clause = " WHERE NH_REQV.parent_id " . $in_clause;
     // added -1 AS revision_id to make some process easier
     $sql = " /* {$debugMsg} */ SELECT REQ.id,REQ.srs_id,REQ.req_doc_id," . " REQV.scope,REQV.status,REQV.type,REQV.active," . " REQV.is_open,REQV.author_id,REQV.version,REQV.id AS version_id," . " REQV.expected_coverage,REQV.creation_ts,REQV.modifier_id," . " REQV.modification_ts,REQV.revision, -1 AS revision_id, " . " NH_REQ.name AS title, REQ_SPEC.testproject_id, " . " NH_RSPEC.name AS req_spec_title, REQ_SPEC.doc_id AS req_spec_doc_id, NH_REQ.node_order " . " FROM {$this->tables['nodes_hierarchy']} NH_REQV JOIN " . "( SELECT XNH_REQV.parent_id,MAX(XNH_REQV.id) AS LATEST_VERSION_ID " . "  FROM  {$this->tables['nodes_hierarchy']} XNH_REQV " . "  WHERE XNH_REQV.parent_id {$in_clause} " . "  GROUP BY XNH_REQV.parent_id ) ZAZA ON NH_REQV.id = ZAZA.LATEST_VERSION_ID " . " JOIN {$this->tables['req_versions']} REQV ON REQV.id = NH_REQV.id " . " JOIN {$this->object_table} REQ ON REQ.id = NH_REQV.parent_id " . " JOIN {$this->tables['req_specs']} REQ_SPEC ON REQ_SPEC.id = REQ.srs_id " . " JOIN {$this->tables['nodes_hierarchy']} NH_RSPEC ON NH_RSPEC.id = REQ_SPEC.id " . " JOIN {$this->tables['nodes_hierarchy']} NH_REQ ON NH_REQ.id = REQ.id " . $where_clause;
     // echo $sql;
     $sqlOpt = $my['opt']['outputFormat'] == 'map' ? 0 : database::CUMULATIVE;
     $recordset = $this->db->fetchRowsIntoMap($sql, 'id', $sqlOpt);
     $rs = null;
     // echo 'IN::' . __FUNCTION__ . '<br>';
     // new dBug($recordset);
     if (!is_null($recordset)) {
         // Decode users
         $rs = $recordset;
         // try to guess output structure
         $x = array_keys(current($rs));
         if (is_int($x[0])) {
             // output[REQID][0] = array('id' =>, 'xx' => ...)
             $flevel = array_keys($recordset);
             foreach ($flevel as $flk) {
                 $key2loop = array_keys($recordset[$flk]);
                 foreach ($key2loop as $key) {
                     foreach ($user_keys as $ukey => $userid_field) {
                         $rs[$flk][$key][$ukey] = '';
                         if (trim($rs[$flk][$key][$userid_field]) != "") {
                             if (!isset($userCache[$rs[$flk][$key][$userid_field]])) {
                                 $user = tlUser::getByID($this->db, $rs[$flk][$key][$userid_field]);
                                 $rs[$flk][$key][$ukey] = $user ? $user->getDisplayName() : $labels['undefined'];
                                 $userCache[$rs[$flk][$key][$userid_field]] = $rs[$flk][$key][$ukey];
                                 unset($user);
                             } else {
                                 $rs[$flk][$key][$ukey] = $userCache[$rs[$flk][$key][$userid_field]];
                             }
                         }
                     }
                 }
             }
         } else {
             // output[REQID] = array('id' =>, 'xx' => ...)
             $key2loop = array_keys($recordset);
             foreach ($key2loop as $key) {
                 foreach ($user_keys as $ukey => $userid_field) {
                     $rs[$key][$ukey] = '';
                     if (trim($rs[$key][$userid_field]) != "") {
                         if (!isset($userCache[$rs[$key][$userid_field]])) {
                             $user = tlUser::getByID($this->db, $rs[$key][$userid_field]);
                             $rs[$key][$ukey] = $user ? $user->getDisplayName() : $labels['undefined'];
                             $userCache[$rs[$key][$userid_field]] = $rs[$key][$ukey];
                             unset($user);
                         } else {
                             $rs[$key][$ukey] = $userCache[$rs[$key][$userid_field]];
                         }
                     }
                 }
             }
         }
     }
     unset($recordset);
     unset($my);
     unset($dummy);
     return $rs;
 }