WordPress.org

Make WordPress Core

Ticket #23220: 23220-6.patch

File 23220-6.patch, 18.9 KB (added by azaozz, 5 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