| [ Root ] [ Search ] [ Index ] |
PHP Cross Reference of bbPress TrunkProvided by Yoast |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * XML-RPC protocol support for bbPress 4 * 5 * @since 1.0 6 * @package bbPress 7 */ 8 9 10 11 /** 12 * Whether this is an XML-RPC Request 13 * 14 * @since 1.0 15 * @var bool 16 */ 17 define( 'XMLRPC_REQUEST', true ); 18 19 // Get rid of cookies sent by some browser-embedded clients 20 $_COOKIE = array(); 21 22 // A bug in PHP < 5.2.2 makes $HTTP_RAW_POST_DATA not set by default 23 if ( !isset( $HTTP_RAW_POST_DATA ) ) { 24 $HTTP_RAW_POST_DATA = file_get_contents( 'php://input' ); 25 } 26 27 // Fix for mozBlog and other cases where '<?xml' isn't on the very first line 28 if ( isset( $HTTP_RAW_POST_DATA ) ) { 29 $HTTP_RAW_POST_DATA = trim( $HTTP_RAW_POST_DATA ); 30 } 31 32 // Load bbPress 33 require_once ( './bb-load.php' ); 34 35 36 37 // If the service discovery data is requested then return it and exit 38 if ( isset( $_GET['rsd'] ) ) { 39 header( 'Content-Type: text/xml; charset=UTF-8', true ); 40 echo '<?xml version="1.0" encoding="UTF-8"?'.'>' . "\n"; 41 echo '<rsd version="1.0" xmlns="http://archipelago.phrasewise.com/rsd">' . "\n"; 42 echo ' <service>' . "\n"; 43 echo ' <engineName>bbPress</engineName>' . "\n"; 44 echo ' <engineLink>http://bbpress.org/</engineLink>' . "\n"; 45 echo ' <homePageLink>' . bb_get_uri() . '</homePageLink>' . "\n"; 46 echo ' <apis>' . "\n"; 47 echo ' <api name="bbPress" blogID="1" preferred="true" apiLink="' . bb_get_uri( 'xmlrpc.php' ) . '" />' . "\n"; 48 echo ' </apis>' . "\n"; 49 echo ' </service>' . "\n"; 50 echo '</rsd>' . "\n"; 51 exit; 52 } 53 54 55 56 // Load the XML-RPC server/client classes 57 require_once( BACKPRESS_PATH . '/class.ixr.php' ); 58 59 60 61 /** 62 * XML-RPC server class to allow for remote publishing 63 * 64 * @since 1.0 65 * @package bbPress 66 * @subpackage Publishing 67 * @uses class IXR_Server 68 */ 69 class BB_XMLRPC_Server extends IXR_Server 70 { 71 /** 72 * Stores the last error generated by the class 73 * 74 * @since 1.0 75 * @var object|boolean An instance of the IXR_Error class or false if no error exists 76 */ 77 var $error = false; 78 79 /** 80 * Site options which can be manipulated using XML-RPC 81 * 82 * @since 1.0 83 * @var array 84 */ 85 var $site_options = array(); 86 87 /** 88 * Whether read-only methods require authentication 89 * 90 * @since 1.0 91 * @var boolean 92 **/ 93 var $auth_readonly = false; 94 95 /** 96 * Whether user switching is allowed 97 * 98 * @since 1.0 99 * @var boolean 100 **/ 101 var $allow_user_switching = false; 102 103 /** 104 * Initialises the XML-RPC server 105 * 106 * @since 1.0 107 * @return void 108 */ 109 function BB_XMLRPC_Server() 110 { 111 // bbPress publishing API 112 if ( bb_get_option( 'enable_xmlrpc' ) ) { 113 $this->methods = array( 114 // - Demo 115 'demo.sayHello' => 'this:sayHello', 116 'demo.addTwoNumbers' => 'this:addTwoNumbers', 117 // - Forums 118 'bb.getForumCount' => 'this:bb_getForumCount', 119 'bb.getForums' => 'this:bb_getForums', 120 'bb.getForum' => 'this:bb_getForum', 121 'bb.newForum' => 'this:bb_newForum', 122 'bb.editForum' => 'this:bb_editForum', 123 'bb.deleteForum' => 'this:bb_deleteForum', 124 // - Topics 125 'bb.getTopicCount' => 'this:bb_getTopicCount', 126 'bb.getTopics' => 'this:bb_getTopics', 127 'bb.getTopic' => 'this:bb_getTopic', 128 'bb.newTopic' => 'this:bb_newTopic', 129 'bb.editTopic' => 'this:bb_editTopic', 130 'bb.deleteTopic' => 'this:bb_deleteTopic', // Also undeletes 131 'bb.moveTopic' => 'this:bb_moveTopic', 132 'bb.stickTopic' => 'this:bb_stickTopic', // Also unsticks 133 'bb.closeTopic' => 'this:bb_closeTopic', // Also opens 134 'bb.getTopicStatusList' => 'this:bb_getTopicStatusList', 135 // - Posts (replies) 136 'bb.getPostCount' => 'this:bb_getPostCount', 137 'bb.getPosts' => 'this:bb_getPosts', 138 'bb.getPost' => 'this:bb_getPost', 139 'bb.newPost' => 'this:bb_newPost', 140 'bb.editPost' => 'this:bb_editPost', 141 'bb.deletePost' => 'this:bb_deletePost', // Also undeletes 142 'bb.getPostStatusList' => 'this:bb_getPostStatusList', 143 // - Topic Tags 144 'bb.getHotTopicTags' => 'this:bb_getHotTopicTags', 145 'bb.getTopicTagCount' => 'this:bb_getTopicTagCount', 146 'bb.getTopicTags' => 'this:bb_getTopicTags', 147 'bb.getTopicTag' => 'this:bb_getTopicTag', 148 'bb.addTopicTags' => 'this:bb_addTopicTags', 149 'bb.removeTopicTags' => 'this:bb_removeTopicTags', 150 'bb.renameTopicTag' => 'this:bb_renameTopicTag', 151 'bb.mergeTopicTags' => 'this:bb_mergeTopicTags', 152 'bb.destroyTopicTag' => 'this:bb_destroyTopicTag', 153 // - Options 154 'bb.getOptions' => 'this:bb_getOptions', 155 'bb.setOptions' => 'this:bb_setOptions' 156 ); 157 } 158 159 // Pingback 160 if ( bb_get_option( 'enable_pingback' ) ) { 161 $this->methods = array_merge( (array)$this->methods, array( 162 'pingback.ping' => 'this:pingback_ping', 163 'pingback.extensions.getPingbacks' => 'this:pingback_extensions_getPingbacks' 164 ) ); 165 } 166 167 // Tells read-only methods whether they require authentication or not 168 $this->auth_readonly = apply_filters( 'bb_xmlrpc_auth_readonly', $this->auth_readonly ); 169 170 // Whether or not to allow user switching 171 $this->allow_user_switching = bb_get_option( 'bb_xmlrpc_allow_user_switching' ); 172 173 $this->initialise_site_option_info(); 174 $this->methods = apply_filters( 'bb_xmlrpc_methods', $this->methods ); 175 $this->IXR_Server( $this->methods ); 176 } 177 178 179 180 /** 181 * Utility methods 182 */ 183 184 /** 185 * Checks the user credentials supplied in the request to make sure they are valid 186 * 187 * @since 1.0 188 * @return integer|boolean The user id if the user is valid, otherwise false 189 * @param string $user_login The users login 190 * @param string $user_pass The users password in plain text 191 * @param string $capability The capability to check (optional) 192 * @param string $message The message to pass back in the error if the capability check fails (optional) 193 */ 194 function authenticate( $user_login, $user_pass, $capability = 'read', $message = false ) 195 { 196 if ( is_array( $user_login ) ) { 197 $auth_user_login = (string) $user_login[0]; 198 $switch_user_login = (string) $user_login[1]; 199 } else { 200 $auth_user_login = (string) $user_login; 201 $switch_user_login = false; 202 } 203 204 // Check the login 205 $user = bb_check_login( $auth_user_login, $user_pass ); 206 if ( !$user || is_wp_error( $user ) ) { 207 $this->error = new IXR_Error( 403, __( 'Authentication failed.' ) ); 208 return false; 209 } 210 211 // Set the current user 212 $user = bb_set_current_user( $user->ID ); 213 214 // Make sure they are allowed to do this 215 if ( !bb_current_user_can( $capability ) ) { 216 if ( !$message ) { 217 $message = __( 'You do not have permission to read this.' ); 218 } 219 $this->error = new IXR_Error( 403, $message ); 220 return false; 221 } 222 223 // Switch the user if requested and allowed 224 if ( $switch_user_login && $this->allow_user_switching && bb_current_user_can( 'edit_users' ) ) { 225 $user = $this->switch_user( $switch_user_login, $capability, $message ); 226 } 227 228 return $user; 229 } 230 231 /** 232 * Switches the currently active user for incognito actions 233 * 234 * @since 1.0 235 * @return integer|boolean The user id if the user is valid, otherwise false 236 * @param string $user_login The users login 237 * @param string $capability The capability to check (optional) 238 * @param string $message The message to pass back in the error if the capability check fails (optional) 239 */ 240 function switch_user( $user_login, $capability = 'read', $message = false ) 241 { 242 // Just get the user, authentication has already been established by the 243 $user = bb_get_user( $user_login, array( 'by' => 'login' ) ); 244 if ( !$user || is_wp_error( $user ) ) { 245 $this->error = new IXR_Error( 400, __( 'User switching failed, the requested user does not exist.' ) ); 246 return false; 247 } 248 249 // Set the current user 250 $user = bb_set_current_user( $user->ID ); 251 252 // Make sure they are allowed to do this 253 if ( !bb_current_user_can( $capability ) ) { 254 if ( !$message ) { 255 $message = __( 'You do not have permission to read this.' ); 256 } 257 $this->error = new IXR_Error( 403, $message ); 258 return false; 259 } 260 261 return $user; 262 } 263 264 /** 265 * Sanitises data from XML-RPC request parameters 266 * 267 * @since 1.0 268 * @return mixed The sanitised variable, should come back with the same type 269 * @param $array mixed The variable to be sanitised 270 * @uses $bbdb BackPress database class instance 271 */ 272 function escape( &$array ) 273 { 274 global $bbdb; 275 276 if ( !is_array( $array ) ) { 277 // Escape it 278 $array = $bbdb->escape( $array ); 279 } elseif ( count( $array ) ) { 280 foreach ( (array) $array as $k => $v ) { 281 if ( is_array( $v ) ) { 282 // Recursively sanitize arrays 283 $this->escape( $array[$k] ); 284 } elseif ( is_object( $v ) ) { 285 // Don't sanitise objects - shouldn't happen anyway 286 } else { 287 // Escape it 288 $array[$k] = $bbdb->escape( $v ); 289 } 290 } 291 } 292 293 return $array; 294 } 295 296 /** 297 * Prepares forum data for return in an XML-RPC object 298 * 299 * @since 1.0 300 * @return array The prepared forum data 301 * @param array|object The unprepared forum data 302 **/ 303 function prepare_forum( $forum ) 304 { 305 // Cast to an array 306 $_forum = (array) $forum; 307 // Set the URI 308 $_forum['forum_uri'] = get_forum_link( $_forum['forum_id'] ); 309 // Give this a definite value 310 if ( !isset( $_forum['forum_is_category'] ) ) { 311 $_forum['forum_is_category'] = 0; 312 } 313 // Allow plugins to modify the data 314 return apply_filters( 'bb_xmlrpc_prepare_forum', $_forum, (array) $forum ); 315 } 316 317 /** 318 * Prepares topic data for return in an XML-RPC object 319 * 320 * @since 1.0 321 * @return array The prepared topic data 322 * @param array|object The unprepared topic data 323 **/ 324 function prepare_topic( $topic ) 325 { 326 // Cast to an array 327 $_topic = (array) $topic; 328 // Set the URI 329 $_topic['topic_uri'] = get_topic_link( $_topic['topic_id'] ); 330 // Set readable times 331 $_topic['topic_start_time_since'] = bb_since( $_topic['topic_start_time'] ); 332 $_topic['topic_time_since'] = bb_since( $_topic['topic_time'] ); 333 // Set the display names 334 $_topic['topic_poster_display_name'] = get_user_display_name( $_topic['topic_poster'] ); 335 $_topic['topic_last_poster_display_name'] = get_user_display_name( $_topic['topic_last_poster'] ); 336 // Remove some sensitive user ids 337 unset( 338 $_topic['topic_poster'], 339 $_topic['topic_last_poster'] 340 ); 341 // Allow plugins to modify the data 342 return apply_filters( 'bb_xmlrpc_prepare_topic', $_topic, (array) $topic ); 343 } 344 345 /** 346 * Prepares post data for return in an XML-RPC object 347 * 348 * @since 1.0 349 * @return array The prepared post data 350 * @param array|object The unprepared post data 351 **/ 352 function prepare_post( $post ) 353 { 354 // Cast to an array 355 $_post = (array) $post; 356 // Set the URI 357 $_post['post_uri'] = get_post_link( $_post['post_id'] ); 358 // Set readable times 359 $_post['post_time_since'] = bb_since( $_post['post_time'] ); 360 // Set the display names 361 $_post['poster_display_name'] = get_user_display_name( $_post['poster_id'] ); 362 // Remove some sensitive data 363 unset( 364 $_post['poster_id'], 365 $_post['poster_ip'], 366 $_post['pingback_queued'] 367 ); 368 // Allow plugins to modify the data 369 return apply_filters( 'bb_xmlrpc_prepare_post', $_post, (array) $post ); 370 } 371 372 /** 373 * Prepares topic tag data for return in an XML-RPC object 374 * 375 * @since 1.0 376 * @return array The prepared topic tag data 377 * @param array|object The unprepared topic tag data 378 **/ 379 function prepare_topic_tag( $tag ) 380 { 381 // Cast to an array 382 $_tag = (array) $tag; 383 // Set the URI 384 $_tag['topic_tag_uri'] = bb_get_tag_link( $tag ); 385 // Consistent nomenclature 386 $_tag['topic_tag_name'] = (string) $_tag['name']; 387 $_tag['topic_tag_slug'] = (string) $_tag['slug']; 388 $_tag['topic_tag_count'] = (int) $_tag['count']; 389 // Remove some sensitive data 390 unset( 391 $_tag['object_id'], 392 $_tag['name'], 393 $_tag['slug'], 394 $_tag['count'], 395 $_tag['term_id'], 396 $_tag['term_group'], 397 $_tag['term_taxonomy_id'], 398 $_tag['taxonomy'], 399 $_tag['description'], 400 $_tag['parent'], 401 $_tag['count'], 402 $_tag['user_id'], 403 $_tag['tag_id'], 404 $_tag['tag'], 405 $_tag['raw_tag'], 406 $_tag['tag_count'] 407 ); 408 // Allow plugins to modify the data 409 return apply_filters( 'bb_xmlrpc_prepare_topic_tag', $_tag, (array) $tag ); 410 } 411 412 413 414 /** 415 * bbPress publishing API - Demo XML-RPC methods 416 */ 417 418 /** 419 * Hello world demo function for XML-RPC 420 * 421 * @since 1.0 422 * @return string The phrase 'Hello!' 423 * @param array $args Arguments passed by the XML-RPC call 424 * @param string $args[0] The username for authentication 425 * @param string $args[1] The password for authentication 426 * 427 * XML-RPC request to get a greeting 428 * <methodCall> 429 * <methodName>demo.sayHello</methodName> 430 * <params> 431 * <param><value><string>joeblow</string></value></param> 432 * <param><value><string>123password</string></value></param> 433 * </params> 434 * </methodCall> 435 */ 436 function sayHello( $args ) 437 { 438 // Escape args 439 $this->escape( $args ); 440 441 // Get the login credentials 442 $username = $args[0]; 443 $password = (string) $args[1]; 444 445 // Check the user is valid 446 if ( $this->auth_readonly && !$this->authenticate( $username, $password ) ) { 447 return $this->error; 448 } 449 450 return 'Hello!'; 451 } 452 453 /** 454 * Adds two numbers together as a demo of XML-RPC 455 * 456 * @since 1.0 457 * @return integer The sum of the two supplied numbers 458 * @param array $args Arguments passed by the XML-RPC call 459 * @param string $args[0] The username for authentication 460 * @param string $args[1] The password for authentication 461 * @param integer $args[2] The first number to be added 462 * @param integer $args[3] The second number to be added 463 * 464 * XML-RPC request to get the sum of two numbers 465 * <methodCall> 466 * <methodName>demo.addTwoNumbers</methodName> 467 * <params> 468 * <param><value><string>joeblow</string></value></param> 469 * <param><value><string>123password</string></value></param> 470 * <param><value><int>5</int></value></param> 471 * <param><value><int>102</int></value></param> 472 * </params> 473 * </methodCall> 474 */ 475 function addTwoNumbers( $args ) 476 { 477 // Escape args 478 $this->escape( $args ); 479 480 // Get the login credentials 481 $username = $args[0]; 482 $password = (string) $args[1]; 483 484 // Check the user is valid 485 if ( $this->auth_readonly && !$this->authenticate( $username, $password ) ) { 486 return $this->error; 487 } 488 489 $number1 = (int) $args[2]; 490 $number2 = (int) $args[3]; 491 492 return ( $number1 + $number2 ); 493 } 494 495 496 497 /** 498 * bbPress publishing API - Forum XML-RPC methods 499 */ 500 501 /** 502 * Returns a numerical count of forums 503 * 504 * @since 1.0 505 * @return integer|object The number of forums when successfully executed or an IXR_Error object on failure 506 * @param array $args Arguments passed by the XML-RPC call 507 * @param string $args[0] The username for authentication 508 * @param string $args[1] The password for authentication 509 * @param integer|string $args[2] The parent forum's id or slug (optional) 510 * @param integer $args[3] The depth of child forums to retrieve (optional) 511 * 512 * XML-RPC request to get a count of all forums in the bbPress instance 513 * <methodCall> 514 * <methodName>bb.getForumCount</methodName> 515 * <params> 516 * <param><value><string>joeblow</string></value></param> 517 * <param><value><string>123password</string></value></param> 518 * </params> 519 * </methodCall> 520 * 521 * XML-RPC request to get a count of all child forums in the forum with id number 34 522 * <methodCall> 523 * <methodName>bb.getForumCount</methodName> 524 * <params> 525 * <param><value><string>joeblow</string></value></param> 526 * <param><value><string>123password</string></value></param> 527 * <param><value><int>34</int></value></param> 528 * </params> 529 * </methodCall> 530 * 531 * XML-RPC request to get a count of all child forums in the forum with slug "first-forum" 532 * <methodCall> 533 * <methodName>bb.getForumCount</methodName> 534 * <params> 535 * <param><value><string>joeblow</string></value></param> 536 * <param><value><string>123password</string></value></param> 537 * <param><value><string>first-forum</string></value></param> 538 * </params> 539 * </methodCall> 540 * 541 * XML-RPC request to get a count of all child forums in the forum with id number 34 no more than 2 forums deep in the hierarchy 542 * <methodCall> 543 * <methodName>bb.getForumCount</methodName> 544 * <params> 545 * <param><value><string>joeblow</string></value></param> 546 * <param><value><string>123password</string></value></param> 547 * <param><value><int>34</int></value></param> 548 * <param><value><int>2</int></value></param> 549 * </params> 550 * </methodCall> 551 */ 552 function bb_getForumCount( $args ) 553 { 554 do_action( 'bb_xmlrpc_call', 'bb.getForumCount' ); 555 556 // Escape args 557 $this->escape( $args ); 558 559 // Get the login credentials 560 $username = $args[0]; 561 $password = (string) $args[1]; 562 563 // Check the user is valid 564 if ( $this->auth_readonly ) { 565 $user = $this->authenticate( $username, $password ); 566 } 567 568 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getForumCount' ); 569 570 // If an error was raised by authentication or by an action then return it 571 if ( $this->error ) { 572 return $this->error; 573 } 574 575 // Setup an array to store arguments to pass to bb_get_forums() function 576 $get_forums_args = array( 577 'child_of' => 0, 578 'hierarchical' => 0, 579 'depth' => 0 580 ); 581 582 // Can be numeric id or slug 583 $forum_id = isset( $args[2] ) ? $args[2] : false; 584 585 if ( $forum_id ) { 586 // Check for bad data 587 if ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) { 588 $this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) ); 589 return $this->error; 590 } 591 // Check the requested forum exists 592 if ( !$forum = bb_get_forum( $forum_id ) ) { 593 $this->error = new IXR_Error( 400, __( 'The forum does not exist.' ) ); 594 return $this->error; 595 } 596 // Add the specific forum to the arguments 597 $get_forums_args['child_of'] = (int) $forum->forum_id; 598 } 599 600 // Can only be an integer 601 $depth = (int) $args[3]; 602 603 if ( $depth > 0 ) { 604 // Add the depth to traverse to the arguments 605 $get_forums_args['depth'] = $depth; 606 // Only make it hierarchical if the depth > 1 607 if ( $depth > 1 ) { 608 $get_forums_args['hierarchical'] = 1; 609 } 610 } 611 612 // Get the forums. Return 0 when no forums exist 613 if ( !$forums = bb_get_forums( $get_forums_args ) ) { 614 $count = 0; 615 } else { 616 $count = count( $forums ); 617 } 618 619 do_action( 'bb_xmlrpc_call_return', 'bb.getForumCount' ); 620 621 // Return a count of the forums 622 return $count; 623 } 624 625 /** 626 * Returns details of multiple forums 627 * 628 * @since 1.0 629 * @return array|object An array containing details of all returned forums when successfully executed or an IXR_Error object on failure 630 * @param array $args Arguments passed by the XML-RPC call 631 * @param string $args[0] The username for authentication 632 * @param string $args[1] The password for authentication 633 * @param integer|string $args[2] The parent forum's id or slug (optional) 634 * @param integer $args[3] The depth of child forums to retrieve (optional) 635 * 636 * XML-RPC request to get all forums in the bbPress instance 637 * <methodCall> 638 * <methodName>bb.getForums</methodName> 639 * <params> 640 * <param><value><string>joeblow</string></value></param> 641 * <param><value><string>123password</string></value></param> 642 * </params> 643 * </methodCall> 644 * 645 * XML-RPC request to get all child forums in the forum with id number 34 646 * <methodCall> 647 * <methodName>bb.getForums</methodName> 648 * <params> 649 * <param><value><string>joeblow</string></value></param> 650 * <param><value><string>123password</string></value></param> 651 * <param><value><int>34</int></value></param> 652 * </params> 653 * </methodCall> 654 * 655 * XML-RPC request to get all child forums in the forum with slug "first-forum" 656 * <methodCall> 657 * <methodName>bb.getForums</methodName> 658 * <params> 659 * <param><value><string>joeblow</string></value></param> 660 * <param><value><string>123password</string></value></param> 661 * <param><value><string>first-forum</string></value></param> 662 * </params> 663 * </methodCall> 664 * 665 * XML-RPC request to get all child forums in the forum with id number 34 no more than 2 forums deep in the hierarchy 666 * <methodCall> 667 * <methodName>bb.getForums</methodName> 668 * <params> 669 * <param><value><string>joeblow</string></value></param> 670 * <param><value><string>123password</string></value></param> 671 * <param><value><int>34</int></value></param> 672 * <param><value><int>2</int></value></param> 673 * </params> 674 * </methodCall> 675 */ 676 function bb_getForums( $args ) 677 { 678 do_action( 'bb_xmlrpc_call', 'bb.getForums' ); 679 680 // Escape args 681 $this->escape( $args ); 682 683 // Get the login credentials 684 $username = $args[0]; 685 $password = (string) $args[1]; 686 687 // Check the user is valid 688 if ( $this->auth_readonly ) { 689 $user = $this->authenticate( $username, $password ); 690 } 691 692 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getForums' ); 693 694 // If an error was raised by authentication or by an action then return it 695 if ( $this->error ) { 696 return $this->error; 697 } 698 699 // Setup an array to store arguments to pass to bb_get_forums() function 700 $get_forums_args = array( 701 'child_of' => 0, 702 'hierarchical' => 0, 703 'depth' => 0 704 ); 705 706 // Can be numeric id or slug 707 $forum_id = isset( $args[2] ) ? $args[2] : false; 708 709 if ( $forum_id ) { 710 // Check for bad data 711 if ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) { 712 $this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) ); 713 return $this->error; 714 } 715 // First check the requested forum exists 716 if ( !$forum = bb_get_forum( $forum_id ) ) { 717 $this->error = new IXR_Error( 400, __( 'The forum does not exist.' ) ); 718 return $this->error; 719 } 720 // Add the specific forum to the arguments 721 $get_forums_args['child_of'] = (int) $forum->forum_id; 722 } 723 724 // Can only be an integer 725 $depth = (int) $args[3]; 726 727 if ( $depth > 0 ) { 728 // Add the depth to traverse to to the arguments 729 $get_forums_args['depth'] = $depth; 730 // Only make it hierarchical if the depth > 1 731 if ( $depth > 1 ) { 732 $get_forums_args['hierarchical'] = 1; 733 } 734 } 735 736 // Get the forums. Return an error when no forums exist 737 if ( !$forums = bb_get_forums( $get_forums_args ) ) { 738 $this->error = new IXR_Error( 404, __( 'No forums found.' ) ); 739 return $this->error; 740 } 741 742 // Only include "safe" data in the array 743 $_forums = array(); 744 foreach ( $forums as $forum ) { 745 $_forums[] = $this->prepare_forum( $forum ); 746 } 747 748 do_action( 'bb_xmlrpc_call_return', 'bb.getForums' ); 749 750 // Return the forums 751 return $_forums; 752 } 753 754 /** 755 * Returns details of a forum 756 * 757 * @since 1.0 758 * @return array|object An array containing details of the returned forum when successfully executed or an IXR_Error object on failure 759 * @param string $args[0] The username for authentication 760 * @param string $args[1] The password for authentication 761 * @param integer|string $args[2] The forum's id or slug 762 * 763 * XML-RPC request to get the forum with id number 34 764 * <methodCall> 765 * <methodName>bb.getForum</methodName> 766 * <params> 767 * <param><value><string>joeblow</string></value></param> 768 * <param><value><string>123password</string></value></param> 769 * <param><value><int>34</int></value></param> 770 * </params> 771 * </methodCall> 772 * 773 * XML-RPC request to get the forum with slug "first-forum" 774 * <methodCall> 775 * <methodName>bb.getForum</methodName> 776 * <params> 777 * <param><value><string>joeblow</string></value></param> 778 * <param><value><string>123password</string></value></param> 779 * <param><value><string>first-forum</string></value></param> 780 * </params> 781 * </methodCall> 782 */ 783 function bb_getForum( $args ) 784 { 785 do_action( 'bb_xmlrpc_call', 'bb.getForum' ); 786 787 // Escape args 788 $this->escape( $args ); 789 790 // Get the login credentials 791 $username = $args[0]; 792 $password = (string) $args[1]; 793 794 // Check the user is valid 795 if ( $this->auth_readonly ) { 796 $user = $this->authenticate( $username, $password ); 797 } 798 799 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getForum' ); 800 801 // If an error was raised by authentication or by an action then return it 802 if ( $this->error ) { 803 return $this->error; 804 } 805 806 // Can be numeric id or slug 807 $forum_id = isset( $args[2] ) ? $args[2] : false; 808 809 // Check for bad data 810 if ( !$forum_id || ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) ) { 811 $this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) ); 812 return $this->error; 813 } 814 815 // Check the requested forum exists 816 if ( !$forum = bb_get_forum( $forum_id ) ) { 817 $this->error = new IXR_Error( 404, __( 'No forum found.' ) ); 818 return $this->error; 819 } 820 821 // Only include "safe" data in the array 822 $forum = $this->prepare_forum( $forum ); 823 824 do_action( 'bb_xmlrpc_call_return', 'bb.getForum' ); 825 826 // Return the forums 827 return $forum; 828 } 829 830 /** 831 * Creates a new forum 832 * 833 * @since 1.0 834 * @return array|object The forum data when successfully created or an IXR_Error object on failure 835 * @param array $args Arguments passed by the XML-RPC call 836 * @param string $args[0] The username for authentication 837 * @param string $args[1] The password for authentication 838 * @param array $args[2] The values for the various settings in the new forum 839 * @param string $args[2]['name'] The name of the forum 840 * @param string $args[2]['description'] The description of the forum (optional) 841 * @param integer|string $args[2]['parent_id'] The unique id of the parent forum for this forum (optional) 842 * @param integer $args[2]['order'] The position of the forum in the forum list (optional) 843 * @param integer $args[2]['is_category'] Whether the forum is simply a container category (optional) 844 * 845 * XML-RPC request to create a new sub-forum called "A new forum" inside the parent forum with id 2 846 * <methodCall> 847 * <methodName>bb.newForum</methodName> 848 * <params> 849 * <param><value><string>joeblow</string></value></param> 850 * <param><value><string>123password</string></value></param> 851 * <param><value><struct> 852 * <member> 853 * <name>name</name> 854 * <value><string>A new forum</string></value> 855 * </member> 856 * <member> 857 * <name>parent_id</name> 858 * <value><integer>2</integer></value> 859 * </member> 860 * </struct></value></param> 861 * </params> 862 * </methodCall> 863 */ 864 function bb_newForum( $args ) 865 { 866 do_action( 'bb_xmlrpc_call', 'bb.newForum' ); 867 868 // Escape args 869 $this->escape( $args ); 870 871 // Get the login credentials 872 $username = $args[0]; 873 $password = (string) $args[1]; 874 875 // Check the user is valid 876 $user = $this->authenticate( $username, $password, 'manage_forums', __( 'You do not have permission to manage forums.' ) ); 877 878 do_action( 'bb_xmlrpc_call_authenticated', 'bb.newForum' ); 879 880 // If an error was raised by authentication or by an action then return it 881 if ( $this->error ) { 882 return $this->error; 883 } 884 885 // Make sure there is something for us to do 886 if ( !$args[2] || !is_array( $args[2] ) || !count( $args[2] ) ) { 887 $this->error = new IXR_Error( 400, __( 'The forum data is invalid.' ) ); 888 return $this->error; 889 } 890 891 $structure = (array) $args[2]; 892 893 // Minimum requirement is a name for the new forum 894 if ( !isset( $structure['name'] ) || !$structure['name'] ) { 895 $this->error = new IXR_Error( 400, __( 'The forum name is invalid.' ) ); 896 return $this->error; 897 } 898 899 // Inject structure into an array suitable for bb_new_forum() 900 $bb_new_forum_args = array( 901 'forum_name' => (string) $structure['name'], 902 'forum_desc' => (string) $structure['description'], 903 'forum_parent' => (int) $structure['parent_id'], 904 'forum_order' => (int) $structure['order'], 905 'forum_is_category' => (int) $structure['is_category'] 906 ); 907 908 // Remove empty settings so that changes to the defaults in bb_new_forum() are honoured 909 $bb_new_forum_args = array_filter( $bb_new_forum_args ); 910 911 // Leave the require until the very end 912 require_once ( BB_PATH . 'bb-admin/includes/functions.bb-admin.php' ); 913 914 // Create the forum 915 if ( !$forum_id = (int) bb_new_forum( $bb_new_forum_args ) ) { 916 $this->error = new IXR_Error( 500, __( 'The forum could not be created.' ) ); 917 return $this->error; 918 } 919 920 // Only include "safe" data in the array 921 $forum = $this->prepare_forum( bb_get_forum( $forum_id ) ); 922 923 do_action( 'bb_xmlrpc_call_return', 'bb.newForum' ); 924 925 return $forum; 926 } 927 928 /** 929 * Edits an existing forum 930 * 931 * @since 1.0 932 * @return array|object The forum data when successfully edited or an IXR_Error object on failure 933 * @param array $args Arguments passed by the XML-RPC call 934 * @param string $args[0] The username for authentication 935 * @param string $args[1] The password for authentication 936 * @param array $args[2] The values for the various settings in the new forum, at least one must be specified 937 * @param integer|string $args[2]['forum_id'] The unique id of the forum to be edited 938 * @param string $args[2]['name'] The name of the forum (optional) 939 * @param string $args[2]['slug'] The slug for the forum (optional) 940 * @param string $args[2]['description'] The description of the forum (optional) 941 * @param integer $args[2]['parent_id'] The unique id of the parent forum for this forum (optional) 942 * @param integer $args[2]['order'] The position of the forum in the forum list (optional) 943 * @param integer $args[2]['is_category'] Whether the forum is simply a container category (optional) 944 * 945 * XML-RPC request to edit a forum with id 11, changing the description 946 * <methodCall> 947 * <methodName>bb.editForum</methodName> 948 * <params> 949 * <param><value><string>joeblow</string></value></param> 950 * <param><value><string>123password</string></value></param> 951 * <param><value><struct> 952 * <member> 953 * <name>forum_id</name> 954 * <value><integer>11</integer></value> 955 * </member> 956 * <member> 957 * <name>description</name> 958 * <value><string>This is a great forum for all sorts of reasons.</string></value> 959 * </member> 960 * </struct></value></param> 961 * </params> 962 * </methodCall> 963 */ 964 function bb_editForum( $args ) 965 { 966 do_action( 'bb_xmlrpc_call', 'bb.editForum' ); 967 968 // Escape args 969 $this->escape( $args ); 970 971 // Get the login credentials 972 $username = $args[0]; 973 $password = (string) $args[1]; 974 975 // Check the user is valid 976 $user = $this->authenticate( $username, $password, 'manage_forums', __( 'You do not have permission to manage forums.' ) ); 977 978 do_action( 'bb_xmlrpc_call_authenticated', 'bb.editForum' ); 979 980 // If an error was raised by authentication or by an action then return it 981 if ( $this->error ) { 982 return $this->error; 983 } 984 985 // Make sure there is something for us to do 986 if ( !$args[2] || !is_array( $args[2] ) || !count( $args[2] ) ) { 987 $this->error = new IXR_Error( 400, __( 'The forum data is invalid.' ) ); 988 return $this->error; 989 } 990 991 $structure = (array) $args[2]; 992 993 // Can be numeric id or slug 994 $forum_id = isset( $structure['forum_id'] ) ? $structure['forum_id'] : false; 995 996 // Check for bad data 997 if ( !$forum_id || ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) ) { 998 $this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) ); 999 return $this->error; 1000 } 1001 1002 // Check the requested forum exists 1003 if ( !$forum = bb_get_forum( $forum_id ) ) { 1004 $this->error = new IXR_Error( 400, __( 'No forum found.' ) ); 1005 return $this->error; 1006 } 1007 1008 // Cast the forum object as an array 1009 $forum = (array) $forum; 1010 // The forum id may have been a slug, so make sure it's an integer here 1011 $forum_id = (int) $forum['forum_id']; 1012 1013 // Remove some unneeded indexes 1014 unset( $forum['topics'] ); 1015 unset( $forum['posts'] ); 1016 1017 // Add one if it isn't there 1018 if ( !isset( $forum['forum_is_category'] ) ) { 1019 $forum['forum_is_category'] = 0; 1020 } 1021 1022 // Validate the name for the forum 1023 if ( isset( $structure['name'] ) && !$structure['name'] ) { 1024 $this->error = new IXR_Error( 400, __( 'The forum name is invalid.' ) ); 1025 return $this->error; 1026 } 1027 1028 // Inject structure into an array suitable for bb_update_forum() 1029 $bb_update_forum_args = array( 1030 'forum_name' => $structure['name'] 1031 ); 1032 1033 // Slug cannot be blank 1034 if ( isset( $structure['slug'] ) && $structure['slug'] !== '' ) { 1035 $bb_update_forum_args['forum_slug'] = $structure['slug']; 1036 } 1037 1038 // Description can be nothing 1039 if ( isset( $structure['description'] ) ) { 1040 $bb_update_forum_args['forum_desc'] = $structure['description']; 1041 } 1042 1043 // Parent forum ID must be an integer and it can be 0 1044 if ( isset( $structure['parent_id'] ) && is_integer( $structure['parent_id'] ) ) { 1045 $bb_update_forum_args['forum_parent'] = $structure['parent_id']; 1046 } 1047 1048 // Order must be an integer and it can be 0 1049 if ( isset( $structure['order'] ) && is_integer( $structure['order'] ) ) { 1050 $bb_update_forum_args['forum_order'] = $structure['order']; 1051 } 1052 1053 // Category flag must be an integer and it can be 0 1054 if ( isset( $structure['is_category'] ) && is_integer( $structure['is_category'] ) ) { 1055 $bb_update_forum_args['forum_is_category'] = $structure['is_category']; 1056 } 1057 1058 // Merge the changes into the existing data for the forum 1059 $bb_update_forum_args = wp_parse_args( $bb_update_forum_args, $forum ); 1060 1061 // Leave the require until the very end 1062 require_once ( BB_PATH . 'bb-admin/includes/functions.bb-admin.php' ); 1063 1064 // Update the forum 1065 if ( !bb_update_forum( $bb_update_forum_args ) ) { 1066 $this->error = new IXR_Error( 500, __( 'The forum could not be edited.' ) ); 1067 return $this->error; 1068 } 1069 1070 // Only include "safe" data in the array 1071 $forum = $this->prepare_forum( bb_get_forum( $forum_id ) ); 1072 1073 do_action( 'bb_xmlrpc_call_return', 'bb.editForum' ); 1074 1075 return $forum; 1076 } 1077 1078 /** 1079 * Deletes a forum 1080 * 1081 * @since 1.0 1082 * @return integer|object 1 when successfully deleted or an IXR_Error object on failure 1083 * @param array $args Arguments passed by the XML-RPC call 1084 * @param string $args[0] The username for authentication 1085 * @param string $args[1] The password for authentication 1086 * @param integer|string $args[2] The unique id of the forum to be deleted 1087 * 1088 * XML-RPC request to delete a forum with the slug "naughty-forum" 1089 * <methodCall> 1090 * <methodName>bb.deleteForum</methodName> 1091 * <params> 1092 * <param><value><string>joeblow</string></value></param> 1093 * <param><value><string>123password</string></value></param> 1094 * <param><value><string>naughty-forum</string></value></param> 1095 * </params> 1096 * </methodCall> 1097 */ 1098 function bb_deleteForum( $args ) 1099 { 1100 do_action( 'bb_xmlrpc_call', 'bb.deleteForum' ); 1101 1102 // Escape args 1103 $this->escape( $args ); 1104 1105 // Get the login credentials 1106 $username = $args[0]; 1107 $password = (string) $args[1]; 1108 1109 // Check the user is valid 1110 $user = $this->authenticate( $username, $password, 'delete_forums', __( 'You do not have permission to delete forums.' ) ); 1111 1112 do_action( 'bb_xmlrpc_call_authenticated', 'bb.deleteForum' ); 1113 1114 // If an error was raised by authentication or by an action then return it 1115 if ( $this->error ) { 1116 return $this->error; 1117 } 1118 1119 // Can be numeric id or slug 1120 $forum_id = isset( $args[2] ) ? $args[2] : false; 1121 1122 // Check for bad data 1123 if ( !$forum_id || ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) ) { 1124 $this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) ); 1125 return $this->error; 1126 } 1127 1128 // Check the requested forum exists 1129 if ( !$forum = bb_get_forum( $forum_id ) ) { 1130 $this->error = new IXR_Error( 400, __( 'No forum found.' ) ); 1131 return $this->error; 1132 } 1133 1134 // Cast the forum object as an array 1135 $forum = (array) $forum; 1136 // The forum id may have been a slug, so make sure it's an integer here 1137 $forum_id = (int) $forum['forum_id']; 1138 1139 // Make sure they are allowed to delete this forum specifically 1140 if ( !bb_current_user_can( 'delete_forum', $forum_id ) ) { 1141 $this->error = new IXR_Error( 403, __( 'You do not have permission to delete this forum.' ) ); 1142 return $this->error; 1143 } 1144 1145 // Leave the require until the very end 1146 require_once ( BB_PATH . 'bb-admin/includes/functions.bb-admin.php' ); 1147 1148 // Delete the forum 1149 if ( !bb_delete_forum( $forum_id ) ) { 1150 $this->error = new IXR_Error( 500, __( 'The forum could not be deleted.' ) ); 1151 return $this->error; 1152 } 1153 1154 $result = 1; 1155 1156 do_action( 'bb_xmlrpc_call_return', 'bb.deleteForum' ); 1157 1158 return $result; 1159 } 1160 1161 1162 1163 /** 1164 * bbPress publishing API - Topic XML-RPC methods 1165 */ 1166 1167 /** 1168 * Returns a numerical count of topics 1169 * 1170 * @since 1.0 1171 * @return integer|object The number of topics when successfully executed or an IXR_Error object on failure 1172 * @param array $args Arguments passed by the XML-RPC call 1173 * @param string $args[0] The username for authentication 1174 * @param string $args[1] The password for authentication 1175 * @param integer|string $args[2] The forum id or slug (optional) 1176 * 1177 * XML-RPC request to get a count of all topics in the bbPress instance 1178 * <methodCall> 1179 * <methodName>bb.getTopicCount</methodName> 1180 * <params> 1181 * <param><value><string>joeblow</string></value></param> 1182 * <param><value><string>123password</string></value></param> 1183 * </params> 1184 * </methodCall> 1185 * 1186 * XML-RPC request to get a count of all topics in the forum with id number 34 1187 * <methodCall> 1188 * <methodName>bb.getTopicCount</methodName> 1189 * <params> 1190 * <param><value><string>joeblow</string></value></param> 1191 * <param><value><string>123password</string></value></param> 1192 * <param><value><int>34</int></value></param> 1193 * </params> 1194 * </methodCall> 1195 * 1196 * XML-RPC request to get a count of all topics in the forum with slug "first-forum" 1197 * <methodCall> 1198 * <methodName>bb.getTopicCount</methodName> 1199 * <params> 1200 * <param><value><string>joeblow</string></value></param> 1201 * <param><value><string>123password</string></value></param> 1202 * <param><value><string>first-forum</string></value></param> 1203 * </params> 1204 * </methodCall> 1205 */ 1206 function bb_getTopicCount( $args ) 1207 { 1208 do_action( 'bb_xmlrpc_call', 'bb.getTopicCount' ); 1209 1210 // Escape args 1211 $this->escape( $args ); 1212 1213 // Get the login credentials 1214 $username = $args[0]; 1215 $password = (string) $args[1]; 1216 1217 // Check the user is valid 1218 if ( $this->auth_readonly ) { 1219 $user = $this->authenticate( $username, $password ); 1220 } 1221 1222 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getTopicCount' ); 1223 1224 // If an error was raised by authentication or by an action then return it 1225 if ( $this->error ) { 1226 return $this->error; 1227 } 1228 1229 // Can be numeric id or slug 1230 if ( isset( $args[2] ) && $forum_id = $args[2] ) { 1231 // Check for bad data 1232 if ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) { 1233 $this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) ); 1234 return $this->error; 1235 } 1236 // Check the requested forum exists 1237 if ( !$forum = bb_get_forum( $forum_id ) ) { 1238 $this->error = new IXR_Error( 400, __( 'The forum does not exist.' ) ); 1239 return $this->error; 1240 } 1241 1242 // OK, let's trust the count in the forum table 1243 $count = (int) $forum->topics; 1244 } else { 1245 // Get all forums 1246 $forums = bb_get_forums(); 1247 1248 // Return an error when no forums exist 1249 if ( !$forums ) { 1250 $this->error = new IXR_Error( 400, __( 'No forums found.' ) ); 1251 return $this->error; 1252 } 1253 1254 // Count the topics 1255 $count = 0; 1256 foreach ( $forums as $forum ) { 1257 $count += (int) $forum->topics; 1258 } 1259 } 1260 1261 do_action( 'bb_xmlrpc_call_return', 'bb.getTopicCount' ); 1262 1263 // Return the count of topics 1264 return $count; 1265 } 1266 1267 /** 1268 * Returns details of the latest topics 1269 * 1270 * @since 1.0 1271 * @return array|object The topics when successfully executed or an IXR_Error object on failure 1272 * @param array $args Arguments passed by the XML-RPC call 1273 * @param string $args[0] The username for authentication 1274 * @param string $args[1] The password for authentication 1275 * @param integer|string $args[2] The forum id or slug (optional) 1276 * @param integer $args[3] The number of topics to return (optional) 1277 * @param integer $args[4] The number of the page to return (optional) 1278 * 1279 * XML-RPC request to get all topics in the bbPress instance 1280 * <methodCall> 1281 * <methodName>bb.getTopics</methodName> 1282 * <params> 1283 * <param><value><string>joeblow</string></value></param> 1284 * <param><value><string>123password</string></value></param> 1285 * </params> 1286 * </methodCall> 1287 * 1288 * XML-RPC request to get all topics in the forum with id number 34 1289 * <methodCall> 1290 * <methodName>bb.getTopics</methodName> 1291 * <params> 1292 * <param><value><string>joeblow</string></value></param> 1293 * <param><value><string>123password</string></value></param> 1294 * <param><value><int>34</int></value></param> 1295 * </params> 1296 * </methodCall> 1297 * 1298 * XML-RPC request to get topics 6 to 10 in the forum with slug "first-forum" 1299 * <methodCall> 1300 * <methodName>bb.getTopics</methodName> 1301 * <params> 1302 * <param><value><string>joeblow</string></value></param> 1303 * <param><value><string>123password</string></value></param> 1304 * <param><value><string>first-forum</string></value></param> 1305 * <param><value><int>5</int></value></param> 1306 * <param><value><int>2</int></value></param> 1307 * </params> 1308 * </methodCall> 1309 */ 1310 function bb_getTopics( $args ) 1311 { 1312 do_action( 'bb_xmlrpc_call', 'bb.getTopics' ); 1313 1314 // Escape args 1315 $this->escape( $args ); 1316 1317 // Get the login credentials 1318 $username = $args[0]; 1319 $password = (string) $args[1]; 1320 1321 // Check the user is valid 1322 if ( $this->auth_readonly ) { 1323 $user = $this->authenticate( $username, $password ); 1324 } 1325 1326 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getTopics' ); 1327 1328 // If an error was raised by authentication or by an action then return it 1329 if ( $this->error ) { 1330 return $this->error; 1331 } 1332 1333 // Setup an array to store arguments to pass to get_topics() function 1334 $get_topics_args = array( 1335 'forum' => false, 1336 'number' => false, 1337 'page' => false 1338 ); 1339 1340 // Can be numeric id or slug 1341 if ( isset( $args[2] ) && $forum_id = $args[2] ) { 1342 // Check for bad data 1343 if ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) { 1344 $this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) ); 1345 return $this->error; 1346 } 1347 // Check the requested forum exists 1348 if ( !$forum = bb_get_forum( $forum_id ) ) { 1349 $this->error = new IXR_Error( 400, __( 'The forum does not exist.' ) ); 1350 return $this->error; 1351 } 1352 1353 // The forum id may have been a slug, so make sure it's an integer here 1354 $get_topics_args['forum'] = (int) $forum->forum_id; 1355 } 1356 1357 // Can only be an integer 1358 if ( isset( $args[3] ) && $number = (int) $args[3] ) { 1359 $get_topics_args['number'] = $number; 1360 } 1361 1362 // Can only be an integer 1363 if ( isset( $args[4] ) && $page = (int) $args[4] ) { 1364 $get_topics_args['page'] = $page; 1365 } 1366 1367 // Get the topics 1368 if ( !$topics = get_latest_topics( $get_topics_args ) ) { 1369 $this->error = new IXR_Error( 400, __( 'No topics found.' ) ); 1370 return $this->error; 1371 } 1372 1373 // Only include "safe" data in the array 1374 $_topics = array(); 1375 foreach ( $topics as $topic ) { 1376 $_topics[] = $this->prepare_topic( $topic ); 1377 } 1378 1379 do_action( 'bb_xmlrpc_call_return', 'bb.getTopics' ); 1380 1381 // Return the topics 1382 return $_topics; 1383 } 1384 1385 /** 1386 * Returns details of a topic 1387 * 1388 * @since 1.0 1389 * @return array|object An array containing details of the returned topic when successfully executed or an IXR_Error object on failure 1390 * @param string $args[0] The username for authentication 1391 * @param string $args[1] The password for authentication 1392 * @param integer|string $args[2] The topic's id or slug 1393 * 1394 * XML-RPC request to get the topic with id number 105 1395 * <methodCall> 1396 * <methodName>bb.getTopic</methodName> 1397 * <params> 1398 * <param><value><string>joeblow</string></value></param> 1399 * <param><value><string>123password</string></value></param> 1400 * <param><value><int>105</int></value></param> 1401 * </params> 1402 * </methodCall> 1403 * 1404 * XML-RPC request to get the topic with slug "cheesy-biscuits" 1405 * <methodCall> 1406 * <methodName>bb.getTopic</methodName> 1407 * <params> 1408 * <param><value><string>joeblow</string></value></param> 1409 * <param><value><string>123password</string></value></param> 1410 * <param><value><string>cheesy-biscuits</string></value></param> 1411 * </params> 1412 * </methodCall> 1413 */ 1414 function bb_getTopic( $args ) 1415 { 1416 do_action( 'bb_xmlrpc_call', 'bb.getTopic' ); 1417 1418 // Escape args 1419 $this->escape( $args ); 1420 1421 // Get the login credentials 1422 $username = $args[0]; 1423 $password = (string) $args[1]; 1424 1425 // Check the user is valid 1426 if ( $this->auth_readonly ) { 1427 $user = $this->authenticate( $username, $password ); 1428 } 1429 1430 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getTopic' ); 1431 1432 // If an error was raised by authentication or by an action then return it 1433 if ( $this->error ) { 1434 return $this->error; 1435 } 1436 1437 // Can be numeric id or slug 1438 $topic_id = isset( $args[2] ) ? $args[2] : false; 1439 1440 // Check for bad data 1441 if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) { 1442 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 1443 return $this->error; 1444 } 1445 1446 // Check the requested topic exists 1447 if ( !$topic = get_topic( $topic_id ) ) { 1448 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 1449 return $this->error; 1450 } 1451 1452 // Only include "safe" data in the array 1453 $topic = $this->prepare_topic( $topic ); 1454 1455 do_action( 'bb_xmlrpc_call_return', 'bb.getTopic' ); 1456 1457 // Return the topic 1458 return $topic; 1459 } 1460 1461 /** 1462 * Creates a new topic 1463 * 1464 * @since 1.0 1465 * @return array|object The topic data when successfully created or an IXR_Error object on failure 1466 * @param array $args Arguments passed by the XML-RPC call 1467 * @param string $args[0] The username for authentication 1468 * @param string $args[1] The password for authentication 1469 * @param array $args[2] The values for the various parameters in the new topic 1470 * @param string $args[2]['title'] The title of the topic 1471 * @param string $args[2]['text'] The text of the topic 1472 * @param integer|string $args[2]['forum_id'] The unique id of the forum which will contain this topic, slugs are OK to use too 1473 * @param string|array $args[2]['tags'] A comma delimited string or an array of tags to add to the topic (optional) 1474 * 1475 * XML-RPC request to create a new topic called "Insane monkeys" inside the forum with id 2 1476 * <methodCall> 1477 * <methodName>bb.newTopic</methodName> 1478 * <params> 1479 * <param><value><string>joeblow</string></value></param> 1480 * <param><value><string>123password</string></value></param> 1481 * <param><value><struct> 1482 * <member> 1483 * <name>title</name> 1484 * <value><string>Insane monkeys</string></value> 1485 * </member> 1486 * <member> 1487 * <name>text</name> 1488 * <value><string>I just saw some insane monkeys eating bananas, did anyone else see that?</string></value> 1489 * </member> 1490 * <member> 1491 * <name>forum_id</name> 1492 * <value><integer>2</integer></value> 1493 * </member> 1494 * <member> 1495 * <name>tags</name> 1496 * <value><string>monkeys, bananas</string></value> 1497 * </member> 1498 * </struct></value></param> 1499 * </params> 1500 * </methodCall> 1501 */ 1502 function bb_newTopic( $args ) 1503 { 1504 do_action( 'bb_xmlrpc_call', 'bb.newTopic' ); 1505 1506 // Escape args 1507 $this->escape( $args ); 1508 1509 // Get the login credentials 1510 $username = $args[0]; 1511 $password = (string) $args[1]; 1512 1513 // Check the user is valid 1514 $user = $this->authenticate( $username, $password, 'write_topics', __( 'You do not have permission to write topics.' ) ); 1515 1516 // Additionally they need to be able to write posts 1517 if ( !$this->error && !bb_current_user_can( 'write_posts' ) ) { 1518 $this->error = new IXR_Error( 403, __( 'You do not have permission to write posts.' ) ); 1519 } 1520 1521 do_action( 'bb_xmlrpc_call_authenticated', 'bb.newTopic' ); 1522 1523 // If an error was raised by authentication or by an action then return it 1524 if ( $this->error ) { 1525 return $this->error; 1526 } 1527 1528 // Make sure there is something for us to do 1529 if ( !$args[2] || !is_array( $args[2] ) || !count( $args[2] ) ) { 1530 $this->error = new IXR_Error( 400, __( 'The topic data is invalid.' ) ); 1531 return $this->error; 1532 } 1533 1534 $structure = (array) $args[2]; 1535 1536 // Can be numeric id or slug 1537 $forum_id = isset( $structure['forum_id'] ) ? $structure['forum_id'] : false; 1538 1539 // Check for bad data 1540 if ( !$forum_id || ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) ) { 1541 $this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) ); 1542 return $this->error; 1543 } 1544 1545 // Check the requested forum exists 1546 if ( !$forum = bb_get_forum( $forum_id ) ) { 1547 $this->error = new IXR_Error( 400, __( 'No forum found.' ) ); 1548 return $this->error; 1549 } 1550 1551 // The forum id may have been a slug, so make sure it's an integer here 1552 $forum_id = (int) $forum->forum_id; 1553 1554 // Make sure they are allowed to write topics to this forum 1555 if ( !bb_current_user_can( 'write_topic', $forum_id ) ) { 1556 $this->error = new IXR_Error( 403, __( 'You do not have permission to write topics to this forum.' ) ); 1557 return $this->error; 1558 } 1559 1560 // The topic requires a title 1561 if ( !isset( $structure['title'] ) || !$structure['title'] ) { 1562 $this->error = new IXR_Error( 400, __( 'The topic title is invalid.' ) ); 1563 return $this->error; 1564 } 1565 1566 // The topic requires text 1567 if ( !isset( $structure['text'] ) || !$structure['text'] ) { 1568 $this->error = new IXR_Error( 400, __( 'The topic text is invalid.' ) ); 1569 return $this->error; 1570 } 1571 1572 // Inject structure into an array suitable for bb_insert_topic() 1573 $bb_insert_topic_args = array( 1574 'topic_title' => (string) $structure['title'], 1575 'forum_id' => $forum_id, 1576 'tags' => (string) trim( $structure['tags'] ) 1577 ); 1578 1579 // Remove empty settings so that changes to the defaults in bb_insert_topic() are honoured 1580 $bb_insert_topic_args = array_filter( $bb_insert_topic_args ); 1581 1582 // Create the topic 1583 if ( !$topic_id = bb_insert_topic( $bb_insert_topic_args ) ) { 1584 $this->error = new IXR_Error( 500, __( 'The topic could not be created.' ) ); 1585 return $this->error; 1586 } 1587 1588 // Inject structure into an array suitable for bb_insert_post() 1589 $bb_insert_post_args = array( 1590 'topic_id' => (int) $topic_id, 1591 'post_text' => (string) $structure['text'] 1592 ); 1593 1594 // Create the post 1595 if ( !$post_id = bb_insert_post( $bb_insert_post_args ) ) { 1596 $this->error = new IXR_Error( 500, __( 'The post could not be created.' ) ); 1597 return $this->error; 1598 } 1599 1600 // Only include "safe" data in the array 1601 $topic = $this->prepare_topic( get_topic( $topic_id ) ); 1602 1603 do_action( 'bb_xmlrpc_call_return', 'bb.newTopic' ); 1604 1605 return $topic; 1606 } 1607 1608 /** 1609 * Edits an existing topic 1610 * 1611 * @since 1.0 1612 * @return array|object The topic data when successfully edited or an IXR_Error object on failure 1613 * @param array $args Arguments passed by the XML-RPC call 1614 * @param string $args[0] The username for authentication 1615 * @param string $args[1] The password for authentication 1616 * @param array $args[2] The values for the various parameters in the edited topic 1617 * @param integer|string $args[2]['topic_id'] The topic's id or slug 1618 * @param string $args[2]['title'] The title of the topic 1619 * @param string $args[2]['text'] The text of the topic 1620 * 1621 * XML-RPC request to edit the title of a topic with the slug "insane-monkeys" 1622 * <methodCall> 1623 * <methodName>bb.editTopic</methodName> 1624 * <params> 1625 * <param><value><string>joeblow</string></value></param> 1626 * <param><value><string>123password</string></value></param> 1627 * <param><value><struct> 1628 * <member> 1629 * <name>topic_id</name> 1630 * <value><string>insane-monkeys</string></value> 1631 * </member> 1632 * <member> 1633 * <name>title</name> 1634 * <value><string>Very insane monkeys</string></value> 1635 * </member> 1636 * </struct></value></param> 1637 * </params> 1638 * </methodCall> 1639 */ 1640 function bb_editTopic( $args ) 1641 { 1642 do_action( 'bb_xmlrpc_call', 'bb.editTopic' ); 1643 1644 // Escape args 1645 $this->escape( $args ); 1646 1647 // Get the login credentials 1648 $username = $args[0]; 1649 $password = (string) $args[1]; 1650 1651 // Check the user is valid 1652 $user = $this->authenticate( $username, $password, 'edit_topics', __( 'You do not have permission to edit topics.' ) ); 1653 1654 // Additionally they need to be able to edit posts 1655 if ( !$this->error && !bb_current_user_can( 'edit_posts' ) ) { 1656 $this->error = new IXR_Error( 403, __( 'You do not have permission to edit posts.' ) ); 1657 } 1658 1659 do_action( 'bb_xmlrpc_call_authenticated', 'bb.editTopic' ); 1660 1661 // If an error was raised by authentication or by an action then return it 1662 if ( $this->error ) { 1663 return $this->error; 1664 } 1665 1666 // Make sure there is something for us to do 1667 if ( !$args[2] || !is_array( $args[2] ) || !count( $args[2] ) ) { 1668 $this->error = new IXR_Error( 400, __( 'The topic data is invalid.' ) ); 1669 return $this->error; 1670 } 1671 1672 $structure = (array) $args[2]; 1673 1674 // Can be numeric id or slug 1675 $topic_id = isset( $structure['topic_id'] ) ? $structure['topic_id'] : false; 1676 1677 // Check for bad data 1678 if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) { 1679 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 1680 return $this->error; 1681 } 1682 1683 // Check the requested topic exists 1684 if ( !$topic = get_topic( $topic_id ) ) { 1685 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 1686 return $this->error; 1687 } 1688 1689 // The topic id may have been a slug, so make sure it's an integer here 1690 $topic_id = (int) $topic->topic_id; 1691 1692 // Make sure they are allowed to edit this topic 1693 if ( !bb_current_user_can( 'edit_topic', $topic_id ) ) { 1694 $this->error = new IXR_Error( 403, __( 'You do not have permission to edit this topic.' ) ); 1695 return $this->error; 1696 } 1697 1698 // Get the first post in the topic (that's where the content is) 1699 if ( !$post = bb_get_first_post( $topic_id ) ) { 1700 $this->error = new IXR_Error( 400, __( 'No posts found.' ) ); 1701 return $this->error; 1702 } 1703 1704 $post_id = (int) $post->post_id; 1705 1706 // Make sure they are allowed to edit this post 1707 if ( !bb_current_user_can( 'edit_post', $post_id ) ) { 1708 $this->error = new IXR_Error( 403, __( 'You do not have permission to edit this post.' ) ); 1709 return $this->error; 1710 } 1711 1712 // The topic requires a title 1713 if ( isset( $structure['title'] ) && !$structure['title'] ) { 1714 $this->error = new IXR_Error( 400, __( 'The topic title is invalid.' ) ); 1715 return $this->error; 1716 } 1717 1718 // The topic requires text 1719 if ( isset( $structure['text'] ) && !$structure['text'] ) { 1720 $this->error = new IXR_Error( 400, __( 'The topic text is invalid.' ) ); 1721 return $this->error; 1722 } 1723 1724 if ( $structure['title'] ) { 1725 if ( !bb_insert_topic( array( 'topic_title' => (string) $structure['title'], 'topic_id' => $topic_id ) ) ) { 1726 $this->error = new IXR_Error( 500, __( 'The topic could not be edited.' ) ); 1727 return $this->error; 1728 } 1729 } 1730 1731 if ( $structure['text'] ) { 1732 if ( !bb_insert_post( array( 'post_text' => (string) $structure['text'], 'post_id' => $post_id, 'topic_id'=> $topic_id ) ) ) { 1733 $this->error = new IXR_Error( 500, __( 'The post could not be edited.' ) ); 1734 return $this->error; 1735 } 1736 } 1737 1738 // Only include "safe" data in the array 1739 $topic = $this->prepare_topic( get_topic( $topic_id ) ); 1740 1741 do_action( 'bb_xmlrpc_call_return', 'bb.editTopic' ); 1742 1743 return $topic; 1744 } 1745 1746 /** 1747 * Deletes a topic 1748 * 1749 * @since 1.0 1750 * @return integer|object 0 if already changed, 1 when successfully changed or an IXR_Error object on failure 1751 * @param array $args Arguments passed by the XML-RPC call 1752 * @param string $args[0] The username for authentication 1753 * @param string $args[1] The password for authentication 1754 * @param integer|string $args[2] The unique id of the topic to be deleted 1755 * @param integer $args[3] 1 deletes the topic, 0 undeletes the topic 1756 * 1757 * XML-RPC request to delete a topic with id of 34 1758 * <methodCall> 1759 * <methodName>bb.deleteTopic</methodName> 1760 * <params> 1761 * <param><value><string>joeblow</string></value></param> 1762 * <param><value><string>123password</string></value></param> 1763 * <param><value><integer>34</integer></value></param> 1764 * </params> 1765 * </methodCall> 1766 */ 1767 function bb_deleteTopic( $args ) 1768 { 1769 do_action( 'bb_xmlrpc_call', 'bb.deleteTopic' ); 1770 1771 // Escape args 1772 $this->escape( $args ); 1773 1774 // Get the login credentials 1775 $username = $args[0]; 1776 $password = (string) $args[1]; 1777 1778 // Check the user is valid 1779 $user = $this->authenticate( $username, $password, 'delete_topics', __( 'You do not have permission to delete topics.' ) ); 1780 1781 do_action( 'bb_xmlrpc_call_authenticated', 'bb.deleteTopic' ); 1782 1783 // If an error was raised by authentication or by an action then return it 1784 if ( $this->error ) { 1785 return $this->error; 1786 } 1787 1788 // Can be numeric id or slug 1789 $topic_id = isset( $args[2] ) ? $args[2] : false; 1790 1791 // Check for bad data 1792 if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) { 1793 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 1794 return $this->error; 1795 } 1796 1797 // Check the requested topic exists 1798 if ( !$topic = get_topic( $topic_id ) ) { 1799 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 1800 return $this->error; 1801 } 1802 1803 // The topic id may have been a slug, so make sure it's an integer here 1804 $topic_id = (int) $topic->topic_id; 1805 1806 $delete = isset( $args[3] ) ? (int) $args[3] : 1; 1807 1808 // Don't do anything if already set that way 1809 if ( $delete === (int) $topic->topic_status ) { 1810 return 0; 1811 } 1812 1813 // Make sure they are allowed to delete this topic 1814 if ( !bb_current_user_can( 'delete_topic', $topic_id ) ) { 1815 $this->error = new IXR_Error( 403, __( 'You do not have permission to delete this topic.' ) ); 1816 return $this->error; 1817 } 1818 1819 // Delete the topic 1820 if ( !bb_delete_topic( $topic_id, $delete ) ) { 1821 $this->error = new IXR_Error( 500, __( 'The topic could not be deleted.' ) ); 1822 return $this->error; 1823 } 1824 1825 $result = 1; 1826 1827 do_action( 'bb_xmlrpc_call_return', 'bb.deleteTopic' ); 1828 1829 return $result; 1830 } 1831 1832 /** 1833 * Moves a topic to a different forum 1834 * 1835 * @since 1.0 1836 * @return integer|object the forum id where the topic lives after the method is called or an IXR_Error object on failure 1837 * @param array $args Arguments passed by the XML-RPC call 1838 * @param string $args[0] The username for authentication 1839 * @param string $args[1] The password for authentication 1840 * @param integer|string $args[2] The unique id of the topic to be moved 1841 * @param integer|string $args[3] The unique id of the forum to be moved to 1842 * 1843 * XML-RPC request to move the topic with id of 34 to forum with slug of "better-forum" 1844 * <methodCall> 1845 * <methodName>bb.moveTopic</methodName> 1846 * <params> 1847 * <param><value><string>joeblow</string></value></param> 1848 * <param><value><string>123password</string></value></param> 1849 * <param><value><integer>34</integer></value></param> 1850 * <param><value><string>better-forum</string></value></param> 1851 * </params> 1852 * </methodCall> 1853 */ 1854 function bb_moveTopic( $args ) 1855 { 1856 do_action( 'bb_xmlrpc_call', 'bb.moveTopic' ); 1857 1858 // Escape args 1859 $this->escape( $args ); 1860 1861 // Get the login credentials 1862 $username = $args[0]; 1863 $password = (string) $args[1]; 1864 1865 // Check the user is valid 1866 $user = $this->authenticate( $username, $password, 'move_topics', __( 'You do not have permission to move topics.' ) ); 1867 1868 do_action( 'bb_xmlrpc_call_authenticated', 'bb.moveTopic' ); 1869 1870 // If an error was raised by authentication or by an action then return it 1871 if ( $this->error ) { 1872 return $this->error; 1873 } 1874 1875 // Can be numeric id or slug 1876 $topic_id = isset( $args[2] ) ? $args[2] : false; 1877 1878 // Check for bad data 1879 if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) { 1880 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 1881 return $this->error; 1882 } 1883 1884 // Check the requested topic exists 1885 if ( !$topic = get_topic( $topic_id ) ) { 1886 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 1887 return $this->error; 1888 } 1889 1890 // The topic id may have been a slug, so make sure it's an integer here 1891 $topic_id = (int) $topic->topic_id; 1892 1893 // Can be numeric id or slug 1894 $forum_id = isset( $args[3] ) ? $args[3] : false; 1895 1896 // Check for bad data 1897 if ( !$forum_id || ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) ) { 1898 $this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) ); 1899 return $this->error; 1900 } 1901 1902 // Check the requested topic exists 1903 if ( !$forum = bb_get_forum( $forum_id ) ) { 1904 $this->error = new IXR_Error( 400, __( 'No forum found.' ) ); 1905 return $this->error; 1906 } 1907 1908 // The forum id may have been a slug, so make sure it's an integer here 1909 $forum_id = (int) $forum->forum_id; 1910 1911 // Only move it if it isn't already there 1912 if ( $forum_id !== (int) $topic->forum_id ) { 1913 // Make sure they are allowed to move this topic specifically to this forum 1914 if ( !bb_current_user_can( 'move_topic', $topic_id, $forum_id ) ) { 1915 $this->error = new IXR_Error( 403, __( 'You are not allowed to move this topic to this forum.' ) ); 1916 return $this->error; 1917 } 1918 1919 // Move the topic 1920 if ( !bb_move_topic( $topic_id, $forum_id ) ) { 1921 $this->error = new IXR_Error( 500, __( 'The topic could not be moved.' ) ); 1922 return $this->error; 1923 } 1924 } 1925 1926 do_action( 'bb_xmlrpc_call_return', 'bb.moveTopic' ); 1927 1928 return $forum_id; 1929 } 1930 1931 /** 1932 * Sticks a topic to the top of a forum or the front page 1933 * 1934 * @since 1.0 1935 * @return integer|object 0 if it is already stuck to the desired location, 1 when successfully stuck or an IXR_Error object on failure 1936 * @param array $args Arguments passed by the XML-RPC call 1937 * @param string $args[0] The username for authentication 1938 * @param string $args[1] The password for authentication 1939 * @param integer|string $args[2] The unique id of the topic to be stuck 1940 * @param integer $args[3] 0 unsticks, 1 sticks, 2 sticks to front (optional) 1941 * 1942 * XML-RPC request to stick the topic with id of 34 to the front page 1943 * <methodCall> 1944 * <methodName>bb.stickTopic</methodName> 1945 * <params> 1946 * <param><value><string>joeblow</string></value></param> 1947 * <param><value><string>123password</string></value></param> 1948 * <param><value><integer>34</integer></value></param> 1949 * <param><value><integer>1</integer></value></param> 1950 * </params> 1951 * </methodCall> 1952 */ 1953 function bb_stickTopic( $args ) 1954 { 1955 do_action( 'bb_xmlrpc_call', 'bb.stickTopic' ); 1956 1957 // Escape args 1958 $this->escape( $args ); 1959 1960 // Get the login credentials 1961 $username = $args[0]; 1962 $password = (string) $args[1]; 1963 1964 // Check the user is valid 1965 $user = $this->authenticate( $username, $password, 'stick_topics', __( 'You do not have permission to stick topics.' ) ); 1966 1967 do_action( 'bb_xmlrpc_call_authenticated', 'bb.stickTopic' ); 1968 1969 // If an error was raised by authentication or by an action then return it 1970 if ( $this->error ) { 1971 return $this->error; 1972 } 1973 1974 // Can be numeric id or slug 1975 $topic_id = isset( $args[2] ) ? $args[2] : false; 1976 1977 // Check for bad data 1978 if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) { 1979 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 1980 return $this->error; 1981 } 1982 1983 // Check the requested topic exists 1984 if ( !$topic = get_topic( $topic_id ) ) { 1985 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 1986 return $this->error; 1987 } 1988 1989 // The topic id may have been a slug, so make sure it's an integer here 1990 $topic_id = (int) $topic->topic_id; 1991 1992 // Make sure they are allowed to stick this topic 1993 if ( !bb_current_user_can( 'stick_topic', $topic_id ) ) { 1994 $this->error = new IXR_Error( 403, __( 'You do not have permission to stick this topic.' ) ); 1995 return $this->error; 1996 } 1997 1998 // Stick to where? 1999 $where = isset( $args[3] ) ? (int) $args[3] : 1; 2000 2001 // Forget it if it's already there 2002 if ( $where === (int) $topic->topic_sticky ) { 2003 return 0; 2004 } 2005 2006 // Stick the topic 2007 if ( !bb_stick_topic( $topic_id, $where ) ) { 2008 $this->error = new IXR_Error( 500, __( 'The topic could not be stuck.' ) ); 2009 return $this->error; 2010 } 2011 2012 $result = 1; 2013 2014 do_action( 'bb_xmlrpc_call_return', 'bb.stickTopic' ); 2015 2016 return $result; 2017 } 2018 2019 2020 2021 /** 2022 * Closes a topic 2023 * 2024 * @since 1.0 2025 * @return integer|object 0 when already changed, 1 when successfully changed or an IXR_Error object on failure 2026 * @param array $args Arguments passed by the XML-RPC call 2027 * @param string $args[0] The username for authentication 2028 * @param string $args[1] The password for authentication 2029 * @param integer|string $args[2] The unique id of the topic to be closed 2030 * @param integer $args[2] 0 closes, 1 opens (optional) 2031 * 2032 * XML-RPC request to close the topic with slug of "really-old-topic" 2033 * <methodCall> 2034 * <methodName>bb.closeTopic</methodName> 2035 * <params> 2036 * <param><value><string>joeblow</string></value></param> 2037 * <param><value><string>123password</string></value></param> 2038 * <param><value><string>really-old-topic</string></value></param> 2039 * </params> 2040 * </methodCall> 2041 * 2042 * XML-RPC request to open the topic with slug of "really-old-topic" 2043 * <methodCall> 2044 * <methodName>bb.closeTopic</methodName> 2045 * <params> 2046 * <param><value><string>joeblow</string></value></param> 2047 * <param><value><string>123password</string></value></param> 2048 * <param><value><string>really-old-topic</string></value></param> 2049 * <param><value><integer>1</integer></value></param> 2050 * </params> 2051 * </methodCall> 2052 */ 2053 function bb_closeTopic( $args ) 2054 { 2055 do_action( 'bb_xmlrpc_call', 'bb.closeTopic' ); 2056 2057 // Escape args 2058 $this->escape( $args ); 2059 2060 // Get the login credentials 2061 $username = $args[0]; 2062 $password = (string) $args[1]; 2063 2064 // Check the user is valid 2065 $user = $this->authenticate( $username, $password, 'close_topics', __( 'You do not have permission to close topics.' ) ); 2066 2067 do_action( 'bb_xmlrpc_call_authenticated', 'bb.closeTopic' ); 2068 2069 // If an error was raised by authentication or by an action then return it 2070 if ( $this->error ) { 2071 return $this->error; 2072 } 2073 2074 // Can be numeric id or slug 2075 $topic_id = isset( $args[2] ) ? $args[2] : false; 2076 2077 // Check for bad data 2078 if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) { 2079 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 2080 return $this->error; 2081 } 2082 2083 // Check the requested topic exists 2084 if ( !$topic = get_topic( $topic_id ) ) { 2085 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 2086 return $this->error; 2087 } 2088 2089 // The topic id may have been a slug, so make sure it's an integer here 2090 $topic_id = (int) $topic->topic_id; 2091 2092 // Make sure they are allowed to close this topic 2093 if ( !bb_current_user_can( 'close_topic', $topic_id ) ) { 2094 $this->error = new IXR_Error( 403, __( 'You do not have permission to close this topic.' ) ); 2095 return $this->error; 2096 } 2097 2098 // Open or close? 2099 $close = isset( $args[3] ) ? (int) $args[3] : 0; 2100 2101 // Forget it if it's already matching 2102 if ( $close === (int) $topic->topic_open ) { 2103 return 0; 2104 } 2105 2106 // Close the topic 2107 if ( !$close && !bb_close_topic( $topic_id ) ) { 2108 $this->error = new IXR_Error( 500, __( 'The topic could not be closed.' ) ); 2109 return $this->error; 2110 } 2111 2112 // Open the topic 2113 if ( $close && !bb_open_topic( $topic_id ) ) { 2114 $this->error = new IXR_Error( 500, __( 'The topic could not be opened.' ) ); 2115 return $this->error; 2116 } 2117 2118 $result = 1; 2119 2120 do_action( 'bb_xmlrpc_call_return', 'bb.closeTopic' ); 2121 2122 return $result; 2123 } 2124 2125 2126 2127 /** 2128 * bbPress publishing API - Post XML-RPC methods 2129 */ 2130 2131 /** 2132 * Returns a numerical count of posts 2133 * 2134 * @since 1.0 2135 * @return integer|object The number of topics when successfully executed or an IXR_Error object on failure 2136 * @param array $args Arguments passed by the XML-RPC call 2137 * @param string $args[0] The username for authentication 2138 * @param string $args[1] The password for authentication 2139 * @param integer|string $args[2] The topic id or slug 2140 * 2141 * XML-RPC request to get a count of all posts in the topic with slug "countable-topic" 2142 * <methodCall> 2143 * <methodName>bb.getPostCount</methodName> 2144 * <params> 2145 * <param><value><string>joeblow</string></value></param> 2146 * <param><value><string>123password</string></value></param> 2147 * <param><value><string>countable-topic</string></value></param> 2148 * </params> 2149 * </methodCall> 2150 */ 2151 function bb_getPostCount( $args ) 2152 { 2153 do_action( 'bb_xmlrpc_call', 'bb.getPostCount' ); 2154 2155 // Escape args 2156 $this->escape( $args ); 2157 2158 // Get the login credentials 2159 $username = $args[0]; 2160 $password = (string) $args[1]; 2161 2162 // Check the user is valid 2163 if ( $this->auth_readonly ) { 2164 $user = $this->authenticate( $username, $password ); 2165 } 2166 2167 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getPostCount' ); 2168 2169 // If an error was raised by authentication or by an action then return it 2170 if ( $this->error ) { 2171 return $this->error; 2172 } 2173 2174 // Can be numeric id or slug 2175 $topic_id = isset( $args[2] ) ? $args[2] : false; 2176 2177 // Check for bad data 2178 if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) { 2179 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 2180 return $this->error; 2181 } 2182 2183 // Check the requested topic exists 2184 if ( !$topic = get_topic( $topic_id ) ) { 2185 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 2186 return $this->error; 2187 } 2188 2189 // OK, let's trust the count in the topic table 2190 $count = $topic->topic_posts; 2191 2192 do_action( 'bb_xmlrpc_call_return', 'bb.getPostCount' ); 2193 2194 // Return the count of posts 2195 return $count; 2196 } 2197 2198 /** 2199 * Returns details of the posts in a given topic 2200 * 2201 * @since 1.0 2202 * @return array|object The posts when successfully executed or an IXR_Error object on failure 2203 * @param array $args Arguments passed by the XML-RPC call 2204 * @param string $args[0] The username for authentication 2205 * @param string $args[1] The password for authentication 2206 * @param integer|string $args[2] The topic id or slug 2207 * @param integer $args[3] The number of posts to return (optional) 2208 * @param integer $args[4] The number of the page to return (optional) 2209 * 2210 * XML-RPC request to get all posts in the topic with id number 53 2211 * <methodCall> 2212 * <methodName>bb.getPosts</methodName> 2213 * <params> 2214 * <param><value><string>joeblow</string></value></param> 2215 * <param><value><string>123password</string></value></param> 2216 * <param><value><int>53</int></value></param> 2217 * </params> 2218 * </methodCall> 2219 * 2220 * XML-RPC request to get the latest 5 posts in the topic with id number 341 2221 * <methodCall> 2222 * <methodName>bb.getPosts</methodName> 2223 * <params> 2224 * <param><value><string>joeblow</string></value></param> 2225 * <param><value><string>123password</string></value></param> 2226 * <param><value><int>341</int></value></param> 2227 * <param><value><int>5</int></value></param> 2228 * </params> 2229 * </methodCall> 2230 * 2231 * XML-RPC request to get posts 11 to 20 in the topic with slug "long-topic" 2232 * <methodCall> 2233 * <methodName>bb.getPosts</methodName> 2234 * <params> 2235 * <param><value><string>joeblow</string></value></param> 2236 * <param><value><string>123password</string></value></param> 2237 * <param><value><string>long-topic</string></value></param> 2238 * <param><value><int>10</int></value></param> 2239 * <param><value><int>2</int></value></param> 2240 * </params> 2241 * </methodCall> 2242 */ 2243 function bb_getPosts( $args ) 2244 { 2245 do_action( 'bb_xmlrpc_call', 'bb.getPosts' ); 2246 2247 // Escape args 2248 $this->escape( $args ); 2249 2250 // Get the login credentials 2251 $username = $args[0]; 2252 $password = (string) $args[1]; 2253 2254 // Check the user is valid 2255 if ( $this->auth_readonly ) { 2256 $user = $this->authenticate( $username, $password ); 2257 } 2258 2259 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getPosts' ); 2260 2261 // If an error was raised by authentication or by an action then return it 2262 if ( $this->error ) { 2263 return $this->error; 2264 } 2265 2266 // Can be numeric id or slug 2267 $topic_id = isset( $args[2] ) ? $args[2] : false; 2268 2269 // Check for bad data 2270 if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) { 2271 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 2272 return $this->error; 2273 } 2274 2275 // Check the requested topic exists 2276 if ( !$topic = get_topic( $topic_id ) ) { 2277 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 2278 return $this->error; 2279 } 2280 2281 // The topic id may have been a slug, so make sure it's an integer here 2282 $topic_id = (int) $topic->topic_id; 2283 2284 // Setup an array to store arguments to pass to get_thread() function 2285 $get_thread_args = array(); 2286 2287 // Can only be an integer 2288 if ( isset( $args[3] ) && $per_page = (int) $args[3] ) { 2289 $get_thread_args['per_page'] = $per_page; 2290 } 2291 2292 // Can only be an integer 2293 if ( isset( $args[4] ) && $page = (int) $args[4] ) { 2294 $get_thread_args['page'] = $page; 2295 } 2296 2297 // Get the posts 2298 if ( !$posts = get_thread( $topic_id, $get_thread_args ) ) { 2299 $this->error = new IXR_Error( 500, __( 'No posts found.' ) ); 2300 return $this->error; 2301 } 2302 2303 // Only include "safe" data in the array 2304 $_posts = array(); 2305 foreach ( $posts as $post ) { 2306 $_posts[] = $this->prepare_post( $post ); 2307 } 2308 2309 do_action( 'bb_xmlrpc_call_return', 'bb.getPosts' ); 2310 2311 // Return the posts 2312 return $_posts; 2313 } 2314 2315 /** 2316 * Returns details of a post 2317 * 2318 * @since 1.0 2319 * @return array|object An array containing details of the returned post when successfully executed or an IXR_Error object on failure 2320 * @param array $args Arguments passed by the XML-RPC call 2321 * @param string $args[0] The username for authentication 2322 * @param string $args[1] The password for authentication 2323 * @param integer $args[2] The post's id 2324 * 2325 * XML-RPC request to get the post with id number 32 2326 * <methodCall> 2327 * <methodName>bb.getPost</methodName> 2328 * <params> 2329 * <param><value><string>joeblow</string></value></param> 2330 * <param><value><string>123password</string></value></param> 2331 * <param><value><int>32</int></value></param> 2332 * </params> 2333 * </methodCall> 2334 */ 2335 function bb_getPost( $args ) 2336 { 2337 do_action( 'bb_xmlrpc_call', 'bb.getPost' ); 2338 2339 // Escape args 2340 $this->escape( $args ); 2341 2342 // Get the login credentials 2343 $username = $args[0]; 2344 $password = (string) $args[1]; 2345 2346 // Check the user is valid 2347 if ( $this->auth_readonly ) { 2348 $user = $this->authenticate( $username, $password ); 2349 } 2350 2351 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getPost' ); 2352 2353 // If an error was raised by authentication or by an action then return it 2354 if ( $this->error ) { 2355 return $this->error; 2356 } 2357 2358 // Can be numeric id or slug 2359 $post_id = isset( $args[2] ) ? (int) $args[2] : false; 2360 2361 // Check for bad data 2362 if ( !$post_id ) { 2363 $this->error = new IXR_Error( 400, __( 'The post id is invalid.' ) ); 2364 return $this->error; 2365 } 2366 2367 // Check the requested post exists 2368 if ( !$post = bb_get_post( $post_id ) ) { 2369 $this->error = new IXR_Error( 400, __( 'No post found.' ) ); 2370 return $this->error; 2371 } 2372 2373 // Only include "safe" data in the array 2374 $_post = $this->prepare_post( $post ); 2375 2376 do_action( 'bb_xmlrpc_call_return', 'bb.getPost' ); 2377 2378 // Return the post 2379 return $_post; 2380 } 2381 2382 /** 2383 * Creates a new post in a given topic 2384 * 2385 * @since 1.0 2386 * @return array|object The post data when successfully created or an IXR_Error object on failure 2387 * @param array $args Arguments passed by the XML-RPC call 2388 * @param string $args[0] The username for authentication 2389 * @param string $args[1] The password for authentication 2390 * @param array $args[2] The values for the various parameters in the new topic 2391 * @param string $args[2]['text'] The text of the topic 2392 * @param integer|string $args[2]['topic_id'] The unique id of the topic which will contain this topic, slugs are OK to use too 2393 * 2394 * XML-RPC request to create a new post in the topic with slug "totally-worth-it" 2395 * <methodCall> 2396 * <methodName>bb.newPost</methodName> 2397 * <params> 2398 * <param><value><string>joeblow</string></value></param> 2399 * <param><value><string>123password</string></value></param> 2400 * <param><value><struct> 2401 * <member> 2402 * <name>text</name> 2403 * <value><string>I agree, it is totally worth it.</string></value> 2404 * </member> 2405 * <member> 2406 * <name>topic_id</name> 2407 * <value><string>totally-worth-it</string></value> 2408 * </member> 2409 * </struct></value></param> 2410 * </params> 2411 * </methodCall> 2412 */ 2413 function bb_newPost( $args ) 2414 { 2415 do_action( 'bb_xmlrpc_call', 'bb.newPost' ); 2416 2417 // Escape args 2418 $this->escape( $args ); 2419 2420 // Get the login credentials 2421 $username = $args[0]; 2422 $password = (string) $args[1]; 2423 2424 // Check the user is valid 2425 $user = $this->authenticate( $username, $password, 'write_posts', __( 'You do not have permission to write posts.' ) ); 2426 2427 do_action( 'bb_xmlrpc_call_authenticated', 'bb.newPost' ); 2428 2429 // If an error was raised by authentication or by an action then return it 2430 if ( $this->error ) { 2431 return $this->error; 2432 } 2433 2434 // Make sure there is something for us to do 2435 if ( !$args[2] || !is_array( $args[2] ) || !count( $args[2] ) ) { 2436 $this->error = new IXR_Error( 400, __( 'The post data is invalid.' ) ); 2437 return $this->error; 2438 } 2439 2440 $structure = (array) $args[2]; 2441 2442 // Can be numeric id or slug 2443 $topic_id = isset( $structure['topic_id'] ) ? $structure['topic_id'] : false; 2444 2445 // Check for bad data 2446 if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) { 2447 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 2448 return $this->error; 2449 } 2450 2451 // Check the requested topic exists 2452 if ( !$topic = get_topic( $topic_id ) ) { 2453 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 2454 return $this->error; 2455 } 2456 2457 // The topic id may have been a slug, so make sure it's an integer here 2458 $topic_id = (int) $topic->topic_id; 2459 2460 // Make sure they are allowed to write posts to this topic 2461 if ( !bb_current_user_can( 'write_post', $topic_id ) ) { 2462 $this->error = new IXR_Error( 403, __( 'You do not have permission to write posts to this topic.' ) ); 2463 return $this->error; 2464 } 2465 2466 // The post requires text 2467 if ( !isset( $structure['text'] ) || !$structure['text'] ) { 2468 $this->error = new IXR_Error( 400, __( 'The post text is invalid.' ) ); 2469 return $this->error; 2470 } 2471 2472 // Inject structure into an array suitable for bb_insert_post() 2473 $bb_insert_post_args = array( 2474 'topic_id' => $topic_id, 2475 'post_text' => (string) $structure['text'] 2476 ); 2477 2478 // Create the post 2479 if ( !$post_id = bb_insert_post( $bb_insert_post_args ) ) { 2480 $this->error = new IXR_Error( 500, __( 'The post could not be created.' ) ); 2481 return $this->error; 2482 } 2483 2484 // Only include "safe" data in the array 2485 $post = $this->prepare_forum( bb_get_post( $post_id ) ); 2486 2487 do_action( 'bb_xmlrpc_call_return', 'bb.newPost' ); 2488 2489 return $post; 2490 } 2491 2492 /** 2493 * Edits an existing post 2494 * 2495 * @since 1.0 2496 * @return array|object The post data when successfully edited or an IXR_Error object on failure 2497 * @param array $args Arguments passed by the XML-RPC call 2498 * @param string $args[0] The username for authentication 2499 * @param string $args[1] The password for authentication 2500 * @param array $args[2] The values for the various parameters in the new topic 2501 * @param integer $args[2]['post_id'] The unique id of the post 2502 * @param string $args[2]['text'] The text of the topic 2503 * 2504 * XML-RPC request to edit the text of the post with an id of 452 2505 * <methodCall> 2506 * <methodName>bb.editPost</methodName> 2507 * <params> 2508 * <param><value><string>joeblow</string></value></param> 2509 * <param><value><string>123password</string></value></param> 2510 * <param><value><struct> 2511 * <member> 2512 * <name>post_id</name> 2513 * <value><int>452</int></value> 2514 * </member> 2515 * <member> 2516 * <name>text</name> 2517 * <value><string>For now I will withhold my opinion.</string></value> 2518 * </member> 2519 * </struct></value></param> 2520 * </params> 2521 * </methodCall> 2522 */ 2523 function bb_editPost( $args ) 2524 { 2525 do_action( 'bb_xmlrpc_call', 'bb.editPost' ); 2526 2527 // Escape args 2528 $this->escape( $args ); 2529 2530 // Get the login credentials 2531 $username = $args[0]; 2532 $password = (string) $args[1]; 2533 2534 // Check the user is valid 2535 $user = $this->authenticate( $username, $password, 'edit_posts', __( 'You do not have permission to edit posts.' ) ); 2536 2537 do_action( 'bb_xmlrpc_call_authenticated', 'bb.editPost' ); 2538 2539 // If an error was raised by authentication or by an action then return it 2540 if ( $this->error ) { 2541 return $this->error; 2542 } 2543 2544 // Make sure there is something for us to do 2545 if ( !$args[2] || !is_array( $args[2] ) || !count( $args[2] ) ) { 2546 $this->error = new IXR_Error( 400, __( 'The post data is invalid.' ) ); 2547 return $this->error; 2548 } 2549 2550 $structure = (array) $args[2]; 2551 2552 // Can be numeric id or slug 2553 $post_id = isset( $structure['post_id'] ) ? (int) $structure['post_id'] : false; 2554 2555 // Check for bad data 2556 if ( !$post_id ) { 2557 $this->error = new IXR_Error( 400, __( 'The post id is invalid.' ) ); 2558 return $this->error; 2559 } 2560 2561 // Check the requested topic exists 2562 if ( !$post = bb_get_post( $post_id ) ) { 2563