Нет описания

class-form.php 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802
  1. <?php
  2. /**
  3. * All the form goodness and basics.
  4. *
  5. * Contains a bunch of helper methods as well.
  6. *
  7. * @since 1.0.0
  8. */
  9. class WPForms_Form_Handler {
  10. /**
  11. * Primary class constructor.
  12. *
  13. * @since 1.0.0
  14. */
  15. public function __construct() {
  16. // Register wpforms custom post type.
  17. $this->register_cpt();
  18. // Add wpforms to new-content admin bar menu.
  19. add_action( 'admin_bar_menu', [ $this, 'admin_bar' ], 99 );
  20. add_action( 'wpforms_create_form', [ $this, 'track_first_form' ], 10, 3 );
  21. }
  22. /**
  23. * Register the custom post type to be used for forms.
  24. *
  25. * @since 1.0.0
  26. */
  27. public function register_cpt() {
  28. // Custom post type arguments, which can be filtered if needed.
  29. $args = apply_filters(
  30. 'wpforms_post_type_args',
  31. [
  32. 'label' => 'WPForms',
  33. 'public' => false,
  34. 'exclude_from_search' => true,
  35. 'show_ui' => false,
  36. 'show_in_admin_bar' => false,
  37. 'rewrite' => false,
  38. 'query_var' => false,
  39. 'can_export' => false,
  40. 'supports' => [ 'title' ],
  41. 'capability_type' => 'wpforms_form', // Not using 'capability_type' anywhere. It just has to be custom for security reasons.
  42. 'map_meta_cap' => false, // Don't let WP to map meta caps to have a granular control over this process via 'map_meta_cap' filter.
  43. ]
  44. );
  45. // Register the post type.
  46. register_post_type( 'wpforms', $args );
  47. }
  48. /**
  49. * Add "WPForms" item to new-content admin bar menu item.
  50. *
  51. * @since 1.1.7.2
  52. *
  53. * @param WP_Admin_Bar $wp_admin_bar WP_Admin_Bar instance, passed by reference.
  54. */
  55. public function admin_bar( $wp_admin_bar ) {
  56. if ( ! is_admin_bar_showing() || ! wpforms_current_user_can( 'create_forms' ) ) {
  57. return;
  58. }
  59. $args = [
  60. 'id' => 'wpforms',
  61. 'title' => esc_html__( 'WPForms', 'wpforms-lite' ),
  62. 'href' => admin_url( 'admin.php?page=wpforms-builder' ),
  63. 'parent' => 'new-content',
  64. ];
  65. $wp_admin_bar->add_node( $args );
  66. }
  67. /**
  68. * Preserve the timestamp when the very first form has been created.
  69. *
  70. * @since 1.6.7.1
  71. *
  72. * @param int $form_id Newly created form ID.
  73. * @param array $form Array past to create a new form in wp_posts table.
  74. * @param array $data Additional form data.
  75. */
  76. public function track_first_form( $form_id, $form, $data ) {
  77. // Do we have the value already?
  78. $time = get_option( 'wpforms_forms_first_created' );
  79. // Check whether we have already saved this option - skip.
  80. if ( ! empty( $time ) ) {
  81. return;
  82. }
  83. // Check whether we have any forms other than the currently created one.
  84. $other_form = wpforms()->form->get(
  85. '',
  86. [
  87. 'order' => 'id',
  88. 'orderby' => 'desc',
  89. 'posts_per_page' => 1,
  90. 'nopaging' => false,
  91. 'fields' => 'ids',
  92. 'post__not_in' => [ $form_id ],
  93. ]
  94. );
  95. // As we have other forms - we are not certain about the situation, skip.
  96. if ( ! empty( $other_form ) ) {
  97. return;
  98. }
  99. add_option( 'wpforms_forms_first_created', time(), '', 'no' );
  100. }
  101. /**
  102. * Fetch forms.
  103. *
  104. * @since 1.0.0
  105. *
  106. * @param mixed $id Form ID.
  107. * @param array $args Additional arguments array.
  108. *
  109. * @return array|bool|null|WP_Post
  110. */
  111. public function get( $id = '', $args = [] ) {
  112. $args = apply_filters( 'wpforms_get_form_args', $args, $id );
  113. if ( $id === false ) {
  114. return false;
  115. }
  116. $forms = empty( $id ) ? $this->get_multiple( $args ) : $this->get_single( $id, $args );
  117. if ( empty( $forms ) ) {
  118. return false;
  119. }
  120. return $forms;
  121. }
  122. /**
  123. * Fetch a single form.
  124. *
  125. * @since 1.5.8
  126. *
  127. * @param string|int $id Form ID.
  128. * @param array $args Additional arguments array.
  129. *
  130. * @return array|bool|null|WP_Post
  131. */
  132. protected function get_single( $id = '', $args = [] ) {
  133. $args = apply_filters( 'wpforms_get_single_form_args', $args, $id );
  134. if ( ! isset( $args['cap'] ) && wpforms()->get( 'access' )->init_allowed() ) {
  135. $args['cap'] = 'view_form_single';
  136. }
  137. if ( ! empty( $args['cap'] ) && ! wpforms_current_user_can( $args['cap'], $id ) ) {
  138. return false;
  139. }
  140. // @todo add $id array support
  141. // If ID is provided, we get a single form
  142. $form = get_post( absint( $id ) );
  143. if ( ! empty( $args['content_only'] ) ) {
  144. $form = ! empty( $form ) && $form->post_type === 'wpforms' ? wpforms_decode( $form->post_content ) : false;
  145. }
  146. return $form;
  147. }
  148. /**
  149. * Fetch multiple forms.
  150. *
  151. * @since 1.5.8
  152. *
  153. * @param array $args Additional arguments array.
  154. *
  155. * @return array
  156. */
  157. protected function get_multiple( $args = [] ) {
  158. $args = apply_filters( 'wpforms_get_multiple_forms_args', $args );
  159. // No ID provided, get multiple forms.
  160. $defaults = [
  161. 'orderby' => 'id',
  162. 'order' => 'ASC',
  163. 'no_found_rows' => true,
  164. 'nopaging' => true,
  165. ];
  166. $args = wp_parse_args( $args, $defaults );
  167. $args['post_type'] = 'wpforms';
  168. return get_posts( $args );
  169. }
  170. /**
  171. * Delete forms.
  172. *
  173. * @since 1.0.0
  174. *
  175. * @param array $ids Form IDs.
  176. *
  177. * @return bool
  178. */
  179. public function delete( $ids = [] ) {
  180. if ( ! is_array( $ids ) ) {
  181. $ids = [ $ids ];
  182. }
  183. $ids = array_map( 'absint', $ids );
  184. foreach ( $ids as $id ) {
  185. // Check for permissions.
  186. if ( ! wpforms_current_user_can( 'delete_form_single', $id ) ) {
  187. return false;
  188. }
  189. if ( class_exists( 'WPForms_Entry_Handler', false ) ) {
  190. wpforms()->entry->delete_by( 'form_id', $id );
  191. wpforms()->entry_meta->delete_by( 'form_id', $id );
  192. wpforms()->entry_fields->delete_by( 'form_id', $id );
  193. }
  194. $form = wp_delete_post( $id, true );
  195. if ( ! $form ) {
  196. return false;
  197. }
  198. }
  199. do_action( 'wpforms_delete_form', $ids );
  200. return true;
  201. }
  202. /**
  203. * Add new form.
  204. *
  205. * @since 1.0.0
  206. *
  207. * @param string $title Form title.
  208. * @param array $args Additional arguments.
  209. * @param array $data Form data.
  210. *
  211. * @return mixed
  212. */
  213. public function add( $title = '', $args = [], $data = [] ) {
  214. // Must have a title.
  215. if ( empty( $title ) ) {
  216. return false;
  217. }
  218. // Check for permissions.
  219. if ( ! wpforms_current_user_can( 'create_forms' ) ) {
  220. return false;
  221. }
  222. // This filter breaks forms if they contain HTML.
  223. remove_filter( 'content_save_pre', 'balanceTags', 50 );
  224. // Add filter of the link rel attr to avoid JSON damage.
  225. add_filter( 'wp_targeted_link_rel', '__return_empty_string', 50, 1 );
  226. $args = apply_filters( 'wpforms_create_form_args', $args, $data );
  227. $form_content = [
  228. 'field_id' => '0',
  229. 'settings' => [
  230. 'form_title' => sanitize_text_field( $title ),
  231. 'form_desc' => '',
  232. ],
  233. ];
  234. // Prevent $args['post_content'] from overwriting predefined $form_content.
  235. // Typically it happens if the form was created with a form template and a user was not redirected to a form editing screen afterwards.
  236. // This is only possible if a user has 'wpforms_create_forms' and no 'wpforms_edit_own_forms' capability.
  237. if ( isset( $args['post_content'] ) && is_array( json_decode( wp_unslash( $args['post_content'] ), true ) ) ) {
  238. $args['post_content'] = wpforms_encode( array_replace_recursive( $form_content, json_decode( wp_unslash( $args['post_content'] ), true ) ) );
  239. }
  240. // Merge args and create the form.
  241. $form = wp_parse_args(
  242. $args,
  243. [
  244. 'post_title' => esc_html( $title ),
  245. 'post_status' => 'publish',
  246. 'post_type' => 'wpforms',
  247. 'post_content' => wpforms_encode( $form_content ),
  248. ]
  249. );
  250. $form_id = wp_insert_post( $form );
  251. // If user has no editing permissions the form considered to be created out of the WPForms form builder's context.
  252. if ( ! wpforms_current_user_can( 'edit_form_single', $form_id ) ) {
  253. $data['builder'] = false;
  254. }
  255. // If the form is created outside the context of the WPForms form
  256. // builder, then we define some additional default values.
  257. if ( ! empty( $form_id ) && isset( $data['builder'] ) && $data['builder'] === false ) {
  258. $form_data = json_decode( wp_unslash( $form['post_content'] ), true );
  259. $form_data['id'] = $form_id;
  260. $form_data['settings']['submit_text'] = esc_html__( 'Submit', 'wpforms-lite' );
  261. $form_data['settings']['submit_text_processing'] = esc_html__( 'Sending...', 'wpforms-lite' );
  262. $form_data['settings']['notification_enable'] = '1';
  263. $form_data['settings']['notifications'] = [
  264. '1' => [
  265. 'email' => '{admin_email}',
  266. 'subject' => sprintf( esc_html__( 'New Entry: %s', 'wpforms-lite' ), esc_html( $title ) ),
  267. 'sender_name' => get_bloginfo( 'name' ),
  268. 'sender_address' => '{admin_email}',
  269. 'replyto' => '{field_id="1"}',
  270. 'message' => '{all_fields}',
  271. ],
  272. ];
  273. $form_data['settings']['confirmations'] = [
  274. '1' => [
  275. 'type' => 'message',
  276. 'message' => esc_html__( 'Thanks for contacting us! We will be in touch with you shortly.', 'wpforms-lite' ),
  277. 'message_scroll' => '1',
  278. ],
  279. ];
  280. $this->update( $form_id, $form_data, [ 'cap' => 'create_forms' ] );
  281. }
  282. do_action( 'wpforms_create_form', $form_id, $form, $data );
  283. return $form_id;
  284. }
  285. /**
  286. * Update form.
  287. *
  288. * @since 1.0.0
  289. *
  290. * @param string|int $form_id Form ID.
  291. * @param array $data Data retrieved from $_POST and processed.
  292. * @param array $args Empty by default, may have custom data not intended to be saved.
  293. *
  294. * @return mixed
  295. * @internal param string $title
  296. */
  297. public function update( $form_id = '', $data = [], $args = [] ) {
  298. if ( empty( $data ) ) {
  299. return false;
  300. }
  301. if ( empty( $form_id ) && isset( $data['id'] ) ) {
  302. $form_id = $data['id'];
  303. }
  304. if ( ! isset( $args['cap'] ) ) {
  305. $args['cap'] = 'edit_form_single';
  306. }
  307. if ( ! empty( $args['cap'] ) && ! wpforms_current_user_can( $args['cap'], $form_id ) ) {
  308. return false;
  309. }
  310. // This filter breaks forms if they contain HTML.
  311. remove_filter( 'content_save_pre', 'balanceTags', 50 );
  312. // Add filter of the link rel attr to avoid JSON damage.
  313. add_filter( 'wp_targeted_link_rel', '__return_empty_string', 50, 1 );
  314. $data = wp_unslash( $data );
  315. $title = empty( $data['settings']['form_title'] ) ? get_the_title( $form_id ) : $data['settings']['form_title'];
  316. $desc = empty( $data['settings']['form_desc'] ) ? '' : $data['settings']['form_desc'];
  317. $data['field_id'] = ! empty( $data['field_id'] ) ? absint( $data['field_id'] ) : '0';
  318. // Preserve form meta.
  319. $meta = $this->get_meta( $form_id );
  320. if ( $meta ) {
  321. $data['meta'] = $meta;
  322. }
  323. // Preserve fields meta.
  324. if ( isset( $data['fields'] ) ) {
  325. $data['fields'] = $this->update__preserve_fields_meta( $data['fields'], $form_id );
  326. }
  327. // Sanitize - don't allow tags for users who do not have appropriate cap.
  328. // If we don't do this, forms for these users can get corrupt due to
  329. // conflicts with wp_kses().
  330. if ( ! current_user_can( 'unfiltered_html' ) ) {
  331. $data = map_deep( $data, 'wp_strip_all_tags' );
  332. }
  333. // Sanitize notifications names.
  334. if ( isset( $data['settings']['notifications'] ) ) {
  335. $data['settings']['notifications'] = $this->update__sanitize_notifications_names( $data['settings']['notifications'] );
  336. }
  337. unset( $notification );
  338. $form = apply_filters(
  339. 'wpforms_save_form_args',
  340. [
  341. 'ID' => $form_id,
  342. 'post_title' => esc_html( $title ),
  343. 'post_excerpt' => $desc,
  344. 'post_content' => wpforms_encode( $data ),
  345. ],
  346. $data,
  347. $args
  348. );
  349. $_form_id = wp_update_post( $form );
  350. do_action( 'wpforms_save_form', $_form_id, $form );
  351. return $_form_id;
  352. }
  353. /**
  354. * Preserve fields meta in 'update' method.
  355. *
  356. * @since 1.5.8
  357. *
  358. * @param array $fields Form fields.
  359. * @param string|int $form_id Form ID.
  360. *
  361. * @return array
  362. */
  363. protected function update__preserve_fields_meta( $fields, $form_id ) {
  364. foreach ( $fields as $i => $field_data ) {
  365. if ( isset( $field_data['id'] ) ) {
  366. $field_meta = $this->get_field_meta( $form_id, $field_data['id'] );
  367. if ( $field_meta ) {
  368. $fields[ $i ]['meta'] = $field_meta;
  369. }
  370. }
  371. }
  372. return $fields;
  373. }
  374. /**
  375. * Sanitize notifications names meta in 'update' method.
  376. *
  377. * @since 1.5.8
  378. *
  379. * @param array $notifications Form notifications.
  380. *
  381. * @return array
  382. */
  383. protected function update__sanitize_notifications_names( $notifications ) {
  384. foreach ( $notifications as $id => &$notification ) {
  385. if ( ! empty( $notification['notification_name'] ) ) {
  386. $notification['notification_name'] = sanitize_text_field( $notification['notification_name'] );
  387. }
  388. }
  389. return $notifications;
  390. }
  391. /**
  392. * Duplicate forms.
  393. *
  394. * @since 1.1.4
  395. *
  396. * @param array $ids Form IDs to duplicate.
  397. *
  398. * @return bool
  399. */
  400. public function duplicate( $ids = [] ) {
  401. // Check for permissions.
  402. if ( ! wpforms_current_user_can( 'create_forms' ) ) {
  403. return false;
  404. }
  405. // Add filter of the link rel attr to avoid JSON damage.
  406. add_filter( 'wp_targeted_link_rel', '__return_empty_string', 50, 1 );
  407. // This filter breaks forms if they contain HTML.
  408. remove_filter( 'content_save_pre', 'balanceTags', 50 );
  409. if ( ! is_array( $ids ) ) {
  410. $ids = [ $ids ];
  411. }
  412. $ids = array_map( 'absint', $ids );
  413. foreach ( $ids as $id ) {
  414. // Get original entry.
  415. $form = get_post( $id );
  416. if ( ! wpforms_current_user_can( 'view_form_single', $id ) ) {
  417. return false;
  418. }
  419. // Confirm form exists.
  420. if ( ! $form || empty( $form ) ) {
  421. return false;
  422. }
  423. // Get the form data.
  424. $new_form_data = wpforms_decode( $form->post_content );
  425. // Remove form ID from title if present.
  426. $new_form_data['settings']['form_title'] = str_replace( '(ID #' . absint( $id ) . ')', '', $new_form_data['settings']['form_title'] );
  427. // Create the duplicate form.
  428. $new_form = [
  429. 'post_content' => wpforms_encode( $new_form_data ),
  430. 'post_excerpt' => $form->post_excerpt,
  431. 'post_status' => $form->post_status,
  432. 'post_title' => $new_form_data['settings']['form_title'],
  433. 'post_type' => $form->post_type,
  434. ];
  435. $new_form_id = wp_insert_post( $new_form );
  436. if ( ! $new_form_id || is_wp_error( $new_form_id ) ) {
  437. return false;
  438. }
  439. // Set new form name.
  440. $new_form_data['settings']['form_title'] .= ' (ID #' . absint( $new_form_id ) . ')';
  441. // Set new form ID.
  442. $new_form_data['id'] = absint( $new_form_id );
  443. // Update new duplicate form.
  444. $new_form_id = $this->update( $new_form_id, $new_form_data, [ 'cap' => 'create_forms' ] );
  445. if ( ! $new_form_id || is_wp_error( $new_form_id ) ) {
  446. return false;
  447. }
  448. }
  449. return true;
  450. }
  451. /**
  452. * Get the next available field ID and increment by one.
  453. *
  454. * @since 1.0.0
  455. *
  456. * @param string|int $form_id Form ID.
  457. * @param array $args Additional arguments.
  458. *
  459. * @return mixed int or false
  460. */
  461. public function next_field_id( $form_id, $args = [] ) {
  462. if ( empty( $form_id ) ) {
  463. return false;
  464. }
  465. $defaults = [
  466. 'content_only' => true,
  467. ];
  468. if ( isset( $args['cap'] ) ) {
  469. $defaults['cap'] = $args['cap'];
  470. }
  471. $form = $this->get( $form_id, $defaults );
  472. if ( empty( $form ) ) {
  473. return false;
  474. }
  475. if ( ! empty( $form['field_id'] ) ) {
  476. $field_id = absint( $form['field_id'] );
  477. if ( ! empty( $form['fields'] ) && max( array_keys( $form['fields'] ) ) > $field_id ) {
  478. $field_id = max( array_keys( $form['fields'] ) ) + 1;
  479. }
  480. $form['field_id'] = $field_id + 1;
  481. } else {
  482. $field_id = '0';
  483. $form['field_id'] = '1';
  484. }
  485. $this->update( $form_id, $form );
  486. return $field_id;
  487. }
  488. /**
  489. * Get private meta information for a form.
  490. *
  491. * @since 1.0.0
  492. *
  493. * @param string|int $form_id Form ID.
  494. * @param string $field Field.
  495. * @param array $args Additional arguments.
  496. *
  497. * @return false|array
  498. */
  499. public function get_meta( $form_id, $field = '', $args = [] ) {
  500. if ( empty( $form_id ) ) {
  501. return false;
  502. }
  503. $defaults = [
  504. 'content_only' => true,
  505. ];
  506. if ( isset( $args['cap'] ) ) {
  507. $defaults['cap'] = $args['cap'];
  508. }
  509. $data = $this->get( $form_id, $defaults );
  510. if ( ! isset( $data['meta'] ) ) {
  511. return false;
  512. }
  513. if ( empty( $field ) ) {
  514. return $data['meta'];
  515. }
  516. if ( isset( $data['meta'][ $field ] ) ) {
  517. return $data['meta'][ $field ];
  518. }
  519. return false;
  520. }
  521. /**
  522. * Update or add form meta information to a form.
  523. *
  524. * @since 1.4.0
  525. *
  526. * @param string|int $form_id Form ID.
  527. * @param string $meta_key Meta key.
  528. * @param mixed $meta_value Meta value.
  529. * @param array $args Additional arguments.
  530. *
  531. * @return false|int|WP_Error
  532. */
  533. public function update_meta( $form_id, $meta_key, $meta_value, $args = [] ) {
  534. if ( empty( $form_id ) || empty( $meta_key ) ) {
  535. return false;
  536. }
  537. // Add filter of the link rel attr to avoid JSON damage.
  538. add_filter( 'wp_targeted_link_rel', '__return_empty_string', 50, 1 );
  539. // This filter breaks forms if they contain HTML.
  540. remove_filter( 'content_save_pre', 'balanceTags', 50 );
  541. if ( ! isset( $args['cap'] ) ) {
  542. $args['cap'] = 'edit_form_single';
  543. }
  544. $form = $this->get_single( absint( $form_id ), $args );
  545. if ( empty( $form ) ) {
  546. return false;
  547. }
  548. $data = wpforms_decode( $form->post_content );
  549. $meta_key = wpforms_sanitize_key( $meta_key );
  550. $data['meta'][ $meta_key ] = $meta_value;
  551. $form = [
  552. 'ID' => $form_id,
  553. 'post_content' => wpforms_encode( $data ),
  554. ];
  555. $form = apply_filters( 'wpforms_update_form_meta_args', $form, $data );
  556. $form_id = wp_update_post( $form );
  557. do_action( 'wpforms_update_form_meta', $form_id, $form, $meta_key, $meta_value );
  558. return $form_id;
  559. }
  560. /**
  561. * Delete form meta information from a form.
  562. *
  563. * @since 1.4.0
  564. *
  565. * @param string|int $form_id Form ID.
  566. * @param string $meta_key Meta key.
  567. * @param array $args Additional arguments.
  568. *
  569. * @return false|int|WP_Error
  570. */
  571. public function delete_meta( $form_id, $meta_key, $args = [] ) {
  572. if ( empty( $form_id ) || empty( $meta_key ) ) {
  573. return false;
  574. }
  575. // Add filter of the link rel attr to avoid JSON damage.
  576. add_filter( 'wp_targeted_link_rel', '__return_empty_string', 50, 1 );
  577. // This filter breaks forms if they contain HTML.
  578. remove_filter( 'content_save_pre', 'balanceTags', 50 );
  579. if ( ! isset( $args['cap'] ) ) {
  580. $args['cap'] = 'edit_form_single';
  581. }
  582. $form = $this->get_single( absint( $form_id ), $args );
  583. if ( empty( $form ) ) {
  584. return false;
  585. }
  586. $data = wpforms_decode( $form->post_content );
  587. $meta_key = wpforms_sanitize_key( $meta_key );
  588. unset( $data['meta'][ $meta_key ] );
  589. $form = [
  590. 'ID' => $form_id,
  591. 'post_content' => wpforms_encode( $data ),
  592. ];
  593. $form = apply_filters( 'wpforms_delete_form_meta_args', $form, $data );
  594. $form_id = wp_update_post( $form );
  595. do_action( 'wpforms_delete_form_meta', $form_id, $form, $meta_key );
  596. return $form_id;
  597. }
  598. /**
  599. * Get private meta information for a form field.
  600. *
  601. * @since 1.0.0
  602. *
  603. * @param string|int $form_id Form ID.
  604. * @param string $field_id Field ID.
  605. * @param array $args Additional arguments.
  606. *
  607. * @return array|false
  608. */
  609. public function get_field( $form_id, $field_id = '', $args = [] ) {
  610. if ( empty( $form_id ) ) {
  611. return false;
  612. }
  613. $defaults = [
  614. 'content_only' => true,
  615. ];
  616. if ( isset( $args['cap'] ) ) {
  617. $defaults['cap'] = $args['cap'];
  618. }
  619. $data = $this->get( $form_id, $defaults );
  620. return isset( $data['fields'][ $field_id ] ) ? $data['fields'][ $field_id ] : false;
  621. }
  622. /**
  623. * Get private meta information for a form field.
  624. *
  625. * @since 1.0.0
  626. *
  627. * @param string|int $form_id Form ID.
  628. * @param string $field_id Field ID.
  629. * @param array $args Additional arguments.
  630. *
  631. * @return array|false
  632. */
  633. public function get_field_meta( $form_id, $field_id = '', $args = [] ) {
  634. $field = $this->get_field( $form_id, $field_id, $args );
  635. if ( ! $field ) {
  636. return false;
  637. }
  638. return isset( $field['meta'] ) ? $field['meta'] : false;
  639. }
  640. }