Ugrás a tartalomhoz

Cellaszintű egyesítés

Az oszlopszintű egyesítés észleli, ha mindkét oldal ugyanazt az oszlopot módosította. A cellaszintű egyesítés mélyebbre hatol, és az oszlopon belüli tartalmat egyesíti. Két ember különböző sorokat szerkeszthet egy TEXT mezőben, vagy különböző kulcsokat egy JSON objektumban, és a módosítások ütközésmentesen egyesíthetők.

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

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

Cellaszintű egyesítés engedélyezése

A cellaszintű egyesítés választható. Csak olyan ThreeWayMerge esetén fut, amelyet CellMergeConfig értékkel hoztak létre. Enélkül minden olyan oszlop, amelyet mindkét oldal eltérő értékre módosított, update_update ütközésnek számít.

A Merql homlokzat nem fogad el konfigurációt: a Merql::merge(), Merql::patch() és Merql::plan() konfiguráció nélkül hozza létre a new ThreeWayMerge() példányát, a CLI merge parancsa pedig a Merql::merge() útján fut. Ezek mindig oszlopszinten egyesítenek (#7).

Ha a homlokzat vagy a CLI által mentett pillanatképeket cellaszintű egyesítéssel szeretné egyesíteni, töltse be őket, majd hívja meg saját maga a ThreeWayMerge műveletet. Az eredmény egy szokványos MergeResult, ezért a homlokzat továbbra is alkalmazhatja, a MergePlanBuilder pedig egyesítési tervvé alakítja:

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);

A cellaegyesítők csak azoknál az oszlopoknál futnak le, amelyeket mindkét oldal módosított. Ha csak az egyik oldal módosított egy oszlopot, az értéke változatlanul kerül át.

CellMergeConfig

A CellMergeConfig oszlopokat vagy oszloptípusokat rendel cellaegyesítő-megvalósításokhoz. A auto() gyár alapértelmezésként ésszerű beállításokat ad:

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());

Az egyesítő feloldásának prioritása:

  1. Minősített oszlopnév (table.column).
  2. Nem minősített oszlopnév (column).
  3. Oszloptípus szerinti illesztés (kis- és nagybetűket figyelmen kívül hagyó str_contains).
  4. Alapértelmezés: OpaqueCellMerger (eltérő értékek esetén mindig ütközést jelez).

TextCellMerger

Többsoros szöveget egyesít a Myers-féle különbségvizsgálattal, ugyanazzal az algoritmussal, amelyet a git használ a fájltartalomhoz. Minden sor önálló egységnek számít, így a különböző sorok módosításai ütközésmentesen egyesíthetők.

PHP
use Merql\CellMerge\TextCellMerger;

$merger = new TextCellMerger();

Példa: ütközésmentes szövegegyesítés

Kód
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

Különböző sorokat szerkesztettek. Az egyesítés eredménye "LINE ONE\nline two\nLINE THREE", ütközés nélkül.

Példa: szövegütközés

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

Mindkét oldal ugyanazt a sort módosította eltérő értékre. Az egyesítő ütközési eredményt ad vissza. Az egyesített tartalom a gitben használthoz hasonló ütközésjelölőket tartalmaz.

Működés

A TextCellMerger a pitmaster ThreeWayMerge::merge() megoldására bízza a feladatot, amely Myers-féle különbségvizsgálattal összehasonlítja a base állapotot mindkét oldallal, majd egyesíti a két módosítási listát. Ha a módosítások ugyanazon a sorszakaszon fedik egymást, ütközést jelez.

JsonCellMerger

JSON objektumokat egyesít úgy, hogy a legfelső szintű kulcsokat külön-külön hasonlítja össze. Minden kulcs egyesítése a szokásos háromutas szabályok szerint történik.

PHP
use Merql\CellMerge\JsonCellMerger;

$merger = new JsonCellMerger();

Példa: ütközésmentes JSON egyesítés

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}

A különböző kulcsok módosultak. Az egyesítés eredménye:

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

Példa: JSON ütközés

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

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

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

Mindkét oldal ugyanazt az color kulcsot módosította, eltérő értékre. Ez ütközés. Az egyesítő alapértelmezés szerint az ours értékét választja, és egy ütközést jelez.

Kulcsszintű szabályok

Base Ours Theirs Eredmény
Kulcs változatlan Kulcs változatlan Az alap elfogadása
Kulcs változatlan Kulcs módosult A theirs elfogadása
Kulcs módosult Kulcs változatlan Az ours elfogadása
Kulcs módosult (azonos) Kulcs módosult (azonos) Elfogadás (egyezés)
Kulcs módosult (eltérő) Kulcs módosult (eltérő) Ütközés (alapértelmezés: ours)
Kulcs létezik Kulcs létezik Kulcs eltávolítva Az eltávolítás elfogadása
Kulcs létezik Kulcs eltávolítva Kulcs létezik Az eltávolítás elfogadása
Kulcs hiányzik Kulcs hozzáadva Kulcs hiányzik A hozzáadás elfogadása
Kulcs hiányzik Kulcs hiányzik Kulcs hozzáadva A hozzáadás elfogadása

A beágyazott objektumokat átlátszatlan JSON karakterláncként hasonlítja össze, rekurzió nélkül. Ha egy beágyazott objektum eltér, a teljes kulcsértéket hasonlítja össze, nem annak alkulcsait.

Követelmények

Mindhárom értéknek érvényes JSON objektumnak vagy tömbnek kell lennie. Ha bármelyik érték nem érvényes JSON, vagy JSON skalár (karakterlánc, szám, logikai érték), az egyesítő ütközésre vált.

OpaqueCellMerger

Az alapértelmezett egyesítő, ha nincs beállítva cellaszintű stratégia. Az oszlopértéket átlátszatlan adatként kezeli, és mindig ütközést jelez, ha a két oldal eltér.

PHP
use Merql\CellMerge\OpaqueCellMerger;

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

CellMergeResult

Minden cellaegyesítő egy CellMergeResult értéket ad vissza:

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

Gyári metódusok:

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

Egyéni cellaegyesítők

Saját egyesítési stratégia hozzáadásához valósítsa meg a CellMerger interfészt:

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());