Нет описания

ajax-actions.php 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. <?php
  2. /**
  3. * Ajax actions used in by admin.
  4. *
  5. * @since 1.0.0
  6. */
  7. /**
  8. * Save a form.
  9. *
  10. * @since 1.0.0
  11. */
  12. function wpforms_save_form() {
  13. // Run a security check.
  14. if ( ! check_ajax_referer( 'wpforms-builder', 'nonce', false ) ) {
  15. wp_send_json_error( esc_html__( 'Your session expired. Please reload the builder.', 'wpforms-lite' ) );
  16. }
  17. // Check for permissions.
  18. if ( ! wpforms_current_user_can( 'edit_forms' ) ) {
  19. wp_send_json_error( esc_html__( 'You are not allowed to perform this action.', 'wpforms-lite' ) );
  20. }
  21. // Check for form data.
  22. if ( empty( $_POST['data'] ) ) {
  23. wp_send_json_error( esc_html__( 'Something went wrong while performing this action.', 'wpforms-lite' ) );
  24. }
  25. // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
  26. $form_post = json_decode( wp_unslash( $_POST['data'] ) );
  27. $data = [
  28. 'fields' => [],
  29. ];
  30. if ( $form_post ) {
  31. foreach ( $form_post as $post_input_data ) {
  32. // For input names that are arrays (e.g. `menu-item-db-id[3][4][5]`),
  33. // derive the array path keys via regex and set the value in $_POST.
  34. preg_match( '#([^\[]*)(\[(.+)\])?#', $post_input_data->name, $matches );
  35. $array_bits = array( $matches[1] );
  36. if ( isset( $matches[3] ) ) {
  37. $array_bits = array_merge( $array_bits, explode( '][', $matches[3] ) );
  38. }
  39. $new_post_data = [];
  40. // Build the new array value from leaf to trunk.
  41. for ( $i = count( $array_bits ) - 1; $i >= 0; $i -- ) {
  42. if ( $i === count( $array_bits ) - 1 ) {
  43. $new_post_data[ $array_bits[ $i ] ] = wp_slash( $post_input_data->value );
  44. } else {
  45. $new_post_data = array(
  46. $array_bits[ $i ] => $new_post_data,
  47. );
  48. }
  49. }
  50. $data = array_replace_recursive( $data, $new_post_data );
  51. }
  52. }
  53. $form_id = wpforms()->form->update( $data['id'], $data );
  54. do_action( 'wpforms_builder_save_form', $form_id, $data );
  55. if ( ! $form_id ) {
  56. wp_send_json_error( esc_html__( 'Something went wrong while saving the form.', 'wpforms-lite' ) );
  57. }
  58. wp_send_json_success(
  59. apply_filters(
  60. 'wpforms_builder_save_form_response_data',
  61. array(
  62. 'form_name' => esc_html( $data['settings']['form_title'] ),
  63. 'form_desc' => $data['settings']['form_desc'],
  64. 'redirect' => admin_url( 'admin.php?page=wpforms-overview' ),
  65. ),
  66. $form_id,
  67. $data
  68. )
  69. );
  70. }
  71. add_action( 'wp_ajax_wpforms_save_form', 'wpforms_save_form' );
  72. /**
  73. * Create a new form.
  74. *
  75. * @since 1.0.0
  76. */
  77. function wpforms_new_form() {
  78. // Run a security check.
  79. check_ajax_referer( 'wpforms-builder', 'nonce' );
  80. // Check for form name.
  81. if ( empty( $_POST['title'] ) ) {
  82. die( esc_html__( 'No form name provided.', 'wpforms-lite' ) );
  83. }
  84. // Create form.
  85. $form_title = sanitize_text_field( wp_unslash( $_POST['title'] ) );
  86. $form_template = empty( $_POST['template'] ) ? 'blank' : sanitize_text_field( wp_unslash( $_POST['template'] ) );
  87. $title_exists = get_page_by_title( $form_title, 'OBJECT', 'wpforms' );
  88. $form_id = wpforms()->form->add(
  89. $form_title,
  90. [],
  91. [
  92. 'template' => $form_template,
  93. ]
  94. );
  95. if ( $title_exists !== null ) {
  96. wp_update_post(
  97. [
  98. 'ID' => $form_id,
  99. 'post_title' => $form_title . ' (ID #' . $form_id . ')',
  100. ]
  101. );
  102. }
  103. if ( ! $form_id ) {
  104. die( esc_html__( 'Error creating form.', 'wpforms-lite' ) );
  105. }
  106. if ( wpforms_current_user_can( 'edit_form_single', $form_id ) ) {
  107. wp_send_json_success(
  108. [
  109. 'id' => $form_id,
  110. 'redirect' => add_query_arg(
  111. [
  112. 'view' => 'fields',
  113. 'form_id' => $form_id,
  114. 'newform' => '1',
  115. ],
  116. admin_url( 'admin.php?page=wpforms-builder' )
  117. ),
  118. ]
  119. );
  120. }
  121. if ( wpforms_current_user_can( 'view_forms' ) ) {
  122. wp_send_json_success( [ 'redirect' => admin_url( 'admin.php?page=wpforms-overview' ) ] );
  123. }
  124. wp_send_json_success( [ 'redirect' => admin_url() ] );
  125. }
  126. add_action( 'wp_ajax_wpforms_new_form', 'wpforms_new_form' );
  127. /**
  128. * Update form template.
  129. *
  130. * @since 1.0.0
  131. */
  132. function wpforms_update_form_template() {
  133. // Run a security check.
  134. check_ajax_referer( 'wpforms-builder', 'nonce' );
  135. // Check for form name.
  136. if ( empty( $_POST['form_id'] ) ) {
  137. wp_send_json_error( esc_html__( 'No form ID provided.', 'wpforms-lite' ) );
  138. }
  139. $form_id = absint( $_POST['form_id'] );
  140. $form_template = empty( $_POST['template'] ) ? 'blank' : sanitize_text_field( wp_unslash( $_POST['template'] ) );
  141. $data = wpforms()->form->get(
  142. $form_id,
  143. [
  144. 'content_only' => true,
  145. ]
  146. );
  147. $updated = (bool) wpforms()->form->update(
  148. $form_id,
  149. $data,
  150. [
  151. 'template' => $form_template,
  152. ]
  153. );
  154. if ( $updated ) {
  155. wp_send_json_success(
  156. [
  157. 'id' => $form_id,
  158. 'redirect' => add_query_arg(
  159. [
  160. 'view' => 'fields',
  161. 'form_id' => $form_id,
  162. ],
  163. admin_url( 'admin.php?page=wpforms-builder' )
  164. ),
  165. ]
  166. );
  167. }
  168. wp_send_json_error( esc_html__( 'Error updating form template.', 'wpforms-lite' ) );
  169. }
  170. add_action( 'wp_ajax_wpforms_update_form_template', 'wpforms_update_form_template' );
  171. /**
  172. * Form Builder update next field ID.
  173. *
  174. * @since 1.2.9
  175. */
  176. function wpforms_builder_increase_next_field_id() {
  177. // Run a security check.
  178. check_ajax_referer( 'wpforms-builder', 'nonce' );
  179. // Check for permissions.
  180. if ( ! wpforms_current_user_can( 'edit_forms' ) ) {
  181. wp_send_json_error();
  182. }
  183. // Check for required items.
  184. if ( empty( $_POST['form_id'] ) ) {
  185. wp_send_json_error();
  186. }
  187. wpforms()->form->next_field_id( absint( $_POST['form_id'] ) );
  188. wp_send_json_success();
  189. }
  190. add_action( 'wp_ajax_wpforms_builder_increase_next_field_id', 'wpforms_builder_increase_next_field_id' );
  191. /**
  192. * Form Builder Dynamic Choices option toggle.
  193. *
  194. * This can be triggered with select/radio/checkbox fields.
  195. *
  196. * @since 1.2.8
  197. */
  198. function wpforms_builder_dynamic_choices() {
  199. // Run a security check.
  200. check_ajax_referer( 'wpforms-builder', 'nonce' );
  201. // Check for permissions.
  202. if ( ! wpforms_current_user_can( 'edit_forms' ) ) {
  203. wp_send_json_error();
  204. }
  205. // Check for valid/required items.
  206. if ( ! isset( $_POST['field_id'] ) || empty( $_POST['type'] ) || ! in_array( $_POST['type'], [ 'post_type', 'taxonomy' ], true ) ) {
  207. wp_send_json_error();
  208. }
  209. $type = sanitize_key( $_POST['type'] );
  210. $id = absint( $_POST['field_id'] );
  211. // Fetch the option row HTML to be returned to the builder.
  212. $field = new WPForms_Field_Select( false );
  213. $field_args = array(
  214. 'id' => $id,
  215. 'dynamic_choices' => $type,
  216. );
  217. $option_row = $field->field_option( 'dynamic_choices_source', $field_args, array(), false );
  218. wp_send_json_success(
  219. array(
  220. 'markup' => $option_row,
  221. )
  222. );
  223. }
  224. add_action( 'wp_ajax_wpforms_builder_dynamic_choices', 'wpforms_builder_dynamic_choices' );
  225. /**
  226. * Form Builder Dynamic Choices Source option toggle.
  227. *
  228. * This can be triggered with select/radio/checkbox fields.
  229. *
  230. * @since 1.2.8
  231. */
  232. function wpforms_builder_dynamic_source() {
  233. // Run a security check.
  234. check_ajax_referer( 'wpforms-builder', 'nonce' );
  235. // Check for permissions.
  236. if ( ! wpforms_current_user_can( 'edit_forms' ) ) {
  237. wp_send_json_error();
  238. }
  239. // Check for required items.
  240. if ( ! isset( $_POST['field_id'] ) || empty( $_POST['form_id'] ) || empty( $_POST['type'] ) || empty( $_POST['source'] ) ) {
  241. wp_send_json_error();
  242. }
  243. $type = sanitize_key( $_POST['type'] );
  244. $source = sanitize_key( $_POST['source'] );
  245. $id = absint( $_POST['field_id'] );
  246. $form_id = absint( $_POST['form_id'] );
  247. $items = [];
  248. $total = 0;
  249. $source_name = '';
  250. $type_name = '';
  251. if ( $type === 'post_type' ) {
  252. $type_name = esc_html__( 'post type', 'wpforms-lite' );
  253. $args = [
  254. 'post_type' => $source,
  255. 'posts_per_page' => 20,
  256. 'orderby' => 'title',
  257. 'order' => 'ASC',
  258. ];
  259. $posts = wpforms_get_hierarchical_object(
  260. apply_filters(
  261. 'wpforms_dynamic_choice_post_type_args',
  262. $args,
  263. [
  264. 'id' => $id,
  265. ],
  266. $form_id
  267. ),
  268. true
  269. );
  270. $total = wp_count_posts( $source );
  271. $total = $total->publish;
  272. $pt = get_post_type_object( $source );
  273. $source_name = '';
  274. if ( $pt !== null ) {
  275. $source_name = $pt->labels->name;
  276. }
  277. foreach ( $posts as $post ) {
  278. $items[] = trim( $post->post_title );
  279. }
  280. } elseif ( $type === 'taxonomy' ) {
  281. $type_name = esc_html__( 'taxonomy', 'wpforms-lite' );
  282. $args = [
  283. 'taxonomy' => $source,
  284. 'hide_empty' => false,
  285. 'number' => 20,
  286. ];
  287. $terms = wpforms_get_hierarchical_object(
  288. apply_filters(
  289. 'wpforms_dynamic_choice_taxonomy_args',
  290. $args,
  291. [
  292. 'id' => $id,
  293. ],
  294. $form_id
  295. ),
  296. true
  297. );
  298. $total = wp_count_terms( $source );
  299. $tax = get_taxonomy( $source );
  300. $source_name = $tax->labels->name;
  301. foreach ( $terms as $term ) {
  302. $items[] = trim( $term->name );
  303. }
  304. }
  305. if ( empty( $items ) ) {
  306. $items = [
  307. esc_html__( '(empty)', 'wpforms-lite' ),
  308. ];
  309. }
  310. wp_send_json_success(
  311. [
  312. 'items' => $items,
  313. 'source' => $source,
  314. 'source_name' => $source_name,
  315. 'total' => $total,
  316. 'type' => $type,
  317. 'type_name' => $type_name,
  318. ]
  319. );
  320. }
  321. add_action( 'wp_ajax_wpforms_builder_dynamic_source', 'wpforms_builder_dynamic_source' );
  322. /**
  323. * Perform test connection to verify that the current web host can successfully
  324. * make outbound SSL connections.
  325. *
  326. * @since 1.4.5
  327. */
  328. function wpforms_verify_ssl() {
  329. // Run a security check.
  330. check_ajax_referer( 'wpforms-admin', 'nonce' );
  331. // Check for permissions.
  332. if ( ! wpforms_current_user_can() ) {
  333. wp_send_json_error(
  334. array(
  335. 'msg' => esc_html__( 'You do not have permission to perform this operation.', 'wpforms-lite' ),
  336. )
  337. );
  338. }
  339. $response = wp_remote_post( 'https://wpforms.com/connection-test.php' );
  340. if ( 200 === wp_remote_retrieve_response_code( $response ) ) {
  341. wp_send_json_success(
  342. array(
  343. 'msg' => esc_html__( 'Success! Your server can make SSL connections.', 'wpforms-lite' ),
  344. )
  345. );
  346. }
  347. wp_send_json_error(
  348. array(
  349. 'msg' => esc_html__( 'There was an error and the connection failed. Please contact your web host with the technical details below.', 'wpforms-lite' ),
  350. 'debug' => '<pre>' . print_r( map_deep( $response, 'wp_strip_all_tags' ), true ) . '</pre>',
  351. )
  352. );
  353. }
  354. add_action( 'wp_ajax_wpforms_verify_ssl', 'wpforms_verify_ssl' );
  355. /**
  356. * Deactivate addon.
  357. *
  358. * @since 1.0.0
  359. * @since 1.6.2.3 Updated the permissions checking.
  360. */
  361. function wpforms_deactivate_addon() {
  362. // Run a security check.
  363. check_ajax_referer( 'wpforms-admin', 'nonce' );
  364. // Check for permissions.
  365. if ( ! current_user_can( 'deactivate_plugins' ) ) {
  366. wp_send_json_error( esc_html__( 'Plugin deactivation is disabled for you on this site.', 'wpforms-lite' ) );
  367. }
  368. $type = empty( $_POST['type'] ) ? 'addon' : sanitize_key( $_POST['type'] );
  369. if ( isset( $_POST['plugin'] ) ) {
  370. $plugin = sanitize_text_field( wp_unslash( $_POST['plugin'] ) );
  371. deactivate_plugins( $plugin );
  372. do_action( 'wpforms_plugin_deactivated', $plugin );
  373. if ( $type === 'plugin' ) {
  374. wp_send_json_success( esc_html__( 'Plugin deactivated.', 'wpforms-lite' ) );
  375. } else {
  376. wp_send_json_success( esc_html__( 'Addon deactivated.', 'wpforms-lite' ) );
  377. }
  378. }
  379. wp_send_json_error( esc_html__( 'Could not deactivate the addon. Please deactivate from the Plugins page.', 'wpforms-lite' ) );
  380. }
  381. add_action( 'wp_ajax_wpforms_deactivate_addon', 'wpforms_deactivate_addon' );
  382. /**
  383. * Activate addon.
  384. *
  385. * @since 1.0.0
  386. * @since 1.6.2.3 Updated the permissions checking.
  387. */
  388. function wpforms_activate_addon() {
  389. // Run a security check.
  390. check_ajax_referer( 'wpforms-admin', 'nonce' );
  391. // Check for permissions.
  392. if ( ! current_user_can( 'activate_plugins' ) ) {
  393. wp_send_json_error( esc_html__( 'Plugin activation is disabled for you on this site.', 'wpforms-lite' ) );
  394. }
  395. $type = 'addon';
  396. if ( isset( $_POST['plugin'] ) ) {
  397. if ( ! empty( $_POST['type'] ) ) {
  398. $type = sanitize_key( $_POST['type'] );
  399. }
  400. $plugin = sanitize_text_field( wp_unslash( $_POST['plugin'] ) );
  401. $activate = activate_plugins( $plugin );
  402. /**
  403. * Fire after plugin activating via the WPForms installer.
  404. *
  405. * @since 1.6.3.1
  406. *
  407. * @param string $plugin Path to the plugin file relative to the plugins directory.
  408. */
  409. do_action( 'wpforms_plugin_activated', $plugin );
  410. if ( ! is_wp_error( $activate ) ) {
  411. if ( $type === 'plugin' ) {
  412. wp_send_json_success( esc_html__( 'Plugin activated.', 'wpforms-lite' ) );
  413. } else {
  414. wp_send_json_success( esc_html__( 'Addon activated.', 'wpforms-lite' ) );
  415. }
  416. }
  417. }
  418. if ( $type === 'plugin' ) {
  419. wp_send_json_error( esc_html__( 'Could not activate the plugin. Please activate it on the Plugins page.', 'wpforms-lite' ) );
  420. }
  421. wp_send_json_error( esc_html__( 'Could not activate the addon. Please activate it on the Plugins page.', 'wpforms-lite' ) );
  422. }
  423. add_action( 'wp_ajax_wpforms_activate_addon', 'wpforms_activate_addon' );
  424. /**
  425. * Install addon.
  426. *
  427. * @since 1.0.0
  428. * @since 1.6.2.3 Updated the permissions checking.
  429. */
  430. function wpforms_install_addon() {
  431. // Run a security check.
  432. check_ajax_referer( 'wpforms-admin', 'nonce' );
  433. $generic_error = esc_html__( 'There was an error while performing your request.', 'wpforms-lite' );
  434. $type = ! empty( $_POST['type'] ) ? sanitize_key( $_POST['type'] ) : 'addon';
  435. // Check if new installations are allowed.
  436. if ( ! wpforms_can_install( $type ) ) {
  437. wp_send_json_error( $generic_error );
  438. }
  439. $error = $type === 'plugin'
  440. ? esc_html__( 'Could not install the plugin. Please download and install it manually.', 'wpforms-lite' )
  441. : esc_html__( 'Could not install the addon. Please download it from wpforms.com and install it manually.', 'wpforms-lite' );
  442. $plugin_url = ! empty( $_POST['plugin'] ) ? esc_url_raw( wp_unslash( $_POST['plugin'] ) ) : '';
  443. if ( empty( $plugin_url ) ) {
  444. wp_send_json_error( $error );
  445. }
  446. // Set the current screen to avoid undefined notices.
  447. set_current_screen( 'wpforms_page_wpforms-settings' );
  448. // Prepare variables.
  449. $url = esc_url_raw(
  450. add_query_arg(
  451. [
  452. 'page' => 'wpforms-addons',
  453. ],
  454. admin_url( 'admin.php' )
  455. )
  456. );
  457. ob_start();
  458. $creds = request_filesystem_credentials( $url, '', false, false, null );
  459. // Hide the filesystem credentials form.
  460. ob_end_clean();
  461. // Check for file system permissions.
  462. if ( $creds === false ) {
  463. wp_send_json_error( $error );
  464. }
  465. if ( ! WP_Filesystem( $creds ) ) {
  466. wp_send_json_error( $error );
  467. }
  468. /*
  469. * We do not need any extra credentials if we have gotten this far, so let's install the plugin.
  470. */
  471. require_once WPFORMS_PLUGIN_DIR . 'includes/admin/class-install-skin.php';
  472. // Do not allow WordPress to search/download translations, as this will break JS output.
  473. remove_action( 'upgrader_process_complete', [ 'Language_Pack_Upgrader', 'async_upgrade' ], 20 );
  474. // Create the plugin upgrader with our custom skin.
  475. $installer = new WPForms\Helpers\PluginSilentUpgrader( new WPForms_Install_Skin() );
  476. // Error check.
  477. if ( ! method_exists( $installer, 'install' ) ) {
  478. wp_send_json_error( $error );
  479. }
  480. $installer->install( $plugin_url );
  481. // Flush the cache and return the newly installed plugin basename.
  482. wp_cache_flush();
  483. $plugin_basename = $installer->plugin_info();
  484. if ( empty( $plugin_basename ) ) {
  485. wp_send_json_error( $error );
  486. }
  487. $result = [
  488. 'msg' => $generic_error,
  489. 'is_activated' => false,
  490. 'basename' => $plugin_basename,
  491. ];
  492. // Check for permissions.
  493. if ( ! current_user_can( 'activate_plugins' ) ) {
  494. $result['msg'] = $type === 'plugin' ? esc_html__( 'Plugin installed.', 'wpforms-lite' ) : esc_html__( 'Addon installed.', 'wpforms-lite' );
  495. wp_send_json_success( $result );
  496. }
  497. // Activate the plugin silently.
  498. $activated = activate_plugin( $plugin_basename );
  499. if ( ! is_wp_error( $activated ) ) {
  500. /**
  501. * Fire after plugin activating via the WPForms installer.
  502. *
  503. * @since 1.7.0
  504. *
  505. * @param string $plugin_basename Path to the plugin file relative to the plugins directory.
  506. */
  507. do_action( 'wpforms_plugin_activated', $plugin_basename );
  508. $result['is_activated'] = true;
  509. $result['msg'] = $type === 'plugin' ? esc_html__( 'Plugin installed & activated.', 'wpforms-lite' ) : esc_html__( 'Addon installed & activated.', 'wpforms-lite' );
  510. wp_send_json_success( $result );
  511. }
  512. // Fallback error just in case.
  513. wp_send_json_error( $result );
  514. }
  515. add_action( 'wp_ajax_wpforms_install_addon', 'wpforms_install_addon' );