404

[ Avaa Bypassed ]




Upload:

Command:

elspacio@18.219.227.70: ~ $
<?php

namespace Doctrine\DBAL\Schema;

use BadMethodCallException;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types;
use Doctrine\Deprecations\Deprecation;

use function array_intersect_key;
use function array_key_exists;
use function array_keys;
use function array_map;
use function array_merge;
use function array_unique;
use function assert;
use function count;
use function get_class;
use function sprintf;
use function strtolower;

/**
 * Compares two Schemas and return an instance of SchemaDiff.
 *
 * @method SchemaDiff compareSchemas(Schema $fromSchema, Schema $toSchema)
 */
class Comparator
{
    private ?AbstractPlatform $platform;

    /** @internal The comparator can be only instantiated by a schema manager. */
    public function __construct(?AbstractPlatform $platform = null)
    {
        if ($platform === null) {
            Deprecation::triggerIfCalledFromOutside(
                'doctrine/dbal',
                'https://github.com/doctrine/dbal/pull/4746',
                'Not passing a $platform to %s is deprecated.'
                    . ' Use AbstractSchemaManager::createComparator() to instantiate the comparator.',
                __METHOD__,
            );
        }

        $this->platform = $platform;
    }

    /** @param list<mixed> $args */
    public function __call(string $method, array $args): SchemaDiff
    {
        if ($method !== 'compareSchemas') {
            throw new BadMethodCallException(sprintf('Unknown method "%s"', $method));
        }

        return $this->doCompareSchemas(...$args);
    }

    /** @param list<mixed> $args */
    public static function __callStatic(string $method, array $args): SchemaDiff
    {
        if ($method !== 'compareSchemas') {
            throw new BadMethodCallException(sprintf('Unknown method "%s"', $method));
        }

        Deprecation::trigger(
            'doctrine/dbal',
            'https://github.com/doctrine/dbal/pull/4707',
            'Calling %s::%s() statically is deprecated.',
            self::class,
            $method,
        );

        $comparator = new self();

        return $comparator->doCompareSchemas(...$args);
    }

    /**
     * Returns a SchemaDiff object containing the differences between the schemas $fromSchema and $toSchema.
     *
     * This method should be called non-statically since it will be declared as non-static in the next major release.
     *
     * @return SchemaDiff
     *
     * @throws SchemaException
     */
    private function doCompareSchemas(
        Schema $fromSchema,
        Schema $toSchema
    ) {
        $createdSchemas   = [];
        $droppedSchemas   = [];
        $createdTables    = [];
        $alteredTables    = [];
        $droppedTables    = [];
        $createdSequences = [];
        $alteredSequences = [];
        $droppedSequences = [];

        $orphanedForeignKeys = [];

        $foreignKeysToTable = [];

        foreach ($toSchema->getNamespaces() as $namespace) {
            if ($fromSchema->hasNamespace($namespace)) {
                continue;
            }

            $createdSchemas[$namespace] = $namespace;
        }

        foreach ($fromSchema->getNamespaces() as $namespace) {
            if ($toSchema->hasNamespace($namespace)) {
                continue;
            }

            $droppedSchemas[$namespace] = $namespace;
        }

        foreach ($toSchema->getTables() as $table) {
            $tableName = $table->getShortestName($toSchema->getName());
            if (! $fromSchema->hasTable($tableName)) {
                $createdTables[$tableName] = $toSchema->getTable($tableName);
            } else {
                $tableDifferences = $this->diffTable(
                    $fromSchema->getTable($tableName),
                    $toSchema->getTable($tableName),
                );

                if ($tableDifferences !== false) {
                    $alteredTables[$tableName] = $tableDifferences;
                }
            }
        }

        /* Check if there are tables removed */
        foreach ($fromSchema->getTables() as $table) {
            $tableName = $table->getShortestName($fromSchema->getName());

            $table = $fromSchema->getTable($tableName);
            if (! $toSchema->hasTable($tableName)) {
                $droppedTables[$tableName] = $table;
            }

            // also remember all foreign keys that point to a specific table
            foreach ($table->getForeignKeys() as $foreignKey) {
                $foreignTable = strtolower($foreignKey->getForeignTableName());
                if (! isset($foreignKeysToTable[$foreignTable])) {
                    $foreignKeysToTable[$foreignTable] = [];
                }

                $foreignKeysToTable[$foreignTable][] = $foreignKey;
            }
        }

        foreach ($droppedTables as $tableName => $table) {
            if (! isset($foreignKeysToTable[$tableName])) {
                continue;
            }

            foreach ($foreignKeysToTable[$tableName] as $foreignKey) {
                if (isset($droppedTables[strtolower($foreignKey->getLocalTableName())])) {
                    continue;
                }

                $orphanedForeignKeys[] = $foreignKey;
            }

            // deleting duplicated foreign keys present on both on the orphanedForeignKey
            // and the removedForeignKeys from changedTables
            foreach ($foreignKeysToTable[$tableName] as $foreignKey) {
                // strtolower the table name to make if compatible with getShortestName
                $localTableName = strtolower($foreignKey->getLocalTableName());
                if (! isset($alteredTables[$localTableName])) {
                    continue;
                }

                foreach ($alteredTables[$localTableName]->getDroppedForeignKeys() as $droppedForeignKey) {
                    assert($droppedForeignKey instanceof ForeignKeyConstraint);

                    // We check if the key is from the removed table if not we skip.
                    if ($tableName !== strtolower($droppedForeignKey->getForeignTableName())) {
                        continue;
                    }

                    $alteredTables[$localTableName]->unsetDroppedForeignKey($droppedForeignKey);
                }
            }
        }

        foreach ($toSchema->getSequences() as $sequence) {
            $sequenceName = $sequence->getShortestName($toSchema->getName());
            if (! $fromSchema->hasSequence($sequenceName)) {
                if (! $this->isAutoIncrementSequenceInSchema($fromSchema, $sequence)) {
                    $createdSequences[] = $sequence;
                }
            } else {
                if ($this->diffSequence($sequence, $fromSchema->getSequence($sequenceName))) {
                    $alteredSequences[] = $toSchema->getSequence($sequenceName);
                }
            }
        }

        foreach ($fromSchema->getSequences() as $sequence) {
            if ($this->isAutoIncrementSequenceInSchema($toSchema, $sequence)) {
                continue;
            }

            $sequenceName = $sequence->getShortestName($fromSchema->getName());

            if ($toSchema->hasSequence($sequenceName)) {
                continue;
            }

            $droppedSequences[] = $sequence;
        }

        $diff = new SchemaDiff(
            $createdTables,
            $alteredTables,
            $droppedTables,
            $fromSchema,
            $createdSchemas,
            $droppedSchemas,
            $createdSequences,
            $alteredSequences,
            $droppedSequences,
        );

        $diff->orphanedForeignKeys = $orphanedForeignKeys;

        return $diff;
    }

