michaelorenda / etherpad-client
A framework-agnostic PHP client for Etherpad API with session and permission handling.
Installs: 1
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/michaelorenda/etherpad-client
Requires
- php: >=8.1
- ext-curl: *
- ext-pdo: *
- guzzlehttp/guzzle: ^7.0
Requires (Dev)
- phpunit/phpunit: ^10.0
README
A framework-agnostic PHP library for integrating with the Etherpad collaborative editor API β complete with per-user pad permissions, ready for Laravel 12 or plain PHP 8.1+ projects.
π What Is Etherpad?
Etherpad Lite is an open-source collaborative text editor.
It runs on Node.js and exposes a REST API for creating pads, managing sessions, and synchronizing text in real time.
This library provides a simple PHP interface to that API, and a permissions system for managing user access to pads in your own application.
π§© Features
β
Full Etherpad API support (create, read, update, delete pads)
β
Laravel 12βready via Service Provider
β
Optional Eloquent integration for Laravel projects
β
Simple permissions table (pad_permissions) for managing who can view/edit
β
Framework-agnostic β works with or without Laravel
β
Includes SQL migration + auto table creation helper
β
Secure: uses PDO + prepared statements
β
MIT licensed for open use
βοΈ Installation
1. Install via Composer
Run this command in your project directory:
composer require michaelorenda/etherpad-client
2. Configure Etherpad
In your Etherpad installation (often /opt/etherpad-lite):
cat APIKEY.txt
Copy the key β youβll need it in your .env.
Ensure Etherpad is accessible on a port (e.g. http://localhost:9001).
3. Add Environment Variables
In Laravel, add to your .env file:
ETHERPAD_API_URL=http://localhost:9001
ETHERPAD_API_KEY=your_api_key_here
For plain PHP, youβll just use these values directly in your script.
π§± Database Setup
This package includes a migration file for your permissions table.
Run manually in MySQL:
mysql -u youruser -p yourdatabase < vendor/michaelorenda/etherpad-client/database/migrations/create_pad_permissions_table.sql
Or in Laravel (optional):
You can copy the SQL contents into a migration file under database/migrations/ and run:
php artisan migrate
π§ Understanding the Permissions Model
The table pad_permissions links users to Etherpad pads.
Each record defines whether a user can view or edit that pad.
| Column | Description |
|---|---|
pad_id |
Etherpad pad identifier |
user_id |
Your applicationβs user ID |
can_edit |
1 if user can edit |
can_view |
1 if user can view |
created_at |
Timestamp of assignment |
π§° Laravel 12 Integration
Hereβs how to make it work seamlessly inside Laravel.
Step 1: Create a Service Provider
Create file:
app/Providers/EtherpadServiceProvider.php
<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; use MichaelOrenda\Etherpad\EtherpadClient; use MichaelOrenda\Etherpad\PadPermissionManager; use PDO; class EtherpadServiceProvider extends ServiceProvider { public function register(): void { $this->app->singleton(EtherpadClient::class, function () { return new EtherpadClient( config('services.etherpad.url'), config('services.etherpad.key') ); }); $this->app->singleton(PadPermissionManager::class, function () { $pdo = new PDO( env('DB_CONNECTION') . ':host=' . env('DB_HOST') . ';dbname=' . env('DB_DATABASE'), env('DB_USERNAME'), env('DB_PASSWORD') ); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); return new PadPermissionManager($pdo); }); } }
Register the provider in config/app.php:
'providers' => [ ... App\Providers\EtherpadServiceProvider::class, ],
Then in config/services.php, add:
'etherpad' => [ 'url' => env('ETHERPAD_API_URL'), 'key' => env('ETHERPAD_API_KEY'), ],
Step 2: Create a Controller
app/Http/Controllers/PadController.php
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use MichaelOrenda\Etherpad\EtherpadClient; use MichaelOrenda\Etherpad\PadPermissionManager; class PadController extends Controller { protected $etherpad; protected $permissions; public function __construct(EtherpadClient $etherpad, PadPermissionManager $permissions) { $this->etherpad = $etherpad; $this->permissions = $permissions; } public function open(Request $request, string $padId) { $userId = $request->user()->id; // Check if user has permissions if ($this->permissions->canEdit($padId, $userId)) { $authorID = $this->etherpad->createAuthor($request->user()->name, (string)$userId); $groupID = $this->etherpad->createGroup(); $sessionID = $this->etherpad->createSession($groupID, $authorID, time() + 3600); setcookie('sessionID', $sessionID, time() + 3600, '/', '', false, true); return redirect()->away(config('services.etherpad.url') . "/p/{$padId}"); } if ($this->permissions->canView($padId, $userId)) { $readonlyID = $this->etherpad->getReadOnlyID($padId); return redirect()->away(config('services.etherpad.url') . "/p/{$readonlyID}"); } abort(403, 'Access denied.'); } public function grantEdit(int $userId, string $padId) { $this->permissions->grant($padId, $userId, true, true); return response()->json(['status' => 'granted']); } public function revokeAccess(int $userId, string $padId) { $this->permissions->revoke($padId, $userId); return response()->json(['status' => 'revoked']); } }
Step 3: Add Routes
In routes/web.php:
use App\Http\Controllers\PadController; Route::middleware(['auth'])->group(function () { Route::get('/pads/{padId}', [PadController::class, 'open']); Route::post('/pads/{padId}/grant/{userId}', [PadController::class, 'grantEdit']); Route::delete('/pads/{padId}/revoke/{userId}', [PadController::class, 'revokeAccess']); });
π§ͺ Example for Plain PHP Project
You can also use the library without Laravel.
require 'vendor/autoload.php'; use MichaelOrenda\Etherpad\EtherpadClient; use MichaelOrenda\Etherpad\PadPermissionManager; $etherpad = new EtherpadClient('http://localhost:9001', 'your_api_key_here'); $pdo = new PDO('mysql:host=localhost;dbname=mydb', 'user', 'pass'); $permissions = new PadPermissionManager($pdo); // Create a new pad if needed $groupId = $etherpad->createGroup(); $padId = $etherpad->createGroupPad($groupId, 'demoPad', 'Hello world'); // Grant a user edit rights $permissions->grant($padId, 1, true, true); // Check permissions if ($permissions->canEdit($padId, 1)) { echo "User #1 can edit pad: $padId"; }
π§° Using Permissions
1. Using PDO (Framework-agnostic)
use MichaelOrenda\Etherpad\PadPermissionManager; use PDO; $pdo = new PDO('mysql:host=localhost;dbname=mydb', 'user', 'pass'); $permissions = new PadPermissionManager($pdo); // Grant a user edit permission $permissions->grant($padId, $userId, true, true); // Revoke a user $permissions->revoke($padId, $userId); // Check permissions $permissions->canEdit($padId, $userId); $permissions->canView($padId, $userId);
2. Using Eloquent (Laravel optional)
use MichaelOrenda\Etherpad\PadPermissionEloquent; // Grant a user edit permission PadPermissionEloquent::grant($padId, $userId, true, true); // Revoke a user PadPermissionEloquent::revoke($padId, $userId); // Check permissions PadPermissionEloquent::canEdit($padId, $userId); PadPermissionEloquent::canView($padId, $userId); // List users for a pad $users = PadPermissionEloquent::listUsersForPad($padId); // List pads for a user $pads = PadPermissionEloquent::listPadsForUser($userId);
π‘ Tip: Use PDO if you want a framework-agnostic setup, or Eloquent for Laravel projects.
π Security Tips
- Always protect your API key β never expose it to frontend code.
- Use HTTPS between your PHP app and Etherpad.
- Regularly rotate your Etherpad API key if shared between systems.
- Sanitize pad IDs if you let users create them dynamically.
π§© Common Troubleshooting
| Issue | Cause | Fix |
|---|---|---|
HTTP Request failed |
Etherpad not running or wrong port | Check your Etherpad process and URL |
Invalid API key |
APIKEY.txt mismatch | Verify the contents match your .env |
| Pad opens read-only | Permission table entry missing | Use grant() before accessing pad |
Access denied (403) |
User lacks can_view or can_edit |
Check pad_permissions table |
π§° Directory Overview
src/
βββ EtherpadClient.php
βββ PadPermissionManager.php
βββ Exceptions/
βββ EtherpadException.php
database/
βββ migrations/
βββ create_pad_permissions_table.sql
examples/
βββ open_pad.php
β Summary
- Use PadPermissionManager for PDO-based universal access
- Use PadPermissionEloquent for Laravel ORM integration
- Supports view and edit per-user permissions
- Fully compatible with Laravel 12, or any PHP project
π§Ύ License
MIT License β free for personal and commercial use.
See LICENSE for details.
β€οΈ Credits
Developed by Michael Orenda
Built for developers who love clean, modular PHP integrations.