<?php
namespace nur\m\base;

use nur\A;
use nur\m\IConn;
use nur\m\IQueryLogger;

/**
 * Class AbstractConn
 */
abstract class AbstractConn implements IConn {
  static function fix_sql_with_seq_bindings(string &$sql, ?array $bindings): void {
    if ($bindings !== null) {
      # si une des valeurs est un tableau séquentiel, il faut binder sur chaque
      # valeur du tableau. ici, on corrige la requête
      foreach ($bindings as $name => $values) {
        if (A::is_seq($values)) {
          $count = count($values);
          $names = [];
          for ($i = 0; $i < $count; $i++) {
            $names[] = ":${name}_${i}";
          }
          $names = implode(", ", $names);
          $sql = str_replace(":$name", "($names)", $sql);
        }
      }
    }
  }

  /** @var IQueryLogger */
  protected $queryLogger;

  /**
   * spécifier une instance de IQueryLogger permettant le suivi des requêtes
   * exécutées par cet objet.
   *
   * retourner l'instance spécifiée.
   */
  function setQueryLogger(IQueryLogger $queryLogger): IQueryLogger {
    $this->queryLogger = $queryLogger;
    return $queryLogger;
  }

  /**
   * supprimer l'instance de IQueryLogger configurée avec {@link setQueryLogger()}.
   * retourner l'instance qui a été supprimée, ou null s'il n'y en avait pas.
   *
   * @return IQueryLogger
   */
  function resetQueryLogger(): ?IQueryLogger {
    $query_logger = $this->queryLogger;
    $this->queryLogger = null;
    return $query_logger;
  }

  function all(string $sql, ?array $filter=null): array {
    return $this->query()->select($sql, $filter)->all();
  }

  function allVals(?string $name, string $sql, ?array $filter=null): array {
    return rows::vals($this->all($sql, $filter), $name);
  }

  function first(string $sql, ?array $filter=null): ?array {
    return $this->query()->select($sql, $filter)->first();
  }

  function firstVal(?string $name, string $sql, ?array $filter=null, $default=null) {
    return rows::val($this->first($sql, $filter), $name, $default);
  }

  function update(string $sql, ?array $filter=null): int {
    return $this->query()->update($sql, $filter)->execute(true)->numRows();
  }
}