PageRenderTime 46ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/woocommerce/includes/admin/class-wc-admin-webhooks.php

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