TransactionManager
<?php require_once "autoload.php";
class TransactionManager extends Bean
{
private static $instance;
public static function getInstance()
{
if (!isset(self::$instance))
{
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
protected $txStack;
public function __construct()
{
$pm = PersistenceManager::getInstance();
$this->txStack = $pm->load("TX_STACK");
if (!$this->txStack)
$this->txStack = array();
}
public function persist()
{
$ret = false;
$pm = PersistenceManager::getInstance();
$pm->save("TX_STACK", $this->txStack);
$ret = true;
return $ret;
}
public function push($item)
{
$tx = end($this->txStack);
if ($tx)
{
$ret = $tx->push($item);
$this->persist();
}
return $ret;
}
public function pop()
{
$tx = $this->topTx();
if (!$tx)
return null;
while ($tx && !$tx->count())
{
$tx = $this->popTx();
$tx = $this->topTx();
}
if (!$tx)
return null;
$tx = $this->topTx();
$item = $tx->pop();
while ($tx && !$tx->count())
{
$tx = $this->popTx();
$tx = $this->topTx();
}
$this->persist();
return $item;
}
/*cutTo trips the stack to the $item. Only defined for use within one transaction. Cutting
to an item outside the current transaction scope crashes.
*/
public function cutTo($item)
{
$ret;
$topTx = $this->topTx();
do{
$ret = $topTx->pop();
$model = $ret->get("model");
// echo "comparision<br>".print_r($item,true)."<br>to".print_r($model["path"],true);
}
while($item != $model["path"] & $topTx->top());
$topTx->push($ret);
return $ret;
}
public function top()
{
$ret = null;
do
{
$tx = end($this->txStack);
if (!$tx)
break;
$ret = $tx->top();
} while (false);
return $ret;
}
public function topTx()
{
return end($this->txStack);
}
public function popTx()
{
return array_pop($this->txStack);
}
public function pushTx($tx)
{
$this->txStack[] = $tx;
}
public function start(&$tx)
{
$ret = false;
$x = $this->topTx();
if ($x && (get_class($x) == get_class($tx)))
{
return $this->top()->view();
}
$this->txStack[] = $tx;
$this->persist();
$ret = $tx->start();
return $ret;
}
public function endPassive()
{
$ret = true;
$tx = array_pop($this->txStack);
$this->persist();
$ret &= $tx->end();
$tx = end($this->txStack);
return true;
}
public function end()
{
$ret = true;
$tx = array_pop($this->txStack);
$this->persist();
$ret &= $tx->end();
$tx = end($this->txStack);
$item = $tx->pop();
$ret = $item->view();
return $ret;
}
}
Bean
<?php include_once "autoload.php";
abstract class Bean
{
public function set($field, &$value) { $this->$field = $value; }
public function &get($field) { return $this->$field; }
public function __construct()
{
}
public function map_to_vars(&$map)
{
foreach (array_keys(get_object_vars($this)) as $key)
{
$this->$key = $map[$key];
}
}
}
?>