Merge a set of patches onto the text. Return a patched text, as well
as a list of true/false values indicating which patches were applied.
public patch_apply ( $patches, $text ) : {Array. |
||
return | {Array. |
public function modify() { // Change name if ($this->new_name) { $explode = explode('/', $this->path); array_pop($explode); $new_path = implode("/", $explode) . "/" . $this->new_name; if (!file_exists($new_path)) { if (rename($this->path, $new_path)) { //unlink($this->path); $this->status = "success"; } else { $this->status = "error"; $this->message = "Could Not Rename"; } } else { $this->status = "error"; $this->message = "Path Already Exists"; } } else { // Change content if ($this->content || $this->patch) { if ($this->content == ' ') { $this->content = ''; // Blank out file } if ($this->patch && !$this->mtime) { $this->status = "error"; $this->message = "mtime parameter not found"; $this->respond(); return; } if (is_file($this->path)) { $serverMTime = filemtime($this->path); $fileContents = file_get_contents($this->path); if ($this->patch && $this->mtime != $serverMTime) { $this->status = "error"; $this->message = "Client is out of sync"; //DEBUG : file_put_contents($this->path.".conflict", "SERVER MTIME :".$serverMTime.", CLIENT MTIME :".$this->mtime); $this->respond(); return; } else { if (strlen(trim($this->patch)) == 0 && !$this->content) { // Do nothing if the patch is empty and there is no content $this->status = "success"; $this->data = '"mtime":' . $serverMTime; $this->respond(); return; } } if ($file = fopen($this->path, 'w')) { if ($this->patch) { $dmp = new diff_match_patch(); $p = $dmp->patch_apply($dmp->patch_fromText($this->patch), $fileContents); $this->content = $p[0]; //DEBUG : file_put_contents($this->path.".orig",$fileContents ); //DEBUG : file_put_contents($this->path.".patch", $this->patch); } if (fwrite($file, $this->content) === false) { $this->status = "error"; $this->message = "could not write to file"; } else { // Unless stat cache is cleared the pre-cached mtime will be // returned instead of new modification time after editing // the file. clearstatcache(); $this->data = '"mtime":' . filemtime($this->path); $this->status = "success"; } fclose($file); } else { $this->status = "error"; $this->message = "Cannot Write to File"; } } else { $this->status = "error"; $this->message = "Not A File"; } } else { $file = fopen($this->path, 'w'); fclose($file); $this->data = '"mtime":' . filemtime($this->path); $this->status = "success"; } } $this->respond(); }
} $query = array('user' => $_SESSION['user'], 'filename' => $_POST['filename']); $shadowTextEntry = getDB()->select($query, 'shadow'); if ($shadowTextEntry == null) { exit(formatJSEND('error', 'Inconsistent sever text filename in synchronizeText: ' . $shadowTextEntry)); } /* First acquire a lock or wait until a lock can be acquired for server * text and shadow. */ $serverTextEntry->lock(); $shadowTextEntry->lock(); $serverText = $serverTextEntry->get_value(); $shadowText = $shadowTextEntry->get_value(); $patchFromClient = $_POST['patch']; /* Patch the shadow and server texts with the edits from the client. */ $dmp = new diff_match_patch(); $patchedServerText = $dmp->patch_apply($dmp->patch_fromText($patchFromClient), $serverText); $serverTextEntry->put_value($patchedServerText[0]); $patchedShadowText = $dmp->patch_apply($dmp->patch_fromText($patchFromClient), $shadowText); /* Make a diff between server text and shadow to get the edits to send * back to the client. */ $patchFromServer = $dmp->patch_toText($dmp->patch_make($patchedShadowText[0], $patchedServerText[0])); /* Apply it to the shadow. */ $patchedShadowText = $dmp->patch_apply($dmp->patch_fromText($patchFromServer), $patchedShadowText[0]); $shadowTextEntry->put_value($patchedShadowText[0]); /* Release locks. */ $serverTextEntry->unlock(); $shadowTextEntry->unlock(); echo formatJSEND('success', $patchFromServer); break; case 'sendHeartbeat': /* Hard coded heartbeat time interval. Beware to keep this value here