<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[31333] trunk/src: Shiny Updates: Add ajax-y updates to the plugin list page, and ajax-y updates and installs to the plugin card page.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/31333">31333</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/31333","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>pento</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2015-02-05 04:18:57 +0000 (Thu, 05 Feb 2015)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Shiny Updates: Add ajax-y updates to the plugin list page, and ajax-y updates and installs to the plugin card page.

This also includes JS architecture that can be expanded to support theme, core and language pack updates.

Props pento, ericlewis, lgladdy, adamsilverstein, DrewAPicture

See <a href="https://core.trac.wordpress.org/ticket/29820">#29820</a></pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpadminadminajaxphp">trunk/src/wp-admin/admin-ajax.php</a></li>
<li><a href="#trunksrcwpadmincsslisttablescss">trunk/src/wp-admin/css/list-tables.css</a></li>
<li><a href="#trunksrcwpadminincludesajaxactionsphp">trunk/src/wp-admin/includes/ajax-actions.php</a></li>
<li><a href="#trunksrcwpadminincludesclasswpplugininstalllisttablephp">trunk/src/wp-admin/includes/class-wp-plugin-install-list-table.php</a></li>
<li><a href="#trunksrcwpadminincludesplugininstallphp">trunk/src/wp-admin/includes/plugin-install.php</a></li>
<li><a href="#trunksrcwpadminincludesupdatephp">trunk/src/wp-admin/includes/update.php</a></li>
<li><a href="#trunksrcwpadminjsplugininstalljs">trunk/src/wp-admin/js/plugin-install.js</a></li>
<li><a href="#trunksrcwpadminjsupdatesjs">trunk/src/wp-admin/js/updates.js</a></li>
<li><a href="#trunksrcwpadminplugininstallphp">trunk/src/wp-admin/plugin-install.php</a></li>
<li><a href="#trunksrcwpadminpluginsphp">trunk/src/wp-admin/plugins.php</a></li>
<li><a href="#trunksrcwpincludesscriptloaderphp">trunk/src/wp-includes/script-loader.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpadminadminajaxphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/admin-ajax.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/admin-ajax.php 2015-02-04 22:14:31 UTC (rev 31332)
+++ trunk/src/wp-admin/admin-ajax.php   2015-02-05 04:18:57 UTC (rev 31333)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -61,7 +61,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">        'query-attachments', 'save-attachment', 'save-attachment-compat', 'send-link-to-editor',
</span><span class="cx" style="display: block; padding: 0 10px">        'send-attachment-to-editor', 'save-attachment-order', 'heartbeat', 'get-revision-diffs',
</span><span class="cx" style="display: block; padding: 0 10px">        'save-user-color-scheme', 'update-widget', 'query-themes', 'parse-embed', 'set-attachment-thumbnail',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        'parse-media-shortcode', 'destroy-sessions'
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'parse-media-shortcode', 'destroy-sessions', 'install-plugin', 'update-plugin'
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> // Register core Ajax calls.
</span></span></pre></div>
<a id="trunksrcwpadmincsslisttablescss"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/css/list-tables.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/css/list-tables.css    2015-02-04 22:14:31 UTC (rev 31332)
+++ trunk/src/wp-admin/css/list-tables.css      2015-02-05 04:18:57 UTC (rev 31333)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1143,7 +1143,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> .upgrade .plugins tr:last-of-type td,
</span><span class="cx" style="display: block; padding: 0 10px"> .upgrade .plugins tr:last-of-type th,
</span><span class="cx" style="display: block; padding: 0 10px"> .plugins tr.active + tr.inactive.update th,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-.plugins tr.active + tr.inactive.update td {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.plugins tr.active + tr.inactive.update td,
+.plugins .updated td,
+.plugins .updated th,
+.plugins tr.active + tr.inactive.updated th,
+.plugins tr.active + tr.inactive.updated td {
</ins><span class="cx" style="display: block; padding: 0 10px">         -webkit-box-shadow: none;
</span><span class="cx" style="display: block; padding: 0 10px">        box-shadow: none;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1154,7 +1158,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">        background-color: #fef7f1;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-.plugins .active th.check-column {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.plugins .active th.check-column,
+.plugin-update-tr.active td {
</ins><span class="cx" style="display: block; padding: 0 10px">         border-left: 4px solid #2ea2cc;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1199,18 +1204,49 @@
</span><span class="cx" style="display: block; padding: 0 10px">        background-color: rgba(0,0,0,0.03);
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-.plugin-update-tr .update-message:before {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.plugin-update-tr .update-message:before,
+.plugin-card .update-now:before,
+.plugin-card .install-now:before {
</ins><span class="cx" style="display: block; padding: 0 10px">         color: #d54e21;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        content: '\f463';
</del><span class="cx" style="display: block; padding: 0 10px">         display: inline-block;
</span><span class="cx" style="display: block; padding: 0 10px">        font: normal 20px/1 'dashicons';
</span><span class="cx" style="display: block; padding: 0 10px">        speak: none;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        margin: 0 8px 0 -2px;
</del><span class="cx" style="display: block; padding: 0 10px">         -webkit-font-smoothing: antialiased;
</span><span class="cx" style="display: block; padding: 0 10px">        -moz-osx-font-smoothing: grayscale;
</span><span class="cx" style="display: block; padding: 0 10px">        vertical-align: top;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.plugin-update-tr .update-message:before,
+.plugin-card .update-now:before {
+       content: '\f463';
+}
+
+.plugin-update-tr .update-message:before {
+       margin: 0 8px 0 -2px;
+}
+
+.plugin-card .update-now:before,
+.plugin-card .install-now:before {
+       margin: 3px 5px 0 -2px;
+}
+
+.plugin-update-tr .updating-message:before,
+.plugin-card .updating-message:before {
+       content: '\f463';
+   -webkit-animation: rotation 2s infinite linear;
+}
+
+@-webkit-keyframes rotation {
+    from {-webkit-transform: rotate(0deg);}
+    to   {-webkit-transform: rotate(359deg);}
+}
+
+.plugin-update-tr .updated-message:before,
+.plugin-card .updated-message:before {
+       color: #79ba49;
+       content: '\f147';
+}
+
</ins><span class="cx" style="display: block; padding: 0 10px"> .plugins .plugin-update {
</span><span class="cx" style="display: block; padding: 0 10px">        padding: 0;
</span><span class="cx" style="display: block; padding: 0 10px">        border: none;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1223,7 +1259,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">        background-color: #f7fcfe;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-tr.active + tr.plugin-update-tr .plugin-update .update-message {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+tr.active + tr.plugin-update-tr:not(.updated) .plugin-update .update-message {
</ins><span class="cx" style="display: block; padding: 0 10px">         background-color: #fcf3ef;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span></span></pre></div>
<a id="trunksrcwpadminincludesajaxactionsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/ajax-actions.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/ajax-actions.php      2015-02-04 22:14:31 UTC (rev 31332)
+++ trunk/src/wp-admin/includes/ajax-actions.php        2015-02-05 04:18:57 UTC (rev 31333)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2828,3 +2828,81 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        wp_send_json_success( array( 'message' => $message ) );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+/**
+ * AJAX handler for installing a plugin.
+ *
+ * @since 4.2.0
+ */
+function wp_ajax_install_plugin() {
+       check_ajax_referer( 'updates' );
+
+       include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
+       include_once( ABSPATH . 'wp-admin/includes/plugin-install.php' );
+
+       $status = array(
+               'install' => 'plugin',
+               'slug'    => sanitize_key( $_POST['slug'] ),
+       );
+
+       $api = plugins_api( 'plugin_information', array(
+               'slug'   => sanitize_key( $_POST['slug'] ),
+               'fields' => array( 'sections' => false )
+       ) );
+
+       if ( is_wp_error( $api ) ) {
+               $status['error'] = $api->get_error_message();
+               wp_send_json_error( $status );
+       }
+
+       $upgrader = new Plugin_Upgrader( new Automatic_Upgrader_Skin() );
+       $result = $upgrader->install( $api->download_link );
+
+       if ( is_wp_error( $result ) ) {
+               $status['error'] = $result->get_error_message();
+               wp_send_json_error( $status );
+       }
+
+       $plugin_status = install_plugin_install_status( array( 'slug' => sanitize_key( $_POST['slug'] ) ) );
+       activate_plugin( $plugin_status['file'] );
+
+       wp_send_json_success( $status );
+}
+
+/**
+ * AJAX handler for updating a plugin.
+ *
+ * @since 4.2.0
+ */
+function wp_ajax_update_plugin() {
+       check_ajax_referer( 'updates' );
+
+       include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
+
+       $plugin = urldecode( $_POST['plugin'] );
+
+       $status = array(
+               'update' => 'plugin',
+               'plugin' => $plugin,
+               'slug'   => sanitize_key( $_POST['slug'] ),
+       );
+
+       $current = get_site_transient( 'update_plugins' );
+       if ( empty( $current ) ) {
+               wp_update_plugins();
+       }
+
+       $upgrader = new Plugin_Upgrader( new Automatic_Upgrader_Skin() );
+       $result = $upgrader->bulk_upgrade( array( $plugin ) );
+
+       if ( is_array( $result ) ) {
+               $result = $result[ $plugin ];
+       }
+
+       if ( is_wp_error( $result ) ) {
+               $status['error'] = $result->get_error_message();
+               wp_send_json_error( $status );
+       }
+
+       wp_send_json_success( $status );
+}
</ins></span></pre></div>
<a id="trunksrcwpadminincludesclasswpplugininstalllisttablephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/class-wp-plugin-install-list-table.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/class-wp-plugin-install-list-table.php        2015-02-04 22:14:31 UTC (rev 31332)
+++ trunk/src/wp-admin/includes/class-wp-plugin-install-list-table.php  2015-02-05 04:18:57 UTC (rev 31333)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -402,14 +402,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        case 'install':
</span><span class="cx" style="display: block; padding: 0 10px">                                                if ( $status['url'] ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                        /* translators: 1: Plugin name and version. */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $action_links[] = '<a class="install-now button" href="' . $status['url'] . '" aria-label="' . esc_attr( sprintf( __( 'Install %s now' ), $name ) ) . '">' . __( 'Install Now' ) . '</a>';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $action_links[] = '<a class="install-now button" data-slug="' . esc_attr( $plugin['slug'] ) . '" href="' . esc_url( $status['url'] ) . '" aria-label="' . esc_attr( sprintf( __( 'Install %s now' ), $name ) ) . '">' . __( 'Install Now' ) . '</a>';
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                break;
</span><span class="cx" style="display: block; padding: 0 10px">                                        case 'update_available':
</span><span class="cx" style="display: block; padding: 0 10px">                                                if ( $status['url'] ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                        /* translators: 1: Plugin name and version */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $action_links[] = '<a class="button" href="' . $status['url'] . '" aria-label="' . esc_attr( sprintf( __( 'Update %s now' ), $name ) ) . '">' . __( 'Update Now' ) . '</a>';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $action_links[] = '<a class="update-now button" data-plugin="' . esc_attr( $status['file'] ) . '" data-slug="' . esc_attr( $plugin['slug'] ) . '" href="' . esc_url( $status['url'] ) . '" aria-label="' . esc_attr( sprintf( __( 'Update %s now' ), $name ) ) . '">' . __( 'Update Now' ) . '</a>';
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                break;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -449,7 +449,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $date_format = __( 'M j, Y @ G:i' );
</span><span class="cx" style="display: block; padding: 0 10px">                        $last_updated_timestamp = strtotime( $plugin['last_updated'] );
</span><span class="cx" style="display: block; padding: 0 10px">                ?>
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                <div class="plugin-card">
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         <div class="plugin-card plugin-card-<?php echo sanitize_html_class( $plugin['slug'] ); ?>">
</ins><span class="cx" style="display: block; padding: 0 10px">                         <div class="plugin-card-top">
</span><span class="cx" style="display: block; padding: 0 10px">                                <a href="<?php echo esc_url( $details_link ); ?>" class="thickbox plugin-icon"><img src="<?php echo esc_attr( $plugin_icon_url ) ?>" /></a>
</span><span class="cx" style="display: block; padding: 0 10px">                                <div class="name column-name">
</span></span></pre></div>
<a id="trunksrcwpadminincludesplugininstallphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/plugin-install.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/plugin-install.php    2015-02-04 22:14:31 UTC (rev 31332)
+++ trunk/src/wp-admin/includes/plugin-install.php      2015-02-05 04:18:57 UTC (rev 31333)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -276,6 +276,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">        // Default to a "new" plugin
</span><span class="cx" style="display: block; padding: 0 10px">        $status = 'install';
</span><span class="cx" style="display: block; padding: 0 10px">        $url = false;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        $update_file = false;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /*
</span><span class="cx" style="display: block; padding: 0 10px">         * Check to see if this plugin is known to be installed,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -304,6 +305,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        } else {
</span><span class="cx" style="display: block; padding: 0 10px">                                $key = array_keys( $installed_plugin );
</span><span class="cx" style="display: block; padding: 0 10px">                                $key = array_shift( $key ); //Use the first plugin regardless of the name, Could have issues for multiple-plugins in one directory if they share different version numbers
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                $update_file = $api->slug . '/' . $key;
</ins><span class="cx" style="display: block; padding: 0 10px">                                 if ( version_compare($api->version, $installed_plugin[ $key ]['Version'], '=') ){
</span><span class="cx" style="display: block; padding: 0 10px">                                        $status = 'latest_installed';
</span><span class="cx" style="display: block; padding: 0 10px">                                } elseif ( version_compare($api->version, $installed_plugin[ $key ]['Version'], '<') ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -327,7 +329,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">        if ( isset($_GET['from']) )
</span><span class="cx" style="display: block; padding: 0 10px">                $url .= '&amp;from=' . urlencode( wp_unslash( $_GET['from'] ) );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        return compact('status', 'url', 'version');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $file = $update_file;
+       return compact( 'status', 'url', 'version', 'file' );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span></span></pre></div>
<a id="trunksrcwpadminincludesupdatephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/update.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/update.php    2015-02-04 22:14:31 UTC (rev 31332)
+++ trunk/src/wp-admin/includes/update.php      2015-02-05 04:18:57 UTC (rev 31333)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -276,14 +276,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">        $wp_list_table = _get_list_table('WP_Plugins_List_Table');
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        if ( is_network_admin() || !is_multisite() ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                echo '<tr class="plugin-update-tr"><td colspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange"><div class="update-message">';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $active_class = ( is_plugin_active( $plugin_data['plugin'] ) ) ? ' active' : '';
+               echo '<tr class="plugin-update-tr' . $active_class . '" id="' . esc_attr( $r->slug . '-update' ) . '" data-slug="' . esc_attr( $r->slug ) . '" data-plugin="' . esc_attr( $file ) . '"><td colspan="' . esc_attr( $wp_list_table->get_column_count() ) . '" class="plugin-update colspanchange"><div class="update-message">';
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if ( ! current_user_can( 'update_plugins' ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        printf( __('There is a new version of %1$s available. <a href="%2$s" class="thickbox" title="%3$s">View version %4$s details</a>.'), $plugin_name, esc_url($details_url), esc_attr($plugin_name), $r->new_version );
</span><span class="cx" style="display: block; padding: 0 10px">                } elseif ( empty($r->package) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        printf( __('There is a new version of %1$s available. <a href="%2$s" class="thickbox" title="%3$s">View version %4$s details</a>. <em>Automatic update is unavailable for this plugin.</em>'), $plugin_name, esc_url($details_url), esc_attr($plugin_name), $r->new_version );
</span><span class="cx" style="display: block; padding: 0 10px">                } else {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        printf( __('There is a new version of %1$s available. <a href="%2$s" class="thickbox" title="%3$s">View version %4$s details</a> or <a href="%5$s">update now</a>.'), $plugin_name, esc_url($details_url), esc_attr($plugin_name), $r->new_version, wp_nonce_url( self_admin_url('update.php?action=upgrade-plugin&plugin=') . $file, 'upgrade-plugin_' . $file) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 printf( __( 'There is a new version of %1$s available. <a href="%2$s" class="thickbox" title="%3$s">View version %4$s details</a> or <a href="%5$s" class="update-link">update now</a>.' ), $plugin_name, esc_url( $details_url ), esc_attr( $plugin_name ), $r->new_version, wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $file, 'upgrade-plugin_' . $file ) );
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px">                /**
</span><span class="cx" style="display: block; padding: 0 10px">                 * Fires at the end of the update message container in each
</span></span></pre></div>
<a id="trunksrcwpadminjsplugininstalljs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/js/plugin-install.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/js/plugin-install.js   2015-02-04 22:14:31 UTC (rev 31332)
+++ trunk/src/wp-admin/js/plugin-install.js     2015-02-05 04:18:57 UTC (rev 31333)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -69,8 +69,4 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $( '#section-holder div.section' ).hide(); // Hide 'em all.
</span><span class="cx" style="display: block; padding: 0 10px">                $( '#section-' + tab ).show();
</span><span class="cx" style="display: block; padding: 0 10px">        });
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-       $( 'a.install-now' ).click( function() {
-               return confirm( plugininstallL10n.ays );
-       });
</del><span class="cx" style="display: block; padding: 0 10px"> });
</span></span></pre></div>
<a id="trunksrcwpadminjsupdatesjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/js/updates.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/js/updates.js  2015-02-04 22:14:31 UTC (rev 31332)
+++ trunk/src/wp-admin/js/updates.js    2015-02-05 04:18:57 UTC (rev 31333)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -5,43 +5,370 @@
</span><span class="cx" style="display: block; padding: 0 10px">        wp.updates = {};
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-         * Decrement update counts throughout the various menus
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  * User nonce for ajax calls.
</ins><span class="cx" style="display: block; padding: 0 10px">          *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * @since 4.2.0
+        *
+        * @var string
+        */
+       wp.updates.ajaxNonce = window._wpUpdatesSettings.ajax_nonce;
+
+       /**
+        * Localized strings.
+        *
+        * @since 4.2.0
+        *
+        * @var object
+        */
+       wp.updates.l10n = window._wpUpdatesSettings.l10n;
+
+       /**
+        * Flag if we're waiting for an install/update to complete.
+        *
+        * @since 4.2.0
+        *
+        * @var bool
+        */
+       wp.updates.updateLock = false;
+
+       /**
+        * If the user tries to install/update a plugin while an install/update is
+        * already happening, it can be placed in this queue to perform later.
+        *
+        * @since 4.2.0
+        *
+        * @var array
+        */
+       wp.updates.updateQueue = [];
+
+       /**
+        * Decrement update counts throughout the various menus.
+        *
+        * @since 3.9.0
+        *
</ins><span class="cx" style="display: block; padding: 0 10px">          * @param {string} updateType
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        wp.updates.decrementCount = function( upgradeType ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                var count, pluginCount, $elem;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         var count,
+                   pluginCount,
+                   $adminBarUpdateCount = $( '#wp-admin-bar-updates .ab-label' ),
+                   $dashboardNavMenuUpdateCount = $( 'a[href="update-core.php"] .update-plugins' )
+                   $pluginsMenuItem = $( '#menu-plugins' );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $elem = $( '#wp-admin-bar-updates .ab-label' );
-               count = $elem.text();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+               count = $adminBarUpdateCount.text();
</ins><span class="cx" style="display: block; padding: 0 10px">                 count = parseInt( count, 10 ) - 1;
</span><span class="cx" style="display: block; padding: 0 10px">                if ( count < 0 || isNaN( count ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">                $( '#wp-admin-bar-updates .ab-item' ).removeAttr( 'title' );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $elem.text( count );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $adminBarUpdateCount.text( count );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $elem = $( 'a[href="update-core.php"] .update-plugins' );
-               $elem.each( function( index, elem ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+               $dashboardNavMenuUpdateCount.each( function( index, elem ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                         elem.className = elem.className.replace( /count-\d+/, 'count-' + count );
</span><span class="cx" style="display: block; padding: 0 10px">                } );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $elem.removeAttr( 'title' );
-               $elem.find( '.update-count' ).text( count );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $dashboardNavMenuUpdateCount.removeAttr( 'title' );
+               $dashboardNavMenuUpdateCount.find( '.update-count' ).text( count );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if ( 'plugin' === upgradeType ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $elem = $( '#menu-plugins' );
-                       pluginCount = $elem.find( '.plugin-count' ).eq(0).text();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 pluginCount = $pluginsMenuItem.find( '.plugin-count' ).eq(0).text();
</ins><span class="cx" style="display: block; padding: 0 10px">                         pluginCount = parseInt( pluginCount, 10 ) - 1;
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( pluginCount < 0 || isNaN( pluginCount ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                return;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $elem.find( '.plugin-count' ).text( pluginCount );
-                       $elem.find( '.update-plugins' ).each( function( index, elem ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $pluginsMenuItem.find( '.plugin-count' ).text( pluginCount );
+                       $pluginsMenuItem.find( '.update-plugins' ).each( function( index, elem ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 elem.className = elem.className.replace( /count-\d+/, 'count-' + pluginCount );
</span><span class="cx" style="display: block; padding: 0 10px">                        } );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+                       if (pluginCount > 0 ) {
+                               $( '.subsubsub .upgrade .count' ).text( '(' + pluginCount + ')' );
+                       } else {
+                               $( '.subsubsub .upgrade' ).remove();
+                       }
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px">        };
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * Send an Ajax request to the server to update a plugin.
+        *
+        * @since 4.2.0
+        *
+        * @param {string} plugin
+        * @param {string} slug
+        */
+       wp.updates.updatePlugin = function( plugin, slug ) {
+               var $message;
+               if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) {
+                       $message = $( '#' + slug ).next().find( '.update-message' );
+               } else if ( 'plugin-install' === pagenow ) {
+                       $message = $( '.plugin-card-' + slug ).find( '.update-now' );
+               }
+
+               $message.addClass( 'updating-message' );
+               $message.text( wp.updates.l10n.updating );
+
+               if ( wp.updates.updateLock ) {
+                       wp.updates.updateQueue.push( {
+                               type: 'update-plugin',
+                               data: {
+                                       plugin: plugin,
+                                       slug: slug
+                               }
+                       } );
+                       return;
+               }
+
+               wp.updates.updateLock = true;
+
+               var data = {
+                       'action':      'update-plugin',
+                       '_ajax_nonce': wp.updates.ajaxNonce,
+                       'plugin':      plugin,
+                       'slug':        slug
+               };
+
+               $.ajax( {
+                       type:      'post',
+                       url:       ajaxurl,
+                       data:      data,
+                       complete:  wp.updates.updateRequestComplete
+               } );
+       };
+
+       /**
+        * After an update attempt has completed, deal with the response.
+        *
+        * @since 4.2.0
+        *
+        * @param  {jqXHR} jqxhr The jQuery XMLHttpRequest for the request.
+        */
+       wp.updates.updateRequestComplete = function( jqxhr ) {
+               wp.updates.updateLock = false;
+               if ( jqxhr.responseJSON && jqxhr.responseJSON.success ) {
+                       wp.updates.updateSuccess( jqxhr.responseJSON );
+               } else {
+                       var alertText = wp.updates.l10n.updateFailed;
+                       if ( jqxhr.responseJSON && jqxhr.responseJSON.data && jqxhr.responseJSON.data.error ) {
+                                alertText += ': ' + jqxhr.responseJSON.data.error;
+                       }
+                       alert( alertText );
+                       if ( jqxhr.responseJSON && jqxhr.responseJSON.data && jqxhr.responseJSON.data.slug ) {
+                               wp.updates.updateError( jqxhr.responseJSON );
+                       }
+               }
+               /**
+                * Check the queue.
+                */
+               wp.updates.queueChecker();
+       }
+
+       /**
+        * On a successful plugin update, update the UI with the result.
+        *
+        * @since 4.2.0
+        *
+        * @param {object} response
+        */
+       wp.updates.updateSuccess = function( response ) {
+               var $message;
+               if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) {
+                       $message = $( '#' + response.data.slug ).next().find( '.update-message' );
+                       $( '#' + response.data.slug ).addClass( 'updated' ).removeClass( 'update' );
+                       $( '#' + response.data.slug + '-update' ).addClass( 'updated' ).removeClass( 'update' );
+               } else if ( 'plugin-install' === pagenow ) {
+                       $message = $( '.plugin-card-' + response.data.slug ).find( '.update-now' );
+                       $message.addClass( 'button-disabled' );
+               }
+
+               $message.removeClass( 'updating-message' ).addClass( 'updated-message' );
+               $message.text( wp.updates.l10n.updated );
+
+               wp.updates.decrementCount( 'plugin' );
+       };
+
+       /**
+        * On a plugin update error, update the UI appropriately.
+        *
+        * @since 4.2.0
+        *
+        * @param {object} response
+        */
+       wp.updates.updateError = function( response ) {
+               var $message;
+               if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) {
+                       $message = $( '#' + response.data.slug ).next().find( '.update-message' );
+               } else if ( 'plugin-install' === pagenow ) {
+                       $message = $( '.plugin-card-' + response.data.slug ).find( '.update-now' );
+               }
+               $message.removeClass( 'updating-message' );
+               $message.text( wp.updates.l10n.updateFailed );
+       };
+
+       /**
+        * Send an Ajax request to the server to install a plugin.
+        *
+        * @since 4.2.0
+        *
+        * @param {string} slug
+        */
+       wp.updates.installPlugin = function( slug ) {
+               var $message = $( '.plugin-card-' + slug ).find( '.install-now' );
+
+               $message.addClass( 'updating-message' );
+               $message.text( wp.updates.l10n.installing );
+
+               if ( wp.updates.updateLock ) {
+                       wp.updates.updateQueue.push( {
+                               type: 'install-plugin',
+                               data: {
+                                       slug: slug
+                               }
+                       } );
+                       return;
+               }
+
+               wp.updates.updateLock = true;
+
+               var data = {
+                       'action':      'install-plugin',
+                       '_ajax_nonce': wp.updates.ajaxNonce,
+                       'slug':        slug
+               };
+
+               $.ajax( {
+                       type:     'post',
+                       url:      ajaxurl,
+                       data:     data,
+                       complete: wp.updates.installRequestComplete
+               } );
+       };
+
+
+       /**
+        * After an installation attempt has completed, deal with the response.
+        *
+        * @since 4.2.0
+        *
+        * @param {jqXHR} jqxhr The jQuery XMLHttpRequest for the request.
+        */
+       wp.updates.installRequestComplete = function( jqxhr ) {
+               wp.updates.updateLock = false;
+               if ( jqxhr.responseJSON && jqxhr.responseJSON.success ) {
+                       wp.updates.installSuccess( jqxhr.responseJSON );
+               } else {
+                       var alertText = wp.updates.l10n.installFailed;
+                       if ( jqxhr.responseJSON && jqxhr.responseJSON.data && jqxhr.responseJSON.data.error ) {
+                                alertText += ': ' + jqxhr.responseJSON.data.error;
+                       }
+                       alert( alertText );
+                       if ( jqxhr.responseJSON && jqxhr.responseJSON.data && jqxhr.responseJSON.data.slug ) {
+                               wp.updates.installError( jqxhr.responseJSON );
+                       }
+               }
+               /**
+                * Check the queue.
+                */
+               wp.updates.queueChecker();
+       };
+
+       /**
+        * On plugin install success, update the UI with the result.
+        *
+        * @since 4.2.0
+        *
+        * @param {object} response
+        */
+       wp.updates.installSuccess = function( response ) {
+               var $message = $( '.plugin-card-' + response.data.slug ).find( '.install-now' );
+
+               $message.removeClass( 'updating-message' ).addClass( 'updated-message button-disabled' );
+               $message.text( wp.updates.l10n.installed );
+       };
+
+       /**
+        * On plugin install failure, update the UI appropriately.
+        *
+        * @since 4.2.0
+        *
+        * @param {object} response
+        */
+       wp.updates.installError = function( response ) {
+               var $message = $( '.plugin-card-' + response.data.slug ).find( '.install-now' );
+
+               $message.removeClass( 'updating-message' );
+               $message.text( wp.updates.l10n.installNow );
+       };
+
+
+       /**
+        * If an install/update job has been placed in the queue, queueChecker pulls it out and runs it.
+        *
+        * @since 4.2.0
+        */
+       wp.updates.queueChecker = function() {
+               if ( wp.updates.updateLock || wp.updates.updateQueue.length <= 0 ) {
+                       return;
+               }
+
+               var job = wp.updates.updateQueue.shift();
+
+               switch ( job.type ) {
+                       case 'update-plugin':
+                               wp.updates.updatePlugin( job.data.plugin, job.data.slug );
+                               break;
+                       case 'install-plugin':
+                               wp.updates.installPlugin( job.data.slug );
+                               break;
+                       default:
+                               console.log( 'Failed to exect queued update job.' );
+                               console.log( job );
+                               break;
+               }
+       };
+
+       $( document ).ready( function() {
+               $( '.plugin-update-tr .update-link' ).on( 'click', function( e ) {
+                       e.preventDefault();
+                       var $row = $( e.target ).parents( '.plugin-update-tr' );
+                       wp.updates.updatePlugin( $row.data( 'plugin' ), $row.data( 'slug' ) );
+               } );
+
+               $( '#bulk-action-form' ).on( 'submit', function( e ) {
+                       var checkbox, plugin, slug;
+
+                       if ( $( '#bulk-action-selector-top' ).val() == 'update-selected' ) {
+                               e.preventDefault();
+
+                               $( 'input[name="checked[]"]:checked' ).each( function( index, elem ) {
+                                       $checkbox = $( elem );
+                                       plugin = $checkbox.val();
+                                       slug = $checkbox.parents( 'tr' ).prop( 'id' );
+
+                                       wp.updates.updatePlugin( plugin, slug );
+
+                                       $checkbox.attr( 'checked', false );
+                               } );
+                       }
+               } );
+
+               $( '.plugin-card .update-now' ).on( 'click', function( e ) {
+                       e.preventDefault();
+                       $button = $( e.target );
+                       wp.updates.updatePlugin( $button.data( 'plugin' ), $button.data( 'slug' ) );
+               } );
+
+               $( '.plugin-card .install-now' ).on( 'click', function( e ) {
+                       e.preventDefault();
+                       $button = $( e.target );
+                       if ( $button.hasClass( 'button-disabled' ) ) {
+                               return;
+                       }
+                       wp.updates.installPlugin( $button.data( 'slug' ) );
+               } );
+       } );
+
</ins><span class="cx" style="display: block; padding: 0 10px">         $( window ).on( 'message', function( e ) {
</span><span class="cx" style="display: block; padding: 0 10px">                var event = e.originalEvent,
</span><span class="cx" style="display: block; padding: 0 10px">                        message,
</span></span></pre></div>
<a id="trunksrcwpadminplugininstallphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/plugin-install.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/plugin-install.php     2015-02-04 22:14:31 UTC (rev 31332)
+++ trunk/src/wp-admin/plugin-install.php       2015-02-05 04:18:57 UTC (rev 31333)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -54,6 +54,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> $body_id = $tab;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+wp_enqueue_script( 'updates' );
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px">  * Fires before each tab on the Install Plugins screen is loaded.
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span></span></pre></div>
<a id="trunksrcwpadminpluginsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/plugins.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/plugins.php    2015-02-04 22:14:31 UTC (rev 31332)
+++ trunk/src/wp-admin/plugins.php      2015-02-05 04:18:57 UTC (rev 31333)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -23,6 +23,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // Clean up request URI from temporary args for screen options/paging uri's to work as expected.
</span><span class="cx" style="display: block; padding: 0 10px"> $_SERVER['REQUEST_URI'] = remove_query_arg(array('error', 'deleted', 'activate', 'activate-multi', 'deactivate', 'deactivate-multi', '_error_nonce'), $_SERVER['REQUEST_URI']);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+wp_enqueue_script( 'updates' );
+
</ins><span class="cx" style="display: block; padding: 0 10px"> if ( $action ) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        switch ( $action ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -460,7 +462,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <?php $wp_list_table->search_box( __( 'Search Installed Plugins' ), 'plugin' ); ?>
</span><span class="cx" style="display: block; padding: 0 10px"> </form>
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<form method="post">
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<form method="post" id="bulk-action-form">
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> <input type="hidden" name="plugin_status" value="<?php echo esc_attr($status) ?>" />
</span><span class="cx" style="display: block; padding: 0 10px"> <input type="hidden" name="paged" value="<?php echo esc_attr($page) ?>" />
</span></span></pre></div>
<a id="trunksrcwpincludesscriptloaderphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/script-loader.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/script-loader.php   2015-02-04 22:14:31 UTC (rev 31332)
+++ trunk/src/wp-includes/script-loader.php     2015-02-05 04:18:57 UTC (rev 31333)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -501,6 +501,18 @@
</span><span class="cx" style="display: block; padding: 0 10px">                ) );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $scripts->add( 'updates', "/wp-admin/js/updates$suffix.js", array( 'jquery' ) );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                did_action( 'init' ) && $scripts->localize( 'updates', '_wpUpdatesSettings', array(
+                       'ajax_nonce' => wp_create_nonce( 'updates' ),
+                       'l10n'       => array(
+                               'updating'      => __( 'Updating...' ),
+                               'updated'       => __( 'Updated!' ),
+                               'updateFailed'  => __( 'Update failed' ),
+                               'installNow'    => __( 'Install Now' ),
+                               'installing'    => __( 'Installing...' ),
+                               'installed'     => __( 'Installed!' ),
+                               'installFailed' => __( 'Installation failed' ),
+                       )
+               ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $scripts->add( 'farbtastic', '/wp-admin/js/farbtastic.js', array('jquery'), '1.2' );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span></span></pre>
</div>
</div>

</body>
</html>