    /**
     * @deprecated Use non-static call to {@see compareSchemas()} instead.
     *
     * @return SchemaDiff
     *
     * @throws SchemaException
     */
    public function compare(Schema $fromSchema, Schema $toSchema)
    {
        Deprecation::trigger(
            'doctrine/dbal',
            'https://github.com/doctrine/dbal/pull/4707',
            'Method compare() is deprecated. Use a non-static call to compareSchemas() instead.',
        );

        return $this->compareSchemas($fromSchema, $toSchema);
    }

    /**
     * @param Schema   $schema
     * @param Sequence $sequence
     */
    private function isAutoIncrementSequenceInSchema($schema, $sequence): bool
    {
        foreach ($schema->getTables() as $table) {
            if ($sequence->isAutoIncrementsFor($table)) {
                return true;
            }
        }

        return false;
    }

    /** @return bool */
    public function diffSequence(Sequence $sequence1, Sequence $sequence2)
    {
        if ($sequence1->getAllocationSize() !== $sequence2->getAllocationSize()) {
            return true;
        }

        return $sequence1->getInitialValue() !== $sequence2->getInitialValue();
    }

    /**
     * Returns the difference between the tables $fromTable and $toTable.
     *
     * If there are no differences this method returns the boolean false.
     *
     * @deprecated Use {@see compareTables()} and, optionally, {@see TableDiff::isEmpty()} instead.
     *
     * @return TableDiff|false
     *
     * @throws Exception
     */
    public function diffTable(Table $fromTable, Table $toTable)
    {
        Deprecation::triggerIfCalledFromOutside(
            'doctrine/dbal',
            'https://github.com/doctrine/dbal/pull/5770',
            '%s is deprecated. Use compareTables() instead.',
            __METHOD__,
        );

        $diff = $this->compareTables($fromTable, $toTable);

        if ($diff->isEmpty()) {
            return false;
        }

        return $diff;
    }

