[ Index ] |
PHP Cross Reference of BuddyPress |
[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 // Load the XML-RPC server/client classes 55 if ( ! class_exists( 'IXR_Value' ) ) { 56 require_once( BACKPRESS_PATH . '/class.ixr.php' ); 57 } 58 59 /** 60 * XML-RPC server class to allow for remote publishing 61 * 62 * @since 1.0 63 * @package bbPress 64 * @subpackage Publishing 65 * @uses class IXR_Server 66 */ 67 class BB_XMLRPC_Server extends IXR_Server 68 { 69 /** 70 * Stores the last error generated by the class 71 * 72 * @since 1.0 73 * @var object|boolean An instance of the IXR_Error class or false if no error exists 74 */ 75 var $error = false; 76 77 /** 78 * Site options which can be manipulated using XML-RPC 79 * 80 * @since 1.0 81 * @var array 82 */ 83 var $site_options = array(); 84 85 /** 86 * Whether read-only methods require authentication 87 * 88 * @since 1.0 89 * @var boolean 90 **/ 91 var $auth_readonly = false; 92 93 /** 94 * Whether user switching is allowed 95 * 96 * @since 1.0 97 * @var boolean 98 **/ 99 var $allow_user_switching = false; 100 101 /** 102 * Initialises the XML-RPC server 103 * 104 * @since 1.0 105 * @return void 106 */ 107 function __construct() 108 { 109 // bbPress publishing API 110 if ( bb_get_option( 'enable_xmlrpc' ) ) { 111 $this->methods = array( 112 // - Demo 113 'demo.sayHello' => 'this:sayHello', 114 'demo.addTwoNumbers' => 'this:addTwoNumbers', 115 // - Forums 116 'bb.getForumCount' => 'this:bb_getForumCount', 117 'bb.getForums' => 'this:bb_getForums', 118 'bb.getForum' => 'this:bb_getForum', 119 'bb.newForum' => 'this:bb_newForum', 120 'bb.editForum' => 'this:bb_editForum', 121 'bb.deleteForum' => 'this:bb_deleteForum', 122 // - Topics 123 'bb.getTopicCount' => 'this:bb_getTopicCount', 124 'bb.getTopics' => 'this:bb_getTopics', 125 'bb.getTopic' => 'this:bb_getTopic', 126 'bb.newTopic' => 'this:bb_newTopic', 127 'bb.editTopic' => 'this:bb_editTopic', 128 'bb.deleteTopic' => 'this:bb_deleteTopic', // Also undeletes 129 'bb.moveTopic' => 'this:bb_moveTopic', 130 'bb.stickTopic' => 'this:bb_stickTopic', // Also unsticks 131 'bb.closeTopic' => 'this:bb_closeTopic', // Also opens 132 'bb.getTopicStatusList' => 'this:bb_getTopicStatusList', 133 // - Posts (replies) 134 'bb.getPostCount' => 'this:bb_getPostCount', 135 'bb.getPosts' => 'this:bb_getPosts', 136 'bb.getPost' => 'this:bb_getPost', 137 'bb.newPost' => 'this:bb_newPost', 138 'bb.editPost' => 'this:bb_editPost', 139 'bb.deletePost' => 'this:bb_deletePost', // Also undeletes 140 'bb.getPostStatusList' => 'this:bb_getPostStatusList', 141 // - Topic Tags 142 'bb.getHotTopicTags' => 'this:bb_getHotTopicTags', 143 'bb.getTopicTagCount' => 'this:bb_getTopicTagCount', 144 'bb.getTopicTags' => 'this:bb_getTopicTags', 145 'bb.getTopicTag' => 'this:bb_getTopicTag', 146 'bb.addTopicTags' => 'this:bb_addTopicTags', 147 'bb.removeTopicTags' => 'this:bb_removeTopicTags', 148 'bb.renameTopicTag' => 'this:bb_renameTopicTag', 149 'bb.mergeTopicTags' => 'this:bb_mergeTopicTags', 150 'bb.destroyTopicTag' => 'this:bb_destroyTopicTag', 151 // - Options 152 'bb.getOptions' => 'this:bb_getOptions', 153 'bb.setOptions' => 'this:bb_setOptions' 154 ); 155 } 156 157 // Pingback 158 if ( bb_get_option( 'enable_pingback' ) ) { 159 $this->methods = array_merge( (array)$this->methods, array( 160 'pingback.ping' => 'this:pingback_ping', 161 'pingback.extensions.getPingbacks' => 'this:pingback_extensions_getPingbacks' 162 ) ); 163 } 164 165 // Tells read-only methods whether they require authentication or not 166 $this->auth_readonly = apply_filters( 'bb_xmlrpc_auth_readonly', $this->auth_readonly ); 167 168 // Whether or not to allow user switching 169 $this->allow_user_switching = bb_get_option( 'bb_xmlrpc_allow_user_switching' ); 170 171 $this->initialise_site_option_info(); 172 $this->methods = apply_filters( 'bb_xmlrpc_methods', $this->methods ); 173 $this->IXR_Server( $this->methods ); 174 } 175 176 function BB_XMLRPC_Server() 177 { 178 $this->__construct(); 179 } 180 181 /** 182 * Utility methods 183 */ 184 185 /** 186 * Checks the user credentials supplied in the request to make sure they are valid 187 * 188 * @since 1.0 189 * @return integer|boolean The user id if the user is valid, otherwise false 190 * @param string $user_login The users login 191 * @param string $user_pass The users password in plain text 192 * @param string $capability The capability to check (optional) 193 * @param string $message The message to pass back in the error if the capability check fails (optional) 194 */ 195 function authenticate( $user_login, $user_pass, $capability = 'read', $message = false ) 196 { 197 if ( is_array( $user_login ) ) { 198 $auth_user_login = (string) $user_login[0]; 199 $switch_user_login = (string) $user_login[1]; 200 } else { 201 $auth_user_login = (string) $user_login; 202 $switch_user_login = false; 203 } 204 205 // Check the login 206 $user = bb_check_login( $auth_user_login, $user_pass ); 207 if ( !$user || is_wp_error( $user ) ) { 208 $this->error = new IXR_Error( 403, __( 'Authentication failed.' ) ); 209 return false; 210 } 211 212 // Set the current user 213 $user = bb_set_current_user( $user->ID ); 214 215 // Make sure they are allowed to do this 216 if ( !bb_current_user_can( $capability ) ) { 217 if ( !$message ) { 218 $message = __( 'You do not have permission to read this.' ); 219 } 220 $this->error = new IXR_Error( 403, $message ); 221 return false; 222 } 223 224 // Switch the user if requested and allowed 225 if ( $switch_user_login && $this->allow_user_switching && bb_current_user_can( 'edit_users' ) ) { 226 $user = $this->switch_user( $switch_user_login, $capability, $message ); 227 } 228 229 return $user; 230 } 231 232 /** 233 * Switches the currently active user for incognito actions 234 * 235 * @since 1.0 236 * @return integer|boolean The user id if the user is valid, otherwise false 237 * @param string $user_login The users login 238 * @param string $capability The capability to check (optional) 239 * @param string $message The message to pass back in the error if the capability check fails (optional) 240 */ 241 function switch_user( $user_login, $capability = 'read', $message = false ) 242 { 243 // Just get the user, authentication has already been established by the 244 $user = bb_get_user( $user_login, array( 'by' => 'login' ) ); 245 if ( !$user || is_wp_error( $user ) ) { 246 $this->error = new IXR_Error( 400, __( 'User switching failed, the requested user does not exist.' ) ); 247 return false; 248 } 249 250 // Set the current user 251 $user = bb_set_current_user( $user->ID ); 252 253 // Make sure they are allowed to do this 254 if ( !bb_current_user_can( $capability ) ) { 255 if ( !$message ) { 256 $message = __( 'You do not have permission to read this.' ); 257 } 258 $this->error = new IXR_Error( 403, $message ); 259 return false; 260 } 261 262 return $user; 263 } 264 265 /** 266 * Sanitises data from XML-RPC request parameters 267 * 268 * @since 1.0 269 * @return mixed The sanitised variable, should come back with the same type 270 * @param $array mixed The variable to be sanitised 271 * @uses $bbdb BackPress database class instance 272 */ 273 function escape( &$array ) 274 { 275 global $bbdb; 276 277 if ( !is_array( $array ) ) { 278 // Escape it 279 $array = $bbdb->escape( $array ); 280 } elseif ( count( $array ) ) { 281 foreach ( (array) $array as $k => $v ) { 282 if ( is_array( $v ) ) { 283 // Recursively sanitize arrays 284 $this->escape( $array[$k] ); 285 } elseif ( is_object( $v ) ) { 286 // Don't sanitise objects - shouldn't happen anyway 287 } else { 288 // Escape it 289 $array[$k] = $bbdb->escape( $v ); 290 } 291 } 292 } 293 294 return $array; 295 } 296 297 /** 298 * Prepares forum data for return in an XML-RPC object 299 * 300 * @since 1.0 301 * @return array The prepared forum data 302 * @param array|object The unprepared forum data 303 **/ 304 function prepare_forum( $forum ) 305 { 306 // Cast to an array 307 $_forum = (array) $forum; 308 // Set the URI 309 $_forum['forum_uri'] = get_forum_link( $_forum['forum_id'] ); 310 // Give this a definite value 311 if ( !isset( $_forum['forum_is_category'] ) ) { 312 $_forum['forum_is_category'] = 0; 313 } 314 // Allow plugins to modify the data 315 return apply_filters( 'bb_xmlrpc_prepare_forum', $_forum, (array) $forum ); 316 } 317 318 /** 319 * Prepares topic data for return in an XML-RPC object 320 * 321 * @since 1.0 322 * @return array The prepared topic data 323 * @param array|object The unprepared topic data 324 **/ 325 function prepare_topic( $topic ) 326 { 327 // Cast to an array 328 $_topic = (array) $topic; 329 // Set the URI 330 $_topic['topic_uri'] = get_topic_link( $_topic['topic_id'] ); 331 // Set readable times 332 $_topic['topic_start_time_since'] = bb_since( $_topic['topic_start_time'] ); 333 $_topic['topic_time_since'] = bb_since( $_topic['topic_time'] ); 334 // Set the display names 335 $_topic['topic_poster_display_name'] = get_user_display_name( $_topic['topic_poster'] ); 336 $_topic['topic_last_poster_display_name'] = get_user_display_name( $_topic['topic_last_poster'] ); 337 // Remove some sensitive user ids 338 unset( 339 $_topic['topic_poster'], 340 $_topic['topic_last_poster'] 341 ); 342 // Allow plugins to modify the data 343 return apply_filters( 'bb_xmlrpc_prepare_topic', $_topic, (array) $topic ); 344 } 345 346 /** 347 * Prepares post data for return in an XML-RPC object 348 * 349 * @since 1.0 350 * @return array The prepared post data 351 * @param array|object The unprepared post data 352 **/ 353 function prepare_post( $post ) 354 { 355 // Cast to an array 356 $_post = (array) $post; 357 // Set the URI 358 $_post['post_uri'] = get_post_link( $_post['post_id'] ); 359 // Set readable times 360 $_post['post_time_since'] = bb_since( $_post['post_time'] ); 361 // Set the display names 362 $_post['poster_display_name'] = get_user_display_name( $_post['poster_id'] ); 363 // Remove some sensitive data 364 unset( 365 $_post['poster_id'], 366 $_post['poster_ip'], 367 $_post['pingback_queued'] 368 ); 369 // Allow plugins to modify the data 370 return apply_filters( 'bb_xmlrpc_prepare_post', $_post, (array) $post ); 371 } 372 373 /** 374 * Prepares topic tag data for return in an XML-RPC object 375 * 376 * @since 1.0 377 * @return array The prepared topic tag data 378 * @param array|object The unprepared topic tag data 379 **/ 380 function prepare_topic_tag( $tag ) 381 { 382 // Cast to an array 383 $_tag = (array) $tag; 384 // Set the URI 385 $_tag['topic_tag_uri'] = bb_get_tag_link( $tag ); 386 // Consistent nomenclature 387 $_tag['topic_tag_name'] = (string) $_tag['name']; 388 $_tag['topic_tag_slug'] = (string) $_tag['slug']; 389 $_tag['topic_tag_count'] = (int) $_tag['count']; 390 // Remove some sensitive data 391 unset( 392 $_tag['object_id'], 393 $_tag['name'], 394 $_tag['slug'], 395 $_tag['count'], 396 $_tag['term_id'], 397 $_tag['term_group'], 398 $_tag['term_taxonomy_id'], 399 $_tag['taxonomy'], 400 $_tag['description'], 401 $_tag['parent'], 402 $_tag['count'], 403 $_tag['user_id'], 404 $_tag['tag_id'], 405 $_tag['tag'], 406 $_tag['raw_tag'], 407 $_tag['tag_count'] 408 ); 409 // Allow plugins to modify the data 410 return apply_filters( 'bb_xmlrpc_prepare_topic_tag', $_tag, (array) $tag ); 411 } 412 413 414 415 /** 416 * bbPress publishing API - Demo XML-RPC methods 417 */ 418 419 /** 420 * Hello world demo function for XML-RPC 421 * 422 * @since 1.0 423 * @return string The phrase 'Hello!' 424 * @param array $args Arguments passed by the XML-RPC call 425 * @param string $args[0] The username for authentication 426 * @param string $args[1] The password for authentication 427 * 428 * XML-RPC request to get a greeting 429 * <methodCall> 430 * <methodName>demo.sayHello</methodName> 431 * <params> 432 * <param><value><string>joeblow</string></value></param> 433 * <param><value><string>123password</string></value></param> 434 * </params> 435 * </methodCall> 436 */ 437 function sayHello( $args ) 438 { 439 // Escape args 440 $this->escape( $args ); 441 442 // Get the login credentials 443 $username = $args[0]; 444 $password = (string) $args[1]; 445 446 // Check the user is valid 447 if ( $this->auth_readonly && !$this->authenticate( $username, $password ) ) { 448 return $this->error; 449 } 450 451 return 'Hello!'; 452 } 453 454 /** 455 * Adds two numbers together as a demo of XML-RPC 456 * 457 * @since 1.0 458 * @return integer The sum of the two supplied numbers 459 * @param array $args Arguments passed by the XML-RPC call 460 * @param string $args[0] The username for authentication 461 * @param string $args[1] The password for authentication 462 * @param integer $args[2] The first number to be added 463 * @param integer $args[3] The second number to be added 464 * 465 * XML-RPC request to get the sum of two numbers 466 * <methodCall> 467 * <methodName>demo.addTwoNumbers</methodName> 468 * <params> 469 * <param><value><string>joeblow</string></value></param> 470 * <param><value><string>123password</string></value></param> 471 * <param><value><int>5</int></value></param> 472 * <param><value><int>102</int></value></param> 473 * </params> 474 * </methodCall> 475 */ 476 function addTwoNumbers( $args ) 477 { 478 // Escape args 479 $this->escape( $args ); 480 481 // Get the login credentials 482 $username = $args[0]; 483 $password = (string) $args[1]; 484 485 // Check the user is valid 486 if ( $this->auth_readonly && !$this->authenticate( $username, $password ) ) { 487 return $this->error; 488 } 489 490 $number1 = (int) $args[2]; 491 $number2 = (int) $args[3]; 492 493 return ( $number1 + $number2 ); 494 } 495 496 497 498 /** 499 * bbPress publishing API - Forum XML-RPC methods 500 */ 501 502 /** 503 * Returns a numerical count of forums 504 * 505 * @since 1.0 506 * @return integer|object The number of forums when successfully executed or an IXR_Error object on failure 507 * @param array $args Arguments passed by the XML-RPC call 508 * @param string $args[0] The username for authentication 509 * @param string $args[1] The password for authentication 510 * @param integer|string $args[2] The parent forum's id or slug (optional) 511 * @param integer $args[3] The depth of child forums to retrieve (optional) 512 * 513 * XML-RPC request to get a count of all forums in the bbPress instance 514 * <methodCall> 515 * <methodName>bb.getForumCount</methodName> 516 * <params> 517 * <param><value><string>joeblow</string></value></param> 518 * <param><value><string>123password</string></value></param> 519 * </params> 520 * </methodCall> 521 * 522 * XML-RPC request to get a count of all child forums in the forum with id number 34 523 * <methodCall> 524 * <methodName>bb.getForumCount</methodName> 525 * <params> 526 * <param><value><string>joeblow</string></value></param> 527 * <param><value><string>123password</string></value></param> 528 * <param><value><int>34</int></value></param> 529 * </params> 530 * </methodCall> 531 * 532 * XML-RPC request to get a count of all child forums in the forum with slug "first-forum" 533 * <methodCall> 534 * <methodName>bb.getForumCount</methodName> 535 * <params> 536 * <param><value><string>joeblow</string></value></param> 537 * <param><value><string>123password</string></value></param> 538 * <param><value><string>first-forum</string></value></param> 539 * </params> 540 * </methodCall> 541 * 542 * 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 543 * <methodCall> 544 * <methodName>bb.getForumCount</methodName> 545 * <params> 546 * <param><value><string>joeblow</string></value></param> 547 * <param><value><string>123password</string></value></param> 548 * <param><value><int>34</int></value></param> 549 * <param><value><int>2</int></value></param> 550 * </params> 551 * </methodCall> 552 */ 553 function bb_getForumCount( $args ) 554 { 555 do_action( 'bb_xmlrpc_call', 'bb.getForumCount' ); 556 557 // Escape args 558 $this->escape( $args ); 559 560 // Get the login credentials 561 $username = $args[0]; 562 $password = (string) $args[1]; 563 564 // Check the user is valid 565 if ( $this->auth_readonly ) { 566 $user = $this->authenticate( $username, $password ); 567 } 568 569 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getForumCount' ); 570 571 // If an error was raised by authentication or by an action then return it 572 if ( $this->error ) { 573 return $this->error; 574 } 575 576 // Setup an array to store arguments to pass to bb_get_forums() function 577 $get_forums_args = array( 578 'child_of' => 0, 579 'hierarchical' => 0, 580 'depth' => 0 581 ); 582 583 // Can be numeric id or slug 584 $forum_id = isset( $args[2] ) ? $args[2] : false; 585 586 if ( $forum_id ) { 587 // Check for bad data 588 if ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) { 589 $this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) ); 590 return $this->error; 591 } 592 // Check the requested forum exists 593 if ( !$forum = bb_get_forum( $forum_id ) ) { 594 $this->error = new IXR_Error( 400, __( 'The forum does not exist.' ) ); 595 return $this->error; 596 } 597 // Add the specific forum to the arguments 598 $get_forums_args['child_of'] = (int) $forum->forum_id; 599 } 600 601 // Can only be an integer 602 $depth = (int) $args[3]; 603 604 if ( $depth > 0 ) { 605 // Add the depth to traverse to the arguments 606 $get_forums_args['depth'] = $depth; 607 // Only make it hierarchical if the depth > 1 608 if ( $depth > 1 ) { 609 $get_forums_args['hierarchical'] = 1; 610 } 611 } 612 613 // Get the forums. Return 0 when no forums exist 614 if ( !$forums = bb_get_forums( $get_forums_args ) ) { 615 $count = 0; 616 } else { 617 $count = count( $forums ); 618 } 619 620 do_action( 'bb_xmlrpc_call_return', 'bb.getForumCount' ); 621 622 // Return a count of the forums 623 return $count; 624 } 625 626 /** 627 * Returns details of multiple forums 628 * 629 * @since 1.0 630 * @return array|object An array containing details of all returned forums when successfully executed or an IXR_Error object on failure 631 * @param array $args Arguments passed by the XML-RPC call 632 * @param string $args[0] The username for authentication 633 * @param string $args[1] The password for authentication 634 * @param integer|string $args[2] The parent forum's id or slug (optional) 635 * @param integer $args[3] The depth of child forums to retrieve (optional) 636 * 637 * XML-RPC request to get all forums in the bbPress instance 638 * <methodCall> 639 * <methodName>bb.getForums</methodName> 640 * <params> 641 * <param><value><string>joeblow</string></value></param> 642 * <param><value><string>123password</string></value></param> 643 * </params> 644 * </methodCall> 645 * 646 * XML-RPC request to get all child forums in the forum with id number 34 647 * <methodCall> 648 * <methodName>bb.getForums</methodName> 649 * <params> 650 * <param><value><string>joeblow</string></value></param> 651 * <param><value><string>123password</string></value></param> 652 * <param><value><int>34</int></value></param> 653 * </params> 654 * </methodCall> 655 * 656 * XML-RPC request to get all child forums in the forum with slug "first-forum" 657 * <methodCall> 658 * <methodName>bb.getForums</methodName> 659 * <params> 660 * <param><value><string>joeblow</string></value></param> 661 * <param><value><string>123password</string></value></param> 662 * <param><value><string>first-forum</string></value></param> 663 * </params> 664 * </methodCall> 665 * 666 * XML-RPC request to get all child forums in the forum with id number 34 no more than 2 forums deep in the hierarchy 667 * <methodCall> 668 * <methodName>bb.getForums</methodName> 669 * <params> 670 * <param><value><string>joeblow</string></value></param> 671 * <param><value><string>123password</string></value></param> 672 * <param><value><int>34</int></value></param> 673 * <param><value><int>2</int></value></param> 674 * </params> 675 * </methodCall> 676 */ 677 function bb_getForums( $args ) 678 { 679 do_action( 'bb_xmlrpc_call', 'bb.getForums' ); 680 681 // Escape args 682 $this->escape( $args ); 683 684 // Get the login credentials 685 $username = $args[0]; 686 $password = (string) $args[1]; 687 688 // Check the user is valid 689 if ( $this->auth_readonly ) { 690 $user = $this->authenticate( $username, $password ); 691 } 692 693 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getForums' ); 694 695 // If an error was raised by authentication or by an action then return it 696 if ( $this->error ) { 697 return $this->error; 698 } 699 700 // Setup an array to store arguments to pass to bb_get_forums() function 701 $get_forums_args = array( 702 'child_of' => 0, 703 'hierarchical' => 0, 704 'depth' => 0 705 ); 706 707 // Can be numeric id or slug 708 $forum_id = isset( $args[2] ) ? $args[2] : false; 709 710 if ( $forum_id ) { 711 // Check for bad data 712 if ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) { 713 $this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) ); 714 return $this->error; 715 } 716 // First check the requested forum exists 717 if ( !$forum = bb_get_forum( $forum_id ) ) { 718 $this->error = new IXR_Error( 400, __( 'The forum does not exist.' ) ); 719 return $this->error; 720 } 721 // Add the specific forum to the arguments 722 $get_forums_args['child_of'] = (int) $forum->forum_id; 723 } 724 725 // Can only be an integer 726 $depth = (int) $args[3]; 727 728 if ( $depth > 0 ) { 729 // Add the depth to traverse to to the arguments 730 $get_forums_args['depth'] = $depth; 731 // Only make it hierarchical if the depth > 1 732 if ( $depth > 1 ) { 733 $get_forums_args['hierarchical'] = 1; 734 } 735 } 736 737 // Get the forums. Return an error when no forums exist 738 if ( !$forums = bb_get_forums( $get_forums_args ) ) { 739 $this->error = new IXR_Error( 404, __( 'No forums found.' ) ); 740 return $this->error; 741 } 742 743 // Only include "safe" data in the array 744 $_forums = array(); 745 foreach ( $forums as $forum ) { 746 $_forums[] = $this->prepare_forum( $forum ); 747 } 748 749 do_action( 'bb_xmlrpc_call_return', 'bb.getForums' ); 750 751 // Return the forums 752 return $_forums; 753 } 754 755 /** 756 * Returns details of a forum 757 * 758 * @since 1.0 759 * @return array|object An array containing details of the returned forum when successfully executed or an IXR_Error object on failure 760 * @param string $args[0] The username for authentication 761 * @param string $args[1] The password for authentication 762 * @param integer|string $args[2] The forum's id or slug 763 * 764 * XML-RPC request to get the forum with id number 34 765 * <methodCall> 766 * <methodName>bb.getForum</methodName> 767 * <params> 768 * <param><value><string>joeblow</string></value></param> 769 * <param><value><string>123password</string></value></param> 770 * <param><value><int>34</int></value></param> 771 * </params> 772 * </methodCall> 773 * 774 * XML-RPC request to get the forum with slug "first-forum" 775 * <methodCall> 776 * <methodName>bb.getForum</methodName> 777 * <params> 778 * <param><value><string>joeblow</string></value></param> 779 * <param><value><string>123password</string></value></param> 780 * <param><value><string>first-forum</string></value></param> 781 * </params> 782 * </methodCall> 783 */ 784 function bb_getForum( $args ) 785 { 786 do_action( 'bb_xmlrpc_call', 'bb.getForum' ); 787 788 // Escape args 789 $this->escape( $args ); 790 791 // Get the login credentials 792 $username = $args[0]; 793 $password = (string) $args[1]; 794 795 // Check the user is valid 796 if ( $this->auth_readonly ) { 797 $user = $this->authenticate( $username, $password ); 798 } 799 800 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getForum' ); 801 802 // If an error was raised by authentication or by an action then return it 803 if ( $this->error ) { 804 return $this->error; 805 } 806 807 // Can be numeric id or slug 808 $forum_id = isset( $args[2] ) ? $args[2] : false; 809 810 // Check for bad data 811 if ( !$forum_id || ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) ) { 812 $this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) ); 813 return $this->error; 814 } 815 816 // Check the requested forum exists 817 if ( !$forum = bb_get_forum( $forum_id ) ) { 818 $this->error = new IXR_Error( 404, __( 'No forum found.' ) ); 819 return $this->error; 820 } 821 822 // Only include "safe" data in the array 823 $forum = $this->prepare_forum( $forum ); 824 825 do_action( 'bb_xmlrpc_call_return', 'bb.getForum' ); 826 827 // Return the forums 828 return $forum; 829 } 830 831 /** 832 * Creates a new forum 833 * 834 * @since 1.0 835 * @return array|object The forum data when successfully created or an IXR_Error object on failure 836 * @param array $args Arguments passed by the XML-RPC call 837 * @param string $args[0] The username for authentication 838 * @param string $args[1] The password for authentication 839 * @param array $args[2] The values for the various settings in the new forum 840 * @param string $args[2]['name'] The name of the forum 841 * @param string $args[2]['description'] The description of the forum (optional) 842 * @param integer|string $args[2]['parent_id'] The unique id of the parent forum for this forum (optional) 843 * @param integer $args[2]['order'] The position of the forum in the forum list (optional) 844 * @param integer $args[2]['is_category'] Whether the forum is simply a container category (optional) 845 * 846 * XML-RPC request to create a new sub-forum called "A new forum" inside the parent forum with id 2 847 * <methodCall> 848 * <methodName>bb.newForum</methodName> 849 * <params> 850 * <param><value><string>joeblow</string></value></param> 851 * <param><value><string>123password</string></value></param> 852 * <param><value><struct> 853 * <member> 854 * <name>name</name> 855 * <value><string>A new forum</string></value> 856 * </member> 857 * <member> 858 * <name>parent_id</name> 859 * <value><integer>2</integer></value> 860 * </member> 861 * </struct></value></param> 862 * </params> 863 * </methodCall> 864 */ 865 function bb_newForum( $args ) 866 { 867 do_action( 'bb_xmlrpc_call', 'bb.newForum' ); 868 869 // Escape args 870 $this->escape( $args ); 871 872 // Get the login credentials 873 $username = $args[0]; 874 $password = (string) $args[1]; 875 876 // Check the user is valid 877 $user = $this->authenticate( $username, $password, 'manage_forums', __( 'You do not have permission to manage forums.' ) ); 878 879 do_action( 'bb_xmlrpc_call_authenticated', 'bb.newForum' ); 880 881 // If an error was raised by authentication or by an action then return it 882 if ( $this->error ) { 883 return $this->error; 884 } 885 886 // Make sure there is something for us to do 887 if ( !$args[2] || !is_array( $args[2] ) || !count( $args[2] ) ) { 888 $this->error = new IXR_Error( 400, __( 'The forum data is invalid.' ) ); 889 return $this->error; 890 } 891 892 $structure = (array) $args[2]; 893 894 // Minimum requirement is a name for the new forum 895 if ( !isset( $structure['name'] ) || !$structure['name'] ) { 896 $this->error = new IXR_Error( 400, __( 'The forum name is invalid.' ) ); 897 return $this->error; 898 } 899 900 // Inject structure into an array suitable for bb_new_forum() 901 $bb_new_forum_args = array( 902 'forum_name' => (string) $structure['name'], 903 'forum_desc' => (string) $structure['description'], 904 'forum_parent' => (int) $structure['parent_id'], 905 'forum_order' => (int) $structure['order'], 906 'forum_is_category' => (int) $structure['is_category'] 907 ); 908 909 // Remove empty settings so that changes to the defaults in bb_new_forum() are honoured 910 $bb_new_forum_args = array_filter( $bb_new_forum_args ); 911 912 // Leave the require until the very end 913 require_once ( BB_PATH . 'bb-admin/includes/functions.bb-admin.php' ); 914 915 // Create the forum 916 if ( !$forum_id = (int) bb_new_forum( $bb_new_forum_args ) ) { 917 $this->error = new IXR_Error( 500, __( 'The forum could not be created.' ) ); 918 return $this->error; 919 } 920 921 // Only include "safe" data in the array 922 $forum = $this->prepare_forum( bb_get_forum( $forum_id ) ); 923 924 do_action( 'bb_xmlrpc_call_return', 'bb.newForum' ); 925 926 return $forum; 927 } 928 929 /** 930 * Edits an existing forum 931 * 932 * @since 1.0 933 * @return array|object The forum data when successfully edited or an IXR_Error object on failure 934 * @param array $args Arguments passed by the XML-RPC call 935 * @param string $args[0] The username for authentication 936 * @param string $args[1] The password for authentication 937 * @param array $args[2] The values for the various settings in the new forum, at least one must be specified 938 * @param integer|string $args[2]['forum_id'] The unique id of the forum to be edited 939 * @param string $args[2]['name'] The name of the forum (optional) 940 * @param string $args[2]['slug'] The slug for the forum (optional) 941 * @param string $args[2]['description'] The description of the forum (optional) 942 * @param integer $args[2]['parent_id'] The unique id of the parent forum for this forum (optional) 943 * @param integer $args[2]['order'] The position of the forum in the forum list (optional) 944 * @param integer $args[2]['is_category'] Whether the forum is simply a container category (optional) 945 * 946 * XML-RPC request to edit a forum with id 11, changing the description 947 * <methodCall> 948 * <methodName>bb.editForum</methodName> 949 * <params> 950 * <param><value><string>joeblow</string></value></param> 951 * <param><value><string>123password</string></value></param> 952 * <param><value><struct> 953 * <member> 954 * <name>forum_id</name> 955 * <value><integer>11</integer></value> 956 * </member> 957 * <member> 958 * <name>description</name> 959 * <value><string>This is a great forum for all sorts of reasons.</string></value> 960 * </member> 961 * </struct></value></param> 962 * </params> 963 * </methodCall> 964 */ 965 function bb_editForum( $args ) 966 { 967 do_action( 'bb_xmlrpc_call', 'bb.editForum' ); 968 969 // Escape args 970 $this->escape( $args ); 971 972 // Get the login credentials 973 $username = $args[0]; 974 $password = (string) $args[1]; 975 976 // Check the user is valid 977 $user = $this->authenticate( $username, $password, 'manage_forums', __( 'You do not have permission to manage forums.' ) ); 978 979 do_action( 'bb_xmlrpc_call_authenticated', 'bb.editForum' ); 980 981 // If an error was raised by authentication or by an action then return it 982 if ( $this->error ) { 983 return $this->error; 984 } 985 986 // Make sure there is something for us to do 987 if ( !$args[2] || !is_array( $args[2] ) || !count( $args[2] ) ) { 988 $this->error = new IXR_Error( 400, __( 'The forum data is invalid.' ) ); 989 return $this->error; 990 } 991 992 $structure = (array) $args[2]; 993 994 // Can be numeric id or slug 995 $forum_id = isset( $structure['forum_id'] ) ? $structure['forum_id'] : false; 996 997 // Check for bad data 998 if ( !$forum_id || ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) ) { 999 $this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) ); 1000 return $this->error; 1001 } 1002 1003 // Check the requested forum exists 1004 if ( !$forum = bb_get_forum( $forum_id ) ) { 1005 $this->error = new IXR_Error( 400, __( 'No forum found.' ) ); 1006 return $this->error; 1007 } 1008 1009 // Cast the forum object as an array 1010 $forum = (array) $forum; 1011 // The forum id may have been a slug, so make sure it's an integer here 1012 $forum_id = (int) $forum['forum_id']; 1013 1014 // Remove some unneeded indexes 1015 unset( $forum['topics'] ); 1016 unset( $forum['posts'] ); 1017 1018 // Add one if it isn't there 1019 if ( !isset( $forum['forum_is_category'] ) ) { 1020 $forum['forum_is_category'] = 0; 1021 } 1022 1023 // Validate the name for the forum 1024 if ( isset( $structure['name'] ) && !$structure['name'] ) { 1025 $this->error = new IXR_Error( 400, __( 'The forum name is invalid.' ) ); 1026 return $this->error; 1027 } 1028 1029 // Inject structure into an array suitable for bb_update_forum() 1030 $bb_update_forum_args = array( 1031 'forum_name' => $structure['name'] 1032 ); 1033 1034 // Slug cannot be blank 1035 if ( isset( $structure['slug'] ) && $structure['slug'] !== '' ) { 1036 $bb_update_forum_args['forum_slug'] = $structure['slug']; 1037 } 1038 1039 // Description can be nothing 1040 if ( isset( $structure['description'] ) ) { 1041 $bb_update_forum_args['forum_desc'] = $structure['description']; 1042 } 1043 1044 // Parent forum ID must be an integer and it can be 0 1045 if ( isset( $structure['parent_id'] ) && is_integer( $structure['parent_id'] ) ) { 1046 $bb_update_forum_args['forum_parent'] = $structure['parent_id']; 1047 } 1048 1049 // Order must be an integer and it can be 0 1050 if ( isset( $structure['order'] ) && is_integer( $structure['order'] ) ) { 1051 $bb_update_forum_args['forum_order'] = $structure['order']; 1052 } 1053 1054 // Category flag must be an integer and it can be 0 1055 if ( isset( $structure['is_category'] ) && is_integer( $structure['is_category'] ) ) { 1056 $bb_update_forum_args['forum_is_category'] = $structure['is_category']; 1057 } 1058 1059 // Merge the changes into the existing data for the forum 1060 $bb_update_forum_args = wp_parse_args( $bb_update_forum_args, $forum ); 1061 1062 // Leave the require until the very end 1063 require_once ( BB_PATH . 'bb-admin/includes/functions.bb-admin.php' ); 1064 1065 // Update the forum 1066 if ( !bb_update_forum( $bb_update_forum_args ) ) { 1067 $this->error = new IXR_Error( 500, __( 'The forum could not be edited.' ) ); 1068 return $this->error; 1069 } 1070 1071 // Only include "safe" data in the array 1072 $forum = $this->prepare_forum( bb_get_forum( $forum_id ) ); 1073 1074 do_action( 'bb_xmlrpc_call_return', 'bb.editForum' ); 1075 1076 return $forum; 1077 } 1078 1079 /** 1080 * Deletes a forum 1081 * 1082 * @since 1.0 1083 * @return integer|object 1 when successfully deleted or an IXR_Error object on failure 1084 * @param array $args Arguments passed by the XML-RPC call 1085 * @param string $args[0] The username for authentication 1086 * @param string $args[1] The password for authentication 1087 * @param integer|string $args[2] The unique id of the forum to be deleted 1088 * 1089 * XML-RPC request to delete a forum with the slug "naughty-forum" 1090 * <methodCall> 1091 * <methodName>bb.deleteForum</methodName> 1092 * <params> 1093 * <param><value><string>joeblow</string></value></param> 1094 * <param><value><string>123password</string></value></param> 1095 * <param><value><string>naughty-forum</string></value></param> 1096 * </params> 1097 * </methodCall> 1098 */ 1099 function bb_deleteForum( $args ) 1100 { 1101 do_action( 'bb_xmlrpc_call', 'bb.deleteForum' ); 1102 1103 // Escape args 1104 $this->escape( $args ); 1105 1106 // Get the login credentials 1107 $username = $args[0]; 1108 $password = (string) $args[1]; 1109 1110 // Check the user is valid 1111 $user = $this->authenticate( $username, $password, 'delete_forums', __( 'You do not have permission to delete forums.' ) ); 1112 1113 do_action( 'bb_xmlrpc_call_authenticated', 'bb.deleteForum' ); 1114 1115 // If an error was raised by authentication or by an action then return it 1116 if ( $this->error ) { 1117 return $this->error; 1118 } 1119 1120 // Can be numeric id or slug 1121 $forum_id = isset( $args[2] ) ? $args[2] : false; 1122 1123 // Check for bad data 1124 if ( !$forum_id || ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) ) { 1125 $this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) ); 1126 return $this->error; 1127 } 1128 1129 // Check the requested forum exists 1130 if ( !$forum = bb_get_forum( $forum_id ) ) { 1131 $this->error = new IXR_Error( 400, __( 'No forum found.' ) ); 1132 return $this->error; 1133 } 1134 1135 // Cast the forum object as an array 1136 $forum = (array) $forum; 1137 // The forum id may have been a slug, so make sure it's an integer here 1138 $forum_id = (int) $forum['forum_id']; 1139 1140 // Make sure they are allowed to delete this forum specifically 1141 if ( !bb_current_user_can( 'delete_forum', $forum_id ) ) { 1142 $this->error = new IXR_Error( 403, __( 'You do not have permission to delete this forum.' ) ); 1143 return $this->error; 1144 } 1145 1146 // Leave the require until the very end 1147 require_once ( BB_PATH . 'bb-admin/includes/functions.bb-admin.php' ); 1148 1149 // Delete the forum 1150 if ( !bb_delete_forum( $forum_id ) ) { 1151 $this->error = new IXR_Error( 500, __( 'The forum could not be deleted.' ) ); 1152 return $this->error; 1153 } 1154 1155 $result = 1; 1156 1157 do_action( 'bb_xmlrpc_call_return', 'bb.deleteForum' ); 1158 1159 return $result; 1160 } 1161 1162 1163 1164 /** 1165 * bbPress publishing API - Topic XML-RPC methods 1166 */ 1167 1168 /** 1169 * Returns a numerical count of topics 1170 * 1171 * @since 1.0 1172 * @return integer|object The number of topics when successfully executed or an IXR_Error object on failure 1173 * @param array $args Arguments passed by the XML-RPC call 1174 * @param string $args[0] The username for authentication 1175 * @param string $args[1] The password for authentication 1176 * @param integer|string $args[2] The forum id or slug (optional) 1177 * 1178 * XML-RPC request to get a count of all topics in the bbPress instance 1179 * <methodCall> 1180 * <methodName>bb.getTopicCount</methodName> 1181 * <params> 1182 * <param><value><string>joeblow</string></value></param> 1183 * <param><value><string>123password</string></value></param> 1184 * </params> 1185 * </methodCall> 1186 * 1187 * XML-RPC request to get a count of all topics in the forum with id number 34 1188 * <methodCall> 1189 * <methodName>bb.getTopicCount</methodName> 1190 * <params> 1191 * <param><value><string>joeblow</string></value></param> 1192 * <param><value><string>123password</string></value></param> 1193 * <param><value><int>34</int></value></param> 1194 * </params> 1195 * </methodCall> 1196 * 1197 * XML-RPC request to get a count of all topics in the forum with slug "first-forum" 1198 * <methodCall> 1199 * <methodName>bb.getTopicCount</methodName> 1200 * <params> 1201 * <param><value><string>joeblow</string></value></param> 1202 * <param><value><string>123password</string></value></param> 1203 * <param><value><string>first-forum</string></value></param> 1204 * </params> 1205 * </methodCall> 1206 */ 1207 function bb_getTopicCount( $args ) 1208 { 1209 do_action( 'bb_xmlrpc_call', 'bb.getTopicCount' ); 1210 1211 // Escape args 1212 $this->escape( $args ); 1213 1214 // Get the login credentials 1215 $username = $args[0]; 1216 $password = (string) $args[1]; 1217 1218 // Check the user is valid 1219 if ( $this->auth_readonly ) { 1220 $user = $this->authenticate( $username, $password ); 1221 } 1222 1223 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getTopicCount' ); 1224 1225 // If an error was raised by authentication or by an action then return it 1226 if ( $this->error ) { 1227 return $this->error; 1228 } 1229 1230 // Can be numeric id or slug 1231 if ( isset( $args[2] ) && $forum_id = $args[2] ) { 1232 // Check for bad data 1233 if ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) { 1234 $this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) ); 1235 return $this->error; 1236 } 1237 // Check the requested forum exists 1238 if ( !$forum = bb_get_forum( $forum_id ) ) { 1239 $this->error = new IXR_Error( 400, __( 'The forum does not exist.' ) ); 1240 return $this->error; 1241 } 1242 1243 // OK, let's trust the count in the forum table 1244 $count = (int) $forum->topics; 1245 } else { 1246 // Get all forums 1247 $forums = bb_get_forums(); 1248 1249 // Return an error when no forums exist 1250 if ( !$forums ) { 1251 $this->error = new IXR_Error( 400, __( 'No forums found.' ) ); 1252 return $this->error; 1253 } 1254 1255 // Count the topics 1256 $count = 0; 1257 foreach ( $forums as $forum ) { 1258 $count += (int) $forum->topics; 1259 } 1260 } 1261 1262 do_action( 'bb_xmlrpc_call_return', 'bb.getTopicCount' ); 1263 1264 // Return the count of topics 1265 return $count; 1266 } 1267 1268 /** 1269 * Returns details of the latest topics 1270 * 1271 * @since 1.0 1272 * @return array|object The topics when successfully executed or an IXR_Error object on failure 1273 * @param array $args Arguments passed by the XML-RPC call 1274 * @param string $args[0] The username for authentication 1275 * @param string $args[1] The password for authentication 1276 * @param integer|string $args[2] The forum id or slug (optional) 1277 * @param integer $args[3] The number of topics to return (optional) 1278 * @param integer $args[4] The number of the page to return (optional) 1279 * 1280 * XML-RPC request to get all topics in the bbPress instance 1281 * <methodCall> 1282 * <methodName>bb.getTopics</methodName> 1283 * <params> 1284 * <param><value><string>joeblow</string></value></param> 1285 * <param><value><string>123password</string></value></param> 1286 * </params> 1287 * </methodCall> 1288 * 1289 * XML-RPC request to get all topics in the forum with id number 34 1290 * <methodCall> 1291 * <methodName>bb.getTopics</methodName> 1292 * <params> 1293 * <param><value><string>joeblow</string></value></param> 1294 * <param><value><string>123password</string></value></param> 1295 * <param><value><int>34</int></value></param> 1296 * </params> 1297 * </methodCall> 1298 * 1299 * XML-RPC request to get topics 6 to 10 in the forum with slug "first-forum" 1300 * <methodCall> 1301 * <methodName>bb.getTopics</methodName> 1302 * <params> 1303 * <param><value><string>joeblow</string></value></param> 1304 * <param><value><string>123password</string></value></param> 1305 * <param><value><string>first-forum</string></value></param> 1306 * <param><value><int>5</int></value></param> 1307 * <param><value><int>2</int></value></param> 1308 * </params> 1309 * </methodCall> 1310 */ 1311 function bb_getTopics( $args ) 1312 { 1313 do_action( 'bb_xmlrpc_call', 'bb.getTopics' ); 1314 1315 // Escape args 1316 $this->escape( $args ); 1317 1318 // Get the login credentials 1319 $username = $args[0]; 1320 $password = (string) $args[1]; 1321 1322 // Check the user is valid 1323 if ( $this->auth_readonly ) { 1324 $user = $this->authenticate( $username, $password ); 1325 } 1326 1327 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getTopics' ); 1328 1329 // If an error was raised by authentication or by an action then return it 1330 if ( $this->error ) { 1331 return $this->error; 1332 } 1333 1334 // Setup an array to store arguments to pass to get_topics() function 1335 $get_topics_args = array( 1336 'forum' => false, 1337 'number' => false, 1338 'page' => false 1339 ); 1340 1341 // Can be numeric id or slug 1342 if ( isset( $args[2] ) && $forum_id = $args[2] ) { 1343 // Check for bad data 1344 if ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) { 1345 $this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) ); 1346 return $this->error; 1347 } 1348 // Check the requested forum exists 1349 if ( !$forum = bb_get_forum( $forum_id ) ) { 1350 $this->error = new IXR_Error( 400, __( 'The forum does not exist.' ) ); 1351 return $this->error; 1352 } 1353 1354 // The forum id may have been a slug, so make sure it's an integer here 1355 $get_topics_args['forum'] = (int) $forum->forum_id; 1356 } 1357 1358 // Can only be an integer 1359 if ( isset( $args[3] ) && $number = (int) $args[3] ) { 1360 $get_topics_args['number'] = $number; 1361 } 1362 1363 // Can only be an integer 1364 if ( isset( $args[4] ) && $page = (int) $args[4] ) { 1365 $get_topics_args['page'] = $page; 1366 } 1367 1368 // Get the topics 1369 if ( !$topics = get_latest_topics( $get_topics_args ) ) { 1370 $this->error = new IXR_Error( 400, __( 'No topics found.' ) ); 1371 return $this->error; 1372 } 1373 1374 // Only include "safe" data in the array 1375 $_topics = array(); 1376 foreach ( $topics as $topic ) { 1377 $_topics[] = $this->prepare_topic( $topic ); 1378 } 1379 1380 do_action( 'bb_xmlrpc_call_return', 'bb.getTopics' ); 1381 1382 // Return the topics 1383 return $_topics; 1384 } 1385 1386 /** 1387 * Returns details of a topic 1388 * 1389 * @since 1.0 1390 * @return array|object An array containing details of the returned topic when successfully executed or an IXR_Error object on failure 1391 * @param string $args[0] The username for authentication 1392 * @param string $args[1] The password for authentication 1393 * @param integer|string $args[2] The topic's id or slug 1394 * 1395 * XML-RPC request to get the topic with id number 105 1396 * <methodCall> 1397 * <methodName>bb.getTopic</methodName> 1398 * <params> 1399 * <param><value><string>joeblow</string></value></param> 1400 * <param><value><string>123password</string></value></param> 1401 * <param><value><int>105</int></value></param> 1402 * </params> 1403 * </methodCall> 1404 * 1405 * XML-RPC request to get the topic with slug "cheesy-biscuits" 1406 * <methodCall> 1407 * <methodName>bb.getTopic</methodName> 1408 * <params> 1409 * <param><value><string>joeblow</string></value></param> 1410 * <param><value><string>123password</string></value></param> 1411 * <param><value><string>cheesy-biscuits</string></value></param> 1412 * </params> 1413 * </methodCall> 1414 */ 1415 function bb_getTopic( $args ) 1416 { 1417 do_action( 'bb_xmlrpc_call', 'bb.getTopic' ); 1418 1419 // Escape args 1420 $this->escape( $args ); 1421 1422 // Get the login credentials 1423 $username = $args[0]; 1424 $password = (string) $args[1]; 1425 1426 // Check the user is valid 1427 if ( $this->auth_readonly ) { 1428 $user = $this->authenticate( $username, $password ); 1429 } 1430 1431 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getTopic' ); 1432 1433 // If an error was raised by authentication or by an action then return it 1434 if ( $this->error ) { 1435 return $this->error; 1436 } 1437 1438 // Can be numeric id or slug 1439 $topic_id = isset( $args[2] ) ? $args[2] : false; 1440 1441 // Check for bad data 1442 if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) { 1443 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 1444 return $this->error; 1445 } 1446 1447 // Check the requested topic exists 1448 if ( !$topic = get_topic( $topic_id ) ) { 1449 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 1450 return $this->error; 1451 } 1452 1453 // Only include "safe" data in the array 1454 $topic = $this->prepare_topic( $topic ); 1455 1456 do_action( 'bb_xmlrpc_call_return', 'bb.getTopic' ); 1457 1458 // Return the topic 1459 return $topic; 1460 } 1461 1462 /** 1463 * Creates a new topic 1464 * 1465 * @since 1.0 1466 * @return array|object The topic data when successfully created or an IXR_Error object on failure 1467 * @param array $args Arguments passed by the XML-RPC call 1468 * @param string $args[0] The username for authentication 1469 * @param string $args[1] The password for authentication 1470 * @param array $args[2] The values for the various parameters in the new topic 1471 * @param string $args[2]['title'] The title of the topic 1472 * @param string $args[2]['text'] The text of the topic 1473 * @param integer|string $args[2]['forum_id'] The unique id of the forum which will contain this topic, slugs are OK to use too 1474 * @param string|array $args[2]['tags'] A comma delimited string or an array of tags to add to the topic (optional) 1475 * 1476 * XML-RPC request to create a new topic called "Insane monkeys" inside the forum with id 2 1477 * <methodCall> 1478 * <methodName>bb.newTopic</methodName> 1479 * <params> 1480 * <param><value><string>joeblow</string></value></param> 1481 * <param><value><string>123password</string></value></param> 1482 * <param><value><struct> 1483 * <member> 1484 * <name>title</name> 1485 * <value><string>Insane monkeys</string></value> 1486 * </member> 1487 * <member> 1488 * <name>text</name> 1489 * <value><string>I just saw some insane monkeys eating bananas, did anyone else see that?</string></value> 1490 * </member> 1491 * <member> 1492 * <name>forum_id</name> 1493 * <value><integer>2</integer></value> 1494 * </member> 1495 * <member> 1496 * <name>tags</name> 1497 * <value><string>monkeys, bananas</string></value> 1498 * </member> 1499 * </struct></value></param> 1500 * </params> 1501 * </methodCall> 1502 */ 1503 function bb_newTopic( $args ) 1504 { 1505 do_action( 'bb_xmlrpc_call', 'bb.newTopic' ); 1506 1507 // Escape args 1508 $this->escape( $args ); 1509 1510 // Get the login credentials 1511 $username = $args[0]; 1512 $password = (string) $args[1]; 1513 1514 // Check the user is valid 1515 $user = $this->authenticate( $username, $password, 'write_topics', __( 'You do not have permission to write topics.' ) ); 1516 1517 // Additionally they need to be able to write posts 1518 if ( !$this->error && !bb_current_user_can( 'write_posts' ) ) { 1519 $this->error = new IXR_Error( 403, __( 'You do not have permission to write posts.' ) ); 1520 } 1521 1522 do_action( 'bb_xmlrpc_call_authenticated', 'bb.newTopic' ); 1523 1524 // If an error was raised by authentication or by an action then return it 1525 if ( $this->error ) { 1526 return $this->error; 1527 } 1528 1529 // Make sure there is something for us to do 1530 if ( !$args[2] || !is_array( $args[2] ) || !count( $args[2] ) ) { 1531 $this->error = new IXR_Error( 400, __( 'The topic data is invalid.' ) ); 1532 return $this->error; 1533 } 1534 1535 $structure = (array) $args[2]; 1536 1537 // Can be numeric id or slug 1538 $forum_id = isset( $structure['forum_id'] ) ? $structure['forum_id'] : false; 1539 1540 // Check for bad data 1541 if ( !$forum_id || ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) ) { 1542 $this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) ); 1543 return $this->error; 1544 } 1545 1546 // Check the requested forum exists 1547 if ( !$forum = bb_get_forum( $forum_id ) ) { 1548 $this->error = new IXR_Error( 400, __( 'No forum found.' ) ); 1549 return $this->error; 1550 } 1551 1552 // The forum id may have been a slug, so make sure it's an integer here 1553 $forum_id = (int) $forum->forum_id; 1554 1555 // Make sure they are allowed to write topics to this forum 1556 if ( !bb_current_user_can( 'write_topic', $forum_id ) ) { 1557 $this->error = new IXR_Error( 403, __( 'You do not have permission to write topics to this forum.' ) ); 1558 return $this->error; 1559 } 1560 1561 // The topic requires a title 1562 if ( !isset( $structure['title'] ) || !$structure['title'] ) { 1563 $this->error = new IXR_Error( 400, __( 'The topic title is invalid.' ) ); 1564 return $this->error; 1565 } 1566 1567 // The topic requires text 1568 if ( !isset( $structure['text'] ) || !$structure['text'] ) { 1569 $this->error = new IXR_Error( 400, __( 'The topic text is invalid.' ) ); 1570 return $this->error; 1571 } 1572 1573 // Inject structure into an array suitable for bb_insert_topic() 1574 $bb_insert_topic_args = array( 1575 'topic_title' => (string) $structure['title'], 1576 'forum_id' => $forum_id, 1577 'tags' => (string) trim( $structure['tags'] ) 1578 ); 1579 1580 // Remove empty settings so that changes to the defaults in bb_insert_topic() are honoured 1581 $bb_insert_topic_args = array_filter( $bb_insert_topic_args ); 1582 1583 // Create the topic 1584 if ( !$topic_id = bb_insert_topic( $bb_insert_topic_args ) ) { 1585 $this->error = new IXR_Error( 500, __( 'The topic could not be created.' ) ); 1586 return $this->error; 1587 } 1588 1589 // Inject structure into an array suitable for bb_insert_post() 1590 $bb_insert_post_args = array( 1591 'topic_id' => (int) $topic_id, 1592 'post_text' => (string) $structure['text'] 1593 ); 1594 1595 // Create the post 1596 if ( !$post_id = bb_insert_post( $bb_insert_post_args ) ) { 1597 $this->error = new IXR_Error( 500, __( 'The post could not be created.' ) ); 1598 return $this->error; 1599 } 1600 1601 // Only include "safe" data in the array 1602 $topic = $this->prepare_topic( get_topic( $topic_id ) ); 1603 1604 do_action( 'bb_xmlrpc_call_return', 'bb.newTopic' ); 1605 1606 return $topic; 1607 } 1608 1609 /** 1610 * Edits an existing topic 1611 * 1612 * @since 1.0 1613 * @return array|object The topic data when successfully edited or an IXR_Error object on failure 1614 * @param array $args Arguments passed by the XML-RPC call 1615 * @param string $args[0] The username for authentication 1616 * @param string $args[1] The password for authentication 1617 * @param array $args[2] The values for the various parameters in the edited topic 1618 * @param integer|string $args[2]['topic_id'] The topic's id or slug 1619 * @param string $args[2]['title'] The title of the topic 1620 * @param string $args[2]['text'] The text of the topic 1621 * 1622 * XML-RPC request to edit the title of a topic with the slug "insane-monkeys" 1623 * <methodCall> 1624 * <methodName>bb.editTopic</methodName> 1625 * <params> 1626 * <param><value><string>joeblow</string></value></param> 1627 * <param><value><string>123password</string></value></param> 1628 * <param><value><struct> 1629 * <member> 1630 * <name>topic_id</name> 1631 * <value><string>insane-monkeys</string></value> 1632 * </member> 1633 * <member> 1634 * <name>title</name> 1635 * <value><string>Very insane monkeys</string></value> 1636 * </member> 1637 * </struct></value></param> 1638 * </params> 1639 * </methodCall> 1640 */ 1641 function bb_editTopic( $args ) 1642 { 1643 do_action( 'bb_xmlrpc_call', 'bb.editTopic' ); 1644 1645 // Escape args 1646 $this->escape( $args ); 1647 1648 // Get the login credentials 1649 $username = $args[0]; 1650 $password = (string) $args[1]; 1651 1652 // Check the user is valid 1653 $user = $this->authenticate( $username, $password, 'edit_topics', __( 'You do not have permission to edit topics.' ) ); 1654 1655 // Additionally they need to be able to edit posts 1656 if ( !$this->error && !bb_current_user_can( 'edit_posts' ) ) { 1657 $this->error = new IXR_Error( 403, __( 'You do not have permission to edit posts.' ) ); 1658 } 1659 1660 do_action( 'bb_xmlrpc_call_authenticated', 'bb.editTopic' ); 1661 1662 // If an error was raised by authentication or by an action then return it 1663 if ( $this->error ) { 1664 return $this->error; 1665 } 1666 1667 // Make sure there is something for us to do 1668 if ( !$args[2] || !is_array( $args[2] ) || !count( $args[2] ) ) { 1669 $this->error = new IXR_Error( 400, __( 'The topic data is invalid.' ) ); 1670 return $this->error; 1671 } 1672 1673 $structure = (array) $args[2]; 1674 1675 // Can be numeric id or slug 1676 $topic_id = isset( $structure['topic_id'] ) ? $structure['topic_id'] : false; 1677 1678 // Check for bad data 1679 if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) { 1680 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 1681 return $this->error; 1682 } 1683 1684 // Check the requested topic exists 1685 if ( !$topic = get_topic( $topic_id ) ) { 1686 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 1687 return $this->error; 1688 } 1689 1690 // The topic id may have been a slug, so make sure it's an integer here 1691 $topic_id = (int) $topic->topic_id; 1692 1693 // Make sure they are allowed to edit this topic 1694 if ( !bb_current_user_can( 'edit_topic', $topic_id ) ) { 1695 $this->error = new IXR_Error( 403, __( 'You do not have permission to edit this topic.' ) ); 1696 return $this->error; 1697 } 1698 1699 // Get the first post in the topic (that's where the content is) 1700 if ( !$post = bb_get_first_post( $topic_id ) ) { 1701 $this->error = new IXR_Error( 400, __( 'No posts found.' ) ); 1702 return $this->error; 1703 } 1704 1705 $post_id = (int) $post->post_id; 1706 1707 // Make sure they are allowed to edit this post 1708 if ( !bb_current_user_can( 'edit_post', $post_id ) ) { 1709 $this->error = new IXR_Error( 403, __( 'You do not have permission to edit this post.' ) ); 1710 return $this->error; 1711 } 1712 1713 // The topic requires a title 1714 if ( isset( $structure['title'] ) && !$structure['title'] ) { 1715 $this->error = new IXR_Error( 400, __( 'The topic title is invalid.' ) ); 1716 return $this->error; 1717 } 1718 1719 // The topic requires text 1720 if ( isset( $structure['text'] ) && !$structure['text'] ) { 1721 $this->error = new IXR_Error( 400, __( 'The topic text is invalid.' ) ); 1722 return $this->error; 1723 } 1724 1725 if ( $structure['title'] ) { 1726 if ( !bb_insert_topic( array( 'topic_title' => (string) $structure['title'], 'topic_id' => $topic_id ) ) ) { 1727 $this->error = new IXR_Error( 500, __( 'The topic could not be edited.' ) ); 1728 return $this->error; 1729 } 1730 } 1731 1732 if ( $structure['text'] ) { 1733 if ( !bb_insert_post( array( 'post_text' => (string) $structure['text'], 'post_id' => $post_id, 'topic_id'=> $topic_id ) ) ) { 1734 $this->error = new IXR_Error( 500, __( 'The post could not be edited.' ) ); 1735 return $this->error; 1736 } 1737 } 1738 1739 // Only include "safe" data in the array 1740 $topic = $this->prepare_topic( get_topic( $topic_id ) ); 1741 1742 do_action( 'bb_xmlrpc_call_return', 'bb.editTopic' ); 1743 1744 return $topic; 1745 } 1746 1747 /** 1748 * Deletes a topic 1749 * 1750 * @since 1.0 1751 * @return integer|object 0 if already changed, 1 when successfully changed or an IXR_Error object on failure 1752 * @param array $args Arguments passed by the XML-RPC call 1753 * @param string $args[0] The username for authentication 1754 * @param string $args[1] The password for authentication 1755 * @param integer|string $args[2] The unique id of the topic to be deleted 1756 * @param integer $args[3] 1 deletes the topic, 0 undeletes the topic 1757 * 1758 * XML-RPC request to delete a topic with id of 34 1759 * <methodCall> 1760 * <methodName>bb.deleteTopic</methodName> 1761 * <params> 1762 * <param><value><string>joeblow</string></value></param> 1763 * <param><value><string>123password</string></value></param> 1764 * <param><value><integer>34</integer></value></param> 1765 * </params> 1766 * </methodCall> 1767 */ 1768 function bb_deleteTopic( $args ) 1769 { 1770 do_action( 'bb_xmlrpc_call', 'bb.deleteTopic' ); 1771 1772 // Escape args 1773 $this->escape( $args ); 1774 1775 // Get the login credentials 1776 $username = $args[0]; 1777 $password = (string) $args[1]; 1778 1779 // Check the user is valid 1780 $user = $this->authenticate( $username, $password, 'delete_topics', __( 'You do not have permission to delete topics.' ) ); 1781 1782 do_action( 'bb_xmlrpc_call_authenticated', 'bb.deleteTopic' ); 1783 1784 // If an error was raised by authentication or by an action then return it 1785 if ( $this->error ) { 1786 return $this->error; 1787 } 1788 1789 // Can be numeric id or slug 1790 $topic_id = isset( $args[2] ) ? $args[2] : false; 1791 1792 // Check for bad data 1793 if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) { 1794 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 1795 return $this->error; 1796 } 1797 1798 // Check the requested topic exists 1799 if ( !$topic = get_topic( $topic_id ) ) { 1800 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 1801 return $this->error; 1802 } 1803 1804 // The topic id may have been a slug, so make sure it's an integer here 1805 $topic_id = (int) $topic->topic_id; 1806 1807 $delete = isset( $args[3] ) ? (int) $args[3] : 1; 1808 1809 // Don't do anything if already set that way 1810 if ( $delete === (int) $topic->topic_status ) { 1811 return 0; 1812 } 1813 1814 // Make sure they are allowed to delete this topic 1815 if ( !bb_current_user_can( 'delete_topic', $topic_id ) ) { 1816 $this->error = new IXR_Error( 403, __( 'You do not have permission to delete this topic.' ) ); 1817 return $this->error; 1818 } 1819 1820 // Delete the topic 1821 if ( !bb_delete_topic( $topic_id, $delete ) ) { 1822 $this->error = new IXR_Error( 500, __( 'The topic could not be deleted.' ) ); 1823 return $this->error; 1824 } 1825 1826 $result = 1; 1827 1828 do_action( 'bb_xmlrpc_call_return', 'bb.deleteTopic' ); 1829 1830 return $result; 1831 } 1832 1833 /** 1834 * Moves a topic to a different forum 1835 * 1836 * @since 1.0 1837 * @return integer|object the forum id where the topic lives after the method is called or an IXR_Error object on failure 1838 * @param array $args Arguments passed by the XML-RPC call 1839 * @param string $args[0] The username for authentication 1840 * @param string $args[1] The password for authentication 1841 * @param integer|string $args[2] The unique id of the topic to be moved 1842 * @param integer|string $args[3] The unique id of the forum to be moved to 1843 * 1844 * XML-RPC request to move the topic with id of 34 to forum with slug of "better-forum" 1845 * <methodCall> 1846 * <methodName>bb.moveTopic</methodName> 1847 * <params> 1848 * <param><value><string>joeblow</string></value></param> 1849 * <param><value><string>123password</string></value></param> 1850 * <param><value><integer>34</integer></value></param> 1851 * <param><value><string>better-forum</string></value></param> 1852 * </params> 1853 * </methodCall> 1854 */ 1855 function bb_moveTopic( $args ) 1856 { 1857 do_action( 'bb_xmlrpc_call', 'bb.moveTopic' ); 1858 1859 // Escape args 1860 $this->escape( $args ); 1861 1862 // Get the login credentials 1863 $username = $args[0]; 1864 $password = (string) $args[1]; 1865 1866 // Check the user is valid 1867 $user = $this->authenticate( $username, $password, 'move_topics', __( 'You do not have permission to move topics.' ) ); 1868 1869 do_action( 'bb_xmlrpc_call_authenticated', 'bb.moveTopic' ); 1870 1871 // If an error was raised by authentication or by an action then return it 1872 if ( $this->error ) { 1873 return $this->error; 1874 } 1875 1876 // Can be numeric id or slug 1877 $topic_id = isset( $args[2] ) ? $args[2] : false; 1878 1879 // Check for bad data 1880 if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) { 1881 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 1882 return $this->error; 1883 } 1884 1885 // Check the requested topic exists 1886 if ( !$topic = get_topic( $topic_id ) ) { 1887 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 1888 return $this->error; 1889 } 1890 1891 // The topic id may have been a slug, so make sure it's an integer here 1892 $topic_id = (int) $topic->topic_id; 1893 1894 // Can be numeric id or slug 1895 $forum_id = isset( $args[3] ) ? $args[3] : false; 1896 1897 // Check for bad data 1898 if ( !$forum_id || ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) ) { 1899 $this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) ); 1900 return $this->error; 1901 } 1902 1903 // Check the requested topic exists 1904 if ( !$forum = bb_get_forum( $forum_id ) ) { 1905 $this->error = new IXR_Error( 400, __( 'No forum found.' ) ); 1906 return $this->error; 1907 } 1908 1909 // The forum id may have been a slug, so make sure it's an integer here 1910 $forum_id = (int) $forum->forum_id; 1911 1912 // Only move it if it isn't already there 1913 if ( $forum_id !== (int) $topic->forum_id ) { 1914 // Make sure they are allowed to move this topic specifically to this forum 1915 if ( !bb_current_user_can( 'move_topic', $topic_id, $forum_id ) ) { 1916 $this->error = new IXR_Error( 403, __( 'You are not allowed to move this topic to this forum.' ) ); 1917 return $this->error; 1918 } 1919 1920 // Move the topic 1921 if ( !bb_move_topic( $topic_id, $forum_id ) ) { 1922 $this->error = new IXR_Error( 500, __( 'The topic could not be moved.' ) ); 1923 return $this->error; 1924 } 1925 } 1926 1927 do_action( 'bb_xmlrpc_call_return', 'bb.moveTopic' ); 1928 1929 return $forum_id; 1930 } 1931 1932 /** 1933 * Sticks a topic to the top of a forum or the front page 1934 * 1935 * @since 1.0 1936 * @return integer|object 0 if it is already stuck to the desired location, 1 when successfully stuck or an IXR_Error object on failure 1937 * @param array $args Arguments passed by the XML-RPC call 1938 * @param string $args[0] The username for authentication 1939 * @param string $args[1] The password for authentication 1940 * @param integer|string $args[2] The unique id of the topic to be stuck 1941 * @param integer $args[3] 0 unsticks, 1 sticks, 2 sticks to front (optional) 1942 * 1943 * XML-RPC request to stick the topic with id of 34 to the front page 1944 * <methodCall> 1945 * <methodName>bb.stickTopic</methodName> 1946 * <params> 1947 * <param><value><string>joeblow</string></value></param> 1948 * <param><value><string>123password</string></value></param> 1949 * <param><value><integer>34</integer></value></param> 1950 * <param><value><integer>1</integer></value></param> 1951 * </params> 1952 * </methodCall> 1953 */ 1954 function bb_stickTopic( $args ) 1955 { 1956 do_action( 'bb_xmlrpc_call', 'bb.stickTopic' ); 1957 1958 // Escape args 1959 $this->escape( $args ); 1960 1961 // Get the login credentials 1962 $username = $args[0]; 1963 $password = (string) $args[1]; 1964 1965 // Check the user is valid 1966 $user = $this->authenticate( $username, $password, 'stick_topics', __( 'You do not have permission to stick topics.' ) ); 1967 1968 do_action( 'bb_xmlrpc_call_authenticated', 'bb.stickTopic' ); 1969 1970 // If an error was raised by authentication or by an action then return it 1971 if ( $this->error ) { 1972 return $this->error; 1973 } 1974 1975 // Can be numeric id or slug 1976 $topic_id = isset( $args[2] ) ? $args[2] : false; 1977 1978 // Check for bad data 1979 if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) { 1980 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 1981 return $this->error; 1982 } 1983 1984 // Check the requested topic exists 1985 if ( !$topic = get_topic( $topic_id ) ) { 1986 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 1987 return $this->error; 1988 } 1989 1990 // The topic id may have been a slug, so make sure it's an integer here 1991 $topic_id = (int) $topic->topic_id; 1992 1993 // Make sure they are allowed to stick this topic 1994 if ( !bb_current_user_can( 'stick_topic', $topic_id ) ) { 1995 $this->error = new IXR_Error( 403, __( 'You do not have permission to stick this topic.' ) ); 1996 return $this->error; 1997 } 1998 1999 // Stick to where? 2000 $where = isset( $args[3] ) ? (int) $args[3] : 1; 2001 2002 // Forget it if it's already there 2003 if ( $where === (int) $topic->topic_sticky ) { 2004 return 0; 2005 } 2006 2007 // Stick the topic 2008 if ( !bb_stick_topic( $topic_id, $where ) ) { 2009 $this->error = new IXR_Error( 500, __( 'The topic could not be stuck.' ) ); 2010 return $this->error; 2011 } 2012 2013 $result = 1; 2014 2015 do_action( 'bb_xmlrpc_call_return', 'bb.stickTopic' ); 2016 2017 return $result; 2018 } 2019 2020 2021 2022 /** 2023 * Closes a topic 2024 * 2025 * @since 1.0 2026 * @return integer|object 0 when already changed, 1 when successfully changed or an IXR_Error object on failure 2027 * @param array $args Arguments passed by the XML-RPC call 2028 * @param string $args[0] The username for authentication 2029 * @param string $args[1] The password for authentication 2030 * @param integer|string $args[2] The unique id of the topic to be closed 2031 * @param integer $args[2] 0 closes, 1 opens (optional) 2032 * 2033 * XML-RPC request to close the topic with slug of "really-old-topic" 2034 * <methodCall> 2035 * <methodName>bb.closeTopic</methodName> 2036 * <params> 2037 * <param><value><string>joeblow</string></value></param> 2038 * <param><value><string>123password</string></value></param> 2039 * <param><value><string>really-old-topic</string></value></param> 2040 * </params> 2041 * </methodCall> 2042 * 2043 * XML-RPC request to open the topic with slug of "really-old-topic" 2044 * <methodCall> 2045 * <methodName>bb.closeTopic</methodName> 2046 * <params> 2047 * <param><value><string>joeblow</string></value></param> 2048 * <param><value><string>123password</string></value></param> 2049 * <param><value><string>really-old-topic</string></value></param> 2050 * <param><value><integer>1</integer></value></param> 2051 * </params> 2052 * </methodCall> 2053 */ 2054 function bb_closeTopic( $args ) 2055 { 2056 do_action( 'bb_xmlrpc_call', 'bb.closeTopic' ); 2057 2058 // Escape args 2059 $this->escape( $args ); 2060 2061 // Get the login credentials 2062 $username = $args[0]; 2063 $password = (string) $args[1]; 2064 2065 // Check the user is valid 2066 $user = $this->authenticate( $username, $password, 'close_topics', __( 'You do not have permission to close topics.' ) ); 2067 2068 do_action( 'bb_xmlrpc_call_authenticated', 'bb.closeTopic' ); 2069 2070 // If an error was raised by authentication or by an action then return it 2071 if ( $this->error ) { 2072 return $this->error; 2073 } 2074 2075 // Can be numeric id or slug 2076 $topic_id = isset( $args[2] ) ? $args[2] : false; 2077 2078 // Check for bad data 2079 if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) { 2080 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 2081 return $this->error; 2082 } 2083 2084 // Check the requested topic exists 2085 if ( !$topic = get_topic( $topic_id ) ) { 2086 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 2087 return $this->error; 2088 } 2089 2090 // The topic id may have been a slug, so make sure it's an integer here 2091 $topic_id = (int) $topic->topic_id; 2092 2093 // Make sure they are allowed to close this topic 2094 if ( !bb_current_user_can( 'close_topic', $topic_id ) ) { 2095 $this->error = new IXR_Error( 403, __( 'You do not have permission to close this topic.' ) ); 2096 return $this->error; 2097 } 2098 2099 // Open or close? 2100 $close = isset( $args[3] ) ? (int) $args[3] : 0; 2101 2102 // Forget it if it's already matching 2103 if ( $close === (int) $topic->topic_open ) { 2104 return 0; 2105 } 2106 2107 // Close the topic 2108 if ( !$close && !bb_close_topic( $topic_id ) ) { 2109 $this->error = new IXR_Error( 500, __( 'The topic could not be closed.' ) ); 2110 return $this->error; 2111 } 2112 2113 // Open the topic 2114 if ( $close && !bb_open_topic( $topic_id ) ) { 2115 $this->error = new IXR_Error( 500, __( 'The topic could not be opened.' ) ); 2116 return $this->error; 2117 } 2118 2119 $result = 1; 2120 2121 do_action( 'bb_xmlrpc_call_return', 'bb.closeTopic' ); 2122 2123 return $result; 2124 } 2125 2126 2127 2128 /** 2129 * bbPress publishing API - Post XML-RPC methods 2130 */ 2131 2132 /** 2133 * Returns a numerical count of posts 2134 * 2135 * @since 1.0 2136 * @return integer|object The number of topics when successfully executed or an IXR_Error object on failure 2137 * @param array $args Arguments passed by the XML-RPC call 2138 * @param string $args[0] The username for authentication 2139 * @param string $args[1] The password for authentication 2140 * @param integer|string $args[2] The topic id or slug 2141 * 2142 * XML-RPC request to get a count of all posts in the topic with slug "countable-topic" 2143 * <methodCall> 2144 * <methodName>bb.getPostCount</methodName> 2145 * <params> 2146 * <param><value><string>joeblow</string></value></param> 2147 * <param><value><string>123password</string></value></param> 2148 * <param><value><string>countable-topic</string></value></param> 2149 * </params> 2150 * </methodCall> 2151 */ 2152 function bb_getPostCount( $args ) 2153 { 2154 do_action( 'bb_xmlrpc_call', 'bb.getPostCount' ); 2155 2156 // Escape args 2157 $this->escape( $args ); 2158 2159 // Get the login credentials 2160 $username = $args[0]; 2161 $password = (string) $args[1]; 2162 2163 // Check the user is valid 2164 if ( $this->auth_readonly ) { 2165 $user = $this->authenticate( $username, $password ); 2166 } 2167 2168 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getPostCount' ); 2169 2170 // If an error was raised by authentication or by an action then return it 2171 if ( $this->error ) { 2172 return $this->error; 2173 } 2174 2175 // Can be numeric id or slug 2176 $topic_id = isset( $args[2] ) ? $args[2] : false; 2177 2178 // Check for bad data 2179 if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) { 2180 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 2181 return $this->error; 2182 } 2183 2184 // Check the requested topic exists 2185 if ( !$topic = get_topic( $topic_id ) ) { 2186 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 2187 return $this->error; 2188 } 2189 2190 // OK, let's trust the count in the topic table 2191 $count = $topic->topic_posts; 2192 2193 do_action( 'bb_xmlrpc_call_return', 'bb.getPostCount' ); 2194 2195 // Return the count of posts 2196 return $count; 2197 } 2198 2199 /** 2200 * Returns details of the posts in a given topic 2201 * 2202 * @since 1.0 2203 * @return array|object The posts when successfully executed or an IXR_Error object on failure 2204 * @param array $args Arguments passed by the XML-RPC call 2205 * @param string $args[0] The username for authentication 2206 * @param string $args[1] The password for authentication 2207 * @param integer|string $args[2] The topic id or slug 2208 * @param integer $args[3] The number of posts to return (optional) 2209 * @param integer $args[4] The number of the page to return (optional) 2210 * 2211 * XML-RPC request to get all posts in the topic with id number 53 2212 * <methodCall> 2213 * <methodName>bb.getPosts</methodName> 2214 * <params> 2215 * <param><value><string>joeblow</string></value></param> 2216 * <param><value><string>123password</string></value></param> 2217 * <param><value><int>53</int></value></param> 2218 * </params> 2219 * </methodCall> 2220 * 2221 * XML-RPC request to get the latest 5 posts in the topic with id number 341 2222 * <methodCall> 2223 * <methodName>bb.getPosts</methodName> 2224 * <params> 2225 * <param><value><string>joeblow</string></value></param> 2226 * <param><value><string>123password</string></value></param> 2227 * <param><value><int>341</int></value></param> 2228 * <param><value><int>5</int></value></param> 2229 * </params> 2230 * </methodCall> 2231 * 2232 * XML-RPC request to get posts 11 to 20 in the topic with slug "long-topic" 2233 * <methodCall> 2234 * <methodName>bb.getPosts</methodName> 2235 * <params> 2236 * <param><value><string>joeblow</string></value></param> 2237 * <param><value><string>123password</string></value></param> 2238 * <param><value><string>long-topic</string></value></param> 2239 * <param><value><int>10</int></value></param> 2240 * <param><value><int>2</int></value></param> 2241 * </params> 2242 * </methodCall> 2243 */ 2244 function bb_getPosts( $args ) 2245 { 2246 do_action( 'bb_xmlrpc_call', 'bb.getPosts' ); 2247 2248 // Escape args 2249 $this->escape( $args ); 2250 2251 // Get the login credentials 2252 $username = $args[0]; 2253 $password = (string) $args[1]; 2254 2255 // Check the user is valid 2256 if ( $this->auth_readonly ) { 2257 $user = $this->authenticate( $username, $password ); 2258 } 2259 2260 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getPosts' ); 2261 2262 // If an error was raised by authentication or by an action then return it 2263 if ( $this->error ) { 2264 return $this->error; 2265 } 2266 2267 // Can be numeric id or slug 2268 $topic_id = isset( $args[2] ) ? $args[2] : false; 2269 2270 // Check for bad data 2271 if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) { 2272 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 2273 return $this->error; 2274 } 2275 2276 // Check the requested topic exists 2277 if ( !$topic = get_topic( $topic_id ) ) { 2278 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 2279 return $this->error; 2280 } 2281 2282 // The topic id may have been a slug, so make sure it's an integer here 2283 $topic_id = (int) $topic->topic_id; 2284 2285 // Setup an array to store arguments to pass to get_thread() function 2286 $get_thread_args = array(); 2287 2288 // Can only be an integer 2289 if ( isset( $args[3] ) && $per_page = (int) $args[3] ) { 2290 $get_thread_args['per_page'] = $per_page; 2291 } 2292 2293 // Can only be an integer 2294 if ( isset( $args[4] ) && $page = (int) $args[4] ) { 2295 $get_thread_args['page'] = $page; 2296 } 2297 2298 // Get the posts 2299 if ( !$posts = get_thread( $topic_id, $get_thread_args ) ) { 2300 $this->error = new IXR_Error( 500, __( 'No posts found.' ) ); 2301 return $this->error; 2302 } 2303 2304 // Only include "safe" data in the array 2305 $_posts = array(); 2306 foreach ( $posts as $post ) { 2307 $_posts[] = $this->prepare_post( $post ); 2308 } 2309 2310 do_action( 'bb_xmlrpc_call_return', 'bb.getPosts' ); 2311 2312 // Return the posts 2313 return $_posts; 2314 } 2315 2316 /** 2317 * Returns details of a post 2318 * 2319 * @since 1.0 2320 * @return array|object An array containing details of the returned post when successfully executed or an IXR_Error object on failure 2321 * @param array $args Arguments passed by the XML-RPC call 2322 * @param string $args[0] The username for authentication 2323 * @param string $args[1] The password for authentication 2324 * @param integer $args[2] The post's id 2325 * 2326 * XML-RPC request to get the post with id number 32 2327 * <methodCall> 2328 * <methodName>bb.getPost</methodName> 2329 * <params> 2330 * <param><value><string>joeblow</string></value></param> 2331 * <param><value><string>123password</string></value></param> 2332 * <param><value><int>32</int></value></param> 2333 * </params> 2334 * </methodCall> 2335 */ 2336 function bb_getPost( $args ) 2337 { 2338 do_action( 'bb_xmlrpc_call', 'bb.getPost' ); 2339 2340 // Escape args 2341 $this->escape( $args ); 2342 2343 // Get the login credentials 2344 $username = $args[0]; 2345 $password = (string) $args[1]; 2346 2347 // Check the user is valid 2348 if ( $this->auth_readonly ) { 2349 $user = $this->authenticate( $username, $password ); 2350 } 2351 2352 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getPost' ); 2353 2354 // If an error was raised by authentication or by an action then return it 2355 if ( $this->error ) { 2356 return $this->error; 2357 } 2358 2359 // Can be numeric id or slug 2360 $post_id = isset( $args[2] ) ? (int) $args[2] : false; 2361 2362 // Check for bad data 2363 if ( !$post_id ) { 2364 $this->error = new IXR_Error( 400, __( 'The post id is invalid.' ) ); 2365 return $this->error; 2366 } 2367 2368 // Check the requested post exists 2369 if ( !$post = bb_get_post( $post_id ) ) { 2370 $this->error = new IXR_Error( 400, __( 'No post found.' ) ); 2371 return $this->error; 2372 } 2373 2374 // Only include "safe" data in the array 2375 $_post = $this->prepare_post( $post ); 2376 2377 do_action( 'bb_xmlrpc_call_return', 'bb.getPost' ); 2378 2379 // Return the post 2380 return $_post; 2381 } 2382 2383 /** 2384 * Creates a new post in a given topic 2385 * 2386 * @since 1.0 2387 * @return array|object The post data when successfully created or an IXR_Error object on failure 2388 * @param array $args Arguments passed by the XML-RPC call 2389 * @param string $args[0] The username for authentication 2390 * @param string $args[1] The password for authentication 2391 * @param array $args[2] The values for the various parameters in the new topic 2392 * @param string $args[2]['text'] The text of the topic 2393 * @param integer|string $args[2]['topic_id'] The unique id of the topic which will contain this topic, slugs are OK to use too 2394 * 2395 * XML-RPC request to create a new post in the topic with slug "totally-worth-it" 2396 * <methodCall> 2397 * <methodName>bb.newPost</methodName> 2398 * <params> 2399 * <param><value><string>joeblow</string></value></param> 2400 * <param><value><string>123password</string></value></param> 2401 * <param><value><struct> 2402 * <member> 2403 * <name>text</name> 2404 * <value><string>I agree, it is totally worth it.</string></value> 2405 * </member> 2406 * <member> 2407 * <name>topic_id</name> 2408 * <value><string>totally-worth-it</string></value> 2409 * </member> 2410 * </struct></value></param> 2411 * </params> 2412 * </methodCall> 2413 */ 2414 function bb_newPost( $args ) 2415 { 2416 do_action( 'bb_xmlrpc_call', 'bb.newPost' ); 2417 2418 // Escape args 2419 $this->escape( $args ); 2420 2421 // Get the login credentials 2422 $username = $args[0]; 2423 $password = (string) $args[1]; 2424 2425 // Check the user is valid 2426 $user = $this->authenticate( $username, $password, 'write_posts', __( 'You do not have permission to write posts.' ) ); 2427 2428 do_action( 'bb_xmlrpc_call_authenticated', 'bb.newPost' ); 2429 2430 // If an error was raised by authentication or by an action then return it 2431 if ( $this->error ) { 2432 return $this->error; 2433 } 2434 2435 // Make sure there is something for us to do 2436 if ( !$args[2] || !is_array( $args[2] ) || !count( $args[2] ) ) { 2437 $this->error = new IXR_Error( 400, __( 'The post data is invalid.' ) ); 2438 return $this->error; 2439 } 2440 2441 $structure = (array) $args[2]; 2442 2443 // Can be numeric id or slug 2444 $topic_id = isset( $structure['topic_id'] ) ? $structure['topic_id'] : false; 2445 2446 // Check for bad data 2447 if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) { 2448 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 2449 return $this->error; 2450 } 2451 2452 // Check the requested topic exists 2453 if ( !$topic = get_topic( $topic_id ) ) { 2454 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 2455 return $this->error; 2456 } 2457 2458 // The topic id may have been a slug, so make sure it's an integer here 2459 $topic_id = (int) $topic->topic_id; 2460 2461 // Make sure they are allowed to write posts to this topic 2462 if ( !bb_current_user_can( 'write_post', $topic_id ) ) { 2463 $this->error = new IXR_Error( 403, __( 'You do not have permission to write posts to this topic.' ) ); 2464 return $this->error; 2465 } 2466 2467 // The post requires text 2468 if ( !isset( $structure['text'] ) || !$structure['text'] ) { 2469 $this->error = new IXR_Error( 400, __( 'The post text is invalid.' ) ); 2470 return $this->error; 2471 } 2472 2473 // Inject structure into an array suitable for bb_insert_post() 2474 $bb_insert_post_args = array( 2475 'topic_id' => $topic_id, 2476 'post_text' => (string) $structure['text'] 2477 ); 2478 2479 // Create the post 2480 if ( !$post_id = bb_insert_post( $bb_insert_post_args ) ) { 2481 $this->error = new IXR_Error( 500, __( 'The post could not be created.' ) ); 2482 return $this->error; 2483 } 2484 2485 // Only include "safe" data in the array 2486 $post = $this->prepare_forum( bb_get_post( $post_id ) ); 2487 2488 do_action( 'bb_xmlrpc_call_return', 'bb.newPost' ); 2489 2490 return $post; 2491 } 2492 2493 /** 2494 * Edits an existing post 2495 * 2496 * @since 1.0 2497 * @return array|object The post data when successfully edited or an IXR_Error object on failure 2498 * @param array $args Arguments passed by the XML-RPC call 2499 * @param string $args[0] The username for authentication 2500 * @param string $args[1] The password for authentication 2501 * @param array $args[2] The values for the various parameters in the new topic 2502 * @param integer $args[2]['post_id'] The unique id of the post 2503 * @param string $args[2]['text'] The text of the topic 2504 * 2505 * XML-RPC request to edit the text of the post with an id of 452 2506 * <methodCall> 2507 * <methodName>bb.editPost</methodName> 2508 * <params> 2509 * <param><value><string>joeblow</string></value></param> 2510 * <param><value><string>123password</string></value></param> 2511 * <param><value><struct> 2512 * <member> 2513 * <name>post_id</name> 2514 * <value><int>452</int></value> 2515 * </member> 2516 * <member> 2517 * <name>text</name> 2518 * <value><string>For now I will withhold my opinion.</string></value> 2519 * </member> 2520 * </struct></value></param> 2521 * </params> 2522 * </methodCall> 2523 */ 2524 function bb_editPost( $args ) 2525 { 2526 do_action( 'bb_xmlrpc_call', 'bb.editPost' ); 2527 2528 // Escape args 2529 $this->escape( $args ); 2530 2531 // Get the login credentials 2532 $username = $args[0]; 2533 $password = (string) $args[1]; 2534 2535 // Check the user is valid 2536 $user = $this->authenticate( $username, $password, 'edit_posts', __( 'You do not have permission to edit posts.' ) ); 2537 2538 do_action( 'bb_xmlrpc_call_authenticated', 'bb.editPost' ); 2539 2540 // If an error was raised by authentication or by an action then return it 2541 if ( $this->error ) { 2542 return $this->error; 2543 } 2544 2545 // Make sure there is something for us to do 2546 if ( !$args[2] || !is_array( $args[2] ) || !count( $args[2] ) ) { 2547 $this->error = new IXR_Error( 400, __( 'The post data is invalid.' ) ); 2548 return $this->error; 2549 } 2550 2551 $structure = (array) $args[2]; 2552 2553 // Can be numeric id or slug 2554 $post_id = isset( $structure['post_id'] ) ? (int) $structure['post_id'] : false; 2555 2556 // Check for bad data 2557 if ( !$post_id ) { 2558 $this->error = new IXR_Error( 400, __( 'The post id is invalid.' ) ); 2559 return $this->error; 2560 } 2561 2562 // Check the requested topic exists 2563 if ( !$post = bb_get_post( $post_id ) ) { 2564 $this->error = new IXR_Error( 400, __( 'No post found.' ) ); 2565 return $this->error; 2566 } 2567 2568 // Re-assign the post id 2569 $post_id = (int) $post->post_id; 2570 2571 // Make sure they are allowed to edit this post 2572 if ( !bb_current_user_can( 'edit_post', $post_id ) ) { 2573 $this->error = new IXR_Error( 403, __( 'You do not have permission to edit this post.' ) ); 2574 return $this->error; 2575 } 2576 2577 // The post requires text 2578 if ( !isset( $structure['text'] ) || !$structure['text'] ) { 2579 $this->error = new IXR_Error( 400, __( 'The post text is invalid.' ) ); 2580 return $this->error; 2581 } 2582 2583 // Inject structure into an array suitable for bb_insert_post() 2584 $bb_insert_post_args = array( 2585 'post_id' => $post_id, 2586 'post_text' => (string) $structure['text'] 2587 ); 2588 2589 // Create the post 2590 if ( !$post_id = bb_insert_post( $bb_insert_post_args ) ) { 2591 $this->error = new IXR_Error( 500, __( 'The post could not be edited.' ) ); 2592 return $this->error; 2593 } 2594 2595 // Only include "safe" data in the array 2596 $post = $this->prepare_forum( bb_get_post( $post_id ) ); 2597 2598 do_action( 'bb_xmlrpc_call_return', 'bb.editPost' ); 2599 2600 return $post; 2601 } 2602 2603 /** 2604 * Deletes an existing post 2605 * 2606 * @since 1.0 2607 * @return integer|object 1 when successfully deleted, 0 when already deleted or an IXR_Error object on failure 2608 * @param array $args Arguments passed by the XML-RPC call 2609 * @param string $args[0] The username for authentication 2610 * @param string $args[1] The password for authentication 2611 * @param array $args[2] The unique id of the post 2612 * @param array $args[3] 1 deletes the post, 0 undeletes the post (optional) 2613 * 2614 * XML-RPC request to delete the post with an id of 4301 2615 * <methodCall> 2616 * <methodName>bb.editPost</methodName> 2617 * <params> 2618 * <param><value><string>joeblow</string></value></param> 2619 * <param><value><string>123password</string></value></param> 2620 * <param><value><int>4301</int></value></param> 2621 * </params> 2622 * </methodCall> 2623 */ 2624 function bb_deletePost( $args ) 2625 { 2626 do_action( 'bb_xmlrpc_call', 'bb.deletePost' ); 2627 2628 // Escape args 2629 $this->escape( $args ); 2630 2631 // Get the login credentials 2632 $username = $args[0]; 2633 $password = (string) $args[1]; 2634 2635 // Check the user is valid 2636 $user = $this->authenticate( $username, $password, 'delete_posts', __( 'You do not have permission to delete posts.' ) ); 2637 2638 do_action( 'bb_xmlrpc_call_authenticated', 'bb.deletePost' ); 2639 2640 // If an error was raised by authentication or by an action then return it 2641 if ( $this->error ) { 2642 return $this->error; 2643 } 2644 2645 // Can be numeric id or slug 2646 $post_id = isset( $args[2] ) ? (int) $args[2] : false; 2647 2648 // Check for bad data 2649 if ( !$post_id ) { 2650 $this->error = new IXR_Error( 400, __( 'The post id is invalid.' ) ); 2651 return $this->error; 2652 } 2653 2654 // Check the requested topic exists 2655 if ( !$post = bb_get_post( $post_id ) ) { 2656 $this->error = new IXR_Error( 400, __( 'No post found.' ) ); 2657 return $this->error; 2658 } 2659 2660 // Re-assign the post id 2661 $post_id = (int) $post->post_id; 2662 2663 // Make sure they are allowed to delete this post 2664 if ( !bb_current_user_can( 'delete_post', $post_id ) ) { 2665 $this->error = new IXR_Error( 403, __( 'You do not have permission to delete this post.' ) ); 2666 return $this->error; 2667 } 2668 2669 $status = isset( $args[3] ) ? (int) $args[3] : 1; 2670 2671 if ( $status === (int) $post->post_status ) { 2672 return 0; 2673 } 2674 2675 // Delete the post 2676 if ( !$post_id = bb_delete_post( $post_id, $status ) ) { 2677 $this->error = new IXR_Error( 500, __( 'The post could not be edited.' ) ); 2678 return $this->error; 2679 } 2680 2681 $result = 1; 2682 2683 do_action( 'bb_xmlrpc_call_return', 'bb.deletePost' ); 2684 2685 return $result; 2686 } 2687 2688 2689 2690 /** 2691 * bbPress publishing API - Topic Tag XML-RPC methods 2692 */ 2693 2694 /** 2695 * Returns the hot tags in order of hotness in a given forum or all hot tags 2696 * 2697 * @since 1.0 2698 * @return integer|object The tag data when successfully executed or an IXR_Error object on failure 2699 * @param array $args Arguments passed by the XML-RPC call 2700 * @param string $args[0] The username for authentication 2701 * @param string $args[1] The password for authentication 2702 * @param integer $args[2] The number of tags to return (optional) 2703 * @param integer|string $args[3] The forum id or slug (optional) 2704 * 2705 * XML-RPC request to get the 20 hottest tags in the forum with slug "hawtness" 2706 * <methodCall> 2707 * <methodName>bb.getTopicTags</methodName> 2708 * <params> 2709 * <param><value><string>joeblow</string></value></param> 2710 * <param><value><string>123password</string></value></param> 2711 * <param><value><int>20</int></value></param> 2712 * <param><value><string>hawtness</string></value></param> 2713 * </params> 2714 * </methodCall> 2715 */ 2716 function bb_getHotTopicTags( $args ) 2717 { 2718 do_action( 'bb_xmlrpc_call', 'bb.getHotTopicTags' ); 2719 2720 // Escape args 2721 $this->escape( $args ); 2722 2723 // Get the login credentials 2724 $username = $args[0]; 2725 $password = (string) $args[1]; 2726 2727 // Check the user is valid 2728 if ( $this->auth_readonly ) { 2729 $user = $this->authenticate( $username, $password ); 2730 } 2731 2732 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getHotTopicTags' ); 2733 2734 // If an error was raised by authentication or by an action then return it 2735 if ( $this->error ) { 2736 return $this->error; 2737 } 2738 2739 // Must be a number 2740 $per_page = isset( $args[2] ) ? (integer) $args[2] : false; 2741 2742 // Can be numeric id or slug 2743 $forum_id = isset( $args[3] ) ? $args[3] : false; 2744 2745 if ( $forum_id ) { 2746 // Check for bad data 2747 if ( !is_string( $forum_id ) && !is_integer( $forum_id ) ) { 2748 $this->error = new IXR_Error( 400, __( 'The forum id is invalid.' ) ); 2749 return $this->error; 2750 } 2751 2752 // Check the requested forum exists 2753 if ( !$forum = bb_get_forum( $forum_id ) ) { 2754 $this->error = new IXR_Error( 404, __( 'No forum found.' ) ); 2755 return $this->error; 2756 } 2757 2758 global $bbdb; 2759 $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 ) ); 2760 2761 if ( !count( $topic_ids ) ) { 2762 $this->error = new IXR_Error( 400, __( 'No topics found.' ) ); 2763 return $this->error; 2764 } 2765 2766 global $wp_taxonomy_object; 2767 $tags = $wp_taxonomy_object->get_object_terms( $topic_ids, 'bb_topic_tag', array( 'fields' => 'all_with_object_id', 'orderby' => 'count', 'order' => 'DESC' ) ); 2768 2769 if ( !$tags || is_wp_error( $tags ) ) { 2770 $this->error = new IXR_Error( 500, __( 'Could not retrieve hot topic tags.' ) ); 2771 return $this->error; 2772 } 2773 if ( !count( $tags ) ) { 2774 $this->error = new IXR_Error( 500, __( 'No hot topic tags found.' ) ); 2775 return $this->error; 2776 } 2777 global $bb_log; 2778 $bb_log->debug($tags); 2779 2780 for ( $i = 0; isset( $tags[$i] ); $i++ ) { 2781 _bb_make_tag_compat( $tags[$i] ); 2782 } 2783 $bb_log->debug($tags); 2784 2785 // Only include "safe" data in the array 2786 $_tags = array(); 2787 foreach ( $tags as $tag ) { 2788 $_tag = $this->prepare_topic_tag( $tag ); 2789 if ( !in_array( $_tag, $_tags ) ) { 2790 $_tags[] = $_tag; 2791 } 2792 } 2793 2794 if ( $per_page ) { 2795 $_tags = array_slice( $_tags, 0, $per_page ); 2796 } 2797 } else { 2798 if ( !$tags = bb_get_top_tags( array( 'get' => 'all', 'number' => $per_page ) ) ) { 2799 $this->error = new IXR_Error( 500, __( 'No hot topic tags found.' ) ); 2800 return $this->error; 2801 } 2802 2803 // Only include "safe" data in the array 2804 $_tags = array(); 2805 foreach ( $tags as $tag ) { 2806 $_tags[] = $this->prepare_topic_tag( $tag ); 2807 } 2808 } 2809 2810 do_action( 'bb_xmlrpc_call', 'bb.getHotTopicTags' ); 2811 2812 return $_tags; 2813 } 2814 2815 /** 2816 * Returns a numerical count of tags in a given topic or all tags 2817 * 2818 * @since 1.0 2819 * @return integer|object The number of topics when successfully executed or an IXR_Error object on failure 2820 * @param array $args Arguments passed by the XML-RPC call 2821 * @param string $args[0] The username for authentication 2822 * @param string $args[1] The password for authentication 2823 * @param integer|string $args[2] The topic id or slug (optional) 2824 * 2825 * XML-RPC request to get a count of all tags in the topic with slug "woot-frist-topic" 2826 * <methodCall> 2827 * <methodName>bb.getTopicTagCount</methodName> 2828 * <params> 2829 * <param><value><string>joeblow</string></value></param> 2830 * <param><value><string>123password</string></value></param> 2831 * <param><value><string>woot-frist-topic</string></value></param> 2832 * </params> 2833 * </methodCall> 2834 */ 2835 function bb_getTopicTagCount( $args ) 2836 { 2837 do_action( 'bb_xmlrpc_call', 'bb.getTopicTagCount' ); 2838 2839 // Escape args 2840 $this->escape( $args ); 2841 2842 // Get the login credentials 2843 $username = $args[0]; 2844 $password = (string) $args[1]; 2845 2846 // Check the user is valid 2847 if ( $this->auth_readonly ) { 2848 $user = $this->authenticate( $username, $password ); 2849 } 2850 2851 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getTopicTagCount' ); 2852 2853 // If an error was raised by authentication or by an action then return it 2854 if ( $this->error ) { 2855 return $this->error; 2856 } 2857 2858 // Can be numeric id or slug 2859 $topic_id = isset( $args[2] ) ? $args[2] : false; 2860 2861 // Check for bad data 2862 if ( $topic_id ) { 2863 if ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) { 2864 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 2865 return $this->error; 2866 } 2867 2868 // Check the requested topic exists 2869 if ( !$topic = get_topic( $topic_id ) ) { 2870 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 2871 return $this->error; 2872 } 2873 2874 // The topic id may have been a slug, so make sure it's an integer here 2875 $topic_id = (int) $topic->topic_id; 2876 2877 // Now get the tags 2878 if ( !$tags = bb_get_topic_tags( $topic_id ) ) { 2879 $tags = array(); 2880 } 2881 2882 // Count the tags 2883 $count = count( $tags ); 2884 } else { 2885 global $wp_taxonomy_object; 2886 $count = $wp_taxonomy_object->count_terms( 'bb_topic_tag' ); 2887 if ( is_wp_error( $count ) ) { 2888 $this->error = new IXR_Error( 500, __( 'Could not get a count of all topic tags.' ) ); 2889 return $this->error; 2890 } 2891 } 2892 2893 do_action( 'bb_xmlrpc_call_return', 'bb.getTopicTagCount' ); 2894 2895 // Return the count of tags 2896 return $count; 2897 } 2898 2899 /** 2900 * Returns the tags in a given topic or all tags 2901 * 2902 * @since 1.0 2903 * @return integer|object The tag data when successfully executed or an IXR_Error object on failure 2904 * @param array $args Arguments passed by the XML-RPC call 2905 * @param string $args[0] The username for authentication 2906 * @param string $args[1] The password for authentication 2907 * @param integer|string $args[2] The topic id or slug (optional) 2908 * 2909 * XML-RPC request to get all tags in the topic with slug "woot-frist-topic" 2910 * <methodCall> 2911 * <methodName>bb.getTopicTags</methodName> 2912 * <params> 2913 * <param><value><string>joeblow</string></value></param> 2914 * <param><value><string>123password</string></value></param> 2915 * <param><value><string>woot-frist-topic</string></value></param> 2916 * </params> 2917 * </methodCall> 2918 */ 2919 function bb_getTopicTags( $args ) 2920 { 2921 do_action( 'bb_xmlrpc_call', 'bb.getTopicTags' ); 2922 2923 // Escape args 2924 $this->escape( $args ); 2925 2926 // Get the login credentials 2927 $username = $args[0]; 2928 $password = (string) $args[1]; 2929 2930 // Check the user is valid 2931 if ( $this->auth_readonly ) { 2932 $user = $this->authenticate( $username, $password ); 2933 } 2934 2935 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getTopicTags' ); 2936 2937 // If an error was raised by authentication or by an action then return it 2938 if ( $this->error ) { 2939 return $this->error; 2940 } 2941 2942 // Can be numeric id or slug 2943 $topic_id = isset( $args[2] ) ? $args[2] : false; 2944 2945 // Check for bad data 2946 if ( $topic_id ) { 2947 if ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) { 2948 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 2949 return $this->error; 2950 } 2951 2952 // Check the requested topic exists 2953 if ( !$topic = get_topic( $topic_id ) ) { 2954 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 2955 return $this->error; 2956 } 2957 2958 // The topic id may have been a slug, so make sure it's an integer here 2959 $topic_id = (int) $topic->topic_id; 2960 2961 // Now get the tags 2962 if ( !$tags = bb_get_topic_tags( $topic_id ) ) { 2963 $this->error = new IXR_Error( 500, __( 'No topic tags found.' ) ); 2964 return $this->error; 2965 } 2966 } else { 2967 global $wp_taxonomy_object; 2968 $tags = $wp_taxonomy_object->get_terms( 'bb_topic_tag', array( 'get' => 'all' ) ); 2969 if ( is_wp_error( $tags ) ) { 2970 $this->error = new IXR_Error( 500, __( 'Could not retrieve all topic tags.' ) ); 2971 return $this->error; 2972 } 2973 for ( $i = 0; isset( $tags[$i] ); $i++ ) { 2974 _bb_make_tag_compat( $tags[$i] ); 2975 } 2976 } 2977 2978 // Only include "safe" data in the array 2979 $_tags = array(); 2980 foreach ( $tags as $tag ) { 2981 $_tags[] = $this->prepare_topic_tag( $tag ); 2982 } 2983 2984 do_action( 'bb_xmlrpc_call_return', 'bb.getTopicTags' ); 2985 2986 // Return the tags 2987 return $_tags; 2988 } 2989 2990 /** 2991 * Returns the topics which are tagged with the given tag 2992 * 2993 * @since 1.0 2994 * @return integer|object The topic data when successfully executed or an IXR_Error object on failure 2995 * @param array $args Arguments passed by the XML-RPC call 2996 * @param string $args[0] The username for authentication 2997 * @param string $args[1] The password for authentication 2998 * @param string $args[2] The tag name or slug 2999 * @param integer $args[3] The number of topics to return (optional) 3000 * @param integer $args[4] The number of the page to return (optional) 3001 * 3002 * XML-RPC request to get the latest 10 topics tagged with the tag "apples" 3003 * <methodCall> 3004 * <methodName>bb.getTopicTag</methodName> 3005 * <params> 3006 * <param><value><string>joeblow</string></value></param> 3007 * <param><value><string>123password</string></value></param> 3008 * <param><value><string>apples</string></value></param> 3009 * <param><value><string>10</string></value></param> 3010 * </params> 3011 * </methodCall> 3012 */ 3013 function bb_getTopicTag( $args ) 3014 { 3015 do_action( 'bb_xmlrpc_call', 'bb.getTopicTag' ); 3016 3017 // Escape args 3018 $this->escape( $args ); 3019 3020 // Get the login credentials 3021 $username = $args[0]; 3022 $password = (string) $args[1]; 3023 3024 // Check the user is valid 3025 if ( $this->auth_readonly ) { 3026 $user = $this->authenticate( $username, $password ); 3027 } 3028 3029 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getTopicTag' ); 3030 3031 // If an error was raised by authentication or by an action then return it 3032 if ( $this->error ) { 3033 return $this->error; 3034 } 3035 3036 // Can only be a string 3037 $tag_id = isset( $args[2] ) ? (string) $args[2] : false; 3038 3039 // Check for bad data 3040 if ( !$tag_id ) { 3041 $this->error = new IXR_Error( 400, __( 'The tag id is invalid.' ) ); 3042 return $this->error; 3043 } 3044 3045 // Check the requested topic exists 3046 if ( !$tag = bb_get_tag( $tag_id ) ) { 3047 $this->error = new IXR_Error( 400, __( 'No tag found.' ) ); 3048 return $this->error; 3049 } 3050 3051 // Get the numeric tag id 3052 $tag_id = (int) $tag->tag_id; 3053 3054 // Setup an array to store arguments to pass to get_tagged_topics() function 3055 $get_topics_args = array( 3056 'tag_id' => false, 3057 'number' => false, 3058 'page' => false 3059 ); 3060 3061 // Can only be an integer 3062 if ( isset( $args[3] ) && $number = (int) $args[3] ) { 3063 $get_topics_args['number'] = $number; 3064 } 3065 3066 // Can only be an integer 3067 if ( isset( $args[4] ) && $page = (int) $args[4] ) { 3068 $get_topics_args['page'] = $page; 3069 } 3070 3071 // Now get the topics 3072 if ( !$topics = get_tagged_topics( $tag_id ) ) { 3073 $this->error = new IXR_Error( 500, __( 'No topics found.' ) ); 3074 return $this->error; 3075 } 3076 3077 // Only include "safe" data in the array 3078 $_topics = array(); 3079 foreach ( $topics as $topic ) { 3080 $_topics[] = $this->prepare_topic( $topic ); 3081 } 3082 3083 do_action( 'bb_xmlrpc_call_return', 'bb.getTopicTag' ); 3084 3085 // Return the topics 3086 return $_topics; 3087 } 3088 3089 /** 3090 * Adds the specified tags to the specified topic 3091 * 3092 * @since 1.0 3093 * @return array|object The tags which were added when successfully executed or an IXR_Error object on failure 3094 * @param array $args Arguments passed by the XML-RPC call 3095 * @param string $args[0] The username for authentication 3096 * @param string $args[1] The password for authentication 3097 * @param string|integer $args[2] The topic id or slug 3098 * @param string|array $args[3] The tags to add to the topic 3099 * 3100 * XML-RPC request to add the tag "banana" to the topic with id 219 3101 * <methodCall> 3102 * <methodName>bb.addTopicTags</methodName> 3103 * <params> 3104 * <param><value><string>joeblow</string></value></param> 3105 * <param><value><string>123password</string></value></param> 3106 * <param><value><int>219</int></value></param> 3107 * <param><value><string>banana</string></value></param> 3108 * </params> 3109 * </methodCall> 3110 * 3111 * XML-RPC request to add the tags "banana" and "man" to the topic with id 219 3112 * <methodCall> 3113 * <methodName>bb.addTopicTags</methodName> 3114 * <params> 3115 * <param><value><string>joeblow</string></value></param> 3116 * <param><value><string>123password</string></value></param> 3117 * <param><value><int>219</int></value></param> 3118 * <param><value><string>banana, man</string></value></param> 3119 * </params> 3120 * </methodCall> 3121 * 3122 * XML-RPC request to add the tags "banana" and "man" to the topic with id 219 using an array 3123 * <methodCall> 3124 * <methodName>bb.addTopicTags</methodName> 3125 * <params> 3126 * <param><value><string>joeblow</string></value></param> 3127 * <param><value><string>123password</string></value></param> 3128 * <param><value><int>219</int></value></param> 3129 * <param><value><array> 3130 * <data><value><string>banana</string></value></data> 3131 * <data><value><string>man</string></value></data> 3132 * </array></value></param> 3133 * </params> 3134 * </methodCall> 3135 */ 3136 function bb_addTopicTags( $args ) 3137 { 3138 do_action( 'bb_xmlrpc_call', 'bb.addTopicTags' ); 3139 3140 // Escape args 3141 $this->escape( $args ); 3142 3143 // Get the login credentials 3144 $username = $args[0]; 3145 $password = (string) $args[1]; 3146 3147 // Check the user is valid 3148 $user = $this->authenticate( $username, $password, 'edit_tags', __( 'You do not have permission to edit tags.' ) ); 3149 3150 do_action( 'bb_xmlrpc_call_authenticated', 'bb.addTopicTags' ); 3151 3152 // If an error was raised by authentication or by an action then return it 3153 if ( $this->error ) { 3154 return $this->error; 3155 } 3156 3157 // Can be numeric id or slug 3158 $topic_id = isset( $args[2] ) ? $args[2] : false; 3159 3160 // Check for bad data 3161 if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) { 3162 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 3163 return $this->error; 3164 } 3165 3166 // Check the requested topic exists 3167 if ( !$topic = get_topic( $topic_id ) ) { 3168 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 3169 return $this->error; 3170 } 3171 3172 // The topic id may have been a slug, so make sure it's an integer here 3173 $topic_id = (int) $topic->topic_id; 3174 3175 // Make sure they are allowed to add tags to this topic 3176 if ( !bb_current_user_can( 'add_tag_to', $topic_id ) ) { 3177 $this->error = new IXR_Error( 403, __( 'You do not have permission to add tags to this topic.' ) ); 3178 return $this->error; 3179 } 3180 3181 $tags = isset( $args[3] ) ? $args[3] : false; 3182 3183 // Check for bad data 3184 if ( !$tags || ( !is_string( $tags ) && !is_array( $tags ) ) ) { 3185 $this->error = new IXR_Error( 400, __( 'The tag data is invalid.' ) ); 3186 return $this->error; 3187 } 3188 3189 // Add the tags 3190 if ( !$tag_ids = bb_add_topic_tags( $topic_id, $tags ) ) { 3191 $this->error = new IXR_Error( 500, __( 'The tags could not be added.' ) ); 3192 return $this->error; 3193 } 3194 3195 // Only include "safe" data in the array 3196 $_tags = array(); 3197 foreach ( $tag_ids as $tag_id ) { 3198 $_tags[] = $this->prepare_topic_tag( bb_get_tag( $tag_id ) ); 3199 } 3200 3201 do_action( 'bb_xmlrpc_call_return', 'bb.addTopicTags' ); 3202 3203 // Return the tags which were added as an array 3204 return $_tags; 3205 } 3206 3207 /** 3208 * Removes the specified tags from the specified topic 3209 * 3210 * @since 1.0 3211 * @return integer|object 1 when successfully executed or an IXR_Error object on failure 3212 * @param array $args Arguments passed by the XML-RPC call 3213 * @param string $args[0] The username for authentication 3214 * @param string $args[1] The password for authentication 3215 * @param string|integer $args[2] The topic id or slug 3216 * @param string|array $args[3] The tags to remove from the topic 3217 * 3218 * XML-RPC request to remove the tag "banana" to the topic with id 219 3219 * <methodCall> 3220 * <methodName>bb.removeTopicTags</methodName> 3221 * <params> 3222 * <param><value><string>joeblow</string></value></param> 3223 * <param><value><string>123password</string></value></param> 3224 * <param><value><int>219</int></value></param> 3225 * <param><value><string>banana</string></value></param> 3226 * </params> 3227 * </methodCall> 3228 * 3229 * XML-RPC request to remove the tags "banana" and "man" to the topic with id 219 3230 * <methodCall> 3231 * <methodName>bb.removeTopicTags</methodName> 3232 * <params> 3233 * <param><value><string>joeblow</string></value></param> 3234 * <param><value><string>123password</string></value></param> 3235 * <param><value><int>219</int></value></param> 3236 * <param><value><string>banana, man</string></value></param> 3237 * </params> 3238 * </methodCall> 3239 * 3240 * XML-RPC request to remove the tags "banana" and "man" to the topic with id 219 using an array 3241 * <methodCall> 3242 * <methodName>bb.removeTopicTags</methodName> 3243 * <params> 3244 * <param><value><string>joeblow</string></value></param> 3245 * <param><value><string>123password</string></value></param> 3246 * <param><value><int>219</int></value></param> 3247 * <param><value><array> 3248 * <data><value><string>banana</string></value></data> 3249 * <data><value><string>man</string></value></data> 3250 * </array></value></param> 3251 * </params> 3252 * </methodCall> 3253 */ 3254 function bb_removeTopicTags( $args ) 3255 { 3256 do_action( 'bb_xmlrpc_call', 'bb.removeTopicTags' ); 3257 3258 // Escape args 3259 $this->escape( $args ); 3260 3261 // Get the login credentials 3262 $username = $args[0]; 3263 $password = (string) $args[1]; 3264 3265 // Check the user is valid 3266 $user = $this->authenticate( $username, $password, 'edit_tags', __( 'You do not have permission to edit tags.' ) ); 3267 3268 do_action( 'bb_xmlrpc_call_authenticated', 'bb.removeTopicTags' ); 3269 3270 // If an error was raised by authentication or by an action then return it 3271 if ( $this->error ) { 3272 return $this->error; 3273 } 3274 3275 // Can be numeric id or slug 3276 $topic_id = isset( $args[2] ) ? $args[2] : false; 3277 3278 // Check for bad data 3279 if ( !$topic_id || ( !is_string( $topic_id ) && !is_integer( $topic_id ) ) ) { 3280 $this->error = new IXR_Error( 400, __( 'The topic id is invalid.' ) ); 3281 return $this->error; 3282 } 3283 3284 // Check the requested topic exists 3285 if ( !$topic = get_topic( $topic_id ) ) { 3286 $this->error = new IXR_Error( 400, __( 'No topic found.' ) ); 3287 return $this->error; 3288 } 3289 3290 // The topic id may have been a slug, so make sure it's an integer here 3291 $topic_id = (int) $topic->topic_id; 3292 3293 // Make sure they are allowed to add tags to this topic 3294 if ( !bb_current_user_can( 'add_tag_to', $topic_id ) ) { 3295 $this->error = new IXR_Error( 403, __( 'You do not have permission to remove tags from this topic.' ) ); 3296 return $this->error; 3297 } 3298 3299 $tags = isset( $args[3] ) ? $args[3] : false; 3300 3301 // Check for bad data 3302 if ( !$tags || ( !is_string( $tags ) && !is_array( $tags ) ) ) { 3303 $this->error = new IXR_Error( 400, __( 'The tag data is invalid.' ) ); 3304 return $this->error; 3305 } 3306 3307 // Add the tags 3308 if ( !bb_remove_topic_tags( $topic_id, $tags ) ) { 3309 $this->error = new IXR_Error( 500, __( 'The tags could not be removed.' ) ); 3310 return $this->error; 3311 } 3312 3313 $result = 1; 3314 3315 do_action( 'bb_xmlrpc_call_return', 'bb.removeTopicTags' ); 3316 3317 // Return the result 3318 return $result; 3319 } 3320 3321 /** 3322 * Renames the specified tag to a new tag name 3323 * 3324 * @since 1.0 3325 * @return array|object The tag data when successfully renamed or an IXR_Error object on failure 3326 * @param array $args Arguments passed by the XML-RPC call 3327 * @param string $args[0] The username for authentication 3328 * @param string $args[1] The password for authentication 3329 * @param string $args[2] The tag name or slug 3330 * @param string $args[3] The new tag name (slug is auto-generated) 3331 * 3332 * XML-RPC request to rename the tag "banana" to "bananas" 3333 * <methodCall> 3334 * <methodName>bb.renameTopicTag</methodName> 3335 * <params> 3336 * <param><value><string>joeblow</string></value></param> 3337 * <param><value><string>123password</string></value></param> 3338 * <param><value><string>banana</string></value></param> 3339 * <param><value><string>bananas</string></value></param> 3340 * </params> 3341 * </methodCall> 3342 */ 3343 function bb_renameTopicTag( $args ) 3344 { 3345 do_action( 'bb_xmlrpc_call', 'bb.renameTopicTag' ); 3346 3347 // Escape args 3348 $this->escape( $args ); 3349 3350 // Get the login credentials 3351 $username = $args[0]; 3352 $password = (string) $args[1]; 3353 3354 // Check the user is valid 3355 $user = $this->authenticate( $username, $password, 'manage_tags', __( 'You do not have permission to manage tags.' ) ); 3356 3357 do_action( 'bb_xmlrpc_call_authenticated', 'bb.renameTopicTag' ); 3358 3359 // If an error was raised by authentication or by an action then return it 3360 if ( $this->error ) { 3361 return $this->error; 3362 } 3363 3364 // Can only be a string 3365 $tag_id = isset( $args[2] ) ? (string) $args[2] : false; 3366 3367 // Check for bad data 3368 if ( !$tag_id ) { 3369 $this->error = new IXR_Error( 400, __( 'The tag id is invalid.' ) ); 3370 return $this->error; 3371 } 3372 3373 // Check the requested tag exists 3374 if ( !$tag = bb_get_tag( $tag_id ) ) { 3375 $this->error = new IXR_Error( 400, __( 'No tag found.' ) ); 3376 return $this->error; 3377 } 3378 3379 // Get the numeric tag id 3380 $tag_id = (int) $tag->tag_id; 3381 3382 // Can only be a string 3383 $tag_name = isset( $args[3] ) ? (string) $args[3] : false; 3384 3385 // Check for bad data 3386 if ( !$tag_name || $tag_name == $tag->tag_name ) { 3387 $this->error = new IXR_Error( 400, __( 'The tag name is invalid.' ) ); 3388 return $this->error; 3389 } 3390 3391 // Rename the tag 3392 if ( !$new_tag = bb_rename_tag( $tag_id, $tag_name ) ) { 3393 $this->error = new IXR_Error( 500, __( 'The tag could not be renamed.' ) ); 3394 return $this->error; 3395 } 3396 3397 // Only include "safe" data in the array 3398 $new_tag = $this->prepare_topic_tag( $new_tag ); 3399 3400 do_action( 'bb_xmlrpc_call_return', 'bb.renameTopicTag' ); 3401 3402 // Return the tag 3403 return $new_tag; 3404 } 3405 3406 /** 3407 * Merges the specified tags 3408 * 3409 * @since 1.0 3410 * @return array|object The tag data when successfully merged or an IXR_Error object on failure 3411 * @param array $args Arguments passed by the XML-RPC call 3412 * @param string $args[0] The username for authentication 3413 * @param string $args[1] The password for authentication 3414 * @param string $args[2] The old tag name or slug to be destroyed 3415 * @param string $args[3] The new tag name or slug where the old tag will be merged to 3416 * 3417 * XML-RPC request to merge the tag "banana" into the tag "apple" 3418 * <methodCall> 3419 * <methodName>bb.mergeTopicTags</methodName> 3420 * <params> 3421 * <param><value><string>joeblow</string></value></param> 3422 * <param><value><string>123password</string></value></param> 3423 * <param><value><string>banana</string></value></param> 3424 * <param><value><string>apple</string></value></param> 3425 * </params> 3426 * </methodCall> 3427 */ 3428 function bb_mergeTopicTags( $args ) 3429 { 3430 do_action( 'bb_xmlrpc_call', 'bb.mergeTopicTags' ); 3431 3432 // Escape args 3433 $this->escape( $args ); 3434 3435 // Get the login credentials 3436 $username = $args[0]; 3437 $password = (string) $args[1]; 3438 3439 // Check the user is valid 3440 $user = $this->authenticate( $username, $password, 'manage_tags', __( 'You do not have permission to manage tags.' ) ); 3441 3442 do_action( 'bb_xmlrpc_call_authenticated', 'bb.mergeTopicTags' ); 3443 3444 // If an error was raised by authentication or by an action then return it 3445 if ( $this->error ) { 3446 return $this->error; 3447 } 3448 3449 // Can only be strings 3450 $old_tag_id = isset( $args[2] ) ? (string) $args[2] : false; 3451 $new_tag_id = isset( $args[3] ) ? (string) $args[3] : false; 3452 3453 // Check for bad data 3454 if ( !$old_tag_id ) { 3455 $this->error = new IXR_Error( 400, __( 'The old tag id is invalid.' ) ); 3456 return $this->error; 3457 } 3458 if ( !$new_tag_id ) { 3459 $this->error = new IXR_Error( 400, __( 'The new tag id is invalid.' ) ); 3460 return $this->error; 3461 } 3462 3463 // Check the requested tags exist 3464 if ( !$old_tag = bb_get_tag( $old_tag_id ) ) { 3465 $this->error = new IXR_Error( 400, __( 'No old tag found.' ) ); 3466 return $this->error; 3467 } 3468 if ( !$new_tag = bb_get_tag( $new_tag_id ) ) { 3469 $this->error = new IXR_Error( 400, __( 'No new tag found.' ) ); 3470 return $this->error; 3471 } 3472 3473 // Get the numeric tag ids 3474 $old_tag_id = (int) $old_tag->tag_id; 3475 $new_tag_id = (int) $new_tag->tag_id; 3476 3477 // Rename the tag 3478 if ( !$result = bb_rename_tag( $old_tag_id, $new_tag_id ) ) { 3479 $this->error = new IXR_Error( 500, __( 'The tags could not be merged.' ) ); 3480 return $this->error; 3481 } 3482 3483 // Get the merged tag 3484 $new_tag = bb_get_tag( $new_tag_id ); 3485 3486 // Only include "safe" data in the array 3487 $new_tag = $this->prepare_topic_tag( $new_tag ); 3488 3489 do_action( 'bb_xmlrpc_call_return', 'bb.mergeTopicTags' ); 3490 3491 // Return the tag 3492 return $new_tag; 3493 } 3494 3495 /** 3496 * Destroys the specified tag 3497 * 3498 * @since 1.0 3499 * @return integer|object 1 when successfully deleted or an IXR_Error object on failure 3500 * @param array $args Arguments passed by the XML-RPC call 3501 * @param string $args[0] The username for authentication 3502 * @param string $args[1] The password for authentication 3503 * @param string $args[2] The tag name or slug to be destroyed 3504 * 3505 * XML-RPC request to destroy the tag "banana" 3506 * <methodCall> 3507 * <methodName>bb.destroyTopicTag</methodName> 3508 * <params> 3509 * <param><value><string>joeblow</string></value></param> 3510 * <param><value><string>123password</string></value></param> 3511 * <param><value><string>banana</string></value></param> 3512 * </params> 3513 * </methodCall> 3514 */ 3515 function bb_destroyTopicTag( $args ) 3516 { 3517 do_action( 'bb_xmlrpc_call', 'bb.destroyTopicTag' ); 3518 3519 // Escape args 3520 $this->escape( $args ); 3521 3522 // Get the login credentials 3523 $username = $args[0]; 3524 $password = (string) $args[1]; 3525 3526 // Check the user is valid 3527 $user = $this->authenticate( $username, $password, 'manage_tags', __( 'You do not have permission to manage tags.' ) ); 3528 3529 do_action( 'bb_xmlrpc_call_authenticated', 'bb.destroyTopicTag' ); 3530 3531 // If an error was raised by authentication or by an action then return it 3532 if ( $this->error ) { 3533 return $this->error; 3534 } 3535 3536 // Can only be a string 3537 $tag_id = isset( $args[2] ) ? (string) $args[2] : false; 3538 3539 // Check for bad data 3540 if ( !$tag_id ) { 3541 $this->error = new IXR_Error( 400, __( 'The tag id is invalid.' ) ); 3542 return $this->error; 3543 } 3544 3545 // Check the requested tag exists 3546 if ( !$tag = bb_get_tag( $tag_id ) ) { 3547 $this->error = new IXR_Error( 400, __( 'No tag found.' ) ); 3548 return $this->error; 3549 } 3550 3551 // Get the numeric tag id 3552 $tag_id = (int) $tag->tag_id; 3553 3554 // Destroy the tag 3555 if ( !$result = bb_destroy_tag( $tag_id ) ) { 3556 $this->error = new IXR_Error( 500, __( 'The tag could not be destroyed.' ) ); 3557 return $this->error; 3558 } 3559 3560 $result = 1; 3561 3562 do_action( 'bb_xmlrpc_call_return', 'bb.destroyTopicTag' ); 3563 3564 // Return the tag 3565 return $result; 3566 } 3567 3568 3569 3570 /** 3571 * bbPress publishing API - Options XML-RPC methods 3572 */ 3573 3574 /** 3575 * Initialises site options which can be manipulated using XML-RPC 3576 * 3577 * @since 1.0 3578 * @return void 3579 */ 3580 function initialise_site_option_info() 3581 { 3582 $this->site_options = array( 3583 // Read only options 3584 'software_name' => array( 3585 'desc' => __( 'Software Name' ), 3586 'readonly' => true, 3587 'value' => 'bbPress' 3588 ), 3589 'software_version' => array( 3590 'desc' => __( 'Software Version' ), 3591 'readonly' => true, 3592 'option' => 'version' 3593 ), 3594 'site_url' => array( 3595 'desc' => __( 'Site URL' ), 3596 'readonly' => true, 3597 'option' => 'uri' 3598 ), 3599 3600 // Updatable options 3601 'site_name' => array( 3602 'desc' => __( 'Site Name' ), 3603 'readonly' => false, 3604 'option' => 'name' 3605 ), 3606 'site_description' => array( 3607 'desc' => __( 'Site Description' ), 3608 'readonly' => false, 3609 'option' => 'description' 3610 ), 3611 'time_zone' => array( 3612 'desc' => __( 'Time Zone' ), 3613 'readonly' => false, 3614 'option' => 'gmt_offset' 3615 ), 3616 'datetime_format' => array( 3617 'desc' => __( 'Date/Time Format' ), 3618 'readonly' => false, 3619 'option' => 'datetime_format' 3620 ), 3621 'date_format' => array( 3622 'desc' => __( 'Date Format' ), 3623 'readonly' => false, 3624 'option' => 'date_format' 3625 ) 3626 ); 3627 3628 $this->site_options = apply_filters( 'xmlrpc_site_options', $this->site_options ); 3629 } 3630 3631 /** 3632 * Compiles site options into an array suitable to be passed back through the XML-RPC server 3633 * 3634 * @since 1.0 3635 * @return array The site options in an array 3636 * @param array $options An array of options to fetch and return 3637 */ 3638 function _getOptions( $options ) 3639 { 3640 $data = array(); 3641 foreach ( $options as $option ) { 3642 if ( array_key_exists( $option, $this->site_options ) ) { 3643 $data[$option] = $this->site_options[$option]; 3644 3645 // Is the value static or dynamic? 3646 if ( isset( $data[$option]['option'] ) ) { 3647 $data[$option]['value'] = bb_get_option( $data[$option]['option'] ); 3648 unset( $data[$option]['option'] ); 3649 } 3650 } 3651 } 3652 3653 return $data; 3654 } 3655 3656 /** 3657 * Gets the specified site options 3658 * 3659 * @since 1.0 3660 * @return array|object An array containing the specified options when successfully executed or an IXR_Error object on failure 3661 * @param array $args Arguments passed by the XML-RPC call 3662 * @param string $args[0] The username for authentication 3663 * @param string $args[1] The password for authentication 3664 * @param array $args[2] The options to be retrieved, when omitted the method returns all options (optional) 3665 * 3666 * XML-RPC request to get all site options 3667 * <methodCall> 3668 * <methodName>bb.getOptions</methodName> 3669 * <params> 3670 * <param><value><string>joeblow</string></value></param> 3671 * <param><value><string>123password</string></value></param> 3672 * </params> 3673 * </methodCall> 3674 * 3675 * XML-RPC request to get the site name and site description 3676 * <methodCall> 3677 * <methodName>bb.getOptions</methodName> 3678 * <params> 3679 * <param><value><string>joeblow</string></value></param> 3680 * <param><value><string>123password</string></value></param> 3681 * <param><value><array> 3682 * <data><value><string>site_name</string></value></data> 3683 * <data><value><string>site_description</string></value></data> 3684 * </array></value></param> 3685 * </params> 3686 * </methodCall> 3687 */ 3688 function bb_getOptions( $args ) 3689 { 3690 do_action( 'bb_xmlrpc_call', 'bb.getOptions' ); 3691 3692 // Escape args 3693 $this->escape( $args ); 3694 3695 // Get the login credentials 3696 $username = $args[0]; 3697 $password = (string) $args[1]; 3698 3699 // Check the user is valid 3700 if ( $this->auth_readonly ) { 3701 $user = $this->authenticate( $username, $password ); 3702 } 3703 3704 do_action( 'bb_xmlrpc_call_authenticated', 'bb.getOptions' ); 3705 3706 // If an error was raised by authentication or by an action then return it 3707 if ( $this->error ) { 3708 return $this->error; 3709 } 3710 3711 // If there are parameters supplied then make sure they are in an array 3712 $options = isset( $args[2] ) ? (array) $args[2] : false; 3713 3714 // If no specific options where asked for, return all of them 3715 if ( !$options || !count( $options ) ) { 3716 $options = array_keys( $this->site_options ); 3717 } 3718 3719 do_action( 'bb_xmlrpc_call_return', 'bb.getOptions' ); 3720 3721 return $this->_getOptions( $options ); 3722 } 3723 3724 /** 3725 * Sets the specified site options to the specified values 3726 * 3727 * @since 1.0 3728 * @return array|object An array containing the specified options when successfully executed or an IXR_Error object on failure 3729 * @param array $args Arguments passed by the XML-RPC call 3730 * @param string $args[0] The username for authentication 3731 * @param string $args[1] The password for authentication 3732 * @param array $args[2] The options to be updated along with the new value of the option 3733 * 3734 * XML-RPC request to set the site name and site description 3735 * <methodCall> 3736 * <methodName>bb.setOptions</methodName> 3737 * <params> 3738 * <param><value><string>joeblow</string></value></param> 3739 * <param><value><string>123password</string></value></param> 3740 * <param><value><struct> 3741 * <member> 3742 * <name>site_name</name> 3743 * <value><string>Awesome forums</string></value> 3744 * </member> 3745 * <member> 3746 * <name>site_description</name> 3747 * <value><string>My totally awesome forums will kick your butt</string></value> 3748 * </member> 3749 * </struct></value></param> 3750 * </params> 3751 * </methodCall> 3752 */ 3753 function bb_setOptions( $args ) 3754 { 3755 do_action( 'bb_xmlrpc_call', 'bb.setOptions' ); 3756 3757 // Escape args 3758 $this->escape( $args ); 3759 3760 // Get the login credentials 3761 $username = $args[0]; 3762 $password = (string) $args[1]; 3763 3764 // Check the user is valid 3765 $user = $this->authenticate( $username, $password, 'manage_options', __( 'You are not allowed to manage options.' ) ); 3766 3767 do_action( 'bb_xmlrpc_call_authenticated', 'bb.setOptions' ); 3768 3769 // If an error was raised by authentication or by an action then return it 3770 if ( $this->error ) { 3771 return $this->error; 3772 } 3773 3774 // Make sure there is something for us to do 3775 if ( !$args[2] || !is_array( $args[2] ) || !count( $args[2] ) ) { 3776 $this->error = new IXR_Error( 400, __( 'The options data is invalid.' ) ); 3777 return $this->error; 3778 } 3779 3780 $options = (array) $args[2]; 3781 3782 // Update the requested options 3783 foreach( $options as $o_name => $o_value ) { 3784 $option_names[] = $o_name; 3785 3786 // If there is no value set skip it 3787 if ( empty( $o_value ) ) { 3788 continue; 3789 } 3790 3791 // If the option doesn't exist skip it 3792 if ( !array_key_exists( $o_name, $this->site_options ) ) { 3793 continue; 3794 } 3795 3796 // If the option is readonly skip it 3797 if ( $this->site_options[$o_name]['readonly'] == true ) { 3798 continue; 3799 } 3800 3801 // Everything is good, update the option 3802 bb_update_option( $this->site_options[$o_name]['option'], $o_value ); 3803 } 3804 3805 $_options = $this->_getOptions( $option_names ); 3806 3807 do_action( 'bb_xmlrpc_call_return', 'bb.setOptions' ); 3808 3809 // Now return the updated values 3810 return $_options; 3811 } 3812 3813 3814 3815 /** 3816 * Pingback XML-RPC methods 3817 */ 3818 3819 /** 3820 * Processes pingback requests 3821 * 3822 * @since 1.0 3823 * @link http://www.hixie.ch/specs/pingback/pingback 3824 * @return string|object A message of success or an IXR_Error object on failure 3825 * @param array $args Arguments passed by the XML-RPC call 3826 * @param string $args[0] The full URI of the post where the pingback is being sent from 3827 * @param string $args[1] The full URI of the post where the pingback is being sent to 3828 * 3829 * XML-RPC request to register a pingback 3830 * <methodCall> 3831 * <methodName>pingback.ping</methodName> 3832 * <params> 3833 * <param><value><string>http://example.org/2008/09/post-containing-a-link/</string></value></param> 3834 * <param><value><string>http://example.com/2008/08/post-being-linked-to/</string></value></param> 3835 * </params> 3836 * </methodCall> 3837 */ 3838 function pingback_ping( $args ) 3839 { 3840 do_action( 'bb_xmlrpc_call', 'pingback.ping' ); 3841 3842 $this->escape( $args ); 3843 3844 // No particular need to sanitise 3845 $link_from = (string) $args[0]; 3846 $link_to = (string) $args[1]; 3847 3848 // Tidy up ampersands in the URLs 3849 $link_from = str_replace( '&', '&', $link_from ); 3850 $link_to = str_replace( '&', '&', $link_to ); 3851 $link_to = str_replace( '&', '&', $link_to ); 3852 3853 // Check if the topic linked to is in our site - a little more strict than WordPress, doesn't pull out the www if added 3854 if ( !bb_match_domains( $link_to, bb_get_uri() ) ) { 3855 // These are not the droids you are looking for 3856 $this->error = new IXR_Error( 0, __( 'This is not the site you are trying to pingback.' ) ); 3857 return $this->error; 3858 } 3859 3860 // Get the topic 3861 if ( $topic_to = bb_get_topic_from_uri( $link_to ) ) { 3862 // Topics shouldn't ping themselves 3863 if ( $topic_from = bb_get_topic_from_uri( $link_from ) ) { 3864 if ( $topic_from->topic_id === $topic_to->topic_id ) { 3865 $this->error = new IXR_Error( 0, __( 'The source URL and the target URL cannot both point to the same resource.' ) ); 3866 return $this->error; 3867 } 3868 } 3869 } else { 3870 $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.' ) ); 3871 return $this->error; 3872 } 3873 3874 // Let's check that the remote site didn't already pingback this entry 3875 $query = new BB_Query( 'post', array( 'topic_id' => $topic_to->topic_id, 'append_meta' => true ), 'get_thread' ); 3876 $posts_to = $query->results; 3877 unset( $query ); 3878 3879 // Make sure we have some posts in the topic, this error should never happen really 3880 if ( !$posts_to || !is_array( $posts_to ) || !count( $posts_to ) ) { 3881 $this->error = new IXR_Error( 0, __( 'The specified target topic does not contain any posts.' ) ); 3882 return $this->error; 3883 } 3884 3885 // Check if we already have a pingback from this URL 3886 foreach ( $posts_to as $post ) { 3887 if ( isset( $post->pingback_uri ) && trim( $post->pingback_uri ) === trim( $link_from ) ) { 3888 $this->error = new IXR_Error( 48, __( 'The pingback has already been registered.' ) ); 3889 return $this->error; 3890 } 3891 } 3892 unset( $posts_to, $post ); 3893 3894 // Give time for the server sending the pingback to finish publishing it's post 3895 sleep(1); 3896 3897 // Let's check the remote site for valid URL and content 3898 $link_from_source = wp_remote_fopen( $link_from ); 3899 if ( !$link_from_source ) { 3900 $this->error = new IXR_Error( 16, __( 'The source URL does not exist.' ) ); 3901 return $this->error; 3902 } 3903 3904 // Allow plugins to filter here 3905 $link_from_source = apply_filters( 'bb_pre_remote_source', $link_from_source, $link_to ); 3906 3907 // Work around bug in strip_tags() 3908 $link_from_source = str_replace( '<!DOC', '<DOC', $link_from_source ); 3909 3910 // Normalize spaces 3911 $link_from_source = preg_replace( '/[\s\r\n\t]+/', ' ', $link_from_source ); 3912 3913 // Turn certain elements to double line returns 3914 $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 ); 3915 3916 // Find the title of the page 3917 preg_match( '|<title>([^<]*?)</title>|is', $link_from_source, $link_from_title ); 3918 $link_from_title = $link_from_title[1]; 3919 if ( empty( $link_from_title ) ) { 3920 $this->error = new IXR_Error( 32, __( 'We cannot find a title on that page.' ) ); 3921 return $this->error; 3922 } 3923 3924 // Strip out all tags except anchors 3925 $link_from_source = strip_tags( $link_from_source, '<a>' ); // just keep the tag we need 3926 3927 // Split the source into paragraphs 3928 $link_from_paragraphs = explode( "\n\n", $link_from_source ); 3929 3930 // Prepare the link to search for in preg_match() once here 3931 $preg_target = preg_quote( $link_to ); 3932 3933 // Loop through the paragraphs looking for the context for the url 3934 foreach ( $link_from_paragraphs as $link_from_paragraph ) { 3935 // The url exists 3936 if ( strpos( $link_from_paragraph, $link_to ) !== false ) { 3937 // But is it in an anchor tag 3938 preg_match( 3939 "|<a[^>]+?" . $preg_target . "[^>]*>([^>]+?)</a>|", 3940 $link_from_paragraph, 3941 $context 3942 ); 3943 // If the URL isn't in an anchor tag, keep looking 3944 if ( empty( $context ) ) { 3945 continue; 3946 } 3947 3948 // We're going to use this fake tag to mark the context in a bit 3949 // the marker is needed in case the link text appears more than once in the paragraph 3950 $excerpt = preg_replace( '|\</?wpcontext\>|', '', $link_from_paragraph ); 3951 3952 // Prevent really long link text 3953 if ( strlen( $context[1] ) > 100 ) { 3954 $context[1] = substr( $context[1], 0, 100 ) . '...'; 3955 } 3956 3957 // Set up the marker around the context 3958 $marker = '<wpcontext>' . $context[1] . '</wpcontext>'; 3959 // Swap out the link for our marker 3960 $excerpt = str_replace( $context[0], $marker, $excerpt ); 3961 // Strip all tags except for our context marker 3962 $excerpt = trim( strip_tags( $excerpt, '<wpcontext>' ) ); 3963 // Make the marker safe for use in regexp 3964 $preg_marker = preg_quote( $marker ); 3965 // Reduce the excerpt to only include 100 characters on either side of the link 3966 $excerpt = preg_replace( "|.*?\s(.{0,100}" . $preg_marker . "{0,100})\s.*|s", '$1', $excerpt ); 3967 // Strip tags again, to remove the marker wrapper 3968 $excerpt = strip_tags( $excerpt ); 3969 break; 3970 } 3971 } 3972 3973 // Make sure the link to the target was found in the excerpt 3974 if ( empty( $context ) ) { 3975 $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.' ) ); 3976 return $this->error; 3977 } 3978 3979 // Add whacky prefix and suffix to the excerpt and sanitize 3980 $excerpt = '[...] ' . esc_html( $excerpt ) . ' [...]'; 3981 $this->escape( $excerpt ); 3982 3983 // Build an array of post data to insert then insert a new post 3984 $postdata = array( 3985 'topic_id' => $topic_to->topic_id, 3986 'post_text' => $excerpt, 3987 'poster_id' => 0, 3988 ); 3989 if ( !$post_ID = bb_insert_post( $postdata ) ) { 3990 $this->error = new IXR_Error( 0, __( 'The pingback could not be added.' ) ); 3991 return $this->error; 3992 } 3993 3994 // Add meta to let us know where the pingback came from 3995 $link_from = str_replace( '&', '&', $link_from ); 3996 $this->escape( $link_from ); 3997 bb_update_postmeta( $post_ID, 'pingback_uri', $link_from ); 3998 3999 // Add the title to meta 4000 $this->escape( $link_from_title ); 4001 bb_update_postmeta( $post_ID, 'pingback_title', $link_from_title ); 4002 4003 // Action for plugins and what not 4004 do_action( 'bb_pingback_post', $post_ID ); 4005 4006 // Return success message, complete with emoticon 4007 return sprintf( __( 'Pingback from %1$s to %2$s registered. Keep the web talking! :-)' ), $link_from, $link_to ); 4008 } 4009 4010 4011 4012 /** 4013 * Returns an array of URLs that pingbacked the given URL 4014 * 4015 * @since 1.0 4016 * @link http://www.aquarionics.com/misc/archives/blogite/0198.html 4017 * @return array The array of URLs that pingbacked the given topic 4018 * @param array $args Arguments passed by the XML-RPC call 4019 * @param string $args[0] The full URI of the post where the pingback is being sent from 4020 * @param string $args[1] The full URI of the post where the pingback is being sent to 4021 * 4022 * XML-RPC request to get all pingbacks on a topic 4023 * <methodCall> 4024 * <methodName>pingback.ping</methodName> 4025 * <params> 4026 * <param><value><string>http://example.com/2008/08/post-tobe-queried/</string></value></param> 4027 * </params> 4028 * </methodCall> 4029 */ 4030 function pingback_extensions_getPingbacks( $args ) 4031 { 4032 do_action( 'bb_xmlrpc_call', 'pingback.extensions.getPingbacks' ); 4033 4034 $this->escape( $args ); 4035 4036 // Don't accept arrays of arguments 4037 if ( is_array( $args ) ) { 4038 $this->error = new IXR_Error( 404, __( 'The requested method only accepts one parameter.' ) ); 4039 return $this->error; 4040 } else { 4041 $url = (string) $args; 4042 } 4043 4044 // Tidy up ampersands in the URI 4045 $url = str_replace( '&', '&', $url ); 4046 $url = str_replace( '&', '&', $url ); 4047 4048 // Check if the URI is in our site 4049 if ( !bb_match_domains( $url, bb_get_uri() ) ) { 4050 // These are not the droids you are looking for 4051 $this->error = new IXR_Error( 0, __( 'The specified target URL is not on this domain.' ) ); 4052 return $this->error; 4053 } 4054 4055 // Make sure the specified URI is in fact associated with a topic 4056 if ( !$topic = bb_get_topic_from_uri( $url ) ) { 4057 $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.' ) ); 4058 return $this->error; 4059 } 4060 4061 // Grab the posts from the topic 4062 $query = new BB_Query( 'post', array( 'topic_id' => $topic_to->topic_id, 'append_meta' => true ), 'get_thread' ); 4063 $posts_to = $query->results; 4064 unset( $query ); 4065 4066 // Check for pingbacks in the post meta data 4067 $pingbacks = array(); 4068 foreach ( $posts_to as $post ) { 4069 if ( isset( $post->pingback_uri ) ) { 4070 $pingbacks[] = $post->pingback_uri; 4071 } 4072 } 4073 unset( $post ); 4074 4075 // This will return an empty array on failure 4076 return $pingbacks; 4077 } 4078 } 4079 4080 4081 4082 /** 4083 * Initialises the XML-RPC server 4084 * 4085 * @since 1.0 4086 * @var object The instance of the XML-RPC server class 4087 */ 4088 $bb_xmlrpc_server = new BB_XMLRPC_Server();
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Dec 7 01:01:35 2017 | Cross-referenced by PHPXref 0.7.1 |