diff --git a/includes/forms/form-post.php b/includes/forms/form-post.php index 9d6b36eb..5d40cdcb 100644 --- a/includes/forms/form-post.php +++ b/includes/forms/form-post.php @@ -6,10 +6,22 @@ if ( ! class_exists( 'ACF_Form_Post' ) ) : + /** + * Class ACF_Form_Post + * + * Handles the functionality for adding custom fields to post edit screens. + * + * @package ACF + * @since ACF 5.0.0 + */ class ACF_Form_Post { - /** @var string The first field groups style CSS. */ - var $style = ''; + /** + * Style. + * + * @var string The first field groups style CSS. + */ + public $style = ''; /** * __construct @@ -21,20 +33,20 @@ class ACF_Form_Post { * * @return void */ - function __construct() { + public function __construct() { // initialize on post edit screens add_action( 'load-post.php', array( $this, 'initialize' ) ); add_action( 'load-post-new.php', array( $this, 'initialize' ) ); // save - add_filter( 'wp_insert_post_empty_content', array( $this, 'wp_insert_post_empty_content' ), 10, 2 ); + add_filter( 'wp_insert_post_empty_content', array( $this, 'wp_insert_post_empty_content' ), 10, 1 ); add_action( 'save_post', array( $this, 'save_post' ), 10, 2 ); } /** - * initialize + * Initialize. * * Sets up Form functionality. * @@ -43,7 +55,7 @@ function __construct() { * * @return void */ - function initialize() { + public function initialize() { // globals global $typenow; @@ -72,7 +84,6 @@ function initialize() { } /** - * add_meta_boxes * * Adds ACF metaboxes for the given $post_type and $post. * @@ -83,7 +94,7 @@ function initialize() { * @param WP_Post $post The post being edited. * @return void */ - function add_meta_boxes( $post_type, $post ) { + public function add_meta_boxes( $post_type, $post ) { // Storage for localized postboxes. $postboxes = array(); @@ -107,7 +118,7 @@ function add_meta_boxes( $post_type, $post ) { $priority = 'high'; // high, core, default, low // Reduce priority for sidebar metaboxes for best position. - if ( $context == 'side' ) { + if ( 'side' === $context ) { $priority = 'core'; } @@ -176,7 +187,7 @@ function add_meta_boxes( $post_type, $post ) { public function edit_form_after_title() { // globals - global $post, $wp_meta_boxes; + global $post; // render post data acf_form_data( @@ -199,18 +210,16 @@ public function edit_form_after_title() { } /** - * render_meta_box - * * Renders the ACF metabox HTML. * * @date 19/9/18 * @since ACF 5.7.6.7.6 * - * @param WP_Post $post The post being edited. - * @param array metabox The add_meta_box() args. + * @param WP_Post $post The post being edited. + * @param array $metabox The add_meta_box() args. * @return void */ - function render_meta_box( $post, $metabox ) { + public function render_meta_box( $post, $metabox ) { // vars $id = $metabox['id']; @@ -222,7 +231,6 @@ function render_meta_box( $post, $metabox ) { } /** - * wp_insert_post_empty_content * * Allows WP to insert a new post without title or post_content if ACF data exists. * @@ -230,17 +238,14 @@ function render_meta_box( $post, $metabox ) { * @since ACF 5.0.1.0.1 * * @param boolean $maybe_empty Whether the post should be considered "empty". - * @param array $postarr Array of post data. * @return boolean */ - function wp_insert_post_empty_content( $maybe_empty, $postarr ) { + public function wp_insert_post_empty_content( $maybe_empty ) { - // return false and allow insert if '_acf_changed' exists + // Return false and allow insert if '_acf_changed' exists. if ( $maybe_empty && acf_maybe_get_POST( '_acf_changed' ) ) { return false; } - - // return return $maybe_empty; } @@ -255,33 +260,31 @@ function wp_insert_post_empty_content( $maybe_empty, $postarr ) { * @param WP_Post $post The post to check. * @return boolean */ - function allow_save_post( $post ) { + public function allow_save_post( $post ) { - // vars $allow = true; - // restrict post types + // Restricted post types. $restrict = array( 'auto-draft', 'revision', 'acf-field', 'acf-field-group' ); - if ( in_array( $post->post_type, $restrict ) ) { + if ( in_array( $post->post_type, $restrict, true ) ) { $allow = false; } - // disallow if the $_POST ID value does not match the $post->ID + // Disallow if the $_POST ID value does not match the $post->ID. $form_post_id = (int) acf_maybe_get_POST( 'post_ID' ); if ( $form_post_id && $form_post_id !== $post->ID ) { $allow = false; } - // revision (preview) - if ( $post->post_type == 'revision' ) { + // Revision (preview). + if ( 'revision' === $post->post_type ) { // allow if doing preview and this $post is a child of the $_POST ID - if ( acf_maybe_get_POST( 'wp-preview' ) == 'dopreview' && $form_post_id === $post->post_parent ) { + if ( 'dopreview' === acf_maybe_get_POST( 'wp-preview' ) && $form_post_id === $post->post_parent ) { $allow = true; } } - // return return $allow; } @@ -306,7 +309,7 @@ public function save_post( $post_id, $post ) { } // Validate for published post (allow draft to save without validation). - if ( $post->post_status === 'publish' ) { + if ( 'publish' === $post->post_status ) { // Bail early if validation fails. if ( ! acf_validate_save_post() ) { return; diff --git a/tests/php/includes/forms/test-form-post.php b/tests/php/includes/forms/test-form-post.php new file mode 100644 index 00000000..d201223f --- /dev/null +++ b/tests/php/includes/forms/test-form-post.php @@ -0,0 +1,145 @@ +assertTrue( class_exists( 'ACF_Form_Post' ), 'ACF_Form_Post class should exist' ); + } + + /** + * Test if the ACF_Form_Post class is properly initialized. + */ + public function test_form_post_initialization() { + $form_post = new ACF_Form_Post(); + + $this->assertInstanceOf( 'ACF_Form_Post', $form_post, 'ACF_Form_Post should be properly initialized' ); + } + + /** + * Test the allow_save_post method under different scenarios. + */ + public function test_allow_save_post() { + $form_post = new ACF_Form_Post(); + + // Test auto-draft post type (should not be allowed). + $auto_draft_post = (object) array( + 'ID' => 1, + 'post_type' => 'auto-draft', + ); + $this->assertFalse( $form_post->allow_save_post( $auto_draft_post ), 'Auto-draft posts should not be allowed' ); + + // Test regular post (should be allowed). + $regular_post = (object) array( + 'ID' => 2, + 'post_type' => 'post', + ); + $this->assertTrue( $form_post->allow_save_post( $regular_post ), 'Regular posts should be allowed' ); + + // Test ACF field group (should not be allowed). + $acf_field_group = (object) array( + 'ID' => 3, + 'post_type' => 'acf-field-group', + ); + $this->assertFalse( $form_post->allow_save_post( $acf_field_group ), 'ACF field groups should not be allowed' ); + } + + /** + * Test wp_insert_post_empty_content method. + */ + public function test_wp_insert_post_empty_content() { + $form_post = new ACF_Form_Post(); + + // Should return true when no ACF data is present. + $this->assertTrue( + $form_post->wp_insert_post_empty_content( true ), + 'Should return true when no ACF data is present' + ); + + // Simulate POST data with ACF changes. + $_POST['_acf_changed'] = '1'; + $this->assertFalse( + $form_post->wp_insert_post_empty_content( true ), + 'Should return false when ACF data is present' + ); + unset( $_POST['_acf_changed'] ); + } + + /** + * Test revision handling in allow_save_post. + */ + public function test_allow_save_post_revision_handling() { + $form_post = new ACF_Form_Post(); + + // Test regular revision (should not be allowed). + $revision = (object) array( + 'ID' => 4, + 'post_type' => 'revision', + 'post_parent' => 10, + ); + $this->assertFalse( + $form_post->allow_save_post( $revision ), + 'Regular revision should not be allowed' + ); + + // Test preview revision (should be allowed). + $_POST['wp-preview'] = 'dopreview'; + $_POST['post_ID'] = 10; // Set parent post ID. + $preview_revision = (object) array( + 'ID' => 5, + 'post_type' => 'revision', + 'post_parent' => 10, + ); + $this->assertTrue( + $form_post->allow_save_post( $preview_revision ), + 'Preview revision should be allowed when parent matches' + ); + + // Cleanup + unset( $_POST['wp-preview'] ); + unset( $_POST['post_ID'] ); + } + + /** + * Test post ID validation in allow_save_post. + */ + public function test_allow_save_post_id_validation() { + $form_post = new ACF_Form_Post(); + + // Test when POST ID doesn't match post ID + $_POST['post_ID'] = 999; + $post = (object) array( + 'ID' => 123, + 'post_type' => 'post', + ); + $this->assertFalse( + $form_post->allow_save_post( $post ), + 'Should not allow save when POST ID differs from post ID' + ); + + // Test when POST ID matches post ID + $_POST['post_ID'] = 123; + $this->assertTrue( + $form_post->allow_save_post( $post ), + 'Should allow save when POST ID matches post ID' + ); + + // Cleanup + unset( $_POST['post_ID'] ); + } +}