    /**
     * Compares the tables and returns the difference between them.
     *
     * @throws Exception
     */
    public function compareTables(Table $fromTable, Table $toTable): TableDiff
    {
        $addedColumns        = [];
        $modifiedColumns     = [];
        $droppedColumns      = [];
        $addedIndexes        = [];
        $modifiedIndexes     = [];
        $droppedIndexes      = [];
        $addedForeignKeys    = [];
        $modifiedForeignKeys = [];
        $droppedForeignKeys  = [];

        $fromTableColumns = $fromTable->getColumns();
        $toTableColumns   = $toTable->getColumns();

        /* See if all the columns in "from" table exist in "to" table */
        foreach ($toTableColumns as $columnName => $column) {
            if ($fromTable->hasColumn($columnName)) {
                continue;
            }

            $addedColumns[$columnName] = $column;
        }

        /* See if there are any removed columns in "to" table */
        foreach ($fromTableColumns as $columnName => $column) {
            // See if column is removed in "to" table.
            if (! $toTable->hasColumn($columnName)) {
                $droppedColumns[$columnName] = $column;

                continue;
            }

            $toColumn = $toTable->getColumn($columnName);

            // See if column has changed properties in "to" table.
            $changedProperties = $this->diffColumn($column, $toColumn);

            if ($this->platform !== null) {
                if ($this->columnsEqual($column, $toColumn)) {
                    continue;
                }
            } elseif (count($changedProperties) === 0) {
                continue;
            }

            $modifiedColumns[$column->getName()] = new ColumnDiff(
                $column->getName(),
                $toColumn,
                $changedProperties,
                $column,
            );
        }

        $renamedColumns = $this->detectRenamedColumns($addedColumns, $droppedColumns);

        $fromTableIndexes = $fromTable->getIndexes();
        $toTableIndexes   = $toTable->getIndexes();

        /* See if all the indexes in "from" table exist in "to" table */
        foreach ($toTableIndexes as $indexName => $index) {
            if (($index->isPrimary() && $fromTable->getPrimaryKey() !== null) || $fromTable->hasIndex($indexName)) {
                continue;
            }

            $addedIndexes[$indexName] = $index;
        }

        /* See if there are any removed indexes in "to" table */
        foreach ($fromTableIndexes as $indexName => $index) {
            // See if index is removed in "to" table.
            if (
                ($index->isPrimary() && $toTable->getPrimaryKey() === null) ||
                ! $index->isPrimary() && ! $toTable->hasIndex($indexName)
            ) {
                $droppedIndexes[$indexName] = $index;

                continue;
            }

            // See if index has changed in "to" table.
            $toTableIndex = $index->isPrimary() ? $toTable->getPrimaryKey() : $toTable->getIndex($indexName);
            assert($toTableIndex instanceof Index);

            if (! $this->diffIndex($index, $toTableIndex)) {
                continue;
            }

            $modifiedIndexes[$indexName] = $toTableIndex;
        }

        $renamedIndexes = $this->detectRenamedIndexes($addedIndexes, $droppedIndexes);

        $fromForeignKeys = $fromTable->getForeignKeys();
        $toForeignKeys   = $toTable->getForeignKeys();

        foreach ($fromForeignKeys as $fromKey => $fromConstraint) {
            foreach ($toForeignKeys as $toKey => $toConstraint) {
                if ($this->diffForeignKey($fromConstraint, $toConstraint) === false) {
                    unset($fromForeignKeys[$fromKey], $toForeignKeys[$toKey]);
                } else {
                    if (strtolower($fromConstraint->getName()) === strtolower($toConstraint->getName())) {
                        $modifiedForeignKeys[] = $toConstraint;

                        unset($fromForeignKeys[$fromKey], $toForeignKeys[$toKey]);
                    }
                }
            }
        }

        foreach ($fromForeignKeys as $fromConstraint) {
            $droppedForeignKeys[] = $fromConstraint;
        }

        foreach ($toForeignKeys as $toConstraint) {
            $addedForeignKeys[] = $toConstraint;
        }

        return new TableDiff(
            $toTable->getName(),
            $addedColumns,
            $modifiedColumns,
            $droppedColumns,
            $addedIndexes,
            $modifiedIndexes,
            $droppedIndexes,
            $fromTable,
            $addedForeignKeys,
            $modifiedForeignKeys,
            $droppedForeignKeys,
            $renamedColumns,
            $renamedIndexes,
        );
    }

