/core/controllers/post.php

  1. <?php  
  2.  
  3. /** 
  4. * acf_controller_post 
  5. * 
  6. * This class contains the functionality to add ACF fields to a post edit form 
  7. * 
  8. * @type class 
  9. * @date 5/09/13 
  10. * @since 3.1.8 
  11. * 
  12. */ 
  13.  
  14. class acf_controller_post 
  15.  
  16. /** 
  17. * Constructor 
  18. * 
  19. * This function will construct all the neccessary actions and filters 
  20. * 
  21. * @type function 
  22. * @date 23/06/12 
  23. * @since 3.1.8 
  24. * 
  25. * @param N/A 
  26. * @return N/A 
  27. */ 
  28.  
  29. function __construct() 
  30. // actions 
  31. add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts')); 
  32. add_action('save_post', array($this, 'save_post'), 10, 1); 
  33.  
  34.  
  35. // ajax 
  36. add_action('wp_ajax_acf/post/render_fields', array($this, 'ajax_render_fields')); 
  37. add_action('wp_ajax_acf/post/get_style', array($this, 'ajax_get_style')); 
  38.  
  39.  
  40. /** 
  41. * validate_page 
  42. * 
  43. * This function will check if the current page is for a post/page edit form 
  44. * 
  45. * @type function 
  46. * @date 23/06/12 
  47. * @since 3.1.8 
  48. * 
  49. * @param N/A 
  50. * @return (boolean) 
  51. */ 
  52.  
  53. function validate_page() 
  54. // global 
  55. global $pagenow, $typenow; 
  56.  
  57.  
  58. // vars 
  59. $return = false; 
  60.  
  61.  
  62. // validate page 
  63. if( in_array( $pagenow, array('post.php', 'post-new.php') ) ) 
  64.  
  65. // validate post type 
  66. global $typenow; 
  67.  
  68. if( $typenow != "acf" ) 
  69. $return = true; 
  70.  
  71.  
  72.  
  73. // validate page (Shopp) 
  74. if( $pagenow == "admin.php" && isset( $_GET['page'] ) && $_GET['page'] == "shopp-products" && isset( $_GET['id'] ) ) 
  75. $return = true; 
  76.  
  77.  
  78. // return 
  79. return $return; 
  80.  
  81.  
  82. /** 
  83. * admin_enqueue_scripts 
  84. * 
  85. * This action is run after post query but before any admin script / head actions.  
  86. * It is a good place to register all actions. 
  87. * 
  88. * @type action (admin_enqueue_scripts) 
  89. * @date 26/01/13 
  90. * @since 3.6.0 
  91. * 
  92. * @param N/A 
  93. * @return N/A 
  94. */ 
  95.  
  96. function admin_enqueue_scripts() 
  97. // validate page 
  98. if( ! $this->validate_page() ) 
  99. return; 
  100.  
  101.  
  102. // actions 
  103. do_action('acf/input/admin_enqueue_scripts'); 
  104.  
  105. add_action('admin_head', array($this, 'admin_head')); 
  106.  
  107.  
  108. /** 
  109. * admin_head 
  110. * 
  111. * This action will find and add field groups to the current edit page 
  112. * 
  113. * @type action (admin_head) 
  114. * @date 23/06/12 
  115. * @since 3.1.8 
  116. * 
  117. * @param N/A 
  118. * @return N/A 
  119. */ 
  120.  
  121. function admin_head() 
  122. // global
  123. global $post, $pagenow, $typenow; 
  124.  
  125.  
  126. // shopp 
  127. if( $pagenow == "admin.php" && isset( $_GET['page'] ) && $_GET['page'] == "shopp-products" && isset( $_GET['id'] ) ) 
  128. $typenow = "shopp_product"; 
  129.  
  130.  
  131. // vars 
  132. $post_id = $post ? $post->ID : 0; 
  133.  
  134.  
  135. // get field groups 
  136. $filter = array(  
  137. 'post_id' => $post_id,  
  138. 'post_type' => $typenow  
  139. ); 
  140. $metabox_ids = array(); 
  141. $metabox_ids = apply_filters( 'acf/location/match_field_groups', $metabox_ids, $filter ); 
  142.  
  143.  
  144. // get style of first field group 
  145. $style = ''; 
  146. if( isset($metabox_ids[0]) ) 
  147. $style = $this->get_style( $metabox_ids[0] ); 
  148.  
  149.  
  150. // Style 
  151. echo '<style type="text/css" id="acf_style" >' . $style . '</style>'; 
  152.  
  153.  
  154. // add user js + css 
  155. do_action('acf/input/admin_head'); 
  156.  
  157.  
  158. // get field groups 
  159. $acfs = apply_filters('acf/get_field_groups', array()); 
  160.  
  161.  
  162. if( $acfs ) 
  163. foreach( $acfs as $acf ) 
  164. // load options 
  165. $acf['options'] = apply_filters('acf/field_group/get_options', array(), $acf['id']); 
  166.  
  167.  
  168. // vars 
  169. $show = in_array( $acf['id'], $metabox_ids ) ? 1 : 0; 
  170.  
  171.  
  172. // priority 
  173. $priority = 'high'; 
  174. if( $acf['options']['position'] == 'side' ) 
  175. $priority = 'core'; 
  176. $priority = apply_filters('acf/input/meta_box_priority', $priority, $acf); 
  177.  
  178.  
  179. // add meta box 
  180. add_meta_box( 
  181. 'acf_' . $acf['id'],  
  182. $acf['title'],  
  183. array($this, 'meta_box_input'),  
  184. $typenow,  
  185. $acf['options']['position'],  
  186. $priority,  
  187. array( 'field_group' => $acf, 'show' => $show, 'post_id' => $post_id ) 
  188. ); 
  189.  
  190. // foreach($acfs as $acf) 
  191. // if($acfs) 
  192.  
  193.  
  194. // Allow 'acf_after_title' metabox position 
  195. add_action('edit_form_after_title', array($this, 'edit_form_after_title')); 
  196.  
  197.  
  198. // remove ACF from meta postbox 
  199. add_filter( 'is_protected_meta', array($this, 'is_protected_meta'), 10, 3 ); 
  200.  
  201.  
  202. /** 
  203. * edit_form_after_title 
  204. * 
  205. * This action will allow ACF to render metaboxes after the title 
  206. * 
  207. * @type action 
  208. * @date 17/08/13 
  209. * 
  210. * @param N/A 
  211. * @return N/A 
  212. */ 
  213.  
  214. function edit_form_after_title() 
  215. // global
  216. global $post, $wp_meta_boxes; 
  217.  
  218.  
  219. // render 
  220. do_meta_boxes( get_current_screen(), 'acf_after_title', $post); 
  221.  
  222.  
  223. // clean up 
  224. unset( $wp_meta_boxes['post']['acf_after_title'] ); 
  225.  
  226.  
  227. // preview hack 
  228. // the following code will add a hidden input which will trigger WP to create a revision apon save 
  229. // http://support.advancedcustomfields.com/forums/topic/preview-solution/#post-4106 
  230. ?> 
  231. <div style="display:none"> 
  232. <input type="hidden" name="acf_has_changed" id="acf-has-changed" value="0" /> 
  233. </div> 
  234. <?php 
  235.  
  236.  
  237. /** 
  238. * meta_box_input 
  239. * 
  240. * @description:  
  241. * @since 1.0.0 
  242. * @created: 23/06/12 
  243. */ 
  244.  
  245. function meta_box_input( $post, $args ) 
  246. // extract $args 
  247. extract( $args ); 
  248.  
  249.  
  250. // classes 
  251. $class = 'acf_postbox ' . $args['field_group']['options']['layout']; 
  252. $toggle_class = 'acf_postbox-toggle'; 
  253.  
  254.  
  255. if( ! $args['show'] ) 
  256. $class .= ' acf-hidden'; 
  257. $toggle_class .= ' acf-hidden'; 
  258.  
  259.  
  260. // HTML 
  261. if( $args['show'] ) 
  262. $fields = apply_filters('acf/field_group/get_fields', array(), $args['field_group']['id']); 
  263.  
  264. do_action('acf/create_fields', $fields, $args['post_id']); 
  265. else 
  266. echo '<div class="acf-replace-with-fields"><div class="acf-loading"></div></div>'; 
  267.  
  268.  
  269. // nonce 
  270. echo '<div style="display:none">'; 
  271. echo '<input type="hidden" name="acf_nonce" value="' . wp_create_nonce( 'input' ) . '" />'; 
  272. ?> 
  273. <script type="text/javascript"> 
  274. (function($) { 
  275.  
  276. $('#<?php echo $id; ?>').addClass('<?php echo $class; ?>').removeClass('hide-if-js'); 
  277. $('#adv-settings label[for="<?php echo $id; ?>-hide"]').addClass('<?php echo $toggle_class; ?>'); 
  278.  
  279. })(jQuery);  
  280. </script> 
  281. <?php 
  282. echo '</div>'; 
  283.  
  284.  
  285. /** 
  286. * get_style 
  287. * 
  288. * @description: called by admin_head to generate acf css style (hide other metaboxes) 
  289. * @since 2.0.5 
  290. * @created: 23/06/12 
  291. */ 
  292.  
  293. function get_style( $acf_id ) 
  294. // vars 
  295. $options = apply_filters('acf/field_group/get_options', array(), $acf_id); 
  296. $html = ''; 
  297.  
  298.  
  299. // add style to html  
  300. if( in_array('permalink', $options['hide_on_screen']) ) 
  301. $html .= '#edit-slug-box {display: none;} '; 
  302. if( in_array('the_content', $options['hide_on_screen']) ) 
  303. $html .= '#postdivrich {display: none;} '; 
  304. if( in_array('excerpt', $options['hide_on_screen']) ) 
  305. $html .= '#postexcerpt, #screen-meta label[for=postexcerpt-hide] {display: none;} '; 
  306. if( in_array('custom_fields', $options['hide_on_screen']) ) 
  307. $html .= '#postcustom, #screen-meta label[for=postcustom-hide] { display: none; } '; 
  308. if( in_array('discussion', $options['hide_on_screen']) ) 
  309. $html .= '#commentstatusdiv, #screen-meta label[for=commentstatusdiv-hide] {display: none;} '; 
  310. if( in_array('comments', $options['hide_on_screen']) ) 
  311. $html .= '#commentsdiv, #screen-meta label[for=commentsdiv-hide] {display: none;} '; 
  312. if( in_array('slug', $options['hide_on_screen']) ) 
  313. $html .= '#slugdiv, #screen-meta label[for=slugdiv-hide] {display: none;} '; 
  314. if( in_array('author', $options['hide_on_screen']) ) 
  315. $html .= '#authordiv, #screen-meta label[for=authordiv-hide] {display: none;} '; 
  316. if( in_array('format', $options['hide_on_screen']) ) 
  317. $html .= '#formatdiv, #screen-meta label[for=formatdiv-hide] {display: none;} '; 
  318. if( in_array('featured_image', $options['hide_on_screen']) ) 
  319. $html .= '#postimagediv, #screen-meta label[for=postimagediv-hide] {display: none;} '; 
  320. if( in_array('revisions', $options['hide_on_screen']) ) 
  321. $html .= '#revisionsdiv, #screen-meta label[for=revisionsdiv-hide] {display: none;} '; 
  322. if( in_array('categories', $options['hide_on_screen']) ) 
  323. $html .= '#categorydiv, #screen-meta label[for=categorydiv-hide] {display: none;} '; 
  324. if( in_array('tags', $options['hide_on_screen']) ) 
  325. $html .= '#tagsdiv-post_tag, #screen-meta label[for=tagsdiv-post_tag-hide] {display: none;} '; 
  326. if( in_array('send-trackbacks', $options['hide_on_screen']) ) 
  327. $html .= '#trackbacksdiv, #screen-meta label[for=trackbacksdiv-hide] {display: none;} '; 
  328.  
  329.  
  330. return $html; 
  331.  
  332.  
  333. /** 
  334. * ajax_get_input_style 
  335. * 
  336. * @description: called by input-actions.js to hide / show other metaboxes 
  337. * @since 2.0.5 
  338. * @created: 23/06/12 
  339. */ 
  340.  
  341. function ajax_get_style() 
  342. // vars 
  343. $options = array( 
  344. 'acf_id' => 0,  
  345. 'nonce' => '' 
  346. ); 
  347.  
  348. // load post options 
  349. $options = array_merge($options, $_POST); 
  350.  
  351.  
  352. // verify nonce 
  353. if( ! wp_verify_nonce($options['nonce'], 'acf_nonce') ) 
  354. die(0); 
  355.  
  356.  
  357. // return style 
  358. echo $this->get_style( $options['acf_id'] ); 
  359.  
  360.  
  361. // die 
  362. die; 
  363.  
  364.  
  365. /** 
  366. * ajax_render_fields 
  367. * 
  368. * @description:  
  369. * @since 3.1.6 
  370. * @created: 23/06/12 
  371. */ 
  372.  
  373. function ajax_render_fields() 
  374.  
  375. // defaults 
  376. $options = array( 
  377. 'acf_id' => 0,  
  378. 'post_id' => 0,  
  379. 'nonce' => '' 
  380. ); 
  381.  
  382.  
  383. // load post options 
  384. $options = array_merge($options, $_POST); 
  385.  
  386.  
  387. // verify nonce 
  388. if( ! wp_verify_nonce($options['nonce'], 'acf_nonce') ) 
  389. die(0); 
  390.  
  391.  
  392. // get acfs 
  393. $acfs = apply_filters('acf/get_field_groups', array()); 
  394. if( $acfs ) 
  395. foreach( $acfs as $acf ) 
  396. if( $acf['id'] == $options['acf_id'] ) 
  397. $fields = apply_filters('acf/field_group/get_fields', array(), $acf['id']); 
  398.  
  399. do_action('acf/create_fields', $fields, $options['post_id']); 
  400.  
  401. break; 
  402.  
  403. die(); 
  404.  
  405.  
  406.  
  407. /** 
  408. * save_post 
  409. * 
  410. * @description: Saves the field / location / option data for a field group 
  411. * @since 1.0.0 
  412. * @created: 23/06/12 
  413. */ 
  414.  
  415. function save_post( $post_id ) 
  416. {  
  417.  
  418. // do not save if this is an auto save routine 
  419. if( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) 
  420. return $post_id; 
  421.  
  422.  
  423. // verify nonce 
  424. if( !isset($_POST['acf_nonce'], $_POST['fields']) || !wp_verify_nonce($_POST['acf_nonce'], 'input') ) 
  425. return $post_id; 
  426.  
  427.  
  428. // if save lock contains a value, the save_post action is already running for another post. 
  429. // this would imply that the user is hooking into an ACF update_value or save_post action and inserting a new post 
  430. // if this is the case, we do not want to save all the $POST data to this post. 
  431. if( isset($GLOBALS['acf_save_lock']) && $GLOBALS['acf_save_lock'] ) 
  432. return $post_id; 
  433.  
  434.  
  435. // update the post (may even be a revision / autosave preview) 
  436. do_action('acf/save_post', $post_id); 
  437.  
  438.  
  439.  
  440. /** 
  441. * is_protected_meta 
  442. * 
  443. * This function will remove any ACF meta from showing in the meta postbox 
  444. * 
  445. * @type function 
  446. * @date 12/04/2014 
  447. * @since 5.0.0 
  448. * 
  449. * @param $post_id (int) 
  450. * @return $post_id (int) 
  451. */ 
  452.  
  453. function is_protected_meta( $protected, $meta_key, $meta_type ) { 
  454.  
  455. // global
  456. global $post; 
  457.  
  458.  
  459. // if acf_get_field_reference returns a valid key, this is an acf value, so protect it! 
  460. if( !$protected ) { 
  461.  
  462. $reference = get_field_reference( $meta_key, $post->ID ); 
  463.  
  464. if( substr($reference, 0, 6) === 'field_' ) { 
  465.  
  466. $protected = true; 
  467.  
  468. }  
  469.  
  470.  
  471.  
  472. // return 
  473. return $protected; 
  474.  
  475.  
  476.  
  477.  
  478. new acf_controller_post(); 
  479.  
  480. ?> 
.