Skip to content

Add PHP port of Etherpad Lite Changeset library with pad writer script#136

Draft
Copilot wants to merge 3 commits intomainfrom
copilot/add-changeset-library-integration
Draft

Add PHP port of Etherpad Lite Changeset library with pad writer script#136
Copilot wants to merge 3 commits intomainfrom
copilot/add-changeset-library-integration

Conversation

Copy link

Copilot AI commented Mar 9, 2026

Adds a PHP implementation of the Etherpad Lite Changeset library, enabling clients to construct and apply changesets to write text into pads programmatically.

New classes (src/Changeset/)

  • Op — single changeset operation: keep (=), insert (+), delete (-)
  • AttributePool — attribute interning (key/value pairs ↔ numeric IDs)
  • StringIterator / StringAssembler — low-level string processing primitives
  • OpAssembler / MergingOpAssembler / SmartOpAssembler — Op serialization with progressive merging/optimization
  • Builder — fluent API for incrementally composing changesets
  • Changeset — core static methods: pack, unpack, applyToText, makeSplice, compose, identity, moveOpsToNewPool, etc.

Proof-of-concept script (bin/etherpad-writer.php)

A CLI script demonstrating the Changeset library by connecting to a live Etherpad instance and inserting "Hello world" in the middle of an existing pad's text:

php bin/etherpad-writer.php https://etherpad.example.com my-pad

The script follows the full Etherpad Socket.IO collab protocol:

  1. Fetches the pad page via HTTP to obtain the session cookie
  2. Connects via Socket.IO (ElephantIO) and sends CLIENT_READY
  3. Receives CLIENT_VARS — extracts current text and head revision number
  4. Builds a changeset with Changeset::makeSplice() inserting at the midpoint
  5. Sends USER_CHANGES wrapped in a COLLABROOM message
  6. Awaits ACCEPT_COMMIT confirmation from the server

Usage

use Gared\EtherScan\Changeset\Changeset;

$padText = "\n"; // Etherpad pads always start with a trailing newline

// Build and apply a changeset that inserts text at position 0
$cs = Changeset::makeSplice($padText, 0, 0, 'Hello World');
$padText = Changeset::applyToText($cs, $padText);
// "Hello World\n"

// Chain further edits
$cs2 = Changeset::makeSplice($padText, 6, 5, 'PHP');
$padText = Changeset::applyToText($cs2, $padText);
// "Hello PHP\n"

The Builder class offers a more ergonomic interface for keep/insert/remove sequences, matching the format expected by the Etherpad Socket.IO collab protocol.

Wire protocol compatibility

AttributePool::toJsonable() returns numToAttrib as a \stdClass so that json_encode() always produces a JSON object ({}) rather than a JSON array ([]). This matches what the Etherpad server expects. fromJsonable() transparently accepts both \stdClass and plain arrays.


🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

Co-authored-by: Gared <913630+Gared@users.noreply.github.com>
Copilot AI changed the title [WIP] Add changeset library integration for Etherpad Lite Add PHP port of Etherpad Lite Changeset library Mar 9, 2026
Copilot finished work on behalf of Gared March 9, 2026 14:37
@Gared
Copy link
Owner

Gared commented Mar 9, 2026

@copilot please use the code in this pull request in a proof-of-concept php script to connect to a pad of an etherpad instance and add the text "Hello world" in the middle to the text

…ion for wire protocol

Co-authored-by: Gared <913630+Gared@users.noreply.github.com>
Copy link
Author

Copilot AI commented Mar 9, 2026

@copilot please use the code in this pull request in a proof-of-concept php script to connect to a pad of an etherpad instance and add the text "Hello world" in the middle to the tex...

Added bin/etherpad-writer.php (commit e2a3f86) — a proof-of-concept CLI script that uses the Changeset library to connect to a live Etherpad pad and insert "Hello world" in the middle of its text.

Usage:

php bin/etherpad-writer.php https://etherpad.example.com my-pad

How it works:

  1. Fetches the pad page to get a session cookie
  2. Connects via Socket.IO (ElephantIO) and sends CLIENT_READY
  3. Waits for CLIENT_VARS — extracts the current text (initialAttributedText.text) and revision number (rev)
  4. Computes the midpoint of the text and builds a changeset with Changeset::makeSplice()
  5. Sends USER_CHANGES wrapped in a COLLABROOM message with baseRev and apool
  6. Waits for ACCEPT_COMMIT confirmation

Also fixed AttributePool::toJsonable() so numToAttrib serializes as a JSON object {} (not []), which is required by the Etherpad wire protocol.

Copilot AI changed the title Add PHP port of Etherpad Lite Changeset library Add PHP port of Etherpad Lite Changeset library with pad writer script Mar 9, 2026
Copilot finished work on behalf of Gared March 9, 2026 22:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants