WC_Admin_Webhooks

WC_Admin_Webhooks.

Defined (1)

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

/includes/admin/class-wc-admin-webhooks.php  
  1. class WC_Admin_Webhooks { 
  2.  
  3. /** 
  4. * Initialize the webhooks admin actions. 
  5. */ 
  6. public function __construct() { 
  7. add_action( 'admin_init', array( $this, 'actions' ) ); 
  8.  
  9. /** 
  10. * Check if is webhook settings page. 
  11. * @return bool 
  12. */ 
  13. private function is_webhook_settings_page() { 
  14. return isset( $_GET['page'] ) 
  15. && 'wc-settings' == $_GET['page'] 
  16. && isset( $_GET['tab'] ) 
  17. && 'api' == $_GET['tab'] 
  18. && isset( $_GET['section'] ) 
  19. && 'webhooks' == isset( $_GET['section'] ); 
  20.  
  21. /** 
  22. * Updated the Webhook name. 
  23. * @param int $webhook_id 
  24. */ 
  25. private function update_name( $webhook_id ) { 
  26. global $wpdb; 
  27.  
  28. // @codingStandardsIgnoreStart 
  29. /** translators: %s: date` */ 
  30. $name = ! empty( $_POST['webhook_name'] ) ? $_POST['webhook_name'] : sprintf( __( 'Webhook created on %s', 'woocommerce' ), strftime( _x( '%b %d, %Y @ %I:%M %p', 'Webhook created on date parsed by strftime', 'woocommerce' ) ) ); 
  31. // @codingStandardsIgnoreEnd 
  32. $wpdb->update( $wpdb->posts, array( 'post_title' => $name ), array( 'ID' => $webhook_id ) ); 
  33.  
  34. /** 
  35. * Updated the Webhook status. 
  36. * @param WC_Webhook $webhook 
  37. */ 
  38. private function update_status( $webhook ) { 
  39. $status = ! empty( $_POST['webhook_status'] ) ? wc_clean( $_POST['webhook_status'] ) : ''; 
  40.  
  41. $webhook->update_status( $status ); 
  42.  
  43. /** 
  44. * Updated the Webhook delivery URL. 
  45. * @param WC_Webhook $webhook 
  46. */ 
  47. private function update_delivery_url( $webhook ) { 
  48. $delivery_url = ! empty( $_POST['webhook_delivery_url'] ) ? $_POST['webhook_delivery_url'] : ''; 
  49.  
  50. if ( wc_is_valid_url( $delivery_url ) ) { 
  51. $webhook->set_delivery_url( $delivery_url ); 
  52.  
  53. /** 
  54. * Updated the Webhook secret. 
  55. * @param WC_Webhook $webhook 
  56. */ 
  57. private function update_secret( $webhook ) { 
  58. $secret = ! empty( $_POST['webhook_secret'] ) ? $_POST['webhook_secret'] : wp_generate_password( 50, true, true ); 
  59.  
  60. $webhook->set_secret( $secret ); 
  61.  
  62. /** 
  63. * Updated the Webhook topic. 
  64. * @param WC_Webhook $webhook 
  65. */ 
  66. private function update_topic( $webhook ) { 
  67. if ( ! empty( $_POST['webhook_topic'] ) ) { 
  68.  
  69. $resource = ''; 
  70. $event = ''; 
  71.  
  72. switch ( $_POST['webhook_topic'] ) { 
  73. case 'custom' : 
  74. if ( ! empty( $_POST['webhook_custom_topic'] ) ) { 
  75. list( $resource, $event ) = explode( '.', wc_clean( $_POST['webhook_custom_topic'] ) ); 
  76. break; 
  77. case 'action' : 
  78. $resource = 'action'; 
  79. $event = ! empty( $_POST['webhook_action_event'] ) ? wc_clean( $_POST['webhook_action_event'] ) : ''; 
  80. break; 
  81.  
  82. default : 
  83. list( $resource, $event ) = explode( '.', wc_clean( $_POST['webhook_topic'] ) ); 
  84. break; 
  85.  
  86. $topic = $resource . '.' . $event; 
  87.  
  88. if ( wc_is_webhook_valid_topic( $topic ) ) { 
  89. $webhook->set_topic( $topic ); 
  90.  
  91. /** 
  92. * Update webhook api version. 
  93. * @param WC_Webhook $webhook Webhook instance. 
  94. */ 
  95. private function update_api_version( $webhook ) { 
  96. $version = ! empty( $_POST['webhook_api_version'] ) ? wc_clean( $_POST['webhook_api_version'] ) : 'wp_api_v2'; 
  97.  
  98. $webhook->set_api_version( $version ); 
  99.  
  100. /** 
  101. * Save method. 
  102. */ 
  103. private function save() { 
  104. if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'woocommerce-settings' ) ) { 
  105. wp_die( __( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) ); 
  106.  
  107. $webhook_id = absint( $_POST['webhook_id'] ); 
  108.  
  109. if ( ! current_user_can( 'edit_shop_webhook', $webhook_id ) ) { 
  110. return; 
  111.  
  112. $webhook = new WC_Webhook( $webhook_id ); 
  113.  
  114. // Name 
  115. $this->update_name( $webhook->id ); 
  116.  
  117. // Status 
  118. $this->update_status( $webhook ); 
  119.  
  120. // Delivery URL 
  121. $this->update_delivery_url( $webhook ); 
  122.  
  123. // Secret 
  124. $this->update_secret( $webhook ); 
  125.  
  126. // Topic 
  127. $this->update_topic( $webhook ); 
  128.  
  129. // API version. 
  130. $this->update_api_version( $webhook ); 
  131.  
  132. // Update date. 
  133. wp_update_post( array( 'ID' => $webhook->id, 'post_modified' => current_time( 'mysql' ) ) ); 
  134.  
  135. // Run actions 
  136. do_action( 'woocommerce_webhook_options_save', $webhook->id ); 
  137.  
  138. delete_transient( 'woocommerce_webhook_ids' ); 
  139.  
  140. // Ping the webhook at the first time that is activated 
  141. $pending_delivery = get_post_meta( $webhook->id, '_webhook_pending_delivery', true ); 
  142.  
  143. if ( isset( $_POST['webhook_status'] ) && 'active' === $_POST['webhook_status'] && $pending_delivery ) { 
  144. $result = $webhook->deliver_ping(); 
  145.  
  146. if ( is_wp_error( $result ) ) { 
  147. // Redirect to webhook edit page to avoid settings save actions 
  148. wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=api§ion=webhooks&edit-webhook=' . $webhook->id . '&error=' . urlencode( $result->get_error_message() ) ) ); 
  149. exit(); 
  150.  
  151. // Redirect to webhook edit page to avoid settings save actions 
  152. wp_safe_redirect( admin_url( 'admin.php?page=wc-settings&tab=api§ion=webhooks&edit-webhook=' . $webhook->id . '&updated=1' ) ); 
  153. exit(); 
  154.  
  155. /** 
  156. * Create Webhook. 
  157. */ 
  158. private function create() { 
  159. if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'create-webhook' ) ) { 
  160. wp_die( __( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) ); 
  161.  
  162. if ( ! current_user_can( 'publish_shop_webhooks' ) ) { 
  163. wp_die( __( 'You don\'t have permissions to create Webhooks!', 'woocommerce' ) ); 
  164.  
  165. $webhook_id = wp_insert_post( array( 
  166. 'post_type' => 'shop_webhook',  
  167. 'post_status' => 'pending',  
  168. 'ping_status' => 'closed',  
  169. 'post_author' => get_current_user_id(),  
  170. 'post_password' => strlen( ( $password = uniqid( 'webhook_' ) ) ) > 20 ? substr( $password, 0, 20 ) : $password,  
  171. // @codingStandardsIgnoreStart 
  172. /** translators: %s: date */ 
  173. 'post_title' => sprintf( __( 'Webhook created on %s', 'woocommerce' ), strftime( _x( '%b %d, %Y @ %I:%M %p', 'Webhook created on date parsed by strftime', 'woocommerce' ) ) ),  
  174. // @codingStandardsIgnoreEnd 
  175. 'comment_status' => 'open',  
  176. ) ); 
  177.  
  178. if ( is_wp_error( $webhook_id ) ) { 
  179. wp_die( $webhook_id->get_error_messages() ); 
  180.  
  181. update_post_meta( $webhook_id, '_webhook_pending_delivery', true ); 
  182. $webhook = new WC_Webhook( $webhook_id ); 
  183. $webhook->set_api_version( 'wp_api_v2' ); 
  184.  
  185. delete_transient( 'woocommerce_webhook_ids' ); 
  186.  
  187. // Redirect to edit page 
  188. wp_redirect( admin_url( 'admin.php?page=wc-settings&tab=api§ion=webhooks&edit-webhook=' . $webhook_id . '&created=1' ) ); 
  189. exit(); 
  190.  
  191. /** 
  192. * Bulk trash/delete. 
  193. * @param array $webhooks 
  194. * @param bool $delete 
  195. */ 
  196. private function bulk_trash( $webhooks, $delete = false ) { 
  197. foreach ( $webhooks as $webhook_id ) { 
  198. if ( $delete ) { 
  199. wp_delete_post( $webhook_id, true ); 
  200. } else { 
  201. wp_trash_post( $webhook_id ); 
  202.  
  203. $type = ! EMPTY_TRASH_DAYS || $delete ? 'deleted' : 'trashed'; 
  204. $qty = count( $webhooks ); 
  205. $status = isset( $_GET['status'] ) ? '&status=' . sanitize_text_field( $_GET['status'] ) : ''; 
  206.  
  207. delete_transient( 'woocommerce_webhook_ids' ); 
  208.  
  209. // Redirect to webhooks page 
  210. wp_redirect( admin_url( 'admin.php?page=wc-settings&tab=api§ion=webhooks' . $status . '&' . $type . '=' . $qty ) ); 
  211. exit(); 
  212.  
  213. /** 
  214. * Bulk untrash. 
  215. * @param array $webhooks 
  216. */ 
  217. private function bulk_untrash( $webhooks ) { 
  218. foreach ( $webhooks as $webhook_id ) { 
  219. wp_untrash_post( $webhook_id ); 
  220.  
  221. $qty = count( $webhooks ); 
  222.  
  223. delete_transient( 'woocommerce_webhook_ids' ); 
  224.  
  225. // Redirect to webhooks page 
  226. wp_redirect( admin_url( 'admin.php?page=wc-settings&tab=api§ion=webhooks&status=trash&untrashed=' . $qty ) ); 
  227. exit(); 
  228.  
  229. /** 
  230. * Bulk actions. 
  231. */ 
  232. private function bulk_actions() { 
  233. if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'woocommerce-settings' ) ) { 
  234. wp_die( __( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) ); 
  235.  
  236. if ( ! current_user_can( 'edit_shop_webhooks' ) ) { 
  237. wp_die( __( 'You don\'t have permissions to edit Webhooks!', 'woocommerce' ) ); 
  238.  
  239. $webhooks = array_map( 'absint', (array) $_GET['webhook'] ); 
  240.  
  241. switch ( $_GET['action'] ) { 
  242. case 'trash' : 
  243. $this->bulk_trash( $webhooks ); 
  244. break; 
  245. case 'untrash' : 
  246. $this->bulk_untrash( $webhooks ); 
  247. break; 
  248. case 'delete' : 
  249. $this->bulk_trash( $webhooks, true ); 
  250. break; 
  251. default : 
  252. break; 
  253.  
  254. /** 
  255. * Empty Trash. 
  256. */ 
  257. private function empty_trash() { 
  258. if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'empty_trash' ) ) { 
  259. wp_die( __( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) ); 
  260.  
  261. if ( ! current_user_can( 'delete_shop_webhooks' ) ) { 
  262. wp_die( __( 'You don\'t have permissions to delete Webhooks!', 'woocommerce' ) ); 
  263.  
  264. $webhooks = get_posts( array( 
  265. 'post_type' => 'shop_webhook',  
  266. 'ignore_sticky_posts' => true,  
  267. 'nopaging' => true,  
  268. 'post_status' => 'trash',  
  269. 'fields' => 'ids',  
  270. ) ); 
  271.  
  272. foreach ( $webhooks as $webhook_id ) { 
  273. wp_delete_post( $webhook_id, true ); 
  274.  
  275. $qty = count( $webhooks ); 
  276.  
  277. // Redirect to webhooks page 
  278. wp_redirect( admin_url( 'admin.php?page=wc-settings&tab=api§ion=webhooks&deleted=' . $qty ) ); 
  279. exit(); 
  280.  
  281. /** 
  282. * Webhooks admin actions. 
  283. */ 
  284. public function actions() { 
  285. if ( $this->is_webhook_settings_page() ) { 
  286. // Save 
  287. if ( isset( $_POST['save'] ) && isset( $_POST['webhook_id'] ) ) { 
  288. $this->save(); 
  289.  
  290. // Create 
  291. if ( isset( $_GET['create-webhook'] ) ) { 
  292. $this->create(); 
  293.  
  294. // Bulk actions 
  295. if ( isset( $_GET['action'] ) && isset( $_GET['webhook'] ) ) { 
  296. $this->bulk_actions(); 
  297.  
  298. // Empty trash 
  299. if ( isset( $_GET['empty_trash'] ) ) { 
  300. $this->empty_trash(); 
  301.  
  302. /** 
  303. * Page output. 
  304. */ 
  305. public static function page_output() { 
  306. // Hide the save button 
  307. $GLOBALS['hide_save_button'] = true; 
  308.  
  309. if ( isset( $_GET['edit-webhook'] ) ) { 
  310. $webhook_id = absint( $_GET['edit-webhook'] ); 
  311. $webhook = new WC_Webhook( $webhook_id ); 
  312.  
  313. if ( 'trash' != $webhook->post_data->post_status ) { 
  314. include( 'settings/views/html-webhooks-edit.php' ); 
  315. return; 
  316.  
  317. self::table_list_output(); 
  318.  
  319. /** 
  320. * Notices. 
  321. */ 
  322. public static function notices() { 
  323. if ( isset( $_GET['trashed'] ) ) { 
  324. $trashed = absint( $_GET['trashed'] ); 
  325.  
  326. /** translators: %d: count */ 
  327. WC_Admin_Settings::add_message( sprintf( _n( '%d webhook moved to the Trash.', '%d webhooks moved to the Trash.', $trashed, 'woocommerce' ), $trashed ) ); 
  328.  
  329. if ( isset( $_GET['untrashed'] ) ) { 
  330. $untrashed = absint( $_GET['untrashed'] ); 
  331.  
  332. /** translators: %d: count */ 
  333. WC_Admin_Settings::add_message( sprintf( _n( '%d webhook restored from the Trash.', '%d webhooks restored from the Trash.', $untrashed, 'woocommerce' ), $untrashed ) ); 
  334.  
  335. if ( isset( $_GET['deleted'] ) ) { 
  336. $deleted = absint( $_GET['deleted'] ); 
  337.  
  338. /** translators: %d: count */ 
  339. WC_Admin_Settings::add_message( sprintf( _n( '%d webhook permanently deleted.', '%d webhooks permanently deleted.', $deleted, 'woocommerce' ), $deleted ) ); 
  340.  
  341. if ( isset( $_GET['updated'] ) ) { 
  342. WC_Admin_Settings::add_message( __( 'Webhook updated successfully.', 'woocommerce' ) ); 
  343.  
  344. if ( isset( $_GET['created'] ) ) { 
  345. WC_Admin_Settings::add_message( __( 'Webhook created successfully.', 'woocommerce' ) ); 
  346.  
  347. if ( isset( $_GET['error'] ) ) { 
  348. WC_Admin_Settings::add_error( wc_clean( $_GET['error'] ) ); 
  349.  
  350. /** 
  351. * Table list output. 
  352. */ 
  353. private static function table_list_output() { 
  354. echo '<h2>' . __( 'Webhooks', 'woocommerce' ) . ' <a href="' . esc_url( wp_nonce_url( admin_url( 'admin.php?page=wc-settings&tab=api§ion=webhooks&create-webhook=1' ), 'create-webhook' ) ) . '" class="add-new-h2">' . __( 'Add webhook', 'woocommerce' ) . '</a></h2>'; 
  355.  
  356. $webhooks_table_list = new WC_Admin_Webhooks_Table_List(); 
  357. $webhooks_table_list->prepare_items(); 
  358.  
  359. echo '<input type="hidden" name="page" value="wc-settings" />'; 
  360. echo '<input type="hidden" name="tab" value="api" />'; 
  361. echo '<input type="hidden" name="section" value="webhooks" />'; 
  362.  
  363. $webhooks_table_list->views(); 
  364. $webhooks_table_list->search_box( __( 'Search webhooks', 'woocommerce' ), 'webhook' ); 
  365. $webhooks_table_list->display(); 
  366.  
  367. /** 
  368. * Logs output. 
  369. * @param WC_Webhook $webhook 
  370. */ 
  371. public static function logs_output( $webhook ) { 
  372. $current = isset( $_GET['log_page'] ) ? absint( $_GET['log_page'] ) : 1; 
  373. $args = array( 
  374. 'post_id' => $webhook->id,  
  375. 'status' => 'approve',  
  376. 'type' => 'webhook_delivery',  
  377. 'number' => 10,  
  378. ); 
  379.  
  380. if ( 1 < $current ) { 
  381. $args['offset'] = ( $current - 1 ) * 10; 
  382.  
  383. remove_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_webhook_comments' ), 10, 1 ); 
  384.  
  385. $logs = get_comments( $args ); 
  386.  
  387. add_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_webhook_comments' ), 10, 1 ); 
  388.  
  389. if ( $logs ) { 
  390. include_once( dirname( __FILE__ ) . '/settings/views/html-webhook-logs.php' ); 
  391. } else { 
  392. echo '<p>' . __( 'This Webhook has no log yet.', 'woocommerce' ) . '</p>'; 
  393.  
  394. /** 
  395. * Get the webhook topic data. 
  396. * @return array 
  397. */ 
  398. public static function get_topic_data( $webhook ) { 
  399. $topic = $webhook->get_topic(); 
  400. $event = ''; 
  401. $resource = ''; 
  402.  
  403. if ( $topic ) { 
  404. list( $resource, $event ) = explode( '.', $topic ); 
  405.  
  406. if ( 'action' === $resource ) { 
  407. $topic = 'action'; 
  408. } elseif ( ! in_array( $resource, array( 'coupon', 'customer', 'order', 'product' ) ) ) { 
  409. $topic = 'custom'; 
  410.  
  411. return array( 
  412. 'topic' => $topic,  
  413. 'event' => $event,  
  414. 'resource' => $resource,  
  415. ); 
  416.  
  417. /** 
  418. * Get the logs navigation. 
  419. * @param int $total 
  420. * @return string 
  421. */ 
  422. public static function get_logs_navigation( $total, $webhook ) { 
  423. $pages = ceil( $total / 10 ); 
  424. $current = isset( $_GET['log_page'] ) ? absint( $_GET['log_page'] ) : 1; 
  425.  
  426. $html = '<div class="webhook-logs-navigation">'; 
  427.  
  428. $html .= '<p class="info" style="float: left;"><strong>'; 
  429. /** translators: 1: items count (i.e. 8 items) 2: current page 3: total pages */ 
  430. $html .= sprintf( 
  431. __( '%1$s – Page %2$d of %3$d', 'woocommerce' ),  
  432. sprintf( _n( '%d item', '%d items', $total, 'woocommerce' ), $total ),  
  433. $current,  
  434. $pages 
  435. ); 
  436. $html .= '</strong></p>'; 
  437.  
  438. if ( 1 < $pages ) { 
  439. $html .= '<p class="tools" style="float: right;">'; 
  440. if ( 1 == $current ) { 
  441. $html .= '<button class="button-primary" disabled="disabled">' . __( '‹ Previous', 'woocommerce' ) . '</button> '; 
  442. } else { 
  443. $html .= '<a class="button-primary" href="' . admin_url( 'admin.php?page=wc-settings&tab=api§ion=webhooks&edit-webhook=' . $webhook->id . '&log_page=' . ( $current - 1 ) ) . '#webhook-logs">' . __( '‹ Previous', 'woocommerce' ) . '</a> '; 
  444.  
  445. if ( $pages == $current ) { 
  446. $html .= '<button class="button-primary" disabled="disabled">' . __( 'Next ›', 'woocommerce' ) . '</button>'; 
  447. } else { 
  448. $html .= '<a class="button-primary" href="' . admin_url( 'admin.php?page=wc-settings&tab=api§ion=webhooks&edit-webhook=' . $webhook->id . '&log_page=' . ( $current + 1 ) ) . '#webhook-logs">' . __( 'Next ›', 'woocommerce' ) . '</a>'; 
  449. $html .= '</p>'; 
  450.  
  451. $html .= '<div class="clear"></div></div>'; 
  452.  
  453. return $html;