Lewati ke konten

Penggabungan Tingkat Sel

Penggabungan tingkat kolom mendeteksi jika kedua sisi mengubah kolom yang sama. Penggabungan tingkat sel bekerja lebih mendalam dengan menggabungkan isi di dalam kolom tersebut. Dua orang yang mengedit baris berbeda dalam kolom TEXT atau kunci berbeda pada objek JSON dapat menggabungkan perubahan dengan bersih.

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

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

Mengaktifkan penggabungan tingkat sel

Penggabungan tingkat sel bersifat opsional. Penggabungan ini hanya berjalan dalam ThreeWayMerge yang dibuat dengan CellMergeConfig. Tanpanya, setiap kolom yang diubah kedua sisi menjadi nilai berbeda akan menjadi konflik update_update.

Fasade Merql tidak menerima konfigurasi: Merql::merge(), Merql::patch(), dan Merql::plan() membuat new ThreeWayMerge() tanpanya, dan perintah merge milik CLI dijalankan melalui Merql::merge(). Semuanya selalu menggabungkan pada tingkat kolom (#7).

Untuk menggabungkan snapshot yang disimpan oleh fasade atau CLI dengan penggabungan tingkat sel, muat snapshot tersebut dan panggil ThreeWayMerge sendiri. Hasilnya adalah MergeResult biasa, sehingga fasade tetap dapat menerapkannya, dan MergePlanBuilder mengubahnya menjadi rencana penggabungan:

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

Penggabung sel hanya berjalan untuk kolom yang diubah kedua sisi. Jika hanya satu sisi yang mengubah kolom, nilainya digunakan apa adanya.

CellMergeConfig

CellMergeConfig memetakan kolom atau jenis kolom ke implementasi penggabung sel. Factory auto() menyediakan nilai default yang sesuai:

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

Prioritas resolusi penggabung:

  1. Nama kolom berkualifikasi (table.column).
  2. Nama kolom tanpa kualifikasi (column).
  3. Pencocokan pola jenis kolom (str_contains tanpa membedakan huruf besar dan kecil).
  4. Default: OpaqueCellMerger (selalu melaporkan konflik jika nilainya berbeda).

TextCellMerger

Menggabungkan teks multi-baris menggunakan diff Myers, algoritme yang sama dengan yang digunakan git untuk isi berkas. Setiap baris diperlakukan sebagai satu unit, dan perubahan pada baris yang berbeda dapat digabungkan dengan bersih.

PHP
use Merql\CellMerge\TextCellMerger;

$merger = new TextCellMerger();

Contoh: penggabungan teks yang bersih

Kode
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

Baris yang berbeda diedit. Penggabungan menghasilkan "LINE ONE\nline two\nLINE THREE" tanpa konflik.

Contoh: konflik teks

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

Kedua sisi mengubah baris yang sama menjadi nilai berbeda. Penggabung mengembalikan hasil konflik. Konten gabungan menyertakan penanda konflik yang mirip dengan git.

Cara kerjanya

TextCellMerger mendelegasikan ke ThreeWayMerge::merge() milik pitmaster, yang menghitung diff Myers antara base dan tiap sisi, lalu menggabungkan kedua skrip edit. Jika edit saling tumpang tindih pada wilayah baris yang sama, konflik akan dilaporkan.

JsonCellMerger

Menggabungkan objek JSON dengan membandingkan kunci tingkat atas secara terpisah. Setiap kunci digabungkan menggunakan aturan tiga arah standar.

PHP
use Merql\CellMerge\JsonCellMerger;

$merger = new JsonCellMerger();

Contoh: penggabungan JSON yang bersih

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}

Kunci yang berbeda diubah. Hasil gabungannya adalah:

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

Contoh: konflik JSON

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

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

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

Kedua sisi mengubah kunci color menjadi nilai yang berbeda. Ini adalah konflik. Secara default, penggabung memilih ours dan melaporkan satu konflik.

Aturan tingkat kunci

Base Ours Theirs Hasil
Kunci tidak berubah Kunci tidak berubah Terima base
Kunci tidak berubah Kunci berubah Terima theirs
Kunci berubah Kunci tidak berubah Terima ours
Kunci berubah (sama) Kunci berubah (sama) Terima (sepakat)
Kunci berubah (berbeda) Kunci berubah (berbeda) Konflik (default: ours)
Kunci ada Kunci ada Kunci dihapus Terima penghapusan
Kunci ada Kunci dihapus Kunci ada Terima penghapusan
Kunci tidak ada Kunci ditambahkan Kunci tidak ada Terima penambahan
Kunci tidak ada Kunci tidak ada Kunci ditambahkan Terima penambahan

Objek bersarang dibandingkan sebagai string JSON tanpa struktur rekursif. Jika suatu objek bersarang berbeda, seluruh nilai kunci tersebut akan dibandingkan, bukan subkuncinya.

Persyaratan

Ketiga nilai harus berupa objek atau larik JSON yang valid. Jika ada nilai yang bukan JSON valid, atau berupa skalar JSON (string, angka, boolean), penggabung akan kembali menggunakan konflik.

OpaqueCellMerger

Penggabung default ketika tidak ada strategi tingkat sel yang dikonfigurasi. Penggabung ini memperlakukan nilai kolom sebagai blob buram dan selalu melaporkan konflik ketika kedua sisi berbeda.

PHP
use Merql\CellMerge\OpaqueCellMerger;

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

CellMergeResult

Semua penggabung sel mengembalikan 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

Metode factory:

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

Penggabung sel kustom

Implementasikan antarmuka CellMerger untuk menambahkan strategi penggabungan Anda sendiri:

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