BB_XMLRPC_Server

XML-RPC server class to allow for remote publishing.

Defined (1)

The class is defined in the following location(s).

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