src/Patch.php
public function make($a, $b = null, $c = null)
    {
        $diff = $this->getDiff();
        if (is_string($a) && is_string($b) && is_null($c)) {
            // Method 1: text1, text2
            // Compute diffs from text1 and text2.
            $text1 = $a;
            $diff->main($text1, $b);
            if (count($diff->getChanges()) > 2) {
                $diff->cleanupSemantic();
                $diff->cleanupEfficiency();
            }
            $diffs = $diff->getChanges();
        } elseif (is_array($a) && is_null($b)) {
            // Method 2: diffs
            // Compute text1 from diffs.
            $diffs = $a;
            $diff->setChanges($diffs);
            $text1 = $diff->text1();
        } elseif (is_string($a) && is_array($b) && is_null($c)) {
            // Method 3: text1, diffs
            $text1 = $a;
            $diffs = $b;
        } elseif (is_string($a) && is_string($b) && is_array($c)) {
            // Method 4: text1, text2, diffs
            $text1 = $a;
            $diffs = $c;
        } else {
            throw new \InvalidArgumentException("Unknown call format");
        }

        $patches = array();
        if (!isset($diffs)) {
            // Get rid of the null case.
            return $patches;
        }
        $patch = new PatchObject();
        // Number of characters into the text1 string.
        $charCount1 = 0;
        // Number of characters into the text2 string.
        $charCount2 = 0;
        // Recreate the patches to determine context info.
        $prePatchText = $text1;
        $postPatchText = $text1;
        for ($i = 0; $i < count($diffs); $i++) {
            list($diffType, $diffText) = $diffs[$i];
            $diffTextLen = mb_strlen($diffText);

            if (count($patch->getChanges()) == 0 && $diffType != Diff::EQUAL) {
                // A new patch starts here.
                $patch->setStart1($charCount1);
                $patch->setStart2($charCount2);
            }
            if ($diffType == Diff::INSERT) {
                // Insertion.
                $patch->appendChanges($diffs[$i]);
                $patch->setLength2($patch->getLength2() + $diffTextLen);
                $postPatchText = mb_substr($postPatchText, 0, $charCount2) .
                    $diffText . mb_substr($postPatchText, $charCount2);
            } elseif ($diffType == Diff::DELETE) {
                // Deletion.
                $patch->appendChanges($diffs[$i]);
                $patch->setLength1($patch->getLength1() + $diffTextLen);
                $postPatchText = mb_substr($postPatchText, 0, $charCount2) .
                    mb_substr($postPatchText, $charCount2 + $diffTextLen);
            } elseif (
                $diffType == Diff::EQUAL && $diffTextLen <= 2 * $this->getMargin() &&
                count($patch->getChanges()) && $i + 1 != count($diffs)
            ) {
                // Small equality inside a patch.
                $patch->appendChanges($diffs[$i]);
                $patch->setLength1($patch->getLength1() + $diffTextLen);
                $patch->setLength2($patch->getLength2() + $diffTextLen);
            }

            if ($diffType == Diff::EQUAL && $diffTextLen >= 2 * $this->getMargin()) {
                // Time for a new patch.
                if (count($patch->getChanges())) {
                    $this->addContext($patch, $prePatchText);
                    $patches[] = $patch;
                    $patch = new PatchObject();
                    // Unlike Unidiff, our patch lists have a rolling context.
                    // http://code.google.com/p/google-diff-match-patch/wiki/Unidiff
                    // Update prepatch text & pos to reflect the application of the
                    // just completed patch.
                    $prePatchText = $postPatchText;
                    $charCount1 = $charCount2;
                }
            }

            // Update the current character count.
            if ($diffType != Diff::INSERT) {
                $charCount1 += $diffTextLen;
            }
            if ($diffType != Diff::DELETE) {
                $charCount2 += $diffTextLen;
            }
        }

        // Pick up the leftover patch if not empty.
        if (count($patch->getChanges())) {
            $this->addContext($patch, $prePatchText);
            $patches[] = $patch;
        }

        return $patches;
    }
