| [ Index ] |
PHP Cross Reference of bbPress |
[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 $this->error = new IXR_Error( 400, __( 'No post found.' ) ); 2564 return $this->error; 2565 } 2566 2567 // Re-assign the post id 2568 $post_id = (int) $post->post_id; 2569 2570 // Make sure they are allowed to edit this post 2571 if ( !bb_current_user_can( 'edit_post', $post_id ) ) { 2572 $this->error = new IXR_Error( 403, __( 'You do not have permission to edit this post.' ) ); 2573 return $this->error; 2574 } 2575 2576 // The post requires text 2577 if ( !isset( $structure['text'] ) || !$structure['text'] ) { 2578 $this->error = new IXR_Error( 400, __( 'The post text is invalid.' ) ); 2579 return $this->error; 2580 } 2581 2582 // Inject structure into an array suitable for bb_insert_post() 2583 $bb_insert_post_args = array( 2584 'post_id' => $post_id, 2585 'post_text' => (string) $structure['text'] 2586 ); 2587 2588 // Create the post 2589 if ( !$post_id = bb_insert_post( $bb_insert_post_args ) ) { 2590 $this->error = new IXR_Error( 500, __( 'The post could not be edited.' ) ); 2591 return $this->error; 2592 } 2593 2594 // Only include "safe" data in the array 2595 $post = $this->prepare_forum( bb_get_post( $post_id ) ); 2596 2597 do_action( 'bb_xmlrpc_call_return', 'bb.editPost' ); 2598 2599 return $post; 2600 } 2601 2602 /** 2603 * Deletes an existing post 2604 * 2605 * @since 1.0 2606 * @return integer|object 1 when successfully deleted, 0 when already deleted or an IXR_Error object on failure 2607 * @param array $args Arguments passed by the XML-RPC call 2608 * @param string $args[0] The username for authentication 2609 * @param string $args[1] The password for authentication 2610 * @param array $args[2] The unique id of the post 2611 * @param array $args[3] 1 deletes the post, 0 undeletes the post (optional) 2612 * 2613 * XML-RPC request to delete the post with an id of 4301 2614 * <methodCall> 2615 * <methodName>bb.editPost</methodName> 2616 * <params> 2617 * <param><value><string>joeblow</string></value></param> 2618 * <param><value><string>123password</string></value></param> 2619 * <param><value><int>4301</int></value></param> 2620 * </params> 2621 * </methodCall> 2622 */ 2623 function bb_deletePost( $args ) 2624 { 2625 do_action( 'bb_xmlrpc_call', 'bb.deletePost' ); 2626 2627 // Escape args 2628 $this->escape( $args ); 2629 2630 // Get the login credentials 2631 $username = $args[0]; 2632 $password = (string) $args[1]; 2633 2634 // Check the user is valid 2635 $user = $this->authenticate( $username, $password, 'delete_posts', __( 'You do not have permission to delete posts.' ) ); 2636 2637 do_action( 'bb_xmlrpc_call_authenticated', 'bb.deletePost' ); 2638 2639 // If an error was raised by authentication or by an action then return it 2640 if ( $this->error ) { 2641 return $this->error; 2642 } 2643 2644 // Can be numeric id or slug 2645 $post_id = isset( $args[2] ) ? (int) $args[2] : false; 2646 2647 // Check for bad data 2648 if ( !$post_id ) { 2649 $this->error = new IXR_Error( 400, __( 'The post id is invalid.' ) ); 2650 return $this->error; 2651 } 2652 2653 // Check the requested topic exists 2654 if ( !$post = bb_get_post( $post_id ) ) { 2655 $this->error = new IXR_Error( 400, __( 'No post found.' ) ); 2656 return $this->error; 2657 } 2658 2659 // Re-assign the post id 2660 $post_id = (int) $post->post_id; 2661 2662 // Make sure they are allowed to delete this post 2663 if ( !bb_current_user_can( 'delete_post', $post_id ) ) { 2664 $this->error = new IXR_Error( 403, __( 'You do not have permission to delete this post.' ) ); 2665 return $this->error; 2666 } 2667 2668 $status = isset( $args[3] ) ? (int) $args[3] : 1; 2669 2670 if ( $status === (int) $post->post_status ) { 2671 return 0; 2672 } 2673 2674 // Delete the post 2675 if ( !$post_id = bb_delete_post( $post_id, $status ) ) { 2676 $this->error = new IXR_Error( 500, __( 'The post could not be edited.' ) ); 2677 return $this->error; 2678 } 2679 2680 $result = 1; 2681 2682 do_action( 'bb_xmlrpc_call_return', 'bb.deletePost' ); 2683 2684 return $result; 2685 } 2686 2687 2688 2689 /** 2690 * bbPress publishing API - Topic Tag XML-RPC methods 2691 */ 2692 2693 /** 2694 * Returns the hot tags in order of hotness in a given forum or all hot tags 2695 * 2696 * @since 1.0 2697 * @return integer|object The tag data when successfully executed or an IXR_Error object on failure 2698 * @param array $args Arguments passed by the XML-RPC call 2699 * @param string $args[0] The username for authentication 2700 * @param string $args[1] The password for authentication 2701 * @param integer $args[2] The number of tags to return (optional) 2702 * @param integer|string $args[3] The forum id or slug (optional) 2703 * 2704 * XML-RPC request to get the 20 hottest tags in the forum with slug "hawtness" 2705 * <methodCall> 2706 * <methodName>bb.getTopicTags</methodName> 2707 * <params> 2708 * <param><value><string>joeblow</string></value></param> 2709 * <param><value><string>123password</string></value></param> 2710 * <param><value><int>20</int></value></param> 2711 * <param><value><string>hawtness</string></value></param> 2712 * </params> 2713 * </methodCall> 2714 */ 2715 function bb_getHotTopicTags( $args ) 2716 { 2717 do_action( 'bb_xmlrpc_call', 'bb.getHotTopicTags' ); 2718 2719 // Escape args 2720 $this->escape( $args ); 2721 2722 // Get the login credentials 2723 $username = $args[0]; 2724 $password = (string) $args[1]; 2725 2726 // Check the user is valid 2727 if ( $this->auth_readonly ) { 2728 $user = $this->authenticate( $username, $password ); 2729 } 2730 2731 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getHotTopicTags' ); 2732 2733 // If an error was raised by authentication or by an action then return it 2734 if ( $this->error ) { 2735 return $this->error; 2736 } 2737 2738 // Must be a number 2739 $per_page = isset( $args[2] ) ? (integer) $args[2] : false; 2740 2741 // Can be numeric id or slug 2742 $forum_id = isset( $args[3] ) ? $args[3] : false; 2743 2744 if ( $forum_id ) { 2745 // Check for bad data 2746 if ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) { 2747 $this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) ); 2748 return $this->error; 2749 } 2750 2751 // Check the requested forum exists 2752 if ( !$forum = bb_get_forum( $forum_id ) ) { 2753 $this->error = new IXR_Error( 404, __( 'No forum found.' ) ); 2754 return $this->error; 2755 } 2756 2757 global $bbdb; 2758 $topic_ids = $bbdb->get_col( $bbdb->prepare( "SELECT topic_id FROM `" . $bbdb->topics . "` WHERE `topic_status` = 0 AND `topic_open` = 1 AND `tag_count` > 0 AND `forum_id` = %s;", $forum_id ) ); 2759 2760 if ( !count( $topic_ids ) ) { 2761 $this->error = new IXR_Error( 400, __( 'No topics found.' ) ); 2762 return $this->error; 2763 } 2764 2765 global $wp_taxonomy_object; 2766 $tags = $wp_taxonomy_object->get_object_terms( $topic_ids, 'bb_topic_tag', array( 'fields' => 'all_with_object_id', 'orderby' => 'count', 'order' => 'DESC' ) ); 2767 2768 if ( !$tags || is_wp_error( $tags ) ) { 2769 $this->error = new IXR_Error( 500, __( 'Could not retrieve hot topic tags.' ) ); 2770 return $this->error; 2771 } 2772 if ( !count( $tags ) ) { 2773 $this->error = new IXR_Error( 500, __( 'No hot topic tags found.' ) ); 2774 return $this->error; 2775 } 2776 global $bb_log; 2777 $bb_log->debug($tags); 2778 2779 for ( $i = 0; isset( $tags[$i] ); $i++ ) { 2780 _bb_make_tag_compat( $tags[$i] ); 2781 } 2782 $bb_log->debug($tags); 2783 2784 // Only include "safe" data in the array 2785 $_tags = array(); 2786 foreach ( $tags as $tag ) { 2787 $_tag = $this->prepare_topic_tag( $tag ); 2788 if ( !in_array( $_tag, $_tags ) ) { 2789 $_tags[] = $_tag; 2790 } 2791 } 2792 2793 if ( $per_page ) { 2794 $_tags = array_slice( $_tags, 0, $per_page ); 2795 } 2796 } else { 2797 if ( !$tags = bb_get_top_tags( array( 'get' => 'all', 'number' => $per_page ) ) ) { 2798 $this->error = new IXR_Error( 500, __( 'No hot topic tags found.' ) ); 2799 return $this->error; 2800 } 2801 2802 // Only include "safe" data in the array 2803 $_tags = array(); 2804 foreach ( $tags as $tag ) { 2805 $_tags[] = $this->prepare_topic_tag( $tag ); 2806 } 2807 } 2808 2809 do_action( 'bb_xmlrpc_call', 'bb.getHotTopicTags' ); 2810 2811 return $_tags; 2812 } 2813 2814 /** 2815 * Returns a numerical count of tags in a given topic or all tags 2816 * 2817 * @since 1.0 2818 * @return integer|object The number of topics when successfully executed or an IXR_Error object on failure 2819 * @param array $args Arguments passed by the XML-RPC call 2820 * @param string $args[0] The username for authentication 2821 * @param string $args[1] The password for authentication 2822 * @param integer|string $args[2] The topic id or slug (optional) 2823 * 2824 * XML-RPC request to get a count of all tags in the topic with slug "woot-frist-topic" 2825 * <methodCall> 2826 * <methodName>bb.getTopicTagCount</methodName> 2827 * <params> 2828 * <param><value><string>joeblow</string></value></param> 2829 * <param><value><string>123password</string></value></param> 2830 * <param><value><string>woot-frist-topic</string></value></param> 2831 * </params> 2832 * </methodCall> 2833 */ 2834 function bb_getTopicTagCount( $args ) 2835 { 2836 do_action( 'bb_xmlrpc_call', 'bb.getTopicTagCount' ); 2837 2838 // Escape args 2839 $this->escape( $args ); 2840 2841 // Get the login credentials 2842 $username = $args[0]; 2843 $password = (string) $args[1]; 2844 2845 // Check the user is valid 2846 if ( $this->auth_readonly ) { 2847 $user = $this->authenticate( $username, $password ); 2848 } 2849 2850 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getTopicTagCount' ); 2851 2852 // If an error was raised by authentication or by an action then return it 2853 if ( $this->error ) { 2854 return $this->error; 2855 } 2856 2857 // Can be numeric id or slug 2858 $topic_id = isset( $args[2] ) ? $args[2] : false; 2859 2860 // Check for bad data 2861 if ( $topic_id ) { 2862 if ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) { 2863 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 2864 return $this->error; 2865 } 2866 2867 // Check the requested topic exists 2868 if ( !$topic = get_topic( $topic_id ) ) { 2869 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 2870 return $this->error; 2871 } 2872 2873 // The topic id may have been a slug, so make sure it's an integer here 2874 $topic_id = (int) $topic->topic_id; 2875 2876 // Now get the tags 2877 if ( !$tags = bb_get_topic_tags( $topic_id ) ) { 2878 $tags = array(); 2879 } 2880 2881 // Count the tags 2882 $count = count( $tags ); 2883 } else { 2884 global $wp_taxonomy_object; 2885 $count = $wp_taxonomy_object->count_terms( 'bb_topic_tag' ); 2886 if ( is_wp_error( $count ) ) { 2887 $this->error = new IXR_Error( 500, __( 'Could not get a count of all topic tags.' ) ); 2888 return $this->error; 2889 } 2890 } 2891 2892 do_action( 'bb_xmlrpc_call_return', 'bb.getTopicTagCount' ); 2893 2894 // Return the count of tags 2895 return $count; 2896 } 2897 2898 /** 2899 * Returns the tags in a given topic or all tags 2900 * 2901 * @since 1.0 2902 * @return integer|object The tag data when successfully executed or an IXR_Error object on failure 2903 * @param array $args Arguments passed by the XML-RPC call 2904 * @param string $args[0] The username for authentication 2905 * @param string $args[1] The password for authentication 2906 * @param integer|string $args[2] The topic id or slug (optional) 2907 * 2908 * XML-RPC request to get all tags in the topic with slug "woot-frist-topic" 2909 * <methodCall> 2910 * <methodName>bb.getTopicTags</methodName> 2911 * <params> 2912 * <param><value><string>joeblow</string></value></param> 2913 * <param><value><string>123password</string></value></param> 2914 * <param><value><string>woot-frist-topic</string></value></param> 2915 * </params> 2916 * </methodCall> 2917 */ 2918 function bb_getTopicTags( $args ) 2919 { 2920 do_action( 'bb_xmlrpc_call', 'bb.getTopicTags' ); 2921 2922 // Escape args 2923 $this->escape( $args ); 2924 2925 // Get the login credentials 2926 $username = $args[0]; 2927 $password = (string) $args[1]; 2928 2929 // Check the user is valid 2930 if ( $this->auth_readonly ) { 2931 $user = $this->authenticate( $username, $password ); 2932 } 2933 2934 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getTopicTags' ); 2935 2936 // If an error was raised by authentication or by an action then return it 2937 if ( $this->error ) { 2938 return $this->error; 2939 } 2940 2941 // Can be numeric id or slug 2942 $topic_id = isset( $args[2] ) ? $args[2] : false; 2943 2944 // Check for bad data 2945 if ( $topic_id ) { 2946 if ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) { 2947 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 2948 return $this->error; 2949 } 2950 2951 // Check the requested topic exists 2952 if ( !$topic = get_topic( $topic_id ) ) { 2953 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 2954 return $this->error; 2955 } 2956 2957 // The topic id may have been a slug, so make sure it's an integer here 2958 $topic_id = (int) $topic->topic_id; 2959 2960 // Now get the tags 2961 if ( !$tags = bb_get_topic_tags( $topic_id ) ) { 2962 $this->error = new IXR_Error( 500, __( 'No topic tags found.' ) ); 2963 return $this->error; 2964 } 2965 } else { 2966 global $wp_taxonomy_object; 2967 $tags = $wp_taxonomy_object->get_terms( 'bb_topic_tag', array( 'get' => 'all' ) ); 2968 if ( is_wp_error( $tags ) ) { 2969 $this->error = new IXR_Error( 500, __( 'Could not retrieve all topic tags.' ) ); 2970 return $this->error; 2971 } 2972 for ( $i = 0; isset( $tags[$i] ); $i++ ) { 2973 _bb_make_tag_compat( $tags[$i] ); 2974 } 2975 } 2976 2977 // Only include "safe" data in the array 2978 $_tags = array(); 2979 foreach ( $tags as $tag ) { 2980 $_tags[] = $this->prepare_topic_tag( $tag ); 2981 } 2982 2983 do_action( 'bb_xmlrpc_call_return', 'bb.getTopicTags' ); 2984 2985 // Return the tags 2986 return $_tags; 2987 } 2988 2989 /** 2990 * Returns the topics which are tagged with the given tag 2991 * 2992 * @since 1.0 2993 * @return integer|object The topic data when successfully executed or an IXR_Error object on failure 2994 * @param array $args Arguments passed by the XML-RPC call 2995 * @param string $args[0] The username for authentication 2996 * @param string $args[1] The password for authentication 2997 * @param string $args[2] The tag name or slug 2998 * @param integer $args[3] The number of topics to return (optional) 2999 * @param integer $args[4] The number of the page to return (optional) 3000 * 3001 * XML-RPC request to get the latest 10 topics tagged with the tag "apples" 3002 * <methodCall> 3003 * <methodName>bb.getTopicTag</methodName> 3004 * <params> 3005 * <param><value><string>joeblow</string></value></param> 3006 * <param><value><string>123password</string></value></param> 3007 * <param><value><string>apples</string></value></param> 3008 * <param><value><string>10</string></value></param> 3009 * </params> 3010 * </methodCall> 3011 */ 3012 function bb_getTopicTag( $args ) 3013 { 3014 do_action( 'bb_xmlrpc_call', 'bb.getTopicTag' ); 3015 3016 // Escape args 3017 $this->escape( $args ); 3018 3019 // Get the login credentials 3020 $username = $args[0]; 3021 $password = (string) $args[1]; 3022 3023 // Check the user is valid 3024 if ( $this->auth_readonly ) { 3025 $user = $this->authenticate( $username, $password ); 3026 } 3027 3028 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getTopicTag' ); 3029 3030 // If an error was raised by authentication or by an action then return it 3031 if ( $this->error ) { 3032 return $this->error; 3033 } 3034 3035 // Can only be a string 3036 $tag_id = isset( $args[2] ) ? (string) $args[2] : false; 3037 3038 // Check for bad data 3039 if ( !$tag_id ) { 3040 $this->error = new IXR_Error( 400, __( 'The tag id is invalid.' ) ); 3041 return $this->error; 3042 } 3043 3044 // Check the requested topic exists 3045 if ( !$tag = bb_get_tag( $tag_id ) ) { 3046 $this->error = new IXR_Error( 400, __( 'No tag found.' ) ); 3047 return $this->error; 3048 } 3049 3050 // Get the numeric tag id 3051 $tag_id = (int) $tag->tag_id; 3052 3053 // Setup an array to store arguments to pass to get_tagged_topics() function 3054 $get_topics_args = array( 3055 'tag_id' => false, 3056 'number' => false, 3057 'page' => false 3058 ); 3059 3060 // Can only be an integer 3061 if ( isset( $args[3] ) && $number = (int) $args[3] ) { 3062 $get_topics_args['number'] = $number; 3063 } 3064 3065 // Can only be an integer 3066 if ( isset( $args[4] ) && $page = (int) $args[4] ) { 3067 $get_topics_args['page'] = $page; 3068 } 3069 3070 // Now get the topics 3071 if ( !$topics = get_tagged_topics( $tag_id ) ) { 3072 $this->error = new IXR_Error( 500, __( 'No topics found.' ) ); 3073 return $this->error; 3074 } 3075 3076 // Only include "safe" data in the array 3077 $_topics = array(); 3078 foreach ( $topics as $topic ) { 3079 $_topics[] = $this->prepare_topic( $topic ); 3080 } 3081 3082 do_action( 'bb_xmlrpc_call_return', 'bb.getTopicTag' ); 3083 3084 // Return the topics 3085 return $_topics; 3086 } 3087 3088 /** 3089 * Adds the specified tags to the specified topic 3090 * 3091 * @since 1.0 3092 * @return array|object The tags which were added when successfully executed or an IXR_Error object on failure 3093 * @param array $args Arguments passed by the XML-RPC call 3094 * @param string $args[0] The username for authentication 3095 * @param string $args[1] The password for authentication 3096 * @param string|integer $args[2] The topic id or slug 3097 * @param string|array $args[3] The tags to add to the topic 3098 * 3099 * XML-RPC request to add the tag "banana" to the topic with id 219 3100 * <methodCall> 3101 * <methodName>bb.addTopicTags</methodName> 3102 * <params> 3103 * <param><value><string>joeblow</string></value></param> 3104 * <param><value><string>123password</string></value></param> 3105 * <param><value><int>219</int></value></param> 3106 * <param><value><string>banana</string></value></param> 3107 * </params> 3108 * </methodCall> 3109 * 3110 * XML-RPC request to add the tags "banana" and "man" to the topic with id 219 3111 * <methodCall> 3112 * <methodName>bb.addTopicTags</methodName> 3113 * <params> 3114 * <param><value><string>joeblow</string></value></param> 3115 * <param><value><string>123password</string></value></param> 3116 * <param><value><int>219</int></value></param> 3117 * <param><value><string>banana, man</string></value></param> 3118 * </params> 3119 * </methodCall> 3120 * 3121 * XML-RPC request to add the tags "banana" and "man" to the topic with id 219 using an array 3122 * <methodCall> 3123 * <methodName>bb.addTopicTags</methodName> 3124 * <params> 3125 * <param><value><string>joeblow</string></value></param> 3126 * <param><value><string>123password</string></value></param> 3127 * <param><value><int>219</int></value></param> 3128 * <param><value><array> 3129 * <data><value><string>banana</string></value></data> 3130 * <data><value><string>man</string></value></data> 3131 * </array></value></param> 3132 * </params> 3133 * </methodCall> 3134 */ 3135 function bb_addTopicTags( $args ) 3136 { 3137 do_action( 'bb_xmlrpc_call', 'bb.addTopicTags' ); 3138 3139 // Escape args 3140 $this->escape( $args ); 3141 3142 // Get the login credentials 3143 $username = $args[0]; 3144 $password = (string) $args[1]; 3145 3146 // Check the user is valid 3147 $user = $this->authenticate( $username, $password, 'edit_tags', __( 'You do not have permission to edit tags.' ) ); 3148 3149 do_action( 'bb_xmlrpc_call_authenticated', 'bb.addTopicTags' ); 3150 3151 // If an error was raised by authentication or by an action then return it 3152 if ( $this->error ) { 3153 return $this->error; 3154 } 3155 3156 // Can be numeric id or slug 3157 $topic_id = isset( $args[2] ) ? $args[2] : false; 3158 3159 // Check for bad data 3160 if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) { 3161 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 3162 return $this->error; 3163 } 3164 3165 // Check the requested topic exists 3166 if ( !$topic = get_topic( $topic_id ) ) { 3167 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 3168 return $this->error; 3169 } 3170 3171 // The topic id may have been a slug, so make sure it's an integer here 3172 $topic_id = (int) $topic->topic_id; 3173 3174 // Make sure they are allowed to add tags to this topic 3175 if ( !bb_current_user_can( 'add_tag_to', $topic_id ) ) { 3176 $this->error = new IXR_Error( 403, __( 'You do not have permission to add tags to this topic.' ) ); 3177 return $this->error; 3178 } 3179 3180 $tags = isset( $args[3] ) ? $args[3] : false; 3181 3182 // Check for bad data 3183 if ( !$tags || ( !is_string( $tags ) && !is_array( $tags ) ) ) { 3184 $this->error = new IXR_Error( 400, __( 'The tag data is invalid.' ) ); 3185 return $this->error; 3186 } 3187 3188 // Add the tags 3189 if ( !$tag_ids = bb_add_topic_tags( $topic_id, $tags ) ) { 3190 $this->error = new IXR_Error( 500, __( 'The tags could not be added.' ) ); 3191 return $this->error; 3192 } 3193 3194 // Only include "safe" data in the array 3195 $_tags = array(); 3196 foreach ( $tag_ids as $tag_id ) { 3197 $_tags[] = $this->prepare_topic_tag( bb_get_tag( $tag_id ) ); 3198 } 3199 3200 do_action( 'bb_xmlrpc_call_return', 'bb.addTopicTags' ); 3201 3202 // Return the tags which were added as an array 3203 return $_tags; 3204 } 3205 3206 /** 3207 * Removes the specified tags from the specified topic 3208 * 3209 * @since 1.0 3210 * @return integer|object 1 when successfully executed or an IXR_Error object on failure 3211 * @param array $args Arguments passed by the XML-RPC call 3212 * @param string $args[0] The username for authentication 3213 * @param string $args[1] The password for authentication 3214 * @param string|integer $args[2] The topic id or slug 3215 * @param string|array $args[3] The tags to remove from the topic 3216 * 3217 * XML-RPC request to remove the tag "banana" to the topic with id 219 3218 * <methodCall> 3219 * <methodName>bb.removeTopicTags</methodName> 3220 * <params> 3221 * <param><value><string>joeblow</string></value></param> 3222 * <param><value><string>123password</string></value></param> 3223 * <param><value><int>219</int></value></param> 3224 * <param><value><string>banana</string></value></param> 3225 * </params> 3226 * </methodCall> 3227 * 3228 * XML-RPC request to remove the tags "banana" and "man" to the topic with id 219 3229 * <methodCall> 3230 * <methodName>bb.removeTopicTags</methodName> 3231 * <params> 3232 * <param><value><string>joeblow</string></value></param> 3233 * <param><value><string>123password</string></value></param> 3234 * <param><value><int>219</int></value></param> 3235 * <param><value><string>banana, man</string></value></param> 3236 * </params> 3237 * </methodCall> 3238 * 3239 * XML-RPC request to remove the tags "banana" and "man" to the topic with id 219 using an array 3240 * <methodCall> 3241 * <methodName>bb.removeTopicTags</methodName> 3242 * <params> 3243 * <param><value><string>joeblow</string></value></param> 3244 * <param><value><string>123password</string></value></param> 3245 * <param><value><int>219</int></value></param> 3246 * <param><value><array> 3247 * <data><value><string>banana</string></value></data> 3248 * <data><value><string>man</string></value></data> 3249 * </array></value></param> 3250 * </params> 3251 * </methodCall> 3252 */ 3253 function bb_removeTopicTags( $args ) 3254 { 3255 do_action( 'bb_xmlrpc_call', 'bb.removeTopicTags' ); 3256 3257 // Escape args 3258 $this->escape( $args ); 3259 3260 // Get the login credentials 3261 $username = $args[0]; 3262 $password = (string) $args[1]; 3263 3264 // Check the user is valid 3265 $user = $this->authenticate( $username, $password, 'edit_tags', __( 'You do not have permission to edit tags.' ) ); 3266 3267 do_action( 'bb_xmlrpc_call_authenticated', 'bb.removeTopicTags' ); 3268 3269 // If an error was raised by authentication or by an action then return it 3270 if ( $this->error ) { 3271 return $this->error; 3272 } 3273 3274 // Can be numeric id or slug 3275 $topic_id = isset( $args[2] ) ? $args[2] : false; 3276 3277 // Check for bad data 3278 if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) { 3279 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 3280 return $this->error; 3281 } 3282 3283 // Check the requested topic exists 3284 if ( !$topic = get_topic( $topic_id ) ) { 3285 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 3286 return $this->error; 3287 } 3288 3289 // The topic id may have been a slug, so make sure it's an integer here 3290 $topic_id = (int) $topic->topic_id; 3291 3292 // Make sure they are allowed to add tags to this topic 3293 if ( !bb_current_user_can( 'add_tag_to', $topic_id ) ) { 3294 $this->error = new IXR_Error( 403, __( 'You do not have permission to remove tags from this topic.' ) ); 3295 return $this->error; 3296 } 3297 3298 $tags = isset( $args[3] ) ? $args[3] : false; 3299 3300 // Check for bad data 3301 if ( !$tags || ( !is_string( $tags ) && !is_array( $tags ) ) ) { 3302 $this->error = new IXR_Error( 400, __( 'The tag data is invalid.' ) ); 3303 return $this->error; 3304 } 3305 3306 // Add the tags 3307 if ( !bb_remove_topic_tags( $topic_id, $tags ) ) { 3308 $this->error = new IXR_Error( 500, __( 'The tags could not be removed.' ) ); 3309 return $this->error; 3310 } 3311 3312 $result = 1; 3313 3314 do_action( 'bb_xmlrpc_call_return', 'bb.removeTopicTags' ); 3315 3316 // Return the result 3317 return $result; 3318 } 3319 3320 /** 3321 * Renames the specified tag to a new tag name 3322 * 3323 * @since 1.0 3324 * @return array|object The tag data when successfully renamed or an IXR_Error object on failure 3325 * @param array $args Arguments passed by the XML-RPC call 3326 * @param string $args[0] The username for authentication 3327 * @param string $args[1] The password for authentication 3328 * @param string $args[2] The tag name or slug 3329 * @param string $args[3] The new tag name (slug is auto-generated) 3330 * 3331 * XML-RPC request to rename the tag "banana" to "bananas" 3332 * <methodCall> 3333 * <methodName>bb.renameTopicTag</methodName> 3334 * <params> 3335 * <param><value><string>joeblow</string></value></param> 3336 * <param><value><string>123password</string></value></param> 3337 * <param><value><string>banana</string></value></param> 3338 * <param><value><string>bananas</string></value></param> 3339 * </params> 3340 * </methodCall> 3341 */ 3342 function bb_renameTopicTag( $args ) 3343 { 3344 do_action( 'bb_xmlrpc_call', 'bb.renameTopicTag' ); 3345 3346 // Escape args 3347 $this->escape( $args ); 3348 3349 // Get the login credentials 3350 $username = $args[0]; 3351 $password = (string) $args[1]; 3352 3353 // Check the user is valid 3354 $user = $this->authenticate( $username, $password, 'manage_tags', __( 'You do not have permission to manage tags.' ) ); 3355 3356 do_action( 'bb_xmlrpc_call_authenticated', 'bb.renameTopicTag' ); 3357 3358 // If an error was raised by authentication or by an action then return it 3359 if ( $this->error ) { 3360 return $this->error; 3361 } 3362 3363 // Can only be a string 3364 $tag_id = isset( $args[2] ) ? (string) $args[2] : false; 3365 3366 // Check for bad data 3367 if ( !$tag_id ) { 3368 $this->error = new IXR_Error( 400, __( 'The tag id is invalid.' ) ); 3369 return $this->error; 3370 } 3371 3372 // Check the requested tag exists 3373 if ( !$tag = bb_get_tag( $tag_id ) ) { 3374 $this->error = new IXR_Error( 400, __( 'No tag found.' ) ); 3375 return $this->error; 3376 } 3377 3378 // Get the numeric tag id 3379 $tag_id = (int) $tag->tag_id; 3380 3381 // Can only be a string 3382 $tag_name = isset( $args[3] ) ? (string) $args[3] : false; 3383 3384 // Check for bad data 3385 if ( !$tag_name || $tag_name == $tag->tag_name ) { 3386 $this->error = new IXR_Error( 400, __( 'The tag name is invalid.' ) ); 3387 return $this->error; 3388 } 3389 3390 // Rename the tag 3391 if ( !$new_tag = bb_rename_tag( $tag_id, $tag_name ) ) { 3392 $this->error = new IXR_Error( 500, __( 'The tag could not be renamed.' ) ); 3393 return $this->error; 3394 } 3395 3396 // Only include "safe" data in the array 3397 $new_tag = $this->prepare_topic_tag( $new_tag ); 3398 3399 do_action( 'bb_xmlrpc_call_return', 'bb.renameTopicTag' ); 3400 3401 // Return the tag 3402 return $new_tag; 3403 } 3404 3405 /** 3406 * Merges the specified tags 3407 * 3408 * @since 1.0 3409 * @return array|object The tag data when successfully merged or an IXR_Error object on failure 3410 * @param array $args Arguments passed by the XML-RPC call 3411 * @param string $args[0] The username for authentication 3412 * @param string $args[1] The password for authentication 3413 * @param string $args[2] The old tag name or slug to be destroyed 3414 * @param string $args[3] The new tag name or slug where the old tag will be merged to 3415 * 3416 * XML-RPC request to merge the tag "banana" into the tag "apple" 3417 * <methodCall> 3418 * <methodName>bb.mergeTopicTags</methodName> 3419 * <params> 3420 * <param><value><string>joeblow</string></value></param> 3421 * <param><value><string>123password</string></value></param> 3422 * <param><value><string>banana</string></value></param> 3423 * <param><value><string>apple</string></value></param> 3424 * </params> 3425 * </methodCall> 3426 */ 3427 function bb_mergeTopicTags( $args ) 3428 { 3429 do_action( 'bb_xmlrpc_call', 'bb.mergeTopicTags' ); 3430 3431 // Escape args 3432 $this->escape( $args ); 3433 3434 // Get the login credentials 3435 $username = $args[0]; 3436 $password = (string) $args[1]; 3437 3438 // Check the user is valid 3439 $user = $this->authenticate( $username, $password, 'manage_tags', __( 'You do not have permission to manage tags.' ) ); 3440 3441 do_action( 'bb_xmlrpc_call_authenticated', 'bb.mergeTopicTags' ); 3442 3443 // If an error was raised by authentication or by an action then return it 3444 if ( $this->error ) { 3445 return $this->error; 3446 } 3447 3448 // Can only be strings 3449 $old_tag_id = isset( $args[2] ) ? (string) $args[2] : false; 3450 $new_tag_id = isset( $args[3] ) ? (string) $args[3] : false; 3451 3452 // Check for bad data 3453 if ( !$old_tag_id ) { 3454 $this->error = new IXR_Error( 400, __( 'The old tag id is invalid.' ) ); 3455 return $this->error; 3456 } 3457 if ( !$new_tag_id ) { 3458 $this->error = new IXR_Error( 400, __( 'The new tag id is invalid.' ) ); 3459 return $this->error; 3460 } 3461 3462 // Check the requested tags exist 3463 if ( !$old_tag = bb_get_tag( $old_tag_id ) ) { 3464 $this->error = new IXR_Error( 400, __( 'No old tag found.' ) ); 3465 return $this->error; 3466 } 3467 if ( !$new_tag = bb_get_tag( $new_tag_id ) ) { 3468 $this->error = new IXR_Error( 400, __( 'No new tag found.' ) ); 3469 return $this->error; 3470 } 3471 3472 // Get the numeric tag ids 3473 $old_tag_id = (int) $old_tag->tag_id; 3474 $new_tag_id = (int) $new_tag->tag_id; 3475 3476 // Rename the tag 3477 if ( !$result = bb_rename_tag( $old_tag_id, $new_tag_id ) ) { 3478 $this->error = new IXR_Error( 500, __( 'The tags could not be merged.' ) ); 3479 return $this->error; 3480 } 3481 3482 // Get the merged tag 3483 $new_tag = bb_get_tag( $new_tag_id ); 3484 3485 // Only include "safe" data in the array 3486 $new_tag = $this->prepare_topic_tag( $new_tag ); 3487 3488 do_action( 'bb_xmlrpc_call_return', 'bb.mergeTopicTags' ); 3489 3490 // Return the tag 3491 return $new_tag; 3492 } 3493 3494 /** 3495 * Destroys the specified tag 3496 * 3497 * @since 1.0 3498 * @return integer|object 1 when successfully deleted or an IXR_Error object on failure 3499 * @param array $args Arguments passed by the XML-RPC call 3500 * @param string $args[0] The username for authentication 3501 * @param string $args[1] The password for authentication 3502 * @param string $args[2] The tag name or slug to be destroyed 3503 * 3504 * XML-RPC request to destroy the tag "banana" 3505 * <methodCall> 3506 * <methodName>bb.destroyTopicTag</methodName> 3507 * <params> 3508 * <param><value><string>joeblow</string></value></param> 3509 * <param><value><string>123password</string></value></param> 3510 * <param><value><string>banana</string></value></param> 3511 * </params> 3512 * </methodCall> 3513 */ 3514 function bb_destroyTopicTag( $args ) 3515 { 3516 do_action( 'bb_xmlrpc_call', 'bb.destroyTopicTag' ); 3517 3518 // Escape args 3519 $this->escape( $args ); 3520 3521 // Get the login credentials 3522 $username = $args[0]; 3523 $password = (string) $args[1]; 3524 3525 // Check the user is valid 3526 $user = $this->authenticate( $username, $password, 'manage_tags', __( 'You do not have permission to manage tags.' ) ); 3527 3528 do_action( 'bb_xmlrpc_call_authenticated', 'bb.destroyTopicTag' ); 3529 3530 // If an error was raised by authentication or by an action then return it 3531 if ( $this->error ) { 3532 return $this->error; 3533 } 3534 3535 // Can only be a string 3536 $tag_id = isset( $args[2] ) ? (string) $args[2] : false; 3537 3538 // Check for bad data 3539 if ( !$tag_id ) { 3540 $this->error = new IXR_Error( 400, __( 'The tag id is invalid.' ) ); 3541 return $this->error; 3542 } 3543 3544 // Check the requested tag exists 3545 if ( !$tag = bb_get_tag( $tag_id ) ) { 3546 $this->error = new IXR_Error( 400, __( 'No tag found.' ) ); 3547 return $this->error; 3548 } 3549 3550 // Get the numeric tag id 3551 $tag_id = (int) $tag->tag_id; 3552 3553 // Destroy the tag 3554 if ( !$result = bb_destroy_tag( $tag_id ) ) { 3555 $this->error = new IXR_Error( 500, __( 'The tag could not be destroyed.' ) ); 3556 return $this->error; 3557 } 3558 3559 $result = 1; 3560 3561 do_action( 'bb_xmlrpc_call_return', 'bb.destroyTopicTag' ); 3562 3563 // Return the tag 3564 return $result; 3565 } 3566 3567 3568 3569 /** 3570 * bbPress publishing API - Options XML-RPC methods 3571 */ 3572 3573 /** 3574 * Initialises site options which can be manipulated using XML-RPC 3575 * 3576 * @since 1.0 3577 * @return void 3578 */ 3579 function initialise_site_option_info() 3580 { 3581 $this->site_options = array( 3582 // Read only options 3583 'software_name' => array( 3584 'desc' => __( 'Software Name' ), 3585 'readonly' => true, 3586 'value' => 'bbPress' 3587 ), 3588 'software_version' => array( 3589 'desc' => __( 'Software Version' ), 3590 'readonly' => true, 3591 'option' => 'version' 3592 ), 3593 'site_url' => array( 3594 'desc' => __( 'Site URL' ), 3595 'readonly' => true, 3596 'option' => 'uri' 3597 ), 3598 3599 // Updatable options 3600 'site_name' => array( 3601 'desc' => __( 'Site Name' ), 3602 'readonly' => false, 3603 'option' => 'name' 3604 ), 3605 'site_description' => array( 3606 'desc' => __( 'Site Description' ), 3607 'readonly' => false, 3608 'option' => 'description' 3609 ), 3610 'time_zone' => array( 3611 'desc' => __( 'Time Zone' ), 3612 'readonly' => false, 3613 'option' => 'gmt_offset' 3614 ), 3615 'datetime_format' => array( 3616 'desc' => __( 'Date/Time Format' ), 3617 'readonly' => false, 3618 'option' => 'datetime_format' 3619 ), 3620 'date_format' => array( 3621 'desc' => __( 'Date Format' ), 3622 'readonly' => false, 3623 'option' => 'date_format' 3624 ) 3625 ); 3626 3627 $this->site_options = apply_filters( 'xmlrpc_site_options', $this->site_options ); 3628 } 3629 3630 /** 3631 * Compiles site options into an array suitable to be passed back through the XML-RPC server 3632 * 3633 * @since 1.0 3634 * @return array The site options in an array 3635 * @param array $options An array of options to fetch and return 3636 */ 3637 function _getOptions( $options ) 3638 { 3639 $data = array(); 3640 foreach ( $options as $option ) { 3641 if ( array_key_exists( $option, $this->site_options ) ) { 3642 $data[$option] = $this->site_options[$option]; 3643 3644 // Is the value static or dynamic? 3645 if ( isset( $data[$option]['option'] ) ) { 3646 $data[$option]['value'] = bb_get_option( $data[$option]['option'] ); 3647 unset( $data[$option]['option'] ); 3648 } 3649 } 3650 } 3651 3652 return $data; 3653 } 3654 3655 /** 3656 * Gets the specified site options 3657 * 3658 * @since 1.0 3659 * @return array|object An array containing the specified options when successfully executed or an IXR_Error object on failure 3660 * @param array $args Arguments passed by the XML-RPC call 3661 * @param string $args[0] The username for authentication 3662 * @param string $args[1] The password for authentication 3663 * @param array $args[2] The options to be retrieved, when omitted the method returns all options (optional) 3664 * 3665 * XML-RPC request to get all site options 3666 * <methodCall> 3667 * <methodName>bb.getOptions</methodName> 3668 * <params> 3669 * <param><value><string>joeblow</string></value></param> 3670 * <param><value><string>123password</string></value></param> 3671 * </params> 3672 * </methodCall> 3673 * 3674 * XML-RPC request to get the site name and site description 3675 * <methodCall> 3676 * <methodName>bb.getOptions</methodName> 3677 * <params> 3678 * <param><value><string>joeblow</string></value></param> 3679 * <param><value><string>123password</string></value></param> 3680 * <param><value><array> 3681 * <data><value><string>site_name</string></value></data> 3682 * <data><value><string>site_description</string></value></data> 3683 * </array></value></param> 3684 * </params> 3685 * </methodCall> 3686 */ 3687 function bb_getOptions( $args ) 3688 { 3689 do_action( 'bb_xmlrpc_call', 'bb.getOptions' ); 3690 3691 // Escape args 3692 $this->escape( $args ); 3693 3694 // Get the login credentials 3695 $username = $args[0]; 3696 $password = (string) $args[1]; 3697 3698 // Check the user is valid 3699 if ( $this->auth_readonly ) { 3700 $user = $this->authenticate( $username, $password ); 3701 } 3702 3703 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getOptions' ); 3704 3705 // If an error was raised by authentication or by an action then return it 3706 if ( $this->error ) { 3707 return $this->error; 3708 } 3709 3710 // If there are parameters supplied then make sure they are in an array 3711 $options = isset( $args[2] ) ? (array) $args[2] : false; 3712 3713 // If no specific options where asked for, return all of them 3714 if ( !$options || !count( $options ) ) { 3715 $options = array_keys( $this->site_options ); 3716 } 3717 3718 do_action( 'bb_xmlrpc_call_return', 'bb.getOptions' ); 3719 3720 return $this->_getOptions( $options ); 3721 } 3722 3723 /** 3724 * Sets the specified site options to the specified values 3725 * 3726 * @since 1.0 3727 * @return array|object An array containing the specified options when successfully executed or an IXR_Error object on failure 3728 * @param array $args Arguments passed by the XML-RPC call 3729 * @param string $args[0] The username for authentication 3730 * @param string $args[1] The password for authentication 3731 * @param array $args[2] The options to be updated along with the new value of the option 3732 * 3733 * XML-RPC request to set the site name and site description 3734 * <methodCall> 3735 * <methodName>bb.setOptions</methodName> 3736 * <params> 3737 * <param><value><string>joeblow</string></value></param> 3738 * <param><value><string>123password</string></value></param> 3739 * <param><value><struct> 3740 * <member> 3741 * <name>site_name</name> 3742 * <value><string>Awesome forums</string></value> 3743 * </member> 3744 * <member> 3745 * <name>site_description</name> 3746 * <value><string>My totally awesome forums will kick your butt</string></value> 3747 * </member> 3748 * </struct></value></param> 3749 * </params> 3750 * </methodCall> 3751 */ 3752 function bb_setOptions( $args ) 3753 { 3754 do_action( 'bb_xmlrpc_call', 'bb.setOptions' ); 3755 3756 // Escape args 3757 $this->escape( $args ); 3758 3759 // Get the login credentials 3760 $username = $args[0]; 3761 $password = (string) $args[1]; 3762 3763 // Check the user is valid 3764 $user = $this->authenticate( $username, $password, 'manage_options', __( 'You are not allowed to manage options.' ) ); 3765 3766 do_action( 'bb_xmlrpc_call_authenticated', 'bb.setOptions' ); 3767 3768 // If an error was raised by authentication or by an action then return it 3769 if ( $this->error ) { 3770 return $this->error; 3771 } 3772 3773 // Make sure there is something for us to do 3774 if ( !$args[2] || !is_array( $args[2] ) || !count( $args[2] ) ) { 3775 $this->error = new IXR_Error( 400, __( 'The options data is invalid.' ) ); 3776 return $this->error; 3777 } 3778 3779 $options = (array) $args[2]; 3780 3781 // Update the requested options 3782 foreach( $options as $o_name => $o_value ) { 3783 $option_names[] = $o_name; 3784 3785 // If there is no value set skip it 3786 if ( empty( $o_value ) ) { 3787 continue; 3788 } 3789 3790 // If the option doesn't exist skip it 3791 if ( !array_key_exists( $o_name, $this->site_options ) ) { 3792 continue; 3793 } 3794 3795 // If the option is readonly skip it 3796 if ( $this->site_options[$o_name]['readonly'] == true ) { 3797 continue; 3798 } 3799 3800 // Everything is good, update the option 3801 bb_update_option( $this->site_options[$o_name]['option'], $o_value ); 3802 } 3803 3804 $_options = $this->_getOptions( $option_names ); 3805 3806 do_action( 'bb_xmlrpc_call_return', 'bb.setOptions' ); 3807 3808 // Now return the updated values 3809 return $_options; 3810 } 3811 3812 3813 3814 /** 3815 * Pingback XML-RPC methods 3816 */ 3817 3818 /** 3819 * Processes pingback requests 3820 * 3821 * @since 1.0 3822 * @link http://www.hixie.ch/specs/pingback/pingback 3823 * @return string|object A message of success or an IXR_Error object on failure 3824 * @param array $args Arguments passed by the XML-RPC call 3825 * @param string $args[0] The full URI of the post where the pingback is being sent from 3826 * @param string $args[1] The full URI of the post where the pingback is being sent to 3827 * 3828 * XML-RPC request to register a pingback 3829 * <methodCall> 3830 * <methodName>pingback.ping</methodName> 3831 * <params> 3832 * <param><value><string>http://example.org/2008/09/post-containing-a-link/</string></value></param> 3833 * <param><value><string>http://example.com/2008/08/post-being-linked-to/</string></value></param> 3834 * </params> 3835 * </methodCall> 3836 */ 3837 function pingback_ping( $args ) 3838 { 3839 do_action( 'bb_xmlrpc_call', 'pingback.ping' ); 3840 3841 $this->escape( $args ); 3842 3843 // No particular need to sanitise 3844 $link_from = (string) $args[0]; 3845 $link_to = (string) $args[1]; 3846 3847 // Tidy up ampersands in the URLs 3848 $link_from = str_replace( '&', '&', $link_from ); 3849 $link_to = str_replace( '&', '&', $link_to ); 3850 $link_to = str_replace( '&', '&', $link_to ); 3851 3852 // Check if the topic linked to is in our site - a little more strict than WordPress, doesn't pull out the www if added 3853 if ( !bb_match_domains( $link_to, bb_get_uri() ) ) { 3854 // These are not the droids you are looking for 3855 $this->error = new IXR_Error( 0, __( 'This is not the site you are trying to pingback.' ) ); 3856 return $this->error; 3857 } 3858 3859 // Get the topic 3860 if ( $topic_to = bb_get_topic_from_uri( $link_to ) ) { 3861 // Topics shouldn't ping themselves 3862 if ( $topic_from = bb_get_topic_from_uri( $link_from ) ) { 3863 if ( $topic_from->topic_id === $topic_to->topic_id ) { 3864 $this->error = new IXR_Error( 0, __( 'The source URL and the target URL cannot both point to the same resource.' ) ); 3865 return $this->error; 3866 } 3867 } 3868 } else { 3869 $this->error = new IXR_Error ( 33, __( 'The specified target URL cannot be used as a target. It either doesn\'t exist, or it is not a pingback-enabled resource.' ) ); 3870 return $this->error; 3871 } 3872 3873 // Let's check that the remote site didn't already pingback this entry 3874 $query = new BB_Query( 'post', array( 'topic_id' => $topic_to->topic_id, 'append_meta' => true ), 'get_thread' ); 3875 $posts_to = $query->results; 3876 unset( $query ); 3877 3878 // Make sure we have some posts in the topic, this error should never happen really 3879 if ( !$posts_to || !is_array( $posts_to ) || !count( $posts_to ) ) { 3880 $this->error = new IXR_Error( 0, __( 'The specified target topic does not contain any posts.' ) ); 3881 return $this->error; 3882 } 3883 3884 // Check if we already have a pingback from this URL 3885 foreach ( $posts_to as $post ) { 3886 if ( isset( $post->pingback_uri ) && trim( $post->pingback_uri ) === trim( $link_from ) ) { 3887 $this->error = new IXR_Error( 48, __( 'The pingback has already been registered.' ) ); 3888 return $this->error; 3889 } 3890 } 3891 unset( $posts_to, $post ); 3892 3893 // Give time for the server sending the pingback to finish publishing it's post 3894 sleep(1); 3895 3896 // Let's check the remote site for valid URL and content 3897 $link_from_source = wp_remote_fopen( $link_from ); 3898 if ( !$link_from_source ) { 3899 $this->error = new IXR_Error( 16, __( 'The source URL does not exist.' ) ); 3900 return $this->error; 3901 } 3902 3903 // Allow plugins to filter here 3904 $link_from_source = apply_filters( 'bb_pre_remote_source', $link_from_source, $link_to ); 3905 3906 // Work around bug in strip_tags() 3907 $link_from_source = str_replace( '<!DOC', '<DOC', $link_from_source ); 3908 3909 // Normalize spaces 3910 $link_from_source = preg_replace( '/[\s\r\n\t]+/', ' ', $link_from_source ); 3911 3912 // Turn certain elements to double line returns 3913 $link_from_source = preg_replace( "/ <(h1|h2|h3|h4|h5|h6|p|th|td|li|dt|dd|pre|caption|input|textarea|button|body)[^>]*>/", "\n\n", $link_from_source ); 3914 3915 // Find the title of the page 3916 preg_match( '|<title>([^<]*?)</title>|is', $link_from_source, $link_from_title ); 3917 $link_from_title = $link_from_title[1]; 3918 if ( empty( $link_from_title ) ) { 3919 $this->error = new IXR_Error( 32, __( 'We cannot find a title on that page.' ) ); 3920 return $this->error; 3921 } 3922 3923 // Strip out all tags except anchors 3924 $link_from_source = strip_tags( $link_from_source, '<a>' ); // just keep the tag we need 3925 3926 // Split the source into paragraphs 3927 $link_from_paragraphs = explode( "\n\n", $link_from_source ); 3928 3929 // Prepare the link to search for in preg_match() once here 3930 $preg_target = preg_quote( $link_to ); 3931 3932 // Loop through the paragraphs looking for the context for the url 3933 foreach ( $link_from_paragraphs as $link_from_paragraph ) { 3934 // The url exists 3935 if ( strpos( $link_from_paragraph, $link_to ) !== false ) { 3936 // But is it in an anchor tag 3937 preg_match( 3938 "|<a[^>]+?" . $preg_target . "[^>]*>([^>]+?)</a>|", 3939 $link_from_paragraph, 3940 $context 3941 ); 3942 // If the URL isn't in an anchor tag, keep looking 3943 if ( empty( $context ) ) { 3944 continue; 3945 } 3946 3947 // We're going to use this fake tag to mark the context in a bit 3948 // the marker is needed in case the link text appears more than once in the paragraph 3949 $excerpt = preg_replace( '|\</?wpcontext\>|', '', $link_from_paragraph ); 3950 3951 // Prevent really long link text 3952 if ( strlen( $context[1] ) > 100 ) { 3953 $context[1] = substr( $context[1], 0, 100 ) . '...'; 3954 } 3955 3956 // Set up the marker around the context 3957 $marker = '<wpcontext>' . $context[1] . '</wpcontext>'; 3958 // Swap out the link for our marker 3959 $excerpt = str_replace( $context[0], $marker, $excerpt ); 3960 // Strip all tags except for our context marker 3961 $excerpt = trim( strip_tags( $excerpt, '<wpcontext>' ) ); 3962 // Make the marker safe for use in regexp 3963 $preg_marker = preg_quote( $marker ); 3964 // Reduce the excerpt to only include 100 characters on either side of the link 3965 $excerpt = preg_replace( "|.*?\s(.{0,100}" . $preg_marker . "{0,100})\s.*|s", '$1', $excerpt ); 3966 // Strip tags again, to remove the marker wrapper 3967 $excerpt = strip_tags( $excerpt ); 3968 break; 3969 } 3970 } 3971 3972 // Make sure the link to the target was found in the excerpt 3973 if ( empty( $context ) ) { 3974 $this->error = new IXR_Error( 17, __( 'The source URL does not contain a link to the target URL, and so cannot be used as a source.' ) ); 3975 return $this->error; 3976 } 3977 3978 // Add whacky prefix and suffix to the excerpt and sanitize 3979 $excerpt = '[...] ' . esc_html( $excerpt ) . ' [...]'; 3980 $this->escape( $excerpt ); 3981 3982 // Build an array of post data to insert then insert a new post 3983 $postdata = array( 3984 'topic_id' => $topic_to->topic_id, 3985 'post_text' => $excerpt, 3986 'poster_id' => 0, 3987 ); 3988 if ( !$post_ID = bb_insert_post( $postdata ) ) { 3989 $this->error = new IXR_Error( 0, __( 'The pingback could not be added.' ) ); 3990 return $this->error; 3991 } 3992 3993 // Add meta to let us know where the pingback came from 3994 $link_from = str_replace( '&', '&', $link_from ); 3995 $this->escape( $link_from ); 3996 bb_update_postmeta( $post_ID, 'pingback_uri', $link_from ); 3997 3998 // Add the title to meta 3999 $this->escape( $link_from_title ); 4000 bb_update_postmeta( $post_ID, 'pingback_title', $link_from_title ); 4001 4002 // Action for plugins and what not 4003 do_action( 'bb_pingback_post', $post_ID ); 4004 4005 // Return success message, complete with emoticon 4006 return sprintf( __( 'Pingback from %1$s to %2$s registered. Keep the web talking! :-)' ), $link_from, $link_to ); 4007 } 4008 4009 4010 4011 /** 4012 * Returns an array of URLs that pingbacked the given URL 4013 * 4014 * @since 1.0 4015 * @link http://www.aquarionics.com/misc/archives/blogite/0198.html 4016 * @return array The array of URLs that pingbacked the given topic 4017 * @param array $args Arguments passed by the XML-RPC call 4018 * @param string $args[0] The full URI of the post where the pingback is being sent from 4019 * @param string $args[1] The full URI of the post where the pingback is being sent to 4020 * 4021 * XML-RPC request to get all pingbacks on a topic 4022 * <methodCall> 4023 * <methodName>pingback.ping</methodName> 4024 * <params> 4025 * <param><value><string>http://example.com/2008/08/post-tobe-queried/</string></value></param> 4026 * </params> 4027 * </methodCall> 4028 */ 4029 function pingback_extensions_getPingbacks( $args ) 4030 { 4031 do_action( 'bb_xmlrpc_call', 'pingback.extensions.getPingbacks' ); 4032 4033 $this->escape( $args ); 4034 4035 // Don't accept arrays of arguments 4036 if ( is_array( $args ) ) { 4037 $this->error = new IXR_Error( 404, __( 'The requested method only accepts one parameter.' ) ); 4038 return $this->error; 4039 } else { 4040 $url = (string) $args; 4041 } 4042 4043 // Tidy up ampersands in the URI 4044 $url = str_replace( '&', '&', $url ); 4045 $url = str_replace( '&', '&', $url ); 4046 4047 // Check if the URI is in our site 4048 if ( !bb_match_domains( $url, bb_get_uri() ) ) { 4049 // These are not the droids you are looking for 4050 $this->error = new IXR_Error( 0, __( 'The specified target URL is not on this domain.' ) ); 4051 return $this->error; 4052 } 4053 4054 // Make sure the specified URI is in fact associated with a topic 4055 if ( !$topic = bb_get_topic_from_uri( $url ) ) { 4056 $this->error = new IXR_Error( 33, __( 'The specified target URL cannot be used as a target. It either doesn\'t exist, or it is not a pingback-enabled resource.' ) ); 4057 return $this->error; 4058 } 4059 4060 // Grab the posts from the topic 4061 $query = new BB_Query( 'post', array( 'topic_id' => $topic_to->topic_id, 'append_meta' => true ), 'get_thread' ); 4062 $posts_to = $query->results; 4063 unset( $query ); 4064 4065 // Check for pingbacks in the post meta data 4066 $pingbacks = array(); 4067 foreach ( $posts_to as $post ) { 4068 if ( isset( $post->pingback_uri ) ) { 4069 $pingbacks[] = $post->pingback_uri; 4070 } 4071 } 4072 unset( $post ); 4073 4074 // This will return an empty array on failure 4075 return $pingbacks; 4076 } 4077 } 4078 4079 4080 4081 /** 4082 * Initialises the XML-RPC server 4083 * 4084 * @since 1.0 4085 * @var object The instance of the XML-RPC server class 4086 */ 4087 $bb_xmlrpc_server = new BB_XMLRPC_Server();
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Wed May 22 03:58:36 2013 | Hosted by follow the white rabbit. |