public function test_is_autosave_dont_flush_cache() { $post = $this->factory->post->create_and_get(); $revision_id = _wp_put_post_revision($post, true); $salt = $this->obj->cache_salt; $revision = get_post($revision_id); $this->obj->clean_post_cache($revision->ID, $revision); $this->assertsame($salt, $this->obj->cache_salt); }
/** * Update an autosave for a post. * * @param WP_REST_Request $request Full details about the request. * @return WP_Error|WP_REST_Response */ public function update_item($request) { $parent = get_post($request['id']); $autosave = wp_get_post_autosave($parent->ID, get_current_user_id()); $post_data = (array) $this->prepare_item_for_database($request); if (!$autosave) { $autosave_id = _wp_put_post_revision($post_data, true); } else { $post_data['ID'] = $autosave->ID; /** * Fires before an autosave is stored. * * @since 4.1.0 * * @param array $new_autosave Post array - the autosave that is about to be saved. */ do_action('wp_creating_autosave', $post_data); wp_update_post($post_data); $autosave_id = $autosave->ID; } return $this->prepare_item_for_response(get_post($autosave_id), $request); }
/** * Saves an already existing post as a post revision. * * Typically used immediately prior to post updates. * * @package WordPress * @subpackage Post_Revisions * @since 2.6.0 * * @uses _wp_put_post_revision() * * @param int $post_id The ID of the post to save as a revision. * @return mixed Null or 0 if error, new revision ID, if success. */ function wp_save_post_revision($post_id) { // We do autosaves manually with wp_create_post_autosave() if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return; } // WP_POST_REVISIONS = 0, false if (!WP_POST_REVISIONS) { return; } if (!($post = get_post($post_id, ARRAY_A))) { return; } if (!post_type_supports($post['post_type'], 'revisions')) { return; } $return = _wp_put_post_revision($post); // WP_POST_REVISIONS = true (default), -1 if (!is_numeric(WP_POST_REVISIONS) || WP_POST_REVISIONS < 0) { return $return; } // all revisions and (possibly) one autosave $revisions = wp_get_post_revisions($post_id, array('order' => 'ASC')); // WP_POST_REVISIONS = (int) (# of autosaves to save) $delete = count($revisions) - WP_POST_REVISIONS; if ($delete < 1) { return $return; } $revisions = array_slice($revisions, 0, $delete); for ($i = 0; isset($revisions[$i]); $i++) { if (false !== strpos($revisions[$i]->post_name, 'autosave')) { continue; } wp_delete_post_revision($revisions[$i]->ID); } return $return; }
/** * Creates a revision for the current version of a post. * * Typically used immediately after a post update, as every update is a revision, * and the most recent revision always matches the current post. * * @since 2.6.0 * * @param int $post_id The ID of the post to save as a revision. * @return int|WP_Error|void Void or 0 if error, new revision ID, if success. */ function wp_save_post_revision($post_id) { if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return; } if (!($post = get_post($post_id))) { return; } if (!post_type_supports($post->post_type, 'revisions')) { return; } if ('auto-draft' == $post->post_status) { return; } if (!wp_revisions_enabled($post)) { return; } // Compare the proposed update with the last stored revision verifying that // they are different, unless a plugin tells us to always save regardless. // If no previous revisions, save one if ($revisions = wp_get_post_revisions($post_id)) { // grab the last revision, but not an autosave foreach ($revisions as $revision) { if (false !== strpos($revision->post_name, "{$revision->post_parent}-revision")) { $last_revision = $revision; break; } } /** * Filter whether the post has changed since the last revision. * * By default a revision is saved only if one of the revisioned fields has changed. * This filter can override that so a revision is saved even if nothing has changed. * * @since 3.6.0 * * @param bool $check_for_changes Whether to check for changes before saving a new revision. * Default true. * @param WP_Post $last_revision The the last revision post object. * @param WP_Post $post The post object. * */ if (isset($last_revision) && apply_filters('wp_save_post_revision_check_for_changes', $check_for_changes = true, $last_revision, $post)) { $post_has_changed = false; foreach (array_keys(_wp_post_revision_fields()) as $field) { if (normalize_whitespace($post->{$field}) != normalize_whitespace($last_revision->{$field})) { $post_has_changed = true; break; } } /** * Filter whether a post has changed. * * By default a revision is saved only if one of the revisioned fields has changed. * This filter allows for additional checks to determine if there were changes. * * @since 4.1.0 * * @param bool $post_has_changed Whether the post has changed. * @param WP_Post $last_revision The last revision post object. * @param WP_Post $post The post object. * */ $post_has_changed = (bool) apply_filters('wp_save_post_revision_post_has_changed', $post_has_changed, $last_revision, $post); //don't save revision if post unchanged if (!$post_has_changed) { return; } } } $return = _wp_put_post_revision($post); // If a limit for the number of revisions to keep has been set, // delete the oldest ones. $revisions_to_keep = wp_revisions_to_keep($post); if ($revisions_to_keep < 0) { return $return; } $revisions = wp_get_post_revisions($post_id, array('order' => 'ASC')); $delete = count($revisions) - $revisions_to_keep; if ($delete < 1) { return $return; } $revisions = array_slice($revisions, 0, $delete); for ($i = 0; isset($revisions[$i]); $i++) { if (false !== strpos($revisions[$i]->post_name, 'autosave')) { continue; } wp_delete_post_revision($revisions[$i]->ID); } return $return; }
/** * Save new revision of CSS * Checks to see if content was modified before really saving * * @param string $css * @param bool $is_preview * @return bool|int If nothing was saved, returns false. If a post * or revision was saved, returns the post ID. */ static function save_revision($css, $is_preview = false, $preprocessor = '') { $safecss_post = Jetpack_Custom_CSS::get_post(); $compressed_css = Jetpack_Custom_CSS::minify($css, $preprocessor); // If null, there was no original safecss record, so create one if (null == $safecss_post) { if (!$css) { return false; } $post = array(); $post['post_content'] = $css; $post['post_title'] = 'safecss'; $post['post_status'] = 'publish'; $post['post_type'] = 'safecss'; $post['post_content_filtered'] = $compressed_css; // Set excerpt to current theme, for display in revisions list if (function_exists('wp_get_theme')) { $current_theme = wp_get_theme(); $post['post_excerpt'] = $current_theme->Name; } else { $post['post_excerpt'] = get_current_theme(); } // Insert the CSS into wp_posts $post_id = wp_insert_post($post); wp_cache_set('custom_css_post_id', $post_id); return $post_id; } // Update CSS in post array with new value passed to this function $safecss_post['post_content'] = $css; $safecss_post['post_content_filtered'] = $compressed_css; // Set excerpt to current theme, for display in revisions list if (function_exists('wp_get_theme')) { $current_theme = wp_get_theme(); $safecss_post['post_excerpt'] = $current_theme->Name; } else { $safecss_post['post_excerpt'] = get_current_theme(); } // Don't carry over last revision's timestamps, otherwise revisions all have matching timestamps unset($safecss_post['post_date']); unset($safecss_post['post_date_gmt']); unset($safecss_post['post_modified']); unset($safecss_post['post_modified_gmt']); // Do not update post if we are only saving a preview if (false === $is_preview) { $post_id = wp_update_post($safecss_post); wp_cache_set('custom_css_post_id', $post_id); return $post_id; } else { if (!defined('DOING_MIGRATE')) { return _wp_put_post_revision($safecss_post); } } }
/** * Creates autosave data for the specified post from $_POST data. * * @package WordPress * @subpackage Post_Revisions * @since 2.6.0 * * @param mixed $post_data Associative array containing the post data or int post ID. * @return mixed The autosave revision ID. WP_Error or 0 on error. */ function wp_create_post_autosave($post_data) { if (is_numeric($post_data)) { $post_id = $post_data; $post_data = $_POST; } else { $post_id = (int) $post_data['post_ID']; } $post_data = _wp_translate_postdata(true, $post_data); if (is_wp_error($post_data)) { return $post_data; } $post_author = get_current_user_id(); // Store one autosave per author. If there is already an autosave, overwrite it. if ($old_autosave = wp_get_post_autosave($post_id, $post_author)) { $new_autosave = _wp_post_revision_data($post_data, true); $new_autosave['ID'] = $old_autosave->ID; $new_autosave['post_author'] = $post_author; // If the new autosave has the same content as the post, delete the autosave. $post = get_post($post_id); $autosave_is_different = false; foreach (array_intersect(array_keys($new_autosave), array_keys(_wp_post_revision_fields($post))) as $field) { if (normalize_whitespace($new_autosave[$field]) != normalize_whitespace($post->{$field})) { $autosave_is_different = true; break; } } if (!$autosave_is_different) { wp_delete_post_revision($old_autosave->ID); return 0; } /** * Fires before an autosave is stored. * * @since 4.1.0 * * @param array $new_autosave Post array - the autosave that is about to be saved. */ do_action('wp_creating_autosave', $new_autosave); return wp_update_post($new_autosave); } // _wp_put_post_revision() expects unescaped. $post_data = wp_unslash($post_data); // Otherwise create the new autosave as a special post revision return _wp_put_post_revision($post_data, true); }
/** * Creates autosave data for the specified post from $_POST data. * * @package WordPress * @subpackage Post_Revisions * @since 2.6.0 * * @uses _wp_translate_postdata() * @uses _wp_post_revision_fields() * * @return unknown */ function wp_create_post_autosave($post_id) { $translated = _wp_translate_postdata(true); if (is_wp_error($translated)) { return $translated; } $post_author = get_current_user_id(); // Store one autosave per author. If there is already an autosave, overwrite it. if ($old_autosave = wp_get_post_autosave($post_id, $post_author)) { $new_autosave = _wp_post_revision_fields($_POST, true); $new_autosave['ID'] = $old_autosave->ID; $new_autosave['post_author'] = $post_author; // If the new autosave is the same content as the post, delete the old autosave. $post = get_post($post_id); $autosave_is_different = false; foreach (array_keys(_wp_post_revision_fields()) as $field) { if (normalize_whitespace($new_autosave[$field]) != normalize_whitespace($post->{$field})) { $autosave_is_different = true; break; } } if (!$autosave_is_different) { wp_delete_post_revision($old_autosave->ID); return; } return wp_update_post($new_autosave); } // _wp_put_post_revision() expects unescaped. $post_data = wp_unslash($_POST); // Otherwise create the new autosave as a special post revision return _wp_put_post_revision($post_data, true); }
function insert_post($update = false, $freshness = 2) { global $wpdb; $dbpost = $this->normalize_post(true); if (!is_null($dbpost)) { $dbpost['post_pingback'] = false; // Tell WP 2.1 and 2.2 not to process for pingbacks // This is a ridiculous f*****g kludge necessitated by WordPress 2.6 munging authorship meta-data add_action('_wp_put_post_revision', array($this, 'fix_revision_meta')); // Kludge to prevent kses filters from stripping the // content of posts when updating without a logged in // user who has `unfiltered_html` capability. $mungers = array('wp_filter_kses', 'wp_filter_post_kses'); $removed = array(); foreach ($mungers as $munger) { if (has_filter('content_save_pre', $munger)) { remove_filter('content_save_pre', $munger); $removed[] = $munger; } } if ($update and function_exists('get_post_field')) { // Don't munge status fields that the user may // have reset manually $doNotMunge = array('post_status', 'comment_status', 'ping_status'); foreach ($doNotMunge as $field) { $dbpost[$field] = get_post_field($field, $this->wp_id()); } } // WP3's wp_insert_post scans current_user_can() for the // tax_input, with no apparent way to override. Ugh. add_action('transition_post_status', array($this, 'add_terms'), -10001, 3); // WP3 appears to override whatever you give it for // post_modified. Ugh. add_action('transition_post_status', array($this, 'fix_post_modified_ts'), -10000, 3); if ($update) { $this->post['ID'] = $this->wp_id(); $dbpost['ID'] = $this->post['ID']; } // O.K., is this a new post? If so, we need to create // the basic post record before we do anything else. if ($this->this_revision_needs_original_post()) { // *sigh*, for handling inconsistent slash expectations < 3.6 $sdbpost = $this->db_sanitize_post($dbpost); // Go ahead and insert the first post record to // anchor the revision history. $this->_wp_id = wp_insert_post($sdbpost, true); $dbpost['ID'] = $this->_wp_id; } // Now that we've made sure the original exists, insert // this version here as a revision. $revision_id = _wp_put_post_revision($dbpost, false); if (!$this->this_revision_needs_original_post()) { if ($this->this_revision_is_current()) { wp_restore_post_revision($revision_id); } else { // If we do not activate this revision, then the // add_rss_meta will not be called, which is // more or less as it should be, but that means // we have to actively record this revision's // update hash from here. $postId = $this->post['ID']; $key = 'syndication_item_hash'; $hash = $this->update_hash(); FeedWordPress::diagnostic('syndicated_posts:meta_data', "Adding post meta-datum to post [{$postId}]: [{$key}] = " . FeedWordPress::val($hash, true)); add_post_meta($postId, $key, $hash, false); } } remove_action('transition_post_status', array($this, 'add_terms'), -10001, 3); remove_action('transition_post_status', array($this, 'fix_post_modified_ts'), -10000, 3); // Turn off ridiculous f*****g kludges #1 and #2 remove_action('_wp_put_post_revision', array($this, 'fix_revision_meta')); foreach ($removed as $filter) { add_filter('content_save_pre', $filter); } $this->validate_post_id($dbpost, $update, array(__CLASS__, __FUNCTION__)); } }
/** * Creates autosave data for the specified post from $_POST data. * * @package WordPress * @subpackage Post_Revisions * @since 2.6.0 * * @uses _wp_translate_postdata() * @uses _wp_post_revision_fields() * * @return unknown */ function wp_create_post_autosave($post_id) { $translated = _wp_translate_postdata(true); if (is_wp_error($translated)) { return $translated; } // Only store one autosave. If there is already an autosave, overwrite it. if ($old_autosave = wp_get_post_autosave($post_id)) { $new_autosave = _wp_post_revision_fields($_POST, true); $new_autosave['ID'] = $old_autosave->ID; $new_autosave['post_author'] = get_current_user_id(); return wp_update_post($new_autosave); } // _wp_put_post_revision() expects unescaped. $_POST = stripslashes_deep($_POST); // Otherwise create the new autosave as a special post revision return _wp_put_post_revision($_POST, true); }
/** * Creates autosave data for the specified post from $_POST data. * * @package WordPress * @subpackage Post_Revisions * @since 2.6.0 * * @uses _wp_translate_postdata() * @uses _wp_post_revision_fields() */ function wp_create_post_autosave($post_id) { $translated = _wp_translate_postdata(true); if (is_wp_error($translated)) { return $translated; } // Only store one autosave. If there is already an autosave, overwrite it. if ($old_autosave = wp_get_post_autosave($post_id)) { $new_autosave = _wp_post_revision_fields($_POST, true); $new_autosave['ID'] = $old_autosave->ID; return wp_update_post($new_autosave); } // Otherwise create the new autosave as a special post revision return _wp_put_post_revision($_POST, true); }
/** * Save new revision of CSS * Checks to see if content was modified before really saving * * @param string $css * @param bool $is_preview * @return bool */ function save_revision($css, $is_preview = false) { // If null, there was no original safecss record, so create one if (!($safecss_post = get_safecss_post())) { $post = array(); $post['post_content'] = $css; $post['post_title'] = 'safecss'; $post['post_status'] = 'publish'; $post['post_type'] = 'safecss'; // Insert the CSS into wp_posts $post_id = wp_insert_post($post); return true; } $safecss_post['post_content'] = $css; // Do not update post if we are only saving a preview if (false === $is_preview) { wp_update_post($safecss_post); } if (!defined('DOING_MIGRATE')) { _wp_put_post_revision($safecss_post); } }
function testGetPostPreview() { $editor_user_id = $this->factory->user->create(array('role' => 'editor')); wp_set_current_user($editor_user_id); $post_id = $this->factory->post->create(array('post_author' => $editor_user_id)); _wp_put_post_revision(array('ID' => $post_id, 'post_content' => 'New Stuff Goes here'), true); $_GET['preview'] = true; $_GET['preview_id'] = $post_id; $the_post = Timber::get_post($post_id); $this->assertEquals('New Stuff Goes here', $the_post->post_content); }
/** * Saves an already existing post as a post revision. * * Typically used immediately after post updates. * Adds a copy of the current post as a revision, so latest revision always matches current post * * @since 2.6.0 * * @uses _wp_put_post_revision() * * @param int $post_id The ID of the post to save as a revision. * @return mixed Null or 0 if error, new revision ID, if success. */ function wp_save_post_revision($post_id) { if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return; } if (!($post = get_post($post_id))) { return; } if (!post_type_supports($post->post_type, 'revisions')) { return; } if ('auto-draft' == $post->post_status) { return; } if (!wp_revisions_enabled($post)) { return; } // Compare the proposed update with the last stored revision verifying that // they are different, unless a plugin tells us to always save regardless. // If no previous revisions, save one if ($revisions = wp_get_post_revisions($post_id)) { // grab the last revision, but not an autosave foreach ($revisions as $revision) { if (false !== strpos($revision->post_name, "{$revision->post_parent}-revision")) { $last_revision = $revision; break; } } if (isset($last_revision) && apply_filters('wp_save_post_revision_check_for_changes', true, $last_revision, $post)) { $post_has_changed = false; foreach (array_keys(_wp_post_revision_fields()) as $field) { if (normalize_whitespace($post->{$field}) != normalize_whitespace($last_revision->{$field})) { $post_has_changed = true; break; } } // Check whether revisioned meta fields have changed. foreach (_wp_post_revision_meta_keys() as $meta_key) { if (get_post_meta($post->ID, $meta_key, true) != get_post_meta($last_revision->ID, $meta_key, true)) { $post_has_changed = true; break; } } // Check whether the post format has changed if (get_post_format($post->ID) != get_post_meta($last_revision->ID, '_revision_post_format', true)) { $post_has_changed = true; } //don't save revision if post unchanged if (!$post_has_changed) { return; } } } $return = _wp_put_post_revision($post); $revisions_to_keep = wp_revisions_to_keep($post); if ($revisions_to_keep < 0) { return $return; } // all revisions and autosaves $revisions = wp_get_post_revisions($post_id, array('order' => 'ASC')); $delete = count($revisions) - $revisions_to_keep; if ($delete < 1) { return $return; } $revisions = array_slice($revisions, 0, $delete); for ($i = 0; isset($revisions[$i]); $i++) { if (false !== strpos($revisions[$i]->post_name, 'autosave')) { continue; } wp_delete_post_revision($revisions[$i]->ID); } return $return; }
/** * Creates autosave data for the specified post from $_POST data. * * @package WordPress * @subpackage Post_Revisions * @since 2.6.0 * * @uses _wp_translate_postdata() * @uses _wp_post_revision_fields() * * @return unknown */ function wp_create_post_autosave($post_id) { $translated = _wp_translate_postdata(true); if (is_wp_error($translated)) { return $translated; } $post_author = get_current_user_id(); // Store one autosave per author. If there is already an autosave, overwrite it. if ($old_autosave = wp_get_post_autosave($post_id, $post_author)) { $new_autosave = _wp_post_revision_fields($_POST, true); $new_autosave['ID'] = $old_autosave->ID; $new_autosave['post_author'] = $post_author; // Auto-save revisioned meta fields. foreach (_wp_post_revision_meta_keys() as $meta_key) { if (isset($_POST[$meta_key]) && get_post_meta($new_autosave['ID'], $meta_key, true) != $_POST[$meta_key]) { // Use the underlying delete_metadata and add_metadata vs delete_post_meta // and add_post_meta to make sure we're working with the actual revision meta. delete_metadata('post', $new_autosave['ID'], $meta_key); if (!empty($_POST[$meta_key])) { add_metadata('post', $new_autosave['ID'], $meta_key, $_POST[$meta_key]); } } } // Save the post format if different if (isset($_POST['post_format']) && get_post_meta($new_autosave['ID'], '_revision_post_format', true) != $_POST['post_format']) { delete_metadata('post', $new_autosave['ID'], '_revision_post_format'); if (!empty($_POST['post_format'])) { add_metadata('post', $new_autosave['ID'], '_revision_post_format', $_POST['post_format']); } } return wp_update_post($new_autosave); } // _wp_put_post_revision() expects unescaped. $_POST = wp_unslash($_POST); // Otherwise create the new autosave as a special post revision return _wp_put_post_revision($_POST, true); }