public function make($a, $b = null, $c = null)
    {
        $diff = $this->getDiff();
        if (is_string($a) && is_string($b) && is_null($c)) {
            // Method 1: text1, text2
            // Compute diffs from text1 and text2.
            $text1 = $a;
            $diff->main($text1, $b);
            if (count($diff->getChanges()) > 2) {
                $diff->cleanupSemantic();
                $diff->cleanupEfficiency();
            }
            $diffs = $diff->getChanges();
        } elseif (is_array($a) && is_null($b)) {
            // Method 2: diffs
            // Compute text1 from diffs.
            $diffs = $a;
            $diff->setChanges($diffs);
            $text1 = $diff->text1();
        } elseif (is_string($a) && is_array($b) && is_null($c)) {
            // Method 3: text1, diffs
            $text1 = $a;
            $diffs = $b;
        } elseif (is_string($a) && is_string($b) && is_array($c)) {
            // Method 4: text1, text2, diffs
            $text1 = $a;
            $diffs = $c;
        } else {
            throw new \InvalidArgumentException("Unknown call format");
        }

        $patches = array();
        if (!isset($diffs)) {
            // Get rid of the null case.
            return $patches;
        }
        $patch = new PatchObject();
        // Number of characters into the text1 string.
        $charCount1 = 0;
        // Number of characters into the text2 string.
        $charCount2 = 0;
        // Recreate the patches to determine context info.
        $prePatchText = $text1;
        $postPatchText = $text1;
        for ($i = 0; $i < count($diffs); $i++) {
            list($diffType, $diffText) = $diffs[$i];
            $diffTextLen = mb_strlen($diffText);

            if (count($patch->getChanges()) == 0 && $diffType != Diff::EQUAL) {
                // A new patch starts here.
                $patch->setStart1($charCount1);
                $patch->setStart2($charCount2);
            }
            if ($diffType == Diff::INSERT) {
                // Insertion.
                $patch->appendChanges($diffs[$i]);
                $patch->setLength2($patch->getLength2() + $diffTextLen);
                $postPatchText = mb_substr($postPatchText, 0, $charCount2) .
                    $diffText . mb_substr($postPatchText, $charCount2);
            } elseif ($diffType == Diff::DELETE) {
                // Deletion.
                $patch->appendChanges($diffs[$i]);
                $patch->setLength1($patch->getLength1() + $diffTextLen);
                $postPatchText = mb_substr($postPatchText, 0, $charCount2) .
                    mb_substr($postPatchText, $charCount2 + $diffTextLen);
            } elseif (
                $diffType == Diff::EQUAL && $diffTextLen <= 2 * $this->getMargin() &&
                count($patch->getChanges()) && $i + 1 != count($diffs)
            ) {
                // Small equality inside a patch.
                $patch->appendChanges($diffs[$i]);
                $patch->setLength1($patch->getLength1() + $diffTextLen);
                $patch->setLength2($patch->getLength2() + $diffTextLen);
            }

            if ($diffType == Diff::EQUAL && $diffTextLen >= 2 * $this->getMargin()) {
                // Time for a new patch.
                if (count($patch->getChanges())) {
                    $this->addContext($patch, $prePatchText);
                    $patches[] = $patch;
                    $patch = new PatchObject();
                    // Unlike Unidiff, our patch lists have a rolling context.
                    // http://code.google.com/p/google-diff-match-patch/wiki/Unidiff
                    // Update prepatch text & pos to reflect the application of the
                    // just completed patch.
                    $prePatchText = $postPatchText;
                    $charCount1 = $charCount2;
                }
            }

            // Update the current character count.
            if ($diffType != Diff::INSERT) {
                $charCount1 += $diffTextLen;
            }
            if ($diffType != Diff::DELETE) {
                $charCount2 += $diffTextLen;
            }
        }

        // Pick up the leftover patch if not empty.
        if (count($patch->getChanges())) {
            $this->addContext($patch, $prePatchText);
            $patches[] = $patch;
        }

        return $patches;
    }
Compute a list of patches to turn text1 into text2.
Use diffs if provided, otherwise compute it ourselves.
There are four ways to call this function, depending on what data is
available to the caller:
Method 1:
a = text1, b = text2
Method 2:
a = diffs
Method 3 (optimal):
a = text1, b = diffs
Method 4 (deprecated, use method 3):
a = text1, b = text2, c = diffs

@param string|array      $a text1 (methods 1,3,4) or Array of diff arrays for text1 to text2 (method 2).
@param string|array|null $b text2 (methods 1,4) or Array of diff arrays for text1 to text2 (method 3)
or null (method 2).
@param array|null        $c Array of diff arrays for text1 to text2 (method 4) or null (methods 1,2,3).

@throws \InvalidArgumentException If unknown call format.
@return PatchObject[] Array of PatchObjects.