├── .gitignore ├── tools ├── testcontainer │ ├── APIKEY.txt │ ├── run-container.sh │ └── Dockerfile ├── templates │ ├── method.php │ └── client.php └── generate.php ├── phpunit.xml ├── Makefile ├── CHANGELOG ├── composer.json ├── test └── FullStack │ ├── AuthorTest.php │ ├── PadTest.php │ └── GroupsTest.php ├── README.md ├── api-spec.json ├── etherpad-lite-client.php └── EtherpadLite └── Client.php /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | vendor 3 | composer.lock 4 | 5 | -------------------------------------------------------------------------------- /tools/testcontainer/APIKEY.txt: -------------------------------------------------------------------------------- 1 | dcf118bfc58cc69cdf3ae870071f97149924f5f5a9a4a552fd2921b40830aaae 2 | -------------------------------------------------------------------------------- /tools/testcontainer/run-container.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | sudo docker run --detach --publish=9001:9001 $1 3 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | test/FullStack 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | test: 2 | ./vendor/bin/phpunit --colors --verbose 3 | 4 | dev-deps: 5 | composer install --dev 6 | 7 | client: 8 | php ./tools/generate.php > ./EtherpadLite/Client.php 9 | 10 | .PHONY: all test clean 11 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | Tag: api-v1 2 | * All v1 methods implemented. 3 | * Start of changelog. 4 | 5 | Tag: api-v1.1 (2012-11-17) 6 | * Added v1.1 methods: 7 | - listAllGroups 8 | - getAuthorName 9 | - padUsers 10 | - sendClientsMessage 11 | 12 | Tag: api-v.1.2.11 (2015-03-22) 13 | * Autogeneration of client methods 14 | * Test Suite 15 | 16 | 2015-10-07: 17 | * Converts boolean arguments to strings 18 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tomnomnom/etherpad-lite-client", 3 | "description": "Etherpad Lite client for PHP", 4 | "homepage": "https://github.com/TomNomNom/etherpad-lite-client/", 5 | "license": "Apache", 6 | 7 | "require-dev": { 8 | "phpunit/phpunit": "3.7.*" 9 | }, 10 | "autoload": { 11 | "psr-4": {"EtherpadLite\\": "EtherpadLite/"} 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tools/testcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu 2 | 3 | RUN apt-get update 4 | RUN apt-get install -y gzip git curl python libssl-dev pkg-config build-essential 5 | RUN apt-get install -y nodejs npm 6 | RUN ln -s /usr/bin/nodejs /usr/bin/node 7 | RUN git clone git://github.com/ether/etherpad-lite.git 8 | 9 | COPY APIKEY.txt /etherpad-lite/ 10 | 11 | EXPOSE 9001 12 | 13 | ENTRYPOINT ["/etherpad-lite/bin/run.sh", "--root"] 14 | -------------------------------------------------------------------------------- /test/FullStack/AuthorTest.php: -------------------------------------------------------------------------------- 1 | newClient(); 12 | 13 | $a = $client->createAuthor('Bob'); 14 | $this->assertTrue(is_string($a->authorID)); 15 | 16 | $n = $client->getAuthorName($a->authorID); 17 | $this->assertEquals("Bob", $n); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /tools/templates/method.php: -------------------------------------------------------------------------------- 1 | {$httpMethod}(\"{$name}\", \$params);\n"; 30 | echo " }\n\n"; 31 | ?> 32 | -------------------------------------------------------------------------------- /test/FullStack/PadTest.php: -------------------------------------------------------------------------------- 1 | newClient(); 12 | 13 | $group = $client->createGroup(); 14 | $this->assertTrue(is_string($group->groupID)); 15 | 16 | $pad = $client->createGroupPad($group->groupID, "PadName", "Default Text"); 17 | $this->assertTrue(is_string($pad->padID)); 18 | 19 | $text = $client->getText($pad->padID); 20 | $this->assertEquals("Default Text", trim($text->text)); 21 | 22 | $set = $client->setText($pad->padID, "The new text"); 23 | $this->assertNull($set); 24 | 25 | $text = $client->getText($pad->padID); 26 | $this->assertEquals("The new text", trim($text->text)); 27 | 28 | $del = $client->deletePad($pad->padID); 29 | $this->assertNull($del); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /tools/generate.php: -------------------------------------------------------------------------------- 1 | methods as $name => $args){ 10 | 11 | // Slightly hacky, but should cover all bases 12 | $httpMethod = "post"; 13 | if (hasPrefix($name, "get") || 14 | hasPrefix($name, "list") || 15 | hasPrefix($name, "pad") || 16 | hasPrefix($name, "is")){ 17 | $httpMethod = "get"; 18 | } 19 | 20 | $methods[] = array( 21 | "name" => $name, 22 | "args" => $args, 23 | "httpMethod" => $httpMethod, 24 | ); 25 | } 26 | 27 | echo " $spec->version, 32 | "methods" => $methods, 33 | )); 34 | 35 | function render($template, $data){ 36 | extract($data); 37 | include($template); 38 | } 39 | 40 | function hasPrefix($candidate, $prefix){ 41 | if (strpos($candidate, $prefix) === 0){ 42 | return true; 43 | } 44 | return false; 45 | } 46 | -------------------------------------------------------------------------------- /test/FullStack/GroupsTest.php: -------------------------------------------------------------------------------- 1 | newClient(); 12 | 13 | // Create a group 14 | $group = $client->createGroup(); 15 | $this->assertTrue(is_string($group->groupID)); 16 | 17 | // Delete it 18 | $r = $client->deleteGroup($group->groupID); 19 | $this->assertNull($r); 20 | 21 | // Try to delete it again 22 | try { 23 | $client->deleteGroup($group->groupID); 24 | $this->fail("deleteGroup should fail if group does not exist"); 25 | } catch (\InvalidArgumentException $e){ 26 | $this->assertTrue(true); // Just to keep the counter up ;) 27 | } 28 | } 29 | 30 | public function testListGroups(){ 31 | $client = $this->newClient(); 32 | 33 | // Create a couple of groups 34 | $one = $client->createGroup(); 35 | $two = $client->createGroup(); 36 | 37 | $groups = $client->listAllGroups(); 38 | $this->assertContains($one->groupID, $groups->groupIDs); 39 | $this->assertContains($two->groupID, $groups->groupIDs); 40 | 41 | // Clean up 42 | $client->deleteGroup($one->groupID); 43 | $client->deleteGroup($two->groupID); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PHP Etherpad Lite Client 2 | This PHP Etherpad Lite class allows you to easily interact with Etherpad Lite API with PHP. 3 | Etherpad Lite is a collaborative editor provided by the Etherpad Foundation (http://etherpad.org) 4 | 5 | ## Basic Usage 6 | 7 | Install from packagist: 8 | 9 | ``` 10 | composer require tomnomnom/etherpad-lite-client 11 | ``` 12 | 13 | A legacy `etherpad-lite-client.php` file is included for people who are unwilling/unable to switch to the new 14 | namespaced version, but it is deprecated and will be removed in future versions. 15 | 16 | ```php 17 | getRevisionsCount('testPad'); 21 | $revisionCount = $revisionCount->revisions; 22 | echo "Pad has $revisionCount revisions"; 23 | ``` 24 | 25 | # Running The Tests 26 | The full-stack tests can be run by running `make test`. 27 | 28 | The test suite makes the following assumptions: 29 | 30 | * A copy of Etherpad is running at http://localhost:9001 31 | * The data in the running instance of Etherpad can be destroyed 32 | * The APIKey for the running instance is 'dcf118bfc58cc69cdf3ae870071f97149924f5f5a9a4a552fd2921b40830aaae' 33 | * PHPUnit has been installed with [Composer](https://getcomposer.org/) (run `make dev-deps`) 34 | 35 | A Dockerfile is provided in `tools/testcontainer` to ease setup of a test instance. 36 | 37 | # License 38 | 39 | Apache License 40 | 41 | # Other Stuff 42 | 43 | The Etherpad Foundation also provides a jQuery plugin for Etherpad Lite. 44 | This can be found at http://etherpad.org/2011/08/14/etherpad-lite-jquery-plugin/ 45 | 46 | -------------------------------------------------------------------------------- /api-spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.2.11", 3 | "methods": 4 | { "createGroup" : [] 5 | , "createGroupIfNotExistsFor" : ["groupMapper"] 6 | , "deleteGroup" : ["groupID"] 7 | , "listPads" : ["groupID"] 8 | , "listAllPads" : [] 9 | , "createDiffHTML" : ["padID", "startRev", "endRev"] 10 | , "createPad" : ["padID", "[text]"] 11 | , "createGroupPad" : ["groupID", "padName", "[text]"] 12 | , "createAuthor" : ["[name]"] 13 | , "createAuthorIfNotExistsFor": ["authorMapper" , "[name]"] 14 | , "listPadsOfAuthor" : ["authorID"] 15 | , "createSession" : ["groupID", "authorID", "validUntil"] 16 | , "deleteSession" : ["sessionID"] 17 | , "getSessionInfo" : ["sessionID"] 18 | , "listSessionsOfGroup" : ["groupID"] 19 | , "listSessionsOfAuthor" : ["authorID"] 20 | , "getText" : ["padID", "[rev]"] 21 | , "setText" : ["padID", "text"] 22 | , "getHTML" : ["padID", "[rev]"] 23 | , "setHTML" : ["padID", "html"] 24 | , "getAttributePool" : ["padID"] 25 | , "getRevisionsCount" : ["padID"] 26 | , "getSavedRevisionsCount" : ["padID"] 27 | , "listSavedRevisions" : ["padID"] 28 | , "saveRevision" : ["padID", "rev"] 29 | , "getRevisionChangeset" : ["padID", "[rev]"] 30 | , "getLastEdited" : ["padID"] 31 | , "deletePad" : ["padID"] 32 | , "copyPad" : ["sourceID", "destinationID", "[force]"] 33 | , "movePad" : ["sourceID", "destinationID", "[force]"] 34 | , "getReadOnlyID" : ["padID"] 35 | , "getPadID" : ["roID"] 36 | , "setPublicStatus" : ["padID", "publicStatus"] 37 | , "getPublicStatus" : ["padID"] 38 | , "setPassword" : ["padID", "password"] 39 | , "isPasswordProtected" : ["padID"] 40 | , "listAuthorsOfPad" : ["padID"] 41 | , "padUsersCount" : ["padID"] 42 | , "getAuthorName" : ["authorID"] 43 | , "padUsers" : ["padID"] 44 | , "sendClientsMessage" : ["padID", "msg"] 45 | , "listAllGroups" : [] 46 | , "checkToken" : [] 47 | , "getChatHistory" : ["padID", "[start]", "[end]"] 48 | , "getChatHead" : ["padID"] 49 | , "restoreRevision" : ["padID", "rev"] 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /tools/templates/client.php: -------------------------------------------------------------------------------- 1 | // The following code is automatically generated by ./tools/generate.php 2 | // please edit the files in ./tools/templates/ instead of editing this 3 | // file directly. 4 | 5 | namespace EtherpadLite; 6 | 7 | class Client { 8 | 9 | const API_VERSION = ''; 10 | 11 | const CODE_OK = 0; 12 | const CODE_INVALID_PARAMETERS = 1; 13 | const CODE_INTERNAL_ERROR = 2; 14 | const CODE_INVALID_FUNCTION = 3; 15 | const CODE_INVALID_API_KEY = 4; 16 | 17 | protected $apiKey = ""; 18 | protected $baseUrl = "http://localhost:9001/api"; 19 | 20 | public function __construct($apiKey, $baseUrl = null){ 21 | if (strlen($apiKey) < 1){ 22 | throw new \InvalidArgumentException("[{$apiKey}] is not a valid API key"); 23 | } 24 | $this->apiKey = $apiKey; 25 | 26 | if (isset($baseUrl)){ 27 | $this->baseUrl = $baseUrl; 28 | } 29 | if (!filter_var($this->baseUrl, FILTER_VALIDATE_URL)){ 30 | throw new \InvalidArgumentException("[{$this->baseUrl}] is not a valid URL"); 31 | } 32 | } 33 | 34 | protected function get($function, array $arguments = array()){ 35 | return $this->call($function, $arguments, 'GET'); 36 | } 37 | 38 | protected function post($function, array $arguments = array()){ 39 | return $this->call($function, $arguments, 'POST'); 40 | } 41 | 42 | protected function convertBools($candidate){ 43 | if (is_bool($candidate)){ 44 | return $candidate? "true" : "false"; 45 | } 46 | return $candidate; 47 | } 48 | 49 | protected function call($function, array $arguments = array(), $method = 'GET'){ 50 | $arguments['apikey'] = $this->apiKey; 51 | $arguments = array_map(array($this, 'convertBools'), $arguments); 52 | $arguments = http_build_query($arguments, '', '&'); 53 | $url = $this->baseUrl."/".self::API_VERSION."/".$function; 54 | if ($method !== 'POST'){ 55 | $url .= "?".$arguments; 56 | } 57 | // use curl of it's available 58 | if (function_exists('curl_init')){ 59 | $c = curl_init($url); 60 | curl_setopt($c, CURLOPT_RETURNTRANSFER, true); 61 | curl_setopt($c, CURLOPT_TIMEOUT, 20); 62 | if ($method === 'POST'){ 63 | curl_setopt($c, CURLOPT_POST, true); 64 | curl_setopt($c, CURLOPT_POSTFIELDS, $arguments); 65 | } 66 | $result = curl_exec($c); 67 | curl_close($c); 68 | // fallback to plain php 69 | } else { 70 | $params = array('http' => array('method' => $method, 'ignore_errors' => true, 'header' => 'Content-Type:application/x-www-form-urlencoded')); 71 | if ($method === 'POST'){ 72 | $params['http']['content'] = $arguments; 73 | } 74 | $context = stream_context_create($params); 75 | $fp = fopen($url, 'rb', false, $context); 76 | $result = $fp ? stream_get_contents($fp) : null; 77 | } 78 | 79 | if(!$result){ 80 | throw new \UnexpectedValueException("Empty or No Response from the server"); 81 | } 82 | 83 | $result = json_decode($result); 84 | if ($result === null){ 85 | throw new \UnexpectedValueException("JSON response could not be decoded"); 86 | } 87 | return $this->handleResult($result); 88 | } 89 | 90 | protected function handleResult($result){ 91 | if (!isset($result->code)){ 92 | throw new \RuntimeException("API response has no code"); 93 | } 94 | if (!isset($result->message)){ 95 | throw new \RuntimeException("API response has no message"); 96 | } 97 | if (!isset($result->data)){ 98 | $result->data = null; 99 | } 100 | 101 | switch ($result->code){ 102 | case self::CODE_OK: 103 | return $result->data; 104 | case self::CODE_INVALID_PARAMETERS: 105 | case self::CODE_INVALID_API_KEY: 106 | throw new \InvalidArgumentException($result->message); 107 | case self::CODE_INTERNAL_ERROR: 108 | throw new \RuntimeException($result->message); 109 | case self::CODE_INVALID_FUNCTION: 110 | throw new \BadFunctionCallException($result->message); 111 | default: 112 | throw new \RuntimeException("An unexpected error occurred whilst handling the response"); 113 | } 114 | } 115 | 116 | 121 | 122 | } 123 | 124 | -------------------------------------------------------------------------------- /etherpad-lite-client.php: -------------------------------------------------------------------------------- 1 | apiKey = $apiKey; 24 | 25 | if (isset($baseUrl)){ 26 | $this->baseUrl = $baseUrl; 27 | } 28 | if (!filter_var($this->baseUrl, FILTER_VALIDATE_URL)){ 29 | throw new InvalidArgumentException("[{$this->baseUrl}] is not a valid URL"); 30 | } 31 | } 32 | 33 | protected function get($function, array $arguments = array()){ 34 | return $this->call($function, $arguments, 'GET'); 35 | } 36 | 37 | protected function post($function, array $arguments = array()){ 38 | return $this->call($function, $arguments, 'POST'); 39 | } 40 | 41 | protected function convertBools($candidate){ 42 | if (is_bool($candidate)){ 43 | return $candidate? "true" : "false"; 44 | } 45 | return $candidate; 46 | } 47 | 48 | protected function call($function, array $arguments = array(), $method = 'GET'){ 49 | $arguments['apikey'] = $this->apiKey; 50 | $arguments = array_map(array($this, 'convertBools'), $arguments); 51 | $arguments = http_build_query($arguments, '', '&'); 52 | $url = $this->baseUrl."/".self::API_VERSION."/".$function; 53 | if ($method !== 'POST'){ 54 | $url .= "?".$arguments; 55 | } 56 | // use curl of it's available 57 | if (function_exists('curl_init')){ 58 | $c = curl_init($url); 59 | curl_setopt($c, CURLOPT_RETURNTRANSFER, true); 60 | curl_setopt($c, CURLOPT_TIMEOUT, 20); 61 | if ($method === 'POST'){ 62 | curl_setopt($c, CURLOPT_POST, true); 63 | curl_setopt($c, CURLOPT_POSTFIELDS, $arguments); 64 | } 65 | $result = curl_exec($c); 66 | curl_close($c); 67 | // fallback to plain php 68 | } else { 69 | $params = array('http' => array('method' => $method, 'ignore_errors' => true, 'header' => 'Content-Type:application/x-www-form-urlencoded')); 70 | if ($method === 'POST'){ 71 | $params['http']['content'] = $arguments; 72 | } 73 | $context = stream_context_create($params); 74 | $fp = fopen($url, 'rb', false, $context); 75 | $result = $fp ? stream_get_contents($fp) : null; 76 | } 77 | 78 | if(!$result){ 79 | throw new UnexpectedValueException("Empty or No Response from the server"); 80 | } 81 | 82 | $result = json_decode($result); 83 | if ($result === null){ 84 | throw new UnexpectedValueException("JSON response could not be decoded"); 85 | } 86 | return $this->handleResult($result); 87 | } 88 | 89 | protected function handleResult($result){ 90 | if (!isset($result->code)){ 91 | throw new RuntimeException("API response has no code"); 92 | } 93 | if (!isset($result->message)){ 94 | throw new RuntimeException("API response has no message"); 95 | } 96 | if (!isset($result->data)){ 97 | $result->data = null; 98 | } 99 | 100 | switch ($result->code){ 101 | case self::CODE_OK: 102 | return $result->data; 103 | case self::CODE_INVALID_PARAMETERS: 104 | case self::CODE_INVALID_API_KEY: 105 | throw new InvalidArgumentException($result->message); 106 | case self::CODE_INTERNAL_ERROR: 107 | throw new RuntimeException($result->message); 108 | case self::CODE_INVALID_FUNCTION: 109 | throw new BadFunctionCallException($result->message); 110 | default: 111 | throw new RuntimeException("An unexpected error occurred whilst handling the response"); 112 | } 113 | } 114 | 115 | // createGroup 116 | public function createGroup(){ 117 | $params = array(); 118 | 119 | 120 | return $this->post("createGroup", $params); 121 | } 122 | 123 | // createGroupIfNotExistsFor 124 | public function createGroupIfNotExistsFor($groupMapper){ 125 | $params = array(); 126 | 127 | $params['groupMapper'] = $groupMapper; 128 | 129 | return $this->post("createGroupIfNotExistsFor", $params); 130 | } 131 | 132 | // deleteGroup 133 | public function deleteGroup($groupID){ 134 | $params = array(); 135 | 136 | $params['groupID'] = $groupID; 137 | 138 | return $this->post("deleteGroup", $params); 139 | } 140 | 141 | // listPads 142 | public function listPads($groupID){ 143 | $params = array(); 144 | 145 | $params['groupID'] = $groupID; 146 | 147 | return $this->get("listPads", $params); 148 | } 149 | 150 | // listAllPads 151 | public function listAllPads(){ 152 | $params = array(); 153 | 154 | 155 | return $this->get("listAllPads", $params); 156 | } 157 | 158 | // createDiffHTML 159 | public function createDiffHTML($padID, $startRev, $endRev){ 160 | $params = array(); 161 | 162 | $params['padID'] = $padID; 163 | $params['startRev'] = $startRev; 164 | $params['endRev'] = $endRev; 165 | 166 | return $this->post("createDiffHTML", $params); 167 | } 168 | 169 | // createPad 170 | public function createPad($padID, $text = null){ 171 | $params = array(); 172 | 173 | $params['padID'] = $padID; 174 | if (isset($text)){ 175 | $params['text'] = $text; 176 | } 177 | 178 | return $this->post("createPad", $params); 179 | } 180 | 181 | // createGroupPad 182 | public function createGroupPad($groupID, $padName, $text = null){ 183 | $params = array(); 184 | 185 | $params['groupID'] = $groupID; 186 | $params['padName'] = $padName; 187 | if (isset($text)){ 188 | $params['text'] = $text; 189 | } 190 | 191 | return $this->post("createGroupPad", $params); 192 | } 193 | 194 | // createAuthor 195 | public function createAuthor($name = null){ 196 | $params = array(); 197 | 198 | if (isset($name)){ 199 | $params['name'] = $name; 200 | } 201 | 202 | return $this->post("createAuthor", $params); 203 | } 204 | 205 | // createAuthorIfNotExistsFor 206 | public function createAuthorIfNotExistsFor($authorMapper, $name = null){ 207 | $params = array(); 208 | 209 | $params['authorMapper'] = $authorMapper; 210 | if (isset($name)){ 211 | $params['name'] = $name; 212 | } 213 | 214 | return $this->post("createAuthorIfNotExistsFor", $params); 215 | } 216 | 217 | // listPadsOfAuthor 218 | public function listPadsOfAuthor($authorID){ 219 | $params = array(); 220 | 221 | $params['authorID'] = $authorID; 222 | 223 | return $this->get("listPadsOfAuthor", $params); 224 | } 225 | 226 | // createSession 227 | public function createSession($groupID, $authorID, $validUntil){ 228 | $params = array(); 229 | 230 | $params['groupID'] = $groupID; 231 | $params['authorID'] = $authorID; 232 | $params['validUntil'] = $validUntil; 233 | 234 | return $this->post("createSession", $params); 235 | } 236 | 237 | // deleteSession 238 | public function deleteSession($sessionID){ 239 | $params = array(); 240 | 241 | $params['sessionID'] = $sessionID; 242 | 243 | return $this->post("deleteSession", $params); 244 | } 245 | 246 | // getSessionInfo 247 | public function getSessionInfo($sessionID){ 248 | $params = array(); 249 | 250 | $params['sessionID'] = $sessionID; 251 | 252 | return $this->get("getSessionInfo", $params); 253 | } 254 | 255 | // listSessionsOfGroup 256 | public function listSessionsOfGroup($groupID){ 257 | $params = array(); 258 | 259 | $params['groupID'] = $groupID; 260 | 261 | return $this->get("listSessionsOfGroup", $params); 262 | } 263 | 264 | // listSessionsOfAuthor 265 | public function listSessionsOfAuthor($authorID){ 266 | $params = array(); 267 | 268 | $params['authorID'] = $authorID; 269 | 270 | return $this->get("listSessionsOfAuthor", $params); 271 | } 272 | 273 | // getText 274 | public function getText($padID, $rev = null){ 275 | $params = array(); 276 | 277 | $params['padID'] = $padID; 278 | if (isset($rev)){ 279 | $params['rev'] = $rev; 280 | } 281 | 282 | return $this->get("getText", $params); 283 | } 284 | 285 | // setText 286 | public function setText($padID, $text){ 287 | $params = array(); 288 | 289 | $params['padID'] = $padID; 290 | $params['text'] = $text; 291 | 292 | return $this->post("setText", $params); 293 | } 294 | 295 | // getHTML 296 | public function getHTML($padID, $rev = null){ 297 | $params = array(); 298 | 299 | $params['padID'] = $padID; 300 | if (isset($rev)){ 301 | $params['rev'] = $rev; 302 | } 303 | 304 | return $this->get("getHTML", $params); 305 | } 306 | 307 | // setHTML 308 | public function setHTML($padID, $html){ 309 | $params = array(); 310 | 311 | $params['padID'] = $padID; 312 | $params['html'] = $html; 313 | 314 | return $this->post("setHTML", $params); 315 | } 316 | 317 | // getAttributePool 318 | public function getAttributePool($padID){ 319 | $params = array(); 320 | 321 | $params['padID'] = $padID; 322 | 323 | return $this->get("getAttributePool", $params); 324 | } 325 | 326 | // getRevisionsCount 327 | public function getRevisionsCount($padID){ 328 | $params = array(); 329 | 330 | $params['padID'] = $padID; 331 | 332 | return $this->get("getRevisionsCount", $params); 333 | } 334 | 335 | // getSavedRevisionsCount 336 | public function getSavedRevisionsCount($padID){ 337 | $params = array(); 338 | 339 | $params['padID'] = $padID; 340 | 341 | return $this->get("getSavedRevisionsCount", $params); 342 | } 343 | 344 | // listSavedRevisions 345 | public function listSavedRevisions($padID){ 346 | $params = array(); 347 | 348 | $params['padID'] = $padID; 349 | 350 | return $this->get("listSavedRevisions", $params); 351 | } 352 | 353 | // saveRevision 354 | public function saveRevision($padID, $rev){ 355 | $params = array(); 356 | 357 | $params['padID'] = $padID; 358 | $params['rev'] = $rev; 359 | 360 | return $this->post("saveRevision", $params); 361 | } 362 | 363 | // getRevisionChangeset 364 | public function getRevisionChangeset($padID, $rev = null){ 365 | $params = array(); 366 | 367 | $params['padID'] = $padID; 368 | if (isset($rev)){ 369 | $params['rev'] = $rev; 370 | } 371 | 372 | return $this->get("getRevisionChangeset", $params); 373 | } 374 | 375 | // getLastEdited 376 | public function getLastEdited($padID){ 377 | $params = array(); 378 | 379 | $params['padID'] = $padID; 380 | 381 | return $this->get("getLastEdited", $params); 382 | } 383 | 384 | // deletePad 385 | public function deletePad($padID){ 386 | $params = array(); 387 | 388 | $params['padID'] = $padID; 389 | 390 | return $this->post("deletePad", $params); 391 | } 392 | 393 | // copyPad 394 | public function copyPad($sourceID, $destinationID, $force = null){ 395 | $params = array(); 396 | 397 | $params['sourceID'] = $sourceID; 398 | $params['destinationID'] = $destinationID; 399 | if (isset($force)){ 400 | $params['force'] = $force; 401 | } 402 | 403 | return $this->post("copyPad", $params); 404 | } 405 | 406 | // movePad 407 | public function movePad($sourceID, $destinationID, $force = null){ 408 | $params = array(); 409 | 410 | $params['sourceID'] = $sourceID; 411 | $params['destinationID'] = $destinationID; 412 | if (isset($force)){ 413 | $params['force'] = $force; 414 | } 415 | 416 | return $this->post("movePad", $params); 417 | } 418 | 419 | // getReadOnlyID 420 | public function getReadOnlyID($padID){ 421 | $params = array(); 422 | 423 | $params['padID'] = $padID; 424 | 425 | return $this->get("getReadOnlyID", $params); 426 | } 427 | 428 | // getPadID 429 | public function getPadID($roID){ 430 | $params = array(); 431 | 432 | $params['roID'] = $roID; 433 | 434 | return $this->get("getPadID", $params); 435 | } 436 | 437 | // setPublicStatus 438 | public function setPublicStatus($padID, $publicStatus){ 439 | $params = array(); 440 | 441 | $params['padID'] = $padID; 442 | $params['publicStatus'] = $publicStatus; 443 | 444 | return $this->post("setPublicStatus", $params); 445 | } 446 | 447 | // getPublicStatus 448 | public function getPublicStatus($padID){ 449 | $params = array(); 450 | 451 | $params['padID'] = $padID; 452 | 453 | return $this->get("getPublicStatus", $params); 454 | } 455 | 456 | // setPassword 457 | public function setPassword($padID, $password){ 458 | $params = array(); 459 | 460 | $params['padID'] = $padID; 461 | $params['password'] = $password; 462 | 463 | return $this->post("setPassword", $params); 464 | } 465 | 466 | // isPasswordProtected 467 | public function isPasswordProtected($padID){ 468 | $params = array(); 469 | 470 | $params['padID'] = $padID; 471 | 472 | return $this->get("isPasswordProtected", $params); 473 | } 474 | 475 | // listAuthorsOfPad 476 | public function listAuthorsOfPad($padID){ 477 | $params = array(); 478 | 479 | $params['padID'] = $padID; 480 | 481 | return $this->get("listAuthorsOfPad", $params); 482 | } 483 | 484 | // padUsersCount 485 | public function padUsersCount($padID){ 486 | $params = array(); 487 | 488 | $params['padID'] = $padID; 489 | 490 | return $this->get("padUsersCount", $params); 491 | } 492 | 493 | // getAuthorName 494 | public function getAuthorName($authorID){ 495 | $params = array(); 496 | 497 | $params['authorID'] = $authorID; 498 | 499 | return $this->get("getAuthorName", $params); 500 | } 501 | 502 | // padUsers 503 | public function padUsers($padID){ 504 | $params = array(); 505 | 506 | $params['padID'] = $padID; 507 | 508 | return $this->get("padUsers", $params); 509 | } 510 | 511 | // sendClientsMessage 512 | public function sendClientsMessage($padID, $msg){ 513 | $params = array(); 514 | 515 | $params['padID'] = $padID; 516 | $params['msg'] = $msg; 517 | 518 | return $this->post("sendClientsMessage", $params); 519 | } 520 | 521 | // listAllGroups 522 | public function listAllGroups(){ 523 | $params = array(); 524 | 525 | 526 | return $this->get("listAllGroups", $params); 527 | } 528 | 529 | // checkToken 530 | public function checkToken(){ 531 | $params = array(); 532 | 533 | 534 | return $this->post("checkToken", $params); 535 | } 536 | 537 | // getChatHistory 538 | public function getChatHistory($padID, $start = null, $end = null){ 539 | $params = array(); 540 | 541 | $params['padID'] = $padID; 542 | if (isset($start)){ 543 | $params['start'] = $start; 544 | } 545 | if (isset($end)){ 546 | $params['end'] = $end; 547 | } 548 | 549 | return $this->get("getChatHistory", $params); 550 | } 551 | 552 | // getChatHead 553 | public function getChatHead($padID){ 554 | $params = array(); 555 | 556 | $params['padID'] = $padID; 557 | 558 | return $this->get("getChatHead", $params); 559 | } 560 | 561 | // restoreRevision 562 | public function restoreRevision($padID, $rev){ 563 | $params = array(); 564 | 565 | $params['padID'] = $padID; 566 | $params['rev'] = $rev; 567 | 568 | return $this->post("restoreRevision", $params); 569 | } 570 | 571 | 572 | } 573 | 574 | -------------------------------------------------------------------------------- /EtherpadLite/Client.php: -------------------------------------------------------------------------------- 1 | apiKey = $apiKey; 26 | 27 | if (isset($baseUrl)){ 28 | $this->baseUrl = $baseUrl; 29 | } 30 | if (!filter_var($this->baseUrl, FILTER_VALIDATE_URL)){ 31 | throw new \InvalidArgumentException("[{$this->baseUrl}] is not a valid URL"); 32 | } 33 | } 34 | 35 | protected function get($function, array $arguments = array()){ 36 | return $this->call($function, $arguments, 'GET'); 37 | } 38 | 39 | protected function post($function, array $arguments = array()){ 40 | return $this->call($function, $arguments, 'POST'); 41 | } 42 | 43 | protected function convertBools($candidate){ 44 | if (is_bool($candidate)){ 45 | return $candidate? "true" : "false"; 46 | } 47 | return $candidate; 48 | } 49 | 50 | protected function call($function, array $arguments = array(), $method = 'GET'){ 51 | $arguments['apikey'] = $this->apiKey; 52 | $arguments = array_map(array($this, 'convertBools'), $arguments); 53 | $arguments = http_build_query($arguments, '', '&'); 54 | $url = $this->baseUrl."/".self::API_VERSION."/".$function; 55 | if ($method !== 'POST'){ 56 | $url .= "?".$arguments; 57 | } 58 | // use curl of it's available 59 | if (function_exists('curl_init')){ 60 | $c = curl_init($url); 61 | curl_setopt($c, CURLOPT_RETURNTRANSFER, true); 62 | curl_setopt($c, CURLOPT_TIMEOUT, 20); 63 | if ($method === 'POST'){ 64 | curl_setopt($c, CURLOPT_POST, true); 65 | curl_setopt($c, CURLOPT_POSTFIELDS, $arguments); 66 | } 67 | $result = curl_exec($c); 68 | curl_close($c); 69 | // fallback to plain php 70 | } else { 71 | $params = array('http' => array('method' => $method, 'ignore_errors' => true, 'header' => 'Content-Type:application/x-www-form-urlencoded')); 72 | if ($method === 'POST'){ 73 | $params['http']['content'] = $arguments; 74 | } 75 | $context = stream_context_create($params); 76 | $fp = fopen($url, 'rb', false, $context); 77 | $result = $fp ? stream_get_contents($fp) : null; 78 | } 79 | 80 | if(!$result){ 81 | throw new \UnexpectedValueException("Empty or No Response from the server"); 82 | } 83 | 84 | $result = json_decode($result); 85 | if ($result === null){ 86 | throw new \UnexpectedValueException("JSON response could not be decoded"); 87 | } 88 | return $this->handleResult($result); 89 | } 90 | 91 | protected function handleResult($result){ 92 | if (!isset($result->code)){ 93 | throw new \RuntimeException("API response has no code"); 94 | } 95 | if (!isset($result->message)){ 96 | throw new \RuntimeException("API response has no message"); 97 | } 98 | if (!isset($result->data)){ 99 | $result->data = null; 100 | } 101 | 102 | switch ($result->code){ 103 | case self::CODE_OK: 104 | return $result->data; 105 | case self::CODE_INVALID_PARAMETERS: 106 | case self::CODE_INVALID_API_KEY: 107 | throw new \InvalidArgumentException($result->message); 108 | case self::CODE_INTERNAL_ERROR: 109 | throw new \RuntimeException($result->message); 110 | case self::CODE_INVALID_FUNCTION: 111 | throw new \BadFunctionCallException($result->message); 112 | default: 113 | throw new \RuntimeException("An unexpected error occurred whilst handling the response"); 114 | } 115 | } 116 | 117 | // createGroup 118 | public function createGroup(){ 119 | $params = array(); 120 | 121 | 122 | return $this->post("createGroup", $params); 123 | } 124 | 125 | // createGroupIfNotExistsFor 126 | public function createGroupIfNotExistsFor($groupMapper){ 127 | $params = array(); 128 | 129 | $params['groupMapper'] = $groupMapper; 130 | 131 | return $this->post("createGroupIfNotExistsFor", $params); 132 | } 133 | 134 | // deleteGroup 135 | public function deleteGroup($groupID){ 136 | $params = array(); 137 | 138 | $params['groupID'] = $groupID; 139 | 140 | return $this->post("deleteGroup", $params); 141 | } 142 | 143 | // listPads 144 | public function listPads($groupID){ 145 | $params = array(); 146 | 147 | $params['groupID'] = $groupID; 148 | 149 | return $this->get("listPads", $params); 150 | } 151 | 152 | // listAllPads 153 | public function listAllPads(){ 154 | $params = array(); 155 | 156 | 157 | return $this->get("listAllPads", $params); 158 | } 159 | 160 | // createDiffHTML 161 | public function createDiffHTML($padID, $startRev, $endRev){ 162 | $params = array(); 163 | 164 | $params['padID'] = $padID; 165 | $params['startRev'] = $startRev; 166 | $params['endRev'] = $endRev; 167 | 168 | return $this->post("createDiffHTML", $params); 169 | } 170 | 171 | // createPad 172 | public function createPad($padID, $text = null){ 173 | $params = array(); 174 | 175 | $params['padID'] = $padID; 176 | if (isset($text)){ 177 | $params['text'] = $text; 178 | } 179 | 180 | return $this->post("createPad", $params); 181 | } 182 | 183 | // createGroupPad 184 | public function createGroupPad($groupID, $padName, $text = null){ 185 | $params = array(); 186 | 187 | $params['groupID'] = $groupID; 188 | $params['padName'] = $padName; 189 | if (isset($text)){ 190 | $params['text'] = $text; 191 | } 192 | 193 | return $this->post("createGroupPad", $params); 194 | } 195 | 196 | // createAuthor 197 | public function createAuthor($name = null){ 198 | $params = array(); 199 | 200 | if (isset($name)){ 201 | $params['name'] = $name; 202 | } 203 | 204 | return $this->post("createAuthor", $params); 205 | } 206 | 207 | // createAuthorIfNotExistsFor 208 | public function createAuthorIfNotExistsFor($authorMapper, $name = null){ 209 | $params = array(); 210 | 211 | $params['authorMapper'] = $authorMapper; 212 | if (isset($name)){ 213 | $params['name'] = $name; 214 | } 215 | 216 | return $this->post("createAuthorIfNotExistsFor", $params); 217 | } 218 | 219 | // listPadsOfAuthor 220 | public function listPadsOfAuthor($authorID){ 221 | $params = array(); 222 | 223 | $params['authorID'] = $authorID; 224 | 225 | return $this->get("listPadsOfAuthor", $params); 226 | } 227 | 228 | // createSession 229 | public function createSession($groupID, $authorID, $validUntil){ 230 | $params = array(); 231 | 232 | $params['groupID'] = $groupID; 233 | $params['authorID'] = $authorID; 234 | $params['validUntil'] = $validUntil; 235 | 236 | return $this->post("createSession", $params); 237 | } 238 | 239 | // deleteSession 240 | public function deleteSession($sessionID){ 241 | $params = array(); 242 | 243 | $params['sessionID'] = $sessionID; 244 | 245 | return $this->post("deleteSession", $params); 246 | } 247 | 248 | // getSessionInfo 249 | public function getSessionInfo($sessionID){ 250 | $params = array(); 251 | 252 | $params['sessionID'] = $sessionID; 253 | 254 | return $this->get("getSessionInfo", $params); 255 | } 256 | 257 | // listSessionsOfGroup 258 | public function listSessionsOfGroup($groupID){ 259 | $params = array(); 260 | 261 | $params['groupID'] = $groupID; 262 | 263 | return $this->get("listSessionsOfGroup", $params); 264 | } 265 | 266 | // listSessionsOfAuthor 267 | public function listSessionsOfAuthor($authorID){ 268 | $params = array(); 269 | 270 | $params['authorID'] = $authorID; 271 | 272 | return $this->get("listSessionsOfAuthor", $params); 273 | } 274 | 275 | // getText 276 | public function getText($padID, $rev = null){ 277 | $params = array(); 278 | 279 | $params['padID'] = $padID; 280 | if (isset($rev)){ 281 | $params['rev'] = $rev; 282 | } 283 | 284 | return $this->get("getText", $params); 285 | } 286 | 287 | // setText 288 | public function setText($padID, $text){ 289 | $params = array(); 290 | 291 | $params['padID'] = $padID; 292 | $params['text'] = $text; 293 | 294 | return $this->post("setText", $params); 295 | } 296 | 297 | // getHTML 298 | public function getHTML($padID, $rev = null){ 299 | $params = array(); 300 | 301 | $params['padID'] = $padID; 302 | if (isset($rev)){ 303 | $params['rev'] = $rev; 304 | } 305 | 306 | return $this->get("getHTML", $params); 307 | } 308 | 309 | // setHTML 310 | public function setHTML($padID, $html){ 311 | $params = array(); 312 | 313 | $params['padID'] = $padID; 314 | $params['html'] = $html; 315 | 316 | return $this->post("setHTML", $params); 317 | } 318 | 319 | // getAttributePool 320 | public function getAttributePool($padID){ 321 | $params = array(); 322 | 323 | $params['padID'] = $padID; 324 | 325 | return $this->get("getAttributePool", $params); 326 | } 327 | 328 | // getRevisionsCount 329 | public function getRevisionsCount($padID){ 330 | $params = array(); 331 | 332 | $params['padID'] = $padID; 333 | 334 | return $this->get("getRevisionsCount", $params); 335 | } 336 | 337 | // getSavedRevisionsCount 338 | public function getSavedRevisionsCount($padID){ 339 | $params = array(); 340 | 341 | $params['padID'] = $padID; 342 | 343 | return $this->get("getSavedRevisionsCount", $params); 344 | } 345 | 346 | // listSavedRevisions 347 | public function listSavedRevisions($padID){ 348 | $params = array(); 349 | 350 | $params['padID'] = $padID; 351 | 352 | return $this->get("listSavedRevisions", $params); 353 | } 354 | 355 | // saveRevision 356 | public function saveRevision($padID, $rev){ 357 | $params = array(); 358 | 359 | $params['padID'] = $padID; 360 | $params['rev'] = $rev; 361 | 362 | return $this->post("saveRevision", $params); 363 | } 364 | 365 | // getRevisionChangeset 366 | public function getRevisionChangeset($padID, $rev = null){ 367 | $params = array(); 368 | 369 | $params['padID'] = $padID; 370 | if (isset($rev)){ 371 | $params['rev'] = $rev; 372 | } 373 | 374 | return $this->get("getRevisionChangeset", $params); 375 | } 376 | 377 | // getLastEdited 378 | public function getLastEdited($padID){ 379 | $params = array(); 380 | 381 | $params['padID'] = $padID; 382 | 383 | return $this->get("getLastEdited", $params); 384 | } 385 | 386 | // deletePad 387 | public function deletePad($padID){ 388 | $params = array(); 389 | 390 | $params['padID'] = $padID; 391 | 392 | return $this->post("deletePad", $params); 393 | } 394 | 395 | // copyPad 396 | public function copyPad($sourceID, $destinationID, $force = null){ 397 | $params = array(); 398 | 399 | $params['sourceID'] = $sourceID; 400 | $params['destinationID'] = $destinationID; 401 | if (isset($force)){ 402 | $params['force'] = $force; 403 | } 404 | 405 | return $this->post("copyPad", $params); 406 | } 407 | 408 | // movePad 409 | public function movePad($sourceID, $destinationID, $force = null){ 410 | $params = array(); 411 | 412 | $params['sourceID'] = $sourceID; 413 | $params['destinationID'] = $destinationID; 414 | if (isset($force)){ 415 | $params['force'] = $force; 416 | } 417 | 418 | return $this->post("movePad", $params); 419 | } 420 | 421 | // getReadOnlyID 422 | public function getReadOnlyID($padID){ 423 | $params = array(); 424 | 425 | $params['padID'] = $padID; 426 | 427 | return $this->get("getReadOnlyID", $params); 428 | } 429 | 430 | // getPadID 431 | public function getPadID($roID){ 432 | $params = array(); 433 | 434 | $params['roID'] = $roID; 435 | 436 | return $this->get("getPadID", $params); 437 | } 438 | 439 | // setPublicStatus 440 | public function setPublicStatus($padID, $publicStatus){ 441 | $params = array(); 442 | 443 | $params['padID'] = $padID; 444 | $params['publicStatus'] = $publicStatus; 445 | 446 | return $this->post("setPublicStatus", $params); 447 | } 448 | 449 | // getPublicStatus 450 | public function getPublicStatus($padID){ 451 | $params = array(); 452 | 453 | $params['padID'] = $padID; 454 | 455 | return $this->get("getPublicStatus", $params); 456 | } 457 | 458 | // setPassword 459 | public function setPassword($padID, $password){ 460 | $params = array(); 461 | 462 | $params['padID'] = $padID; 463 | $params['password'] = $password; 464 | 465 | return $this->post("setPassword", $params); 466 | } 467 | 468 | // isPasswordProtected 469 | public function isPasswordProtected($padID){ 470 | $params = array(); 471 | 472 | $params['padID'] = $padID; 473 | 474 | return $this->get("isPasswordProtected", $params); 475 | } 476 | 477 | // listAuthorsOfPad 478 | public function listAuthorsOfPad($padID){ 479 | $params = array(); 480 | 481 | $params['padID'] = $padID; 482 | 483 | return $this->get("listAuthorsOfPad", $params); 484 | } 485 | 486 | // padUsersCount 487 | public function padUsersCount($padID){ 488 | $params = array(); 489 | 490 | $params['padID'] = $padID; 491 | 492 | return $this->get("padUsersCount", $params); 493 | } 494 | 495 | // getAuthorName 496 | public function getAuthorName($authorID){ 497 | $params = array(); 498 | 499 | $params['authorID'] = $authorID; 500 | 501 | return $this->get("getAuthorName", $params); 502 | } 503 | 504 | // padUsers 505 | public function padUsers($padID){ 506 | $params = array(); 507 | 508 | $params['padID'] = $padID; 509 | 510 | return $this->get("padUsers", $params); 511 | } 512 | 513 | // sendClientsMessage 514 | public function sendClientsMessage($padID, $msg){ 515 | $params = array(); 516 | 517 | $params['padID'] = $padID; 518 | $params['msg'] = $msg; 519 | 520 | return $this->post("sendClientsMessage", $params); 521 | } 522 | 523 | // listAllGroups 524 | public function listAllGroups(){ 525 | $params = array(); 526 | 527 | 528 | return $this->get("listAllGroups", $params); 529 | } 530 | 531 | // checkToken 532 | public function checkToken(){ 533 | $params = array(); 534 | 535 | 536 | return $this->post("checkToken", $params); 537 | } 538 | 539 | // getChatHistory 540 | public function getChatHistory($padID, $start = null, $end = null){ 541 | $params = array(); 542 | 543 | $params['padID'] = $padID; 544 | if (isset($start)){ 545 | $params['start'] = $start; 546 | } 547 | if (isset($end)){ 548 | $params['end'] = $end; 549 | } 550 | 551 | return $this->get("getChatHistory", $params); 552 | } 553 | 554 | // getChatHead 555 | public function getChatHead($padID){ 556 | $params = array(); 557 | 558 | $params['padID'] = $padID; 559 | 560 | return $this->get("getChatHead", $params); 561 | } 562 | 563 | // restoreRevision 564 | public function restoreRevision($padID, $rev){ 565 | $params = array(); 566 | 567 | $params['padID'] = $padID; 568 | $params['rev'] = $rev; 569 | 570 | return $this->post("restoreRevision", $params); 571 | } 572 | 573 | 574 | } 575 | 576 | --------------------------------------------------------------------------------