Нет описания

form-widget.php 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. <?php
  2. /*
  3. * ACF Widget Form Class
  4. *
  5. * All the logic for adding fields to widgets
  6. *
  7. * @class acf_form_widget
  8. * @package ACF
  9. * @subpackage Forms
  10. */
  11. if ( ! class_exists( 'acf_form_widget' ) ) :
  12. class acf_form_widget {
  13. /*
  14. * __construct
  15. *
  16. * This function will setup the class functionality
  17. *
  18. * @type function
  19. * @date 5/03/2014
  20. * @since 5.0.0
  21. *
  22. * @param n/a
  23. * @return n/a
  24. */
  25. function __construct() {
  26. // vars
  27. $this->preview_values = array();
  28. $this->preview_reference = array();
  29. $this->preview_errors = array();
  30. // actions
  31. add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
  32. add_action( 'in_widget_form', array( $this, 'edit_widget' ), 10, 3 );
  33. add_action( 'acf/validate_save_post', array( $this, 'acf_validate_save_post' ), 5 );
  34. // filters
  35. add_filter( 'widget_update_callback', array( $this, 'save_widget' ), 10, 4 );
  36. }
  37. /*
  38. * admin_enqueue_scripts
  39. *
  40. * This action is run after post query but before any admin script / head actions.
  41. * It is a good place to register all actions.
  42. *
  43. * @type action (admin_enqueue_scripts)
  44. * @date 26/01/13
  45. * @since 3.6.0
  46. *
  47. * @param N/A
  48. * @return N/A
  49. */
  50. function admin_enqueue_scripts() {
  51. // validate screen
  52. if ( acf_is_screen( 'widgets' ) || acf_is_screen( 'customize' ) ) {
  53. // valid
  54. } else {
  55. return;
  56. }
  57. // load acf scripts
  58. acf_enqueue_scripts();
  59. // actions
  60. add_action( 'acf/input/admin_footer', array( $this, 'admin_footer' ), 1 );
  61. }
  62. /*
  63. * acf_validate_save_post
  64. *
  65. * This function will loop over $_POST data and validate
  66. *
  67. * @type action 'acf/validate_save_post' 5
  68. * @date 7/09/2016
  69. * @since 5.4.0
  70. *
  71. * @param n/a
  72. * @return n/a
  73. */
  74. function acf_validate_save_post() {
  75. // bail ealry if not widget
  76. if ( ! isset( $_POST['_acf_widget_id'] ) ) {
  77. return;
  78. }
  79. // vars
  80. $id = $_POST['_acf_widget_id'];
  81. $number = $_POST['_acf_widget_number'];
  82. $prefix = $_POST['_acf_widget_prefix'];
  83. // validate
  84. acf_validate_values( $_POST[ $id ][ $number ]['acf'], $prefix );
  85. }
  86. /*
  87. * edit_widget
  88. *
  89. * This function will render the fields for a widget form
  90. *
  91. * @type function
  92. * @date 11/06/2014
  93. * @since 5.0.0
  94. *
  95. * @param $widget (object)
  96. * @param $return (null)
  97. * @param $instance (object)
  98. * @return $post_id (int)
  99. */
  100. function edit_widget( $widget, $return, $instance ) {
  101. // vars
  102. $post_id = 0;
  103. $prefix = 'widget-' . $widget->id_base . '[' . $widget->number . '][acf]';
  104. // get id
  105. if ( $widget->number !== '__i__' ) {
  106. $post_id = "widget_{$widget->id}";
  107. }
  108. // get field groups
  109. $field_groups = acf_get_field_groups(
  110. array(
  111. 'widget' => $widget->id_base,
  112. )
  113. );
  114. // render
  115. if ( ! empty( $field_groups ) ) {
  116. // render post data
  117. acf_form_data(
  118. array(
  119. 'screen' => 'widget',
  120. 'post_id' => $post_id,
  121. 'widget_id' => 'widget-' . $widget->id_base,
  122. 'widget_number' => $widget->number,
  123. 'widget_prefix' => $prefix,
  124. )
  125. );
  126. // wrap
  127. echo '<div class="acf-widget-fields acf-fields -clear">';
  128. // loop
  129. foreach ( $field_groups as $field_group ) {
  130. // load fields
  131. $fields = acf_get_fields( $field_group );
  132. // bail if not fields
  133. if ( empty( $fields ) ) {
  134. continue;
  135. }
  136. // change prefix
  137. acf_prefix_fields( $fields, $prefix );
  138. // render
  139. acf_render_fields( $fields, $post_id, 'div', $field_group['instruction_placement'] );
  140. }
  141. // wrap
  142. echo '</div>';
  143. // jQuery selector looks odd, but is necessary due to WP adding an incremental number into the ID
  144. // - not possible to find number via PHP parameters
  145. if ( $widget->updated ) : ?>
  146. <script type="text/javascript">
  147. (function($) {
  148. acf.doAction('append', $('[id^="widget"][id$="<?php echo $widget->id; ?>"]') );
  149. })(jQuery);
  150. </script>
  151. <?php
  152. endif;
  153. }
  154. }
  155. /*
  156. * save_widget
  157. *
  158. * This function will hook into the widget update filter and save ACF data
  159. *
  160. * @type function
  161. * @date 27/05/2015
  162. * @since 5.2.3
  163. *
  164. * @param $instance (array) widget settings
  165. * @param $new_instance (array) widget settings
  166. * @param $old_instance (array) widget settings
  167. * @param $widget (object) widget info
  168. * @return $instance
  169. */
  170. function save_widget( $instance, $new_instance, $old_instance, $widget ) {
  171. // validate nonce if we're not a REST API request.
  172. // the $_POST object is not available to us to validate if we're in a REST API call.
  173. if ( ! ( function_exists( 'wp_is_json_request' ) && wp_is_json_request() ) ) {
  174. if ( ! acf_verify_nonce( 'widget' ) ) {
  175. return $instance;
  176. }
  177. }
  178. // bail early if not valid (!customize + acf values + nonce).
  179. if ( isset( $_POST['wp_customize'] ) || ! isset( $new_instance['acf'] ) ) {
  180. return $instance;
  181. }
  182. // save
  183. acf_save_post( "widget_{$widget->id}", $new_instance['acf'] );
  184. // return
  185. return $instance;
  186. }
  187. /*
  188. * admin_footer
  189. *
  190. * This function will add some custom HTML to the footer of the edit page
  191. *
  192. * @type function
  193. * @date 11/06/2014
  194. * @since 5.0.0
  195. *
  196. * @param n/a
  197. * @return n/a
  198. */
  199. function admin_footer() {
  200. ?>
  201. <script type="text/javascript">
  202. (function($) {
  203. // vars
  204. acf.set('post_id', 'widgets');
  205. // Only initialize visible fields.
  206. acf.addFilter('find_fields', function( $fields ){
  207. // not templates
  208. $fields = $fields.not('#available-widgets .acf-field');
  209. // not widget dragging in
  210. $fields = $fields.not('.widget.ui-draggable-dragging .acf-field');
  211. // return
  212. return $fields;
  213. });
  214. // on publish
  215. $('#widgets-right').on('click', '.widget-control-save', function( e ){
  216. // vars
  217. var $button = $(this);
  218. var $form = $button.closest('form');
  219. // validate
  220. var valid = acf.validateForm({
  221. form: $form,
  222. event: e,
  223. reset: true
  224. });
  225. // if not valid, stop event and allow validation to continue
  226. if( !valid ) {
  227. e.preventDefault();
  228. e.stopImmediatePropagation();
  229. }
  230. });
  231. // show
  232. $('#widgets-right').on('click', '.widget-top', function(){
  233. var $widget = $(this).parent();
  234. if( $widget.hasClass('open') ) {
  235. acf.doAction('hide', $widget);
  236. } else {
  237. acf.doAction('show', $widget);
  238. }
  239. });
  240. $(document).on('widget-added', function( e, $widget ){
  241. // - use delay to avoid rendering issues with customizer (ensures div is visible)
  242. setTimeout(function(){
  243. acf.doAction('append', $widget );
  244. }, 100);
  245. });
  246. })(jQuery);
  247. </script>
  248. <?php
  249. }
  250. }
  251. new acf_form_widget();
  252. endif;
  253. ?>