mirror of
https://github.com/OpenXE-org/OpenXE.git
synced 2024-12-27 07:00:29 +01:00
184 lines
4.8 KiB
PHP
184 lines
4.8 KiB
PHP
|
<?php
|
||
|
|
||
|
declare(strict_types=1);
|
||
|
|
||
|
namespace Xentral\Components\SchemaCreator\LineGenerator\Common;
|
||
|
|
||
|
use Xentral\Components\Database\Database;
|
||
|
use Xentral\Components\Database\Exception\EscapingException;
|
||
|
use Xentral\Components\Database\Exception\QueryFailureException;
|
||
|
use Xentral\Components\SchemaCreator\Exception\LineGeneratorException;
|
||
|
use Xentral\Components\SchemaCreator\Index\Constraint;
|
||
|
use Xentral\Components\SchemaCreator\Interfaces\PrimaryKeyInterface;
|
||
|
use Xentral\Components\SchemaCreator\Interfaces\IndexInterface;
|
||
|
|
||
|
final class IndexLineGenerator
|
||
|
{
|
||
|
/** @var Database $db */
|
||
|
private $db;
|
||
|
|
||
|
/**
|
||
|
* @param Database $db
|
||
|
*/
|
||
|
public function __construct(Database $db)
|
||
|
{
|
||
|
$this->db = $db;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param string $indexName
|
||
|
*
|
||
|
* @throws EscapingException
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
private function generateName(string $indexName): string
|
||
|
{
|
||
|
if (!empty($indexName)) {
|
||
|
$indexName = $this->escape($indexName);
|
||
|
}
|
||
|
|
||
|
return $indexName;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param $creatorIndex
|
||
|
*
|
||
|
* @throws EscapingException
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
private function buildReferences($creatorIndex): string
|
||
|
{
|
||
|
if ($creatorIndex instanceof Constraint) {
|
||
|
$default = ['delete'];
|
||
|
$asCascade = $creatorIndex->getCascadeOn();
|
||
|
if (empty($asCascade)) {
|
||
|
$asCascade = $default;
|
||
|
}
|
||
|
$cascade = '';
|
||
|
foreach ($asCascade as $cascadeCase) {
|
||
|
$cascade .= sprintf(' ON %s CASCADE ', strtoupper($cascadeCase));
|
||
|
}
|
||
|
|
||
|
return sprintf(
|
||
|
'FOREIGN KEY (%s) REFERENCES %s (%s)%s',
|
||
|
implode(',', array_map([$this, 'escape'],$creatorIndex->getForeignKey())),
|
||
|
$this->escape($creatorIndex->getParentTable()),
|
||
|
implode(',', array_map([$this, 'escape'], $creatorIndex->getParenId())),
|
||
|
$cascade
|
||
|
);
|
||
|
}
|
||
|
|
||
|
$reference = implode(
|
||
|
',',
|
||
|
array_map(
|
||
|
function ($reference) {
|
||
|
return $this->escape($reference);
|
||
|
},
|
||
|
$creatorIndex->getReferences()
|
||
|
)
|
||
|
);
|
||
|
|
||
|
return sprintf('(%s)', $reference);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param IndexInterface $creatorIndex
|
||
|
*
|
||
|
* @throws EscapingException
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function generateLine(IndexInterface $creatorIndex): string
|
||
|
{
|
||
|
$line = $creatorIndex->getType();
|
||
|
|
||
|
if (!($creatorIndex instanceof PrimaryKeyInterface)) {
|
||
|
$lineName = $this->generateName($creatorIndex->getName());
|
||
|
$line .= ' ' . $lineName;
|
||
|
}
|
||
|
|
||
|
$line .= ' ' . $this->buildReferences($creatorIndex);
|
||
|
|
||
|
return trim($line);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param IndexInterface $creatorIndex
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
private function getName(IndexInterface $creatorIndex): string
|
||
|
{
|
||
|
return $creatorIndex->getName() ?? '';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param IndexInterface $creatorIndex
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function getKeyName(IndexInterface $creatorIndex): string
|
||
|
{
|
||
|
if ($creatorIndex instanceof PrimaryKeyInterface) {
|
||
|
return 'PRIMARY';
|
||
|
}
|
||
|
$keyName = $this->getName($creatorIndex);
|
||
|
|
||
|
return $keyName ?? trim(str_replace('KEY', '', $creatorIndex->getType()));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param string $tableName
|
||
|
*
|
||
|
* @throws LineGeneratorException
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
public function fetchIndexesFromDb(string $tableName): array
|
||
|
{
|
||
|
try {
|
||
|
$indexes = $this->db->fetchAll('SHOW INDEXES FROM ' . $this->db->escapeIdentifier($tableName));
|
||
|
} catch (QueryFailureException | EscapingException $exception) {
|
||
|
throw new LineGeneratorException(
|
||
|
$exception->getMessage(),
|
||
|
$exception->getCode(),
|
||
|
$exception->getPrevious()
|
||
|
);
|
||
|
}
|
||
|
|
||
|
$result = [];
|
||
|
foreach ($indexes as $index) {
|
||
|
$keyName = $index['Key_name'];
|
||
|
$resultKey = array_search($keyName, array_column($result, 'name'), true);
|
||
|
|
||
|
if ($resultKey !== false) {
|
||
|
$result[$resultKey]['columns'][] = $index['Column_name'];
|
||
|
}
|
||
|
|
||
|
if ($resultKey === false) {
|
||
|
$result[] = [
|
||
|
'name' => $index['Key_name'],
|
||
|
'columns' => [$index['Column_name']],
|
||
|
'unique' => (int)$index['Non_unique'] === 0,
|
||
|
];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $result;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param string $name
|
||
|
*
|
||
|
* @throws EscapingException
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function escape(string $name): string
|
||
|
{
|
||
|
return $this->db->escapeIdentifier($name);
|
||
|
}
|
||
|
}
|