public function fromText($patchText) { $patches = array(); if (!$patchText) { return $patches; } $lines = explode("\n", $patchText); while (count($lines)) { $line = $lines[0]; if (!preg_match("/^@@ -(\\d+),?(\\d*) \\+(\\d+),?(\\d*) @@\$/", $line, $m)) { throw new \InvalidArgumentException("Invalid patch string: " . $line); } $patch = new PatchObject(); $patch->setStart1($m[1]); if ($m[2] == '') { $patch->setStart1($patch->getStart1() - 1); $patch->setLength1(1); } elseif ($m[2] == '0') { $patch->setLength1(0); } else { $patch->setStart1($patch->getStart1() - 1); $patch->setLength1($m[2]); } $patch->setStart2($m[3]); if ($m[4] == '') { $patch->setStart2($patch->getStart2() - 1); $patch->setLength2(1); } elseif ($m[4] == '0') { $patch->setLength2(0); } else { $patch->setStart2($patch->getStart2() - 1); $patch->setLength2($m[4]); } $patches[] = $patch; array_shift($lines); while (count($lines)) { $line = $lines[0]; if ($line) { $sign = mb_substr($line, 0, 1); } else { $sign = ''; } $text = Utils::unescapeString(mb_substr($line, 1)); switch ($sign) { case '+': // Insertion. $patch->appendChanges(array(Diff::INSERT, $text)); break; case '-': // Deletion. $patch->appendChanges(array(Diff::DELETE, $text)); break; case ' ': // Minor equality. $patch->appendChanges(array(Diff::EQUAL, $text)); break; case '@': // Start of next patch. break 2; case '': // Blank line? Whatever. break; default: // WTF? throw new \UnexpectedValueException("Invalid patch mode: " . $sign . PHP_EOL . $text); } array_shift($lines); } } return $patches; }