ConfirmAdmin = mlang_message("LOCK_ADMIN_ABORTED"); $this->ConfirmUser = mlang_message("LOCK_TIMED_OUT"); $this->LockAdmin = mlang_message("LOCK_RECORD_EDITED_BY"); $this->LockUser = mlang_message("LOCK_RECORD_EDITED"); $this->connection = $cman->getForLocking(); if(isset($_SESSION["UserID"]) && !is_null($_SESSION["UserID"])) $this->UserID = $_SESSION["UserID"]; else $this->UserID = "Guest"; } function LockRecord($strtable,$keys) { $skeys = ""; foreach($keys as $ind=>$val) { if(strlen($skeys)) $skeys.="&"; $skeys.=rawurlencode($val); } $sdate = now(); // add a record - try to lock $this->insert($strtable, $sdate, $sdate, $skeys, session_id(), $this->UserID, 1); $arrDelete = array(); // check all locking records $where = $this->connection->addFieldWrappers("table")."=".$this->connection->prepareString($strtable) ." AND ".$this->connection->addFieldWrappers("keys")."=".$this->connection->prepareString($skeys) ." AND ".$this->connection->addFieldWrappers("action")."=1"; $qResult = $this->query( $where, $this->connection->addFieldWrappers("id")." asc" ); while( $data = $qResult->fetchAssoc() ) { if(secondsPassedFrom($data["confirmdatetime"])>$this->UnlockTime) { // locking record is expired $arrDelete[]=$data["id"]; } else { // delete expired records foreach($arrDelete as $ind=>$val) { $this->delete($this->connection->addFieldWrappers("id"). "=" .$val); } if($data["sessionid"]==session_id()) { // locking was successful return true; } else { // record is already locked, delete locking attempt $where = $this->connection->addFieldWrappers("sessionid"). "=" .$this->connection->prepareString(session_id()) ." AND ". $this->connection->addFieldWrappers("action"). "=1" ." AND ". $this->connection->addFieldWrappers("table"). "=" .$this->connection->prepareString($strtable) ." AND ". $this->connection->addFieldWrappers("keys"). "=" .$this->connection->prepareString($skeys); $this->delete($where); return false; } } } return false; } function UnlockRecord($strtable,$keys,$sid) { if($sid=="") $sid=session_id(); $skeys=""; foreach($keys as $ind=>$val) { if(strlen($skeys)) $skeys.="&"; $skeys.=rawurlencode($val); } $where = $this->connection->addFieldWrappers("sessionid"). "=" .$this->connection->prepareString($sid) ." AND ". $this->connection->addFieldWrappers("action"). "=1 AND ". $this->connection->addFieldWrappers("table"). "=" .$this->connection->prepareString($strtable) ." AND ". $this->connection->addFieldWrappers("keys"). "=" .$this->connection->prepareString($skeys); $this->delete($where); } function ConfirmLock($strtable,$keys,&$message) { $skeys=""; foreach($keys as $ind=>$val) { if(strlen($skeys)) $skeys.="&"; $skeys.=rawurlencode($val); } // add locking attempt $sdate = now(); $this->insert($strtable, $sdate, $sdate, $skeys, session_id(), $this->UserID, 1); $where = $this->connection->addFieldWrappers("table")."=".$this->connection->prepareString($strtable) ." AND ".$this->connection->addFieldWrappers("keys")."=".$this->connection->prepareString($skeys) ." AND ".$this->connection->addFieldWrappers("action")."=1"; $qResult = $this->query( $where, $this->connection->addFieldWrappers("id")." asc" ); $myfound=0; // total our records found $newid=0; // last our record - added 5 lines ago $oldid=0; // next to last our record $newdate=""; // last our confirm time $olddate=""; // next to last our confirm time $otherfound=0; // other's records found between out last and next to last $tempfound=0; // check all locking records, count records while( $data = $qResult->fetchAssoc() ) { if($data["sessionid"]==session_id()) { $oldid=$newid; $newid=$data["id"]; $newdate=$data["confirmdatetime"]; $olddate=$newdate; $myfound++; $otherfound=$tempfound; $tempfound=0; continue; } $tempfound++; } if($myfound>1 && !$otherfound) { // no other's records, locking is confirmed $this->update($this->connection->addFieldWrappers("confirmdatetime"). "=" .$this->connection->addDateQuotes(now()), $this->connection->addFieldWrappers("id"). "=" .$oldid); $this->delete($this->connection->addFieldWrappers("id"). "=" .$newid); return true; } elseif($myfound>1 && $otherfound) { // found some other's records // check if previous record is not expired if(secondsPassedFrom($olddate)>$this->UnlockTime-5) { // expired - delete locking record, confirm was not successful $this->UnlockRecord($strtable,$keys,session_id()); $message=$this->ConfirmUser; return false; } else { // not expired, locking is confirmed $this->update($this->connection->addFieldWrappers("confirmdatetime"). "=" .$this->connection->addDateQuotes(now()), $this->connection->addFieldWrappers("id"). "=" .$oldid); $this->delete($this->connection->addFieldWrappers("id"). "=" .$newid); return true; } } else { // locking was lost $this->UnlockRecord($strtable,$keys,session_id()); // check if locking was removed by admin or not $where = $this->connection->addFieldWrappers("table")."=".$this->connection->prepareString($strtable) ." AND ".$this->connection->addFieldWrappers("keys")."=".$this->connection->prepareString($skeys) ." AND ".$this->connection->addFieldWrappers("sessionid")."<>'".session_id() ."' AND ".$this->connection->addFieldWrappers("action")."=2"; if($data = $this->query( $where, $this->connection->addFieldWrappers("id")." asc" )->fetchAssoc()) $message = mysprintf($this->ConfirmAdmin,array($data["userid"])); else $message = $this->ConfirmUser; $where = $this->connection->addFieldWrappers("action"). "=2 AND ". $this->connection->addFieldWrappers("table"). "=" .$this->connection->prepareString($strtable) ." AND ". $this->connection->addFieldWrappers("keys"). "=" .$this->connection->prepareString($skeys); $this->delete($where); return false; } } function GetLockInfo($strtable,$keys,$links, $pageid) { $page=GetTableLink(GetTableURL($strtable), "edit"); $skeys=""; foreach($keys as $ind=>$val){ if(strlen($skeys)) $skeys.="&"; $skeys.=rawurlencode($val); } $where = $this->connection->addFieldWrappers("table")."=".$this->connection->prepareString($strtable) ." AND ".$this->connection->addFieldWrappers("keys")."=".$this->connection->prepareString($skeys) ." AND ".$this->connection->addFieldWrappers("sessionid")."<>'".session_id() ."' AND ".$this->connection->addFieldWrappers("action")."=1"; $qResult = $this->query( $where, $this->connection->addFieldWrappers("id")." asc" ); if( $data = $qResult->fetchAssoc() ) { $sdate = now(); $arrDateTime = db2time($data["startdatetime"]); $str = mysprintf($this->LockAdmin,array($data["userid"],round(secondsPassedFrom($data["startdatetime"])/60,2))); if($links){ $str.=''.mlang_message("LOCK_UNLOCK").''; $str.=''.mlang_message("LOCK_EDIT").''; } return $str; } return ""; } function UnlockAdmin($strtable, $keys, $startEdit) { $skeys = ""; foreach($keys as $ind=>$val) { if(strlen($skeys)) $skeys .= "&"; $skeys .= rawurlencode($val); } $sdate = now(); if($startEdit) { // add a record - lock $this->insert($strtable, $sdate, $sdate, $skeys, session_id(), $this->UserID, 1); } // delete all other locking records $where = $this->connection->addFieldWrappers("table")."=".$this->connection->prepareString($strtable) ." AND ".$this->connection->addFieldWrappers("keys")."=".$this->connection->prepareString($skeys) ." AND ".$this->connection->addFieldWrappers("action")."=1 AND ".$this->connection->addFieldWrappers("sessionid")."<>".$this->connection->prepareString(session_id()); $this->delete( $where ); // inform other users that their locking were removed by locking $where = $this->connection->addFieldWrappers("startdatetime")."<".$this->connection->addDateQuotes(format_datetime_custom( adddays(db2time(now()), -2), "yyyy-MM-dd HH:mm:ss" )) ." AND ".$this->connection->addFieldWrappers("action")."=2"; $this->delete( $where ); $this->insert($strtable, $sdate, $sdate, $skeys, session_id(), $this->UserID, 2); } /** * Check if there is any record with particular * fields' values in the 'locking' table * @param String table * @param String keys * @param String action * @return Boolean */ public function isLocked( $table, $keys, $action ) { $lockSQL = "select count(*) from ". $this->connection->addTableWrappers( $this->lockTableName ) ." where ". $this->connection->addFieldWrappers("keys") ."=". $this->connection->prepareString( $lockWhere ) ." AND ". $this->connection->addFieldWrappers("table") ."=". $this->connection->prepareString( $table ) ." AND ". $this->connection->addFieldWrappers("action") ."=". $action; $lockSet = $this->connection->query( $lockSQL )->fetchNumeric(); return $lockSet[0] > 0; } protected function insert($table, $startdatetime, $confirmdatetime, $keys, $sessionid, $userid, $action) { $sql = "INSERT INTO " .$this->connection->addTableWrappers( $this->lockTableName ). " (" .$this->connection->addFieldWrappers("table"). "," .$this->connection->addFieldWrappers("startdatetime"). "," .$this->connection->addFieldWrappers("confirmdatetime"). "," .$this->connection->addFieldWrappers("keys"). "," .$this->connection->addFieldWrappers("sessionid"). "," .$this->connection->addFieldWrappers("userid"). "," .$this->connection->addFieldWrappers("action"). ") VALUES (" .$this->connection->prepareString($table). "," .$this->connection->addDateQuotes($startdatetime). "," .$this->connection->addDateQuotes($confirmdatetime). "," .$this->connection->prepareString($keys). "," .$this->connection->prepareString($sessionid). "," .$this->connection->prepareString($this->UserID). "," .$action. ")"; return $this->connection->exec( $sql ); } protected function query($where, $orderBy) { if(!$where) return; $sql = "SELECT * FROM " .$this->connection->addTableWrappers( $this->lockTableName ). " WHERE " .$where. " ORDER BY " .$orderBy; return $this->connection->query( $sql ); } protected function delete($where) { if(!$where) return; $sql = "DELETE FROM " .$this->connection->addTableWrappers( $this->lockTableName ). " WHERE " .$where; $this->connection->exec( $sql ); } protected function update($values, $where) { if(!$where || !$values) return; $sql = "UPDATE " .$this->connection->addTableWrappers( $this->lockTableName ). " SET " .$values. " WHERE " .$where; $this->connection->exec( $sql ); } } ?>