WordPress.org

Make WordPress Core

Ticket #38342: 38342.diff

File 38342.diff, 14.9 KB (added by adamsilverstein, 4 years ago)

WIP patch for testing

  • src/wp-admin/includes/dashboard.php

    diff --git src/wp-admin/includes/dashboard.php src/wp-admin/includes/dashboard.php
    index aab5976..83fa978 100644
    function wp_dashboard_quick_press( $error_msg = false ) { 
    491491        $post_ID = (int) $post->ID;
    492492?>
    493493
    494         <form name="post" action="<?php echo esc_url( admin_url( 'post.php' ) ); ?>" method="post" id="quick-press" class="initial-form hide-if-no-js">
    495 
    496                 <?php if ( $error_msg ) : ?>
    497                 <div class="error"><?php echo $error_msg; ?></div>
    498                 <?php endif; ?>
     494        <form name="post" method="post" id="quick-press" class="initial-form hide-if-no-js">
    499495
    500496                <div class="input-text-wrap" id="title-wrap">
    501                         <label class="screen-reader-text prompt" for="title" id="title-prompt-text">
     497                        <label class="prompt" for="title" id="title-prompt-text">
    502498
    503499                                <?php
    504500                                /** This filter is documented in wp-admin/edit-form-advanced.php */
    505501                                echo apply_filters( 'enter_title_here', __( 'Title' ), $post );
    506502                                ?>
    507503                        </label>
    508                         <input type="text" name="post_title" id="title" autocomplete="off" />
     504                        <input type="text" name="title" id="title" autocomplete="off" />
    509505                </div>
    510506
    511507                <div class="textarea-wrap" id="description-wrap">
    512                         <label class="screen-reader-text prompt" for="content" id="content-prompt-text"><?php _e( 'What&#8217;s on your mind?' ); ?></label>
     508                        <label class="prompt" for="content" id="content-prompt-text"><?php _e( 'What&#8217;s on your mind?' ); ?></label>
    513509                        <textarea name="content" id="content" class="mceEditor" rows="3" cols="15" autocomplete="off"></textarea>
    514510                </div>
    515 
    516511                <p class="submit">
    517                         <input type="hidden" name="action" id="quickpost-action" value="post-quickdraft-save" />
    518                         <input type="hidden" name="post_ID" value="<?php echo $post_ID; ?>" />
    519                         <input type="hidden" name="post_type" value="post" />
    520                         <?php wp_nonce_field( 'add-post' ); ?>
     512                        <div class="error inline" style="display: none;"><p></p></div>
     513                        <div class="spinner no-float"></div>
    521514                        <?php submit_button( __( 'Save Draft' ), 'primary', 'save', false, array( 'id' => 'save-post' ) ); ?>
    522515                        <br class="clear" />
    523516                </p>
    function wp_dashboard_recent_drafts( $drafts = false ) { 
    554547                 */
    555548                $query_args = apply_filters( 'dashboard_recent_drafts_query_args', $query_args );
    556549
    557                 $drafts = get_posts( $query_args );
     550                $dashboard_data_request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
     551                $dashboard_data_request->set_query_params( array(
     552                        'filter[post_type]' => 'post',
     553                        'status'            => 'draft',
     554                        'author'            => get_current_user_id(),
     555                        'per_page'          => 4
     556                ) );
     557                $drafts = rest_do_request( $dashboard_data_request );
     558
    558559                if ( ! $drafts ) {
    559560                        return;
    560561                }
    561         }
    562562
    563         echo '<div class="drafts">';
    564         if ( count( $drafts ) > 3 ) {
    565                 echo '<p class="view-all"><a href="' . esc_url( admin_url( 'edit.php?post_status=draft' ) ) . '" aria-label="' . __( 'View all drafts' ) . '">' . _x( 'View all', 'drafts' ) . "</a></p>\n";
    566         }
    567         echo '<h2 class="hide-if-no-js">' . __( 'Drafts' ) . "</h2>\n<ul>";
    568 
    569         $drafts = array_slice( $drafts, 0, 3 );
    570         foreach ( $drafts as $draft ) {
    571                 $url = get_edit_post_link( $draft->ID );
    572                 $title = _draft_or_post_title( $draft->ID );
    573                 echo "<li>\n";
    574                 /* translators: %s: post title */
    575                 echo '<div class="draft-title"><a href="' . esc_url( $url ) . '" aria-label="' . esc_attr( sprintf( __( 'Edit &#8220;%s&#8221;' ), $title ) ) . '">' . esc_html( $title ) . '</a>';
    576                 echo '<time datetime="' . get_the_time( 'c', $draft ) . '">' . get_the_time( __( 'F j, Y' ), $draft ) . '</time></div>';
    577                 if ( $the_content = wp_trim_words( $draft->post_content, 10 ) ) {
    578                         echo '<p>' . $the_content . '</p>';
    579                 }
    580                 echo "</li>\n";
    581563        }
     564
     565        echo '<div id="quick-press-drafts" class="drafts">';
     566        echo '<p class="view-all" style="display: none;"><a href="' . esc_url( admin_url( 'edit.php?post_status=draft' ) ) . '" aria-label="' . __( 'View all drafts' ) . '">' . _x( 'View all', 'drafts' ) . "</a></p>\n";
     567        echo '<h2 class="hide-if-no-js">' . __( 'Drafts' ) . "</h2>\n";
     568        echo '<script type="text/javascript">var quickPress = {}; quickPress.data =  ' . json_encode( $drafts ) . ';</script>';
     569        echo '<script id="tmpl-item-quick-press-draft" type="text/template">';
     570        /* translators: %s: post title */
     571        echo '<div class="draft-title"><a href="{{ data.link }}" aria-label="' . esc_attr( __( 'Edit Post' ) ) . '">{{ data.title }}</a>';
     572        echo '<time datetime="{{ data.date }}">{{ data.formattedDate }}</time></div>';
     573        echo '{{{ data.formattedShortContent }}}';
     574        echo '</script>';
     575        echo '<ul class="drafts-list">';
    582576        echo "</ul>\n</div>";
    583577}
    584578
  • src/wp-admin/js/dashboard.js

    diff --git src/wp-admin/js/dashboard.js src/wp-admin/js/dashboard.js
    index fa100dd..43d4a36 100644
     
    1 /* global pagenow, ajaxurl, postboxes, wpActiveEditor:true */
     1/* global wp, quickPress, pagenow, ajaxurl, postboxes, wpActiveEditor:true */
    22var ajaxWidgets, ajaxPopulateWidgets, quickPressLoad;
    33
    44jQuery(document).ready( function($) {
    jQuery(document).ready( function($) { 
    6161
    6262        postboxes.add_postbox_toggles(pagenow, { pbshow: ajaxPopulateWidgets } );
    6363
    64         /* QuickPress */
    65         quickPressLoad = function() {
    66                 var act = $('#quickpost-action'), t;
    67 
    68                 $( '#quick-press .submit input[type="submit"], #quick-press .submit input[type="reset"]' ).prop( 'disabled' , false );
    69 
    70                 t = $('#quick-press').submit( function( e ) {
    71                         e.preventDefault();
    72                         $('#dashboard_quick_press #publishing-action .spinner').show();
    73                         $('#quick-press .submit input[type="submit"], #quick-press .submit input[type="reset"]').prop('disabled', true);
    74 
    75                         $.post( t.attr( 'action' ), t.serializeArray(), function( data ) {
    76                                 // Replace the form, and prepend the published post.
    77                                 $('#dashboard_quick_press .inside').html( data );
    78                                 $('#quick-press').removeClass('initial-form');
    79                                 quickPressLoad();
    80                                 highlightLatestPost();
    81                                 $('#title').focus();
    82                         });
    83 
    84                         function highlightLatestPost () {
    85                                 var latestPost = $('.drafts ul li').first();
    86                                 latestPost.css('background', '#fffbe5');
    87                                 setTimeout(function () {
    88                                         latestPost.css('background', 'none');
    89                                 }, 1000);
    90                         }
    91                 } );
    92 
    93                 $('#publish').click( function() { act.val( 'post-quickpress-publish' ); } );
    94 
    95                 $('#title, #tags-input, #content').each( function() {
    96                         var input = $(this), prompt = $('#' + this.id + '-prompt-text');
    97 
    98                         if ( '' === this.value ) {
    99                                 prompt.removeClass('screen-reader-text');
    100                         }
    101 
    102                         prompt.click( function() {
    103                                 $(this).addClass('screen-reader-text');
    104                                 input.focus();
    105                         });
    106 
    107                         input.blur( function() {
    108                                 if ( '' === this.value ) {
    109                                         prompt.removeClass('screen-reader-text');
    110                                 }
    111                         });
    112 
    113                         input.focus( function() {
    114                                 prompt.addClass('screen-reader-text');
    115                         });
    116                 });
    117 
    118                 $('#quick-press').on( 'click focusin', function() {
    119                         wpActiveEditor = 'content';
    120                 });
    121 
    122                 autoResizeTextarea();
    123         };
    124         quickPressLoad();
    125 
    12664        $( '.meta-box-sortables' ).sortable( 'option', 'containment', '#wpwrap' );
    12765
    12866        function autoResizeTextarea() {
    jQuery(document).ready( function($) { 
    186124                });
    187125        }
    188126
     127        autoResizeTextarea();
     128
     129} );
     130
     131wp.api.loadPromise.done( function() {
     132        var $ = jQuery,
     133                QuickPress = {},
     134                draftsCollection;
     135
     136        QuickPress.Models = {};
     137
     138        QuickPress.Models.Draft = wp.api.models.Post.extend({
     139                initialize: function( attributes ) {
     140                        if ( attributes ) {
     141                                this.set( this.normalizeAttributes( attributes ) );
     142                        }
     143                },
     144
     145                parse: function( response ) {
     146                        return this.normalizeAttributes( response );
     147                },
     148
     149                normalizeAttributes: function( attributes ) {
     150                        if ( ! attributes ) {
     151                                return attributes;
     152                        }
     153
     154                        if ( 'object' === typeof attributes.content ) {
     155                                attributes.content = attributes.content.rendered;
     156                        }
     157
     158                        if ( 'object' === typeof attributes.title ) {
     159                                attributes.title = attributes.title.rendered;
     160                        }
     161
     162                        return attributes;
     163                },
     164
     165                validate: function( attributes ) {
     166                        if ( ! attributes.title && ! attributes.content ) {
     167                                return 'no-content';
     168                        }
     169                }
     170        });
     171
     172        QuickPress.Collections = {};
     173
     174        QuickPress.Collections.Drafts = wp.api.collections.Posts.extend({
     175                model: QuickPress.Models.Draft,
     176
     177                comparator: function( a, b ) {
     178                        return a.get( 'date' ) < b.get( 'date' );
     179                }
     180        });
     181
     182        QuickPress.Views = {};
     183
     184        QuickPress.Views.Form = wp.Backbone.View.extend({
     185                events: {
     186                        'click #title-wrap,#description-wrap': 'hidePromptAndFocus',
     187                        'focus #title-wrap,#description-wrap': 'hidePrompt',
     188                        'blur #title-wrap,#description-wrap': 'showPrompt',
     189                        click: 'setActiveEditor',
     190                        focusin: 'setActiveEditor',
     191                        submit: 'submit'
     192                },
     193
     194                initialize: function() {
     195                        this.listenTo( this.model, 'invalid', this.render );
     196                },
     197
     198                togglePrompt: function( element, visible ) {
     199                        var $input = $( ':input', element ),
     200                                hasContent = $input.val().length > 0;
     201
     202                        $( '.prompt', element ).toggleClass( 'screen-reader-text', ! visible || hasContent );
     203                },
     204
     205                showPrompt: function( event ) {
     206                        this.togglePrompt( event.currentTarget, true );
     207                },
     208
     209                hidePrompt: function( event ) {
     210                        this.togglePrompt( event.currentTarget, false );
     211                },
     212
     213                hidePromptAndFocus: function( event ) {
     214                        this.togglePrompt( event.currentTarget, false );
     215                        $( ':input', event.target ).focus();
     216                },
     217
     218                setActiveEditor: function() {
     219                        wpActiveEditor = 'content';
     220                },
     221
     222                submit: function( event ) {
     223                        var values;
     224
     225                        event.preventDefault();
     226
     227                        values = this.$el.serializeArray().reduce( function( memo, field ) {
     228                                memo[ field.name ] = field.value;
     229                                return memo;
     230                        }, {} );
     231
     232                        this.model.set( values );
     233                        if ( ! this.model.isValid() ) {
     234                                return;
     235                        }
     236
     237                        // Show a spinner during the callback.
     238                        $('#quick-press .spinner').css( 'visibility', 'inherit' );
     239
     240                        this.model.save()
     241                                // TODO: `always` should be `done` to handle success only
     242                                .always( function() {
     243                                        console.log( 'always' );
     244                                        $( '#quick-press .spinner' ).css( 'visibility', 'hidden' );
     245                                } )
     246                                .success( function(){
     247                                        console.log( 'success' );
     248                                        this.collection.add( this.model );
     249                                        // @todo Refresh the nonce (client should handle this).
     250                                        // @todo Clear the form.
     251                                }.bind( this ) )
     252                                .error( function() {
     253                                        console.log( 'error' );
     254                                //      // TODO: Handle failure
     255                                } );
     256
     257                        // TODO: Clear form model
     258                },
     259
     260                render: function() {
     261                        var $error = this.$el.find( '.error' );
     262
     263                        $error.toggle( !! this.model.validationError );
     264                        if ( this.model.validationError ) {
     265                                $error.html( $( '<p />', {
     266                                        text: quickPress.l10n[ this.model.validationError ]
     267                                } ) );
     268                        }
     269                }
     270        });
     271
     272        QuickPress.Views.DraftList = wp.Backbone.View.extend({
     273                initialize: function() {
     274                        this.listenTo( this.collection, 'add', this.render );
     275                },
     276
     277                render: function() {
     278                        var slicedCollection = this.collection.slice( 0, 4 );
     279
     280                        this.$el.toggle( this.collection.length > 0 );
     281                        this.$el.find( '.view-all' ).toggle( slicedCollection.length > 3 );
     282                        this.$el.find( '.drafts-list' ).html( slicedCollection.map( function( draft ) {
     283                                return new QuickPress.Views.DraftListItem({
     284                                        model: draft
     285                                }).render().el;
     286                        }) );
     287
     288                        return this;
     289                }
     290        });
     291
     292        QuickPress.Views.DraftListItem = wp.Backbone.View.extend({
     293                tagName: 'li',
     294
     295                template: wp.template( 'item-quick-press-draft' ),
     296
     297                render: function() {
     298                        // TODO: Render highlight effect to new post
     299
     300                        this.$el.html( this.template( this.model.attributes ) );
     301
     302                        return this;
     303                }
     304        });
     305
     306        draftsCollection = new QuickPress.Collections.Drafts( quickPress.data.data );
     307
     308        new QuickPress.Views.DraftList({
     309                el: '#quick-press-drafts',
     310                collection: draftsCollection
     311        }).render();
     312
     313        new QuickPress.Views.Form({
     314                el: '#quick-press',
     315                model: new QuickPress.Models.Draft(),
     316                collection: draftsCollection
     317        }).render();
    189318} );
  • src/wp-admin/post.php

    diff --git src/wp-admin/post.php src/wp-admin/post.php
    index 437d1bd..df78352 100644
    if ( ! $sendback || 
    6060}
    6161
    6262switch($action) {
    63 case 'post-quickdraft-save':
    64         // Check nonce and capabilities
    65         $nonce = $_REQUEST['_wpnonce'];
    66         $error_msg = false;
    67 
    68         // For output of the quickdraft dashboard widget
    69         require_once ABSPATH . 'wp-admin/includes/dashboard.php';
    70 
    71         if ( ! wp_verify_nonce( $nonce, 'add-post' ) )
    72                 $error_msg = __( 'Unable to submit this form, please refresh and try again.' );
    73 
    74         if ( ! current_user_can( get_post_type_object( 'post' )->cap->create_posts ) ) {
    75                 exit;
    76         }
    77 
    78         if ( $error_msg )
    79                 return wp_dashboard_quick_press( $error_msg );
    80 
    81         $post = get_post( $_REQUEST['post_ID'] );
    82         check_admin_referer( 'add-' . $post->post_type );
    83 
    84         $_POST['comment_status'] = get_default_comment_status( $post->post_type );
    85         $_POST['ping_status']    = get_default_comment_status( $post->post_type, 'pingback' );
    86 
    87         edit_post();
    88         wp_dashboard_quick_press();
    89         exit;
    90 
    9163case 'postajaxpost':
    9264case 'post':
    9365        check_admin_referer( 'add-' . $post_type );
  • src/wp-includes/default-filters.php

    diff --git src/wp-includes/default-filters.php src/wp-includes/default-filters.php
    index d5f2116..699c8af 100644
    add_filter( 'the_excerpt_embed', 'wp_embed_excerpt_attachment' ); 
    492492add_filter( 'oembed_dataparse',       'wp_filter_oembed_result',        10, 3 );
    493493add_filter( 'oembed_response_data',   'get_oembed_response_data_rich',  10, 4 );
    494494add_filter( 'pre_oembed_result',      'wp_filter_pre_oembed_result',    10, 3 );
     495add_action( 'rest_api_init',          'wp_dashboard_filter_api'              );
    495496
    496497unset( $filter, $action );
  • src/wp-includes/script-loader.php

    diff --git src/wp-includes/script-loader.php src/wp-includes/script-loader.php
    index 874f5e7..15634ad 100644
    function wp_default_scripts( &$scripts ) { 
    705705                        'current' => __( 'Current Color' ),
    706706                ) );
    707707
    708                 $scripts->add( 'dashboard', "/wp-admin/js/dashboard$suffix.js", array( 'jquery', 'admin-comments', 'postbox' ), false, 1 );
     708                $scripts->add( 'dashboard', "/wp-admin/js/dashboard$suffix.js", array( 'jquery', 'admin-comments', 'postbox', 'wp-api', 'wp-backbone' ), false, 1 );
    709709
    710710                $scripts->add( 'list-revisions', "/wp-includes/js/wp-list-revisions$suffix.js" );
    711711
    function _wp_footer_scripts() { 
    11751175}
    11761176
    11771177/**
     1178 * Set up a filter for the dashboard API requests.
     1179 */
     1180function wp_dashboard_filter_api() {
     1181
     1182        /**
     1183         * Filter the WP API response for the recent drafts widget in the dashboard, adding a formatted date
     1184         * which is difficult to construct correctly in JavaScript.
     1185         */
     1186        function wp_dashboard_filter_api_post( $response, $post, $request ) {
     1187
     1188                if ( 'draft' !== $post->post_status ) {
     1189                        return;
     1190                }
     1191
     1192                $response->data['formattedDate']         = get_the_time( __( 'F j, Y' ), $post );
     1193                $response->data['formattedShortContent'] = wp_trim_words( $post->post_content, 10 );
     1194                return $response;
     1195        }
     1196
     1197        add_filter( "rest_prepare_post", 'wp_dashboard_filter_api_post', 10, 3 );
     1198
     1199}
     1200
     1201/**
    11781202 * Hooks to print the scripts and styles in the footer.
    11791203 *
    11801204 * @since 2.8.0