瀏覽代碼

- new implementation (database independent) of the transaction mechanism, that prevents a user from submitting the same form twice.

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@900 a333f486-631f-4898-b8df-5754b55c2be0
dflaven 14 年之前
父節點
當前提交
a4d01e18d0
共有 1 個文件被更改,包括 27 次插入64 次删除
  1. 27 64
      application/transaction.class.inc.php

+ 27 - 64
application/transaction.class.inc.php

@@ -17,94 +17,57 @@
 /**
  * This class records the pending "transactions" corresponding to forms that have not been
  * submitted yet, in order to prevent double submissions. When created a transaction remains valid
- * until it is "used" by calling IsTransactionValid once, or until it
- * expires (delay = TRANSACTION_EXPIRATION_DELAY, defaults to 4 hours)
+ * until the user's session expires
  * @package     iTop
  */
-// How long a "transaction" is considered valid, i.e. when a form is submitted
-// if the form dates back from too long a time, it is considered invalid. This is
-// because since HTTP is not a connected protocol, we cannot know when a user disconnects
-// from the application (maybe just by closing her browser), so we keep track - in the database - of all pending
-// forms that have not yet been submitted. To limit this list we consider that after some time
-// a "transaction" is no loger valid an gets purged from the table
-define ('TRANSACTION_EXPIRATION_DELAY', 3600*4); // default: 4h
 
-require_once('../core/dbobject.class.php');
 
-class privUITransaction extends DBObject
+class privUITransaction
 {
-	public static function Init()
-	{
-		$aParams = array
-		(
-			"category" => "gui",
-			"key_type" => "autoincrement",
-			"name_attcode" => "expiration_date",
-			"state_attcode" => "",
-			"reconc_keys" => array(),
-			"db_table" => "priv_transaction",
-			"db_key_field" => "id",
-			"db_finalclass_field" => "",
-		);
-		MetaModel::Init_Params($aParams);
-		MetaModel::Init_AddAttribute(new AttributeDateTime("expiration_date", array("allowed_values"=>null, "sql"=>"expiration_date", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
-
-		MetaModel::Init_SetZListItems('details', array('expiration_date')); // Attributes to be displayed for the complete details
-		MetaModel::Init_SetZListItems('list', array('expiration_date')); // Attributes to be displayed for a list
-	}
 	/**
-	 * Create a new transaction, store it in the database and return its id
+	 * Create a new transaction id, store it in the session and return its id
 	 * @param void
 	 * @return int The identifier of the new transaction
 	 */
 	public static function GetNewTransactionId()
 	{
-		// First remove all the expired transactions...
-		self::CleanupExpiredTransactions();
-		$oTransaction = new privUITransaction();
-		$sDate = date('Y-m-d H:i:s', time()+TRANSACTION_EXPIRATION_DELAY);
-		$oTransaction->Set('expiration_date', $sDate); // 4 h delay by default
-		$oTransaction->DBInsert();
-		return sprintf("%d", $oTransaction->GetKey());
+		if (!isset($_SESSION['transactions']))
+		{
+				$_SESSION['transactions'] = array();
+		}
+		// Strictly speaking, the two lines below should be grouped together
+		// by a critical section
+		// sem_acquire($rSemIdentified);
+		$id = 1 + count($_SESSION['transactions']);
+		$_SESSION['transactions'][$id] = true;
+		// sem_release($rSemIdentified);
+		
+		return sprintf("%d", $id);
 	}
 
 	/**
 	 * Check whether a transaction is valid or not and remove the valid transaction from
-	 * the database so that another call to IsTransactionValid for the same transaction
+	 * the session so that another call to IsTransactionValid for the same transaction id
 	 * will return false
 	 * @param int $id Identifier of the transaction, as returned by GetNewTransactionId
 	 * @return bool True if the transaction is valid, false otherwise
 	 */	
 	public static function IsTransactionValid($id)
 	{
-		// First remove all the expired transactions...
-		self::CleanupExpiredTransactions();
-		// TO DO put a critical section around this part to be 100% safe...
-		// sem_acquire(...)
-		$bResult  = false;
-		$oTransaction = MetaModel::GetObject('privUITransaction', $id, false /* MustBeFound */);
-		if ($oTransaction)
+		$bResult = false;
+		if (isset($_SESSION['transactions']))
 		{
-			$bResult = true;
-			$oTransaction->DBDelete();
+			// Strictly speaking, the three lines below should be grouped together
+			// inside the same critical section as above
+			// sem_acquire($rSemIdentified);
+			if (isset($_SESSION['transactions'][$id]))
+			{
+				$bResult = true;
+				unset($_SESSION['transactions'][$id]);
+			}
+			// sem_release($rSemIdentified);
 		}
-		// sem_release(...)
 		return $bResult;
 	}
-
-	/**
-	 * Remove from the database all transactions that have expired
-	 */
-	protected static function CleanupExpiredTransactions()
-	{
-		$sQuery = 'SELECT privUITransaction WHERE expiration_date < NOW()';
-		$oSearch = DBObjectSearch::FromOQL($sQuery);
-		$oSet = new DBObjectSet($oSearch);
-		while($oTransaction = $oSet->Fetch())
-		{
-			$oTransaction->DBDelete();
-		}
-	}
-
 }
 ?>