* @since Version 1.0 */ class cDbLog { private $module; private $userId = 0; private $userType = 1; // 1 - pub, 2 - cms private $logTables = []; private $logTableData = [ 'mod_accounting', 'mod_accounting_counting', 'mod_accounting_storage', 'mod_partners', 'mod_partners_data', //'mod_balance', 'mod_documents', 'mod_documents_partners', 'mod_documents_settings', 'mod_documents_table', //'mod_objects', //'mod_objects_2', //'mod_objects_links', 'mod_transaction_types', 'mod_visitors_register', ]; private $vDoNotLogActions = [ 'SELECT' ]; public $sOperationOverWrite = ''; const C_SQL_TABLE = 'temp_db_log'; // Log for all executed queries const C_BASE_ACTION_TABLE = 'temp_action_log'; // Base Action base db log table const C_ACTION_TABLE = 'temp_db_log_actions'; // Action base db log table const C_TABLE_SEP = 'temp_db_log_'; // Each table log temp data const C_OP_INSERT = 'INSERT'; const C_OP_UPDATE = 'UPDATE'; const C_OP_DELETE = 'DELETE'; const C_OP_LOGICAL_DELETE = 'LOGICAL_DELETE'; const C_OP_SYS_LOGIN = 'SYS_LOGIN'; /** * Class constructor * @param int|bool $userId - user id to link to log * @param bool $bCmsSide - indicates whether user is cms side */ public function __construct($userId = false, $bCmsSide = false) { $this->userId = $userId; $this->userType = ($bCmsSide ? 2 : 1); $this->module = new cDbLogModule(); } /** * Function to generally log all table data * * @author Mareks Keišs * @category LIB DB logger * @param string $query - query to log * @param mixed $table - query containing affected table * @param bool|string $sWhere - log changes condition to meet * @param bool|string $sOperationType - operation type to set * @return int - new log record ID */ public function log($query, $table = false, $sWhere = false, $sOperationType = false) { $logId = 0; // Case when multiple table passed - logger wont copy data $table = (is_array($table) ? implode(' | ', $table) : $table); $sSql = preg_replace('/\s+/u', ' ', str_replace("\r\n", "", $query)); if (!$sOperationType) { $sOperationType = trim($this->sOperationOverWrite ? $this->sOperationOverWrite : $this->getOperationTypeFromSql($sSql)); $this->sOperationOverWrite = ''; } if (!in_array($sOperationType, $this->vDoNotLogActions)) { $logId = $this->module->insLog(self::C_SQL_TABLE, array( 'date' => time(), 'user_id' => $this->userId, 'user_type' => $this->userType, 'op_type' => $sOperationType, 'affected_table' => $table, 'json_data' => '', 'executed_query' => $sSql )); // Backup old data if (in_array($table, $this->logTableData) && !!$sWhere && $sWhere != cDb::DEF_WHERE) { $this->module->logData($logId, self::C_TABLE_SEP . $table, $this->userId, $table, $sWhere); } } return $logId; } /** * Function to generally log all table data * * @author Mareks Keišs * @category LIB DB logger * @param string $query - query to log * @param string|bool $table - query containing affected table * @param array $insertData - insert log data array * @return string - encrypted string */ public function logArray($query, $table, $insertData = array()) { $logId = $this->log($query, $table); // Backup old data if (in_array($table, $this->logTableData) && $insertData && count($insertData)) { // Add log table data before insert foreach ($insertData as &$v) { $v['pk'] = '0'; $v['log_id'] = &$logId; $v['log_date'] = time(); $v['log_user_id'] = $this->userId; } unset($v); $this->module->cDb->_queryInsertArray(self::C_TABLE_SEP . $table, $insertData, false, true); } } /** * Function to update logged record data - exec time for example * * @author Mareks Keišs * @category LIB DB logger * @param int $id - record to update * @param array $vData - record data to update * @return string - encrypted string */ public function updRecordData($id, $vData) { if (!!$id && !!$vData) { $this->module->cDb->_queryUpdate(self::C_SQL_TABLE, $vData, array('id' => $id), true); } } /** * Function to get operation types from string * * @author Mareks Keišs * @category LIB DB logger * @param string $sSql - get operations from sql * @return string - */ private function getOperationTypeFromSql($sSql) { if (strlen($sSql)) { $matches = array(); preg_match_all('/(select |delete |insert |update |drop)/ui', $sSql, $matches); $data = array(); if (!!$matches) { foreach ($matches as $vOPs) { if (!!$vOPs && is_array($vOPs)) $data += $vOPs; } } $data = array_unique($data); } return implode(' | ', $data); } /** * Function to initialize logger class and check if all log tables ar present * * @author Mareks Keišs * @category LIB DB logger * @return string - encrypted string */ public function initBaseStructure() { $data = array( self::C_SQL_TABLE => self::C_SQL_TABLE, self::C_ACTION_TABLE => self::C_ACTION_TABLE ); if ($this->logTableData && count($this->logTableData)) { foreach ($this->logTableData as $v) $data[$v] = self::C_TABLE_SEP . $v; } $tables = $this->module->getTablesInfoByName($data); $data = array_diff($data, (!!$tables ? $tables : array())); if ($data && count($data)) { // Get columns $vTableColumns = $this->module->getBaseTableColumnsByName($data); // Check base table if(!isset($tables[self::C_SQL_TABLE])) $this->module->createQueryLogTable(); unset($data[self::C_SQL_TABLE]); // Create action table if (!isset($tables[self::C_ACTION_TABLE])) $this->module->createActionLogTable(); unset($data[self::C_ACTION_TABLE]); // Check & create log tables foreach ($data as $k => $v) { if (!isset($tables[$v])) { $this->module->createLogTableByName($k, $v, (isset($vTableColumns[$k]) ? $vTableColumns[$k] : array())); } } } } /** * Function to globally handle log edit request * * @author Mareks Keišs * @category LIB DB logger * @param bool|string $sLogKey - log url key * @param string $sJSONData - json data string * @return bool|array - response data array */ public function chkIfRecordAvailableForEdit($sLogKey = false, $sJSONData = ''){ if(isset($_SESSION[$sLogKey])) return $_SESSION[$sLogKey]; if(!!$sLogKey && !!$sJSONData){ $vLogData = cJSON::decode($sJSONData, true); if(isset($vLogData['id'])){ $_SESSION[$sLogKey] = $vLogData; return $vLogData; } if(isset($vLogData['log_id'])){ // Set lookup table if(in_array($vLogData['t'], $this->logTableData)) { // Check from db if($vData = $this->module->getSingleLogDataById($vLogData['log_id'], self::C_TABLE_SEP . $vLogData['t'])) { if($vData['id']) { $_SESSION[$sLogKey] = $vData; return $vData; } } } } } return false; } }