You are here

public function IntColumnHandler::create in Dynamic Entity Reference 8.2

Creates the _int columns and the triggers for them.

Parameters

string $table: The non-prefix table to operate on.

array $columns: The DER target_id columns.

array $index_columns: Table columns that should be added to the index that is created for the new _int column.

Return value

array The list of new target_id_int columns.

Overrides IntColumnHandlerInterface::create

File

src/Storage/IntColumnHandler.php, line 59

Class

IntColumnHandler
Per database implementation of denormalizing into integer columns.

Namespace

Drupal\dynamic_entity_reference\Storage

Code

public function create($table, array $columns, array $index_columns = []) {
  $schema = $this->connection
    ->schema();

  // The integer column specification.
  $spec = [
    'type' => 'int',
    'unsigned' => TRUE,
    'not null' => FALSE,
  ];

  // Before MySQL 5.7.2, there cannot be multiple triggers for a given table
  // that have the same trigger event and action time so set all involved
  // columns in one go. See
  // https://dev.mysql.com/doc/refman/5.7/en/trigger-syntax.html for more.
  // In SQLite, it's cheaper to run one query instead on per column.
  $body = [];
  $new = [];
  if (!static::allColumnsExist($schema, $table, $columns)) {
    return [];
  }
  foreach ($columns as $column) {
    $column_int = $column . '_int';

    // Make sure the integer columns exist.
    if (!$schema
      ->fieldExists($table, $column_int)) {
      $index_fields = [
        $column_int,
      ];
      $full_spec = [
        'fields' => [
          $column_int => $spec,
        ],
      ];
      if (!empty($index_columns)) {
        $full_spec['fields'] = array_merge($full_spec['fields'], $index_columns);
        $index_fields = array_merge($index_fields, array_keys($index_columns));
      }
      $new[] = $column_int;
      $schema
        ->addField($table, $column_int, $spec);
      $schema
        ->addIndex($table, $column_int, $index_fields, $full_spec);
    }

    // This is the heart of this function: before an UPDATE/INSERT, set the
    // value of the integer column to the integer value of the string column.
    $body[] = $this
      ->createBody($column_int, $column);
  }
  if ($new) {
    $body = implode(', ', $body);
    $prefixed_name = str_replace('"', '', $this->connection
      ->prefixTables('{' . $table . '}'));
    foreach ([
      'update',
      'insert',
    ] as $op) {
      $trigger = $prefixed_name . '_der_' . $op;
      if (strlen($trigger) > 64) {
        $trigger = substr($trigger, 0, 56) . substr(hash('sha256', $trigger), 0, 8);
      }
      $this->connection
        ->query("DROP TRIGGER IF EXISTS {$trigger}");
      if ($body) {
        $this
          ->createTrigger($trigger, $op, $prefixed_name, $body);
      }
    }
  }
  return $new;
}