Make WordPress Core

Ticket #25272: 25272.patch

File 25272.patch, 42.7 KB (added by azaozz, 11 years ago)
  • src/wp-admin/admin-ajax.php

     
    4949        'oembed-cache', 'image-editor', 'delete-comment', 'delete-tag', 'delete-link',
    5050        'delete-meta', 'delete-post', 'trash-post', 'untrash-post', 'delete-page', 'dim-comment',
    5151        'add-link-category', 'add-tag', 'get-tagcloud', 'get-comments', 'replyto-comment',
    52         'edit-comment', 'add-menu-item', 'add-meta', 'add-user', 'autosave', 'closed-postboxes',
     52        'edit-comment', 'add-menu-item', 'add-meta', 'add-user', 'closed-postboxes',
    5353        'hidden-columns', 'update-welcome-panel', 'menu-get-metabox', 'wp-link-ajax',
    5454        'menu-locations-save', 'menu-quick-search', 'meta-box-order', 'get-permalink',
    5555        'sample-permalink', 'inline-save', 'inline-save-tax', 'find_posts', 'widgets-order',
  • src/wp-admin/edit-form-advanced.php

     
    347347
    348348echo $form_extra;
    349349
    350 wp_nonce_field( 'autosave', 'autosavenonce', false );
    351350wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false );
    352351wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
    353352?>
  • src/wp-admin/includes/ajax-actions.php

     
    10421042        $x->send();
    10431043}
    10441044
    1045 function wp_ajax_autosave() {
    1046         define( 'DOING_AUTOSAVE', true );
    1047 
    1048         check_ajax_referer( 'autosave', 'autosavenonce' );
    1049 
    1050         $_POST['post_category'] = explode(",", $_POST['catslist']);
    1051         if ( $_POST['post_type'] == 'page' || empty($_POST['post_category']) )
    1052                 unset($_POST['post_category']);
    1053 
    1054         $data = '';
    1055         $supplemental = array();
    1056         $id = $revision_id = 0;
    1057 
    1058         $post_id = (int) $_POST['post_id'];
    1059         $_POST['ID'] = $_POST['post_ID'] = $post_id;
    1060         $post = get_post($post_id);
    1061         if ( 'auto-draft' == $post->post_status )
    1062                 $_POST['post_status'] = 'draft';
    1063 
    1064         if ( 'page' == $post->post_type ) {
    1065                 if ( !current_user_can('edit_page', $post->ID) )
    1066                         wp_die( __( 'You are not allowed to edit this page.' ) );
    1067         } else {
    1068                 if ( !current_user_can('edit_post', $post->ID) )
    1069                         wp_die( __( 'You are not allowed to edit this post.' ) );
    1070         }
    1071 
    1072         if ( ! empty( $_POST['autosave'] ) ) {
    1073                 if ( ! wp_check_post_lock( $post->ID ) && get_current_user_id() == $post->post_author && ( 'auto-draft' == $post->post_status || 'draft' == $post->post_status ) ) {
    1074                         // Drafts and auto-drafts are just overwritten by autosave for the same user if the post is not locked
    1075                         $id = edit_post();
    1076                 } else {
    1077                         // Non drafts or other users drafts are not overwritten. The autosave is stored in a special post revision for each user.
    1078                         $revision_id = wp_create_post_autosave( $post->ID );
    1079                         if ( is_wp_error($revision_id) )
    1080                                 $id = $revision_id;
    1081                         else
    1082                                 $id = $post->ID;
    1083                 }
    1084 
    1085                 if ( ! is_wp_error($id) ) {
    1086                         /* translators: draft saved date format, see http://php.net/date */
    1087                         $draft_saved_date_format = __('g:i:s a');
    1088                         /* translators: %s: date and time */
    1089                         $data = sprintf( __('Draft saved at %s.'), date_i18n( $draft_saved_date_format ) );
    1090                 }
    1091         } else {
    1092                 if ( ! empty( $_POST['auto_draft'] ) )
    1093                         $id = 0; // This tells us it didn't actually save
    1094                 else
    1095                         $id = $post->ID;
    1096         }
    1097 
    1098         // @todo Consider exposing any errors, rather than having 'Saving draft...'
    1099         $x = new WP_Ajax_Response( array(
    1100                 'what' => 'autosave',
    1101                 'id' => $id,
    1102                 'data' => $data,
    1103                 'supplemental' => $supplemental
    1104         ) );
    1105         $x->send();
    1106 }
    1107 
    11081045function wp_ajax_closed_postboxes() {
    11091046        check_ajax_referer( 'closedpostboxes', 'closedpostboxesnonce' );
    11101047        $closed = isset( $_POST['closed'] ) ? explode( ',', $_POST['closed']) : array();
  • src/wp-admin/includes/misc.php

     
    650650                if ( 2 === wp_verify_nonce( $received['post_nonce'], 'update-post_' . $post_id ) ) {
    651651                        $response['wp-refresh-post-nonces'] = array(
    652652                                'replace' => array(
    653                                         'autosavenonce' => wp_create_nonce('autosave'),
    654653                                        'getpermalinknonce' => wp_create_nonce('getpermalink'),
    655654                                        'samplepermalinknonce' => wp_create_nonce('samplepermalink'),
    656655                                        'closedpostboxesnonce' => wp_create_nonce('closedpostboxes'),
     
    665664        return $response;
    666665}
    667666add_filter( 'heartbeat_received', 'wp_refresh_post_nonces', 10, 3 );
     667
     668/**
     669 * Autosave with heartbeat
     670 *
     671 * @since 3.7
     672 */
     673function wp_autosave( $response, $data ) {
     674        if ( ! empty( $data['autosave'] ) ) {
     675                $saved = autosave( $data['autosave'] );
     676
     677                if ( is_wp_error( $saved ) ) {
     678                        $response['autosave'] = array( 'success' => false, 'message' => $saved->get_error_message() );
     679                } elseif ( empty( $saved ) ) {
     680                        $response['autosave'] = array( 'success' => false, 'message' => __( 'Error while saving the draft.' ) );
     681                } else {
     682                        /* translators: draft saved date format, see http://php.net/date */
     683                        $draft_saved_date_format = __( 'g:i:s a' );
     684                        /* translators: %s: date and time */
     685                        $response['autosave'] = array( 'success' => true, 'message' => sprintf( __( 'Draft saved at %s.' ), date_i18n( $draft_saved_date_format ) ) );
     686                }
     687        }
     688
     689        return $response;
     690}
     691// Run later as we have to set DOING_AUTOSAVE for back-compat
     692add_filter( 'heartbeat_received', 'wp_autosave', 50, 2 );
  • src/wp-admin/includes/post.php

     
    7979                }
    8080        }
    8181
    82         if ( ! empty( $post_data['post_status'] ) )
     82        if ( ! empty( $post_data['post_status'] ) ) {
    8383                $post_data['post_status'] = sanitize_key( $post_data['post_status'] );
    8484
     85                // No longer an auto-draft
     86                if ( 'auto-draft' == $post_data['post_status'] )
     87                        $post_data['post_status'] = 'draft';
     88        }
     89
    8590        // What to do based on which button they pressed
    8691        if ( isset($post_data['saveasdraft']) && '' != $post_data['saveasdraft'] )
    8792                $post_data['post_status'] = 'draft';
     
    181186        $post_data = _wp_translate_postdata( true, $post_data );
    182187        if ( is_wp_error($post_data) )
    183188                wp_die( $post_data->get_error_message() );
    184         if ( ( empty( $post_data['action'] ) || 'autosave' != $post_data['action'] ) && 'auto-draft' == $post_data['post_status'] ) {
    185                 $post_data['post_status'] = 'draft';
    186         }
    187189
    188190        if ( isset($post_data['visibility']) ) {
    189191                switch ( $post_data['visibility'] ) {
     
    13121314 * @uses _wp_translate_postdata()
    13131315 * @uses _wp_post_revision_fields()
    13141316 *
    1315  * @return unknown
     1317 * @param mixed $post_data Associative array containing the post data. Suppotrs passing the post ID for backwards compatibility.
     1318 * @return mixed The autosave revision ID. WP_Error or 0 on error.
    13161319 */
    1317 function wp_create_post_autosave( $post_id ) {
    1318         $translated = _wp_translate_postdata( true );
    1319         if ( is_wp_error( $translated ) )
    1320                 return $translated;
     1320function wp_create_post_autosave( $post_data ) {
     1321        if ( is_numeric( $post_data ) ) {
     1322                $post_id = $post_data;
     1323                $post_data = &$_POST;
     1324        } else {
     1325                $post_id = (int) $post_data['post_ID'];
     1326        }
    13211327
     1328        $post_data = _wp_translate_postdata( true, $post_data );
     1329        if ( is_wp_error( $post_data ) )
     1330                return $post_data;
     1331
    13221332        $post_author = get_current_user_id();
    13231333
    13241334        // Store one autosave per author. If there is already an autosave, overwrite it.
    13251335        if ( $old_autosave = wp_get_post_autosave( $post_id, $post_author ) ) {
    1326                 $new_autosave = _wp_post_revision_fields( $_POST, true );
     1336                $new_autosave = _wp_post_revision_fields( $post_data, true );
    13271337                $new_autosave['ID'] = $old_autosave->ID;
    13281338                $new_autosave['post_author'] = $post_author;
    13291339
    1330                 // If the new autosave is the same content as the post, delete the old autosave.
     1340                // If the new autosave has the same content as the post, delete the autosave.
    13311341                $post = get_post( $post_id );
    13321342                $autosave_is_different = false;
    13331343                foreach ( array_keys( _wp_post_revision_fields() ) as $field ) {
     
    13391349
    13401350                if ( ! $autosave_is_different ) {
    13411351                        wp_delete_post_revision( $old_autosave->ID );
    1342                         return;
     1352                        return 0;
    13431353                }
    13441354
    13451355                return wp_update_post( $new_autosave );
     
    13461356        }
    13471357
    13481358        // _wp_put_post_revision() expects unescaped.
    1349         $post_data = wp_unslash( $_POST );
     1359        $post_data = wp_unslash( $post_data );
    13501360
    13511361        // Otherwise create the new autosave as a special post revision
    13521362        return _wp_put_post_revision( $post_data, true );
     
    13721382function post_preview() {
    13731383
    13741384        $post_ID = (int) $_POST['post_ID'];
    1375         $status = get_post_status( $post_ID );
    1376         if ( 'auto-draft' == $status )
    1377                 wp_die( __('Preview not available. Please save as a draft first.') );
     1385        $_POST['ID'] = $post_ID;
    13781386
    1379         if ( isset($_POST['catslist']) )
    1380                 $_POST['post_category'] = explode(",", $_POST['catslist']);
     1387        if ( ! $post = get_post( $post_ID ) )
     1388                wp_die( __('You attempted to preview a non existing item.') );
    13811389
    1382         if ( isset($_POST['tags_input']) )
    1383                 $_POST['tags_input'] = explode(",", $_POST['tags_input']);
     1390        if ( ! current_user_can( 'edit_post', $post->ID ) )
     1391                wp_die( __('You are not allowed to preview this item.') );
    13841392
    1385         if ( $_POST['post_type'] == 'page' || empty($_POST['post_category']) )
    1386                 unset($_POST['post_category']);
     1393        $is_autosave = false;
    13871394
    1388         $_POST['ID'] = $post_ID;
    1389         $post = get_post($post_ID);
    1390 
    1391         if ( 'page' == $post->post_type ) {
    1392                 if ( ! current_user_can('edit_page', $post_ID) )
    1393                         wp_die( __('You are not allowed to edit this page.') );
     1395        if ( ! wp_check_post_lock( $post->ID ) && get_current_user_id() == $post->post_author && ( 'draft' == $post->post_status || 'auto-draft' == $post->post_status ) ) {
     1396                $saved_post_id = edit_post();
    13941397        } else {
    1395                 if ( ! current_user_can('edit_post', $post_ID) )
    1396                         wp_die( __('You are not allowed to edit this post.') );
    1397         }
     1398                $is_autosave = true;
    13981399
    1399         $user_id = get_current_user_id();
    1400         $locked = wp_check_post_lock( $post->ID );
    1401         if ( ! $locked && 'draft' == $post->post_status && $user_id == $post->post_author ) {
    1402                 $id = edit_post();
    1403         } else { // Non drafts are not overwritten. The autosave is stored in a special post revision.
    1404                 $id = wp_create_post_autosave( $post->ID );
    1405                 if ( ! is_wp_error($id) )
    1406                         $id = $post->ID;
     1400                if ( 'auto-draft' == $_POST['post_status'] )
     1401                        $_POST['post_status'] = 'draft';
     1402
     1403                $saved_post_id = wp_create_post_autosave();
    14071404        }
    14081405
    1409         if ( is_wp_error($id) )
    1410                 wp_die( $id->get_error_message() );
     1406        if ( is_wp_error( $saved_post_id ) )
     1407                wp_die( $saved_post_id->get_error_message() );
    14111408
    1412         if ( ! $locked && $_POST['post_status'] == 'draft' && $user_id == $post->post_author ) {
    1413                 $url = add_query_arg( 'preview', 'true', get_permalink($id) );
    1414         } else {
    1415                 $nonce = wp_create_nonce('post_preview_' . $id);
    1416                 $args = array(
    1417                         'preview' => 'true',
    1418                         'preview_id' => $id,
    1419                         'preview_nonce' => $nonce,
    1420                 );
     1409        $query_args = array( 'preview' => 'true' );
    14211410
     1411        if ( $is_autosave && $saved_post_id ) {
     1412                $query_args['preview_id'] = $post->ID;
     1413                $query_args['preview_nonce'] = wp_create_nonce( 'post_preview_' . $post->ID );
     1414
    14221415                if ( isset( $_POST['post_format'] ) )
    1423                         $args['post_format'] = empty( $_POST['post_format'] ) ? 'standard' : sanitize_key( $_POST['post_format'] );
    1424 
    1425                 $url = add_query_arg( $args, get_permalink($id) );
     1416                        $query_args['post_format'] = empty( $_POST['post_format'] ) ? 'standard' : sanitize_key( $_POST['post_format'] );
    14261417        }
    14271418
     1419        $url = add_query_arg( $query_args, get_permalink( $post->ID ) );
    14281420        return apply_filters( 'preview_post_link', $url );
    14291421}
     1422
     1423/**
     1424 * Save a post submitted with XHR
     1425 *
     1426 * Intended for use with heartbeat and autosave.js
     1427 *
     1428 * @since 3.7
     1429 *
     1430 * @param $post_data Associative array of the submitted post data.
     1431 * @return mixed The value 0 or WP_Error on failure. The saved post ID on success.
     1432 *               Te ID can be either the draft post_id or the autosave revision post_id.
     1433 */
     1434function autosave( $post_data ) {
     1435        // Back-compat
     1436        if ( ! defined( 'DOING_AUTOSAVE' ) )
     1437                define( 'DOING_AUTOSAVE', true );
     1438
     1439        $post_id = (int) $post_data['post_id'];
     1440        $post_data['ID'] = $post_data['post_ID'] = $post_id;
     1441
     1442        if ( false === wp_verify_nonce( $post_data['_wpnonce'], 'update-post_' . $post_id ) )
     1443                return new WP_Error( 'invalid_nonce', __('ERROR: invalid post data.') );
     1444
     1445        $post = get_post( $post_id );
     1446
     1447        if ( ! current_user_can( 'edit_post', $post->ID ) )
     1448                return new WP_Error( 'edit_post', __('You are not allowed to edit this item.') );
     1449
     1450        if ( 'auto-draft' == $post->post_status )
     1451                $post_data['post_status'] = 'draft';
     1452
     1453        if ( $post_data['post_type'] != 'page' && ! empty( $post_data['catslist'] ) )
     1454                $post_data['post_category'] = explode( ',', $post_data['catslist'] );
     1455
     1456        if ( ! wp_check_post_lock( $post->ID ) && get_current_user_id() == $post->post_author && ( 'auto-draft' == $post->post_status || 'draft' == $post->post_status ) ) {
     1457                // Drafts and auto-drafts are just overwritten by autosave for the same user if the post is not locked
     1458                return edit_post( $post_data );
     1459        } else {
     1460                // Non drafts or other users drafts are not overwritten. The autosave is stored in a special post revision for each user.
     1461                return wp_create_post_autosave( $post_data );
     1462        }
     1463}
  • src/wp-admin/js/post.js

     
    1 var tagBox, commentsBox, editPermalink, makeSlugeditClickable, WPSetThumbnailHTML, WPSetThumbnailID, WPRemoveThumbnail, wptitlehint;
     1var tagBox, commentsBox, WPSetThumbnailHTML, WPSetThumbnailID, WPRemoveThumbnail, wptitlehint;
     2// Prevent fatal errors (back-compat)
     3makeSlugeditClickable = editPermalink = function(){};
    24
    35// return an array with any duplicate, whitespace or values removed
    46function array_unique_noempty(a) {
     
    265267                send['lock'] = lock;
    266268
    267269        data['wp-refresh-post-lock'] = send;
    268 });
    269270
    270 // Post locks: update the lock string or show the dialog if somebody has taken over editing
    271 $(document).on( 'heartbeat-tick.refresh-lock', function( e, data ) {
     271}).on( 'heartbeat-tick.refresh-lock', function( e, data ) {
     272        // Post locks: update the lock string or show the dialog if somebody has taken over editing
    272273        var received, wrap, avatar;
    273274
    274275        if ( data['wp-refresh-post-lock'] ) {
     
    279280                        wrap = $('#post-lock-dialog');
    280281
    281282                        if ( wrap.length && ! wrap.is(':visible') ) {
    282                                 if ( typeof autosave == 'function' ) {
    283                                         $(document).on('autosave-disable-buttons.post-lock', function() {
    284                                                 wrap.addClass('saving');
    285                                         }).on('autosave-enable-buttons.post-lock', function() {
     283                                if ( typeof wp != 'undefined' && wp.autosave ) {
     284                                        // Save the latest changes and disable
     285                                        $(document).one( 'heartbeat-tick', function() {
     286                                                wp.autosave.remote.disable();
    286287                                                wrap.removeClass('saving').addClass('saved');
    287                                                 window.onbeforeunload = null;
     288                                                $(window).off( 'beforeunload.autosave' );
    288289                                        });
    289290
    290                                         // Save the latest changes and disable
    291                                         if ( ! autosave() )
    292                                                 window.onbeforeunload = null;
    293 
    294                                         autosave = function(){};
     291                                        wrap.addClass('saving');
     292                                        wp.autosave.remote.triggerSave();
    295293                                }
    296294
    297295                                if ( received.lock_error.avatar_src ) {
     
    306304                        $('#active_post_lock').val( received.new_lock );
    307305                }
    308306        }
     307}).on( 'after-autosave.update-post-slug', function() {
     308        // create slug area only if not already there
     309        if ( ! $('#edit-slug-box > *').length ) {
     310                $.post( ajaxurl, {
     311                                action: 'sample-permalink',
     312                                post_id: $('#post_ID').val(),
     313                                new_title: typeof fullscreen != 'undefined' && fullscreen.settings.visible ? $('#wp-fullscreen-title').val() : $('#title').val(),
     314                                samplepermalinknonce: $('#samplepermalinknonce').val()
     315                        },
     316                        function( data ) {
     317                                if ( data != '-1' ) {
     318                                        $('#edit-slug-box').html(data);
     319                                }
     320                        }
     321                );
     322        }
    309323});
    310324
    311325}(jQuery));
     
    351365}(jQuery));
    352366
    353367jQuery(document).ready( function($) {
    354         var stamp, visibility, sticky = '', last = 0, co = $('#content');
     368        var stamp, visibility, sticky = '', last = 0, co = $('#content'), $editSlugWrap = $('#edit-slug-box'),
     369                postId = $('#post_ID').val() || 0;
    355370
    356371        postboxes.add_postbox_toggles(pagenow);
    357372
     
    680695        } // end submitdiv
    681696
    682697        // permalink
    683         if ( $('#edit-slug-box').length ) {
    684                 editPermalink = function(post_id) {
    685                         var i, c = 0, e = $('#editable-post-name'), revert_e = e.html(), real_slug = $('#post_name'), revert_slug = real_slug.val(), b = $('#edit-slug-buttons'), revert_b = b.html(), full = $('#editable-post-name-full').html();
     698        if ( $editSlugWrap.length ) {
     699                function editPermalink() {
     700                        var i, c = 0, e = $('#editable-post-name'), revert_e = e.html(), real_slug = $('#post_name'),
     701                                revert_slug = real_slug.val(), b = $('#edit-slug-buttons'), revert_b = b.html(),
     702                                full = $('#editable-post-name-full').html();
    686703
    687704                        $('#view-post-btn').hide();
    688705                        b.html('<a href="#" class="save button button-small">'+postL10n.ok+'</a> <a class="cancel" href="#">'+postL10n.cancel+'</a>');
     
    689706                        b.children('.save').click(function() {
    690707                                var new_slug = e.children('input').val();
    691708                                if ( new_slug == $('#editable-post-name-full').text() ) {
    692                                         return $('.cancel', '#edit-slug-buttons').click();
     709                                        return $('#edit-slug-buttons .cancel').click();
    693710                                }
    694711                                $.post(ajaxurl, {
    695712                                        action: 'sample-permalink',
    696                                         post_id: post_id,
     713                                        post_id: postId,
    697714                                        new_slug: new_slug,
    698715                                        new_title: $('#title').val(),
    699716                                        samplepermalinknonce: $('#samplepermalinknonce').val()
     
    707724                                        }
    708725                                        b.html(revert_b);
    709726                                        real_slug.val(new_slug);
    710                                         makeSlugeditClickable();
    711727                                        $('#view-post-btn').show();
    712728                                });
    713729                                return false;
    714730                        });
    715731
    716                         $('.cancel', '#edit-slug-buttons').click(function() {
     732                        $('#edit-slug-buttons .cancel').click(function() {
    717733                                $('#view-post-btn').show();
    718734                                e.html(revert_e);
    719735                                b.html(revert_b);
     
    743759                        }).focus();
    744760                }
    745761
    746                 makeSlugeditClickable = function() {
    747                         $('#editable-post-name').click(function() {
    748                                 $('#edit-slug-buttons').children('.edit-slug').click();
    749                         });
    750                 }
    751                 makeSlugeditClickable();
     762                $editSlugWrap.on( 'click', function( event ) {
     763                        var $target = $( event.target );
     764
     765                        if ( $target.is('#editable-post-name') || $target.hasClass('edit-slug') ) {
     766                                editPermalink();
     767                        }
     768                });
    752769        }
    753770
    754771        // word count
  • src/wp-admin/post.php

     
    296296        break;
    297297
    298298case 'preview':
    299         check_admin_referer( 'autosave', 'autosavenonce' );
     299        check_admin_referer( 'update-post_' . $post_id );
    300300
    301301        $url = post_preview();
    302302
  • src/wp-includes/js/autosave.js

     
    1 var autosave, autosaveLast = '', autosavePeriodical, autosaveDelayPreview = false, notSaved = true, blockSave = false, fullscreen, autosaveLockRelease = true;
     1window.wp = window.wp || {};
    22
    3 jQuery(document).ready( function($) {
     3( function( $, window ) {
     4        var $document = $(document), _disabled, _blockSave, _blockSaveTimeout;
    45
    5         if ( $('#wp-content-wrap').hasClass('tmce-active') && typeof switchEditors != 'undefined' ) {
    6                 autosaveLast = wp.autosave.getCompareString({
    7                         post_title : $('#title').val() || '',
    8                         content : switchEditors.pre_wpautop( $('#content').val() ) || '',
    9                         excerpt : $('#excerpt').val() || ''
    10                 });
    11         } else {
    12                 autosaveLast = wp.autosave.getCompareString();
    13         }
     6/**
     7 * Returns the data saved in both local and remote autosave
     8 *
     9 * @return mixed Object containing the post data or false
     10 */
     11wp.autosave = {
     12        getPostData: function( type ) {
     13                var post_name, parent_id, cats = [], data,
     14                        editor = typeof tinymce != 'undefined' && tinymce.get('content');
    1415
    15         autosavePeriodical = $.schedule({time: autosaveL10n.autosaveInterval * 1000, func: function() { autosave(); }, repeat: true, protect: true});
    16 
    17         //Disable autosave after the form has been submitted
    18         $("#post").submit(function() {
    19                 $.cancel(autosavePeriodical);
    20                 autosaveLockRelease = false;
    21         });
    22 
    23         $('input[type="submit"], a.submitdelete', '#submitpost').click(function(){
    24                 blockSave = true;
    25                 window.onbeforeunload = null;
    26                 $(':button, :submit', '#submitpost').each(function(){
    27                         var t = $(this);
    28                         if ( t.hasClass('button-primary') )
    29                                 t.addClass('button-primary-disabled');
    30                         else
    31                                 t.addClass('button-disabled');
    32                 });
    33                 if ( $(this).attr('id') == 'publish' )
    34                         $('#major-publishing-actions .spinner').show();
    35                 else
    36                         $('#minor-publishing .spinner').show();
    37         });
    38 
    39         window.onbeforeunload = function(){
    40                 var editor = typeof(tinymce) != 'undefined' ? tinymce.activeEditor : false, compareString;
    41 
    4216                if ( editor && ! editor.isHidden() ) {
    43                         if ( editor.isDirty() )
    44                                 return autosaveL10n.saveAlert;
    45                 } else {
    46                         if ( fullscreen && fullscreen.settings.visible ) {
    47                                 compareString = wp.autosave.getCompareString({
    48                                         post_title: $('#wp-fullscreen-title').val() || '',
    49                                         content: $('#wp_mce_fullscreen').val() || '',
    50                                         excerpt: $('#excerpt').val() || ''
    51                                 });
     17                        // Don't run while the tinymce spellcheck is on. It resets all found words.
     18                        if ( editor.plugins.spellchecker && editor.plugins.spellchecker.active ) {
     19                                return false;
    5220                        } else {
    53                                 compareString = wp.autosave.getCompareString();
     21                                tinymce.triggerSave();
    5422                        }
    55 
    56                         if ( compareString != autosaveLast )
    57                                 return autosaveL10n.saveAlert;
    5823                }
    59         };
    6024
    61         $(window).unload( function(e) {
    62                 if ( ! autosaveLockRelease )
    63                         return;
     25                data = {
     26                        post_id: $('#post_ID').val() || 0,
     27                        post_type: $('#post_type').val() || '',
     28                        post_author: $('#post_author').val() || '',
     29                        excerpt: $('#excerpt').val() || ''
     30                };
    6431
    65                 // unload fires (twice) on removing the Thickbox iframe. Make sure we process only the main document unload.
    66                 if ( e.target && e.target.nodeName != '#document' )
    67                         return;
    68 
    69                 $.ajax({
    70                         type: 'POST',
    71                         url: ajaxurl,
    72                         async: false,
    73                         data: {
    74                                 action: 'wp-remove-post-lock',
    75                                 _wpnonce: $('#_wpnonce').val(),
    76                                 post_ID: $('#post_ID').val(),
    77                                 active_post_lock: $('#active_post_lock').val()
    78                         }
    79                 });
    80         } );
    81 
    82         // preview
    83         $('#post-preview').click(function(){
    84                 if ( $('#auto_draft').val() == '1' && notSaved ) {
    85                         autosaveDelayPreview = true;
    86                         autosave();
    87                         return false;
     32                if ( typeof fullscreen != 'undefined' && fullscreen.settings.visible ) {
     33                        data['post_title'] = $('#wp-fullscreen-title').val() || '';
     34                        data['content'] = $('#wp_mce_fullscreen').val() || '';
     35                } else {
     36                        data['post_title'] = $('#title').val() || '';
     37                        data['content'] = $('#content').val() || '';
    8838                }
    89                 doPreview();
    90                 return false;
    91         });
    9239
    93         doPreview = function() {
    94                 $('input#wp-preview').val('dopreview');
    95                 $('form#post').attr('target', 'wp-preview').submit().attr('target', '');
     40                if ( type == 'local' )
     41                        return data;
    9642
    97                 /*
    98                  * Workaround for WebKit bug preventing a form submitting twice to the same action.
    99                  * https://bugs.webkit.org/show_bug.cgi?id=28633
    100                  */
    101                 var ua = navigator.userAgent.toLowerCase();
    102                 if ( ua.indexOf('safari') != -1 && ua.indexOf('chrome') == -1 ) {
    103                         $('form#post').attr('action', function(index, value) {
    104                                 return value + '?t=' + new Date().getTime();
    105                         });
    106                 }
    107 
    108                 $('input#wp-preview').val('');
    109         }
    110 
    111         // This code is meant to allow tabbing from Title to Post content.
    112         $('#title').on('keydown.editor-focus', function(e) {
    113                 var ed;
    114 
    115                 if ( e.which != 9 )
    116                         return;
    117 
    118                 if ( !e.ctrlKey && !e.altKey && !e.shiftKey ) {
    119                         if ( typeof(tinymce) != 'undefined' )
    120                                 ed = tinymce.get('content');
    121 
    122                         if ( ed && !ed.isHidden() ) {
    123                                 $(this).one('keyup', function(e){
    124                                         $('#content_tbl td.mceToolbar > a').focus();
    125                                 });
    126                         } else {
    127                                 $('#content').focus();
    128                         }
    129 
    130                         e.preventDefault();
    131                 }
    132         });
    133 
    134         // autosave new posts after a title is typed but not if Publish or Save Draft is clicked
    135         if ( '1' == $('#auto_draft').val() ) {
    136                 $('#title').blur( function() {
    137                         if ( !this.value || $('#auto_draft').val() != '1' )
    138                                 return;
    139                         delayed_autosave();
     43                $('input[id^="in-category-"]:checked').each( function() {
     44                        cats.push( this.value );
    14045                });
    141         }
     46                data['catslist'] = cats.join(',');
    14247
    143         // When connection is lost, keep user from submitting changes.
    144         $(document).on('heartbeat-connection-lost.autosave', function( e, error ) {
    145                 if ( 'timeout' === error ) {
    146                         var notice = $('#lost-connection-notice');
    147                         if ( ! wp.autosave.local.hasStorage ) {
    148                                 notice.find('.hide-if-no-sessionstorage').hide();
    149                         }
    150                         notice.show();
    151                         autosave_disable_buttons();
    152                 }
    153         }).on('heartbeat-connection-restored.autosave', function() {
    154                 $('#lost-connection-notice').hide();
    155                 autosave_enable_buttons();
    156         });
    157 });
     48                if ( post_name = $('#post_name').val() )
     49                        data['post_name'] = post_name;
    15850
    159 function autosave_parse_response( response ) {
    160         var res = wpAjax.parseAjaxResponse(response, 'autosave'), post_id, sup;
     51                if ( parent_id = $('#parent_id').val() )
     52                        data['parent_id'] = parent_id;
    16153
    162         if ( res && res.responses && res.responses.length ) {
    163                 if ( res.responses[0].supplemental ) {
    164                         sup = res.responses[0].supplemental;
     54                if ( $('#comment_status').prop('checked') )
     55                        data['comment_status'] = 'open';
    16556
    166                         jQuery.each( sup, function( selector, value ) {
    167                                 if ( selector.match(/^replace-/) )
    168                                         jQuery( '#' + selector.replace('replace-', '') ).val( value );
    169                         });
    170                 }
     57                if ( $('#ping_status').prop('checked') )
     58                        data['ping_status'] = 'open';
    17159
    172                 // if no errors: add slug UI and update autosave-message
    173                 if ( !res.errors ) {
    174                         if ( post_id = parseInt( res.responses[0].id, 10 ) )
    175                                 autosave_update_slug( post_id );
     60                if ( $('#auto_draft').val() == '1' )
     61                        data['auto_draft'] = '1';
    17662
    177                         if ( res.responses[0].data ) // update autosave message
    178                                 jQuery('.autosave-message').text( res.responses[0].data );
    179                 }
    180         }
     63                return data;
     64        },
    18165
    182         return res;
    183 }
    184 
    185 // called when autosaving pre-existing post
    186 function autosave_saved(response) {
    187         blockSave = false;
    188         autosave_parse_response(response); // parse the ajax response
    189         autosave_enable_buttons(); // re-enable disabled form buttons
    190 }
    191 
    192 // called when autosaving new post
    193 function autosave_saved_new(response) {
    194         blockSave = false;
    195         var res = autosave_parse_response(response), post_id;
    196 
    197         if ( res && res.responses.length && !res.errors ) {
    198                 // An ID is sent only for real auto-saves, not for autosave=0 "keepalive" saves
    199                 post_id = parseInt( res.responses[0].id, 10 );
    200 
    201                 if ( post_id ) {
    202                         notSaved = false;
    203                         jQuery('#auto_draft').val('0'); // No longer an auto-draft
     66        // Concatenate title, content and excerpt. Used to track changes when auto-saving.
     67        getCompareString: function( post_data ) {
     68                if ( typeof post_data === 'object' ) {
     69                        return ( post_data.post_title || '' ) + '::' + ( post_data.content || '' ) + '::' + ( post_data.excerpt || '' );
    20470                }
    20571
    206                 autosave_enable_buttons();
     72                return ( $('#title').val() || '' ) + '::' + ( $('#content').val() || '' ) + '::' + ( $('#excerpt').val() || '' );
     73        },
    20774
    208                 if ( autosaveDelayPreview ) {
    209                         autosaveDelayPreview = false;
    210                         doPreview();
    211                 }
    212         } else {
    213                 autosave_enable_buttons(); // re-enable disabled form buttons
    214         }
    215 }
     75        enableButtons: function() {
     76                $document.trigger('autosave-enable-buttons');
    21677
    217 function autosave_update_slug(post_id) {
    218         // create slug area only if not already there
    219         if ( 'undefined' != makeSlugeditClickable && jQuery.isFunction(makeSlugeditClickable) && !jQuery('#edit-slug-box > *').size() ) {
    220                 jQuery.post( ajaxurl, {
    221                                 action: 'sample-permalink',
    222                                 post_id: post_id,
    223                                 new_title: fullscreen && fullscreen.settings.visible ? jQuery('#wp-fullscreen-title').val() : jQuery('#title').val(),
    224                                 samplepermalinknonce: jQuery('#samplepermalinknonce').val()
    225                         },
    226                         function(data) {
    227                                 if ( data !== '-1' ) {
    228                                         var box = jQuery('#edit-slug-box');
    229                                         box.html(data);
    230                                         if (box.hasClass('hidden')) {
    231                                                 box.fadeIn('fast', function () {
    232                                                         box.removeClass('hidden');
    233                                                 });
    234                                         }
    235                                         makeSlugeditClickable();
    236                                 }
    237                         }
    238                 );
    239         }
    240 }
    241 
    242 function autosave_loading() {
    243         jQuery('.autosave-message').html(autosaveL10n.savingText);
    244 }
    245 
    246 function autosave_enable_buttons() {
    247         jQuery(document).trigger('autosave-enable-buttons');
    248         if ( ! wp.heartbeat || ! wp.heartbeat.hasConnectionError() ) {
    249                 // delay that a bit to avoid some rare collisions while the DOM is being updated.
    250                 setTimeout(function(){
    251                         var parent = jQuery('#submitpost');
    252                         parent.find(':button, :submit').removeAttr('disabled');
     78                if ( ! wp.heartbeat || ! wp.heartbeat.hasConnectionError() ) {
     79                        var parent = $('#submitpost');
     80                        parent.find(':button, :submit, a.submitdelete, #post-preview').prop('disabled', false).removeClass('button-disabled');
    25381                        parent.find('.spinner').hide();
    254                 }, 500);
    255         }
    256 }
     82                }
     83        },
    25784
    258 function autosave_disable_buttons() {
    259         jQuery(document).trigger('autosave-disable-buttons');
    260         jQuery('#submitpost').find(':button, :submit').prop('disabled', true);
    261         // Re-enable 5 sec later. Just gives autosave a head start to avoid collisions.
    262         setTimeout( autosave_enable_buttons, 5000 );
    263 }
     85        disableButtons: function() {
     86                $document.trigger('autosave-disable-buttons');
    26487
    265 function delayed_autosave() {
    266         setTimeout(function(){
    267                 if ( blockSave )
    268                         return;
    269                 autosave();
    270         }, 200);
    271 }
     88                var parent = $('#submitpost');
     89                parent.find(':button, :submit, a.submitdelete, #post-preview').prop('disabled', true).addClass('button-disabled');
     90                parent.find('#save-action .spinner').show();
    27291
    273 autosave = function() {
    274         var post_data = wp.autosave.getPostData(),
    275                 compareString,
    276                 successCallback;
    277 
    278         blockSave = true;
    279 
    280         // post_data.content cannot be retrieved at the moment
    281         if ( ! post_data.autosave )
    282                 return false;
    283 
    284         // No autosave while thickbox is open (media buttons)
    285         if ( jQuery("#TB_window").css('display') == 'block' )
    286                 return false;
    287 
    288         compareString = wp.autosave.getCompareString( post_data );
    289 
    290         // Nothing to save or no change.
    291         if ( compareString == autosaveLast )
    292                 return false;
    293 
    294         autosaveLast = compareString;
    295         jQuery(document).triggerHandler('wpcountwords', [ post_data["content"] ]);
    296 
    297         // Disable buttons until we know the save completed.
    298         autosave_disable_buttons();
    299 
    300         if ( post_data["auto_draft"] == '1' ) {
    301                 successCallback = autosave_saved_new; // new post
    302         } else {
    303                 successCallback = autosave_saved; // pre-existing post
     92                // Re-enable 5 sec later. Just gives autosave a head start to avoid collisions.
     93                setTimeout( wp.autosave.enableButtons, 5000 );
    30494        }
     95};
    30596
    306         jQuery.ajax({
    307                 data: post_data,
    308                 beforeSend: autosave_loading,
    309                 type: "POST",
    310                 url: ajaxurl,
    311                 success: successCallback
    312         });
    313 
    314         return true;
    315 }
    316 
    31797// Autosave in localStorage
    31898// set as simple object/mixin for now
    319 window.wp = window.wp || {};
    320 wp.autosave = wp.autosave || {};
    321 
    322 (function($){
    323 // Returns the data for saving in both localStorage and autosaves to the server
    324 wp.autosave.getPostData = function() {
    325         var ed = typeof tinymce != 'undefined' ? tinymce.activeEditor : null, post_name, parent_id, cats = [],
    326                 data = {
    327                         action: 'autosave',
    328                         autosave: true,
    329                         post_id: $('#post_ID').val() || 0,
    330                         autosavenonce: $('#autosavenonce').val() || '',
    331                         post_type: $('#post_type').val() || '',
    332                         post_author: $('#post_author').val() || '',
    333                         excerpt: $('#excerpt').val() || ''
    334                 };
    335 
    336         if ( ed && !ed.isHidden() ) {
    337                 // Don't run while the tinymce spellcheck is on. It resets all found words.
    338                 if ( ed.plugins.spellchecker && ed.plugins.spellchecker.active ) {
    339                         data.autosave = false;
    340                         return data;
    341                 } else {
    342                         if ( 'mce_fullscreen' == ed.id )
    343                                 tinymce.get('content').setContent(ed.getContent({format : 'raw'}), {format : 'raw'});
    344 
    345                         tinymce.triggerSave();
    346                 }
    347         }
    348 
    349         if ( typeof fullscreen != 'undefined' && fullscreen.settings.visible ) {
    350                 data['post_title'] = $('#wp-fullscreen-title').val() || '';
    351                 data['content'] = $('#wp_mce_fullscreen').val() || '';
    352         } else {
    353                 data['post_title'] = $('#title').val() || '';
    354                 data['content'] = $('#content').val() || '';
    355         }
    356 
    357         /*
    358         // We haven't been saving tags with autosave since 2.8... Start again?
    359         $('.the-tags').each( function() {
    360                 data[this.name] = this.value;
    361         });
    362         */
    363 
    364         $('input[id^="in-category-"]:checked').each( function() {
    365                 cats.push(this.value);
    366         });
    367         data['catslist'] = cats.join(',');
    368 
    369         if ( post_name = $('#post_name').val() )
    370                 data['post_name'] = post_name;
    371 
    372         if ( parent_id = $('#parent_id').val() )
    373                 data['parent_id'] = parent_id;
    374 
    375         if ( $('#comment_status').prop('checked') )
    376                 data['comment_status'] = 'open';
    377 
    378         if ( $('#ping_status').prop('checked') )
    379                 data['ping_status'] = 'open';
    380 
    381         if ( $('#auto_draft').val() == '1' )
    382                 data['auto_draft'] = '1';
    383 
    384         return data;
    385 };
    386 
    387 // Concatenate title, content and excerpt. Used to track changes when auto-saving.
    388 wp.autosave.getCompareString = function( post_data ) {
    389         if ( typeof post_data === 'object' ) {
    390                 return ( post_data.post_title || '' ) + '::' + ( post_data.content || '' ) + '::' + ( post_data.excerpt || '' );
    391         }
    392 
    393         return ( $('#title').val() || '' ) + '::' + ( $('#content').val() || '' ) + '::' + ( $('#excerpt').val() || '' );
    394 };
    395 
    39699wp.autosave.local = {
    397 
    398100        lastSavedData: '',
    399101        blog_id: 0,
    400102        hasStorage: false,
     
    502204        save: function( data ) {
    503205                var result = false, post_data, compareString;
    504206
    505                 if ( ! data ) {
    506                         post_data = wp.autosave.getPostData();
    507                 } else {
     207                if ( data ) {
    508208                        post_data = this.getData() || {};
    509209                        $.extend( post_data, data );
    510                         post_data.autosave = true;
     210                } else {
     211                        post_data = wp.autosave.getPostData('local');
     212                        // Cannot get the post data at the moment
     213                        if ( ! post_data )
     214                                return false;
    511215                }
    512216
    513                 // Cannot get the post data at the moment
    514                 if ( ! post_data.autosave )
    515                         return false;
    516 
    517217                compareString = wp.autosave.getCompareString( post_data );
    518218
    519219                // If the content, title and excerpt did not change since the last save, don't save again
     
    697397        }
    698398};
    699399
     400// Autosave on the server
     401wp.autosave.remote = {
     402        releaseLock: true,
     403        autosaveLast: '',
     404        nextTime: 0,
     405
     406        init: function() {
     407                var self = this, $submitpost = $('#submitpost');
     408
     409                $document.on( 'heartbeat-send.autosave', function( event, data ) {
     410                        var autosaveData = self.getData();
     411
     412                        if ( autosaveData ) {
     413                                data.autosave = autosaveData;
     414                        }
     415                }).on( 'heartbeat-tick.autosave', function( event, data ) {
     416                        if ( data.autosave ) {
     417                                self.response( data.autosave );
     418                        }
     419                }).on('heartbeat-connection-lost.autosave', function( event, error ) {
     420                        // When connection is lost, keep user from submitting changes.
     421                        if ( 'timeout' === error ) {
     422                                var notice = $('#lost-connection-notice');
     423                                if ( ! wp.autosave.local.hasStorage ) {
     424                                        notice.find('.hide-if-no-sessionstorage').hide();
     425                                }
     426                                notice.show();
     427                                wp.autosave.disableButtons();
     428                        }
     429                }).on('heartbeat-connection-restored.autosave', function() {
     430                        $('#lost-connection-notice').hide();
     431                        wp.autosave.enableButtons();
     432                });
     433
     434                $(window).on( 'beforeunload.autosave', function() {
     435                        var editor = typeof(tinymce) != 'undefined' && tinymce.activeEditor, compareString;
     436
     437                        if ( editor && ! editor.isHidden() ) {
     438                                if ( editor.isDirty() )
     439                                        return autosaveL10n.saveAlert;
     440                        } else {
     441                                if ( fullscreen && fullscreen.settings.visible ) {
     442                                        compareString = wp.autosave.getCompareString({
     443                                                post_title: $('#wp-fullscreen-title').val() || '',
     444                                                content: $('#wp_mce_fullscreen').val() || '',
     445                                                excerpt: $('#excerpt').val() || ''
     446                                        });
     447                                } else {
     448                                        compareString = wp.autosave.getCompareString();
     449                                }
     450
     451                                if ( compareString != self.autosaveLast )
     452                                        return autosaveL10n.saveAlert;
     453                        }
     454                }).on( 'unload.autosave', function( event ) {
     455                        if ( ! self.releaseLock )
     456                                return;
     457
     458                        // unload fires (twice) on removing the Thickbox iframe. Make sure we process only the main document unload.
     459                        if ( event.target && event.target.nodeName != '#document' )
     460                                return;
     461
     462                        $.ajax({
     463                                type: 'POST',
     464                                url: ajaxurl,
     465                                async: false,
     466                                data: {
     467                                        action: 'wp-remove-post-lock',
     468                                        _wpnonce: $('#_wpnonce').val(),
     469                                        post_ID: $('#post_ID').val(),
     470                                        active_post_lock: $('#active_post_lock').val()
     471                                }
     472                        });
     473                });
     474
     475                $document.ready( function() {
     476                        self._schedule();
     477
     478                        if ( $('#wp-content-wrap').hasClass('tmce-active') && typeof switchEditors != 'undefined' ) {
     479                                self.autosaveLast = wp.autosave.getCompareString({
     480                                        post_title : $('#title').val() || '',
     481                                        content : switchEditors.pre_wpautop( $('#content').val() ) || '',
     482                                        excerpt : $('#excerpt').val() || ''
     483                                });
     484                        } else {
     485                                self.autosaveLast = wp.autosave.getCompareString();
     486                        }
     487
     488                        // The form is being submitted by the user
     489                        $submitpost.find( 'input[type="submit"], a.submitdelete' ).on( 'click.autosave', function( event ) {
     490                                var $this = $(this);
     491
     492                                if ( $this.prop('disabled') ) {
     493                                        event.preventDefault(); // For the "Move to Trash" link
     494                                        return;
     495                                }
     496
     497                                self.blockSave();
     498                                self.releaseLock = false;
     499                                $(window).off( 'beforeunload.autosave' );
     500
     501                                $submitpost.find('a.submitdelete, #post-preview').addClass('button-disabled');
     502
     503                                if ( $this.attr('id') == 'publish' )
     504                                        $submitpost.find('#major-publishing-actions .spinner').show();
     505                                else
     506                                        $submitpost.find('#minor-publishing .spinner').show();
     507                        });
     508
     509                        $('#post-preview').on( 'click.post-preview', function( event ) {
     510                                if ( ! $(this).prop('disabled') ) {
     511                                        self.doPreview();
     512                                }
     513                                event.preventDefault();
     514                        });
     515
     516                        // This code is meant to allow tabbing from Title to Post content.
     517                        $('#title').on( 'keydown.editor-focus', function( event ) {
     518                                var editor;
     519
     520                                if ( event.which == 9 && ! event.ctrlKey && ! event.altKey && ! event.shiftKey ) {
     521                                        if ( typeof(tinymce) != 'undefined' )
     522                                                editor = tinymce.get('content');
     523
     524                                        if ( editor && ! editor.isHidden() ) {
     525                                                $(this).one( 'keyup', function() {
     526                                                        $('#content_tbl td.mceToolbar > a').focus();
     527                                                });
     528                                        } else {
     529                                                $('#content').focus();
     530                                        }
     531
     532                                        event.preventDefault();
     533                                }
     534                        });
     535
     536                        // Autosave new posts after a title is typed
     537                        if ( $('#auto_draft').val() ) {
     538                                $('#title').blur( function() {
     539                                        if ( ! this.value || $('#auto_draft').val() != '1' )
     540                                                return;
     541
     542                                        self.triggerSave();
     543                                });
     544                        }
     545                });
     546        },
     547
     548        // Block saving for the next 15 sec.
     549        blockSave: function() {
     550                _blockSave = true;
     551                window.clearTimeout( _blockSaveTimeout );
     552                _blockSaveTimeout = window.setTimeout( function() {
     553                        _blockSave = false;
     554                }, 15000 );
     555        },
     556
     557        // Submit the form saving a draft or an autosave, and show a preview in a new tab
     558        doPreview: function() {
     559                this.blockSave();
     560                $('input#wp-preview').val('dopreview');
     561                $('form#post').attr('target', 'wp-preview').submit().attr('target', '');
     562
     563                // Workaround for WebKit bug preventing a form submitting twice to the same action.
     564                // https://bugs.webkit.org/show_bug.cgi?id=28633
     565                var ua = navigator.userAgent.toLowerCase();
     566                if ( ua.indexOf('safari') != -1 && ua.indexOf('chrome') == -1 ) {
     567                        $('form#post').attr( 'action', function( index, value ) {
     568                                return value + '?t=' + new Date().getTime();
     569                        });
     570                }
     571
     572                $('input#wp-preview').val('');
     573        },
     574
     575        // Runs on heartbeat-response
     576        response: function( data ) {
     577                this._schedule();
     578                _blockSave = false;
     579                this.autosaveLast = this.lastCompareString;
     580                this.lastCompareString = '';
     581
     582                $(document).trigger( 'after-autosave', [data] );
     583                $('#auto_draft').val(''); // No longer an auto-draft
     584                $('.autosave-message').text( data.message );
     585
     586                wp.autosave.enableButtons(); // re-enable disabled form buttons
     587        },
     588
     589        disable: function() {
     590                _disabled = true;
     591        },
     592
     593        _schedule: function() {
     594                this.nextTime = ( new Date() ).getTime() + ( autosaveL10n.autosaveInterval * 1000 ) || 60000;
     595        },
     596
     597        // Set heartbeat to connect fast (once) and save on the next tick.
     598        triggerSave: function() {
     599                this.nextTime = 0;
     600                wp.heartbeat.interval( 'fast', 1 );
     601        },
     602
     603        // Runs on 'heartbeat-send'
     604        getData: function() {
     605                var compareString, postData;
     606
     607                if ( _disabled || _blockSave )
     608                        return false;
     609
     610                if ( ( new Date() ).getTime() < this.nextTime )
     611                        return false;
     612
     613                postData = wp.autosave.getPostData();
     614
     615                // post_data.content cannot be retrieved at the moment
     616                if ( ! postData )
     617                        return false;
     618
     619                compareString = wp.autosave.getCompareString( postData );
     620
     621                // Nothing to save or no change.
     622                if ( compareString == this.autosaveLast )
     623                        return false;
     624
     625                this.blockSave();
     626                wp.autosave.disableButtons();
     627                this.lastCompareString = compareString;
     628
     629                $(document).trigger( 'wpcountwords', [ postData['content'] ] );
     630                $(document).trigger( 'before-autosave', [ postData ] );
     631
     632                $('.autosave-message').text( autosaveL10n.savingText );
     633                postData._wpnonce = $('#_wpnonce').val() || '';
     634
     635                return postData;
     636        }
     637};
     638
    700639wp.autosave.local.init();
     640wp.autosave.remote.init();
    701641
    702 }(jQuery));
     642}( jQuery, window ));
  • src/wp-includes/js/heartbeat.js

     
    183183                                timeout: 30000, // throw an error if not completed after 30 sec.
    184184                                data: send,
    185185                                dataType: 'json'
     186                        }).always( function() {
     187                                connecting = false;
     188                                next();
    186189                        }).done( function( response, textStatus, jqXHR ) {
    187190                                var new_interval;
    188191
     
    209212                                // do this last, can trigger the next XHR if connection time > 5 sec. and new_interval == 'fast'
    210213                                if ( new_interval )
    211214                                        self.interval.call( self, new_interval );
    212                         }).always( function() {
    213                                 connecting = false;
    214                                 next();
    215215                        }).fail( function( jqXHR, textStatus, error ) {
    216216                                errorstate( textStatus || 'unknown' );
    217217                                self.error( jqXHR, textStatus, error );
  • src/wp-includes/revision.php

     
    215215 *
    216216 * @param int|object|array $post Post ID, post object OR post array.
    217217 * @param bool $autosave Optional. Is the revision an autosave?
    218  * @return mixed Null or 0 if error, new revision ID if success.
     218 * @return mixed WP_Error or 0 if error, new revision ID if success.
    219219 */
    220220function _wp_put_post_revision( $post = null, $autosave = false ) {
    221221        if ( is_object($post) )
     
    223223        elseif ( !is_array($post) )
    224224                $post = get_post($post, ARRAY_A);
    225225
    226         if ( !$post || empty($post['ID']) )
    227                 return;
     226        if ( ! $post || empty($post['ID']) )
     227                return new WP_Error( 'invalid_post', __( 'Invalid post ID.' ) );
    228228
    229229        if ( isset($post['post_type']) && 'revision' == $post['post_type'] )
    230230                return new WP_Error( 'post_type', __( 'Cannot create a revision of a revision' ) );