├── .gitignore ├── README.md ├── composer.json └── src └── Roumen └── Disqus ├── DisqusServiceProvider.php └── disqusapi ├── LICENSE ├── README.rst ├── cacert.pem ├── disqusapi.php ├── interfaces.json ├── json.php └── url.php /.gitignore: -------------------------------------------------------------------------------- 1 | /nbproject 2 | /vendor 3 | composer.phar 4 | composer.lock 5 | .directory 6 | .DS_Store 7 | Thumbs.db -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [laravel-disqus](http://roumen.it/projects/laravel-disqus) package 2 | 3 | [![Latest Stable Version](https://poser.pugx.org/roumen/disqus/version.png)](https://packagist.org/packages/roumen/disqus) [![Total Downloads](https://poser.pugx.org/roumen/disqus/d/total.png)](https://packagist.org/packages/roumen/disqus) 4 | 5 | A Laravel 5 package for Disqus API. 6 | 7 | 8 | ## Notes 9 | 10 | Latest supported version for Laravel 5 is v1.* (e.g v1.2) 11 | 12 | Latest supported version for Laravel 4 is v0.1.1.3 13 | 14 | Branch dev-master is for development and is unstable 15 | 16 | 17 | ## Installation 18 | 19 | Run the following command and provide the latest stable version (e.g v1.2) : 20 | 21 | ```bash 22 | composer require roumen/disqus 23 | ``` 24 | 25 | or add the following to your `composer.json` file : 26 | 27 | ```json 28 | "roumen/disqus": "1.*" 29 | ``` 30 | 31 | Then register this service provider with Laravel : 32 | 33 | ```php 34 | 'Roumen\Disqus\DisqusServiceProvider', 35 | ``` 36 | 37 | In your controllers or routes you can create new disqus api object 38 | 39 | ```php 40 | $disqus = new \Disqus('YOUR_SECRET_KEY'); 41 | 42 | // to turn off SSL 43 | $disqus->setSecure(false); 44 | 45 | // example API call 46 | $disqus->trends->listThreads(); 47 | ``` 48 | 49 | Documentation on all methods, as well as general API usage can be found at http://disqus.com/api/ 50 | 51 | 52 | ## Examples 53 | 54 | [How to add your latest comments from disqus to your local DB](https://github.com/RoumenDamianoff/laravel-disqus/wiki/Sync-comments) 55 | 56 | 57 | ## About disqus-php library 58 | 59 | Author: DISQUS 60 | 61 | Copyright: 2007-2010 Big Head Labs 62 | 63 | License: Apache version 2.0 (see disqusapi/LICENSE for more information) 64 | 65 | Link: http://disqus.com/ -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "roumen/disqus", 3 | "description": "Disqus API package for Laravel.", 4 | "homepage": "https://laravelium.com", 5 | "keywords": ["laravel", "disqus", "api"], 6 | "license": "Apache-2.0", 7 | "authors": [ 8 | { 9 | "name": "Roumen Damianoff", 10 | "email": "roumen@damianoff.com", 11 | "role": "Developer", 12 | "homepage": "https://damianoff.com" 13 | } 14 | ], 15 | "require": { 16 | "php": ">=5.5.9", 17 | "illuminate/support": "~5" 18 | }, 19 | "autoload": { 20 | "psr-0": { 21 | "Roumen\\Disqus": "src/" 22 | }, 23 | "files": [ 24 | "src/Roumen/Disqus/disqusapi/disqusapi.php" 25 | ] 26 | }, 27 | "extra": { 28 | "laravel": { 29 | "providers": [ 30 | "Roumen\\Disqus\\DisqusServiceProvider" 31 | ] 32 | } 33 | }, 34 | "minimum-stability": "stable" 35 | } 36 | -------------------------------------------------------------------------------- /src/Roumen/Disqus/DisqusServiceProvider.php: -------------------------------------------------------------------------------- 1 | trends->listThreads() 11 | 12 | Parameters (including the ability to override version, api_secret, and format) are passed as keyword arguments to the resource call:: 13 | 14 | $disqus->posts->details(array('post'=>1, 'version'=>'3.0')); 15 | 16 | Documentation on all methods, as well as general API usage can be found at http://disqus.com/api/ -------------------------------------------------------------------------------- /src/Roumen/Disqus/disqusapi/disqusapi.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright 2007-2010 Big Head Labs 9 | * @link http://disqus.com/ 10 | * @package disqusapi 11 | * @version 0.1.1 12 | * 13 | * Example: 14 | * 15 | * $disqus = new DisqusAPI($secret_key) 16 | * $disqus->trends->listThreads() 17 | * 18 | * ********************************************************************** 19 | * 20 | * Plus modifications by Roumen Damianoff 21 | * 22 | * * @link http://roumen.it/projects/laravel-disqus Laravel package 23 | * * @version 1.2 24 | * 25 | * Important note: 26 | * 27 | * $disqus->setSecure(false); can be used to turn on/off SSL 28 | * 29 | * ********************************************************************** 30 | */ 31 | 32 | class Disqus extends DisqusAPI 33 | { 34 | // 35 | } 36 | 37 | if (!defined('DISQUS_API_HOST')) { 38 | define('DISQUS_API_HOST', 'disqus.com'); 39 | } 40 | define('DISQUS_API_VERSION', '0.0.1'); 41 | 42 | require_once(dirname(__FILE__) . '/url.php'); 43 | 44 | if (!extension_loaded('json')) { 45 | require_once(dirname(__FILE__) . '/json.php'); 46 | function dsq_json_decode($data) { 47 | $json = new JSON; 48 | return $json->unserialize($data); 49 | } 50 | } else { 51 | function dsq_json_decode($data) { 52 | return json_decode($data); 53 | } 54 | } 55 | 56 | global $DISQUS_API_INTERFACES; 57 | 58 | $DISQUS_API_INTERFACES = dsq_json_decode(file_get_contents(dirname(__FILE__) . '/interfaces.json')); 59 | 60 | class DisqusInterfaceNotDefined extends Exception {} 61 | class DisqusAPIError extends Exception { 62 | public function __construct($code, $message) { 63 | $this->code = $code; 64 | $this->message = $message; 65 | } 66 | } 67 | 68 | class DisqusResource { 69 | public function __construct($api, $interface=null, $node=null, $tree=array()) { 70 | global $DISQUS_API_INTERFACES; 71 | 72 | if (!$interface) { 73 | $interface = $DISQUS_API_INTERFACES; 74 | } 75 | $this->api = $api; 76 | $this->interface = $interface; 77 | $this->node = $node; 78 | if ($node) { 79 | array_push($tree, $node); 80 | } 81 | $this->tree = $tree; 82 | } 83 | 84 | public function __get($attr) { 85 | $interface = $this->interface->$attr; 86 | if (!$interface) { 87 | throw new DisqusInterfaceNotDefined(); 88 | } 89 | return new DisqusResource($this->api, $interface, $attr, $this->tree); 90 | } 91 | 92 | public function __call($name, $args) { 93 | $resource = $this->interface->$name; 94 | if (!$resource) { 95 | throw new DisqusInterfaceNotDefined(); 96 | } 97 | $kwargs = ((array)$args) ? (array)$args[0] : false; 98 | 99 | foreach ((array)$resource->required as $k) { 100 | if (empty($kwargs[$k])) { 101 | throw new Exception('Missing required argument: '.$k); 102 | } 103 | } 104 | 105 | $api = $this->api; 106 | 107 | if (empty($kwargs['api_secret'])) { 108 | $kwargs['api_secret'] = $api->key; 109 | } 110 | 111 | // emulate a named pop 112 | $version = (!empty($kwargs['version']) ? $kwargs['version'] : $api->version); 113 | $format = (!empty($kwargs['format']) ? $kwargs['format'] : $api->format); 114 | unset($kwargs['version'], $kwargs['format']); 115 | 116 | $url = ($api->secure ? 'https://'.DISQUS_API_HOST : 'http://'.DISQUS_API_HOST); 117 | $path = '/api/'.$version.'/'.implode('/', $this->tree).'/'.$name.'.'.$format; 118 | 119 | if (!empty($kwargs)) { 120 | if ($resource->method == 'POST') { 121 | $post_data = $kwargs; 122 | } else { 123 | $post_data = false; 124 | $path .= '?'.dsq_get_query_string($kwargs); 125 | } 126 | } 127 | 128 | $response = dsq_urlopen($url.$path, $post_data); 129 | 130 | $data = call_user_func($api->formats[$format], $response['data']); 131 | 132 | if ($response['code'] != 200) { 133 | throw new DisqusAPIError($data->code, $data->response); 134 | } 135 | 136 | return $data->response; 137 | } 138 | } 139 | 140 | 141 | class DisqusAPI extends DisqusResource { 142 | public $formats = array( 143 | 'json' => 'dsq_json_decode' 144 | ); 145 | 146 | public function __construct($key=null, $format='json', $version='3.0', $secure=true) { 147 | $this->key = $key; 148 | $this->format = $format; 149 | $this->version = $version; 150 | $this->secure = $secure; 151 | parent::__construct($this); 152 | } 153 | 154 | public function __invoke() { 155 | throw new Exception('You cannot call the API without a resource.'); 156 | } 157 | 158 | public function setKey($key) { 159 | $this->key = $key; 160 | } 161 | 162 | public function setFormat($format) { 163 | $this->format = $format; 164 | } 165 | 166 | public function setVersion($version) { 167 | $this->version = $version; 168 | } 169 | 170 | public function setSecure($secure) { 171 | $this->secure = $secure; 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /src/Roumen/Disqus/disqusapi/interfaces.json: -------------------------------------------------------------------------------- 1 | { 2 | "organizations": { 3 | "listAdmins": { 4 | "required": [ 5 | "organization" 6 | ], 7 | "method": "GET", 8 | "formats": [ 9 | "json", 10 | "jsonp" 11 | ] 12 | }, 13 | "addAdmin": { 14 | "required": [ 15 | "organization", 16 | "user" 17 | ], 18 | "method": "POST", 19 | "formats": [ 20 | "json", 21 | "jsonp" 22 | ] 23 | }, 24 | "removeAdmin": { 25 | "required": [ 26 | "organization", 27 | "user" 28 | ], 29 | "method": "POST", 30 | "formats": [ 31 | "json", 32 | "jsonp" 33 | ] 34 | } 35 | }, 36 | "reactions": { 37 | "restore": { 38 | "required": [ 39 | "reaction", 40 | "forum" 41 | ], 42 | "method": "POST", 43 | "formats": [ 44 | "json", 45 | "jsonp" 46 | ] 47 | }, 48 | "list": { 49 | "required": [ 50 | "forum" 51 | ], 52 | "method": "POST", 53 | "formats": [ 54 | "json", 55 | "jsonp" 56 | ] 57 | }, 58 | "details": { 59 | "required": [ 60 | "reaction", 61 | "forum" 62 | ], 63 | "method": "GET", 64 | "formats": [ 65 | "json", 66 | "jsonp" 67 | ] 68 | }, 69 | "remove": { 70 | "required": [ 71 | "reaction", 72 | "forum" 73 | ], 74 | "method": "POST", 75 | "formats": [ 76 | "json", 77 | "jsonp" 78 | ] 79 | } 80 | }, 81 | "exports": { 82 | "exportForum": { 83 | "required": [ 84 | "forum" 85 | ], 86 | "method": "POST", 87 | "formats": [ 88 | "json", 89 | "jsonp" 90 | ] 91 | } 92 | }, 93 | "users": { 94 | "listActiveForums": { 95 | "required": [], 96 | "method": "GET", 97 | "formats": [ 98 | "json", 99 | "jsonp" 100 | ] 101 | }, 102 | "listActiveThreads": { 103 | "required": [], 104 | "method": "GET", 105 | "formats": [ 106 | "json", 107 | "jsonp", 108 | "rss" 109 | ] 110 | }, 111 | "listFollowing": { 112 | "required": [], 113 | "method": "GET", 114 | "formats": [ 115 | "json", 116 | "jsonp" 117 | ] 118 | }, 119 | "listForums": { 120 | "required": [], 121 | "method": "GET", 122 | "formats": [ 123 | "json", 124 | "jsonp" 125 | ] 126 | }, 127 | "unfollow": { 128 | "required": [], 129 | "method": "POST", 130 | "formats": [ 131 | "json", 132 | "jsonp" 133 | ] 134 | }, 135 | "listPosts": { 136 | "required": [], 137 | "method": "GET", 138 | "formats": [ 139 | "json", 140 | "jsonp", 141 | "rss" 142 | ] 143 | }, 144 | "details": { 145 | "required": [], 146 | "method": "GET", 147 | "formats": [ 148 | "json", 149 | "jsonp" 150 | ] 151 | }, 152 | "listFollowers": { 153 | "required": [], 154 | "method": "GET", 155 | "formats": [ 156 | "json", 157 | "jsonp" 158 | ] 159 | }, 160 | "follow": { 161 | "required": [], 162 | "method": "POST", 163 | "formats": [ 164 | "json", 165 | "jsonp" 166 | ] 167 | }, 168 | "listActivity": { 169 | "required": [], 170 | "method": "GET", 171 | "formats": [ 172 | "json", 173 | "jsonp" 174 | ] 175 | }, 176 | "listMostActiveForums": { 177 | "required": [], 178 | "method": "GET", 179 | "formats": [ 180 | "json", 181 | "jsonp" 182 | ] 183 | } 184 | }, 185 | "imports": { 186 | "list": { 187 | "required": [ 188 | "forum" 189 | ], 190 | "method": "GET", 191 | "formats": [ 192 | "json", 193 | "jsonp" 194 | ] 195 | }, 196 | "details": { 197 | "required": [ 198 | "group" 199 | ], 200 | "method": "GET", 201 | "formats": [ 202 | "json", 203 | "jsonp" 204 | ] 205 | } 206 | }, 207 | "posts": { 208 | "restore": { 209 | "required": [ 210 | "post" 211 | ], 212 | "method": "POST", 213 | "formats": [ 214 | "json", 215 | "jsonp" 216 | ] 217 | }, 218 | "spam": { 219 | "required": [ 220 | "post" 221 | ], 222 | "method": "POST", 223 | "formats": [ 224 | "json", 225 | "jsonp" 226 | ] 227 | }, 228 | "unhighlight": { 229 | "required": [ 230 | "post" 231 | ], 232 | "method": "POST", 233 | "formats": [ 234 | "json", 235 | "jsonp" 236 | ] 237 | }, 238 | "listPopular": { 239 | "required": [], 240 | "method": "GET", 241 | "formats": [ 242 | "json", 243 | "jsonp", 244 | "rss" 245 | ] 246 | }, 247 | "create": { 248 | "required": [ 249 | "message" 250 | ], 251 | "method": "POST", 252 | "formats": [ 253 | "json", 254 | "jsonp" 255 | ] 256 | }, 257 | "update": { 258 | "required": [ 259 | "message", 260 | "post" 261 | ], 262 | "method": "POST", 263 | "formats": [ 264 | "json", 265 | "jsonp" 266 | ] 267 | }, 268 | "list": { 269 | "required": [], 270 | "method": "GET", 271 | "formats": [ 272 | "json", 273 | "jsonp", 274 | "rss" 275 | ] 276 | }, 277 | "remove": { 278 | "required": [ 279 | "post" 280 | ], 281 | "method": "POST", 282 | "formats": [ 283 | "json", 284 | "jsonp" 285 | ] 286 | }, 287 | "getContext": { 288 | "required": [ 289 | "post" 290 | ], 291 | "method": "GET", 292 | "formats": [ 293 | "json", 294 | "jsonp", 295 | "rss" 296 | ] 297 | }, 298 | "vote": { 299 | "required": [ 300 | "vote", 301 | "post" 302 | ], 303 | "method": "POST", 304 | "formats": [ 305 | "json", 306 | "jsonp" 307 | ] 308 | }, 309 | "details": { 310 | "required": [ 311 | "post" 312 | ], 313 | "method": "GET", 314 | "formats": [ 315 | "json", 316 | "jsonp" 317 | ] 318 | }, 319 | "report": { 320 | "required": [ 321 | "post" 322 | ], 323 | "method": "POST", 324 | "formats": [ 325 | "json", 326 | "jsonp" 327 | ] 328 | }, 329 | "highlight": { 330 | "required": [ 331 | "post" 332 | ], 333 | "method": "POST", 334 | "formats": [ 335 | "json", 336 | "jsonp" 337 | ] 338 | }, 339 | "approve": { 340 | "required": [ 341 | "post" 342 | ], 343 | "method": "POST", 344 | "formats": [ 345 | "json", 346 | "jsonp" 347 | ] 348 | } 349 | }, 350 | "blacklists": { 351 | "add": { 352 | "required": [ 353 | "forum" 354 | ], 355 | "method": "POST", 356 | "formats": [ 357 | "json", 358 | "jsonp" 359 | ] 360 | }, 361 | "list": { 362 | "required": [ 363 | "forum" 364 | ], 365 | "method": "GET", 366 | "formats": [ 367 | "json", 368 | "jsonp" 369 | ] 370 | }, 371 | "remove": { 372 | "required": [ 373 | "forum" 374 | ], 375 | "method": "POST", 376 | "formats": [ 377 | "json", 378 | "jsonp" 379 | ] 380 | } 381 | }, 382 | "reports": { 383 | "domains": { 384 | "required": [], 385 | "method": "GET", 386 | "formats": [ 387 | "json", 388 | "jsonp" 389 | ] 390 | }, 391 | "ips": { 392 | "required": [], 393 | "method": "GET", 394 | "formats": [ 395 | "json", 396 | "jsonp" 397 | ] 398 | }, 399 | "threads": { 400 | "required": [], 401 | "method": "GET", 402 | "formats": [ 403 | "json", 404 | "jsonp" 405 | ] 406 | }, 407 | "users": { 408 | "required": [], 409 | "method": "GET", 410 | "formats": [ 411 | "json", 412 | "jsonp" 413 | ] 414 | } 415 | }, 416 | "whitelists": { 417 | "add": { 418 | "required": [ 419 | "forum" 420 | ], 421 | "method": "POST", 422 | "formats": [ 423 | "json", 424 | "jsonp" 425 | ] 426 | }, 427 | "list": { 428 | "required": [ 429 | "forum" 430 | ], 431 | "method": "GET", 432 | "formats": [ 433 | "json", 434 | "jsonp" 435 | ] 436 | }, 437 | "remove": { 438 | "required": [ 439 | "forum" 440 | ], 441 | "method": "POST", 442 | "formats": [ 443 | "json", 444 | "jsonp" 445 | ] 446 | } 447 | }, 448 | "applications": { 449 | "listUsage": { 450 | "required": [], 451 | "method": "GET", 452 | "formats": [ 453 | "json", 454 | "jsonp" 455 | ] 456 | } 457 | }, 458 | "trends": { 459 | "listThreads": { 460 | "required": [], 461 | "method": "GET", 462 | "formats": [ 463 | "json", 464 | "jsonp", 465 | "rss" 466 | ] 467 | } 468 | }, 469 | "threads": { 470 | "restore": { 471 | "required": [ 472 | "thread" 473 | ], 474 | "method": "POST", 475 | "formats": [ 476 | "json", 477 | "jsonp" 478 | ] 479 | }, 480 | "vote": { 481 | "required": [ 482 | "vote", 483 | "thread" 484 | ], 485 | "method": "POST", 486 | "formats": [ 487 | "json", 488 | "jsonp" 489 | ] 490 | }, 491 | "open": { 492 | "required": [ 493 | "thread" 494 | ], 495 | "method": "POST", 496 | "formats": [ 497 | "json", 498 | "jsonp" 499 | ] 500 | }, 501 | "create": { 502 | "required": [ 503 | "forum", 504 | "title" 505 | ], 506 | "method": "POST", 507 | "formats": [ 508 | "json", 509 | "jsonp" 510 | ] 511 | }, 512 | "list": { 513 | "required": [], 514 | "method": "GET", 515 | "formats": [ 516 | "json", 517 | "jsonp", 518 | "rss" 519 | ] 520 | }, 521 | "listMostLiked": { 522 | "required": [], 523 | "method": "GET", 524 | "formats": [ 525 | "json", 526 | "jsonp", 527 | "rss" 528 | ] 529 | }, 530 | "listHot": { 531 | "required": [], 532 | "method": "GET", 533 | "formats": [ 534 | "json", 535 | "jsonp", 536 | "rss" 537 | ] 538 | }, 539 | "update": { 540 | "required": [ 541 | "thread" 542 | ], 543 | "method": "POST", 544 | "formats": [ 545 | "json", 546 | "jsonp" 547 | ] 548 | }, 549 | "listSimilar": { 550 | "required": [ 551 | "thread" 552 | ], 553 | "method": "GET", 554 | "formats": [ 555 | "json", 556 | "jsonp", 557 | "rss" 558 | ] 559 | }, 560 | "details": { 561 | "required": [ 562 | "thread" 563 | ], 564 | "method": "GET", 565 | "formats": [ 566 | "json", 567 | "jsonp" 568 | ] 569 | }, 570 | "listByDate": { 571 | "required": [], 572 | "method": "GET", 573 | "formats": [ 574 | "json", 575 | "jsonp", 576 | "rss" 577 | ] 578 | }, 579 | "listPosts": { 580 | "required": [ 581 | "thread" 582 | ], 583 | "method": "GET", 584 | "formats": [ 585 | "json", 586 | "jsonp", 587 | "rss" 588 | ] 589 | }, 590 | "close": { 591 | "required": [ 592 | "thread" 593 | ], 594 | "method": "POST", 595 | "formats": [ 596 | "json", 597 | "jsonp" 598 | ] 599 | }, 600 | "remove": { 601 | "required": [ 602 | "thread" 603 | ], 604 | "method": "POST", 605 | "formats": [ 606 | "json", 607 | "jsonp" 608 | ] 609 | }, 610 | "listPopular": { 611 | "required": [], 612 | "method": "GET", 613 | "formats": [ 614 | "json", 615 | "jsonp", 616 | "rss" 617 | ] 618 | } 619 | }, 620 | "forums": { 621 | "create": { 622 | "required": [ 623 | "website", 624 | "name", 625 | "short_name" 626 | ], 627 | "method": "POST", 628 | "formats": [ 629 | "json", 630 | "jsonp" 631 | ] 632 | }, 633 | "listCategories": { 634 | "required": [ 635 | "forum" 636 | ], 637 | "method": "GET", 638 | "formats": [ 639 | "json", 640 | "jsonp" 641 | ] 642 | }, 643 | "listThreads": { 644 | "required": [ 645 | "forum" 646 | ], 647 | "method": "GET", 648 | "formats": [ 649 | "json", 650 | "jsonp", 651 | "rss" 652 | ] 653 | }, 654 | "listUsers": { 655 | "required": [ 656 | "forum" 657 | ], 658 | "method": "GET", 659 | "formats": [ 660 | "json", 661 | "jsonp" 662 | ] 663 | }, 664 | "listMostLikedUsers": { 665 | "required": [ 666 | "forum" 667 | ], 668 | "method": "GET", 669 | "formats": [ 670 | "json", 671 | "jsonp" 672 | ] 673 | }, 674 | "details": { 675 | "required": [ 676 | "forum" 677 | ], 678 | "method": "GET", 679 | "formats": [ 680 | "json", 681 | "jsonp" 682 | ] 683 | }, 684 | "listPosts": { 685 | "required": [ 686 | "forum" 687 | ], 688 | "method": "GET", 689 | "formats": [ 690 | "json", 691 | "jsonp", 692 | "rss" 693 | ] 694 | }, 695 | "listModerators": { 696 | "required": [ 697 | "forum" 698 | ], 699 | "method": "GET", 700 | "formats": [ 701 | "json", 702 | "jsonp" 703 | ] 704 | }, 705 | "addModerator": { 706 | "required": [ 707 | "forum", 708 | "user" 709 | ], 710 | "method": "POST", 711 | "formats": [ 712 | "json", 713 | "jsonp" 714 | ] 715 | }, 716 | "removeModerator": { 717 | "required": [ 718 | "forum", 719 | "moderator" 720 | ], 721 | "method": "POST", 722 | "formats": [ 723 | "json", 724 | "jsonp" 725 | ] 726 | } 727 | }, 728 | "categories": { 729 | "listPosts": { 730 | "required": [ 731 | "category" 732 | ], 733 | "method": "GET", 734 | "formats": [ 735 | "json", 736 | "jsonp", 737 | "rss" 738 | ] 739 | }, 740 | "listThreads": { 741 | "required": [ 742 | "category" 743 | ], 744 | "method": "GET", 745 | "formats": [ 746 | "json", 747 | "jsonp", 748 | "rss" 749 | ] 750 | }, 751 | "create": { 752 | "required": [ 753 | "forum", 754 | "title" 755 | ], 756 | "method": "POST", 757 | "formats": [ 758 | "json", 759 | "jsonp" 760 | ] 761 | }, 762 | "list": { 763 | "required": [], 764 | "method": "GET", 765 | "formats": [ 766 | "json", 767 | "jsonp" 768 | ] 769 | }, 770 | "details": { 771 | "required": [ 772 | "category" 773 | ], 774 | "method": "GET", 775 | "formats": [ 776 | "json", 777 | "jsonp" 778 | ] 779 | } 780 | } 781 | } -------------------------------------------------------------------------------- /src/Roumen/Disqus/disqusapi/json.php: -------------------------------------------------------------------------------- 1 | 35 | * @copyright 2007 Cesar D. Rodas 36 | * @license http://www.opensource.org/licenses/bsd-license.php BSD License 37 | * @version 1.0 38 | * @link http://cesars.users.phpclasses.org/json 39 | */ 40 | 41 | define('IN_NOWHERE',0); 42 | define('IN_STRING',1); 43 | define('IN_OBJECT',2); 44 | define('IN_ATOMIC',3); 45 | define('IN_ASSIGN',4); 46 | define('IN_ENDSTMT',5); 47 | define('IN_ARRAY',6); 48 | 49 | /** 50 | * JSON 51 | * 52 | * This class serilize an PHP OBJECT or an ARRAY into JSON 53 | * notation. Also convert a JSON text into a PHP OBJECT or 54 | * array. 55 | * 56 | * @category Javascript 57 | * @package JSON 58 | * @author Cesar D. Rodas 59 | * @copyright 2007 Cesar D. Rodas 60 | * @license http://www.opensource.org/licenses/bsd-license.php BSD License 61 | * @version 1.0 62 | * @link http://cesars.users.phpclasses.org/json 63 | */ 64 | class JSON 65 | { 66 | /** 67 | * Was parsed with an error? 68 | * 69 | * var bool 70 | * @access private 71 | */ 72 | var $error; 73 | 74 | function Json() { 75 | $this->error = false; 76 | } 77 | 78 | /** 79 | * Serialize 80 | * 81 | * Serialize a PHP OBJECT or an ARRAY into 82 | * JSON notation. 83 | * 84 | * param mixed $obj Object or array to serialize 85 | * return string JSON. 86 | */ 87 | function serialize($obj) { 88 | if ( is_object($obj) ) { 89 | $e = get_object_vars($obj); 90 | /* bug reported by Ben Rowe */ 91 | /* Adding default empty array if the */ 92 | /* object doesn't have any property */ 93 | $properties = array(); 94 | foreach ($e as $k => $v) { 95 | $properties[] = $this->_serialize( $k,$v ); 96 | } 97 | return "{".implode(",",$properties)."}"; 98 | } else if ( is_array($obj) ) { 99 | return $this->_serialize('',$obj); 100 | } 101 | } 102 | 103 | /** 104 | * UnSerialize 105 | * 106 | * Transform an JSON text into a PHP object 107 | * and return it. 108 | * @access public 109 | * @param string $text JSON text 110 | * @return mixed PHP Object, array or false. 111 | */ 112 | function unserialize( $text ) { 113 | $this->error = false; 114 | 115 | return !$this->error ? $this->_unserialize($text) : false; 116 | } 117 | 118 | /** 119 | * UnSerialize 120 | * 121 | * Transform an JSON text into a PHP object 122 | * and return it. 123 | * @access private 124 | * @param string $text JSON text 125 | * @return mixed PHP Object, array or false. 126 | */ 127 | function _unserialize($text) { 128 | $ret = new stdClass; 129 | 130 | while ( $f = $this->getNextToken($text,$i,$type) ) { 131 | switch ( $type ) { 132 | case IN_ARRAY: 133 | $tmp = $this->_unserializeArray($text); 134 | $ret = $tmp[0]; 135 | break; 136 | case IN_OBJECT: 137 | $g=0; 138 | do { 139 | $varName = $this->getNextToken($f,$g,$xType); 140 | if ( $xType != IN_STRING ) { 141 | return false; /* error parsing */ 142 | } 143 | $this->getNextToken($f,$g,$xType); 144 | if ( $xType != IN_ASSIGN) return false; 145 | $value = $this->getNextToken($f,$g,$xType); 146 | 147 | if ( $xType == IN_OBJECT) { 148 | $ret->$varName = $this->unserialize( "{".$value."}" ); 149 | $g--; 150 | } else if ($xType == IN_ARRAY) { 151 | $ret->$varName = $this->_unserializeArray( $value); 152 | $g--; 153 | } else 154 | $ret->$varName = $value; 155 | 156 | $this->getNextToken($f,$g,$xType); 157 | } while ( $xType == IN_ENDSTMT); 158 | break; 159 | default: 160 | $this->error = true; 161 | break 2; 162 | } 163 | } 164 | return $ret; 165 | } 166 | 167 | /** 168 | * JSON Array Parser 169 | * 170 | * This method transform an json-array into a PHP 171 | * array 172 | * @access private 173 | * @param string $text String to parse 174 | * @return Array PHP Array 175 | */ 176 | function _unserializeArray($text) { 177 | $r = array(); 178 | do { 179 | $f = $this->getNextToken($text,$i,$type); 180 | switch ( $type ) { 181 | case IN_STRING: 182 | case IN_ATOMIC: 183 | $r[] = $f; 184 | break; 185 | case IN_OBJECT: 186 | $r[] = $this->unserialize("{".$f."}"); 187 | $i--; 188 | break; 189 | case IN_ARRAY: 190 | $r[] = $this->_unserializeArray($f); 191 | $i--; 192 | break; 193 | 194 | } 195 | $this->getNextToken($text,$i,$type); 196 | } while ( $type == IN_ENDSTMT); 197 | 198 | return $r; 199 | } 200 | 201 | /** 202 | * Tokenizer 203 | * 204 | * Return to the Parser the next valid token and the type 205 | * of the token. If the tokenizer fails it returns false. 206 | * 207 | * @access private 208 | * @param string $e Text to extract token 209 | * @param integer $i Start position to search next token 210 | * @param integer $state Variable to get the token type 211 | * @return string|bool Token in string or false on error. 212 | */ 213 | function getNextToken($e, &$i, &$state) { 214 | $state = IN_NOWHERE; 215 | $end = -1; 216 | $start = -1; 217 | while ( $i < strlen($e) && $end == -1 ) { 218 | switch( $e[$i] ) { 219 | /* objects */ 220 | case "{": 221 | case "[": 222 | $_tag = $e[$i]; 223 | $_endtag = $_tag == "{" ? "}" : "]"; 224 | if ( $state == IN_NOWHERE ) { 225 | $start = $i+1; 226 | switch ($state) { 227 | case IN_NOWHERE: 228 | $aux = 1; /* for loop objects */ 229 | $state = $_tag == "{" ? IN_OBJECT : IN_ARRAY; 230 | break; 231 | default: 232 | break 2; /* exit from switch and while */ 233 | } 234 | while ( ++$i && $i < strlen($e) && $aux != 0 ) { 235 | switch( $e[$i] ) { 236 | case $_tag: 237 | $aux++; 238 | break; 239 | case $_endtag: 240 | $aux--; 241 | break; 242 | } 243 | } 244 | $end = $i-1; 245 | } 246 | break; 247 | 248 | case '"': 249 | case "'": 250 | $state = IN_STRING; 251 | $buf = ""; 252 | while ( ++$i && $i < strlen($e) && $e[$i] != '"' ) { 253 | if ( $e[$i] == "\\") 254 | $i++; 255 | $buf .= $e[$i]; 256 | } 257 | $i++; 258 | return eval('return "'.str_replace('"','\"',$buf).'";'); 259 | break; 260 | case ":": 261 | $state = IN_ASSIGN; 262 | $end = 1; 263 | break; 264 | case "n": 265 | if ( substr($e,$i,4) == "null" ) { 266 | $i=$i+4; 267 | $state = IN_ATOMIC; 268 | return NULL; 269 | } 270 | else break 2; /* exit from switch and while */ 271 | case "t": 272 | if ( substr($e,$i,4) == "true") { 273 | $state = IN_ATOMIC; 274 | $i=$i+4; 275 | return true; 276 | } 277 | else break 2; /* exit from switch and while */ 278 | break; 279 | case "f": 280 | if ( substr($e,$i,5) == "false") { 281 | $state = IN_ATOMIC; 282 | $i=$i+5; 283 | return false; 284 | } 285 | else break 2; /* exit from switch and while */ 286 | break; 287 | case ",": 288 | $state = IN_ENDSTMT; 289 | $end = 1; 290 | break; 291 | case " ": 292 | case "\t": 293 | case "\r": 294 | case "\n": 295 | break; 296 | case "+": 297 | case "-": 298 | case 0: 299 | case 1: 300 | case 2: 301 | case 3: 302 | case 4: 303 | case 5: 304 | case 6: 305 | case 7: 306 | case 8: 307 | case 9: 308 | case '.': 309 | $state = IN_ATOMIC; 310 | $start = (int)$i; 311 | if ( $e[$i] == "-" || $e[$i] == "+") 312 | $i++; 313 | for ( ; $i < strlen($e) && (is_numeric($e[$i]) || $e[$i] == "." || strtolower($e[$i]) == "e") ;$i++){ 314 | $n = $i+1 < strlen($e) ? $e[$i+1] : ""; 315 | $a = strtolower($e[$i]); 316 | if ( $a == "e" && ($n == "+" || $n == "-")) 317 | $i++; 318 | else if ( $a == "e") 319 | $this->error=true; 320 | } 321 | 322 | $end = $i; 323 | break 2; /* break while too */ 324 | default: 325 | $this->error = true; 326 | 327 | } 328 | $i++; 329 | } 330 | 331 | return $start == -1 || $end == -1 ? false : substr($e, $start, $end - $start); 332 | } 333 | 334 | /** 335 | * Internal Serializer 336 | * 337 | * @param string $key Variable name 338 | * @param mixed $value Value of the variable 339 | * @access private 340 | * @return string Serialized variable 341 | */ 342 | function _serialize ( $key = '', &$value ) { 343 | $r = ''; 344 | if ( $key != '')$r .= "\"${key}\" : "; 345 | if ( is_numeric($value) ) { 346 | $r .= ''.$value.''; 347 | } else if ( is_string($value) ) { 348 | $r .= '"'.$this->toString($value).'"'; 349 | } else if ( is_object($value) ) { 350 | $r .= $this->serialize($value); 351 | } else if ( is_null($value) ) { 352 | $r .= "null"; 353 | } else if ( is_bool($value) ) { 354 | $r .= $value ? "true":"false"; 355 | } else if ( is_array($value) ) { 356 | foreach($value as $k => $v) 357 | $f[] = $this->_serialize('',$v); 358 | $r .= "[".implode(",",$f)."]"; 359 | unset($f); 360 | } 361 | return $r; 362 | } 363 | 364 | /** 365 | * Convert String variables 366 | * 367 | * @param string $e Variable with an string value 368 | * @access private 369 | * @return string Serialized variable 370 | */ 371 | function toString($e) { 372 | $rep = array("\\","\r","\n","\t","'",'"'); 373 | $val = array("\\\\",'\r','\n','\t','\'','\"'); 374 | $e = str_replace($rep, $val, $e); 375 | return $e; 376 | } 377 | } 378 | ?> -------------------------------------------------------------------------------- /src/Roumen/Disqus/disqusapi/url.php: -------------------------------------------------------------------------------- 1 | $value) { 10 | if (!is_array($value)) { 11 | $postdata_str .= urlencode($key) . '=' . urlencode($value) . '&'; 12 | } else { 13 | // if the item is an array, expands it so that the 'allows multiple' API option can work 14 | foreach($value as $multipleValue) { 15 | $postdata_str .= urlencode($key) . '=' . urlencode($multipleValue) . '&'; 16 | } 17 | } 18 | } 19 | } 20 | 21 | return $postdata_str; 22 | } 23 | 24 | 25 | function dsq_get_post_content($boundary, $postdata, $file_name, $file_field) { 26 | if(empty($file_name) || empty($file_field)) { 27 | return dsq_get_query_string($postdata); 28 | } 29 | 30 | $content = array(); 31 | $content[] = '--' . $boundary; 32 | foreach($postdata as $key=>$value) { 33 | $content[] = 'Content-Disposition: form-data; name="' . $key . '"' . "\r\n\r\n" . $value; 34 | $content[] = '--' . $boundary; 35 | } 36 | $content[] = 'Content-Disposition: form-data; name="' . $file_field . '"; filename="' . $file_name . '"'; 37 | // HACK: We only need to handle text/plain files right now. 38 | $content[] = "Content-Type: text/plain\r\n"; 39 | $content[] = file_get_contents($file_name); 40 | $content[] = '--' . $boundary . '--'; 41 | $content = implode("\r\n", $content); 42 | return $content; 43 | } 44 | 45 | 46 | function dsq_get_http_headers_for_request($boundary, $content, $file_name, $file_field) { 47 | $headers = array(); 48 | $headers[] = 'User-Agent: ' . USER_AGENT; 49 | $headers[] = 'Connection: close'; 50 | if($content) { 51 | $headers[] = 'Content-Length: ' . strlen($content); 52 | if($file_name && $file_field) { 53 | $headers[] = 'Content-Type: multipart/form-data; boundary=' . $boundary; 54 | } else { 55 | $headers[] = 'Content-Type: application/x-www-form-urlencoded'; 56 | } 57 | } 58 | return implode("\r\n", $headers); 59 | } 60 | 61 | 62 | function _dsq_curl_urlopen($url, $postdata, &$response, $file_name, $file_field) { 63 | $c = curl_init($url); 64 | $postdata_str = dsq_get_query_string($postdata); 65 | 66 | $c_options = array( 67 | CURLOPT_USERAGENT => USER_AGENT, 68 | CURLOPT_RETURNTRANSFER => true, 69 | CURLOPT_POST => ($postdata_str ? 1 : 0), 70 | CURLOPT_HTTPHEADER => array('Expect:'), 71 | CURLOPT_TIMEOUT => SOCKET_TIMEOUT 72 | ); 73 | if($postdata) { 74 | $c_options[CURLOPT_POSTFIELDS] = $postdata_str; 75 | } 76 | if($file_name && $file_field) { 77 | $postdata[$file_field] = '@' . $file_name; 78 | $c_options[CURLOPT_POSTFIELDS] = $postdata; 79 | $c_options[CURLOPT_RETURNTRANSFER] = 1; 80 | } 81 | curl_setopt_array($c, $c_options); 82 | 83 | $response['data'] = curl_exec($c); 84 | 85 | $errno = curl_errno($c); 86 | // CURLE_SSL_CACERT || CURLE_SSL_CACERT_BADFILE 87 | if ($errno == 60 || $errno == 77) { 88 | curl_setopt($c, CURLOPT_CAINFO, dirname(__FILE__) . DIRECTORY_SEPARATOR . 'cacert.pem'); 89 | $response['data'] = curl_exec($c); 90 | } 91 | 92 | $response['code'] = curl_getinfo($c, CURLINFO_HTTP_CODE); 93 | } 94 | 95 | 96 | function _dsq_fsockopen_urlopen($url, $postdata, &$response, $file_name, $file_field) { 97 | $buf = ''; 98 | $req = ''; 99 | $length = 0; 100 | $boundary = '----------' . md5(time()); 101 | $postdata_str = dsq_get_post_content($boundary, $postdata, $file_name, $file_field); 102 | $url_pieces = parse_url($url); 103 | 104 | // Set default port for supported schemes if none is provided. 105 | if(!isset($url_pieces['port'])) { 106 | switch($url_pieces['scheme']) { 107 | case 'http': 108 | $url_pieces['port'] = 80; 109 | break; 110 | case 'https': 111 | $url_pieces['port'] = 443; 112 | $url_pieces['host'] = 'ssl://' . $url_pieces['host']; 113 | break; 114 | } 115 | } 116 | 117 | // Set default path if trailing slash is not provided. 118 | if(!isset($url_pieces['path'])) { $url_pieces['path'] = '/'; } 119 | 120 | // Determine if we need to include the port in the Host header or not. 121 | if(($url_pieces['port'] == 80 && $url_pieces['scheme'] == 'http') || 122 | ($url_pieces['port'] == 443 && $url_pieces['scheme'] == 'https')) { 123 | $host = $url_pieces['host']; 124 | } else { 125 | $host = $url_pieces['host'] . ':' . $url_pieces['port']; 126 | } 127 | 128 | $fp = @fsockopen($url_pieces['host'], $url_pieces['port'], $errno, $errstr, SOCKET_TIMEOUT); 129 | if(!$fp) { return false; } 130 | 131 | $path = $url_pieces['path']; 132 | if ($url_pieces['query']) $path .= '?'.$url_pieces['query']; 133 | 134 | $req .= ($postdata_str ? 'POST' : 'GET') . ' ' . $path . " HTTP/1.1\r\n"; 135 | $req .= 'Host: ' . $host . "\r\n"; 136 | $req .= dsq_get_http_headers_for_request($boundary, $postdata_str, $file_name, $file_field); 137 | if($postdata_str) { 138 | $req .= "\r\n\r\n" . $postdata_str; 139 | } 140 | $req .= "\r\n\r\n"; 141 | 142 | fwrite($fp, $req); 143 | while(!feof($fp)) { 144 | $buf .= fgets($fp, 4096); 145 | } 146 | 147 | // Parse headers from the response buffers. 148 | list($headers, $response['data']) = explode("\r\n\r\n", $buf, 2); 149 | 150 | // Get status code from headers. 151 | $headers = explode("\r\n", $headers); 152 | list($unused, $response['code'], $unused) = explode(' ', $headers[0], 3); 153 | $headers = array_slice($headers, 1); 154 | 155 | // Convert headers into associative array. 156 | foreach($headers as $unused=>$header) { 157 | $header = explode(':', $header); 158 | $header[0] = trim($header[0]); 159 | $header[1] = trim($header[1]); 160 | $headers[strtolower($header[0])] = strtolower($header[1]); 161 | } 162 | 163 | // If transfer-coding is set to chunked, we need to join the message body 164 | // together. 165 | if(isset($headers['transfer-encoding']) && 'chunked' == $headers['transfer-encoding']) { 166 | $chunk_data = $response['data']; 167 | $joined_data = ''; 168 | while(true) { 169 | // Strip length from body. 170 | list($chunk_length, $chunk_data) = explode("\r\n", $chunk_data, 2); 171 | $chunk_length = hexdec($chunk_length); 172 | if(!$chunk_length || !strlen($chunk_data)) { break; } 173 | 174 | $joined_data .= substr($chunk_data, 0, $chunk_length); 175 | $chunk_data = substr($chunk_data, $chunk_length + 1); 176 | $length += $chunk_length; 177 | } 178 | $response['data'] = $joined_data; 179 | } else { 180 | $length = $headers['content-length']; 181 | } 182 | } 183 | 184 | 185 | function _dsq_fopen_urlopen($url, $postdata, &$response, $file_name, $file_field) { 186 | $params = array(); 187 | if($file_name && $file_field) { 188 | $boundary = '----------' . md5(time()); 189 | $content = dsq_get_post_content($boundary, $postdata, $file_name, $file_field); 190 | $header = dsq_get_http_headers_for_request($boundary, $content, $file_name, $file_field); 191 | 192 | $params = array('http' => array( 193 | 'method' => 'POST', 194 | 'header' => $header, 195 | 'content' => $content, 196 | 'timeout' => SOCKET_TIMEOUT 197 | )); 198 | } else { 199 | if($postdata) { 200 | $params = array('http' => array( 201 | 'method' => 'POST', 202 | 'header' => 'Content-Type: application/x-www-form-urlencoded', 203 | 'content' => dsq_get_query_string($postdata), 204 | 'timeout' => SOCKET_TIMEOUT 205 | )); 206 | } 207 | } 208 | 209 | 210 | ini_set('user_agent', USER_AGENT); 211 | $ctx = stream_context_create($params); 212 | $fp = fopen($url, 'rb', false, $ctx); 213 | if(!$fp) { 214 | return false; 215 | } 216 | 217 | // Get status code from headers. 218 | list($unused, $response['code'], $unused) = explode(' ', $http_response_header[0], 3); 219 | $headers = array_slice($http_response_header, 1); 220 | 221 | // Convert headers into associative array. 222 | foreach($headers as $unused=>$header) { 223 | $header = explode(':', $header); 224 | $header[0] = trim($header[0]); 225 | $header[1] = trim($header[1]); 226 | $headers[strtolower($header[0])] = strtolower($header[1]); 227 | } 228 | 229 | $response['data'] = stream_get_contents($fp); 230 | } 231 | 232 | 233 | /** 234 | * Wrapper to provide a single interface for making an HTTP request. 235 | * 236 | * Attempts to use cURL or fsockopen(), whichever is available 237 | * first. 238 | * 239 | * @param string $url URL to make request to. 240 | * @param array $postdata (optional) If postdata is provided, the request 241 | * method is POST with the key/value pairs as 242 | * the data. 243 | * @param array $file (optional) Should provide associative array 244 | * with two keys: name and field. Name should 245 | * be the name of the file and field is the name 246 | * of the field to POST. 247 | */ 248 | function dsq_urlopen($url, $postdata=false, $file=false) { 249 | $response = array( 250 | 'data' => '', 251 | 'code' => 0 252 | ); 253 | 254 | if($file) { 255 | extract($file, EXTR_PREFIX_ALL, 'file'); 256 | } 257 | if(empty($file_name) || empty($file_field)) { 258 | $file_name = false; 259 | $file_field = false; 260 | } 261 | 262 | // Try curl, fsockopen, fopen + stream (PHP5 only), exec wget 263 | if(function_exists('curl_init')) { 264 | if (!function_exists('curl_setopt_array')) { 265 | function curl_setopt_array(&$ch, $curl_options) 266 | { 267 | foreach ($curl_options as $option => $value) { 268 | if (!curl_setopt($ch, $option, $value)) { 269 | return false; 270 | } 271 | } 272 | return true; 273 | } 274 | } 275 | _dsq_curl_urlopen($url, $postdata, $response, $file_name, $file_field); 276 | // } else if(ini_get('allow_url_fopen') && function_exists('stream_get_contents')) { 277 | // _dsq_fopen_urlopen($url, $postdata, $response, $file_name, $file_field); 278 | } else { 279 | // TODO: Find the failure condition for fsockopen() (sockets?) 280 | _dsq_fsockopen_urlopen($url, $postdata, $response, $file_name, $file_field); 281 | } 282 | 283 | // returns array with keys data and code (from headers) 284 | 285 | return $response; 286 | } 287 | 288 | function dsq_url_method() { 289 | if(function_exists('curl_init')) { 290 | return 'curl'; 291 | } else if(ini_get('allow_url_fopen') && function_exists('stream_get_contents')) { 292 | return 'fopen'; 293 | } else { 294 | return 'fsockopen'; 295 | } 296 | } 297 | ?> 298 | --------------------------------------------------------------------------------