/** * Actualizar la clave maestra del usuario en la BBDD. * * @param string $masterPwd con la clave maestra * @return bool */ public function updateUserMPass($masterPwd) { $configHashMPass = ConfigDB::getValue('masterPwd'); if ($configHashMPass === false) { return false; } if (is_null($configHashMPass)) { $configHashMPass = Crypt::mkHashPassword($masterPwd); ConfigDB::setValue('masterPwd', $configHashMPass); } if (Crypt::checkHashPass($masterPwd, $configHashMPass, true)) { $cryptMPass = Crypt::mkCustomMPassEncrypt(self::getCypherPass(), $masterPwd); if (!$cryptMPass) { return false; } } else { return false; } $query = 'UPDATE usrData SET ' . 'user_mPass = :mPass,' . 'user_mIV = :mIV,' . 'user_lastUpdateMPass = UNIX_TIMESTAMP() ' . 'WHERE user_id = :id LIMIT 1'; $data['mPass'] = $cryptMPass[0]; $data['mIV'] = $cryptMPass[1]; $data['id'] = $this->_userId; return DB::getQuery($query, __FUNCTION__, $data); }
/** * Insertar los grupos de usuarios en sysPass. * * @param array $usersGroups con los datos del grupo * @throws SPException * @return bool */ private static function insertUsersGroups($usersGroups) { $query = 'INSERT INTO usrGroups ' . 'SET usergroup_id = :id,' . 'usergroup_name = :name,' . 'usergroup_description = :description'; $data['id'] = $usersGroups['intUGroupId']; $data['name'] = $usersGroups['vacUGroupName']; $data['description'] = $usersGroups['vacUGroupDesc']; if (DB::getQuery($query, __FUNCTION__, $data) === false) { throw new SPException(SPException::SP_CRITICAL, _('Error al crear los grupos de usuarios'), DB::$txtError); } return true; }
/** * Obtener el número de cuentas que usan una categoría. * * @param int $id con el Id de la categoría a consultar * @return false|integer con el número total de cuentas */ private static function getCategoriesInAccounts($id) { $query = 'SELECT account_id FROM accounts WHERE account_categoryId = :id'; $data['id'] = $id; DB::getQuery($query, __FUNCTION__, $data); return DB::$lastNumRows; }
/** * Elimina un parámetro de la configuración. * * @param string $param clave * @return bool */ public static function deleteParam($param) { $query = 'DELETE FROM config WHERE config_parameter = :param LIMIT 1'; $data['param'] = $param; return DB::getQuery($query, __FUNCTION__, $data) !== false; }
/** * Modificar las preferencias de un usuario * * @return bool */ public function updatePreferences() { $query = 'UPDATE usrData SET ' . 'user_preferences = :preferences ' . 'WHERE user_id = :id LIMIT 1'; $data['id'] = $this->getId(); $data['preferences'] = serialize($this); if (DB::getQuery($query, __FUNCTION__, $data) === false) { return false; } return true; }
/** * Actualiza la BBDD según la versión. * * @param int $version con la versión a actualizar * @returns bool */ private static function upgradeTo($version) { $log = new Log(_('Actualizar BBDD')); switch ($version) { case 110: $queries[] = 'ALTER TABLE `accFiles` CHANGE COLUMN `accfile_name` `accfile_name` VARCHAR(100) NOT NULL'; $queries[] = 'ALTER TABLE `accounts` ADD COLUMN `account_otherGroupEdit` BIT(1) NULL DEFAULT 0 AFTER `account_dateEdit`, ADD COLUMN `account_otherUserEdit` BIT(1) NULL DEFAULT 0 AFTER `account_otherGroupEdit`;'; $queries[] = 'CREATE TABLE `accUsers` (`accuser_id` INT NOT NULL AUTO_INCREMENT,`accuser_accountId` INT(10) UNSIGNED NOT NULL,`accuser_userId` INT(10) UNSIGNED NOT NULL, PRIMARY KEY (`accuser_id`), INDEX `idx_account` (`accuser_accountId` ASC)) DEFAULT CHARSET=utf8;'; $queries[] = 'ALTER TABLE `accHistory` ADD COLUMN `accHistory_otherUserEdit` BIT NULL AFTER `acchistory_mPassHash`, ADD COLUMN `accHistory_otherGroupEdit` VARCHAR(45) NULL AFTER `accHistory_otherUserEdit`;'; $queries[] = 'ALTER TABLE `accFiles` CHANGE COLUMN `accfile_type` `accfile_type` VARCHAR(100) NOT NULL ;'; break; case 1121: $queries[] = 'ALTER TABLE `categories` ADD COLUMN `category_description` VARCHAR(255) NULL AFTER `category_name`;'; $queries[] = 'ALTER TABLE `usrProfiles` ADD COLUMN `userProfile_pAppMgmtMenu` BIT(1) NULL DEFAULT b\'0\' AFTER `userProfile_pUsersMenu`,CHANGE COLUMN `userProfile_pConfigCategories` `userProfile_pAppMgmtCategories` BIT(1) NULL DEFAULT b\'0\' AFTER `userProfile_pAppMgmtMenu`,ADD COLUMN `userProfile_pAppMgmtCustomers` BIT(1) NULL DEFAULT b\'0\' AFTER `userProfile_pAppMgmtCategories`;'; break; case 1122: $queries[] = 'ALTER TABLE `usrData` CHANGE COLUMN `user_login` `user_login` VARCHAR(50) NOT NULL ,CHANGE COLUMN `user_email` `user_email` VARCHAR(80) NULL DEFAULT NULL ;'; break; case 1123: $queries[] = 'CREATE TABLE `usrPassRecover` (`userpassr_id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `userpassr_userId` SMALLINT UNSIGNED NOT NULL,`userpassr_hash` VARBINARY(40) NOT NULL,`userpassr_date` INT UNSIGNED NOT NULL,`userpassr_used` BIT(1) NOT NULL DEFAULT b\'0\', PRIMARY KEY (`userpassr_id`),INDEX `IDX_userId` (`userpassr_userId` ASC, `userpassr_date` ASC)) DEFAULT CHARSET=utf8;'; $queries[] = 'ALTER TABLE `log` ADD COLUMN `log_ipAddress` VARCHAR(45) NOT NULL AFTER `log_userId`;'; $queries[] = 'ALTER TABLE `usrData` ADD COLUMN `user_isChangePass` BIT(1) NULL DEFAULT b\'0\' AFTER `user_isMigrate`;'; break; case 11213: $queries[] = 'ALTER TABLE `usrData` CHANGE COLUMN `user_mPass` `user_mPass` VARBINARY(32) NULL DEFAULT NULL ,CHANGE COLUMN `user_lastLogin` `user_lastLogin` DATETIME NULL DEFAULT NULL ,CHANGE COLUMN `user_lastUpdate` `user_lastUpdate` DATETIME NULL DEFAULT NULL, CHANGE COLUMN `user_mIV` `user_mIV` VARBINARY(32) NULL ;'; $queries[] = 'ALTER TABLE `accounts` CHANGE COLUMN `account_login` `account_login` VARCHAR(50) NULL DEFAULT NULL ;'; break; case 11219: $queries[] = 'ALTER TABLE `accounts` CHANGE COLUMN `account_pass` `account_pass` VARBINARY(255) NOT NULL ;'; $queries[] = 'ALTER TABLE `accHistory` CHANGE COLUMN `acchistory_pass` `acchistory_pass` VARBINARY(255) NOT NULL ;'; break; case 11220: $queries[] = 'ALTER TABLE `usrData` CHANGE COLUMN `user_pass` `user_pass` VARBINARY(255) NOT NULL,CHANGE COLUMN `user_mPass` `user_mPass` VARBINARY(255) DEFAULT NULL ;'; break; case 12001: $queries[] = 'ALTER TABLE `accounts` CHANGE COLUMN `account_userEditId` `account_userEditId` TINYINT(3) UNSIGNED NULL DEFAULT NULL, CHANGE COLUMN `account_dateEdit` `account_dateEdit` DATETIME NULL DEFAULT NULL;'; $queries[] = 'ALTER TABLE `accHistory` CHANGE COLUMN `acchistory_userEditId` `acchistory_userEditId` TINYINT(3) UNSIGNED NULL DEFAULT NULL, CHANGE COLUMN `acchistory_dateEdit` `acchistory_dateEdit` DATETIME NULL DEFAULT NULL;'; $queries[] = 'ALTER TABLE `accHistory` CHANGE COLUMN `accHistory_otherGroupEdit` `accHistory_otherGroupEdit` BIT NULL DEFAULT b\'0\';'; $queries[] = 'ALTER TABLE `usrProfiles` ADD COLUMN `userProfile_profile` BLOB NOT NULL;'; $queries[] = 'ALTER TABLE `usrData` ADD `user_preferences` BLOB NULL;'; $queries[] = 'CREATE TABLE usrToGroups (usertogroup_id INT UNSIGNED PRIMARY KEY NOT NULL AUTO_INCREMENT,usertogroup_userId INT UNSIGNED NOT NULL,usertogroup_groupId INT UNSIGNED NOT NULL) DEFAULT CHARSET=utf8;'; $queries[] = 'CREATE INDEX IDX_accountId ON usrToGroups (usertogroup_userId)'; $queries[] = 'ALTER TABLE `accFiles` ADD `accFile_thumb` BLOB NULL;'; $queries[] = 'CREATE TABLE `authTokens` (`authtoken_id` int(11) NOT NULL AUTO_INCREMENT,`authtoken_userId` int(11) NOT NULL,`authtoken_token` varbinary(100) NOT NULL,`authtoken_actionId` smallint(5) unsigned NOT NULL,`authtoken_createdBy` smallint(5) unsigned NOT NULL,`authtoken_startDate` int(10) unsigned NOT NULL,PRIMARY KEY (`authtoken_id`),UNIQUE KEY `unique_authtoken_id` (`authtoken_id`),KEY `IDX_checkToken` (`authtoken_userId`,`authtoken_actionId`,`authtoken_token`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;'; $queries[] = 'CREATE TABLE `customFieldsDef` (`customfielddef_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `customfielddef_module` smallint(5) unsigned NOT NULL, `customfielddef_field` blob NOT NULL, PRIMARY KEY (`customfielddef_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;'; $queries[] = 'CREATE TABLE `customFieldsData` (`customfielddata_id` int(10) unsigned NOT NULL AUTO_INCREMENT,`customfielddata_moduleId` smallint(5) unsigned NOT NULL,`customfielddata_itemId` int(10) unsigned NOT NULL,`customfielddata_defId` int(10) unsigned NOT NULL,`customfielddata_data` longblob,`customfielddata_iv` varbinary(128) DEFAULT NULL, PRIMARY KEY (`customfielddata_id`), KEY `IDX_DEFID` (`customfielddata_defId`), KEY `IDX_DELETE` (`customfielddata_itemId`,`customfielddata_moduleId`), KEY `IDX_UPDATE` (`customfielddata_moduleId`,`customfielddata_itemId`,`customfielddata_defId`), KEY `IDX_ITEM` (`customfielddata_itemId`), KEY `IDX_MODULE` (`customfielddata_moduleId`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;'; break; case 12002: $queries[] = 'ALTER TABLE config CHANGE config_value config_value VARCHAR(255);'; $queries[] = 'ALTER TABLE usrData CHANGE user_pass user_pass VARBINARY(255);'; $queries[] = 'ALTER TABLE usrData CHANGE user_hashSalt user_hashSalt VARBINARY(128);'; $queries[] = 'ALTER TABLE accHistory CHANGE acchistory_mPassHash acchistory_mPassHash VARBINARY(255);'; break; default: $log->addDescription(_('No es necesario actualizar la Base de Datos.')); return true; } foreach ($queries as $query) { try { DB::getQuery($query, __FUNCTION__); } catch (SPException $e) { $log->addDescription(_('Error al aplicar la actualización de la Base de Datos.') . ' (v' . $version . ')'); $log->addDescription('ERROR: ' . $e->getMessage() . ' (' . $e->getCode() . ')'); $log->writeLog(); Email::sendEmail($log); return false; } } $log->addDescription(_('Actualización de la Base de Datos realizada correctamente.') . ' (v' . $version . ')'); $log->writeLog(); Email::sendEmail($log); return true; }
/** * Crear asociación de grupos con cuentas. * * @param int $accountId con el Id de la cuenta * @param array $usersId con los grupos de la cuenta * @return bool */ public static function addUsersForAccount($accountId, $usersId) { if (!is_array($usersId)) { return true; } $values = ''; // Obtenemos los grupos actuales $usersExcluded = self::getUsersForAccount($accountId); foreach ($usersId as $userId) { // Excluimos los usuarios actuales if (isset($usersExcluded) && is_array($usersExcluded) && in_array($userId, $usersExcluded)) { continue; } $values[] = '(' . (int) $accountId . ',' . (int) $userId . ')'; } if (!is_array($values)) { return true; } $query = 'INSERT INTO accUsers (accuser_accountId, accuser_userId) VALUES ' . implode(',', $values); return DB::getQuery($query, __FUNCTION__); }
/** * Actualizar un perfil. * * @return bool */ public function profileUpdate() { $oldProfileName = static::getProfileNameById($this->getId()); $query = 'UPDATE usrProfiles SET ' . 'userprofile_name = :name,' . 'userprofile_profile = :profile ' . 'WHERE userprofile_id = :id LIMIT 1'; $data['id'] = $this->getId(); $data['name'] = $this->getName(); $data['profile'] = serialize($this); if (DB::getQuery($query, __FUNCTION__, $data) === false) { return false; } Log::writeNewLogAndEmail(_('Modificar Perfil'), Html::strongText(_('Perfil') . ': ') . $oldProfileName . ' > ' . $this->getName()); return true; }
/** * Establecer el campo isMigrate de cada usuario */ public static function setMigrateUsers() { $query = 'UPDATE usrData SET user_isMigrate = 1'; return DB::getQuery($query, __FUNCTION__); }
/** * Actualiza el último inicio de sesión del usuario en la BBDD. * * @param $userId int El id del usuario * @return bool */ public static function setUserLastLogin($userId) { $query = 'UPDATE usrData SET user_lastLogin = NOW(),user_count = user_count + 1 WHERE user_id = :id LIMIT 1'; $data['id'] = $userId; return DB::getQuery($query, __FUNCTION__, $data); }
/** * Eliminar un usuario. * * @return bool */ public function deleteUser() { $userLogin = UserUtil::getUserLoginById($this->_userId); $query = 'DELETE FROM usrData WHERE user_id = :id LIMIT 1'; $data['id'] = $this->_userId; if (DB::getQuery($query, __FUNCTION__, $data) === false) { return false; } $this->queryLastId = DB::$lastId; Log::writeNewLogAndEmail(_('Eliminar Usuario'), sprintf('%s: %s', Html::strongText(_('Login')), $userLogin)); return true; }
/** * Crear un nuevo registro de histório de cuenta en la BBDD. * * @param int $id el id de la cuenta primaria * @param bool $isDelete indica que la cuenta es eliminada * @return bool */ public static function addHistory($id, $isDelete = false) { $query = 'INSERT INTO accHistory ' . '(acchistory_accountId,' . 'acchistory_categoryId,' . 'acchistory_customerId,' . 'acchistory_name,' . 'acchistory_login,' . 'acchistory_url,' . 'acchistory_pass,' . 'acchistory_IV,' . 'acchistory_notes,' . 'acchistory_countView,' . 'acchistory_countDecrypt,' . 'acchistory_dateAdd,' . 'acchistory_dateEdit,' . 'acchistory_userId,' . 'acchistory_userGroupId,' . 'acchistory_userEditId,' . 'acchistory_otherUserEdit,' . 'acchistory_otherGroupEdit,' . 'acchistory_isModify,' . 'acchistory_isDeleted,' . 'acchistory_mPassHash) ' . 'SELECT account_id,' . 'account_categoryId,' . 'account_customerId,' . 'account_name,' . 'account_login,' . 'account_url,' . 'account_pass,' . 'account_IV,' . 'account_notes,' . 'account_countView,' . 'account_countDecrypt,' . 'account_dateAdd,' . 'account_dateEdit,' . 'account_userId,' . 'account_userGroupId,' . 'account_userEditId,' . 'account_otherUserEdit,' . 'account_otherGroupEdit,' . ':isModify,' . ':isDelete,' . ':masterPwd ' . 'FROM accounts WHERE account_id = :account_id'; $data['account_id'] = $id; $data['isModify'] = $isDelete === false ? 1 : 0; $data['isDelete'] = $isDelete === false ? 0 : 1; $data['masterPwd'] = ConfigDB::getValue('masterPwd'); return DB::getQuery($query, __FUNCTION__, $data); }
/** * Elimina los archivos de una cuenta en la BBDD. * * @param int $accountId con el Id de la cuenta * @return bool */ public static function deleteAccountFiles($accountId) { $query = 'DELETE FROM accFiles WHERE accfile_accountId = :id'; $data['id'] = $accountId; return DB::getQuery($query, __FUNCTION__, $data); }
<?php include 'Database.php'; // Include the class $dataBase = new DB(); // Create new DB object $sqlInsert = "INSERT INTO testTable (`test1`, `test2`) VALUES('This', 'is a test')"; // Basic SQL INSERT statment $dataBase->runQuery($sqlInsert); // This will run the SQL statement above and will throw an exception if the SQL statement is bad. $sqlSelect = "SELECT test1, test2 FROM testTable WHERE test1 = 'This'"; // Basic SQL SELECT Statment $data = $dataBase->getQuery($sqlSelect); // This will run the SQL statment and return and associative array. foreach ($data as $d) { echo $d["test1"] . " " . $d["test2"] . "!"; // This will output "This is a test!" }
/** * Actualizar campo personalizado * * @return bool */ public function updateCustomField() { $curField = self::getCustomFields($this->_id, true); $query = 'UPDATE customFieldsDef SET ' . 'customfielddef_module = :module, ' . 'customfielddef_field = :field ' . 'WHERE customfielddef_id= :id LIMIT 1'; $data['module'] = $this->_module; $data['field'] = serialize($this); $data['id'] = $this->_id; $queryRes = DB::getQuery($query, __FUNCTION__, $data); if ($queryRes && $curField->customfielddef_module !== $this->_module) { $queryRes = CustomFields::updateCustomFieldModule($this->_module, $this->_id); } return $queryRes; }
/** * Actualiza el hash de las cuentas en el histórico. * * @param $newHash string El nuevo hash de la clave maestra * @return bool */ public static function updateAccountsMPassHash($newHash) { $query = 'UPDATE accHistory SET ' . 'acchistory_mPassHash = :newHash ' . 'WHERE acchistory_mPassHash = :oldHash'; $data['newHash'] = $newHash; $data['oldHash'] = ConfigDB::getValue('masterPwd'); return DB::getQuery($query, __FUNCTION__, $data); }
/** * Escribir un nuevo evento en el registro de eventos * * @param bool $resetDescription Restablecer la descripción * @return bool */ public function writeLog($resetDescription = false) { if (defined('IS_INSTALLER') && IS_INSTALLER === 1) { error_log('Action: ' . $this->getAction() . ' -- Description: ' . $this->getDescription()); } if (!Util::logIsEnabled()) { return false; } $query = 'INSERT INTO log SET ' . 'log_date = UNIX_TIMESTAMP(),' . 'log_login = :login,' . 'log_userId = :userId,' . 'log_ipAddress = :ipAddress,' . 'log_action = :action,' . 'log_description = :description'; $data['login'] = Session::getUserLogin(); $data['userId'] = Session::getUserId(); $data['ipAddress'] = $_SERVER['REMOTE_ADDR']; $data['action'] = $this->getAction(); $data['description'] = $this->getDescription(); if ($resetDescription === true) { $this->resetDescription(); } return DB::getQuery($query, __FUNCTION__, $data); }
/** * Modificar la clave de un usuario. * * @param $userId * @param $userPass * @return bool */ public static function updateUserPass($userId, $userPass) { $passdata = self::makeUserPassHash($userPass); $userLogin = UserUtil::getUserLoginById($userId); $query = 'UPDATE usrData SET ' . 'user_pass = :pass,' . 'user_hashSalt = :salt,' . 'user_isChangePass = 0,' . 'user_lastUpdate = NOW() ' . 'WHERE user_id = :id LIMIT 1'; $data['pass'] = $passdata['pass']; $data['salt'] = $passdata['salt']; $data['id'] = $userId; if (DB::getQuery($query, __FUNCTION__, $data) === false) { return false; } self::$queryLastId = DB::$lastId; Log::writeNewLogAndEmail(_('Modificar Clave Usuario'), sprintf('%s : %s', Html::strongText(_('Login')), $userLogin)); return true; }
/** * Eliminar los datos de un campo personalizado o los de una definición de campos * * @param int $itemId El Id del elemento asociado al campo * @return bool */ public static function deleteCustomFieldForItem($itemId, $moduleId) { $query = 'DELETE FROM customFieldsData ' . 'WHERE customfielddata_itemId = :itemid ' . 'AND customfielddata_moduleId = :moduleid LIMIT 1'; $data['itemid'] = $itemId; $data['moduleid'] = $moduleId; $queryRes = DB::getQuery($query, __FUNCTION__, $data); return $queryRes; }
/** * Comprobar si los datos del usuario de LDAP están en la BBDD. * * @return bool */ public static function checkLDAPUserInDB($userId) { $query = 'SELECT user_login FROM usrData WHERE user_login = :login LIMIT 1'; $data['login'] = $userId; return DB::getQuery($query, __FUNCTION__, $data) === true && DB::$lastNumRows === 1; }
/** * Comprobar el token de seguridad * * @param $actionId int El id de la accion * @param $token string El token de seguridad * @return bool */ public static function checkAuthToken($actionId, $token) { $query = 'SELECT authtoken_id FROM authTokens ' . 'WHERE authtoken_actionId = :actionId ' . 'AND authtoken_token = :token ' . 'LIMIT 1'; $data['actionId'] = $actionId; $data['token'] = $token; DB::getQuery($query, __FUNCTION__, $data); return DB::$lastNumRows === 1; }
/** * Actualiza la clave de una cuenta en la BBDD. * * @param bool $isMassive para no actualizar el histórico ni enviar mensajes * @param bool $isRestore indica si es una restauración * @return bool */ public function updateAccountPass($isMassive = false, $isRestore = false) { $Log = new Log(__FUNCTION__); // No actualizar el histórico si es por cambio de clave maestra o restauración if (!$isMassive && !$isRestore) { // Guardamos una copia de la cuenta en el histórico if (!AccountHistory::addHistory($this->getAccountId(), false)) { $Log->addDescription(_('Error al actualizar el historial')); $Log->writeLog(); return false; } } $query = 'UPDATE accounts SET ' . 'account_pass = :accountPass,' . 'account_IV = :accountIV,' . 'account_userEditId = :accountUserEditId,' . 'account_dateEdit = NOW() ' . 'WHERE account_id = :accountId'; $data['accountPass'] = $this->getAccountPass(); $data['accountIV'] = $this->getAccountIV(); $data['accountUserEditId'] = $this->getAccountUserEditId(); $data['accountId'] = $this->getAccountId(); if (DB::getQuery($query, __FUNCTION__, $data) === false) { return false; } // No escribir en el log ni enviar correos si la actualización es // por cambio de clave maestra o restauración if (!$isMassive && !$isRestore) { $accountInfo = array('customer_name', 'account_name'); $this->getAccountInfoById($accountInfo); $Log->setAction(_('Modificar Clave')); $Log->addDescription(Html::strongText(_('Cliente') . ': ') . $this->_cacheParams['customer_name']); $Log->addDescription(Html::strongText(_('Cuenta') . ': ') . $this->_cacheParams['account_name'] . " (" . $this->getAccountId() . ")"); $Log->writeLog(); Email::sendEmail($Log); } return true; }
/** * Insertar un registro de recuperación de clave. * * @param string $login con el login del usuario * @param string $hash con el hash para el cambio * @return bool */ public static function addPassRecover($login, $hash) { $query = 'INSERT INTO usrPassRecover SET ' . 'userpassr_userId = :userId,' . 'userpassr_hash = :hash,' . 'userpassr_date = UNIX_TIMESTAMP(),' . 'userpassr_used = 0'; $data['userId'] = UserUtil::getUserIdByLogin($login); $data['hash'] = $hash; return DB::getQuery($query, __FUNCTION__, $data); }
/** * Obtener el número de usuarios que usan un perfil. * * @param $id int El id del perfil * @return false|int con el número total de cuentas */ private static function getProfileInUsersCount($id) { $query = 'SELECT user_profileId FROM usrData WHERE user_profileId = :id'; $data['id'] = $id; DB::getQuery($query, __FUNCTION__, $data); return DB::$lastNumRows; }