WordPress.org

Make WordPress Core

Ticket #6043: 6043.diff

File 6043.diff, 30.3 KB (added by mdawaffe, 6 years ago)

first pass

  • wp-includes/version.php

     
    1616 * 
    1717 * @global int $wp_db_version 
    1818 */ 
    19 $wp_db_version = 6846; 
     19$wp_db_version = 7098; 
    2020 
    2121?> 
  • wp-includes/js/autosave.js

     
    11var autosaveLast = ''; 
    22var autosavePeriodical; 
    33 
    4 function autosave_start_timer() { 
    5         autosaveLast = jQuery('#post #title').val()+jQuery('#post #content').val(); 
    6         // Keep autosave_interval in sync with edit_post(). 
    7         autosavePeriodical = jQuery.schedule({time: autosaveL10n.autosaveInterval * 1000, func: autosave, repeat: true, protect: true}); 
     4jQuery(function($) { 
     5        autosaveLast = $('#post #title').val()+$('#post #content').val(); 
     6        autosavePeriodical = $.schedule({time: autosaveL10n.autosaveInterval * 1000, func: function() { autosave(); }, repeat: true, protect: true}); 
    87 
    98        //Disable autosave after the form has been submitted 
    10         jQuery("#post #submit").submit(function() { jQuery.cancel(autosavePeriodical); }); 
    11         jQuery("#post #save").click(function() { jQuery.cancel(autosavePeriodical); }); 
    12         jQuery("#post #submit").click(function() { jQuery.cancel(autosavePeriodical); }); 
    13         jQuery("#post #publish").click(function() { jQuery.cancel(autosavePeriodical); }); 
    14         jQuery("#post #deletepost").click(function() { jQuery.cancel(autosavePeriodical); }); 
     9        $("#post").submit(function() { $.cancel(autosavePeriodical); }); 
    1510 
    16         // Autosave early on for a new post 
    17         jQuery("#content").keypress(function() { 
    18                 if ( 1 === ( jQuery(this).val().length % 15 ) && 1 > parseInt(jQuery("#post_ID").val(),10) ) 
     11        // Autosave early on for a new post.  Why?  Should this only be run once? 
     12        $("#content").keypress(function() { 
     13                if ( 1 === ( $(this).val().length % 15 ) && 1 > parseInt($("#post_ID").val(),10) ) 
    1914                        setTimeout(autosave, 5000); 
    2015        }); 
    21 } 
    22 addLoadEvent(autosave_start_timer) 
     16}); 
    2317 
    24 function autosave_cur_time() { 
    25         var now = new Date(); 
    26         return "" + ((now.getHours() >12) ? now.getHours() -12 : now.getHours()) +  
    27         ((now.getMinutes() < 10) ? ":0" : ":") + now.getMinutes() + 
    28         ((now.getSeconds() < 10) ? ":0" : ":") + now.getSeconds(); 
     18// called when autosaving pre-existing post 
     19function autosave_saved(response) { 
     20        var res = wpAjax.parseAjaxResponse(response, 'autosave'); // parse the ajax response 
     21        var message = ''; 
     22 
     23        if ( res && res.responses.length ) { 
     24                message = res.responses[0].data; // The saved message or error. 
     25                // someone else is editing: disable autosave, set errors 
     26                if ( res.responses[0].supplemental && 'disable' == res.responses[0].supplemental['disable_autosave'] ) { 
     27                        autosave = function() {}; 
     28                        res = { errors: true }; 
     29                } 
     30 
     31                // if no errors: add preview link and slug UI 
     32                if ( !res.errors ) { 
     33                        var postID = parseInt( res.responses[0].id ); 
     34                        if ( !isNaN(postID) && postID > 0 ) { 
     35                                autosave_update_preview_link(postID); 
     36                                autosave_update_slug(postID); 
     37                        } 
     38                } 
     39        } 
     40        if ( message ) { jQuery('#autosave').html(message); } // update autosave message 
     41        autosave_enable_buttons(); // re-enable disabled form buttons 
     42        return res; 
    2943} 
    3044 
     45// called when autosaving new post 
    3146function autosave_update_post_ID(response) { 
    32         var res = parseInt(response); 
    33         var message; 
     47        var res = autosave_saved(response); // parse the ajax response do the above 
    3448 
    35         if(isNaN(res)) { 
    36                 message = autosaveL10n.errorText.replace(/%response%/g, response); 
    37         } else if( res > 0 ) { 
    38                 message = autosaveL10n.saveText.replace(/%time%/g, autosave_cur_time()); 
    39                 jQuery('#post_ID').attr({name: "post_ID"}); 
    40                 jQuery('#post_ID').val(res); 
    41                 // We need new nonces 
    42                 jQuery.post(autosaveL10n.requestFile, { 
    43                         action: "autosave-generate-nonces", 
    44                         post_ID: res, 
    45                         autosavenonce: jQuery('#autosavenonce').val(), 
    46                         post_type: jQuery('#post_type').val() 
    47                 }, function(html) { 
    48                         jQuery('#_wpnonce').val(html); 
    49                 }); 
    50                 jQuery('#hiddenaction').val('editpost'); 
    51         } else { 
    52                 message = autosaveL10n.failText; 
     49        // if no errors: update post_ID from the temporary value, grab new save-nonce for that new ID 
     50        if ( res && res.responses.length && !res.errors ) { 
     51                var postID = parseInt( res.responses[0].id ); 
     52                if ( !isNaN(postID) && postID > 0 ) { 
     53                        if ( postID == parseInt(jQuery('#post_ID').val()) ) { return; } // no need to do this more than once 
     54                        jQuery('#post_ID').attr({name: "post_ID"}); 
     55                        jQuery('#post_ID').val(postID); 
     56                        // We need new nonces 
     57                        jQuery.post(autosaveL10n.requestFile, { 
     58                                action: "autosave-generate-nonces", 
     59                                post_ID: postID, 
     60                                autosavenonce: jQuery('#autosavenonce').val(), 
     61                                post_type: jQuery('#post_type').val() 
     62                        }, function(html) { 
     63                                jQuery('#_wpnonce').val(html); 
     64                        }); 
     65                        jQuery('#hiddenaction').val('editpost'); 
     66                } 
    5367        } 
    54         jQuery('#autosave').html(message); 
    55         autosave_update_preview_link(res); 
    56         autosave_update_slug(res); 
    57         autosave_enable_buttons(); 
    5868} 
    5969 
    6070function autosave_update_preview_link(post_id) { 
    6171        // Add preview button if not already there 
    62         if ( ! jQuery('#previewview > *').get()[0] ) { 
     72        if ( !jQuery('#previewview > *').size() ) { 
    6373                var post_type = jQuery('#post_type').val(); 
    6474                var previewText = 'page' == post_type ? autosaveL10n.previewPageText : autosaveL10n.previewPostText; 
    6575                jQuery.post(autosaveL10n.requestFile, { 
     
    7484 
    7585function autosave_update_slug(post_id) { 
    7686        // create slug area only if not already there 
    77         if ( 'undefined' != typeof make_slugedit_clickable && ! jQuery('#edit-slug-box > *').get()[0] ) { 
    78                 jQuery.post(slugL10n.requestFile, { 
    79                         action: 'sample-permalink', 
    80                         post_id: post_id, 
    81                         samplepermalinknonce: jQuery('#samplepermalinknonce').val()}, function(data) { 
     87        if ( jQuery.isFunction(make_slugedit_clickable) && !jQuery('#edit-slug-box > *').size() ) { 
     88                jQuery.post( 
     89                        slugL10n.requestFile, 
     90                        { 
     91                                action: 'sample-permalink', 
     92                                post_id: post_id, 
     93                                samplepermalinknonce: jQuery('#samplepermalinknonce').val() 
     94                        }, 
     95                        function(data) { 
    8296                                jQuery('#edit-slug-box').html(data); 
    8397                                make_slugedit_clickable(); 
    84                         }); 
     98                        } 
     99                ); 
    85100        } 
    86101} 
    87102 
    88103function autosave_loading() { 
    89         jQuery('#autosave').html(autosaveL10n.savingText); 
     104        jQuery('#autosave').html('<div class="updated"><p>' + autosaveL10n.savingText + '</p></div>'); 
    90105} 
    91106 
    92 function autosave_saved(response) { 
    93         var res = parseInt(response); 
    94         var message; 
    95  
    96         if(isNaN(res)) { 
    97                 message = autosaveL10n.errorText.replace(/%response%/g, response); 
    98         } else { 
    99                 message = autosaveL10n.saveText.replace(/%time%/g, autosave_cur_time()); 
    100         } 
    101         jQuery('#autosave').html(message); 
    102         autosave_update_preview_link(res); 
    103         autosave_update_slug(res); 
    104         autosave_enable_buttons(); 
     107function autosave_enable_buttons() { 
     108        jQuery("#submitpost :button:disabled, #submitpost :submit:disabled").attr('disabled', ''); 
    105109} 
    106110 
    107111function autosave_disable_buttons() { 
    108         jQuery("#post #save:enabled").attr('disabled', 'disabled'); 
    109         jQuery("#post #submit:enabled").attr('disabled', 'disabled'); 
    110         jQuery("#post #publish:enabled").attr('disabled', 'disabled'); 
    111         jQuery("#post #deletepost:enabled").attr('disabled', 'disabled'); 
    112         setTimeout('autosave_enable_buttons();', 1000); // Re-enable 1 sec later.  Just gives autosave a head start to avoid collisions. 
     112        jQuery("#submitpost :button:enabled, #submitpost :submit:enabled").attr('disabled', 'disabled'); 
     113        setTimeout(autosave_enable_buttons, 1000); // Re-enable 1 sec later.  Just gives autosave a head start to avoid collisions. 
    113114} 
    114115 
    115 function autosave_enable_buttons() { 
    116         jQuery("#post #save:disabled").attr('disabled', ''); 
    117         jQuery("#post #submit:disabled").attr('disabled', ''); 
    118         jQuery("#post #publish:disabled").attr('disabled', ''); 
    119         jQuery("#post #deletepost:disabled").attr('disabled', ''); 
    120 } 
    121  
    122 function autosave() { 
    123         var rich = ( (typeof tinyMCE != "undefined") && tinyMCE.activeEditor && ! tinyMCE.activeEditor.isHidden() ) ? true : false; 
     116var autosave = function() { 
     117        // (bool) is rich editor enabled and active 
     118        var rich = (typeof tinyMCE != "undefined") && tinyMCE.activeEditor && !tinyMCE.activeEditor.isHidden(); 
    124119        var post_data = { 
    125                         action: "autosave", 
    126                         post_ID:  jQuery("#post_ID").val() || 0, 
    127                         post_title: jQuery("#title").val() || "", 
    128                         autosavenonce: jQuery('#autosavenonce').val(), 
    129                         tags_input: jQuery("#tags-input").val() || "", 
    130                         post_type: jQuery('#post_type').val() || "" 
    131                 }; 
     120                action: "autosave", 
     121                post_ID:  jQuery("#post_ID").val() || 0, 
     122                post_title: jQuery("#title").val() || "", 
     123                autosavenonce: jQuery('#autosavenonce').val(), 
     124                tags_input: jQuery("#tags-input").val() || "", 
     125                post_type: jQuery('#post_type').val() || "", 
     126                autosave: 1 
     127        }; 
    132128 
     129        // We always send the ajax request in order to keep the post lock fresh. 
     130        // This (bool) tells whether or not to write the post to the DB during the ajax request. 
     131        var doAutoSave = true; 
     132 
    133133        /* Gotta do this up here so we can check the length when tinyMCE is in use */ 
    134         if ( rich ) { 
    135                 // Don't run while the TinyMCE spellcheck is on. 
    136                 if ( tinyMCE.activeEditor.plugins.spellchecker && tinyMCE.activeEditor.plugins.spellchecker.active ) return; 
    137                 tinyMCE.triggerSave(); 
    138         }  
     134        if ( rich ) { tinyMCE.triggerSave(); } 
    139135         
    140136        post_data["content"] = jQuery("#content").val(); 
    141137        if ( jQuery('#post_name').val() ) 
    142138                post_data["post_name"] = jQuery('#post_name').val(); 
    143139 
     140        // Nothing to save or no change. 
    144141        if(post_data["post_title"].length==0 || post_data["content"].length==0 || post_data["post_title"] + post_data["content"] == autosaveLast) { 
    145                 return; 
     142                doAutoSave = false 
    146143        } 
    147144 
    148145        autosave_disable_buttons(); 
    149146 
     147        var origStatus = jQuery('#original_post_status').val(); 
     148        if ( 'draft' != origStatus ) // autosave currently only turned on for drafts 
     149                doAutoSave = false; 
     150 
    150151        autosaveLast = jQuery("#title").val()+jQuery("#content").val(); 
    151152        goodcats = ([]); 
    152153        jQuery("[@name='post_category[]']:checked").each( function(i) { 
     
    161162        if( jQuery("#excerpt")) 
    162163                post_data["excerpt"] = jQuery("#excerpt").val(); 
    163164 
    164         if ( rich )  
    165         tinyMCE.triggerSave(); 
    166      
    167         post_data["content"] = jQuery("#content").val(); 
     165        // Don't run while the TinyMCE spellcheck is on.  Why?  Who knows. 
     166        if ( rich && tinyMCE.activeEditor.plugins.spellchecker && tinyMCE.activeEditor.plugins.spellchecker.active ) { 
     167                doAutoSave = false; 
     168        } 
    168169 
    169170        if(parseInt(post_data["post_ID"]) < 1) { 
    170171                post_data["temp_ID"] = post_data["post_ID"]; 
    171                 jQuery.ajaxSetup({ 
    172                         success: function(html) { autosave_update_post_ID(html); } 
    173                 }); 
     172                var successCallback = autosave_update_post_ID; // new post 
    174173        } else { 
    175                 jQuery.ajaxSetup({ 
    176                         success: function(html) { autosave_saved(html); } 
    177                 }); 
     174                var successCallback = autosave_saved; // pre-existing post 
    178175        } 
     176 
     177        if ( !doAutoSave ) { 
     178                post_data['autosave'] = 0; 
     179        } 
     180 
    179181        jQuery.ajax({ 
    180182                data: post_data, 
    181                 beforeSend: function() { autosave_loading() }, 
     183                beforeSend: doAutoSave ? autosave_loading : null, 
    182184                type: "POST", 
    183                 url: autosaveL10n.requestFile 
     185                url: autosaveL10n.requestFile, 
     186                success: successCallback 
    184187        }); 
    185188} 
  • wp-includes/js/wp-lists.js

     
    22var currentFormEl = false; 
    33var fs = {add:'ajaxAdd',del:'ajaxDel',dim:'ajaxDim',process:'process',recolor:'recolor'}; 
    44 
    5 wpAjax = { 
    6         unserialize: function( s ) { 
    7                 var r = {}; if ( !s ) { return r; } 
    8                 var q = s.split('?'); if ( q[1] ) { s = q[1]; } 
    9                 var pp = s.split('&'); 
    10                 for ( var i in pp ) { 
    11                         if ( $.isFunction(pp.hasOwnProperty) && !pp.hasOwnProperty(i) ) { continue; } 
    12                         var p = pp[i].split('='); 
    13                         r[p[0]] = p[1]; 
    14                 } 
    15                 return r; 
    16         }, 
    17         parseAjaxResponse: function( x, r, e ) { // 1 = good, 0 = strange (bad data?), -1 = you lack permission 
    18                 var re = $('#' + r).html(''); 
    19                 if ( x && typeof x == 'object' && x.getElementsByTagName('wp_ajax') ) { 
    20                         var errs = $('wp_error', x); 
    21                         if ( errs.size() ) { 
    22                                 var err = ''; 
    23                                 errs.each( function() { 
    24                                         var code = $(this).attr('code'); 
    25                                         if ( formField = $('wp_error_data[code="' + code + '"] form-field', x).text() ) 
    26                                                 code = formField; 
    27                                         wpAjax.invalidateForm( $('#' + e + ' :input[name="' + code + '"]' ).parents('.form-field:first') ); 
    28                                         err += '<p>' + this.firstChild.nodeValue + '</p>'; 
    29                                 } ); 
    30                                 return !re.html( '<div class="error">' + err + '</div>' ); 
    31                         } 
    32                         return true; 
    33                 } 
    34                 if ( isNaN(x) ) { return !re.html('<div class="error"><p>' + x + '</p></div>'); } 
    35                 x = parseInt(x,10); 
    36                 if ( -1 == x ) { return !re.html('<div class="error"><p>You do not have permission to do that.</p></div>'); } 
    37                 else if ( 0 === x ) { return !re.html('<div class="error"><p>AJAX is teh b0rked.</p></div>'); } 
    38                 return true; 
    39         }, 
    40         invalidateForm: function( jQ ) { 
    41                 jQ.addClass( 'form-invalid' ).change( function() { $(this).removeClass( 'form-invalid' ); } ); 
    42         } 
    43 }; 
    44  
    455var wpList = { 
    466        settings: { 
    477                url: wpListL10n.url, type: 'POST', 
     
    12787                if ( !s.data.match(/_ajax_nonce=[a-f0-9]+/) ) { return true; } 
    12888 
    12989                s.success = function(r) { 
    130                         if ( !wpAjax.parseAjaxResponse(r, s.response, s.element) ) { return false; } 
     90                        var res = wpAjax.parseAjaxResponse(r, s.response, s.element); 
     91                        if ( !res || res.errors ) { return false; } 
    13192 
    132                         $(s.what + ' response_data', r).each( function() { 
    133                                 var t = $(this); 
    134                                 wpList.add.call( list, t.text(), $.extend( {}, s, { // this.firstChild.nodevalue 
    135                                         pos: t.parent().attr( 'position' ) || 0, 
    136                                         id: t.parent().attr( 'id' ) || 0, 
    137                                         oldId: t.parent().attr( 'old_id' ) || null 
     93                        jQuery.each( res.responses, function() { 
     94                                wpList.add.call( list, this.data, $.extend( {}, s, { // this.firstChild.nodevalue 
     95                                        pos: this.position || 0, 
     96                                        id: this.id || 0, 
     97                                        oldId: this.oldId || null 
    13898                                } ) ); 
    13999                        } ); 
    140100 
    141101                        if ( $.isFunction(s.addAfter) ) { 
    142102                                var o = this.complete; 
    143103                                this.complete = function(x,st) { 
    144                                         var _s = $.extend( { xml: x, status: st }, s ); 
     104                                        var _s = $.extend( { xml: x, status: st, parsed: res }, s ); 
    145105                                        s.addAfter( r, _s ); 
    146106                                        if ( $.isFunction(o) ) { o(x,st); } 
    147107                                }; 
     
    194154                } 
    195155 
    196156                s.success = function(r) { 
    197                         if ( !wpAjax.parseAjaxResponse(r, s.response, s.element) ) { 
     157                        var res = wpAjax.parseAjaxResponse(r, s.response, s.element); 
     158                        if ( !res || res.errors ) { 
    198159                                element.stop().css( 'backgroundColor', '#FF3333' ).show().queue( function() { list.wpList.recolor(); $(this).dequeue(); } ); 
    199160                                return false; 
    200161                        } 
     
    202163                                var o = this.complete; 
    203164                                this.complete = function(x,st) { 
    204165                                        element.queue( function() { 
    205                                                 var _s = $.extend( { xml: x, status: st }, s ); 
     166                                                var _s = $.extend( { xml: x, status: st, parsed: res }, s ); 
    206167                                                s.delAfter( r, _s ); 
    207168                                                if ( $.isFunction(o) ) { o(x,st); } 
    208169                                        } ).dequeue(); 
     
    256217                if ( !s.data._ajax_nonce ) { return true; } 
    257218 
    258219                s.success = function(r) { 
    259                         if ( !wpAjax.parseAjaxResponse(r, s.response, s.element) ) { 
     220                        var res = wpAjax.parseAjaxResponse(r, s.response, s.element); 
     221                        if ( !res || res.errors ) { 
    260222                                element.stop().css( 'backgroundColor', '#FF3333' )[isClass?'removeClass':'addClass'](s.dimClass).show().queue( function() { list.wpList.recolor(); $(this).dequeue(); } ); 
    261223                                return false; 
    262224                        } 
     
    264226                                var o = this.complete; 
    265227                                this.complete = function(x,st) { 
    266228                                        element.queue( function() { 
    267                                                 var _s = $.extend( { xml: x, status: st }, s ); 
     229                                                var _s = $.extend( { xml: x, status: st, parsed: res }, s ); 
    268230                                                s.dimAfter( r, _s ); 
    269231                                                if ( $.isFunction(o) ) { o(x,st); } 
    270232                                        } ).dequeue(); 
  • wp-includes/js/wp-ajax-response.js

     
     1wpAjax = jQuery.extend( { 
     2        unserialize: function( s ) { 
     3                var r = {}; if ( !s ) { return r; } 
     4                var q = s.split('?'); if ( q[1] ) { s = q[1]; } 
     5                var pp = s.split('&'); 
     6                for ( var i in pp ) { 
     7                        if ( jQuery.isFunction(pp.hasOwnProperty) && !pp.hasOwnProperty(i) ) { continue; } 
     8                        var p = pp[i].split('='); 
     9                        r[p[0]] = p[1]; 
     10                } 
     11                return r; 
     12        }, 
     13        parseAjaxResponse: function( x, r, e ) { // 1 = good, 0 = strange (bad data?), -1 = you lack permission 
     14                var parsed = {}; 
     15                var re = jQuery('#' + r).html(''); 
     16                if ( x && typeof x == 'object' && x.getElementsByTagName('wp_ajax') ) { 
     17                        parsed.responses = []; 
     18                        parsed.errors = false; 
     19                        var err = ''; 
     20                        jQuery('response', x).each( function() { 
     21                                var th = jQuery(this); 
     22                                var child = jQuery(this.firstChild); 
     23                                var response = { action: th.attr('action'), what: child.get(0).nodeName, id: child.attr('id'), oldId: child.attr('old_id'), position: child.attr('position') }; 
     24                                response.data = jQuery( 'response_data', child ).text(); 
     25                                response.supplemental = {}; 
     26                                if ( !jQuery( 'supplemental', child ).children().each( function() { 
     27                                        response.supplemental[this.nodeName] = jQuery(this).text(); 
     28                                } ).size() ) { response.supplemental = false } 
     29                                response.errors = []; 
     30                                if ( !jQuery('wp_error', child).each( function() { 
     31                                        var code = jQuery(this).attr('code'); 
     32                                        var anError = { code: code, message: this.firstChild.nodeValue, data: false }; 
     33                                        var errorData = jQuery('wp_error_data[code="' + code + '"]', x); 
     34                                        if ( errorData ) { anError.data = errorData.get(); } 
     35                                        var formField = jQuery( 'form-field', errorData ).text(); 
     36                                        if ( formField ) { code = formField; } 
     37                                        if ( e ) { wpAjax.invalidateForm( jQuery('#' + e + ' :input[name="' + code + '"]' ).parents('.form-field:first') ); } 
     38                                        err += '<p>' + anError.message + '</p>'; 
     39                                        response.errors.push( anError ); 
     40                                        parsed.errors = true; 
     41                                } ).size() ) { response.errors = false; } 
     42                                parsed.responses.push( response ); 
     43                        } ); 
     44                        if ( err.length ) { re.html( '<div class="error">' + err + '</div>' ); } 
     45                        return parsed; 
     46                } 
     47                if ( isNaN(x) ) { return !re.html('<div class="error"><p>' + x + '</p></div>'); } 
     48                x = parseInt(x,10); 
     49                if ( -1 == x ) { return !re.html('<div class="error"><p>' + this.noPerm + '</p></div>'); } 
     50                else if ( 0 === x ) { return !re.html('<div class="error"><p>' + this.broken  + '</p></div>'); } 
     51                return true; 
     52        }, 
     53        invalidateForm: function( jQ ) { 
     54                jQ.addClass( 'form-invalid' ).change( function() { jQuery(this).removeClass( 'form-invalid' ); } ); 
     55        } 
     56}, wpAjax || { noPerm: 'You do not have permission to do that.', broken: 'AJAX is teh b0rked.' } ); 
  • wp-includes/classes.php

     
    777777                } 
    778778 
    779779                $s = ''; 
    780                 if ( (array) $supplemental ) 
     780                if ( (array) $supplemental ) { 
    781781                        foreach ( $supplemental as $k => $v ) 
    782782                                $s .= "<$k><![CDATA[$v]]></$k>"; 
     783                        $s = "<supplemental>$s</supplemental>"; 
     784                } 
    783785 
    784786                if ( false === $action ) 
    785787                        $action = $_POST['action']; 
  • wp-includes/script-loader.php

     
    4141                 
    4242                $this->add( 'prototype', '/wp-includes/js/prototype.js', false, '1.6'); 
    4343 
    44                 $this->add( 'autosave', '/wp-includes/js/autosave.js', array('jquery', 'schedule'), '20080221'); 
     44                $this->add( 'wp-ajax-response', '/wp-includes/js/wp-ajax-response.js', array('jquery'), '20080229' . mt_rand() ); 
     45                $this->localize( 'wp-ajax-response', 'wpAjax', array( 
     46                        'noPerm' => 'You do not have permission to do that.', 
     47                        'broken' => 'AJAX is teh b0rked.' 
     48                ) ); 
     49 
     50                $this->add( 'autosave', '/wp-includes/js/autosave.js', array('schedule', 'wp-ajax-response'), '20080221' . mt_rand()); 
    4551                $this->localize( 'autosave', 'autosaveL10n', array( 
    46                         'autosaveInterval' => apply_filters('autosave_interval', '60'), 
    47                         'errorText' => __('Error: %response%'), 
    48                         'failText' => __('Error: Autosave Failed.'), 
    49                         'previewPageText' => __('Preview this Page'), 
    50                         'previewPostText' => __('Preview this Post'), 
    51                         'saveText' => __('Saved at %time%.'), 
     52                        'autosaveInterval' => get_option( 'autosave_interval' ), 
     53                        'previewPageText' => __('View this Page'), 
     54                        'previewPostText' => __('View this Post'), 
    5255                        'requestFile' => get_option( 'siteurl' ) . '/wp-admin/admin-ajax.php', 
    53                         'savingText' => __('Saving Draft...') 
     56                        'savingText' => __('Saving&#8230;') 
    5457                ) ); 
    5558 
    5659                $this->add( 'wp-ajax', '/wp-includes/js/wp-ajax.js', array('prototype'), '20070306'); 
     
    6164                        'whoaText' => __("Slow down, I'm still sending your data!") 
    6265                ) ); 
    6366 
    64                 $this->add( 'wp-lists', '/wp-includes/js/wp-lists.js', array('jquery'), '20080228' ); 
     67                $this->add( 'wp-lists', '/wp-includes/js/wp-lists.js', array('wp-ajax-response'), '20080228' . mt_rand()); 
    6568                $this->localize( 'wp-lists', 'wpListL10n', array( 
    6669                        'url' => get_option( 'siteurl' ) . '/wp-admin/admin-ajax.php' 
    6770                ) ); 
  • wp-admin/admin-ajax.php

     
    470470        break; 
    471471case 'autosave' : // The name of this action is hardcoded in edit_post() 
    472472        check_ajax_referer( 'autosave', 'autosavenonce' ); 
     473        global $current_user; 
     474 
    473475        $_POST['post_content'] = $_POST['content']; 
    474476        $_POST['post_excerpt'] = $_POST['excerpt']; 
    475477        $_POST['post_status'] = 'draft'; 
     
    478480        if($_POST['post_type'] == 'page' || empty($_POST['post_category'])) 
    479481                unset($_POST['post_category']); 
    480482 
     483        $do_autosave = (bool) $_POST['autosave']; 
     484        $do_lock = true; 
     485 
     486        $data = '<div class="updated"><p>' . sprintf( __('Saved at %s.'), date( __('g:i:s a'), current_time( 'timestamp', true ) ) ) . '</p></div>'; 
     487 
     488        $supplemental = array(); 
     489 
     490        $id = 0; 
    481491        if($_POST['post_ID'] < 0) { 
    482492                $_POST['temp_ID'] = $_POST['post_ID']; 
    483                 $id = wp_write_post(); 
    484                 if( is_wp_error($id) ) 
    485                         die($id->get_error_message()); 
    486                 else 
    487                         die("$id"); 
     493                if ( $do_autosave ) 
     494                        $id = wp_write_post(); 
    488495        } else { 
    489496                $post_ID = (int) $_POST['post_ID']; 
    490497                $_POST['ID'] = $post_ID; 
    491498                $post = get_post($post_ID); 
     499 
     500                if ( $last = wp_check_post_lock( $post->ID ) ) { 
     501                        $do_autosave = $do_lock = false; 
     502 
     503                        $last_user = get_userdata( $last ); 
     504                        $last_user_name = $last_user ? $last_user->display_name : __( 'Someone' ); 
     505                        $data = new WP_Error( 'locked', sprintf( 
     506                                $_POST['post_type'] == 'page' ? __( 'Autosave disabled: %s is currently editing this page.' ) : __( 'Autosave disabled: %s is currently editing this post.' ), 
     507                                wp_specialchars( $last_user_name ) 
     508                        ) ); 
     509 
     510                        $supplemental['disable_autosave'] = 'disable'; 
     511                } 
     512 
    492513                if ( 'page' == $post->post_type ) { 
    493514                        if ( !current_user_can('edit_page', $post_ID) ) 
    494515                                die(__('You are not allowed to edit this page.')); 
     
    496517                        if ( !current_user_can('edit_post', $post_ID) ) 
    497518                                die(__('You are not allowed to edit this post.')); 
    498519                } 
    499                 wp_update_post($_POST); 
     520                if ( $do_autosave ) 
     521                        $id = wp_update_post($_POST); 
     522                else 
     523                        $id = $post->ID; 
    500524        } 
    501         die('0'); 
    502 break; 
     525 
     526        if ( $do_lock && $id && is_numeric($id) ) 
     527                wp_set_post_lock( $id ); 
     528 
     529        $x = new WP_Ajax_Response( array( 
     530                'what' => 'autosave', 
     531                'id' => $id, 
     532                'data' => $id ? $data : '', 
     533                'supplemental' => $supplemental 
     534        ) ); 
     535        $x->send(); 
     536        break; 
    503537case 'autosave-generate-nonces' : 
    504538        check_ajax_referer( 'autosave', 'autosavenonce' ); 
    505539        $ID = (int) $_POST['post_ID']; 
  • wp-admin/wp-admin.css

     
    10331033        margin-right: 8px; 
    10341034} 
    10351035 
     1036#poststuff #autosave { 
     1037        margin: 0; 
     1038        padding: 0; 
     1039} 
     1040 
     1041#poststuff #autosave div.updated, #poststuff #autosave div.error { 
     1042        margin: 0 8px 10px 20px; 
     1043} 
     1044 
    10361045#poststuff .inside { 
    10371046        margin: 0 12px 15px; 
    10381047        font-size: 11px; 
     
    14061415 
    14071416#the-comment-list td.comment p { 
    14081417        margin-left: 8px; 
    1409 } 
    1410  No newline at end of file 
     1418} 
  • wp-admin/includes/post.php

     
    1818                $post =& get_post( $post_ID ); 
    1919                $now = time(); 
    2020                $then = strtotime($post->post_date_gmt . ' +0000'); 
    21                 // Keep autosave_interval in sync with autosave-js.php. 
    22                 $delta = apply_filters( 'autosave_interval', 120 ) / 2; 
     21                $delta = get_option( 'autosave_interval' ) / 2; 
    2322                if ( ($now - $then) < $delta ) 
    2423                        return $post_ID; 
    2524        } 
     
    619618        return $return; 
    620619} 
    621620 
     621// false: not locked or locked by current user 
     622// int: user ID of user with lock 
     623function wp_check_post_lock( $post_id ) { 
     624        global $current_user; 
     625 
     626        if ( !$post = get_post( $post_id ) ) 
     627                return false; 
     628 
     629        $lock = get_post_meta( $post->ID, '_edit_lock', true ); 
     630        $last = get_post_meta( $post->ID, '_edit_last', true ); 
     631 
     632        $time_window = apply_filters( 'wp_check_post_lock_window', get_option( 'autosave_interval' ) * 2 ); 
     633 
     634        if ( $lock && $lock > time() - $time_window && $last != $current_user->ID ) 
     635                return $last; 
     636        return false; 
     637} 
     638 
     639function wp_set_post_lock( $post_id ) { 
     640        global $current_user; 
     641        if ( !$post = get_post( $post_id ) ) 
     642                return false; 
     643        if ( !$current_user || !$current_user->ID ) 
     644                return false; 
     645         
     646        $now = time(); 
     647 
     648        if ( !add_post_meta( $post->ID, '_edit_lock', $now, true ) ) 
     649                update_post_meta( $post->ID, '_edit_lock', $now ); 
     650        if ( !add_post_meta( $post->ID, '_edit_last', $current_user->ID, true ) ) 
     651                update_post_meta( $post->ID, '_edit_last', $current_user->ID ); 
     652} 
     653 
    622654?> 
  • wp-admin/includes/upgrade.php

     
    198198        if ( $wp_current_db_version < 6124 ) 
    199199                upgrade_230_old_tables(); 
    200200 
    201         if ( $wp_current_db_version < 6689 ) 
     201        if ( $wp_current_db_version < 7098 ) 
    202202                upgrade_250(); 
    203203 
    204204        maybe_disable_automattic_widgets(); 
     
    725725        if ( $wp_current_db_version < 6689 ) { 
    726726                populate_roles_250(); 
    727727        } 
     728 
     729        add_option('autosave_interval', 60); 
    728730} 
    729731 
    730732// The functions we use to actually do stuff 
  • wp-admin/post.php

     
    6666                wp_enqueue_script('editor'); 
    6767        wp_enqueue_script('thickbox'); 
    6868        wp_enqueue_script('media-upload'); 
    69  
    70         if ( 'draft' == $post->post_status ) 
     69        if ( $last = wp_check_post_lock( $post->ID ) ) { 
     70                $last_user = get_userdata( $last ); 
     71                $last_user_name = $last_user ? $last_user->display_name : __('Somebody'); 
     72                $message = sprintf( __( '%s is currently editing this post' ), wp_specialchars( $last_user_name ) ); 
     73                $message = str_replace( "'", "\'", "<div class='error'><p>$message</p></div>" ); 
     74                add_action('admin_notices', create_function( '', "echo '$message';" ) ); 
     75        } else { 
     76                wp_set_post_lock( $post->ID ); 
    7177                wp_enqueue_script('autosave'); 
     78        } 
    7279 
    7380        require_once('admin-header.php'); 
    7481 
  • wp-admin/edit-page-form.php

     
    3636<input type="hidden" id="originalaction" name="originalaction" value="<?php echo $form_action ?>" /> 
    3737<?php echo $form_extra ?> 
    3838<input type="hidden" id="post_type" name="post_type" value="<?php echo $post->post_type ?>" /> 
     39<input type="hidden" id="original_post_status" name="original_post_status" value="<?php echo $post->post_status ?>" /> 
    3940<input name="referredby" type="hidden" id="referredby" value="<?php 
    4041if ( url_to_postid(wp_get_referer()) == $post_ID ) 
    4142        echo 'redo'; 
     
    169170<?php wp_nonce_field( 'samplepermalink', 'samplepermalinknonce', false ); ?> 
    170171</div> 
    171172 
    172 <p class="submit"> 
     173<div id="autosave"></div> 
    173174 
    174 <span id="autosave"></span> 
    175  
    176 </p> 
    177  
    178175<?php do_meta_boxes('page', 'normal', $post); ?> 
    179176 
    180177<?php do_action('edit_page_form'); ?> 
  • wp-admin/edit-form-advanced.php

     
    5555<input type="hidden" id="originalaction" name="originalaction" value="<?php echo $form_action ?>" /> 
    5656<input type="hidden" name="post_author" value="<?php echo attribute_escape( $post->post_author ); ?>" /> 
    5757<input type="hidden" id="post_type" name="post_type" value="<?php echo $post->post_type ?>" /> 
     58<input type="hidden" id="original_post_status" name="original_post_status" value="<?php echo $post->post_status ?>" /> 
     59<input name="referredby" type="hidden" id="referredby" value="<?php 
     60if ( !empty($_REQUEST['popupurl']) ) 
     61        echo clean_url(stripslashes($_REQUEST['popupurl'])); 
     62else if ( url_to_postid(wp_get_referer()) == $post_ID ) 
     63        echo 'redo'; 
     64else 
     65        echo clean_url(stripslashes(wp_get_referer())); 
     66?>" /> 
    5867 
    5968<?php echo $form_extra ?> 
    6069<?php if ((isset($post->post_title) && '' == $post->post_title) || (isset($_GET['message']) && 2 > $_GET['message'])) : ?> 
     
    189198<?php echo $form_pingback ?> 
    190199<?php echo $form_prevstatus ?> 
    191200 
    192 <p class="submit"> 
     201<div id="autosave"></div> 
    193202 
    194 <span id="autosave"></span> 
    195  
    196  
    197 <input name="referredby" type="hidden" id="referredby" value="<?php 
    198 if ( !empty($_REQUEST['popupurl']) ) 
    199         echo clean_url(stripslashes($_REQUEST['popupurl'])); 
    200 else if ( url_to_postid(wp_get_referer()) == $post_ID ) 
    201         echo 'redo'; 
    202 else 
    203         echo clean_url(stripslashes(wp_get_referer())); 
    204 ?>" /></p> 
    205  
    206203<div id="tagsdiv" class="postbox <?php echo postbox_classes('tagsdiv', 'post'); ?>"> 
    207204<h3><?php _e('Tags'); ?></h3> 
    208205<div class="inside"> 
  • wp-admin/page.php

     
    5757                wp_enqueue_script('editor'); 
    5858        wp_enqueue_script('thickbox'); 
    5959        wp_enqueue_script('media-upload'); 
    60  
    61         if ( 'draft' == $post->post_status ) 
     60        if ( $last = wp_check_post_lock( $post->ID ) ) { 
     61                $last_user = get_userdata( $last ); 
     62                $last_user_name = $last_user ? $last_user->display_name : __('Somebody'); 
     63                $message = sprintf( __( '%s is currently editing this page' ), wp_specialchars( $last_user_name ) ); 
     64                $message = str_replace( "'", "\'", "<div class='error'><p>$message</p></div>" ); 
     65                add_action('admin_notices', create_function( '', "echo '$message';" ) ); 
     66        } else { 
     67                wp_set_post_lock( $post->ID ); 
    6268                wp_enqueue_script('autosave'); 
     69        } 
    6370 
    6471        require_once('admin-header.php'); 
    6572