Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
SchemaListener.php
Go to the documentation of this file.
1 <?php
7 
12 
17 {
21  const IGNORE_ON = 0;
22 
26  const IGNORE_OFF = 1;
27 
31  const STAGING_FK_KEYS = 2;
32 
36  private $tables = [];
37 
41  private $resource;
42 
48  private $ignore = self::IGNORE_OFF;
49 
53  private static $mapping = [
54  'DATA_TYPE' => 'type',
55  'COLUMN_NAME' => 'name',
56  'TYPE' => 'type',
57  'DEFAULT' => 'default',
58  'NULLABLE' => 'nullable',
59  'LENGTH' => 'length',
60  'PRECISION' => 'precision',
61  'SCALE' => 'scale',
62  'UNSIGNED' => 'unsigned',
63  'IDENTITY' => 'identity',
64  'PRIMARY' => 'primary'
65  ];
66 
70  private static $toUnset = [
71  'COLUMN_POSITION',
72  'COLUMN_TYPE',
73  'PRIMARY_POSITION',
74  'COMMENT'
75  ];
76 
80  private $moduleName = '';
81 
85  private $definitionMappers;
86 
90  private $handlers;
91 
98  public function __construct(
99  array $definitionMappers,
100  array $handlers = []
101  ) {
102  $this->definitionMappers = $definitionMappers;
103  $this->handlers = $handlers;
104  }
105 
112  public function dropForeignKey($tableName, $fkName)
113  {
114  $dataToLog['constraints']['foreign'][$fkName] = [
115  'disabled' => true,
116  ];
117  $this->log($tableName, $dataToLog);
118  }
119 
127  private function castColumnDefinition($definition, $columnName)
128  {
129  if (is_string($definition)) {
130  $definition = ['type' => $definition];
131  }
132  $definition = $this->doColumnMapping($definition);
133  $definition['name'] = strtolower($columnName);
134  $definitionType = $definition['type'] === 'int' ? 'integer' : $definition['type'];
135  $definition = $this->definitionMappers[$definitionType]->convertToDefinition($definition);
136  if (isset($definition['default']) && $definition['default'] === false) {
137  $definition['default'] = null; //uniform default values
138  }
139  $definition['disabled'] = false;
140 
141  return $definition;
142  }
143 
153  private function addPrimaryKeyIfExists($tableName, $columnName, $definition, $primaryKeyName)
154  {
155  if (isset($definition['primary']) && $definition['primary']) {
156  $dataToLog['constraints']['primary'][$primaryKeyName] = [
157  'type' => 'primary',
158  'name' => $primaryKeyName,
159  'disabled' => false,
160  'columns' => [$columnName => strtolower($columnName)]
161  ];
162 
163  $this->log($tableName, $dataToLog);
164  }
165 
166  unset($definition['primary']);
167  return $definition;
168  }
169 
177  public function renameTable($oldTableName, $newTableName)
178  {
179  $moduleName = $this->getModuleName();
180 
181  if (isset($this->tables[$moduleName][strtolower($oldTableName)])) {
182  $this->tables[$moduleName][strtolower($newTableName)] =
183  $this->tables[$moduleName][strtolower($oldTableName)];
184  unset($this->tables[$moduleName][strtolower($oldTableName)]);
185  }
186  }
187 
194  private function doColumnMapping(array $definition)
195  {
196  foreach ($definition as $key => $keyValue) {
197  if (isset(self::$mapping[$key])) {
198  $definition[self::$mapping[$key]] = $keyValue;
199  unset($definition[$key]);
200  }
201 
202  if (in_array($key, self::$toUnset)) {
203  unset($definition[$key]);
204  }
205  }
206 
207  return $definition;
208  }
209 
219  public function addColumn($tableName, $columnName, $definition, $primaryKeyName = 'PRIMARY', $onCreate = null)
220  {
221  $definition = $this->castColumnDefinition($definition, $columnName);
222  $definition = $this->addPrimaryKeyIfExists($tableName, $columnName, $definition, $primaryKeyName);
223  $definition['onCreate'] = $onCreate;
224  $dataToLog['columns'][strtolower($columnName)] = $definition;
225  $this->log($tableName, $dataToLog);
226  }
227 
235  public function dropIndex($tableName, $keyName, $indexType)
236  {
237  if ($indexType === 'index') {
238  $dataToLog['indexes'][$keyName] = [
239  'disabled' => true
240  ];
241  } else {
242  $dataToLog['constraints'][$indexType][$keyName] = [
243  'disabled' => true
244  ];
245  }
246 
247  $this->log($tableName, $dataToLog);
248  }
249 
256  public function dropColumn($tableName, $columnName)
257  {
258  $dataToLog['columns'][strtolower($columnName)] = [
259  'disabled' => true
260  ];
261  $this->log($tableName, $dataToLog);
262  }
263 
272  public function changeColumn($tableName, $oldColumnName, $newColumnName, $definition)
273  {
274  foreach ($this->handlers as $handler) {
275  $this->tables = $handler->handle(
276  $this->moduleName,
277  $this->tables,
278  [
279  'table' => $tableName,
280  'old_column' => $oldColumnName,
281  'new_column' => $newColumnName,
282  ],
283  $definition
284  );
285  }
286 
287  $this->dropColumn($tableName, $oldColumnName);
288  $this->addColumn(
289  $tableName,
290  $newColumnName,
291  $definition,
292  'STAGING_PRIMARY',
293  sprintf('migrateDataFrom(%s)', $oldColumnName)
294  );
295  }
296 
304  public function modifyColumn($tableName, $columnName, $definition)
305  {
306  $this->addColumn($tableName, $columnName, $definition);
307  }
308 
314  private function getModuleName()
315  {
316  return $this->moduleName;
317  }
318 
326  public function log($tableName, array $dataToLog)
327  {
328  if ($this->ignore & self::IGNORE_OFF === 0) {
329  return;
330  }
331  $moduleName = $this->getModuleName();
332  if (isset($this->tables[$moduleName][strtolower($tableName)])) {
333  $this->tables[$moduleName][strtolower($tableName)] = array_replace_recursive(
334  $this->tables[$moduleName][strtolower($tableName)],
335  $dataToLog
336  );
337  } else {
338  $this->tables[$moduleName][strtolower($tableName)] = $dataToLog;
339  }
340 
341  $this->tables[$moduleName][strtolower($tableName)]['resource'] = $this->resource;
342  }
343 
354  public function addForeignKey(
355  $fkName,
356  $tableName,
357  $columnName,
358  $refTableName,
359  $refColumnName,
361  ) {
362  $dataToLog['constraints']['foreign'][$fkName] =
363  [
364  'table' => strtolower($tableName),
365  'column' => strtolower($columnName),
366  'referenceTable' => strtolower($refTableName),
367  'referenceColumn' => strtolower($refColumnName),
368  'onDelete' => $onDelete,
369  'disabled' => false
370  ];
371  $this->log($tableName, $dataToLog);
372  }
373 
380  private function prepareIndexColumns(array $indexColumns)
381  {
382  $columnNames = [];
383 
384  foreach ($indexColumns as $key => $indexColumn) {
385  if (is_array($indexColumn)) {
386  $columnNames[strtolower($key)] = strtolower($key);
387  } else {
388  $columnNames[$indexColumn] = $indexColumn;
389  }
390  }
391 
392  return $columnNames;
393  }
394 
404  public function addIndex(
405  $tableName,
406  $indexName,
407  $fields,
409  $indexAlhoritm = 'btree'
410  ) {
411  if (!is_array($fields)) {
412  $fields = [$fields];
413  }
415  if ($indexType === AdapterInterface::INDEX_TYPE_INDEX) {
416  $indexType = $indexAlhoritm;
417  }
418  $dataToLog['indexes'][$indexName] =
419  [
420  'columns' => $this->prepareIndexColumns($fields),
421  'indexType' => $indexType,
422  'disabled' => false
423  ];
424  } else {
425  $dataToLog['constraints'][$indexType][$indexName] =
426  ['columns' => $this->prepareIndexColumns($fields), 'disabled' => false];
427  }
428 
429  $this->log($tableName, $dataToLog);
430  }
431 
438  private function prepareColumns($tableName, array $tableColumns)
439  {
440  foreach ($tableColumns as $name => $tableColumn) {
441  $this->addColumn($tableName, $name, $tableColumn);
442  }
443  }
444 
452  private function prepareConstraintsAndIndexes(array $foreignKeys, array $indexes, $tableName, $engine)
453  {
454  //Process foreign keys
455  foreach ($foreignKeys as $name => $foreignKey) {
456  $this->addForeignKey(
457  $name,
458  $tableName,
459  $foreignKey['COLUMN_NAME'],
460  $foreignKey['REF_TABLE_NAME'],
461  $foreignKey['REF_COLUMN_NAME'],
462  $foreignKey['ON_DELETE']
463  );
464  }
465  //Process indexes
466  foreach ($indexes as $name => $index) {
467  $this->addIndex(
468  $tableName,
469  $name,
470  $index['COLUMNS'],
471  $index['TYPE'],
472  $engine === 'memory' ? 'hash' : 'btree'
473  );
474  }
475  }
476 
482  public function createTable(Table $table)
483  {
484  $engine = strtolower($table->getOption('type'));
485  $this->tables[$this->getModuleName()][strtolower($table->getName())]['engine'] = $engine;
486  $this->prepareColumns($table->getName(), $table->getColumns());
487  $this->prepareConstraintsAndIndexes($table->getForeignKeys(), $table->getIndexes(), $table->getName(), $engine);
488  }
489 
495  public function flush()
496  {
497  $this->tables = [];
498  }
499 
505  public function toogleIgnore($flag)
506  {
507  $this->ignore = $flag;
508  }
509 
515  public function dropTable($tableName)
516  {
517  if (isset($this->tables[$this->getModuleName()][strtolower($tableName)])) {
518  unset($this->tables[$this->getModuleName()][strtolower($tableName)]);
519  } else {
520  $this->tables[$this->getModuleName()][strtolower($tableName)]['disabled'] = true;
521  }
522  }
523 
529  public function setResource(string $resource)
530  {
531  $this->resource = $resource;
532  }
533 
539  public function setModuleName($moduleName)
540  {
541  $this->moduleName = $moduleName;
542  }
543 
549  public function getTables()
550  {
551  return $this->tables;
552  }
553 }
$tableName
Definition: trigger.php:13
return false
Definition: gallery.phtml:36
__construct(array $definitionMappers, array $handlers=[])
modifyColumn($tableName, $columnName, $definition)
log($tableName, array $dataToLog)
$fields
Definition: details.phtml:14
addForeignKey( $fkName, $tableName, $columnName, $refTableName, $refColumnName, $onDelete=AdapterInterface::FK_ACTION_CASCADE)
$resource
Definition: bulk.php:12
changeColumn($tableName, $oldColumnName, $newColumnName, $definition)
if ignore
Definition: edit.phtml:100
addColumn($tableName, $columnName, $definition, $primaryKeyName='PRIMARY', $onCreate=null)
dropIndex($tableName, $keyName, $indexType)
addIndex( $tableName, $indexName, $fields, $indexType=AdapterInterface::INDEX_TYPE_INDEX, $indexAlhoritm='btree')
$table
Definition: trigger.php:14
$index
Definition: list.phtml:44
renameTable($oldTableName, $newTableName)
catch(\Exception $e) $handler
Definition: index.php:30
if(!isset($_GET['name'])) $name
Definition: log.php:14