Changeset 7103

Show
Ignore:
Timestamp:
02/29/08 09:51:36 (8 months ago)
Author:
ryan
Message:

Post Edit Collision Detection from mdawaffe. fixes #6043

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/wp-admin/admin-ajax.php

    r7098 r7103  
    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']; 
     
    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) ) 
     
    497518                die(__('You are not allowed to edit this post.')); 
    498519        } 
    499         wp_update_post($_POST); 
    500     } 
    501     die('0'); 
    502 break; 
     520        if ( $do_autosave ) 
     521            $id = wp_update_post($_POST); 
     522        else 
     523            $id = $post->ID; 
     524    } 
     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' ); 
  • trunk/wp-admin/edit-form-advanced.php

    r7101 r7103  
    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 ?> 
     
    190199<?php echo $form_prevstatus ?> 
    191200 
    192 <p class="submit"> 
    193  
    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> 
     201<div id="autosave"></div> 
    205202 
    206203<div id="tagsdiv" class="postbox <?php echo postbox_classes('tagsdiv', 'post'); ?>"> 
  • trunk/wp-admin/edit-page-form.php

    r7101 r7103  
    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 ) 
     
    170171</div> 
    171172 
    172 <p class="submit"> 
    173  
    174 <span id="autosave"></span> 
    175  
    176 </p> 
     173<div id="autosave"></div> 
    177174 
    178175<?php do_meta_boxes('page', 'normal', $post); ?> 
  • trunk/wp-admin/includes/post.php

    r6983 r7103  
    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; 
     
    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?> 
  • trunk/wp-admin/includes/upgrade.php

    r6705 r7103  
    199199        upgrade_230_old_tables(); 
    200200 
    201     if ( $wp_current_db_version < 6689
     201    if ( $wp_current_db_version < 7098
    202202        upgrade_250(); 
    203203 
     
    726726        populate_roles_250(); 
    727727    } 
     728 
     729    add_option('autosave_interval', 60); 
    728730} 
    729731 
  • trunk/wp-admin/page.php

    r7047 r7103  
    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'); 
  • trunk/wp-admin/post.php

    r7084 r7103  
    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'); 
  • trunk/wp-admin/wp-admin.css

    r7101 r7103  
    10321032    margin-bottom: 10px; 
    10331033    margin-right: 8px; 
     1034} 
     1035 
     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; 
    10341043} 
    10351044 
  • trunk/wp-includes/classes.php

    r7081 r7103  
    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 ) 
  • trunk/wp-includes/js/autosave.js

    r6955 r7103  
    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; 
     
    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 
     116var autosave = function() { 
     117    // (bool) is rich editor enabled and active 
     118    var rich = (typeof tinyMCE != "undefined") && tinyMCE.activeEditor && !tinyMCE.activeEditor.isHidden(); 
     119    var post_data = { 
     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    }; 
    121128 
    122 function autosave() { 
    123     var rich = ( (typeof tinyMCE != "undefined") && tinyMCE.activeEditor && ! tinyMCE.activeEditor.isHidden() ) ? true : false; 
    124     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         }; 
     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; 
    132132 
    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(); 
     
    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(); 
     146 
     147    var origStatus = jQuery('#original_post_status').val(); 
     148    if ( 'draft' != origStatus ) // autosave currently only turned on for drafts 
     149        doAutoSave = false; 
    149150 
    150151    autosaveLast = jQuery("#title").val()+jQuery("#content").val(); 
     
    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} 
  • trunk/wp-includes/js/wp-lists.js

    r7094 r7103  
    22var currentFormEl = false; 
    33var fs = {add:'ajaxAdd',del:'ajaxDel',dim:'ajaxDim',process:'process',recolor:'recolor'}; 
    4  
    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 }; 
    444 
    455var wpList = { 
     
    12888 
    12989        s.success = function(r) { 
    130             if ( !wpAjax.parseAjaxResponse(r, s.response, s.element) ) { return false; } 
    131  
    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 
     90            var res = wpAjax.parseAjaxResponse(r, s.response, s.element); 
     91            if ( !res || res.errors ) { return false; } 
     92 
     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            } ); 
     
    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); } 
     
    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; 
     
    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); } 
     
    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; 
     
    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); } 
  • trunk/wp-includes/script-loader.php

    r7100 r7103  
    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 
     
    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' 
  • trunk/wp-includes/version.php

    r6957 r7103  
    1717 * @global int $wp_db_version 
    1818 */ 
    19 $wp_db_version = 6846
     19$wp_db_version = 7098
    2020 
    2121?>