<?php

namespace Drupal\Core\Database\Driver\autoslave;

use Drupal\Core\Database\Transaction as DatabaseTransaction;
use Drupal\autoslave\AutoslaveCache;

/**
 * Handle force master for transactions.
 */
class Transaction extends DatabaseTransaction {

  /**
   * Parent transaction object.
   *
   * @var object
   */
  protected $parent;

  /**
   * Constructs a Transaction object.
   *
   * @param \Drupal\Core\Database\Driver\autoslave\Connection $connection
   *   The database connection.
   * @param string|null $name
   *   Optional transaction name.
   */
  public function __construct(Connection $connection, $name = NULL) {
    $this->connection = $connection;
    $this->connection->forceMaster(1);
    // $this->parent = $this->connection->getMasterConnection()->startTransaction($name);
    $this->started = microtime(TRUE);
  }

  /**
   * Destructs the Transaction object.
   */
  public function __destruct() {
    unset($this->parent);
    $this->connection->forceMaster(-1);
    // If tables were flagged inside a transaction, update their timestamp to the commit time.
    if ($this->connection->transactionDepth() == 0) {
      // We need to check if the array exist, just in case some opened and closed a transaction without
      // performing any write queries.
      $key = $this->connection->getKey();
      $target = $this->connection->getTarget();
      $affected_tables = $this->connection->__affected_tables;

      $lag = ceil(microtime(TRUE) - $this->started);
      if ($this->connection->getReplicationLag()) {
        $affected_tables = &$this->connection->__affected_tables;
      }
      elseif (!empty($_SESSION['autoslave_affected_tables'])) {
        $affected_tables = &$_SESSION['autoslave_affected_tables'];
      }
      else {
        $affected_tables = [];
      }

      if (!empty($affected_tables[$key][$target])) {
        foreach ($affected_tables[$key][$target] as $table => &$expires) {
          // If tables were flagged inside a transaction, update their timestamp to the commit time.
          $new_expires = time() + $lag;
          $this->connection->bufferAffectedTable($target, $key, $table, $new_expires);
        }
      }

      $this->connection->flushAffectedTables();

      // Clear cache buffer.
      if (is_callable(['AutoslaveCache', 'clearBuffer'])) {
        AutoslaveCache::clearBuffer();
      }

    }
    else {
      // Soft commit.
      unset($this->parent);
      $this->connection->forceMaster(-1, TRUE);
    }
  }

  /**
   * Gets the transaction name.
   *
   * @return string
   *   The transaction name.
   */
  public function name() {
    return $this->parent->name();
  }

  /**
   * Rolls back the transaction.
   */
  public function rollback() {}

}
