<?php

namespace Drupal\dkan_common\Storage;

/**
 * DKAN JobStore factory trait.
 *
 * Provides helper methods for dealing with deprecated JobStore table names.
 */
trait DeprecatedJobStoreFactoryTrait {

  /**
   * Get the table name, preferring the deprecated one if it exists.
   *
   * If the identifier contains a backslash (\), we assume it's a class name and
   * could be either the deprecated or new hashed-style table name. We try to
   * find out if the deprecated one exists. If it does, we use its name.
   * Otherwise, we use the hashed-style table name.
   *
   * If the identifier does not contain a backslash, then we assume it is a
   * table-name-safe string, and prepend it with 'jobstore_'.
   *
   * @todo Phase out the use of the deprecated and hashed-class table names in
   *   favor of string literal identifiers.
   */
  protected function getTableName(string $identifier): string {
    // Check for either \ or class_exists() because not all class names will
    // contain a backslash.
    if ((str_contains($identifier, '\\')) || class_exists($identifier)) {
      $deprecatedTableName = $this->getDeprecatedTableName($identifier);
      if ($this->connection->schema()->tableExists($deprecatedTableName)) {
        return $deprecatedTableName;
      }
      return $this->getHashedTableName($identifier);
    }
    return 'jobstore_' . $identifier;
  }

  /**
   * Hash the class name identifier to generate a table name.
   *
   * This is the preferred strategy for new jobstore tables.
   *
   * @return string
   *   The hashed table name.
   */
  protected function getHashedTableName(string $identifier): string {
    // Avoid table-name-too-long errors by hashing the FQN of the identifier,
    // assuming it's a class name.
    $exploded_class = explode('\\', $identifier);
    return strtolower(implode('_', [
      'jobstore',
      crc32($identifier),
      array_pop($exploded_class),
    ]));
  }

  /**
   * Get the deprecated table name.
   *
   * The deprecated table name is generated by replacing \ with _ in
   * fully-qualified class names.
   *
   * This style of jobstore table name is deprecated. See release notes for
   * DKAN 2.16.5.
   *
   * @return string
   *   Deprecated table name.
   *
   * @see https://github.com/GetDKAN/dkan/releases/tag/2.16.5
   */
  protected function getDeprecatedTableName(string $identifier): string {
    $safeClassName = strtolower((string) preg_replace(
      '/\\\\/', '_',
      $identifier
    ));
    return 'jobstore_' . $safeClassName;
  }

}
