Preskoči na vsebino

Združevanje na ravni celic

Združevanje na ravni stolpcev zazna, kadar obe strani spremenita isti stolpec. Združevanje na ravni celic gre globlje in združuje vsebino znotraj tega stolpca. Dve osebi lahko brez težav združita spremembe različnih vrstic polja TEXT ali različnih ključev objekta JSON.

PHP
use Merql\CellMerge\CellMergeConfig;
use Merql\Merge\ThreeWayMerge;

$config = CellMergeConfig::auto();
$merge = new ThreeWayMerge($config);
$result = $merge->merge($base, $ours, $theirs);

Omogočanje združevanja na ravni celic

Združevanje na ravni celic je izbirno. Deluje samo, če je ThreeWayMerge ustvarjen z nastavitvijo CellMergeConfig. Brez nje vsak stolpec, ki sta ga obe strani spremenili na različni vrednosti, povzroči spor update_update.

Vmesnik Merql ne sprejme konfiguracije: Merql::merge(), Merql::patch() in Merql::plan() ustvarijo new ThreeWayMerge() brez nje, ukaz merge v CLI pa se izvaja prek Merql::merge(). Vedno združujejo na ravni stolpcev (#7).

Če želite posnetke, shranjene prek vmesnika ali CLI, združiti na ravni celic, jih naložite in sami pokličite ThreeWayMerge. Rezultat je običajen MergeResult, zato ga lahko vmesnik še vedno uveljavi, MergePlanBuilder pa ga pretvori v načrt združevanja:

PHP
use Merql\CellMerge\CellMergeConfig;
use Merql\Merge\ThreeWayMerge;
use Merql\Merql;
use Merql\Plan\MergePlanBuilder;
use Merql\Snapshot\SnapshotStore;

$base   = SnapshotStore::load('base');
$ours   = SnapshotStore::load('ours');
$theirs = SnapshotStore::load('theirs');

$result = (new ThreeWayMerge(CellMergeConfig::auto()))->merge($base, $ours, $theirs);

$plan = (new MergePlanBuilder())->build('plan-1', $base, $ours, $theirs, $result);

Združevalniki celic se zaženejo samo za stolpce, ki sta jih spremenili obe strani. Če je stolpec spremenila samo ena stran, se njegova vrednost prevzame nespremenjena.

CellMergeConfig

CellMergeConfig povezuje stolpce ali vrste stolpcev z izvedbami združevalnikov celic. Tovarna auto() ponuja smiselne privzete vrednosti:

PHP
use Merql\CellMerge\CellMergeConfig;
use Merql\CellMerge\JsonCellMerger;
use Merql\CellMerge\TextCellMerger;

// Auto: column types containing "text" (TEXT, MEDIUMTEXT, LONGTEXT, ...) use
// TextCellMerger, column types containing "json" use JsonCellMerger.
$config = CellMergeConfig::auto();

// Custom: assign mergers to specific columns.
$config = (new CellMergeConfig())
    ->forColumn('posts.content', new TextCellMerger())
    ->forColumn('settings', new JsonCellMerger())
    ->forType('json', new JsonCellMerger());

Prednostni vrstni red razreševanja združevalnikov:

  1. Polno kvalificirano ime stolpca (table.column).
  2. Nekvalificirano ime stolpca (column).
  3. Ujemanje vzorca vrste stolpca (brez razlikovanja velikih in malih črk str_contains).
  4. Privzeto: OpaqueCellMerger (ob različnih vrednostih vedno sporoči spor).

TextCellMerger

Združuje večvrstično besedilo z algoritmom Myers diff, ki ga git uporablja tudi za vsebino datotek. Vsaka vrstica je obravnavana kot enota, spremembe različnih vrstic pa se združijo brez sporov.

PHP
use Merql\CellMerge\TextCellMerger;

$merger = new TextCellMerger();

Primer: čisto združevanje besedila

Koda
Base:    "line one\nline two\nline three"
Ours:    "LINE ONE\nline two\nline three"    // changed line 1
Theirs:  "line one\nline two\nLINE THREE"    // changed line 3

Spremenjene so bile različne vrstice. Združitev ustvari "LINE ONE\nline two\nLINE THREE" brez sporov.

Primer: spor pri besedilu

Koda
Base:    "line one\nline two"
Ours:    "changed by us\nline two"     // changed line 1
Theirs:  "changed by them\nline two"   // also changed line 1

Obe strani sta isto vrstico spremenili na različni vrednosti. Združevalnik vrne rezultat s sporom. Združena vsebina vključuje oznake sporov, podobne kot pri git.

Kako deluje

TextCellMerger uporabi ThreeWayMerge::merge() iz pitmaster, ki izračuna Myersove razlike med osnovo in vsako stranjo, nato pa združi oba skripta sprememb. Če se spremembe prekrivajo na istem območju vrstic, sporoči spor.

JsonCellMerger

Združuje objekte JSON tako, da primerja vsak vrhnji ključ posebej. Vsak ključ združi po standardnih trosmernih pravilih.

PHP
use Merql\CellMerge\JsonCellMerger;

$merger = new JsonCellMerger();

Primer: čisto združevanje JSON

JSON
// Base
{"name": "Alice", "role": "editor", "active": true}

// Ours: changed "role"
{"name": "Alice", "role": "admin", "active": true}

// Theirs: changed "name"
{"name": "Bob", "role": "editor", "active": true}

Spremenjeni so bili različni ključi. Združeni rezultat je:

JSON
{"name": "Bob", "role": "admin", "active": true}

Primer: spor pri JSON

JSON
// Base
{"color": "red"}

// Ours
{"color": "blue"}

// Theirs
{"color": "green"}

Obe strani sta ključ color spremenili na različni vrednosti. To je spor. Združevalnik privzeto izbere našo vrednost in sporoči en spor.

Pravila za ključe

Osnova Naši Njihovi Rezultat
Ključ nespremenjen Ključ nespremenjen Sprejmi osnovo
Ključ nespremenjen Ključ spremenjen Sprejmi njihovega
Ključ spremenjen Ključ nespremenjen Sprejmi našega
Ključ spremenjen (enako) Ključ spremenjen (enako) Sprejmi (ujemanje)
Ključ spremenjen (različno) Ključ spremenjen (različno) Spor (privzeto: naši)
Ključ obstaja Ključ obstaja Ključ odstranjen Sprejmi odstranitev
Ključ obstaja Ključ odstranjen Ključ obstaja Sprejmi odstranitev
Ključ manjka Ključ dodan Ključ manjka Sprejmi dodajanje
Ključ manjka Ključ manjka Ključ dodan Sprejmi dodajanje

Vgnezdeni objekti so primerjani kot neprosojni nizi JSON in ne rekurzivno. Če se vgnezdeni objekt razlikuje, se primerja celotna vrednost tega ključa, ne njegovi podključi.

Zahteve

Vse tri vrednosti morajo biti veljavni objekti ali polja JSON. Če katera koli vrednost ni veljaven JSON ali je skalar JSON (niz, število, logična vrednost), združevalnik sporoči spor.

OpaqueCellMerger

Privzeti združevalnik, kadar strategija za raven celic ni nastavljena. Vrednost stolpca obravnava kot neprosojen blok in vedno sporoči spor, kadar se strani razlikujeta.

PHP
use Merql\CellMerge\OpaqueCellMerger;

$merger = new OpaqueCellMerger();
$result = $merger->merge($base, $ours, $theirs);
// $result->clean is always false when $ours !== $theirs

CellMergeResult

Vsi združevalniki celic vrnejo CellMergeResult:

PHP
$result = $merger->merge($base, $ours, $theirs);

$result->clean;     // bool: true if merge resolved cleanly
$result->value;     // mixed: the merged value (or ours on conflict)
$result->conflicts; // int: number of conflicts within the cell

Tovarniške metode:

PHP
CellMergeResult::resolved($value);           // clean merge
CellMergeResult::conflict($oursValue, $n);   // n conflicts, defaults to ours

Prilagojeni združevalniki celic

Izvedite vmesnik CellMerger, da dodate lastno strategijo združevanja:

PHP
use Merql\CellMerge\CellMerger;
use Merql\CellMerge\CellMergeResult;

class YamlCellMerger implements CellMerger
{
    public function merge(mixed $base, mixed $ours, mixed $theirs): CellMergeResult
    {
        // Parse YAML, merge keys, return result.
        $merged = $this->mergeYaml($base, $ours, $theirs);

        if ($merged['clean']) {
            return CellMergeResult::resolved($merged['value']);
        }

        return CellMergeResult::conflict($ours);
    }
}

$config = (new CellMergeConfig())
    ->forColumn('config_data', new YamlCellMerger());