    /**
     * Try to find columns that only changed their name, rename operations maybe cheaper than add/drop
     * however ambiguities between different possibilities should not lead to renaming at all.
     *
     * @param array<string,Column> $addedColumns
     * @param array<string,Column> $removedColumns
     *
     * @return array<string,Column>
     *
     * @throws Exception
     */
    private function detectRenamedColumns(array &$addedColumns, array &$removedColumns): array
    {
        $candidatesByName = [];

        foreach ($addedColumns as $addedColumnName => $addedColumn) {
            foreach ($removedColumns as $removedColumn) {
                if (! $this->columnsEqual($addedColumn, $removedColumn)) {
                    continue;
                }

                $candidatesByName[$addedColumn->getName()][] = [$removedColumn, $addedColumn, $addedColumnName];
            }
        }

        $renamedColumns = [];

        foreach ($candidatesByName as $candidates) {
            if (count($candidates) !== 1) {
                continue;
            }

            [$removedColumn, $addedColumn] = $candidates[0];
            $removedColumnName             = $removedColumn->getName();
            $addedColumnName               = strtolower($addedColumn->getName());

            if (isset($renamedColumns[$removedColumnName])) {
                continue;
            }

            $renamedColumns[$removedColumnName] = $addedColumn;
            unset(
                $addedColumns[$addedColumnName],
                $removedColumns[strtolower($removedColumnName)],
            );
        }

        return $renamedColumns;
    }

    /**
     * Try to find indexes that only changed their name, rename operations maybe cheaper than add/drop
     * however ambiguities between different possibilities should not lead to renaming at all.
     *
     * @param array<string,Index> $addedIndexes
     * @param array<string,Index> $removedIndexes
     *
     * @return array<string,Index>
     */
    private function detectRenamedIndexes(array &$addedIndexes, array &$removedIndexes): array
    {
        $candidatesByName = [];

        // Gather possible rename candidates by comparing each added and removed index based on semantics.
        foreach ($addedIndexes as $addedIndexName => $addedIndex) {
            foreach ($removedIndexes as $removedIndex) {
                if ($this->diffIndex($addedIndex, $removedIndex)) {
                    continue;
                }

                $candidatesByName[$addedIndex->getName()][] = [$removedIndex, $addedIndex, $addedIndexName];
            }
        }

        $renamedIndexes = [];

        foreach ($candidatesByName as $candidates) {
            // If the current rename candidate contains exactly one semantically equal index,
            // we can safely rename it.
            // Otherwise, it is unclear if a rename action is really intended,
            // therefore we let those ambiguous indexes be added/dropped.
            if (count($candidates) !== 1) {
                continue;
            }

            [$removedIndex, $addedIndex] = $candidates[0];

            $removedIndexName = strtolower($removedIndex->getName());
            $addedIndexName   = strtolower($addedIndex->getName());

            if (isset($renamedIndexes[$removedIndexName])) {
                continue;
            }

            $renamedIndexes[$removedIndexName] = $addedIndex;
            unset(
                $addedIndexes[$addedIndexName],
                $removedIndexes[$removedIndexName],
            );
        }

        return $renamedIndexes;
    }

    /**
     * @internal The method should be only used from within the {@see Comparator} class hierarchy.
     *
     * @return bool
     */
    public function diffForeignKey(ForeignKeyConstraint $key1, ForeignKeyConstraint $key2)
    {
        if (
            array_map('strtolower', $key1->getUnquotedLocalColumns())
            !== array_map('strtolower', $key2->getUnquotedLocalColumns())
        ) {
            return true;
        }

        if (
            array_map('strtolower', $key1->getUnquotedForeignColumns())
            !== array_map('strtolower', $key2->getUnquotedForeignColumns())
        ) {
            return true;
        }

        if ($key1->getUnqualifiedForeignTableName() !== $key2->getUnqualifiedForeignTableName()) {
            return true;
        }

        if ($key1->onUpdate() !== $key2->onUpdate()) {
            return true;
        }

        return $key1->onDelete() !== $key2->onDelete();
    }

    /**
     * Compares the definitions of the given columns
     *
     * @internal The method should be only used from within the {@see Comparator} class hierarchy.
     *
     * @throws Exception
     */
    public function columnsEqual(Column $column1, Column $column2): bool
    {
        if ($this->platform === null) {
            return $this->diffColumn($column1, $column2) === [];
        }

        return $this->platform->columnsEqual($column1, $column2);
    }

