1<?php 2class EtherpadLiteClient { 3 4 const API_VERSION = 1; 5 6 const CODE_OK = 0; 7 const CODE_INVALID_PARAMETERS = 1; 8 const CODE_INTERNAL_ERROR = 2; 9 const CODE_INVALID_FUNCTION = 3; 10 const CODE_INVALID_API_KEY = 4; 11 12 protected $apiKey = ""; 13 protected $baseUrl = "http://localhost:9001/api"; 14 15 public function __construct($apiKey, $baseUrl = null){ 16 $this->apiKey = $apiKey; 17 if (isset($baseUrl)){ 18 $this->baseUrl = $baseUrl; 19 } 20 if (!filter_var($this->baseUrl, FILTER_VALIDATE_URL)){ 21 throw new InvalidArgumentException("[{$this->baseUrl}] is not a valid URL"); 22 } 23 } 24 25 protected function get($function, array $arguments = array()){ 26 return $this->call($function, $arguments, 'GET'); 27 } 28 29 protected function post($function, array $arguments = array()){ 30 return $this->call($function, $arguments, 'POST'); 31 } 32 33 protected function call($function, array $arguments = array(), $method = 'GET'){ 34 $arguments['apikey'] = $this->apiKey; 35 $arguments = http_build_query($arguments, '', '&'); 36 $url = $this->baseUrl."/".self::API_VERSION."/".$function; 37 if ($method !== 'POST'){ 38 $url .= "?".$arguments; 39 } 40 // use curl of it's available 41 if (function_exists('curl_init')){ 42 $c = curl_init($url); 43 curl_setopt($c, CURLOPT_RETURNTRANSFER, true); 44 curl_setopt($c, CURLOPT_TIMEOUT, 20); 45 if ($method === 'POST'){ 46 curl_setopt($c, CURLOPT_POST, true); 47 curl_setopt($c, CURLOPT_POSTFIELDS, $arguments); 48 } 49 $result = curl_exec($c); 50 curl_close($c); 51 // fallback to plain php 52 } else { 53 $params = array('http' => array('method' => $method, 'ignore_errors' => true, 'header' => 'Content-Type:application/x-www-form-urlencoded')); 54 if ($method === 'POST'){ 55 $params['http']['content'] = $arguments; 56 } 57 $context = stream_context_create($params); 58 $fp = fopen($url, 'rb', false, $context); 59 $result = $fp ? stream_get_contents($fp) : null; 60 } 61 62 if(!$result){ 63 throw new UnexpectedValueException("Empty or No Response from the server"); 64 } 65 66 $result = json_decode($result); 67 if ($result === null){ 68 throw new UnexpectedValueException("JSON response could not be decoded"); 69 } 70 return $this->handleResult($result); 71 } 72 73 protected function handleResult($result){ 74 if (!isset($result->code)){ 75 throw new RuntimeException("API response has no code"); 76 } 77 if (!isset($result->message)){ 78 throw new RuntimeException("API response has no message"); 79 } 80 if (!isset($result->data)){ 81 $result->data = null; 82 } 83 84 switch ($result->code){ 85 case self::CODE_OK: 86 return $result->data; 87 case self::CODE_INVALID_PARAMETERS: 88 case self::CODE_INVALID_API_KEY: 89 throw new InvalidArgumentException($result->message); 90 case self::CODE_INTERNAL_ERROR: 91 throw new RuntimeException($result->message); 92 case self::CODE_INVALID_FUNCTION: 93 throw new BadFunctionCallException($result->message); 94 default: 95 throw new RuntimeException("An unexpected error occurred whilst handling the response"); 96 } 97 } 98 99 // GROUPS 100 // Pads can belong to a group. There will always be public pads that doesnt belong to a group (or we give this group the id 0) 101 102 // creates a new group 103 public function createGroup(){ 104 return $this->post("createGroup"); 105 } 106 107 // this functions helps you to map your application group ids to etherpad lite group ids 108 public function createGroupIfNotExistsFor($groupMapper){ 109 return $this->post("createGroupIfNotExistsFor", array( 110 "groupMapper" => $groupMapper 111 )); 112 } 113 114 // deletes a group 115 public function deleteGroup($groupID){ 116 return $this->post("deleteGroup", array( 117 "groupID" => $groupID 118 )); 119 } 120 121 // returns all pads of this group 122 public function listPads($groupID){ 123 return $this->get("listPads", array( 124 "groupID" => $groupID 125 )); 126 } 127 128 // creates a new pad in this group 129 public function createGroupPad($groupID, $padName, $text){ 130 return $this->post("createGroupPad", array( 131 "groupID" => $groupID, 132 "padName" => $padName, 133 "text" => $text 134 )); 135 } 136 137 // AUTHORS 138 // Theses authors are bind to the attributes the users choose (color and name). 139 140 // creates a new author 141 public function createAuthor($name){ 142 return $this->post("createAuthor", array( 143 "name" => $name 144 )); 145 } 146 147 // this functions helps you to map your application author ids to etherpad lite author ids 148 public function createAuthorIfNotExistsFor($authorMapper, $name){ 149 return $this->post("createAuthorIfNotExistsFor", array( 150 "authorMapper" => $authorMapper, 151 "name" => $name 152 )); 153 } 154 155 // SESSIONS 156 // Sessions can be created between a group and a author. This allows 157 // an author to access more than one group. The sessionID will be set as 158 // a cookie to the client and is valid until a certian date. 159 160 // creates a new session 161 public function createSession($groupID, $authorID, $validUntil){ 162 return $this->post("createSession", array( 163 "groupID" => $groupID, 164 "authorID" => $authorID, 165 "validUntil" => $validUntil 166 )); 167 } 168 169 // deletes a session 170 public function deleteSession($sessionID){ 171 return $this->post("deleteSession", array( 172 "sessionID" => $sessionID 173 )); 174 } 175 176 // returns informations about a session 177 public function getSessionInfo($sessionID){ 178 return $this->get("getSessionInfo", array( 179 "sessionID" => $sessionID 180 )); 181 } 182 183 // returns all sessions of a group 184 public function listSessionsOfGroup($groupID){ 185 return $this->get("listSessionsOfGroup", array( 186 "groupID" => $groupID 187 )); 188 } 189 190 // returns all sessions of an author 191 public function listSessionsOfAuthor($authorID){ 192 return $this->get("listSessionsOfAuthor", array( 193 "authorID" => $authorID 194 )); 195 } 196 197 // PAD CONTENT 198 // Pad content can be updated and retrieved through the API 199 200 // returns the text of a pad 201 public function getText($padID, $rev=null){ 202 $params = array("padID" => $padID); 203 if (isset($rev)){ 204 $params["rev"] = $rev; 205 } 206 return $this->get("getText", $params); 207 } 208 209 // returns the text of a pad as html 210 public function getHTML($padID, $rev=null){ 211 $params = array("padID" => $padID); 212 if (isset($rev)){ 213 $params["rev"] = $rev; 214 } 215 return $this->get("getHTML", $params); 216 } 217 218 // sets the text of a pad 219 public function setText($padID, $text){ 220 return $this->post("setText", array( 221 "padID" => $padID, 222 "text" => $text 223 )); 224 } 225 226 // sets the html text of a pad 227 public function setHTML($padID, $html){ 228 return $this->post("setHTML", array( 229 "padID" => $padID, 230 "html" => $html 231 )); 232 } 233 234 // PAD 235 // Group pads are normal pads, but with the name schema 236 // GROUPID$PADNAME. A security manager controls access of them and its 237 // forbidden for normal pads to include a $ in the name. 238 239 // creates a new pad 240 public function createPad($padID, $text){ 241 return $this->post("createPad", array( 242 "padID" => $padID, 243 "text" => $text 244 ), 'POST'); 245 } 246 247 // returns the number of revisions of this pad 248 public function getRevisionsCount($padID){ 249 return $this->get("getRevisionsCount", array( 250 "padID" => $padID 251 )); 252 } 253 254 // deletes a pad 255 public function deletePad($padID){ 256 return $this->post("deletePad", array( 257 "padID" => $padID 258 )); 259 } 260 261 // returns the read only link of a pad 262 public function getReadOnlyID($padID){ 263 return $this->get("getReadOnlyID", array( 264 "padID" => $padID 265 )); 266 } 267 268 // sets a boolean for the public status of a pad 269 public function setPublicStatus($padID, $publicStatus){ 270 if (is_bool($publicStatus)) { 271 $publicStatus = $publicStatus ? "true" : "false"; 272 } 273 return $this->post("setPublicStatus", array( 274 "padID" => $padID, 275 "publicStatus" => $publicStatus 276 )); 277 } 278 279 // return true of false 280 public function getPublicStatus($padID){ 281 return $this->get("getPublicStatus", array( 282 "padID" => $padID 283 )); 284 } 285 286 // returns ok or a error message 287 public function setPassword($padID, $password){ 288 return $this->post("setPassword", array( 289 "padID" => $padID, 290 "password" => $password 291 )); 292 } 293 294 // returns true or false 295 public function isPasswordProtected($padID){ 296 return $this->get("isPasswordProtected", array( 297 "padID" => $padID 298 )); 299 } 300} 301 302