WordPress.org

Make WordPress Core

Ticket #23220: 23220-6.patch

File 23220-6.patch, 18.9 KB (added by azaozz, 2 years ago)
  • wp-admin/includes/ajax-actions.php

     
    10501050 
    10511051        $id = $revision_id = 0; 
    10521052 
    1053         $post_ID = (int) $_POST['post_ID']; 
    1054         $_POST['ID'] = $post_ID; 
    1055         $post = get_post($post_ID); 
     1053        $post_id = (int) $_POST['post_id']; 
     1054        $_POST['ID'] = $_POST['post_ID'] = $post_id; 
     1055        $post = get_post($post_id); 
    10561056        if ( 'auto-draft' == $post->post_status ) 
    10571057                $_POST['post_status'] = 'draft'; 
    10581058 
     
    10681068        } 
    10691069 
    10701070        if ( 'page' == $post->post_type ) { 
    1071                 if ( !current_user_can('edit_page', $post_ID) ) 
     1071                if ( !current_user_can('edit_page', $post->ID) ) 
    10721072                        wp_die( __( 'You are not allowed to edit this page.' ) ); 
    10731073        } else { 
    1074                 if ( !current_user_can('edit_post', $post_ID) ) 
     1074                if ( !current_user_can('edit_post', $post->ID) ) 
    10751075                        wp_die( __( 'You are not allowed to edit this post.' ) ); 
    10761076        } 
    10771077 
  • wp-admin/includes/misc.php

     
    586586        return $response; 
    587587} 
    588588add_filter( 'heartbeat_received', 'wp_check_locked_posts', 10, 2 ); 
     589 
     590/** 
     591 * Output the HTML for restoring the post data from DOM storage 
     592 * 
     593 * @since 3.6 
     594 * @access private 
     595 */ 
     596function _local_storage_notice() { 
     597        global $current_screen; 
     598 
     599        if ( empty($current_screen) || 'post' != $current_screen->id ) 
     600                return; 
     601 
     602        ?> 
     603        <div id="local-storage-notice" class="hidden"> 
     604        <p class="local-restore"> 
     605                <?php _e('The backup of this post in your browser is different from the version below.'); ?> 
     606                <a class="restore-backup" href="#"><?php _e('Restore the backup.'); ?></a> 
     607        </p> 
     608        <p class="undo-restore hidden"> 
     609                <?php _e('Post restored successfully.'); ?> 
     610                <a class="undo-restore-backup" href="#"><?php _e('Undo.'); ?></a> 
     611        </p> 
     612        </div> 
     613        <?php 
     614} 
     615add_action( 'admin_footer', '_local_storage_notice' ); 
  • wp-includes/js/admin-bar.js

     
    132132                                }, 100); 
    133133                        } 
    134134                }); 
     135 
     136                // Empty sessionStorage on logging out 
     137                if ( 'sessionStorage' in window ) { 
     138                        $('#wp-admin-bar-logout a').click( function() { 
     139                                try { 
     140                                        for ( var key in sessionStorage ) { 
     141                                                if ( key.indexOf('wp-autosave-') != -1 ) 
     142                                                        sessionStorage.removeItem(key); 
     143                                        } 
     144                                } catch(e) {} 
     145                        }); 
     146                } 
    135147        }); 
    136148} else { 
    137149        (function(d, w) { 
     
    310322                                addEvent(aB, 'click', function(e) { 
    311323                                        scrollToTop( e.target || e.srcElement ); 
    312324                                }); 
     325 
     326                                addEvent( document.getElementById('wp-admin-bar-logout'), 'click', function() { 
     327                                        if ( 'sessionStorage' in window ) { 
     328                                                try { 
     329                                                        for ( var key in sessionStorage ) { 
     330                                                                if ( key.indexOf('wp-autosave-') != -1 ) 
     331                                                                        sessionStorage.removeItem(key); 
     332                                                        } 
     333                                                } catch(e) {} 
     334                                        } 
     335                                }); 
    313336                        } 
    314337 
    315338                        if ( w.location.hash ) 
  • wp-includes/js/autosave.js

     
    187187function autosave_saved_new(response) { 
    188188        blockSave = false; 
    189189        var res = autosave_parse_response(response), postID; 
     190 
    190191        if ( res && res.responses.length && !res.errors ) { 
    191192                // An ID is sent only for real auto-saves, not for autosave=0 "keepalive" saves 
    192193                postID = parseInt( res.responses[0].id, 10 ); 
     
    257258 
    258259        autosave_disable_buttons(); 
    259260 
    260         post_data = { 
    261                 action: "autosave", 
    262                 post_ID:  jQuery("#post_ID").val() || 0, 
    263                 autosavenonce: jQuery('#autosavenonce').val(), 
    264                 post_type: jQuery('#post_type').val() || "", 
    265                 autosave: 1 
    266         }; 
     261        post_data = wp.autosave.getPostData(); 
    267262 
    268         jQuery('.tags-input').each( function() { 
    269                 post_data[this.name] = this.value; 
    270         } ); 
    271  
    272263        // We always send the ajax request in order to keep the post lock fresh. 
    273264        // This (bool) tells whether or not to write the post to the DB during the ajax request. 
    274         doAutoSave = true; 
     265        doAutoSave = post_data.autosave; 
    275266 
    276267        // No autosave while thickbox is open (media buttons) 
    277268        if ( jQuery("#TB_window").css('display') == 'block' ) 
    278269                doAutoSave = false; 
    279270 
    280         /* Gotta do this up here so we can check the length when tinymce is in use */ 
    281         if ( rich && doAutoSave ) { 
    282                 ed = tinymce.activeEditor; 
    283                 // Don't run while the tinymce spellcheck is on. It resets all found words. 
    284                 if ( ed.plugins.spellchecker && ed.plugins.spellchecker.active ) { 
    285                         doAutoSave = false; 
    286                 } else { 
    287                         if ( 'mce_fullscreen' == ed.id || 'wp_mce_fullscreen' == ed.id ) 
    288                                 tinymce.get('content').setContent(ed.getContent({format : 'raw'}), {format : 'raw'}); 
    289                         tinymce.triggerSave(); 
    290                 } 
    291         } 
    292  
    293         if ( fullscreen && fullscreen.settings.visible ) { 
    294                 post_data["post_title"] = jQuery('#wp-fullscreen-title').val() || ''; 
    295                 post_data["content"] = jQuery("#wp_mce_fullscreen").val() || ''; 
    296         } else { 
    297                 post_data["post_title"] = jQuery("#title").val() || ''; 
    298                 post_data["content"] = jQuery("#content").val() || ''; 
    299         } 
    300  
    301         if ( jQuery('#post_name').val() ) 
    302                 post_data["post_name"] = jQuery('#post_name').val(); 
    303  
    304271        // Nothing to save or no change. 
    305272        if ( ( post_data["post_title"].length == 0 && post_data["content"].length == 0 ) || post_data["post_title"] + post_data["content"] == autosaveLast ) { 
    306273                doAutoSave = false; 
    307274        } 
    308275 
    309         origStatus = jQuery('#original_post_status').val(); 
    310  
    311         goodcats = ([]); 
    312         jQuery("[name='post_category[]']:checked").each( function(i) { 
    313                 goodcats.push(this.value); 
    314         } ); 
    315         post_data["catslist"] = goodcats.join(","); 
    316  
    317         if ( jQuery("#comment_status").prop("checked") ) 
    318                 post_data["comment_status"] = 'open'; 
    319         if ( jQuery("#ping_status").prop("checked") ) 
    320                 post_data["ping_status"] = 'open'; 
    321         if ( jQuery("#excerpt").size() ) 
    322                 post_data["excerpt"] = jQuery("#excerpt").val(); 
    323         if ( jQuery("#post_author").size() ) 
    324                 post_data["post_author"] = jQuery("#post_author").val(); 
    325         if ( jQuery("#parent_id").val() ) 
    326                 post_data["parent_id"] = jQuery("#parent_id").val(); 
    327         post_data["user_ID"] = jQuery("#user-id").val(); 
    328         if ( jQuery('#auto_draft').val() == '1' ) 
    329                 post_data["auto_draft"] = '1'; 
    330  
    331276        if ( doAutoSave ) { 
    332277                autosaveLast = post_data["post_title"] + post_data["content"]; 
    333278                jQuery(document).triggerHandler('wpcountwords', [ post_data["content"] ]); 
     
    350295                success: successCallback 
    351296        }); 
    352297} 
     298 
     299// Autosave in localStorage 
     300// set as simple object/mixin for now 
     301window.wp = window.wp || {}; 
     302wp.autosave = wp.autosave || {}; 
     303 
     304(function($){ 
     305// Returns the data for saving in both localStorage and autosaves to the server 
     306wp.autosave.getPostData = function() { 
     307        var ed = typeof tinymce != 'undefined' ? tinymce.activeEditor : null, post_name, parent_id, cats = [], 
     308                data = { 
     309                        action: 'autosave', 
     310                        autosave: true, 
     311                        post_id: $('#post_ID').val() || 0, 
     312                        autosavenonce: $('#autosavenonce').val() || '', 
     313                        post_type: $('#post_type').val() || '', 
     314                        post_author: $('#post_author').val() || '', 
     315                        excerpt: $('#excerpt').val() || '' 
     316                }; 
     317 
     318        if ( ed && !ed.isHidden() ) { 
     319                // Don't run while the tinymce spellcheck is on. It resets all found words. 
     320                if ( ed.plugins.spellchecker && ed.plugins.spellchecker.active ) { 
     321                        data.autosave = false; 
     322                        return data; 
     323                } else { 
     324                        if ( 'mce_fullscreen' == ed.id ) 
     325                                tinymce.get('content').setContent(ed.getContent({format : 'raw'}), {format : 'raw'}); 
     326 
     327                        tinymce.triggerSave(); 
     328                } 
     329        } 
     330 
     331        if ( typeof fullscreen != 'undefined' && fullscreen.settings.visible ) { 
     332                data['post_title'] = $('#wp-fullscreen-title').val() || ''; 
     333                data['content'] = $('#wp_mce_fullscreen').val() || ''; 
     334        } else { 
     335                data['post_title'] = $('#title').val() || ''; 
     336                data['content'] = $('#content').val() || ''; 
     337        } 
     338 
     339        /* 
     340        // We haven't been saving tags with autosave since 2.8... Start again? 
     341        $('.the-tags').each( function() { 
     342                data[this.name] = this.value; 
     343        }); 
     344        */ 
     345 
     346        $('input[id^="in-category-"]:checked').each( function() { 
     347                cats.push(this.value); 
     348        }); 
     349        data['catslist'] = cats.join(','); 
     350 
     351        if ( post_name = $('#post_name').val() ) 
     352                data['post_name'] = post_name; 
     353 
     354        if ( parent_id = $('#parent_id').val() ) 
     355                data['parent_id'] = parent_id; 
     356 
     357        if ( $('#comment_status').prop('checked') ) 
     358                data['comment_status'] = 'open'; 
     359 
     360        if ( $('#ping_status').prop('checked') ) 
     361                data['ping_status'] = 'open'; 
     362 
     363        if ( $('#auto_draft').val() == '1' ) 
     364                data['auto_draft'] = '1'; 
     365 
     366        return data; 
     367} 
     368 
     369wp.autosave.local = { 
     370 
     371        lastsaveddata: '', 
     372        blog_id: 0, 
     373        ajaxurl: window.ajaxurl || 'wp-admin/admin-ajax.php', 
     374        hasStorage: false, 
     375 
     376        // Check if the browser supports sessionStorage and it's not disabled 
     377        checkStorage: function() { 
     378                var test = Math.random(), result = false; 
     379 
     380                try { 
     381                        sessionStorage.setItem('wp-test', test); 
     382                        result = sessionStorage.getItem('wp-test') == test; 
     383                        sessionStorage.removeItem('wp-test'); 
     384                } catch(e) {} 
     385 
     386                this.hasStorage = result; 
     387                return result; 
     388    }, 
     389 
     390        /** 
     391         * Initialize the local storage 
     392         * 
     393         * @return mixed False if no sessionStorage in the browser or an Object containing all post_data for this blog 
     394         */ 
     395        getStorage: function() { 
     396                var stored_obj = false; 
     397                // Separate local storage containers for each blog_id 
     398                if ( this.hasStorage && this.blog_id ) { 
     399                        stored_obj = sessionStorage.getItem( 'wp-autosave-' + this.blog_id ); 
     400 
     401                        if ( stored_obj ) 
     402                                stored_obj = JSON.parse( stored_obj ); 
     403                        else 
     404                                stored_obj = {}; 
     405                } 
     406 
     407                return stored_obj; 
     408        }, 
     409 
     410        /** 
     411         * Set the storage for this blog 
     412         * 
     413         * Confirms that the data was saved successfully. 
     414         * 
     415         * @return bool 
     416         */ 
     417        setStorage: function( stored_obj ) { 
     418                var key; 
     419 
     420                if ( this.hasStorage && this.blog_id ) { 
     421                        key = 'wp-autosave-' + this.blog_id; 
     422                        sessionStorage.setItem( key, JSON.stringify( stored_obj ) ); 
     423                        return sessionStorage.getItem( key ) !== null; 
     424                } 
     425 
     426                return false; 
     427        }, 
     428 
     429        /** 
     430         * Get the saved post data for the current post 
     431         * 
     432         * @return mixed False if no storage or no data or the post_data as an Object 
     433         */ 
     434        getData: function() { 
     435                var stored = this.getStorage(), post_id = $('#post_ID').val(); 
     436 
     437                if ( !stored || !post_id ) 
     438                        return false; 
     439 
     440                return stored[ 'post_' + post_id ] || false; 
     441        }, 
     442 
     443        /** 
     444         * Set (save) post data in the storage 
     445         * 
     446         * @return bool 
     447         */ 
     448        setData: function( stored_data ) { 
     449                var stored = this.getStorage(), post_id = $('#post_ID').val(); 
     450 
     451                if ( !stored || !post_id ) 
     452                        return false; 
     453 
     454                stored[ 'post_' + post_id ] = stored_data; 
     455 
     456                return this.setStorage(stored); 
     457        }, 
     458 
     459        /** 
     460         * Save post data for the current post 
     461         * 
     462         * Runs on a 15 sec. schedule, saves when there are differences in the post title or content. 
     463         * When the optional data is provided, updates the last saved post data. 
     464         * 
     465         * $param data optional Object The post data for saving, minimum 'post_title' and 'content' 
     466         * @return bool 
     467         */ 
     468        save: function( data ) { 
     469                var result = false; 
     470 
     471                if ( ! data ) { 
     472                        post_data = wp.autosave.getPostData(); 
     473                } else { 
     474                        post_data = this.getData() || {}; 
     475                        $.extend( post_data, data ); 
     476                } 
     477 
     478                // If the content and title are empty or did not change since the last save, don't save again 
     479                if ( post_data.post_title + ': ' + post_data.content == this.lastsaveddata ) 
     480                        return false; 
     481 
     482                // Cannot get the post data at the moment 
     483                if ( !post_data.autosave ) 
     484                        return false; 
     485 
     486                post_data['save_time'] = (new Date()).getTime(); 
     487                post_data['status'] = $('#post_status').val() || ''; 
     488                result = this.setData( post_data ); 
     489 
     490                if ( result ) 
     491                        this.lastsaveddata = post_data.post_title + ': ' + post_data.content; 
     492 
     493                return result; 
     494        }, 
     495 
     496        // Initialize and run checkPost() on loading the script (before TinyMCE init) 
     497        init: function( settings ) { 
     498                var self = this; 
     499 
     500                // Run only on the Add/Edit Post screens and in browsers that have sessionStorage 
     501                if ( 'post' != window.pagenow || ! this.checkStorage() ) 
     502                        return; 
     503                // editor.js has to be loaded before autosave.js 
     504                if ( typeof switchEditors == 'undefined' ) 
     505                        return; 
     506 
     507                if ( settings ) 
     508                        $.extend( this, settings ); 
     509 
     510                if ( !this.blog_id ) 
     511                        this.blog_id = typeof window.autosaveL10n != 'undefined' ? window.autosaveL10n.blog_id : 0; 
     512 
     513                this.checkPost(); 
     514                $(document).ready( self.run ); 
     515        }, 
     516 
     517        // Run on DOM ready 
     518        run: function() { 
     519                var self = this, post_data; 
     520 
     521                // Set the comparison string 
     522                if ( !this.lastsaveddata ) { 
     523                        post_data = wp.autosave.getPostData(); 
     524 
     525                        if ( post_data.content && $('#wp-content-wrap').hasClass('tmce-active') ) 
     526                                this.lastsaveddata = post_data.post_title + ': ' + switchEditors.pre_wpautop( post_data.content ); 
     527                        else 
     528                                this.lastsaveddata = post_data.post_title + ': ' + post_data.content; 
     529                } 
     530 
     531                // Set the schedule 
     532                this.schedule = $.schedule({ 
     533                        time: 15 * 1000, 
     534                        func: function() { wp.autosave.local.save(); }, 
     535                        repeat: true, 
     536                        protect: true 
     537                }); 
     538 
     539                $('form#post').on('submit.autosave-local', function() { 
     540                        var editor = typeof tinymce != 'undefined' && tinymce.get('content'); 
     541 
     542                        if ( editor && ! editor.isHidden() ) { 
     543                                // Last onSubmit event in the editor, needs to run after the content has been moved to the textarea. 
     544                                editor.onSubmit.add( function() { 
     545                                        wp.autosave.local.save({ 
     546                                                post_title: $('#title').val() || '', 
     547                                                content: $('#content').val() || '', 
     548                                                excerpt: $('#excerpt').val() || '' 
     549                                        }); 
     550                                }); 
     551                        } else { 
     552                                self.save({ 
     553                                        post_title: $('#title').val() || '', 
     554                                        content: $('#content').val() || '', 
     555                                        excerpt: $('#excerpt').val() || '' 
     556                                }); 
     557                        } 
     558                }); 
     559        }, 
     560 
     561        // Strip whitespace and compare two strings 
     562        compare: function( str1, str2 ) { 
     563                function strip_space( string ) { 
     564                        return string.toString().replace(/[\x20\t\r\n\f]+/g, ''); 
     565                } 
     566 
     567                return ( strip_space( str1 || '' ) == strip_space( str2 || '' ) ); 
     568        }, 
     569 
     570        /** 
     571         * Check if the saved data for the current post (if any) is different than the loaded post data on the screen 
     572         * 
     573         * Shows a standard message letting the user restore the post data if different. 
     574         * 
     575         * @return void 
     576         */ 
     577        checkPost: function() { 
     578                var self = this, post_data = this.getData(), content, match = false, check_data, notice; 
     579 
     580                if ( post_data ) { 
     581                        content = $('#content').val(); 
     582                        check_data = $.extend( {}, post_data ); 
     583 
     584                        if ( $('#wp-content-wrap').hasClass('tmce-active') ) 
     585                                content = switchEditors.pre_wpautop( content ); 
     586 
     587                        if ( this.compare( content, check_data.content ) && this.compare( $('#title').val(), check_data.post_title ) && this.compare( $('#excerpt').val(), check_data.excerpt ) ) 
     588                                match = true; 
     589 
     590                        if ( ! match ) { 
     591                                // We have three choices here: 
     592                                // - Do an autosave and then show the standard notice "There is an autosave newer than...". 
     593                                // - Offer to load/restore the backed up post data. 
     594                                // - Restore the post_data without asking, then show a notice with an Undo link/button. 
     595                                // Doing an autosave will take few seconds and may take up to 30 and fail if network connectivity is bad 
     596                                // Restoring the post will leave the user with the proper content, but it won't be saved to the server until the next autosave. 
     597 
     598                                this.restore_post_data = post_data; 
     599                                this.undo_post_data = wp.autosave.getPostData(); 
     600 
     601                                /* 
     602                                if ( $('#post_status').val() == 'publish' ) { 
     603                                        // Different message when a post is published? 
     604                                        // Comparing the current and saved post data may fail (false positive) when the post is published 
     605                                        // as in some cases there are changes to post_content on publishing and updating before saving to the DB. 
     606                                } 
     607                                */ 
     608 
     609                                notice = $('#local-storage-notice'); 
     610                                $('form#post').before( notice.addClass('updated').show() ); 
     611 
     612                                notice.on( 'click', function(e) { 
     613                                        var target = $( e.target ); 
     614 
     615                                        if ( target.hasClass('restore-backup') ) { 
     616                                                self.restorePost( self.restore_post_data ); 
     617                                                target.parent().hide(); 
     618                                                $(this).find('p.undo-restore').show(); 
     619                                        } else if ( target.hasClass('undo-restore-backup') ) { 
     620                                                self.restorePost( self.undo_post_data ); 
     621                                                target.parent().hide(); 
     622                                                $(this).find('p.local-restore').show(); 
     623                                        } 
     624 
     625                                        e.preventDefault(); 
     626                                }); 
     627                        } 
     628                } 
     629        }, 
     630 
     631        // Restore the current title, content and excerpt from post_data. 
     632        restorePost: function( post_data ) { 
     633                var editor; 
     634 
     635                if ( post_data ) { 
     636                        // Set the last saved data 
     637                        this.lastsaveddata = post_data.post_title + ': ' + post_data.content; 
     638 
     639                        if ( $('#title').val() != post_data.post_title ) 
     640                                $('#title').focus().val( post_data.post_title || '' ); 
     641 
     642                        $('#excerpt').val( post_data.excerpt || '' ); 
     643                        editor = typeof tinymce != 'undefined' && tinymce.get('content'); 
     644 
     645                        if ( editor && ! editor.isHidden() ) { 
     646                                // Make sure there's an undo level in the editor 
     647                                editor.undoManager.add(); 
     648                                editor.setContent( post_data.content ? switchEditors.wpautop( post_data.content ) : '' ); 
     649                        } else { 
     650                                // Make sure the Text editor is selected 
     651                                $('#content-html').click(); 
     652                                $('#content').val( post_data.content ); 
     653                        } 
     654 
     655                        return true; 
     656                } 
     657 
     658                return false; 
     659        } 
     660} 
     661 
     662wp.autosave.local.init(); 
     663 
     664}(jQuery)); 
  • wp-includes/script-loader.php

     
    106106                'dismiss' => __('Dismiss'), 
    107107        ) ); 
    108108 
    109         $scripts->add( 'autosave', "/wp-includes/js/autosave$suffix.js", array('schedule', 'wp-ajax-response'), false, 1 ); 
     109        $scripts->add( 'autosave', "/wp-includes/js/autosave$suffix.js", array('schedule', 'wp-ajax-response', 'editor'), false, 1 ); 
    110110 
    111111        $scripts->add( 'heartbeat', "/wp-includes/js/heartbeat$suffix.js", array('jquery'), false, 1 ); 
    112112        did_action( 'init' ) && $scripts->localize( 'heartbeat', 'heartbeatSettings', 
     
    587587        wp_localize_script( 'autosave', 'autosaveL10n', array( 
    588588                'autosaveInterval' => AUTOSAVE_INTERVAL, 
    589589                'savingText' => __('Saving Draft&#8230;'), 
    590                 'saveAlert' => __('The changes you made will be lost if you navigate away from this page.') 
     590                'saveAlert' => __('The changes you made will be lost if you navigate away from this page.'), 
     591                'blog_id' => get_current_blog_id(), 
    591592        ) ); 
    592593 
    593594} 
  • wp-login.php

     
    6868                <meta name="viewport" content="width=320; initial-scale=0.9; maximum-scale=1.0; user-scalable=0;" /><?php 
    6969        } 
    7070 
     71        // Remove all stored post data on logging out. 
     72        // This could be added by add_action('login_head'...) like wp_shake_js() 
     73        // but maybe better if it's not removable by plugins 
     74        if ( 'loggedout' == $wp_error->get_error_code() ) { 
     75                ?> 
     76                <script>if("sessionStorage" in window){try{for(var key in sessionStorage){if(key.indexOf("wp-autosave-")!=-1){sessionStorage.removeItem(key)}}}catch(e){}};</script> 
     77                <?php 
     78        } 
     79 
    7180        do_action( 'login_enqueue_scripts' ); 
    7281        do_action( 'login_head' ); 
    7382