ID);
update_post_meta($new_id, '_post_revision_of', $post->ID); // mark the new post as a variation of the old post.
if ($is_original) {
update_post_meta($post->ID, '_post_original', true);
delete_post_meta($new_id, '_post_original'); // a revision is never an original
// only call action if new revision created (not a backup)
do_action('revisionize_after_create_revision', $post->ID, $new_id);
} else {
delete_post_meta($post->ID, '_post_original');
}
// new action has bad name in order to maintain backwards compatibility of action above.
do_action('revisionize_after_revision_created', $new_id);
return $new_id;
}
function publish($post, $original) {
if (user_can_publish_revision() || is_cron()) {
if (keep_original_on_publish()) {
create_revision($original); // keep a backup copy of the live post.
}
do_action('revisionize_before_publish', $original->ID, $post->ID);
delete_post_meta($post->ID, '_post_revision_of'); // remove the variation tag so the meta isn't copied
copy_post($post, $original, $original->post_parent); // copy the variation into the live post
delete_post_meta($post->ID, '_post_original'); // original tag is copied, but remove from source.
wp_delete_post($post->ID, true); // delete the variation
do_action('revisionize_after_publish', $original->ID);
if (!is_ajax() && !is_cron()) {
wp_redirect(admin_url('post.php?action=edit&post=' . $original->ID)); // take us back to the live post
exit;
}
if (is_ajax() && apply_filters('revisionize_allow_ajax_reload', true)) {
echo "";
}
}
}
// if we delete the original post, make the current parent the new original.
function on_delete_post($post_id) {
$post = get_post($post_id);
$parent_id = get_revision_of($post);
if ($parent_id && is_original_post($post)) {
update_post_meta($parent_id, '_post_original', true);
}
}
function copy_post($post, $to=null, $parent_id=null, $status='draft') {
if ($post->post_type == 'revision') {
return;
}
$author_id = $post->post_author;
$post_status = $post->post_status;
if (!$to) {
$post_status = $status;
}
if ($to && is_original_author_preserved($to->ID)) {
$author_id = $to->post_author; // maintain original author.
} else {
$author = wp_get_current_user();
// If we're creating a backup copy of the original and a cron task
// is running at this point, the current author ID will be empty,
// so don't overwrite the $author_id of the given $post.
if (!empty($author->ID)) {
$author_id = $author->ID;
}
}
$data = array(
'menu_order' => $post->menu_order,
'comment_status' => $post->comment_status,
'ping_status' => $post->ping_status,
'post_author' => $author_id,
'post_content' => $post->post_content,
'post_excerpt' => $post->post_excerpt,
'post_mime_type' => $post->post_mime_type,
'post_parent' => !$parent_id ? $post->post_parent : $parent_id,
'post_password' => $post->post_password,
'post_status' => $post_status,
'post_title' => $post->post_title,
'post_type' => $post->post_type,
'post_date' => $post->post_date,
'post_date_gmt' => get_gmt_from_date($post->post_date)
);
if ($to) {
$data['ID'] = $to->ID;
$new_id = $to->ID;
// maintain original date. Fixes scheduled revisions overwriting the date. see issue #9
if (is_post_date_preserved($to->ID)) {
$data['post_date'] = $to->post_date;
$data['post_date_gmt'] = get_gmt_from_date($to->post_date);
}
// fixes PR #4
if (is_cron()) {
kses_remove_filters();
}
if (is_acf_post() && is_acf_fields_different($to, $post)) {
// this will force WP to create a new revision.
add_filter('wp_save_post_revision_post_has_changed', '__return_true');
}
$revision_before = get_latest_wp_revision($new_id);
wp_update_post($data);
$revision_after = get_latest_wp_revision($new_id);
if (is_wp_revision_different($revision_before, $revision_after) && $revision_after) {
copy_post_meta_info($revision_after->ID, $post);
}
if (is_cron()) {
kses_init_filters();
}
} else {
$new_id = wp_insert_post($data);
}
copy_post_taxonomies($new_id, $post);
// apply revisionized post_meta to the original post.
copy_post_meta_info($new_id, $post);
// Let others know a copy has been made
do_action('revisionize_after_copy_post', $new_id, $post);
return $new_id;
}
function copy_post_taxonomies($new_id, $post) {
global $wpdb;
if (isset($wpdb->terms)) {
// Clear default category (added by wp_insert_post)
wp_set_object_terms($new_id, NULL, 'category');
$taxonomies = apply_filters('revisionize_allowed_copy_post_taxonomies', get_object_taxonomies($post->post_type));
foreach ($taxonomies as $taxonomy) {
$post_terms = wp_get_object_terms($post->ID, $taxonomy, array('orderby' => 'term_order'));
$terms = array();
for ($i=0; $islug;
}
wp_set_object_terms($new_id, $terms, $taxonomy);
}
}
}
function clear_post_meta($id) {
$meta_keys = get_post_custom_keys($id);
if (!empty($meta_keys)) {
foreach ($meta_keys as $meta_key) {
delete_metadata('post', $id, $meta_key);
}
}
}
function copy_post_meta_info($new_id, $post) {
clear_post_meta($new_id);
$meta_keys = get_post_custom_keys($post->ID);
if (!empty($meta_keys)) {
foreach ($meta_keys as $meta_key) {
$meta_values = get_post_custom_values($meta_key, $post->ID);
foreach ($meta_values as $meta_value) {
$meta_value = maybe_unserialize($meta_value);
add_metadata('post', $new_id, $meta_key, $meta_value);
}
}
}
}
function is_acf_fields_different($a, $b) {
$afields = get_field_objects($a->ID, array('format_value' => false));
$bfields = get_field_objects($b->ID, array('format_value' => false));
return $afields != $bfields;
}
// -- Admin UI (buttons, links, etc)
// Action for post_submitbox_start which is only added if user_can_revisionize
function post_button() {
global $post;
$parent = get_parent_post($post);
if (!$parent): ?>
' . get_create_button_text() . '';
}
return $actions;
}
// Filter for display_post_states which is only added if user_can_revisionize
function post_status_label($states, $post) {
if (!empty($post) && get_revision_of($post)) {
$label = is_original_post($post) ? __('Backup Revision', 'revisionize') : __('Revision', 'revisionize');
$label = apply_filters('revisionize_post_status_label', $label);
array_unshift($states, $label);
}
return $states;
}
function notice() {
global $post;
$parent = get_parent_post($post);
$screen = get_current_screen();
if ($screen->base == 'post' && $parent):
?>
'any',
'post_status' => 'pending',
'meta_query' => array(
array(
'key' => '_post_revision_of',
'compare' => 'EXISTS',
)
)
));
if (empty($posts)) {
_e('No posts need reviewed at this time!', 'revisionize');
}
echo '';
foreach ($posts as $post) {
printf('- %s - %s
',
get_edit_post_link($post->ID),
get_the_title($post->ID),
get_the_author_meta('nicename', $post->post_author)
);
}
echo '
';
}
function admin_bar_item($admin_bar) {
global $post;
if (!empty($post) && is_post_type_enabled() && is_create_enabled($post)) {
$admin_bar->add_menu(array(
'id' => 'revisionize',
'title' => get_create_button_text(),
'href' => get_create_link($post),
'meta' => array(
'title' => esc_attr(__("Create a Revision", 'revisionize')),
),
));
}
}
// -- Helpers
function user_can_revisionize() {
return apply_filters('revisionize_user_can_revisionize', current_user_can('edit_posts') || current_user_can('edit_pages'));
}
function user_can_publish_revision() {
return apply_filters('revisionize_user_can_publish_revision', current_user_can('publish_posts') || current_user_can('publish_pages'));
}
function keep_original_on_publish() {
return apply_filters('revisionize_keep_original_on_publish', true);
}
function is_cron() {
return defined('DOING_CRON') && DOING_CRON;
}
function is_ajax() {
return defined('DOING_AJAX') && DOING_AJAX;
}
function is_post_type_enabled() {
$type = get_current_post_type();
$excluded = apply_filters('revisionize_exclude_post_types', array('acf', 'attachment'));
return empty($type) || !in_array($type, $excluded);
}
function is_create_enabled($post) {
$is_enabled = !get_revision_of($post) && current_user_can('edit_post', $post->ID);
return apply_filters('revisionize_is_create_enabled', $is_enabled, $post);
}
function is_original_post($post) {
return get_post_meta($post->ID, '_post_original', true);
}
function is_acf_post() {
return has_action('acf/save_post') && (!empty($_POST['acf']) || !empty($_POST['fields']));
}
function is_post_date_preserved($id) {
return apply_filters('revisionize_preserve_post_date', true, $id) === true;
}
function is_original_author_preserved($id) {
return apply_filters('revisionize_preserve_author', true, $id) === true;
}
function show_dashboard_widget() {
return apply_filters('revisionize_show_dashboard_widget', false);
}
function get_revision_of($post) {
return get_post_meta($post->ID, '_post_revision_of', true);
}
function get_create_link($post) {
return wp_nonce_url(admin_url("admin.php?action=revisionize_create&post=".$post->ID), 'revisionize-create-'.$post->ID);
}
function get_create_button_text() {
return apply_filters('revisionize_create_revision_button_text', __('Revisionize', 'revisionize'));
}
function get_parent_editlink($parent, $s=null) {
return sprintf('%s', get_edit_post_link($parent->ID), $s ? $s : $parent->post_title);
}
function get_parent_permalink($parent) {
return sprintf('%s', get_permalink($parent->ID), $parent->post_title);
}
function get_parent_post($post) {
$id = $post ? get_revision_of($post) : false;
return $id ? get_post($id) : false;
}
function get_current_post_type() {
global $post, $typenow, $current_screen, $pagenow;
$type = null;
if ($post && $post->post_type) {
$type = $post->post_type;
} else if ($typenow) {
$type = $typenow;
} else if ($current_screen && $current_screen->post_type) {
$type = $current_screen->post_type;
} else if (isset($_REQUEST['post_type'])) {
$type = sanitize_key($_REQUEST['post_type']);
} else if (isset($_REQUEST['post'])) {
$type = get_post_type($_REQUEST['post']);
} else if ($pagenow == 'edit.php') {
$type = 'post';
}
return $type;
}
function get_latest_wp_revision($id) {
$revisions = wp_get_post_revisions($id);
return !empty($revisions) ? current($revisions) : null;
}
function is_wp_revision_different($a, $b) {
return $a && !$b || !$a && $b || $a && $b && $a->ID != $b->ID;
}