167 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			167 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
namespace nur\sery\db;
 | 
						|
 | 
						|
use nur\sery\php\func;
 | 
						|
use nur\sery\ValueException;
 | 
						|
 | 
						|
/**
 | 
						|
 * Class Capacitor: un objet permettant d'attaquer un canal spécifique d'une
 | 
						|
 * instance de {@link CapacitorStorage}
 | 
						|
 */
 | 
						|
class Capacitor implements ITransactor {
 | 
						|
  function __construct(CapacitorStorage $storage, CapacitorChannel $channel, bool $ensureExists=true) {
 | 
						|
    $this->storage = $storage;
 | 
						|
    $this->channel = $channel;
 | 
						|
    if ($ensureExists) $this->ensureExists();
 | 
						|
  }
 | 
						|
 | 
						|
  /** @var CapacitorStorage */
 | 
						|
  protected $storage;
 | 
						|
 | 
						|
  function getStorage(): CapacitorStorage {
 | 
						|
    return $this->storage;
 | 
						|
  }
 | 
						|
 | 
						|
  function db(): IDatabase {
 | 
						|
    return $this->getStorage()->db();
 | 
						|
  }
 | 
						|
 | 
						|
  /** @var CapacitorChannel */
 | 
						|
  protected $channel;
 | 
						|
 | 
						|
  function getChannel(): CapacitorChannel {
 | 
						|
    return $this->channel;
 | 
						|
  }
 | 
						|
 | 
						|
  function getTableName(): string {
 | 
						|
    return $this->getChannel()->getTableName();
 | 
						|
  }
 | 
						|
 | 
						|
  /** @var CapacitorChannel[]  */
 | 
						|
  protected ?array $subChannels = null;
 | 
						|
 | 
						|
  protected ?array $subManageTransactions = null;
 | 
						|
 | 
						|
  function willUpdate(...$channels): self {
 | 
						|
    if ($this->subChannels === null) {
 | 
						|
      # désactiver la gestion des transaction sur le channel local aussi
 | 
						|
      $this->subChannels[] = $this->channel;
 | 
						|
    }
 | 
						|
    if ($channels) {
 | 
						|
      foreach ($channels as $channel) {
 | 
						|
        if ($channel instanceof Capacitor) $channel = $channel->getChannel();
 | 
						|
        if ($channel instanceof CapacitorChannel) {
 | 
						|
          $this->subChannels[] = $channel;
 | 
						|
        } else {
 | 
						|
          throw ValueException::invalid_type($channel, CapacitorChannel::class);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    return $this;
 | 
						|
  }
 | 
						|
 | 
						|
  function inTransaction(): bool {
 | 
						|
    return $this->db()->inTransaction();
 | 
						|
  }
 | 
						|
 | 
						|
  function beginTransaction(?callable $func=null, bool $commit=true): void {
 | 
						|
    if ($this->subManageTransactions === null && $this->subChannels !== null) {
 | 
						|
      foreach ($this->subChannels as $channel) {
 | 
						|
        $name = $channel->getName();
 | 
						|
        $this->subManageTransactions ??= [];
 | 
						|
        if (!array_key_exists($name, $this->subManageTransactions)) {
 | 
						|
          $this->subManageTransactions[$name] = $channel->isManageTransactions();
 | 
						|
        }
 | 
						|
        $channel->setManageTransactions(false);
 | 
						|
      }
 | 
						|
      $db = $this->db();
 | 
						|
      if (!$db->inTransaction()) $db->beginTransaction();
 | 
						|
    }
 | 
						|
    if ($func !== null) {
 | 
						|
      $commited = false;
 | 
						|
      try {
 | 
						|
        func::call($func, $this);
 | 
						|
        if ($commit) {
 | 
						|
          $this->commit();
 | 
						|
          $commited = true;
 | 
						|
        }
 | 
						|
      } finally {
 | 
						|
        if ($commit && !$commited) $this->rollback();
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  protected function beforeEndTransaction(): void {
 | 
						|
    if ($this->subManageTransactions !== null) {
 | 
						|
      foreach ($this->subChannels as $channel) {
 | 
						|
        $name = $channel->getName();
 | 
						|
        $channel->setManageTransactions($this->subManageTransactions[$name]);
 | 
						|
      }
 | 
						|
      $this->subManageTransactions = null;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  function commit(): void {
 | 
						|
    $this->beforeEndTransaction();
 | 
						|
    $db = $this->db();
 | 
						|
    if ($db->inTransaction()) $this->db()->commit();
 | 
						|
  }
 | 
						|
 | 
						|
  function rollback(): void {
 | 
						|
    $this->beforeEndTransaction();
 | 
						|
    $db = $this->db();
 | 
						|
    if ($db->inTransaction()) $this->db()->rollback();
 | 
						|
  }
 | 
						|
 | 
						|
  function getCreateSql(): string {
 | 
						|
    return $this->storage->_getCreateSql($this->channel);
 | 
						|
  }
 | 
						|
 | 
						|
  function exists(): bool {
 | 
						|
    return $this->storage->_exists($this->channel);
 | 
						|
  }
 | 
						|
 | 
						|
  function ensureExists(): void {
 | 
						|
    $this->storage->_ensureExists($this->channel);
 | 
						|
  }
 | 
						|
 | 
						|
  function reset(bool $recreate=false): void {
 | 
						|
    $this->storage->_reset($this->channel, $recreate);
 | 
						|
  }
 | 
						|
 | 
						|
  function charge($item, $func=null, ?array $args=null, ?array &$values=null): int {
 | 
						|
    $this->beginTransaction();
 | 
						|
    return $this->storage->_charge($this->channel, $item, $func, $args, $values);
 | 
						|
  }
 | 
						|
 | 
						|
  function discharge(bool $reset=true): iterable {
 | 
						|
    return $this->storage->_discharge($this->channel, $reset);
 | 
						|
  }
 | 
						|
 | 
						|
  function count($filter=null): int {
 | 
						|
    return $this->storage->_count($this->channel, $filter);
 | 
						|
  }
 | 
						|
 | 
						|
  function one($filter): ?array {
 | 
						|
    return $this->storage->_one($this->channel, $filter);
 | 
						|
  }
 | 
						|
 | 
						|
  function all($filter): iterable {
 | 
						|
    return $this->storage->_all($this->channel, $filter);
 | 
						|
  }
 | 
						|
 | 
						|
  function each($filter, $func=null, ?array $args=null): int {
 | 
						|
    $this->beginTransaction();
 | 
						|
    return $this->storage->_each($this->channel, $filter, $func, $args);
 | 
						|
  }
 | 
						|
 | 
						|
  function delete($filter, $func=null, ?array $args=null): int {
 | 
						|
    $this->beginTransaction();
 | 
						|
    return $this->storage->_delete($this->channel, $filter, $func, $args);
 | 
						|
  }
 | 
						|
 | 
						|
  function close(): void {
 | 
						|
    $this->storage->close();
 | 
						|
  }
 | 
						|
}
 |