Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
100.00% |
1 / 1 |
|
100.00% |
11 / 11 |
CRAP | |
100.00% |
64 / 64 |
| ReferenceListMigrator | |
100.00% |
1 / 1 |
|
100.00% |
11 / 11 |
29 | |
100.00% |
64 / 64 |
| __construct | |
100.00% |
1 / 1 |
1 | |
100.00% |
6 / 6 |
|||
| createAlterStatementList | |
100.00% |
1 / 1 |
5 | |
100.00% |
11 / 11 |
|||
| getConstraintByReference | |
100.00% |
1 / 1 |
3 | |
100.00% |
4 / 4 |
|||
| createAlterStatement | |
100.00% |
1 / 1 |
3 | |
100.00% |
8 / 8 |
|||
| compareMapping | |
100.00% |
1 / 1 |
6 | |
100.00% |
17 / 17 |
|||
| areMappingIdentical | |
100.00% |
1 / 1 |
3 | |
100.00% |
6 / 6 |
|||
| getConstraintMappingByReferenceMapping | |
100.00% |
1 / 1 |
4 | |
100.00% |
4 / 4 |
|||
| addDropConstraintStatement | |
100.00% |
1 / 1 |
1 | |
100.00% |
3 / 3 |
|||
| addCreateReference | |
100.00% |
1 / 1 |
1 | |
100.00% |
3 / 3 |
|||
| getAddForeignKeyStatementList | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| getDropForeignKeyStatementList | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
| <?php | |
| declare(strict_types = 1); | |
| namespace Siesta\Migration; | |
| use Siesta\Database\MetaData\ConstraintMappingMetaData; | |
| use Siesta\Database\MetaData\ConstraintMetaData; | |
| use Siesta\Database\MigrationStatementFactory; | |
| use Siesta\Model\Reference; | |
| use Siesta\Model\ReferenceMapping; | |
| /** | |
| * @author Gregor Müller | |
| */ | |
| class ReferenceListMigrator | |
| { | |
| /** | |
| * @var ConstraintMetaData[] | |
| */ | |
| protected $constraintMetaDataList; | |
| /** | |
| * @var Reference[] | |
| */ | |
| protected $referenceList; | |
| /** | |
| * @var MigrationStatementFactory | |
| */ | |
| protected $migrationStatementFactory; | |
| /** | |
| * @var string[] | |
| */ | |
| protected $dropForeignKeyStatementList; | |
| /** | |
| * @var string[] | |
| */ | |
| protected $addForeignKeyStatementList; | |
| /** | |
| * ReferenceListMigrator constructor. | |
| * | |
| * @param MigrationStatementFactory $migrationStatementFactory | |
| * @param ConstraintMetaData[] $constraintMetaDataList | |
| * @param Reference[] $referenceList | |
| */ | |
| public function __construct(MigrationStatementFactory $migrationStatementFactory, array $constraintMetaDataList, array $referenceList) | |
| { | |
| $this->migrationStatementFactory = $migrationStatementFactory; | |
| $this->constraintMetaDataList = $constraintMetaDataList; | |
| $this->referenceList = $referenceList; | |
| $this->addForeignKeyStatementList = []; | |
| $this->dropForeignKeyStatementList = []; | |
| } | |
| /** | |
| * compares the refernces (foreign key) found in the database with the definition in the model and creates alter | |
| * statements for columns and foreign key constraints | |
| * @return void | |
| */ | |
| public function createAlterStatementList() | |
| { | |
| $processedDatabaseList = []; | |
| // iterate references from model and retrieve alter statements | |
| foreach ($this->referenceList as $reference) { | |
| // check if a corresponding database reference exists | |
| $constraint = $this->getConstraintByReference($reference); | |
| // retrieve alter statements and add them | |
| $this->createAlterStatement($constraint, $reference); | |
| // if a database reference has been found add it to the processed list | |
| if ($constraint) { | |
| $processedDatabaseList[] = $constraint->getConstraintName(); | |
| } | |
| } | |
| // iterate references from database and retrieve alter statements | |
| foreach ($this->constraintMetaDataList as $constraintMetaData) { | |
| // check if reference has already been processed | |
| if (in_array($constraintMetaData->getConstraintName(), $processedDatabaseList)) { | |
| continue; | |
| } | |
| // no corresponding model reference will result in drop statements | |
| $this->createAlterStatement($constraintMetaData, null); | |
| } | |
| } | |
| /** | |
| * @param Reference $reference | |
| * | |
| * @return null|ConstraintMetaData | |
| */ | |
| private function getConstraintByReference(Reference $reference) | |
| { | |
| foreach ($this->constraintMetaDataList as $constraintMetaData) { | |
| if ($constraintMetaData->getConstraintName() === $reference->getConstraintName()) { | |
| return $constraintMetaData; | |
| } | |
| } | |
| return null; | |
| } | |
| /** | |
| * @param ConstraintMetaData $constraintMetaData | |
| * @param Reference $reference | |
| */ | |
| private function createAlterStatement(ConstraintMetaData $constraintMetaData = null, Reference $reference = null) | |
| { | |
| if ($constraintMetaData === null) { | |
| $this->addCreateReference($reference); | |
| return; | |
| } | |
| if ($reference === null) { | |
| $this->addDropConstraintStatement($constraintMetaData); | |
| return; | |
| } | |
| $this->compareMapping($constraintMetaData, $reference); | |
| } | |
| /** | |
| * @param ConstraintMetaData $constraintMetaData | |
| * @param Reference $reference | |
| */ | |
| private function compareMapping(ConstraintMetaData $constraintMetaData, Reference $reference) | |
| { | |
| // check if they are referencing the same column | |
| if ($constraintMetaData->getForeignTable() !== $reference->getForeignTable()) { | |
| $this->addDropConstraintStatement($constraintMetaData); | |
| $this->addCreateReference($reference); | |
| return; | |
| } | |
| if (sizeof($constraintMetaData->getConstraintMappingList()) !== sizeof($reference->getReferenceMappingList())) { | |
| $this->addDropConstraintStatement($constraintMetaData); | |
| $this->addCreateReference($reference); | |
| return; | |
| } | |
| // modify columns if needed and check if the | |
| if (!$this->areMappingIdentical($constraintMetaData, $reference)) { | |
| $this->addDropConstraintStatement($constraintMetaData); | |
| $this->addCreateReference($reference); | |
| return; | |
| } | |
| // compare on update // >> drop constraint, add constraint | |
| if ($constraintMetaData->getOnUpdate() === $reference->getOnUpdate() and $constraintMetaData->getOnDelete() === $reference->getOnDelete()) { | |
| return; | |
| } | |
| $this->addCreateReference($reference); | |
| $this->addDropConstraintStatement($constraintMetaData); | |
| } | |
| /** | |
| * @param ConstraintMetaData $constraintMetaData | |
| * @param Reference $reference | |
| * | |
| * @return bool | |
| */ | |
| protected function areMappingIdentical(ConstraintMetaData $constraintMetaData, Reference $reference) : bool | |
| { | |
| foreach ($reference->getReferenceMappingList() as $referenceMapping) { | |
| $constraintMappingMetaDataList = $constraintMetaData->getConstraintMappingList(); | |
| $constraintMappingMetaData = $this->getConstraintMappingByReferenceMapping($constraintMappingMetaDataList, $referenceMapping); | |
| if ($constraintMappingMetaData === null) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| /** | |
| * @param ConstraintMappingMetaData[] $constraintMappingList | |
| * @param ReferenceMapping $referenceMapping | |
| * | |
| * @return ConstraintMappingMetaData|null | |
| */ | |
| protected function getConstraintMappingByReferenceMapping(array $constraintMappingList, ReferenceMapping $referenceMapping) | |
| { | |
| foreach ($constraintMappingList as $constraintMapping) { | |
| if ($constraintMapping->getLocalColumn() === $referenceMapping->getLocalColumnName() && $constraintMapping->getForeignColumn() === $referenceMapping->getForeignColumnName()) { | |
| return $constraintMapping; | |
| } | |
| } | |
| return null; | |
| } | |
| /** | |
| * @param ConstraintMetaData $constraintMetaData | |
| */ | |
| private function addDropConstraintStatement(ConstraintMetaData $constraintMetaData) | |
| { | |
| $dropList = $this->migrationStatementFactory->createDropConstraintStatement($constraintMetaData); | |
| $this->dropForeignKeyStatementList = array_merge($this->dropForeignKeyStatementList, $dropList); | |
| } | |
| /** | |
| * @param Reference $reference | |
| */ | |
| private function addCreateReference(Reference $reference) | |
| { | |
| $addList = $this->migrationStatementFactory->createAddReferenceStatement($reference); | |
| $this->addForeignKeyStatementList = array_merge($this->addForeignKeyStatementList, $addList); | |
| } | |
| /** | |
| * @return string[] | |
| */ | |
| public function getAddForeignKeyStatementList() | |
| { | |
| return $this->addForeignKeyStatementList; | |
| } | |
| /** | |
| * @return string[] | |
| */ | |
| public function getDropForeignKeyStatementList() | |
| { | |
| return $this->dropForeignKeyStatementList; | |
| } | |
| } |