    /**
     * Returns the difference between the columns
     *
     * If there are differences this method returns the changed properties as a
     * string array, otherwise an empty array gets returned.
     *
     * @deprecated Use {@see columnsEqual()} instead.
     *
     * @return string[]
     */
    public function diffColumn(Column $column1, Column $column2)
    {
        Deprecation::triggerIfCalledFromOutside(
            'doctrine/dbal',
            'https://github.com/doctrine/dbal/pull/5650',
            '%s is deprecated. Use diffTable() instead.',
            __METHOD__,
        );

        $properties1 = $column1->toArray();
        $properties2 = $column2->toArray();

        $changedProperties = [];

        if (get_class($properties1['type']) !== get_class($properties2['type'])) {
            $changedProperties[] = 'type';
        }

        foreach (['notnull', 'unsigned', 'autoincrement'] as $property) {
            if ($properties1[$property] === $properties2[$property]) {
                continue;
            }

            $changedProperties[] = $property;
        }

        // Null values need to be checked additionally as they tell whether to create or drop a default value.
        // null != 0, null != false, null != '' etc. This affects platform's table alteration SQL generation.
        if (
            ($properties1['default'] === null) !== ($properties2['default'] === null)
            || $properties1['default'] != $properties2['default']
        ) {
            $changedProperties[] = 'default';
        }

        if (
            ($properties1['type'] instanceof Types\StringType && ! $properties1['type'] instanceof Types\GuidType) ||
            $properties1['type'] instanceof Types\BinaryType
        ) {
            // check if value of length is set at all, default value assumed otherwise.
            $length1 = $properties1['length'] ?? 255;
            $length2 = $properties2['length'] ?? 255;
            if ($length1 !== $length2) {
                $changedProperties[] = 'length';
            }

            if ($properties1['fixed'] !== $properties2['fixed']) {
                $changedProperties[] = 'fixed';
            }
        } elseif ($properties1['type'] instanceof Types\DecimalType) {
            if (($properties1['precision'] ?? 10) !== ($properties2['precision'] ?? 10)) {
                $changedProperties[] = 'precision';
            }

            if ($properties1['scale'] !== $properties2['scale']) {
                $changedProperties[] = 'scale';
            }
        }

        // A null value and an empty string are actually equal for a comment so they should not trigger a change.
        if (
            $properties1['comment'] !== $properties2['comment'] &&
            ! ($properties1['comment'] === null && $properties2['comment'] === '') &&
            ! ($properties2['comment'] === null && $properties1['comment'] === '')
        ) {
            $changedProperties[] = 'comment';
        }

        $customOptions1 = $column1->getCustomSchemaOptions();
        $customOptions2 = $column2->getCustomSchemaOptions();

        foreach (array_merge(array_keys($customOptions1), array_keys($customOptions2)) as $key) {
            if (! array_key_exists($key, $properties1) || ! array_key_exists($key, $properties2)) {
                $changedProperties[] = $key;
            } elseif ($properties1[$key] !== $properties2[$key]) {
                $changedProperties[] = $key;
            }
        }

        $platformOptions1 = $column1->getPlatformOptions();
        $platformOptions2 = $column2->getPlatformOptions();

        foreach (array_keys(array_intersect_key($platformOptions1, $platformOptions2)) as $key) {
            if ($properties1[$key] === $properties2[$key]) {
                continue;
            }

            $changedProperties[] = $key;
        }

        return array_unique($changedProperties);
    }

    /**
     * Finds the difference between the indexes $index1 and $index2.
     *
     * Compares $index1 with $index2 and returns true if there are any
     * differences or false in case there are no differences.
     *
     * @internal The method should be only used from within the {@see Comparator} class hierarchy.
     *
     * @return bool
     */
    public function diffIndex(Index $index1, Index $index2)
    {
        return ! ($index1->isFulfilledBy($index2) && $index2->isFulfilledBy($index1));
    }
}

Filemanager

Name Type Size Permission Actions
Exception Folder 0755
Visitor Folder 0755
AbstractAsset.php File 6 KB 0644
AbstractSchemaManager.php File 49.85 KB 0644
Column.php File 9.38 KB 0644
ColumnDiff.php File 4.14 KB 0644
Comparator.php File 23.55 KB 0644
Constraint.php File 1.04 KB 0644
DB2SchemaManager.php File 12.66 KB 0644
DefaultSchemaManagerFactory.php File 578 B 0644
ForeignKeyConstraint.php File 11.03 KB 0644
Identifier.php File 666 B 0644
Index.php File 8.72 KB 0644
LegacySchemaManagerFactory.php File 455 B 0644
MySQLSchemaManager.php File 17.87 KB 0644
OracleSchemaManager.php File 16.03 KB 0644
PostgreSQLSchemaManager.php File 23.13 KB 0644
SQLServerSchemaManager.php File 18.6 KB 0644
Schema.php File 12.66 KB 0644
SchemaConfig.php File 2.4 KB 0644
SchemaDiff.php File 7.53 KB 0644
SchemaException.php File 5.41 KB 0644
SchemaManagerFactory.php File 381 B 0644
Sequence.php File 3.28 KB 0644
SqliteSchemaManager.php File 22.02 KB 0644
Table.php File 27.74 KB 0644
TableDiff.php File 9.61 KB 0644
UniqueConstraint.php File 3.19 KB 0644
View.php File 445 B 0644