Save the post for the loaded changeset.
public save_changeset_post ( array $args = [] ) : array | WP_Error | ||
$args | array | { Args for changeset post. @type array $data Optional additional changeset data. Values will be merged on top of any existing post values. @type string $status Post status. Optional. If supplied, the save will be transactional and a post revision will be allowed. @type string $title Post title. Optional. @type string $date_gmt Date in GMT. Optional. @type int $user_id ID for user who is saving the changeset. Optional, defaults to the current user ID. @type bool $starter_content Whether the data is starter content. If false (default), then $starter_content will be cleared for any $data being saved. } |
return | array | WP_Error | Returns array on success and WP_Error with array data on error. |
/** * Test WP_Customize_Manager::save_changeset_post(). * * @ticket 30937 * @covers WP_Customize_Manager::save_changeset_post() */ function test_save_changeset_post_without_theme_activation() { global $wp_customize; wp_set_current_user(self::$admin_user_id); $did_action = array('customize_save_validation_before' => did_action('customize_save_validation_before'), 'customize_save' => did_action('customize_save'), 'customize_save_after' => did_action('customize_save_after')); $uuid = wp_generate_uuid4(); $wp_customize = $manager = new WP_Customize_Manager(array('changeset_uuid' => $uuid)); $wp_customize = $manager; $manager->register_controls(); $manager->set_post_value('blogname', 'Changeset Title'); $manager->set_post_value('blogdescription', 'Changeset Tagline'); $pre_saved_data = array('blogname' => array('value' => 'Overridden Changeset Title'), 'blogdescription' => array('custom' => 'something')); $date = gmdate('Y') + 1 . '-12-01 00:00:00'; $r = $manager->save_changeset_post(array('status' => 'auto-draft', 'title' => 'Auto Draft', 'date_gmt' => $date, 'data' => $pre_saved_data)); $this->assertInternalType('array', $r); $this->assertEquals($did_action['customize_save_validation_before'] + 1, did_action('customize_save_validation_before')); $post_id = $manager->find_changeset_post_id($uuid); $this->assertNotNull($post_id); $saved_data = json_decode(get_post($post_id)->post_content, true); $this->assertEquals($manager->unsanitized_post_values(), wp_list_pluck($saved_data, 'value')); $this->assertEquals($pre_saved_data['blogname']['value'], $saved_data['blogname']['value']); $this->assertEquals($pre_saved_data['blogdescription']['custom'], $saved_data['blogdescription']['custom']); foreach ($saved_data as $setting_id => $setting_params) { $this->assertArrayHasKey('type', $setting_params); $this->assertEquals('option', $setting_params['type']); $this->assertArrayHasKey('user_id', $setting_params); $this->assertEquals(self::$admin_user_id, $setting_params['user_id']); } $this->assertEquals('Auto Draft', get_post($post_id)->post_title); $this->assertEquals('auto-draft', get_post($post_id)->post_status); $this->assertEquals($date, get_post($post_id)->post_date_gmt); $this->assertNotEquals('Changeset Title', get_option('blogname')); $this->assertArrayHasKey('setting_validities', $r); // Test saving with invalid settings, ensuring transaction blocked. $previous_saved_data = $saved_data; $manager->add_setting('foo_unauthorized', array('capability' => 'do_not_allow')); $manager->add_setting('baz_illegal', array('validate_callback' => array($this, 'return_illegal_error'))); $r = $manager->save_changeset_post(array('status' => 'auto-draft', 'data' => array('blogname' => array('value' => 'OK'), 'foo_unauthorized' => array('value' => 'No'), 'bar_unknown' => array('value' => 'No'), 'baz_illegal' => array('value' => 'No')))); $this->assertInstanceOf('WP_Error', $r); $this->assertEquals('transaction_fail', $r->get_error_code()); $this->assertInternalType('array', $r->get_error_data()); $this->assertArrayHasKey('setting_validities', $r->get_error_data()); $error_data = $r->get_error_data(); $this->assertArrayHasKey('blogname', $error_data['setting_validities']); $this->assertTrue($error_data['setting_validities']['blogname']); $this->assertArrayHasKey('foo_unauthorized', $error_data['setting_validities']); $this->assertInstanceOf('WP_Error', $error_data['setting_validities']['foo_unauthorized']); $this->assertEquals('unauthorized', $error_data['setting_validities']['foo_unauthorized']->get_error_code()); $this->assertArrayHasKey('bar_unknown', $error_data['setting_validities']); $this->assertInstanceOf('WP_Error', $error_data['setting_validities']['bar_unknown']); $this->assertEquals('unrecognized', $error_data['setting_validities']['bar_unknown']->get_error_code()); $this->assertArrayHasKey('baz_illegal', $error_data['setting_validities']); $this->assertInstanceOf('WP_Error', $error_data['setting_validities']['baz_illegal']); $this->assertEquals('illegal', $error_data['setting_validities']['baz_illegal']->get_error_code()); // Since transactional, ensure no changes have been made. $this->assertEquals($previous_saved_data, json_decode(get_post($post_id)->post_content, true)); // Attempt a non-transactional/incremental update. $wp_customize = $manager = new WP_Customize_Manager(array('changeset_uuid' => $uuid)); $wp_customize = $manager; $manager->register_controls(); // That is, register settings. $r = $manager->save_changeset_post(array('status' => null, 'data' => array('blogname' => array('value' => 'Non-Transactional \\o/ <script>unsanitized</script>'), 'bar_unknown' => array('value' => 'No')))); $this->assertInternalType('array', $r); $this->assertArrayHasKey('setting_validities', $r); $this->assertTrue($r['setting_validities']['blogname']); $this->assertInstanceOf('WP_Error', $r['setting_validities']['bar_unknown']); $saved_data = json_decode(get_post($post_id)->post_content, true); $this->assertNotEquals($previous_saved_data, $saved_data); $this->assertEquals('Non-Transactional \\o/ <script>unsanitized</script>', $saved_data['blogname']['value']); // Ensure the filter applies. $customize_changeset_save_data_call_count = $this->customize_changeset_save_data_call_count; add_filter('customize_changeset_save_data', array($this, 'filter_customize_changeset_save_data'), 10, 2); $manager->save_changeset_post(array('status' => null, 'data' => array('blogname' => array('value' => 'Filtered')))); $this->assertEquals($customize_changeset_save_data_call_count + 1, $this->customize_changeset_save_data_call_count); // Publish the changeset: actions will be doubled since also trashed. $expected_actions = array('wp_trash_post' => 1, 'clean_post_cache' => 2, 'transition_post_status' => 2, 'publish_to_trash' => 1, 'trash_customize_changeset' => 1, 'edit_post' => 2, 'save_post_customize_changeset' => 2, 'save_post' => 2, 'wp_insert_post' => 2, 'trashed_post' => 1); $action_counts = array(); foreach (array_keys($expected_actions) as $action_name) { $action_counts[$action_name] = did_action($action_name); } $wp_customize = $manager = new WP_Customize_Manager(array('changeset_uuid' => $uuid)); do_action('customize_register', $wp_customize); $manager->add_setting('scratchpad', array('type' => 'option', 'capability' => 'exist')); $manager->get_setting('blogname')->capability = 'exist'; $original_capabilities = wp_list_pluck($manager->settings(), 'capability'); wp_set_current_user(self::$subscriber_user_id); $r = $manager->save_changeset_post(array('status' => 'publish', 'data' => array('blogname' => array('value' => 'Do it live \\o/'), 'scratchpad' => array('value' => '<script>console.info( "HELLO" )</script>')))); $this->assertInternalType('array', $r); $this->assertEquals('Do it live \\o/', get_option('blogname')); $this->assertEquals('trash', get_post_status($post_id)); // Auto-trashed. $this->assertEquals($original_capabilities, wp_list_pluck($manager->settings(), 'capability')); $this->assertContains('<script>', get_post($post_id)->post_content); $this->assertEquals($manager->changeset_uuid(), get_post($post_id)->post_name, 'Expected that the "__trashed" suffix to not be added.'); wp_set_current_user(self::$admin_user_id); $this->assertEquals('publish', get_post_meta($post_id, '_wp_trash_meta_status', true)); $this->assertTrue(is_numeric(get_post_meta($post_id, '_wp_trash_meta_time', true))); foreach (array_keys($expected_actions) as $action_name) { $this->assertEquals($expected_actions[$action_name] + $action_counts[$action_name], did_action($action_name), "Action: {$action_name}"); } // Test revisions. add_post_type_support('customize_changeset', 'revisions'); $uuid = wp_generate_uuid4(); $wp_customize = $manager = new WP_Customize_Manager(array('changeset_uuid' => $uuid)); do_action('customize_register', $manager); $manager->set_post_value('blogname', 'Hello Surface'); $manager->save_changeset_post(array('status' => 'auto-draft')); $manager->set_post_value('blogname', 'Hello World'); $manager->save_changeset_post(array('status' => 'draft')); $this->assertTrue(wp_revisions_enabled(get_post($manager->changeset_post_id()))); $manager->set_post_value('blogname', 'Hello Solar System'); $manager->save_changeset_post(array('status' => 'draft')); $manager->set_post_value('blogname', 'Hello Galaxy'); $manager->save_changeset_post(array('status' => 'draft')); $this->assertCount(3, wp_get_post_revisions($manager->changeset_post_id())); }
/** * Test WP_Customize_Manager::save(). * * @ticket 30937 * @covers WP_Customize_Manager::save() */ function test_save_failures() { global $wp_customize; $wp_customize = new WP_Customize_Manager(); $wp_customize->register_controls(); add_filter('user_has_cap', array($this, 'filter_user_has_cap')); // Unauthenticated. wp_set_current_user(0); $this->make_ajax_call('customize_save'); $this->assertFalse($this->_last_response_parsed['success']); $this->assertEquals('unauthenticated', $this->_last_response_parsed['data']); // Unauthorized. wp_set_current_user(self::$subscriber_user_id); $nonce = wp_create_nonce('save-customize_' . $wp_customize->get_stylesheet()); $_POST['nonce'] = $_GET['nonce'] = $_REQUEST['nonce'] = $nonce; $exception = null; try { ob_start(); $wp_customize->setup_theme(); } catch (WPAjaxDieContinueException $e) { $exception = $e; } $this->assertNotEmpty($e); $this->assertEquals(-1, $e->getMessage()); // Not called setup_theme. wp_set_current_user(self::$admin_user_id); $nonce = wp_create_nonce('save-customize_' . $wp_customize->get_stylesheet()); $_POST['nonce'] = $_GET['nonce'] = $_REQUEST['nonce'] = $nonce; $this->make_ajax_call('customize_save'); $this->assertFalse($this->_last_response_parsed['success']); $this->assertEquals('not_preview', $this->_last_response_parsed['data']); // Bad nonce. $_POST['nonce'] = $_GET['nonce'] = $_REQUEST['nonce'] = 'bad'; $wp_customize->setup_theme(); $this->make_ajax_call('customize_save'); $this->assertFalse($this->_last_response_parsed['success']); $this->assertEquals('invalid_nonce', $this->_last_response_parsed['data']); // User cannot create. $nonce = wp_create_nonce('save-customize_' . $wp_customize->get_stylesheet()); $_POST['nonce'] = $_GET['nonce'] = $_REQUEST['nonce'] = $nonce; $post_type_obj = get_post_type_object('customize_changeset'); $post_type_obj->cap->create_posts = 'create_customize_changesets'; $this->make_ajax_call('customize_save'); $this->assertFalse($this->_last_response_parsed['success']); $this->assertEquals('cannot_create_changeset_post', $this->_last_response_parsed['data']); $this->overridden_caps[$post_type_obj->cap->create_posts] = true; $this->make_ajax_call('customize_save'); $this->assertTrue($this->_last_response_parsed['success']); $post_type_obj->cap->create_posts = 'customize'; // Restore. // Changeset already published. $wp_customize->set_post_value('blogname', 'Hello'); $wp_customize->save_changeset_post(array('status' => 'publish')); $this->make_ajax_call('customize_save'); $this->assertFalse($this->_last_response_parsed['success']); $this->assertEquals('changeset_already_published', $this->_last_response_parsed['data']['code']); wp_update_post(array('ID' => $wp_customize->changeset_post_id(), 'post_status' => 'auto-draft')); // User cannot edit. $post_type_obj = get_post_type_object('customize_changeset'); $post_type_obj->cap->edit_post = 'edit_customize_changesets'; $this->make_ajax_call('customize_save'); $this->assertFalse($this->_last_response_parsed['success']); $this->assertEquals('cannot_edit_changeset_post', $this->_last_response_parsed['data']); $this->overridden_caps[$post_type_obj->cap->edit_post] = true; $this->make_ajax_call('customize_save'); $this->assertTrue($this->_last_response_parsed['success']); $post_type_obj->cap->edit_post = 'customize'; // Restore. // Bad customize_changeset_data. $_POST['customize_changeset_data'] = '[MALFORMED]'; $this->make_ajax_call('customize_save'); $this->assertFalse($this->_last_response_parsed['success']); $this->assertEquals('invalid_customize_changeset_data', $this->_last_response_parsed['data']); // Bad customize_changeset_status. $_POST['customize_changeset_data'] = '{}'; $_POST['customize_changeset_status'] = 'unrecognized'; $this->make_ajax_call('customize_save'); $this->assertFalse($this->_last_response_parsed['success']); $this->assertEquals('bad_customize_changeset_status', $this->_last_response_parsed['data']); // Disallowed publish posts if not allowed. $post_type_obj = get_post_type_object('customize_changeset'); $post_type_obj->cap->publish_posts = 'publish_customize_changesets'; $_POST['customize_changeset_status'] = 'publish'; $this->make_ajax_call('customize_save'); $this->assertFalse($this->_last_response_parsed['success']); $this->assertEquals('changeset_publish_unauthorized', $this->_last_response_parsed['data']); $_POST['customize_changeset_status'] = 'future'; $this->make_ajax_call('customize_save'); $this->assertFalse($this->_last_response_parsed['success']); $this->assertEquals('changeset_publish_unauthorized', $this->_last_response_parsed['data']); $post_type_obj->cap->publish_posts = 'customize'; // Restore. // Validate date. $_POST['customize_changeset_status'] = 'draft'; $_POST['customize_changeset_date'] = 'BAD DATE'; $this->make_ajax_call('customize_save'); $this->assertFalse($this->_last_response_parsed['success']); $this->assertEquals('bad_customize_changeset_date', $this->_last_response_parsed['data']); $_POST['customize_changeset_date'] = '2010-01-01 00:00:00'; $this->make_ajax_call('customize_save'); $this->assertFalse($this->_last_response_parsed['success']); $this->assertEquals('not_future_date', $this->_last_response_parsed['data']['code']); $_POST['customize_changeset_date'] = gmdate('Y') + 1 . '-01-01 00:00:00'; $this->make_ajax_call('customize_save'); $this->assertTrue($this->_last_response_parsed['success']); $_POST['customize_changeset_status'] = 'future'; $_POST['customize_changeset_date'] = '+10 minutes'; $this->make_ajax_call('customize_save'); $this->assertTrue($this->_last_response_parsed['success']); $this->assertEquals('future', get_post_status($wp_customize->changeset_post_id())); wp_update_post(array('ID' => $wp_customize->changeset_post_id(), 'post_status' => 'auto-draft')); }